pre-0.96 (was Re: gdb still isn't working)

In article         <1992Apr20.085143.23027@klaava.Helsinki.FI>
torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds) writes:
> [ trace not working in gdb ]
>
>My personal version handles this correctly (as well as doing some other
>things in a cleaner manner), but I'm not quite ready for a new release
>yet. I could make YAAR (yet another alpha-release) or just mail
>interested parties the fixes needed - mail me if you're interested, and
>depending on the number of messages I get I'll make it a new release.

Ok, the response seems to make a new pre-release appropriate: I have
uploaded "pre-0.96.tar.Z" to tsx-11 and nic.

Here is what the pre-release contains:

- truncate/ftruncate/fchmod/fchown system calls

	note that there aren't any library functions for these, so they
	aren't very useful yet...

	[f]truncate needed a change in the logic of the internal
	truncate VFS call - anybody that has any nonstandard filesystem
	probably needs to look it up.

- io-bitmap syscalls giving root-processes access to selected io ports
  from user space. There is a "ioperm()" system call that lets the
  process select which ports it wants to enable/disable (all ports
  disabled as default) as well as a (standard sysv?) ioctl interface
  that X uses.

	again, no library stubs, but it allows things like reading and
	setting the cmos clock without using /dev/port, as well as
	control over the VGA registers...

- mmap for /dev/mem

	more things needed for X...

- the signal-handling fixes needed for gdb

	These aren't yet complete: serial lines still send signals under
	interrupts that can result in problems (ie ptrace doesn't
	correctly get them), but that's pretty unlikely (and will be
	fixed in the final 0.96). Breakpoints should work etc..

- multiple shared libraries

	Up to 6 simultaneous shared libraries/process: the patches were
	originally by pmacdona, but they were heavily changed by me, and
	I think they work in a more natural manner now. One user-level
	change is that the libraries are now checked for read and
	execute permissions for safety-reasons.

- cleaned up special files.

	read/write/ioctl no longer has special-case code: it is all
	handled with tables to functions. This will mean that the SCSI
	patches won't patch in quite cleanly into 0.96: you'll need to
	add the code that sets up the functions.

	Again: device drivers and vfs-filesystem hackers need to look
	into the changes, although they are pretty logical (earlier
	versions just didn't implement all the vfs-routines)

	Note that the vfs-code for select is still not used: select is
	hardcoded for the devices it supports right now.

- ptrace() has a new interface

	as gdb for versions < 0.95c don't work on the new version, and
	gdb won't work very well at all on 0.95c[+], there was no reason
	not to break ptrace. Thus 0.96 has a new calling convention for
	ptrace, and the old ptrace library function no longer works.
	I'm including the new ptrace library function at the end of this
	post.

- mount() takes 4 arguments, and checks that only the super-user can
  mount/umount things.

	Happily this shouldn't break any old binaries.

- some general cleanups

I've made the pre-release available only as pure source code: no diffs,
no binary. The reason is that most people that needed this release want
it for the gdb-fixes: and they should have no problem recompiling the
kernel. Others just have to wait for the real 0.96.

Changes that are NOT in this pre-release, but which I hope to have in
the real 0.96:

	- more include-file cleanups - I'm still working on these

	- the wd8003 driver and hopefully some other parts of biro's
	  config.

	- select() using the vfs-tables.

And possibly bugfixes that people find in this pre-release...

		Linus

========== library ptrace.c (wants gcc=2.1) ==========
#define __LIBRARY__
#include <time.h>
#include <unistd.h>

int ptrace(int request, int pid, int addr, int data)
{
	long ret;
	long res;

	if (request > 0 && request < 4)
		(long *)data = &ret;
	__asm__ volatile ("int $0x80"
		:"=a" (res)
		:"0" (__NR_ptrace),"b" (request), "c" (pid),
		 "d" (addr), "S" (data)
		: "si","bx","cx","dx");
	if (res >= 0) {
		if (request > 0 && request < 4) {
			errno = 0;
			return (ret);
		}
		return (int) res;
	}
	errno = -res;
	return -1;
}
diff --git a/Makefile b/Makefile
index 59d5f66..dc83ace 100644
--- a/Makefile
+++ b/Makefile
@@ -8,8 +8,8 @@
 # uncomment the correct keyboard:
 #
 
-# KEYBOARD = -DKBD_FINNISH
-KEYBOARD = -DKBD_US
+KEYBOARD = -DKBD_FINNISH
+# KEYBOARD = -DKBD_US
 # KEYBOARD = -DKBD_GR
 # KEYBOARD = -DKBD_FR
 # KEYBOARD = -DKBD_UK
@@ -32,7 +32,7 @@
 # default of FLOPPY is used by 'build'.
 #
 
-# ROOT_DEV = /dev/hdb1
+ROOT_DEV = /dev/hdb1
 
 #
 # if you want the ram-disk device, define this to be the
@@ -86,7 +86,7 @@
 	dd bs=8192 if=Image of=/dev/PS0
 
 tools/build: tools/build.c
-	$(CC) $(CFLAGS) \
+	$(CC) -static $(CFLAGS) \
 	-o tools/build tools/build.c
 
 boot/head.o: boot/head.s
@@ -159,15 +159,15 @@
 	(cd fs; make dep)
 	(cd kernel; make dep)
 	(cd mm; make dep)
+	(cd lib; make dep)
 
 dummy:
 
 ### Dependencies:
-init/main.o : init/main.c include/unistd.h include/sys/stat.h \
-  include/sys/types.h include/sys/time.h include/time.h include/sys/times.h \
-  include/sys/utsname.h include/sys/param.h include/sys/resource.h \
-  include/utime.h include/linux/tty.h include/termios.h include/linux/sched.h \
-  include/linux/head.h include/linux/fs.h include/sys/dirent.h \
-  include/limits.h include/linux/mm.h include/linux/kernel.h include/signal.h \
-  include/asm/system.h include/asm/io.h include/stddef.h include/stdarg.h \
-  include/fcntl.h include/string.h 
+init/main.o : init/main.c include/unistd.h include/sys/stat.h include/sys/types.h \
+  include/sys/time.h include/time.h include/sys/times.h include/sys/utsname.h \
+  include/sys/param.h include/sys/resource.h include/utime.h include/linux/sched.h \
+  include/linux/head.h include/linux/fs.h include/sys/dirent.h include/limits.h \
+  include/linux/mm.h include/linux/kernel.h include/signal.h include/linux/tty.h \
+  include/termios.h include/linux/string.h include/asm/system.h include/asm/io.h \
+  include/stddef.h include/stdarg.h include/fcntl.h 
diff --git a/fs/Makefile b/fs/Makefile
index 312f2f6..602e09f 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -23,8 +23,8 @@
 	$(AS) -o $*.o $<
 
 OBJS=	open.o read_write.o inode.o file_table.o buffer.o super.o \
-	block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
-	fcntl.o ioctl.o select.o
+	block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
+	select.o
 
 fs.o: $(OBJS)
 	$(LD) -r -o fs.o $(OBJS)
@@ -41,97 +41,74 @@
 	cd minix; make dep
 
 ### Dependencies:
-block_dev.o : block_dev.c ../include/errno.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
-  ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
-  ../include/asm/segment.h ../include/asm/system.h 
-buffer.o : buffer.c ../include/stdarg.h ../include/linux/config.h \
-  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
-  ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
-  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
-  ../include/sys/param.h ../include/sys/time.h ../include/time.h \
-  ../include/sys/resource.h ../include/asm/system.h ../include/asm/io.h 
-char_dev.o : char_dev.c ../include/errno.h ../include/sys/types.h \
-  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
-  ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
-  ../include/asm/segment.h ../include/asm/io.h 
-exec.o : exec.c ../include/signal.h ../include/sys/types.h \
-  ../include/errno.h ../include/string.h ../include/sys/stat.h \
-  ../include/a.out.h ../include/linux/fs.h ../include/sys/dirent.h \
-  ../include/limits.h ../include/linux/sched.h ../include/linux/head.h \
-  ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h \
-  ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
-  ../include/asm/segment.h 
-fcntl.o : fcntl.c ../include/string.h ../include/errno.h \
-  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
-  ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
-  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
-  ../include/sys/param.h ../include/sys/time.h ../include/time.h \
-  ../include/sys/resource.h ../include/asm/segment.h ../include/fcntl.h \
-  ../include/sys/stat.h 
-file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h 
-inode.o : inode.c ../include/string.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
-  ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h \
-  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
-  ../include/sys/param.h ../include/sys/time.h ../include/time.h \
-  ../include/sys/resource.h ../include/asm/system.h 
-ioctl.o : ioctl.c ../include/string.h ../include/errno.h \
-  ../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
-  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
-  ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
-  ../include/time.h ../include/sys/resource.h 
-namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h \
-  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
-  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
-  ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
-  ../include/time.h ../include/sys/resource.h ../include/asm/segment.h \
-  ../include/string.h ../include/fcntl.h ../include/errno.h \
-  ../include/const.h ../include/sys/stat.h 
-open.o : open.c ../include/string.h ../include/errno.h ../include/fcntl.h \
-  ../include/sys/types.h ../include/utime.h ../include/sys/stat.h \
-  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
-  ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
-  ../include/asm/segment.h 
-pipe.o : pipe.c ../include/signal.h ../include/sys/types.h \
-  ../include/errno.h ../include/termios.h ../include/fcntl.h \
-  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/linux/kernel.h ../include/sys/param.h ../include/sys/time.h \
+block_dev.o : block_dev.c ../include/errno.h ../include/linux/sched.h ../include/linux/head.h \
+  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/segment.h \
+  ../include/asm/system.h 
+buffer.o : buffer.c ../include/stdarg.h ../include/linux/config.h ../include/linux/config_rel.h \
+  ../include/linux/config_ver.h ../include/linux/sched.h ../include/linux/head.h \
+  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/system.h \
+  ../include/asm/io.h 
+exec.o : exec.c ../include/signal.h ../include/sys/types.h ../include/errno.h \
+  ../include/linux/string.h ../include/sys/stat.h ../include/a.out.h ../include/linux/fs.h \
+  ../include/sys/dirent.h ../include/limits.h ../include/linux/sched.h ../include/linux/head.h \
+  ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h ../include/sys/time.h \
   ../include/time.h ../include/sys/resource.h ../include/asm/segment.h 
-read_write.o : read_write.c ../include/errno.h ../include/sys/types.h \
-  ../include/sys/stat.h ../include/sys/dirent.h ../include/limits.h \
-  ../include/linux/kernel.h ../include/linux/sched.h ../include/linux/head.h \
-  ../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
-  ../include/sys/param.h ../include/sys/time.h ../include/time.h \
-  ../include/sys/resource.h ../include/linux/minix_fs.h \
+fcntl.o : fcntl.c ../include/linux/string.h ../include/errno.h ../include/linux/sched.h \
+  ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
+  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+  ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+  ../include/asm/segment.h ../include/fcntl.h ../include/sys/stat.h 
+file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
+  ../include/limits.h 
+inode.o : inode.c ../include/linux/string.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
+  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+  ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+  ../include/asm/system.h 
+ioctl.o : ioctl.c ../include/linux/string.h ../include/errno.h ../include/sys/stat.h \
+  ../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
+  ../include/signal.h ../include/sys/param.h ../include/sys/time.h ../include/time.h \
+  ../include/sys/resource.h 
+namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+  ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
+  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+  ../include/time.h ../include/sys/resource.h ../include/asm/segment.h ../include/linux/string.h \
+  ../include/fcntl.h ../include/errno.h ../include/const.h ../include/sys/stat.h 
+open.o : open.c ../include/errno.h ../include/fcntl.h ../include/sys/types.h \
+  ../include/utime.h ../include/sys/stat.h ../include/sys/vfs.h ../include/linux/string.h \
+  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
+  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+  ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
   ../include/asm/segment.h 
-select.o : select.c ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/kernel.h \
-  ../include/linux/tty.h ../include/termios.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/linux/mm.h ../include/signal.h \
-  ../include/sys/param.h ../include/sys/time.h ../include/time.h \
-  ../include/sys/resource.h ../include/asm/segment.h ../include/asm/system.h \
-  ../include/sys/stat.h ../include/string.h ../include/const.h \
-  ../include/errno.h 
-stat.o : stat.c ../include/errno.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/linux/fs.h ../include/sys/dirent.h \
-  ../include/limits.h ../include/linux/sched.h ../include/linux/head.h \
-  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
-  ../include/sys/param.h ../include/sys/time.h ../include/time.h \
-  ../include/sys/resource.h ../include/asm/segment.h 
-super.o : super.c ../include/linux/config.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
-  ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
-  ../include/linux/minix_fs.h ../include/asm/system.h ../include/errno.h \
-  ../include/sys/stat.h 
+pipe.o : pipe.c ../include/signal.h ../include/sys/types.h ../include/errno.h \
+  ../include/termios.h ../include/fcntl.h ../include/asm/segment.h ../include/linux/sched.h \
+  ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h ../include/sys/time.h \
+  ../include/time.h ../include/sys/resource.h 
+read_write.o : read_write.c ../include/errno.h ../include/sys/types.h ../include/sys/stat.h \
+  ../include/sys/dirent.h ../include/limits.h ../include/linux/kernel.h ../include/linux/sched.h \
+  ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
+  ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+  ../include/linux/minix_fs.h ../include/asm/segment.h 
+select.o : select.c ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
+  ../include/limits.h ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
+  ../include/linux/sched.h ../include/linux/head.h ../include/linux/mm.h ../include/signal.h \
+  ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+  ../include/linux/string.h ../include/asm/segment.h ../include/asm/system.h ../include/sys/stat.h \
+  ../include/const.h ../include/errno.h 
+stat.o : stat.c ../include/errno.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h ../include/linux/sched.h \
+  ../include/linux/head.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+  ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+  ../include/asm/segment.h 
+super.o : super.c ../include/linux/config.h ../include/linux/config_rel.h ../include/linux/config_ver.h \
+  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
+  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
+  ../include/signal.h ../include/sys/param.h ../include/sys/time.h ../include/time.h \
+  ../include/sys/resource.h ../include/linux/minix_fs.h ../include/asm/system.h \
+  ../include/asm/segment.h ../include/errno.h ../include/sys/stat.h 
diff --git a/fs/block_dev.c b/fs/block_dev.c
index cca44d3..c102c94 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -50,6 +50,7 @@
 		memcpy_fromfs(p,buf,chars);
 		p += chars;
 		buf += chars;
+		bh->b_uptodate = 1;
 		bh->b_dirt = 1;
 		brelse(bh);
 	}
diff --git a/fs/buffer.c b/fs/buffer.c
index 54fa805..4b80848 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -200,7 +200,8 @@
 		return;
 	bh->b_next = hash(bh->b_dev,bh->b_blocknr);
 	hash(bh->b_dev,bh->b_blocknr) = bh;
-	bh->b_next->b_prev = bh;
+	if (bh->b_next)
+		bh->b_next->b_prev = bh;
 }
 
 static struct buffer_head * find_buffer(int dev, int block)
diff --git a/fs/char_dev.c b/fs/char_dev.c
deleted file mode 100644
index 081b18e..0000000
--- a/fs/char_dev.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- *  linux/fs/char_dev.c
- *
- *  (C) 1991  Linus Torvalds
- */
-
-#include <errno.h>
-#include <sys/types.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-
-#include <checkpoint.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-
-extern int tty_read(unsigned minor,char * buf,int count,unsigned short flags);
-extern int tty_write(unsigned minor,char * buf,int count);
-extern int lp_write(unsigned minor,char *buf, int count);
-
-typedef (*crw_ptr)(int,unsigned,char *,int,off_t *,unsigned short);
-
-static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos, unsigned short flags)
-{
-	return ((rw==READ)?tty_read(minor,buf,count,flags):
-		tty_write(minor,buf,count));
-}
-
-static int rw_lp(int rw,unsigned minor,char * buf,int count,off_t * pos, unsigned short flags)
-{
-	return ((rw==READ)?-EINVAL:lp_write(minor,buf,count));
-}
-
-static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos, unsigned short flags)
-{
-	if (current->tty<0)
-		return -EPERM;
-	return rw_ttyx(rw,current->tty,buf,count,pos,flags);
-}
-
-static int rw_ram(int rw,char * buf, int count, off_t *pos)
-{
-	return -EIO;
-}
-
-static int rw_mem(int rw,char * buf, int count, off_t * pos)
-{
-	char *p;
-	unsigned long pde, pte, tmp;
-	int i = count;
-
-	if (count <= 0)
-		return(0);
-	/*
-	 * return EOF on nonexistant pages or pages swapped out to disk
-	 */
-	pde = (unsigned long) pg_dir + (*pos >> 20 & 0xffc);
-	if (((pte = *((unsigned long *) pde)) & 1) == 0)
-		return 0;	/* page table not present */
-	pte &= 0xfffff000;
-	pte += *pos >> 10 & 0xffc;
-	if (((tmp = *((unsigned long *) pte)) & 1) == 0)
-		return 0;
-	if (rw == WRITE && (tmp & 2) == 0)
-		un_wp_page((unsigned long *) pte);
-	p = (char *) ((tmp & 0xfffff000) + (*pos & 0xfff));
-	while (1) {
-		if (rw == WRITE)
-			*p++ = get_fs_byte(buf++);
-		else
-			put_fs_byte(*p++, buf++);
-
-		if (--i == 0)
-			break;
-
-		if (count && ((unsigned long) p & 0xfff) == 0) {
-			if (((pte += 4) & 0xfff) == 0) {
-				if (((pde += 4) & 0xfff) == 0)
-					break;
-				if (((pte = *((unsigned long *) pde)) & 1) == 0)
-					break;
-				pte &= 0xfffff000;
-			}
-			if (((tmp = *((unsigned long *) pte)) & 1) == 0)
-				break;
-
-			if (rw == WRITE && (tmp & 2) == 0)
-				un_wp_page((unsigned long *) pte);
-			p = (char *) (tmp & 0xfffff000);
-		}
-	}
-	return(count - i);
-}
-
-static int rw_kmem(int rw,char * buf, int count, off_t * pos)
-{
-	char *p=(char *) *pos;
-
-	if ((unsigned long) *pos > HIGH_MEMORY)
-		return 0;
-	if ((unsigned long) *pos + count > HIGH_MEMORY)
-		count = HIGH_MEMORY - *pos;
-
-	switch (rw) {
-		case READ:
-			while ((count -= 4) >= 0)
-				put_fs_long(*((unsigned long *) p)++, 
-					    ((unsigned long *) buf)++);
-			count += 4;
-			while (--count >= 0)
-				put_fs_byte(*p++, buf++);
-			break;
-		case WRITE:
-			while (--count >= 0)
-				*p++ = get_fs_byte(buf++);
-			break;
-		default:
-			return -EINVAL;
-	}
-	p -= *pos;
-	*pos += (int) p;
-	return (int) p;
-}
-
-static int rw_port(int rw,char * buf, int count, off_t * pos)
-{
-	int i=*pos;
-
-	while (count-->0 && i<65536) {
-		if (rw==READ)
-			put_fs_byte(inb(i),buf++);
-		else
-			outb(get_fs_byte(buf++),i);
-		i++;
-	}
-	i -= *pos;
-	*pos += i;
-	return i;
-}
-
-static int rw_memory(int rw, unsigned minor, char * buf, int count,
-	off_t * pos, unsigned short flags)
-{
-	switch(minor) {
-		case 0:
-			return rw_ram(rw,buf,count,pos);
-		case 1:
-			return rw_mem(rw,buf,count,pos);
-		case 2:
-			return rw_kmem(rw,buf,count,pos);
-		case 3:
-			return (rw==READ)?0:count;	/* rw_null */
-		case 4:
-			return rw_port(rw,buf,count,pos);
-		default:
-			return -EIO;
-	}
-}
-
-#define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
-
-static crw_ptr crw_table[]={
-	NULL,		/* nodev */
-	rw_memory,	/* /dev/mem etc */
-	NULL,		/* /dev/fd */
-	NULL,		/* /dev/hd */
-	rw_ttyx,	/* /dev/ttyx */
-	rw_tty,		/* /dev/tty */
-	rw_lp,		/* /dev/lp */
-	NULL};		/* unnamed pipes */
-
-int char_read(struct inode * inode, struct file * filp, char * buf, int count)
-{
-	unsigned int major,minor;
-	crw_ptr call_addr;
-
-	major = MAJOR(inode->i_rdev);
-	minor = MINOR(inode->i_rdev);
-	if (major >= NRDEVS)
-		return -ENODEV;
-	if (!(call_addr = crw_table[major]))
-		return -ENODEV;
-	return call_addr(READ,minor,buf,count,&filp->f_pos,filp->f_flags);
-}
-
-int char_write(struct inode * inode, struct file * filp, char * buf, int count)
-{
-	unsigned int major,minor;
-	crw_ptr call_addr;
-
-	major = MAJOR(inode->i_rdev);
-	minor = MINOR(inode->i_rdev);
-	if (major >= NRDEVS)
-		return -ENODEV;
-	if (!(call_addr=crw_table[major]))
-		return -ENODEV;
-	return call_addr(WRITE,minor,buf,count,&filp->f_pos,filp->f_flags);
-}
diff --git a/fs/exec.c b/fs/exec.c
index f27b51f..cb7b2ba 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -19,7 +19,7 @@
 
 #include <signal.h>
 #include <errno.h>
-#include <string.h>
+#include <linux/string.h>
 #include <sys/stat.h>
 #include <a.out.h>
 
@@ -39,26 +39,57 @@
  */
 #define MAX_ARG_PAGES 32
 
+/*
+ * Note that a shared library must be both readable and executable due to
+ * security reasons.
+ *
+ * Also note that we take the address to load from from the file itself.
+ */
 int sys_uselib(const char * library)
 {
+#define libnum	(current->numlibraries)
 	struct inode * inode;
-	unsigned long base;
+	struct buffer_head * bh;
+	struct exec ex;
 
 	if (get_limit(0x17) != TASK_SIZE)
 		return -EINVAL;
-	if (library) {
-		if (!(inode=namei(library)))		/* get library inode */
-			return -ENOENT;
-	} else
+	if ((libnum >= MAX_SHARED_LIBS) || (libnum < 0))
+		return -EINVAL;
+	if (library)
+		inode = namei(library);
+	else
 		inode = NULL;
-/* we should check filetypes (headers etc), but we don't */
-	iput(current->library);
-	current->library = NULL;
-	base = get_base(current->ldt[2]);
-	base += LIBRARY_OFFSET;
-	free_page_tables(base,LIBRARY_SIZE);
-	current->library = inode;
+	if (!inode)
+		return -ENOENT;
+	if (!S_ISREG(inode->i_mode) || !permission(inode,MAY_READ|MAY_EXEC)) {
+		iput(inode);
+		return -EACCES;
+	}
+	if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
+		iput(inode);
+		return -EACCES;
+	}
+	ex = *(struct exec *) bh->b_data;
+	brelse(bh);
+	if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
+		ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
+		inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
+		iput(inode);
+		return -ENOEXEC;
+	}
+	current->libraries[libnum].library = inode;
+	current->libraries[libnum].start = ex.a_entry;
+	current->libraries[libnum].length = (ex.a_data+ex.a_text+0xfff) & 0xfffff000;
+#if 0
+	printk("Loaded library %d at %08x, length %08x\n",
+		libnum,
+		current->libraries[libnum].start,
+		current->libraries[libnum].length);
+#endif
+	libnum++;
 	return 0;
+#undef libnum
 }
 
 /*
@@ -348,7 +379,6 @@
 		}
 	}
 /* OK, This is the point of no return */
-/* note that current->library stays unchanged by an exec */
 	for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
 		if (ch == '/')
 			i = 0;
@@ -357,9 +387,14 @@
 				current->comm[i++] = ch;
 	if (i < 8)
 		current->comm[i] = '\0';
-	
 	if (current->executable)
 		iput(current->executable);
+	i = current->numlibraries;
+	while (i-- > 0) {
+		iput(current->libraries[i].library);
+		current->libraries[i].library = NULL;
+	}
+	current->numlibraries = 0;
 	current->executable = inode;
 	current->signal = 0;
 	for (i=0 ; i<32 ; i++) {
diff --git a/fs/fcntl.c b/fs/fcntl.c
index ab7fe1f..9658483 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -4,7 +4,7 @@
  *  (C) 1991  Linus Torvalds
  */
 
-#include <string.h>
+#include <linux/string.h>
 #include <errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff --git a/fs/inode.c b/fs/inode.c
index c1634d8..385f2f9 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -4,7 +4,7 @@
  *  (C) 1991  Linus Torvalds
  */
 
-#include <string.h>
+#include <linux/string.h>
 #include <sys/stat.h>
 
 #include <linux/sched.h>
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 284a0dc..7b28116 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -4,47 +4,19 @@
  *  (C) 1991  Linus Torvalds
  */
 
-#include <string.h>
+#include <linux/string.h>
 #include <errno.h>
 #include <sys/stat.h>
 
 #include <linux/sched.h>
 
-extern int hd_ioctl(int dev, int cmd, int arg);
-extern int tty_ioctl(int dev, int cmd, int arg);
-extern int pipe_ioctl(struct inode *pino, int cmd, int arg);
-
-typedef int (*ioctl_ptr)(int dev,int cmd,int arg);
-
-#define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))
-
-static ioctl_ptr ioctl_table[]={
-	NULL,		/* nodev */
-	NULL,		/* /dev/mem */
-	NULL,		/* /dev/fd */
-	hd_ioctl,       /* /dev/hd */
-	tty_ioctl,	/* /dev/ttyx */
-	tty_ioctl,	/* /dev/tty */
-	NULL,		/* /dev/lp */
-	NULL};		/* named pipes */
-	
-
 int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {	
 	struct file * filp;
-	int dev,mode;
 
 	if (fd >= NR_OPEN || !(filp = current->filp[fd]))
 		return -EBADF;
-	if (filp->f_inode->i_pipe)
-		return (filp->f_mode&1)?pipe_ioctl(filp->f_inode,cmd,arg):-EBADF;
-	mode=filp->f_inode->i_mode;
-	if (!S_ISCHR(mode) && !S_ISBLK(mode))
-		return -EINVAL;
-	dev = filp->f_inode->i_rdev;
-	if (MAJOR(dev) >= NRDEVS)
-		return -ENODEV;
-	if (!ioctl_table[MAJOR(dev)])
-		return -ENOTTY;
-	return ioctl_table[MAJOR(dev)](dev,cmd,arg);
+	if (filp->f_op && filp->f_op->ioctl)
+		return filp->f_op->ioctl(filp->f_inode, filp, cmd,arg);
+	return -EINVAL;
 }
diff --git a/fs/minix/Makefile b/fs/minix/Makefile
index fd1a331..81aebc7 100644
--- a/fs/minix/Makefile
+++ b/fs/minix/Makefile
@@ -37,46 +37,33 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-bitmap.o : bitmap.c ../../include/string.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
+bitmap.o : bitmap.c ../../include/linux/string.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/minix_fs.h 
+file_dev.o : file_dev.c ../../include/errno.h ../../include/fcntl.h ../../include/sys/types.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/sys/stat.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/linux/mm.h \
+  ../../include/linux/kernel.h ../../include/signal.h ../../include/sys/param.h \
+  ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h ../../include/linux/minix_fs.h \
+  ../../include/asm/segment.h 
+inode.o : inode.c ../../include/linux/string.h ../../include/sys/stat.h ../../include/sys/types.h \
+  ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/minix_fs.h ../../include/asm/system.h 
+minix_op.o : minix_op.c ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/minix_fs.h 
+namei.o : namei.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
   ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
-  ../../include/linux/mm.h ../../include/linux/kernel.h \
-  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
-  ../../include/time.h ../../include/sys/resource.h \
-  ../../include/linux/minix_fs.h 
-file_dev.o : file_dev.c ../../include/errno.h ../../include/fcntl.h \
-  ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
-  ../../include/sys/stat.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/linux/mm.h ../../include/linux/kernel.h \
-  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
-  ../../include/time.h ../../include/sys/resource.h \
-  ../../include/linux/minix_fs.h ../../include/asm/segment.h 
-inode.o : inode.c ../../include/string.h ../../include/sys/stat.h \
-  ../../include/sys/types.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/linux/minix_fs.h \
-  ../../include/asm/system.h 
-minix_op.o : minix_op.c ../../include/linux/fs.h ../../include/sys/types.h \
-  ../../include/sys/dirent.h ../../include/limits.h \
-  ../../include/linux/minix_fs.h 
-namei.o : namei.c ../../include/linux/sched.h ../../include/linux/head.h \
-  ../../include/linux/fs.h ../../include/sys/types.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/linux/minix_fs.h \
-  ../../include/asm/segment.h ../../include/string.h ../../include/fcntl.h \
-  ../../include/errno.h ../../include/const.h ../../include/sys/stat.h 
-truncate.o : truncate.c ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
-  ../../include/linux/mm.h ../../include/linux/kernel.h \
-  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
-  ../../include/time.h ../../include/sys/resource.h \
-  ../../include/linux/minix_fs.h ../../include/linux/tty.h \
-  ../../include/termios.h ../../include/errno.h ../../include/fcntl.h \
-  ../../include/sys/stat.h 
+  ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+  ../../include/linux/minix_fs.h ../../include/asm/segment.h ../../include/linux/string.h \
+  ../../include/fcntl.h ../../include/errno.h ../../include/const.h ../../include/sys/stat.h 
+truncate.o : truncate.c ../../include/linux/sched.h ../../include/linux/head.h \
+  ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/minix_fs.h ../../include/linux/tty.h \
+  ../../include/termios.h ../../include/errno.h ../../include/fcntl.h ../../include/sys/stat.h 
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 645db74..6a3ead3 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -5,7 +5,7 @@
  */
 
 /* bitmap.c contains the code that handles the inode and block bitmaps */
-#include <string.h>
+#include <linux/string.h>
 
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
diff --git a/fs/minix/file_dev.c b/fs/minix/file_dev.c
index 91995d9..2ae0705 100644
--- a/fs/minix/file_dev.c
+++ b/fs/minix/file_dev.c
@@ -17,16 +17,16 @@
 #define MIN(a,b) (((a)<(b))?(a):(b))
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
-int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent)
+int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count)
 {
 	unsigned int block,offset,i;
 	char c;
 	struct buffer_head * bh;
 	struct minix_dir_entry * de;
 
-	if (!S_ISDIR(inode->i_mode))
+	if (!inode || !S_ISDIR(inode->i_mode))
 		return -EBADF;
-	if (filp->f_pos & 15)
+	if (filp->f_pos & (sizeof (struct minix_dir_entry) - 1))
 		return -EBADF;
 	while (filp->f_pos < inode->i_size) {
 		offset = filp->f_pos & 1023;
@@ -37,10 +37,10 @@
 		}
 		de = (struct minix_dir_entry *) (offset + bh->b_data);
 		while (offset < 1024 && filp->f_pos < inode->i_size) {
-			offset += 16;
-			filp->f_pos += 16;
+			offset += sizeof (struct minix_dir_entry);
+			filp->f_pos += sizeof (struct minix_dir_entry);
 			if (de->inode) {
-				for (i = 0; i < 14; i++)
+				for (i = 0; i < MINIX_NAME_LEN; i++)
 					if (c = de->name[i])
 						put_fs_byte(c,i+dirent->d_name);
 					else
@@ -65,6 +65,14 @@
 	int read,left,chars,nr;
 	struct buffer_head * bh;
 
+	if (!inode) {
+		printk("minix_file_read: inode = NULL\n");
+		return -EINVAL;
+	}
+	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
+		printk("minix_file_read: mode = %07o\n",inode->i_mode);
+		return -EINVAL;
+	}
 	if (filp->f_pos > inode->i_size)
 		left = 0;
 	else
@@ -103,6 +111,14 @@
 	struct buffer_head * bh;
 	char * p;
 
+	if (!inode) {
+		printk("minix_file_write: inode = NULL\n");
+		return -EINVAL;
+	}
+	if (!S_ISREG(inode->i_mode)) {
+		printk("minix_file_write: mode = %07o\n",inode->i_mode);
+		return -EINVAL;
+	}
 /*
  * ok, append may not work when many processes are writing at the same time
  * but so what. That way leads to madness anyway.
@@ -118,16 +134,19 @@
 				written = -ENOSPC;
 			break;
 		}
-		if (!(bh=bread(inode->i_dev,block))) {
+		c = BLOCK_SIZE - (pos % BLOCK_SIZE);
+		if (c > count-written)
+			c = count-written;
+		if (c == BLOCK_SIZE)
+			bh = getblk(inode->i_dev, block);
+		else
+			bh = bread(inode->i_dev,block);
+		if (!bh) {
 			if (!written)
 				written = -EIO;
 			break;
 		}
-		c = pos % BLOCK_SIZE;
-		p = c + bh->b_data;
-		c = BLOCK_SIZE-c;
-		if (c > count-written)
-			c = count-written;
+		p = (pos % BLOCK_SIZE) + bh->b_data;
 		pos += c;
 		if (pos > inode->i_size) {
 			inode->i_size = pos;
@@ -136,6 +155,7 @@
 		written += c;
 		memcpy_fromfs(p,buf,c);
 		buf += c;
+		bh->b_uptodate = 1;
 		bh->b_dirt = 1;
 		brelse(bh);
 	}
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 75ec7a2..c635e6e 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -4,7 +4,7 @@
  *  (C) 1991  Linus Torvalds
  */
 
-#include <string.h>
+#include <linux/string.h>
 #include <sys/stat.h>
 
 #include <linux/sched.h>
diff --git a/fs/minix/minix_op.c b/fs/minix/minix_op.c
index 7fd5559..a588f09 100644
--- a/fs/minix/minix_op.c
+++ b/fs/minix/minix_op.c
@@ -9,6 +9,7 @@
 
 void minix_put_inode(struct inode *inode)
 {
+	inode->i_size = 0;
 	minix_truncate(inode);
 	minix_free_inode(inode);
 }
@@ -41,9 +42,21 @@
  * the minix filesystem.
  */
 struct file_operations minix_file_operations = {
-	NULL,	/* lseek */
-	NULL,	/* read */
-	NULL,	/* write */
-	minix_readdir
+	NULL,			/* lseek - default */
+	minix_file_read,	/* read */
+	minix_file_write,	/* write */
+	NULL,			/* readdir - bad */
+	NULL,			/* close - default */
+	NULL,			/* select - default */
+	NULL			/* ioctl - default */
 };
 	
+struct file_operations minix_dir_operations = {
+	NULL,			/* lseek - default */
+	minix_file_read,	/* read */
+	NULL,			/* write - bad */
+	minix_readdir,		/* readdir */
+	NULL,			/* close - default */
+	NULL,			/* select - default */
+	NULL			/* ioctl - default */
+};
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index ba891cb..912b883 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <asm/segment.h>
 
-#include <string.h>
+#include <linux/string.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <const.h>
@@ -323,7 +323,7 @@
 		iput(dir);
 		return -ENOSPC;
 	}
-	inode->i_size = 32;
+	inode->i_size = 2 * sizeof (struct minix_dir_entry);
 	inode->i_dirt = 1;
 	inode->i_mtime = inode->i_atime = CURRENT_TIME;
 	if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
@@ -337,7 +337,7 @@
 		iput(dir);
 		inode->i_nlink--;
 		iput(inode);
-		return -ERROR;
+		return -EIO;
 	}
 	de = (struct minix_dir_entry *) dir_block->b_data;
 	de->inode=inode->i_ino;
@@ -529,7 +529,7 @@
 		iput(dir);
 		inode->i_nlink--;
 		iput(inode);
-		return -ERROR;
+		return -EIO;
 	}
 	i = 0;
 	while (i < 1023 && (c=get_fs_byte(symname++)))
diff --git a/fs/minix/truncate.c b/fs/minix/truncate.c
index ab72736..7df5268 100644
--- a/fs/minix/truncate.c
+++ b/fs/minix/truncate.c
@@ -12,93 +12,132 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 
-static int minix_free_ind(int dev,int block)
-{
-	struct buffer_head * bh;
-	unsigned short * p;
-	int i;
-	int block_busy;
+/*
+ * Truncate has the most races in the whole filesystem: coding it is
+ * a pain in the a**. Especially as I don't do any locking...
+ *
+ * The code may look a bit weird, but that's just because I've tried to
+ * handle things like file-size changes in a somewhat graceful manner.
+ * Anyway, truncating a file at the same time somebody else writes to it
+ * is likely to result in pretty weird behaviour...
+ *
+ * The new code handles normal truncates (size = 0) as well as the more
+ * general case (size = XXX). I hope.
+ */
 
-	if (!block)
-		return 1;
-	block_busy = 0;
-	if (bh=bread(dev,block)) {
-		p = (unsigned short *) bh->b_data;
-		for (i=0;i<512;i++,p++)
-			if (*p)
-				if (minix_free_block(dev,*p)) {
-					*p = 0;
-					bh->b_dirt = 1;
-				} else
-					block_busy = 1;
-		brelse(bh);
+static int trunc_direct(struct inode * inode)
+{
+	int i;
+	int result = 0;
+#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
+
+repeat:
+	for (i = DIRECT_BLOCK ; i < 7 ; i++) {
+		if (i < DIRECT_BLOCK)
+			goto repeat;
+		if (!inode->i_data[i])
+			continue;
+		result = 1;
+		if (minix_free_block(inode->i_dev,inode->i_data[i]))
+			inode->i_data[i] = 0;
 	}
-	if (block_busy)
-		return 0;
-	else
-		return minix_free_block(dev,block);
+	return result;
 }
 
-static int minix_free_dind(int dev,int block)
+static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
 {
-	struct buffer_head * bh;
-	unsigned short * p;
 	int i;
-	int block_busy;
+	struct buffer_head * bh = NULL;
+	unsigned short * ind;
+	int result = 0;
+#define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
 
-	if (!block)
-		return 1;
-	block_busy = 0;
-	if (bh=bread(dev,block)) {
-		p = (unsigned short *) bh->b_data;
-		for (i=0;i<512;i++,p++)
-			if (*p)
-				if (minix_free_ind(dev,*p)) {
-					*p = 0;
-					bh->b_dirt = 1;
-				} else
-					block_busy = 1;
-		brelse(bh);
-	}
-	if (block_busy)
+	if (*p)
+		bh = bread(inode->i_dev,*p);
+	if (!bh)
 		return 0;
-	else
-		return minix_free_block(dev,block);
+repeat:
+	for (i = INDIRECT_BLOCK ; i < 512 ; i++) {
+		if (i < 0)
+			i = 0;
+		if (i < INDIRECT_BLOCK)
+			goto repeat;
+		ind = i+(unsigned short *) bh->b_data;
+		if (!*ind)
+			continue;
+		result = 1;
+		if (minix_free_block(inode->i_dev,*ind))
+			*ind = 0;
+	}
+	ind = (unsigned short *) bh->b_data;
+	for (i = 0; i < 512; i++)
+		if (*(ind++))
+			break;
+	brelse(bh);
+	if (i >= 512) {
+		result = 1;
+		if (minix_free_block(inode->i_dev,*p))
+			*p = 0;
+	}
+	return result;
 }
+		
+static int trunc_dindirect(struct inode * inode)
+{
+	int i;
+	struct buffer_head * bh = NULL;
+	unsigned short * dind;
+	int result = 0;
+#define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
 
+	if (inode->i_data[8])
+		bh = bread(inode->i_dev,inode->i_data[8]);
+	if (!bh)
+		return 0;
+repeat:
+	for (i = DINDIRECT_BLOCK ; i < 512 ; i ++) {
+		if (i < 0)
+			i = 0;
+		if (i < DINDIRECT_BLOCK)
+			goto repeat;
+		dind = i+(unsigned short *) bh->b_data;
+		if (!*dind)
+			continue;
+		result |= trunc_indirect(inode,7+512+(i<<9),dind);
+	}
+	dind = (unsigned short *) bh->b_data;
+	for (i = 0; i < 512; i++)
+		if (*(dind++))
+			break;
+	brelse(bh);
+	if (i >= 512) {
+		result = 1;
+		if (minix_free_block(inode->i_dev,inode->i_data[8]))
+			inode->i_data[8] = 0;
+	}
+	return result;
+}
+		
 void minix_truncate(struct inode * inode)
 {
-	int i;
-	int block_busy;
+	int flag;
 
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	     S_ISLNK(inode->i_mode)))
 		return;
-repeat:
-	block_busy = 0;
-	for (i=0;i<7;i++)
-		if (inode->i_data[i]) {
-			if (minix_free_block(inode->i_dev,inode->i_data[i]))
-				inode->i_data[i]=0;
-			else
-				block_busy = 1;
-		}
-	if (minix_free_ind(inode->i_dev,inode->i_data[7]))
-		inode->i_data[7] = 0;
-	else
-		block_busy = 1;
-	if (minix_free_dind(inode->i_dev,inode->i_data[8]))
-		inode->i_data[8] = 0;
-	else
-		block_busy = 1;
-	inode->i_dirt = 1;
-	if (block_busy) {
+	if (inode->i_data[7] & 0xffff0000)
+		printk("BAD! minix inode has 16 high bits set\n");
+	while (1) {
+		flag = trunc_direct(inode);
+		flag |= trunc_indirect(inode,7,(unsigned short *)&inode->i_data[7]);
+		flag |= trunc_dindirect(inode);
+		if (!flag)
+			break;
 		current->counter = 0;
 		schedule();
-		goto repeat;
 	}
-	inode->i_size = 0;
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	inode->i_dirt = 1;
 }
 
 /*
@@ -151,6 +190,9 @@
 			return -EAGAIN;
 	} else if (S_ISBLK(inode->i_mode))
 		check_disk_change(inode->i_rdev);
-	filp->f_op = &minix_file_operations;
+	else if (S_ISREG(inode->i_mode))
+		filp->f_op = &minix_file_operations;
+	else if (S_ISDIR(inode->i_mode))
+		filp->f_op = &minix_dir_operations;
 	return 0;
 }
diff --git a/fs/namei.c b/fs/namei.c
index 6833d62..73c1621 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <asm/segment.h>
 
-#include <string.h>
+#include <linux/string.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <const.h>
@@ -248,8 +248,10 @@
 	}
 	inode->i_atime = CURRENT_TIME;
 	if (flag & O_TRUNC)
-		if (inode->i_op && inode->i_op->truncate)
+		if (inode->i_op && inode->i_op->truncate) {
+			inode->i_size = 0;
 			inode->i_op->truncate(inode);
+		}
 	*res_inode = inode;
 	return 0;
 }
diff --git a/fs/open.c b/fs/open.c
index fe0fb5b..e2cdce7 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -4,23 +4,83 @@
  *  (C) 1991  Linus Torvalds
  */
 
-#include <string.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <utime.h>
-#include <sys/stat.h>
 
+#include <sys/stat.h>
+#include <sys/vfs.h>
+
+#include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 
 #include <asm/segment.h>
 
+struct file_operations * chrdev_fops[MAX_CHRDEV] = {
+	NULL,
+};
+
+struct file_operations * blkdev_fops[MAX_BLKDEV] = {
+	NULL,
+};
+
 int sys_ustat(int dev, struct ustat * ubuf)
 {
 	return -ENOSYS;
 }
 
+int sys_statfs(const char * path, struct statfs * buf)
+{
+	printk("statfs not implemented\n");
+	return -ENOSYS;
+}
+
+int sys_fstatfs(unsigned int fd, struct statfs * buf)
+{
+	printk("fstatfs not implemented\n");
+	return -ENOSYS;
+}
+
+int sys_truncate(const char * path, unsigned int length)
+{
+	struct inode * inode;
+
+	if (!(inode = namei(path)))
+		return -ENOENT;
+	if (!permission(inode,MAY_WRITE)) {
+		iput(inode);
+		return -EPERM;
+	}
+	inode->i_size = length;
+	if (inode->i_op && inode->i_op->truncate)
+		inode->i_op->truncate(inode);
+	inode->i_atime = inode->i_mtime = CURRENT_TIME;
+	inode->i_dirt = 1;
+	iput(inode);
+	return 0;
+}
+
+int sys_ftruncate(unsigned int fd, unsigned int length)
+{
+	struct inode * inode;
+	struct file * file;
+
+	if (fd >= NR_OPEN || !(file = current->filp[fd]))
+		return -EBADF;
+	if (!(inode = file->f_inode))
+		return -ENOENT;
+	if (!(file->f_flags & 2))
+		return -EPERM;
+	inode->i_size = length;
+	if (inode->i_op && inode->i_op->truncate)
+		inode->i_op->truncate(inode);
+	inode->i_atime = inode->i_mtime = CURRENT_TIME;
+	inode->i_dirt = 1;
+	return 0;
+}
+
 int sys_utime(char * filename, struct utimbuf * times)
 {
 	struct inode * inode;
@@ -107,11 +167,27 @@
 	return (0);
 }
 
-int sys_chmod(const char * filename,int mode)
+int sys_fchmod(unsigned int fd, mode_t mode)
+{
+	struct inode * inode;
+	struct file * file;
+
+	if (fd >= NR_OPEN || !(file = current->filp[fd]))
+		return -EBADF;
+	if (!(inode = file->f_inode))
+		return -ENOENT;
+	if ((current->euid != inode->i_uid) && !suser())
+		return -EACCES;
+	inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
+	inode->i_dirt = 1;
+	return 0;
+}
+
+int sys_chmod(const char * filename, mode_t mode)
 {
 	struct inode * inode;
 
-	if (!(inode=namei(filename)))
+	if (!(inode = namei(filename)))
 		return -ENOENT;
 	if ((current->euid != inode->i_uid) && !suser()) {
 		iput(inode);
@@ -123,19 +199,36 @@
 	return 0;
 }
 
-int sys_chown(const char * filename,int uid,int gid)
+int sys_fchown(unsigned int fd, uid_t user, gid_t group)
+{
+	struct inode * inode;
+	struct file * file;
+
+	if (fd >= NR_OPEN || !(file = current->filp[fd]))
+		return -EBADF;
+	if (!(inode = file->f_inode))
+		return -ENOENT;
+	if (!suser())
+		return -EACCES;
+	inode->i_uid = user;
+	inode->i_gid = group;
+	inode->i_dirt=1;
+	return 0;
+}
+
+int sys_chown(const char * filename, uid_t user, gid_t group)
 {
 	struct inode * inode;
 
-	if (!(inode=namei(filename)))
+	if (!(inode = namei(filename)))
 		return -ENOENT;
 	if (!suser()) {
 		iput(inode);
 		return -EACCES;
 	}
-	inode->i_uid=uid;
-	inode->i_gid=gid;
-	inode->i_dirt=1;
+	inode->i_uid = user;
+	inode->i_gid = group;
+	inode->i_dirt = 1;
 	iput(inode);
 	return 0;
 }
@@ -157,13 +250,23 @@
 		if (!f->f_count) break;
 	if (i>=NR_FILE)
 		return -EINVAL;
-	(current->filp[fd]=f)->f_count++;
-	if ((i=open_namei(filename,flag,mode,&inode))<0) {
+	(current->filp[fd] = f)->f_count++;
+	if ((i = open_namei(filename,flag,mode,&inode))<0) {
 		current->filp[fd]=NULL;
 		f->f_count=0;
 		return i;
 	}
 	f->f_op = NULL;
+	if (inode)
+		if (S_ISCHR(inode->i_mode)) {
+			i = MAJOR(inode->i_rdev);
+			if (i < MAX_CHRDEV)
+				f->f_op = chrdev_fops[i];
+		} else if (S_ISBLK(inode->i_mode)) {
+			i = MAJOR(inode->i_rdev);
+			if (i < MAX_CHRDEV)
+				f->f_op = blkdev_fops[i];
+		}
 	f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
 	f->f_flags = flag;
 	f->f_count = 1;
@@ -198,6 +301,8 @@
 		panic("Close: file count is 0");
 	if (--filp->f_count)
 		return (0);
+	if (filp->f_op && filp->f_op->close)
+		return filp->f_op->close(filp->f_inode,filp);
 	iput(filp->f_inode);
-	return (0);
+	return 0;
 }
diff --git a/fs/pipe.c b/fs/pipe.c
index 5f773d9..0aef899 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -9,11 +9,12 @@
 #include <termios.h>
 #include <fcntl.h>
 
-#include <linux/sched.h>
 #include <asm/segment.h>
+
+#include <linux/sched.h>
 #include <linux/kernel.h>
 
-int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
+static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
 	int chars, size, read = 0;
 
@@ -44,7 +45,7 @@
 	return read?read:-EAGAIN;
 }
 	
-int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
+static int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
 {
 	int chars, size, written = 0;
 
@@ -76,6 +77,54 @@
 	return written;
 }
 
+static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
+{
+	return -ESPIPE;
+}
+
+static int pipe_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
+{
+	return -ENOTDIR;
+}
+
+static int bad_pipe_rw(struct inode * inode, struct file * filp, char * buf, int count)
+{
+	return -EBADF;
+}
+
+static int pipe_ioctl(struct inode *pino, struct file * filp,
+	unsigned int cmd, unsigned int arg)
+{
+	switch (cmd) {
+		case FIONREAD:
+			verify_area((void *) arg,4);
+			put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
+			return 0;
+		default:
+			return -EINVAL;
+	}
+}
+
+static struct file_operations read_pipe_fops = {
+	pipe_lseek,
+	pipe_read,
+	bad_pipe_rw,
+	pipe_readdir,
+	NULL,		/* pipe_close */
+	NULL,		/* pipe_select */
+	pipe_ioctl
+};
+
+static struct file_operations write_pipe_fops = {
+	pipe_lseek,
+	bad_pipe_rw,
+	pipe_write,
+	pipe_readdir,
+	NULL,		/* pipe_close */
+	NULL,		/* pipe_select */
+	pipe_ioctl
+};
+
 int sys_pipe(unsigned long * fildes)
 {
 	struct inode * inode;
@@ -111,21 +160,11 @@
 	}
 	f[0]->f_inode = f[1]->f_inode = inode;
 	f[0]->f_pos = f[1]->f_pos = 0;
+	f[0]->f_op = &read_pipe_fops;
 	f[0]->f_mode = 1;		/* read */
+	f[1]->f_op = &write_pipe_fops;
 	f[1]->f_mode = 2;		/* write */
 	put_fs_long(fd[0],0+fildes);
 	put_fs_long(fd[1],1+fildes);
 	return 0;
 }
-
-int pipe_ioctl(struct inode *pino, int cmd, int arg)
-{
-	switch (cmd) {
-		case FIONREAD:
-			verify_area((void *) arg,4);
-			put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
-			return 0;
-		default:
-			return -EINVAL;
-	}
-}
diff --git a/fs/read_write.c b/fs/read_write.c
index 1a9b20a..19cbcda 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -28,43 +28,40 @@
 		return -EBADF;
 	if (file->f_op && file->f_op->readdir) {
 		verify_area(dirent, sizeof (*dirent));
-		return file->f_op->readdir(inode,file,dirent);
+		return file->f_op->readdir(inode,file,dirent,count);
 	}
-	return -EBADF;
+	return -ENOTDIR;
 }
 
 int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
 {
 	struct file * file;
-	int tmp, mem_dev;
+	int tmp;
 
 	if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode))
 		return -EBADF;
 	if (origin > 2)
 		return -EINVAL;
-	if (file->f_inode->i_pipe)
-		return -ESPIPE;
 	if (file->f_op && file->f_op->lseek)
 		return file->f_op->lseek(file->f_inode,file,offset,origin);
-	mem_dev = S_ISCHR(file->f_inode->i_mode);
 
 /* this is the default handler if no lseek handler is present */
 	switch (origin) {
 		case 0:
-			if (offset<0 && !mem_dev) return -EINVAL;
-			file->f_pos=offset;
+			tmp = offset;
 			break;
 		case 1:
-			if (file->f_pos+offset<0 && !mem_dev) return -EINVAL;
-			file->f_pos += offset;
+			tmp = file->f_pos + offset;
 			break;
 		case 2:
-			if ((tmp=file->f_inode->i_size+offset)<0 && !mem_dev)
+			if (!file->f_inode)
 				return -EINVAL;
-			file->f_pos = tmp;
+			tmp = file->f_inode->i_size + offset;
+			break;
 	}
-	if (mem_dev && file->f_pos < 0)
-		return 0;
+	if (tmp < 0)
+		return -EINVAL;
+	file->f_pos = tmp;
 	return file->f_pos;
 }
 
@@ -82,15 +79,6 @@
 	verify_area(buf,count);
 	if (file->f_op && file->f_op->read)
 		return file->f_op->read(inode,file,buf,count);
-/* these are the default read-functions */
-	if (inode->i_pipe)
-		return pipe_read(inode,file,buf,count);
-	if (S_ISCHR(inode->i_mode))
-		return char_read(inode,file,buf,count);
-	if (S_ISBLK(inode->i_mode))
-		return block_read(inode,file,buf,count);
-	if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode))
-		return minix_file_read(inode,file,buf,count);
 	printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
 	return -EINVAL;
 }
@@ -108,15 +96,6 @@
 		return 0;
 	if (file->f_op && file->f_op->write)
 		return file->f_op->write(inode,file,buf,count);
-/* these are the default read-functions */
-	if (inode->i_pipe)
-		return pipe_write(inode,file,buf,count);
-	if (S_ISCHR(inode->i_mode))
-		return char_write(inode,file,buf,count);
-	if (S_ISBLK(inode->i_mode))
-		return block_write(inode,file,buf,count);
-	if (S_ISREG(inode->i_mode))
-		return minix_file_write(inode,file,buf,count);
 	printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
 	return -EINVAL;
 }
diff --git a/fs/select.c b/fs/select.c
index e5d1439..98e74c4 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -9,16 +9,17 @@
 #include <linux/kernel.h>
 #include <linux/tty.h>
 #include <linux/sched.h>
+#include <linux/string.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <string.h>
+#include <sys/time.h>
+
 #include <const.h>
 #include <errno.h>
-#include <sys/time.h>
 #include <signal.h>
 
 /*
@@ -34,18 +35,6 @@
  * task.
  */
 
-typedef struct {
-	struct task_struct * old_task;
-	struct task_struct ** wait_address;
-} wait_entry;
-
-typedef struct select_table_struct {
-	int nr, woken;
-	struct task_struct * current;
-	struct select_table_struct * next_table;
-	wait_entry entry[NR_OPEN*3];
-} select_table;
-
 static select_table * sel_tables = NULL;
 
 static void add_wait(struct task_struct ** wait_address, select_table * p)
diff --git a/fs/super.c b/fs/super.c
index b4c95e0..78f8b6c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -12,6 +12,7 @@
 #include <linux/minix_fs.h>
 #include <linux/kernel.h>
 #include <asm/system.h>
+#include <asm/segment.h>
 
 #include <errno.h>
 #include <sys/stat.h>
@@ -146,7 +147,9 @@
 	struct super_block * sb;
 	int dev;
 
-	if (!(inode=namei(dev_name)))
+	if (!suser())
+		return -EPERM;
+	if (!(inode = namei(dev_name)))
 		return -ENOENT;
 	dev = inode->i_rdev;
 	if (!S_ISBLK(inode->i_mode)) {
@@ -176,13 +179,17 @@
 	return 0;
 }
 
-int sys_mount(char * dev_name, char * dir_name, int rw_flag)
+int sys_mount(char * dev_name, char * dir_name, char * type, int rw_flag)
 {
 	struct inode * dev_i, * dir_i;
 	struct super_block * sb;
 	int dev;
+	char tmp[100],*t;
+	int i;
 
-	if (!(dev_i=namei(dev_name)))
+	if (!suser())
+		return -EPERM;
+	if (!(dev_i = namei(dev_name)))
 		return -ENOENT;
 	dev = dev_i->i_rdev;
 	if (!S_ISBLK(dev_i->i_mode)) {
@@ -204,7 +211,14 @@
 		iput(dir_i);
 		return -EPERM;
 	}
-	if (!(sb=read_super(dev,"minix",NULL))) {
+	if (type) {
+		i = 0;
+		while (i < 100 && (tmp[i] = get_fs_byte(type++)))
+			i++;
+		t = tmp;
+	} else
+		t = "minix";
+	if (!(sb = read_super(dev,t,NULL))) {
 		iput(dir_i);
 		return -EBUSY;
 	}
diff --git a/include/asm/system.h b/include/asm/system.h
index 6f5f670..6fbcf1b 100644
--- a/include/asm/system.h
+++ b/include/asm/system.h
@@ -50,7 +50,7 @@
 		((limit) & 0x0ffff); }
 
 #define _set_tssldt_desc(n,addr,type) \
-__asm__ ("movw $104,%1\n\t" \
+__asm__ ("movw $232,%1\n\t" \
 	"movw %%ax,%2\n\t" \
 	"rorl $16,%%eax\n\t" \
 	"movb %%al,%3\n\t" \
diff --git a/include/checkpoint.h b/include/checkpoint.h
deleted file mode 100644
index e69de29..0000000
--- a/include/checkpoint.h
+++ /dev/null
diff --git a/include/errno.h b/include/errno.h
index a38b78f..fdb1b14 100644
--- a/include/errno.h
+++ b/include/errno.h
@@ -16,7 +16,6 @@
 
 extern int errno;
 
-#define ERROR		99
 #define EPERM		 1
 #define ENOENT		 2
 #define ESRCH		 3
diff --git a/include/linux/config_rel.h b/include/linux/config_rel.h
index 0e26529..a602c1f 100644
--- a/include/linux/config_rel.h
+++ b/include/linux/config_rel.h
@@ -1 +1 @@
-#define UTS_RELEASE "0.95c-18"
+#define UTS_RELEASE "0.95c-54"
diff --git a/include/linux/config_ver.h b/include/linux/config_ver.h
index 1024624..34e98a9 100644
--- a/include/linux/config_ver.h
+++ b/include/linux/config_ver.h
@@ -1 +1 @@
-#define UTS_VERSION "04/09/92"
+#define UTS_VERSION "04/22/92"
diff --git a/include/ctype.h b/include/linux/ctype.h
similarity index 100%
rename from include/ctype.h
rename to include/linux/ctype.h
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d75dd80..7e067bd 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -46,6 +46,9 @@
 #define NR_BUFFERS nr_buffers
 #define BLOCK_SIZE 1024
 #define BLOCK_SIZE_BITS 10
+#define MAX_CHRDEV 16
+#define MAX_BLKDEV 16
+
 #ifndef NULL
 #define NULL ((void *) 0)
 #endif
@@ -115,6 +118,18 @@
 	off_t f_pos;
 };
 
+typedef struct {
+	struct task_struct * old_task;
+	struct task_struct ** wait_address;
+} wait_entry;
+
+typedef struct select_table_struct {
+	int nr, woken;
+	struct task_struct * current;
+	struct select_table_struct * next_table;
+	wait_entry entry[NR_OPEN*3];
+} select_table;
+
 struct super_block {
 	unsigned short s_ninodes;
 	unsigned short s_nzones;
@@ -143,7 +158,10 @@
 	int (*lseek) (struct inode *, struct file *, off_t, int);
 	int (*read) (struct inode *, struct file *, char *, int);
 	int (*write) (struct inode *, struct file *, char *, int);
-	int (*readdir) (struct inode *, struct file *, struct dirent *);
+	int (*readdir) (struct inode *, struct file *, struct dirent *, int count);
+	int (*close) (struct inode *, struct file *);
+	int (*select) (struct inode *, struct file *, int, select_table *);
+	int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned int);
 };
 
 struct inode_operations {
@@ -177,6 +195,9 @@
 	char *name;
 };
 
+extern struct file_operations * chrdev_fops[MAX_CHRDEV];
+extern struct file_operations * blkdev_fops[MAX_BLKDEV];
+
 extern struct file_system_type *get_fs_type(char *name);
 
 extern struct inode inode_table[NR_INODE];
@@ -222,11 +243,9 @@
 extern void lock_super(struct super_block * sb);
 extern void free_super(struct super_block * sb);
 
-extern int pipe_read(struct inode *, struct file *, char *, int);
 extern int char_read(struct inode *, struct file *, char *, int);
 extern int block_read(struct inode *, struct file *, char *, int);
 
-extern int pipe_write(struct inode *, struct file *, char *, int);
 extern int char_write(struct inode *, struct file *, char *, int);
 extern int block_write(struct inode *, struct file *, char *, int);
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index eab299b..2451af9 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -7,7 +7,6 @@
 int printf(const char * fmt, ...);
 int printk(const char * fmt, ...);
 void console_print(const char * str);
-int tty_write(unsigned ch,char * buf,int count);
 void * malloc(unsigned int size);
 void free_s(void * obj, int size);
 
diff --git a/include/linux/lp.h b/include/linux/lp.h
index 69049a7..6e565da 100644
--- a/include/linux/lp.h
+++ b/include/linux/lp.h
@@ -107,8 +107,3 @@
  */
 
 extern void lp_init(void);
-
-extern int lp_reset(int minor);
-extern int lp_char(char lpchar, int minor);
-extern int lp_write(unsigned minor, char *buf, int count);
-
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index 189f438..c427cb1 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -65,23 +65,25 @@
 extern int minix_new_block(int dev);
 extern int minix_free_block(int dev, int block);
 
-extern int minix_create_block(struct inode * inode, int block);
-extern int minix_bmap(struct inode * inode,int block);
+extern int minix_create_block(struct inode *, int);
+extern int minix_bmap(struct inode *,int);
 
-extern void minix_truncate(struct inode * inode);
-extern void minix_put_super(struct super_block *sb);
-extern struct super_block *minix_read_super(struct super_block *s,void *data);
-extern void minix_read_inode(struct inode * inode);
-extern void minix_write_inode(struct inode * inode);
+extern void minix_truncate(struct inode *);
+extern void minix_put_super(struct super_block *);
+extern struct super_block *minix_read_super(struct super_block *,void *);
+extern void minix_read_inode(struct inode *);
+extern void minix_write_inode(struct inode *);
 
-extern int minix_lseek(struct inode * inode, struct file * filp, off_t offset, int origin);
-extern int minix_read(struct inode * inode, struct file * filp, char * buf, int count);
-extern int minix_write(struct inode * inode, struct file * filp, char * buf, int count);
-extern int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent);
+extern int minix_lseek(struct inode *, struct file *, off_t, int);
+extern int minix_read(struct inode *, struct file *, char *, int);
+extern int minix_write(struct inode *, struct file *, char *, int);
+extern int minix_readdir(struct inode *, struct file *, struct dirent *, int);
 extern int minix_file_read(struct inode *, struct file *, char *, int);
 extern int minix_file_write(struct inode *, struct file *, char *, int);
 
 extern struct inode_operations minix_inode_operations;
+
 extern struct file_operations minix_file_operations;
+extern struct file_operations minix_dir_operations;
 
 #endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e1fac82..9d744cb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -7,6 +7,11 @@
 #define TASK_SIZE	0x04000000
 #define LIBRARY_SIZE	0x00400000
 
+/*
+ * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
+ */
+#define IO_BITMAP_SIZE	32
+
 #if (TASK_SIZE & 0x3fffff)
 #error "TASK_SIZE must be multiple of 4M"
 #endif
@@ -53,6 +58,8 @@
 #define NULL ((void *) 0)
 #endif
 
+#define MAX_SHARED_LIBS 6
+
 extern int copy_page_tables(unsigned long from, unsigned long to, long size);
 extern int free_page_tables(unsigned long from, unsigned long size);
 
@@ -60,7 +67,6 @@
 extern void schedule(void);
 extern void trap_init(void);
 extern void panic(const char * str);
-extern int tty_write(unsigned minor,char * buf,int count);
 
 typedef int (*fn_ptr)();
 
@@ -76,29 +82,30 @@
 };
 
 struct tss_struct {
-	long	back_link;	/* 16 high bits zero */
-	long	esp0;
-	long	ss0;		/* 16 high bits zero */
-	long	esp1;
-	long	ss1;		/* 16 high bits zero */
-	long	esp2;
-	long	ss2;		/* 16 high bits zero */
-	long	cr3;
-	long	eip;
-	long	eflags;
-	long	eax,ecx,edx,ebx;
-	long	esp;
-	long	ebp;
-	long	esi;
-	long	edi;
-	long	es;		/* 16 high bits zero */
-	long	cs;		/* 16 high bits zero */
-	long	ss;		/* 16 high bits zero */
-	long	ds;		/* 16 high bits zero */
-	long	fs;		/* 16 high bits zero */
-	long	gs;		/* 16 high bits zero */
-	long	ldt;		/* 16 high bits zero */
-	long	trace_bitmap;	/* bits: trace 0, bitmap 16-31 */
+	unsigned long	back_link;	/* 16 high bits zero */
+	unsigned long	esp0;
+	unsigned long	ss0;		/* 16 high bits zero */
+	unsigned long	esp1;
+	unsigned long	ss1;		/* 16 high bits zero */
+	unsigned long	esp2;
+	unsigned long	ss2;		/* 16 high bits zero */
+	unsigned long	cr3;
+	unsigned long	eip;
+	unsigned long	eflags;
+	unsigned long	eax,ecx,edx,ebx;
+	unsigned long	esp;
+	unsigned long	ebp;
+	unsigned long	esi;
+	unsigned long	edi;
+	unsigned long	es;		/* 16 high bits zero */
+	unsigned long	cs;		/* 16 high bits zero */
+	unsigned long	ss;		/* 16 high bits zero */
+	unsigned long	ds;		/* 16 high bits zero */
+	unsigned long	fs;		/* 16 high bits zero */
+	unsigned long	gs;		/* 16 high bits zero */
+	unsigned long	ldt;		/* 16 high bits zero */
+	unsigned long	trace_bitmap;	/* bits: trace 0, bitmap 16-31 */
+	unsigned long	io_bitmap[IO_BITMAP_SIZE];
 	struct i387_struct i387;
 };
 
@@ -143,9 +150,14 @@
 	struct inode * pwd;
 	struct inode * root;
 	struct inode * executable;
-	struct inode * library;
-	unsigned long close_on_exec;
+	struct {
+		struct inode * library;
+		unsigned long start;
+		unsigned long length;
+	} libraries[MAX_SHARED_LIBS];
+	int numlibraries;
 	struct file * filp[NR_OPEN];
+	unsigned long close_on_exec;
 /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
 	struct desc_struct ldt[3];
 /* tss for this task */
@@ -183,17 +195,18 @@
 /* math */	0, \
 /* rss */	2, \
 /* comm */	"swapper", \
-/* fs info */	0,-1,0022,NULL,NULL,NULL,NULL,0, \
-/* filp */	{NULL,}, \
-	{ \
-		{0,0}, \
-/* ldt */	{0x9f,0xc0fa00}, \
-		{0x9f,0xc0f200}, \
-	}, \
+/* fs info */	0,-1,0022,NULL,NULL,NULL, \
+/* libraries */	{ { NULL, 0, 0}, }, 0, \
+/* filp */	{NULL,}, 0, \
+		{ \
+			{0,0}, \
+/* ldt */		{0x9f,0xc0fa00}, \
+			{0x9f,0xc0f200} \
+		}, \
 /*tss*/	{0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\
 	 0,0,0,0,0,0,0,0, \
 	 0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
-	 _LDT(0),0x80000000, \
+	 _LDT(0),0x80000000,{0xffffffff}, \
 		{} \
 	}, \
 }
diff --git a/include/string.h b/include/linux/string.h
similarity index 100%
rename from include/string.h
rename to include/linux/string.h
diff --git a/include/linux/sys.h b/include/linux/sys.h
index e721865..df8264c 100644
--- a/include/linux/sys.h
+++ b/include/linux/sys.h
@@ -92,6 +92,18 @@
 extern int sys_swapon();
 extern int sys_reboot();
 extern int sys_readdir();
+extern int sys_mmap();
+extern int sys_munmap();
+extern int sys_truncate();
+extern int sys_ftruncate();
+extern int sys_fchmod();
+extern int sys_fchown();
+extern int sys_getpriority();
+extern int sys_setpriority();
+extern int sys_profil();
+extern int sys_statfs();
+extern int sys_fstatfs();
+extern int sys_ioperm();
 
 fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
 sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
@@ -105,10 +117,13 @@
 sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
 sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
 sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
-sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname,
-sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday, 
-sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink,
-sys_lstat, sys_readlink, sys_uselib, sys_swapon, sys_reboot, sys_readdir };
+sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending,
+sys_sethostname, sys_setrlimit, sys_getrlimit, sys_getrusage,
+sys_gettimeofday,  sys_settimeofday, sys_getgroups, sys_setgroups,
+sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
+sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap,
+sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
+sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm };
 
 /* So we don't have to do any more manual updating.... */
 int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index d185dd6..22f0f0e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -119,17 +119,17 @@
 */
 #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
 
-void rs_init(void);
-void con_init(void);
-void tty_init(void);
+extern void rs_init(void);
+extern void lp_init(void);
+extern void con_init(void);
+extern void tty_init(void);
 
-int tty_read(unsigned c, char * buf, int n, unsigned short flags);
-int tty_write(unsigned c, char * buf, int n);
+extern int tty_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
 
-void con_write(struct tty_struct * tty);
-void rs_write(struct tty_struct * tty);
-void mpty_write(struct tty_struct * tty);
-void spty_write(struct tty_struct * tty);
+extern void rs_write(struct tty_struct * tty);
+extern void con_write(struct tty_struct * tty);
+extern void mpty_write(struct tty_struct * tty);
+extern void spty_write(struct tty_struct * tty);
 
 extern void serial_open(unsigned int line);
 
diff --git a/include/sys/kd.h b/include/sys/kd.h
new file mode 100644
index 0000000..9335ebf
--- /dev/null
+++ b/include/sys/kd.h
@@ -0,0 +1,179 @@
+#ifndef _KD_H
+#define _KD_H
+
+/* 0x4B is 'K', to avoid collision with termios and vt */
+
+#define SWAPMONO	0x4B00	/* use mca as output device */
+#define SWAPCGA		0x4B01	/* use cga as output device */
+#define SWAPEGA		0x4B02	/* use ega as output device */
+#define SWAPVGA		0x4B03	/* use vga as output device */
+#define CONS_CURRENT	0x4B04	/* return current output device */
+#define		MONO		0x01
+#define		CGA		0x02
+#define		EGA		0x03
+
+#define SW_B40x25	0x4B05	/* 40x25 mono text (cga/ega) */
+#define SW_C40x25	0x4B06	/* 40x24 color text (cga/ega) */
+#define SW_B80x25	0x4B07	/* 80x25 mono text (cga/ega) */
+#define SW_C80x25	0x4B08	/* 80x25 color text (cga/ega) */
+#define SW_BG320	0x4B09	/* 320x200 mono graphics (cga/ega) */
+#define SW_CG320	0x4B0A	/* 320x200 color graphics (cga/ega) */
+#define SW_BG640	0x4B0B	/* 640x200 mono graphics (cga/ega) */
+#define SW_CG320_D	0x4B0C	/* 320x200 graphics (ega mode d) */
+#define SW_CG640_E	0x4B0D	/* 640x200 graphics (ega mode e) */
+#define SW_EGAMONOAPA	0x4B0E	/* 640x350 graphics (ega mode f) */
+#define SW_ENH_MONOAPA2	0x4B0F	/* 640x350 graphics extd mem (ega mode f*) */
+#define SW_CG640x350	0x4B10	/* 640x350 graphics (ega mode 10) */
+#define SW_ENH_CG640	0x4B11	/* 640x350 graphics extd mem (ega mode 10*) */
+#define SW_EGAMONO80x25	0x4B12	/* 80x25 mono text (ega mode 7) */
+#define SW_ENHB40x25	0x4B13	/* enhanced 40x25 mono text (ega) */
+#define SW_ENHC40x25	0x4B14	/* enhanced 40x25 color text (ega) */
+#define SW_ENHB80x25	0x4B15	/* enhanced 80x25 mono text (ega) */
+#define SW_ENHC80x25	0x4B16	/* enhanced 80x25 color text (ega) */
+#define SW_ENHB80x43	0x4B17	/* enhanced 80x43 mono text (ega) */
+#define SW_ENHC80x43	0x4B18	/* enhanced 80x43 color text (ega) */
+#define SW_MCAMODE	0x4B19	/* reinit mca */
+#define SW_ATT640	0x4B1A	/* 640x400 16color */
+/* should add more vga modes, etc */
+
+#define CONS_GET	0x4B1B	/* get current display mode */
+#define		M_B40x25	0	/* 40x25 mono (cga/ega) */
+#define		M_C40x25	1	/* 40x25 color (cga/ega) */
+#define		M_B80x25	2	/* 80x25 mono (cga/ega) */
+#define		M_C80x25	3	/* 80x25 color (cga/ega) */
+#define		M_BG320		4	/* 320x200 mono (cga/ega) */
+#define		M_CG320		5	/* 320x200 color (cga/ega) */
+#define		M_BG640		6	/* 640x200 mono (cga/ega) */
+#define		M_EGAMONO80x25	7	/* 80x25 mono (ega) */
+#define		M_CG320_D	13	/* ega mode d */
+#define		M_CG640_E	14	/* ega mode e */
+#define		M_EFAMONOAPA	15	/* ega mode f */
+#define		M_CG640x350	16	/* ega mode 10 */
+#define		M_ENHMONOAPA2	17	/* ega mode f with ext mem */
+#define		M_ENH_CG640	18	/* ega mode 10* */
+#define		M_ENH_B40x25	19	/* ega enh 40x25 mono */
+#define		M_ENH_C40x25	20	/* ega enh 40x25 color */
+#define		M_ENH_B80x25	21	/* ega enh 80x25 mono */
+#define		M_ENH_C80x25	22	/* ega enh 80x25 color */
+#define		M_ENH_B80x43	0x70	/* ega enh 80x43 mono */
+#define		M_ENH_C80x43	0x71	/* ega enh 80x43 color */
+#define		M_MCA_MODE	0xff	/* monochrome adapter mode */
+#define MCA_GET		0x4B1C	/* get mca display mode */
+#define CGA_GET		0x4B1D	/* get cga display mode */
+#define EGA_GET		0x4B1E	/* get ega display mode */
+
+#define MAPCONS		0x4B1F	/* map current video mem into address space */
+#define MAPMONO		0x4B20	/* map mca video mem into address space */
+#define MAPCGA		0x4B21	/* map cga video mem into address space */
+#define MAPEGA		0x4B22	/* map ega video mem into address space */
+#define MAPVGA		0x4B23	/* map vga video mem into address space */
+
+struct port_io_struc {
+	char dir;			/* direction in vs out */
+	unsigned short port;
+	char data;
+};
+#define		IN_ON_PORT	0x00
+#define		OUT_ON_PORT	0x01
+struct port_io_arg {
+	struct port_io_struc args[4];
+};
+#define MCAIO		0x4B24	/* i/o to mca video board */
+#define CGAIO		0x4B25	/* i/o to cga video board */
+#define EGAIO		0x4B26	/* i/o to ega video board */
+#define VGAIO		0x4B27	/* i/o to vga video board */
+
+#define GIO_FONT8x8	0x4B28	/* gets current 8x8 font used */
+#define PIO_FONT8x8	0x4B29	/* use supplied 8x8 font */
+#define GIO_FONT8x14	0x4B2A	/* gets current 8x14 font used */
+#define PIO_FONT8x14	0x4B2B	/* use supplied 8x14 font */
+#define GIO_FONT8x16	0x4B2C	/* gets current 8x16 font used */
+#define PIO_FONT8x16	0x4B2D	/* use supplied 8x16 font */
+
+#define MKDIOADDR	32	/* io bitmap size from <linux/sched.h> */
+struct kd_disparam {
+	long type;			/* type of display */
+	char *addr;			/* display mem address */
+	ushort ioaddr[MKDIOADDR];	/* valid i/o addresses */
+};
+#define KDDISPTYPE	0x4B2E	/* gets display info */
+#define		KD_MONO		0x01
+#define		KD_HERCULES	0x02
+#define		KD_CGA		0x03
+#define		KD_EGA		0x04
+
+#define KIOCSOUND	0x4B2F	/* start sound generation (0 for off) */
+#define KDMKTONE	0x4B30	/* generate tone */
+
+#define KDGETLED	0x4B31	/* return current led flags */
+#define KDSETLED	0x4B32	/* set current led flags */
+#define 	LED_SCR		0x01	/* scroll lock */
+#define 	LED_CAP		0x04	/* caps lock */
+#define 	LED_NUM		0x02	/* num lock */
+
+#define KDGKBTYPE	0x4B33	/* get keyboard type */
+#define 	KB_84		0x01
+#define 	KB_101		0x02
+#define 	KB_OTHER	0x03
+
+#define KDADDIO		0x4B34	/* add i/o port as valid */
+#define KDDELIO		0x4B35	/* del i/o port as valid */
+#define KDENABIO	0x4B36	/* enable i/o to video board */
+#define KDDISABIO	0x4B37	/* disable i/o to video board */
+
+struct kd_quemode {
+	int qsize;		/* desired # elem in queue */
+	int signo;		/* signal to send when queue not empty */
+	char *qaddr;		/* user virt addr of queue */
+};
+#define KDQUEMODE	0x4B38	/* enable/disable special queue mode */
+
+#define KDSBORDER	0x4B39	/* set screen boarder in ega text mode */
+
+#define KDSETMODE	0x4B3A	/* set text/grahics mode */
+#define		KD_TEXT		0x00
+#define		KD_GRAPHICS	0x01
+#define		KD_TEXT0	0x02	/* ? */
+#define		KD_TEXT1	0x03	/* ? */
+#define KDGETMODE	0x4B3B	/* get current mode */
+
+struct kd_memloc {
+	char *vaddr;		/* virt addr to map to */
+	char *physaddr;		/* phys addr to map from */
+	long length;		/* number of bytes */
+	long ioflg;		/* enable i/o if set */
+};
+#define KDMAPDISP	0x4B3C	/* map display into address space */
+#define KDUNMAPDISP	0x4B3D	/* unmap display from address space */
+
+#define KDVDCTYPE	0x4B3E	/* return vdc controller/display info */
+
+#define KIOCINFO	0x4B3F	/* tell what the device is */
+
+typedef char scrnmap_t;
+#define		E_TABSZ		256
+#define GIO_SCRNMAP	0x4B40	/* get screen mapping from kernel */
+#define PIO_SCRNMAP	0x4B41	/* put screen mapping table in kernel */
+
+#define GIO_ATTR	0x4B42	/* get screen attributes */
+#define GIO_COLOR	0x4B43	/* return nonzero if display is color */
+
+#define		K_RAW		0x00
+#define		K_XLATE		0x01
+#define KDGKBMODE	0x4B44	/* gets current keyboard mode */
+#define KDSKBMODE	0x4B45	/* sets current keyboard mode */
+
+struct kbentry {
+	u_char kb_table;
+	u_char kb_index;
+	u_char kb_value;
+};
+#define		K_NORMTAB	0x00
+#define		K_SHIFTTAB	0x01
+#define		K_ALTTAB	0x02
+#define		K_ALTSHIFTTAB	0x03
+#define		K_SRQTAB	0x04
+#define KDGKBENT	0x4B46	/* gets one entry in translation table */
+#define KDSKBENT	0x4B47	/* sets one entry in translation table */
+
+#endif /* _KD_H */
diff --git a/include/sys/mman.h b/include/sys/mman.h
new file mode 100644
index 0000000..0a26c1b
--- /dev/null
+++ b/include/sys/mman.h
@@ -0,0 +1,18 @@
+#ifndef _MMAN_H
+#define _MMAN_H
+
+#define PROT_READ        0x1       /* page can be read */
+#define PROT_WRITE       0x2       /* page can be written */
+#define PROT_EXEC        0x4       /* page can be executed */
+#define PROT_NONE        0x0       /* page can not be accessed */
+
+#define MAP_SHARED       1         /* Share changes */
+#define MAP_PRIVATE      2         /* Changes are private */
+#define MAP_TYPE         0xf       /* Mask for type of mapping */
+#define MAP_FIXED        0x10      /* Interpret addr exactly */
+
+extern caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd,
+		    off_t off);
+extern int munmap(caddr_t addr, size_t len);
+
+#endif /* _MMAN_H */
diff --git a/include/sys/stat.h b/include/sys/stat.h
index e917e9c..b709165 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -18,6 +18,7 @@
 };
 
 #define S_IFMT  00170000
+#define S_IFSOCK 0140000
 #define S_IFLNK	 0120000
 #define S_IFREG  0100000
 #define S_IFBLK  0060000
@@ -34,6 +35,7 @@
 #define S_ISCHR(m)	(((m) & S_IFMT) == S_IFCHR)
 #define S_ISBLK(m)	(((m) & S_IFMT) == S_IFBLK)
 #define S_ISFIFO(m)	(((m) & S_IFMT) == S_IFIFO)
+#define S_ISSOCK(m)	(((m) & S_IFMT) == S_IFSOCK)
 
 #define S_IRWXU 00700
 #define S_IRUSR 00400
diff --git a/include/sys/types.h b/include/sys/types.h
index 5e220fa..8529532 100644
--- a/include/sys/types.h
+++ b/include/sys/types.h
@@ -31,6 +31,8 @@
 typedef int daddr_t;
 typedef long off_t;
 typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned long u_long;
 typedef unsigned short ushort;
 typedef char *caddr_t;
 
diff --git a/include/sys/vfs.h b/include/sys/vfs.h
new file mode 100644
index 0000000..c7e113e
--- /dev/null
+++ b/include/sys/vfs.h
@@ -0,0 +1,20 @@
+#ifndef _SYS_VFS_H_
+#define _SYS_VFS_H_
+
+typedef struct {
+	long    val[2];
+} fsid_t;
+
+struct statfs {
+	long f_type;
+	long f_bsize;
+	long f_blocks;
+	long f_bfree;
+	long f_bavail;
+	long f_files;
+	long f_ffree;
+	fsid_t f_fsid;
+	long f_spare[7];
+};
+
+#endif
diff --git a/include/sys/vt.h b/include/sys/vt.h
new file mode 100644
index 0000000..092ae0d
--- /dev/null
+++ b/include/sys/vt.h
@@ -0,0 +1,32 @@
+#ifndef _VT_H
+#define _VT_H
+
+/* 0x56 is 'V', to avoid collision with termios and kd */
+
+#define VT_OPENQRY	0x5600	/* find available vt */
+
+struct vt_mode {
+	char mode;		/* vt mode */
+	char waitv;		/* if set, hang on writes if not active */
+	short relsig;		/* signal to raise on release req */
+	short acqsig;		/* signal to raise on acquisition */
+	short frsig;		/* unused (set to 0) */
+};
+#define VT_GETMODE	0x5601	/* get mode of active vt */
+#define VT_SETMODE	0x5602	/* set mode of active vt */
+#define		VT_AUTO		0x00	/* auto vt switching */
+#define		VT_PROCESS	0x01	/* process controls switching */
+
+struct vt_stat {
+	ushort v_active;	/* active vt */
+	ushort v_signal;	/* signal to send */
+	ushort v_state;		/* vt bitmask */
+};
+#define VT_GETSTATE	0x5603	/* get global vt state info */
+#define VT_SENDSIG	0x5604	/* signal to send to bitmask of vts */
+
+#define VT_RELDISP	0x5605	/* release display */
+
+#define VT_ACTIVATE	0x5606	/* make vt active */
+
+#endif /* _VT_H */
diff --git a/include/unistd.h b/include/unistd.h
index f297df9..6631444 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -65,96 +65,112 @@
 
 #ifdef __LIBRARY__
 
-#define __NR_setup	0	/* used only by init, to get system going */
-#define __NR_exit	1
-#define __NR_fork	2
-#define __NR_read	3
-#define __NR_write	4
-#define __NR_open	5
-#define __NR_close	6
-#define __NR_waitpid	7
-#define __NR_creat	8
-#define __NR_link	9
-#define __NR_unlink	10
-#define __NR_execve	11
-#define __NR_chdir	12
-#define __NR_time	13
-#define __NR_mknod	14
-#define __NR_chmod	15
-#define __NR_chown	16
-#define __NR_break	17
-#define __NR_stat	18
-#define __NR_lseek	19
-#define __NR_getpid	20
-#define __NR_mount	21
-#define __NR_umount	22
-#define __NR_setuid	23
-#define __NR_getuid	24
-#define __NR_stime	25
-#define __NR_ptrace	26
-#define __NR_alarm	27
-#define __NR_fstat	28
-#define __NR_pause	29
-#define __NR_utime	30
-#define __NR_stty	31
-#define __NR_gtty	32
-#define __NR_access	33
-#define __NR_nice	34
-#define __NR_ftime	35
-#define __NR_sync	36
-#define __NR_kill	37
-#define __NR_rename	38
-#define __NR_mkdir	39
-#define __NR_rmdir	40
-#define __NR_dup	41
-#define __NR_pipe	42
-#define __NR_times	43
-#define __NR_prof	44
-#define __NR_brk	45
-#define __NR_setgid	46
-#define __NR_getgid	47
-#define __NR_signal	48
-#define __NR_geteuid	49
-#define __NR_getegid	50
-#define __NR_acct	51
-#define __NR_phys	52
-#define __NR_lock	53
-#define __NR_ioctl	54
-#define __NR_fcntl	55
-#define __NR_mpx	56
-#define __NR_setpgid	57
-#define __NR_ulimit	58
-#define __NR_uname	59
-#define __NR_umask	60
-#define __NR_chroot	61
-#define __NR_ustat	62
-#define __NR_dup2	63
-#define __NR_getppid	64
-#define __NR_getpgrp	65
-#define __NR_setsid	66
-#define __NR_sigaction	67
-#define __NR_sgetmask	68
-#define __NR_ssetmask	69
-#define __NR_setreuid	70
-#define __NR_setregid	71
-#define __NR_sigsuspend	72
-#define __NR_sigpending 73
-#define __NR_sethostname 74
-#define __NR_setrlimit	75
-#define __NR_getrlimit	76
-#define __NR_getrusage	77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
-#define __NR_getgroups	80
-#define __NR_setgroups	81
-#define __NR_select	82
-#define __NR_symlink	83
-#define __NR_lstat	84
-#define __NR_readlink	85
-#define __NR_uselib	86
-#define __NR_swapon	87
-#define __NR_reboot	88
-#define __NR_readdir	89
+#define __NR_setup		  0	/* used only by init, to get system going */
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_chown		 16
+#define __NR_break		 17
+#define __NR_stat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_umount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_fstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_stty		 31
+#define __NR_gtty		 32
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_phys		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+#define __NR_uname		 59
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit		 76
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_lstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+#define __NR_mmap		 90
+#define __NR_munmap		 91
+/*
+ * Not all of these are implemented yet, but these are the
+ * numbers they will use.
+ */
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+#define __NR_profil		 98
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+#define __NR_ioperm		101
 
 /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
 #define _syscall0(type,name) \
@@ -212,6 +228,36 @@
 return -1; \
 }
 
+#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
+type name (atype a, btype b, ctype c, dtype d) \
+{ \
+long __res; \
+__asm__ volatile ("movl %2,%%ebx\n\t" \
+	"int $0x80" \
+	: "=a" (__res) \
+	: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
+	  "d" ((long)(c)),"S" ((long)(d))); \
+if (__res>=0) \
+	return (type) __res; \
+errno=-__res; \
+return -1; \
+}
+
+#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
+type name (atype a,btype b,ctype c,dtype d,etype e) \
+{ \
+long __res; \
+__asm__ volatile ("movl %2,%%ebx\n\t" \
+	"int $0x80" \
+	: "=a" (__res) \
+	: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
+	  "d" ((long)(c)),"S" ((long)(d)),"D" ((long)(e))); \
+if (__res>=0) \
+	return (type) __res; \
+errno=-__res; \
+return -1; \
+}
+
 #endif /* __LIBRARY__ */
 
 /* XXX - illegal. */
@@ -255,7 +301,7 @@
 int link(const char * filename1, const char * filename2);
 off_t lseek(int fildes, off_t offset, int origin);
 int mknod(const char * filename, mode_t mode, dev_t dev); /* XXX - shorts */
-int mount(const char * specialfile, const char * dir, int rwflag);
+int mount(const char * specialfile, const char * dir, const char * type, int rwflag);
 int nice(int val);
 int open(const char * filename, int flag, ...);
 int pause(void);
diff --git a/init/main.c b/init/main.c
index d53e00f..378ca99 100644
--- a/init/main.c
+++ b/init/main.c
@@ -25,9 +25,11 @@
 static inline _syscall1(int,setup,void *,BIOS)
 static inline _syscall0(int,sync)
 
-#include <linux/tty.h>
 #include <linux/sched.h>
+#include <linux/tty.h>
 #include <linux/head.h>
+#include <linux/string.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 
@@ -37,10 +39,6 @@
 #include <fcntl.h>
 #include <sys/types.h>
 
-#include <linux/fs.h>
-
-#include <string.h>
-
 static char printbuf[1024];
 
 extern char *strcpy();
@@ -156,9 +154,8 @@
 #endif
 	mem_init(main_memory_start,memory_end);
 	trap_init();
-	blk_dev_init();
 	chr_dev_init();
-	tty_init();
+	blk_dev_init();
 	time_init();
 	sched_init();
 	buffer_init(buffer_memory_end);
diff --git a/kernel/Makefile b/kernel/Makefile
index a822e41..0ebd895 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -15,6 +15,8 @@
 CPP	=cpp -nostdinc -I../include
 
 
+.S.s:
+	$(CPP) -traditional $< -o $*.s
 .c.s:
 	$(CC) $(CFLAGS) \
 	-S -o $*.s $<
@@ -26,17 +28,21 @@
 
 OBJS  = sched.o sys_call.o traps.o asm.o fork.o \
 	panic.o printk.o vsprintf.o sys.o exit.o \
-	signal.o mktime.o ptrace.o
+	signal.o mktime.o ptrace.o ioport.o
 
 kernel.o: $(OBJS)
 	$(LD) -r -o kernel.o $(OBJS)
 	sync
 
+sys_call.s: sys_call.S
+
+sys_call.o: sys_call.s
+
 sched.o: sched.c
 	$(CC) $(CFLAGS) -fno-omit-frame-pointer -c $<
 
 clean:
-	rm -f core *.o *.a tmp_make keyboard.s
+	rm -f core *.o *.a tmp_make sys_call.s
 	for i in *.c;do rm -f `basename $$i .c`.s;done
 	(cd chr_drv; make clean)
 	(cd blk_drv; make clean)
@@ -49,61 +55,55 @@
 	cp tmp_make Makefile
 	(cd chr_drv; make dep)
 	(cd blk_drv; make dep)
+	(cd math; make dep)
 
 ### Dependencies:
-exit.s exit.o : exit.c ../include/errno.h ../include/signal.h \
-  ../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
-  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
-  ../include/sys/param.h ../include/sys/time.h ../include/time.h \
-  ../include/sys/resource.h ../include/linux/tty.h ../include/termios.h \
-  ../include/asm/segment.h 
-fork.s fork.o : fork.c ../include/errno.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
-  ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+exit.s exit.o : exit.c ../include/errno.h ../include/signal.h ../include/sys/types.h \
+  ../include/sys/wait.h ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
+  ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
+  ../include/linux/tty.h ../include/termios.h ../include/asm/segment.h 
+fork.s fork.o : fork.c ../include/errno.h ../include/stddef.h ../include/linux/sched.h \
+  ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
+  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
+  ../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
   ../include/asm/segment.h ../include/asm/system.h 
+ioport.s ioport.o : ioport.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+  ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
+  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+  ../include/time.h ../include/sys/resource.h ../include/errno.h 
 mktime.s mktime.o : mktime.c ../include/time.h 
-panic.s panic.o : panic.c ../include/linux/kernel.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+panic.s panic.o : panic.c ../include/linux/kernel.h ../include/linux/sched.h ../include/linux/head.h \
+  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/mm.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
   ../include/time.h ../include/sys/resource.h 
-printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h \
-  ../include/linux/kernel.h 
-ptrace.s ptrace.o : ptrace.c ../include/linux/head.h ../include/linux/kernel.h \
-  ../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
-  ../include/time.h ../include/sys/resource.h ../include/errno.h \
-  ../include/asm/segment.h ../include/asm/system.h ../include/sys/ptrace.h 
-sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h \
-  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
-  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
-  ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
-  ../include/time.h ../include/sys/resource.h ../include/linux/timer.h \
-  ../include/linux/sys.h ../include/linux/fdreg.h ../include/asm/system.h \
-  ../include/asm/io.h ../include/asm/segment.h ../include/errno.h 
-signal.s signal.o : signal.c ../include/linux/sched.h ../include/linux/head.h \
-  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
-  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
-  ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
-  ../include/time.h ../include/sys/resource.h ../include/asm/segment.h \
-  ../include/sys/wait.h ../include/errno.h 
-sys.s sys.o : sys.c ../include/errno.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
-  ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
-  ../include/linux/tty.h ../include/termios.h ../include/linux/config.h \
-  ../include/asm/segment.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/string.h 
-traps.s traps.o : traps.c ../include/string.h ../include/linux/head.h \
-  ../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
-  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
-  ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
-  ../include/asm/system.h ../include/asm/segment.h ../include/asm/io.h \
+printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h ../include/linux/kernel.h 
+ptrace.s ptrace.o : ptrace.c ../include/linux/head.h ../include/linux/kernel.h ../include/linux/sched.h \
+  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/mm.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+  ../include/time.h ../include/sys/resource.h ../include/errno.h ../include/asm/segment.h \
+  ../include/asm/system.h ../include/sys/ptrace.h 
+sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+  ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
+  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+  ../include/time.h ../include/sys/resource.h ../include/linux/timer.h ../include/linux/sys.h \
+  ../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h ../include/asm/segment.h \
   ../include/errno.h 
-vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/string.h 
+signal.s signal.o : signal.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
+  ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
+  ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
+  ../include/time.h ../include/sys/resource.h ../include/asm/segment.h ../include/sys/wait.h \
+  ../include/errno.h 
+sys.s sys.o : sys.c ../include/errno.h ../include/linux/sched.h ../include/linux/head.h \
+  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/linux/tty.h \
+  ../include/termios.h ../include/linux/config.h ../include/linux/config_rel.h \
+  ../include/linux/config_ver.h ../include/asm/segment.h ../include/sys/times.h \
+  ../include/sys/utsname.h ../include/linux/string.h 
+traps.s traps.o : traps.c ../include/linux/string.h ../include/linux/head.h ../include/linux/sched.h \
+  ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/system.h \
+  ../include/asm/segment.h ../include/asm/io.h ../include/errno.h 
+vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/linux/string.h 
diff --git a/kernel/asm.s b/kernel/asm.s
index 299e4a9..f565060 100644
--- a/kernel/asm.s
+++ b/kernel/asm.s
@@ -5,138 +5,80 @@
  */
 
 /*
- * asm.s contains the low-level code for most hardware faults.
- * page_exception is handled by the mm, so that isn't here. This
- * file also handles (hopefully) fpu-exceptions due to TS-bit, as
- * the fpu must be properly saved/resored. This hasn't been tested.
+ * asm.s contains the low-level code for interrupts that cannot
+ * result in an task-switch. These are things like the hd- and
+ * floppy-interrupt etc. With these interrupts, we don't have to
+ * care about the stack layout etc.
  */
 
-.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
-.globl _double_fault,_coprocessor_segment_overrun
-.globl _invalid_TSS,_segment_not_present,_stack_segment
-.globl _general_protection,_coprocessor_error,_irq13,_reserved
-.globl _alignment_check
-.globl _page_fault
+.globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
 
-_divide_error:
-	pushl $0 		# no error code
-	pushl $_do_divide_error
-error_code:
-	push %fs
-	push %es
-	push %ds
-	pushl %eax
-	pushl %ebp
-	pushl %edi
-	pushl %esi
-	pushl %edx
-	pushl %ecx
-	pushl %ebx
+_hd_interrupt:
 	cld
-	movl $-1, %eax
-	xchgl %eax, 0x2c(%esp)	# orig_eax (get the error code. )
-	xorl %ebx,%ebx		# zero ebx
-	mov %gs,%bx		# get the lower order bits of gs
-	xchgl %ebx, 0x28(%esp)	# get the address and save gs.
-	pushl %eax		# push the error code
-	lea 52(%esp),%edx
+	pushl %eax
+	pushl %ecx
 	pushl %edx
-	movl $0x10,%edx
-	mov %dx,%ds
-	mov %dx,%es
-	mov %dx,%fs
-	call *%ebx
-	addl $8,%esp
-	popl %ebx
-	popl %ecx
-	popl %edx
-	popl %esi
-	popl %edi
-	popl %ebp
-	popl %eax
-	pop %ds
-	pop %es
+	push %ds
+	push %es
+	push %fs
+	movl $0x10,%eax
+	mov %ax,%ds
+	mov %ax,%es
+	movl $0x17,%eax
+	mov %ax,%fs
+	movb $0x20,%al
+	outb %al,$0xA0		# EOI to interrupt controller #1
+	jmp 1f			# give port chance to breathe
+1:	jmp 1f
+1:	outb %al,$0x20
+	andl $0xfffeffff,_timer_active
+	xorl %edx,%edx
+	xchgl _do_hd,%edx
+	testl %edx,%edx
+	jne 1f
+	movl $_unexpected_hd_interrupt,%edx
+1:	call *%edx		# "interesting" way of handling intr.
 	pop %fs
-	pop %gs
-	addl $4,%esp
+	pop %es
+	pop %ds
+	popl %edx
+	popl %ecx
+	popl %eax
 	iret
 
-_debug:
-	pushl $0
-	pushl $_do_int3		# _do_debug
-	jmp error_code
-
-_nmi:
-	pushl $0
-	pushl $_do_nmi
-	jmp error_code
-
-_int3:
-	pushl $0
-	pushl $_do_int3
-	jmp error_code
-
-_overflow:
-	pushl $0
-	pushl $_do_overflow
-	jmp error_code
-
-_bounds:
-	pushl $0
-	pushl $_do_bounds
-	jmp error_code
-
-_invalid_op:
-	pushl $0
-	pushl $_do_invalid_op
-	jmp error_code
-
-_coprocessor_segment_overrun:
-	pushl $0
-	pushl $_do_coprocessor_segment_overrun
-	jmp error_code
-
-_reserved:
-	pushl $0
-	pushl $_do_reserved
-	jmp error_code
-
-_irq13:
+_floppy_interrupt:
+	cld
 	pushl %eax
-	xorb %al,%al
-	outb %al,$0xF0
+	pushl %ecx
+	pushl %edx
+	push %ds
+	push %es
+	push %fs
+	movl $0x10,%eax
+	mov %ax,%ds
+	mov %ax,%es
+	movl $0x17,%eax
+	mov %ax,%fs
+	movb $0x20,%al
+	outb %al,$0x20		# EOI to interrupt controller #1
+	xorl %eax,%eax
+	xchgl _do_floppy,%eax
+	testl %eax,%eax
+	jne 1f
+	movl $_unexpected_floppy_interrupt,%eax
+1:	call *%eax		# "interesting" way of handling intr.
+	pop %fs
+	pop %es
+	pop %ds
+	popl %edx
+	popl %ecx
+	popl %eax
+	iret
+
+_parallel_interrupt:
+	cld
+	pushl %eax
 	movb $0x20,%al
 	outb %al,$0x20
-	jmp 1f
-1:	jmp 1f
-1:	outb %al,$0xA0
 	popl %eax
-	jmp _coprocessor_error
-
-_double_fault:
-	pushl $_do_double_fault
-	jmp error_code
-
-_invalid_TSS:
-	pushl $_do_invalid_TSS
-	jmp error_code
-
-_segment_not_present:
-	pushl $_do_segment_not_present
-	jmp error_code
-
-_stack_segment:
-	pushl $_do_stack_segment
-	jmp error_code
-
-_general_protection:
-	pushl $_do_general_protection
-	jmp error_code
-
-_alignment_check:
-	pushl $_do_alignment_check
-	jmp error_code
-
-_page_fault:
-	pushl $_do_page_fault
-	jmp error_code
+	iret
diff --git a/kernel/blk_drv/Makefile b/kernel/blk_drv/Makefile
index 516ab48..3aaf961 100644
--- a/kernel/blk_drv/Makefile
+++ b/kernel/blk_drv/Makefile
@@ -42,36 +42,29 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-floppy.s floppy.o : floppy.c ../../include/linux/sched.h ../../include/linux/head.h \
-  ../../include/linux/fs.h ../../include/sys/types.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/linux/fdreg.h \
-  ../../include/asm/system.h ../../include/asm/io.h \
-  ../../include/asm/segment.h blk.h 
-hd.s hd.o : hd.c ../../include/errno.h ../../include/linux/config.h \
-  ../../include/linux/sched.h ../../include/linux/head.h \
-  ../../include/linux/fs.h ../../include/sys/types.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/linux/timer.h \
-  ../../include/linux/hdreg.h ../../include/asm/system.h \
-  ../../include/asm/io.h ../../include/asm/segment.h blk.h 
-ll_rw_blk.s ll_rw_blk.o : ll_rw_blk.c ../../include/errno.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
+floppy.s floppy.o : floppy.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
   ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
-  ../../include/linux/mm.h ../../include/linux/kernel.h \
-  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
-  ../../include/time.h ../../include/sys/resource.h \
-  ../../include/asm/system.h blk.h 
-ramdisk.s ramdisk.o : ramdisk.c ../../include/string.h ../../include/linux/config.h \
-  ../../include/linux/sched.h ../../include/linux/head.h \
-  ../../include/linux/fs.h ../../include/sys/types.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/linux/minix_fs.h \
-  ../../include/asm/system.h ../../include/asm/segment.h \
-  ../../include/asm/memory.h blk.h 
+  ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+  ../../include/linux/fdreg.h ../../include/asm/system.h ../../include/asm/io.h \
+  ../../include/asm/segment.h blk.h 
+hd.s hd.o : hd.c ../../include/errno.h ../../include/linux/config.h ../../include/linux/config_rel.h \
+  ../../include/linux/config_ver.h ../../include/linux/sched.h ../../include/linux/head.h \
+  ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/timer.h ../../include/linux/hdreg.h \
+  ../../include/asm/system.h ../../include/asm/io.h ../../include/asm/segment.h \
+  blk.h 
+ll_rw_blk.s ll_rw_blk.o : ll_rw_blk.c ../../include/errno.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/asm/system.h blk.h 
+ramdisk.s ramdisk.o : ramdisk.c ../../include/linux/string.h ../../include/linux/config.h \
+  ../../include/linux/config_rel.h ../../include/linux/config_ver.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/minix_fs.h ../../include/asm/system.h \
+  ../../include/asm/segment.h ../../include/asm/memory.h blk.h 
diff --git a/kernel/blk_drv/floppy.c b/kernel/blk_drv/floppy.c
index 82c3583..acda4c9 100644
--- a/kernel/blk_drv/floppy.c
+++ b/kernel/blk_drv/floppy.c
@@ -552,11 +552,22 @@
 	1440,1440,1440,1440
 };
 
+static struct file_operations floppy_fops = {
+	NULL,			/* lseek - default */
+	block_read,		/* read - general block-dev read */
+	block_write,		/* write - general block-dev write */
+	NULL,			/* readdir - bad */
+	NULL,			/* close - default */
+	NULL,			/* select */
+	NULL			/* ioctl */
+};
+
 void floppy_init(void)
 {
 	outb(current_DOR,FD_DOR);
 	blk_size[MAJOR_NR] = floppy_sizes;
 	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+	blkdev_fops[MAJOR_NR] = &floppy_fops;
 	set_intr_gate(0x26,&floppy_interrupt);
 	outb(inb_p(0x21)&~0x40,0x21);
 }
diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c
index 1ca50c9..756ebde 100644
--- a/kernel/blk_drv/hd.c
+++ b/kernel/blk_drv/hd.c
@@ -125,7 +125,7 @@
 			       current_minor, hd[current_minor].start_sect, 
 			       hd[current_minor].nr_sects,
 			       hd[current_minor].start_sect + 
-			       hd[current_minor].nr_sects);
+			       hd[current_minor].nr_sects - 1);
 			current_minor++;
 			p++;
 		/*
@@ -171,7 +171,7 @@
 			hd[minor].start_sect = first_sector + p->start_sect;
 			printk(" part %d start %d size %d end %d \n\r", i, 
 			       hd[minor].start_sect, hd[minor].nr_sects, 
-			       hd[minor].start_sect + hd[minor].nr_sects);
+			       hd[minor].start_sect + hd[minor].nr_sects - 1);
 			if ((current_minor & 0x3f) >= 60)
 				continue;
 			if (p->sys_ind == EXTENDED_PARTITION) {
@@ -196,7 +196,7 @@
 				       hd[current_minor].start_sect, 
 				       hd[current_minor].nr_sects,
 				       hd[current_minor].start_sect + 
-				       hd[current_minor].nr_sects);
+				       hd[current_minor].nr_sects - 1);
 			}
 		}
 	} else
@@ -519,25 +519,17 @@
 		panic("unknown hd-command");
 }
 
-void hd_init(void)
-{
-	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-	set_intr_gate(0x2E,&hd_interrupt);
-	outb_p(inb_p(0x21)&0xfb,0x21);
-	outb(inb_p(0xA1)&0xbf,0xA1);
-	timer_table[HD_TIMER].fn = hd_times_out;
-}
-
-int hd_ioctl(int dev, int cmd, int arg)
+static int hd_ioctl(struct inode * inode, struct file * file,
+	unsigned int cmd, unsigned int arg)
 {
 	struct hd_geometry *loc = (void *) arg;
+	int dev;
 
-	if (!loc)
+	if (!loc || !inode)
 		return -EINVAL;
-	dev = MINOR(dev) >> 6;
+	dev = MINOR(inode->i_rdev) >> 6;
 	if (dev >= NR_HD)
 		return -EINVAL;
-
 	switch (cmd) {
 		case HDIO_REQ:
 			put_fs_byte(hd_info[dev].head,
@@ -551,3 +543,23 @@
 			return -EINVAL;
 	}
 }
+
+static struct file_operations hd_fops = {
+	NULL,			/* lseek - default */
+	block_read,		/* read - general block-dev read */
+	block_write,		/* write - general block-dev write */
+	NULL,			/* readdir - bad */
+	NULL,			/* close - default */
+	NULL,			/* select */
+	hd_ioctl		/* ioctl */
+};
+
+void hd_init(void)
+{
+	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+	blkdev_fops[MAJOR_NR] = &hd_fops;
+	set_intr_gate(0x2E,&hd_interrupt);
+	outb_p(inb_p(0x21)&0xfb,0x21);
+	outb(inb_p(0xA1)&0xbf,0xA1);
+	timer_table[HD_TIMER].fn = hd_times_out;
+}
diff --git a/kernel/blk_drv/ll_rw_blk.c b/kernel/blk_drv/ll_rw_blk.c
index 7b17306..475863c 100644
--- a/kernel/blk_drv/ll_rw_blk.c
+++ b/kernel/blk_drv/ll_rw_blk.c
@@ -135,7 +135,7 @@
 	if (rw == READ)
 		req = request+NR_REQUEST;
 	else
-		req = request+((NR_REQUEST*2)/3);
+		req = request+(NR_REQUEST/2);
 /* find an empty request */
 	cli();
 	while (--req >= request)
diff --git a/kernel/blk_drv/ramdisk.c b/kernel/blk_drv/ramdisk.c
index a7d86fb..c507631 100644
--- a/kernel/blk_drv/ramdisk.c
+++ b/kernel/blk_drv/ramdisk.c
@@ -4,7 +4,7 @@
  *  Written by Theodore Ts'o, 12/2/91
  */
 
-#include <string.h>
+#include <linux/string.h>
 
 #include <linux/config.h>
 #include <linux/sched.h>
@@ -47,6 +47,16 @@
 	goto repeat;
 }
 
+static struct file_operations rd_fops = {
+	NULL,			/* lseek - default */
+	block_read,		/* read - general block-dev read */
+	block_write,		/* write - general block-dev write */
+	NULL,			/* readdir - bad */
+	NULL,			/* close - default */
+	NULL,			/* select */
+	NULL			/* ioctl */
+};
+
 /*
  * Returns amount of memory which needs to be reserved.
  */
@@ -56,6 +66,7 @@
 	char	*cp;
 
 	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+	blkdev_fops[MAJOR_NR] = &rd_fops;
 	rd_start = (char *) mem_start;
 	rd_length = length;
 	cp = rd_start;
diff --git a/kernel/chr_drv/Makefile b/kernel/chr_drv/Makefile
index 0246fc7..8049f2f 100644
--- a/kernel/chr_drv/Makefile
+++ b/kernel/chr_drv/Makefile
@@ -26,7 +26,7 @@
 	-c -o $*.o $<
 
 OBJS  = tty_io.o console.o keyboard.o serial.o rs_io.o \
-	tty_ioctl.o pty.o lp.o
+	tty_ioctl.o pty.o lp.o vt.o mem.o
 
 chr_drv.a: $(OBJS)
 	$(AR) rcs chr_drv.a $(OBJS)
@@ -46,58 +46,56 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-console.s console.o : console.c ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
+console.s console.o : console.c ../../include/linux/sched.h ../../include/linux/head.h \
+  ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/timer.h ../../include/linux/tty.h \
+  ../../include/termios.h ../../include/linux/config.h ../../include/linux/config_rel.h \
+  ../../include/linux/config_ver.h ../../include/asm/io.h ../../include/asm/system.h \
+  ../../include/asm/segment.h ../../include/linux/string.h ../../include/errno.h \
+  ../../include/sys/kd.h vt_kern.h 
+lp.s lp.o : lp.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
   ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
-  ../../include/linux/mm.h ../../include/linux/kernel.h \
-  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
-  ../../include/time.h ../../include/sys/resource.h \
-  ../../include/linux/timer.h ../../include/linux/tty.h \
-  ../../include/termios.h ../../include/linux/config.h \
-  ../../include/linux/config_rel.h ../../include/linux/config_ver.h \
-  ../../include/asm/io.h ../../include/asm/system.h \
-  ../../include/asm/segment.h ../../include/string.h ../../include/errno.h 
-lp.s lp.o : lp.c ../../include/linux/lp.h ../../include/errno.h \
-  ../../include/linux/kernel.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
+  ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+  ../../include/linux/lp.h ../../include/errno.h ../../include/asm/io.h ../../include/asm/segment.h 
+mem.s mem.o : mem.c ../../include/errno.h ../../include/sys/types.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/tty.h ../../include/termios.h \
+  ../../include/asm/segment.h ../../include/asm/io.h 
+pty.s pty.o : pty.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
   ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
-  ../../include/linux/mm.h ../../include/signal.h ../../include/sys/param.h \
-  ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
-  ../../include/asm/io.h ../../include/asm/segment.h \
-  ../../include/checkpoint.h 
-pty.s pty.o : pty.c ../../include/linux/tty.h ../../include/termios.h \
-  ../../include/sys/types.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/asm/system.h \
+  ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+  ../../include/linux/tty.h ../../include/termios.h ../../include/asm/system.h \
   ../../include/asm/io.h 
-serial.s serial.o : serial.c ../../include/linux/tty.h ../../include/termios.h \
-  ../../include/sys/types.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/linux/timer.h \
+serial.s serial.o : serial.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+  ../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
+  ../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
+  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+  ../../include/linux/timer.h ../../include/linux/tty.h ../../include/termios.h \
   ../../include/asm/system.h ../../include/asm/io.h 
-tty_io.s tty_io.o : tty_io.c ../../include/ctype.h ../../include/errno.h \
-  ../../include/signal.h ../../include/sys/types.h ../../include/unistd.h \
-  ../../include/sys/stat.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/times.h ../../include/sys/utsname.h \
-  ../../include/sys/param.h ../../include/sys/resource.h \
-  ../../include/utime.h ../../include/fcntl.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/linux/tty.h \
-  ../../include/termios.h ../../include/asm/segment.h \
+tty_io.s tty_io.o : tty_io.c ../../include/linux/ctype.h ../../include/errno.h ../../include/signal.h \
+  ../../include/sys/types.h ../../include/unistd.h ../../include/sys/stat.h ../../include/sys/time.h \
+  ../../include/time.h ../../include/sys/times.h ../../include/sys/utsname.h ../../include/sys/param.h \
+  ../../include/sys/resource.h ../../include/utime.h ../../include/fcntl.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/linux/tty.h ../../include/termios.h ../../include/asm/segment.h \
   ../../include/asm/system.h 
-tty_ioctl.s tty_ioctl.o : tty_ioctl.c ../../include/errno.h ../../include/termios.h \
-  ../../include/sys/types.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/linux/tty.h \
-  ../../include/asm/io.h ../../include/asm/segment.h \
-  ../../include/asm/system.h 
+tty_ioctl.s tty_ioctl.o : tty_ioctl.c ../../include/errno.h ../../include/termios.h ../../include/sys/types.h \
+  ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/tty.h ../../include/asm/io.h \
+  ../../include/asm/segment.h ../../include/asm/system.h 
+vt.s vt.o : vt.c ../../include/errno.h ../../include/sys/types.h ../../include/sys/kd.h \
+  ../../include/sys/vt.h ../../include/asm/io.h ../../include/asm/segment.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+  ../../include/sys/resource.h ../../include/linux/tty.h ../../include/termios.h \
+  vt_kern.h 
diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c
index 2d62be3..01421e5 100644
--- a/kernel/chr_drv/console.c
+++ b/kernel/chr_drv/console.c
@@ -40,9 +40,12 @@
 #include <asm/system.h>
 #include <asm/segment.h>
 
-#include <string.h>
+#include <linux/string.h>
 #include <errno.h>
 
+#include <sys/kd.h>
+#include "vt_kern.h"
+
 #define DEF_TERMIOS \
 (struct termios) { \
 	ICRNL, \
@@ -79,11 +82,14 @@
 
 int NR_CONSOLES = 0;
 
+extern void vt_init(void);
 extern void keyboard_interrupt(void);
 extern void set_leds(void);
 extern unsigned char kapplic;
 extern unsigned char kleds;
 extern unsigned char kmode;
+extern unsigned char kraw;
+extern unsigned char ke0;
 
 unsigned long	video_num_columns;		/* Number of text columns	*/
 unsigned long	video_num_lines;		/* Number of test lines		*/
@@ -120,6 +126,8 @@
 	unsigned char	vc_kbdapplic;
 	unsigned char   vc_kbdleds;
 	unsigned char	vc_kbdmode;
+	unsigned char	vc_kbdraw;
+	unsigned char	vc_kbde0;
 	char *		vc_translate;
 } vc_cons [MAX_CONSOLES];
 
@@ -153,6 +161,8 @@
 #define iscolor		(vc_cons[currcons].vc_iscolor)
 #define kbdapplic	(vc_cons[currcons].vc_kbdapplic)
 #define kbdmode		(vc_cons[currcons].vc_kbdmode)
+#define kbdraw		(vc_cons[currcons].vc_kbdraw)
+#define kbde0		(vc_cons[currcons].vc_kbde0)
 #define kbdleds		(vc_cons[currcons].vc_kbdleds)
 
 int blankinterval = 5*60*HZ;
@@ -970,6 +980,8 @@
 	translate = NORM_TRANS;
 	kbdleds = 2;
 	kbdmode = 0;
+	kbdraw = 0;
+	kbde0 = 0;
 	kbdapplic = 0;
         vc_cons[0].vc_bold_attr = -1;
 
@@ -1000,16 +1012,22 @@
 	a=inb_p(0x61);
 	outb_p(a|0x80,0x61);
 	outb_p(a,0x61);
+
+	vt_init();
 }
 
 void kbdsave(int new_console)
 {
 	int currcons = fg_console;
 	kbdmode = kmode;
+	kbdraw = kraw;
+	kbde0 = ke0;
 	kbdleds = kleds;
 	kbdapplic = kapplic;
 	currcons = new_console;
 	kmode = (kmode & 0x3F) | (kbdmode & 0xC0);
+	kraw = kbdraw;
+	ke0 = kbde0;
 	kleds = kbdleds;
 	kapplic = kbdapplic;
 	set_leds();
@@ -1120,6 +1138,8 @@
 
 	if (currcons<0 || currcons>=NR_CONSOLES)
 		currcons = 0;
+	if (vt_info[currcons].mode == KD_GRAPHICS)
+		return;	/* no output in graphics mode */
 	while (c = *(b++)) {
 		if (c == 10) {
 			cr(currcons);
diff --git a/kernel/chr_drv/keyboard.S b/kernel/chr_drv/keyboard.S
index fa5e2b5..099cfc9 100644
--- a/kernel/chr_drv/keyboard.S
+++ b/kernel/chr_drv/keyboard.S
@@ -5,6 +5,15 @@
  */
 
 /*
+ * NOTE! This file no longer contains the low-level keyboard interrupt:
+ * that is now in kernel/sys_call.S. The reason is that the low-level
+ * interrupt must keep track of stack frames for signals etc.
+ *
+ * Thus it should be very easy to rewrite this in C - I just haven't
+ * bothered.
+ */
+
+/*
  *	Thanks to Alfred Leung for US keyboard patches
  *		Wolfgang Thiel for German keyboard patches
  *		Marc Corsini for the French keyboard
@@ -22,11 +31,14 @@
 
 .text
 .globl _hard_reset_now
-.globl _keyboard_interrupt
+.globl _do_keyboard_interrupt
+.globl _do_keyboard
 .globl _kapplic
 .globl _kmode
 .globl _kleds
 .globl _set_leds
+.globl _kraw
+.globl _ke0
 
 /*
  * these are for the keyboard read functions
@@ -41,24 +53,15 @@
 _kapplic:	.byte 0
 _kmode:	.byte 0		/* caps, alt, ctrl and shift mode */
 _kleds:	.byte 2		/* num-lock, caps, scroll-lock mode (nom-lock on) */
-e0:	.byte 0
+_ke0:	.byte 0
+_kraw:	.byte 0
 
 /*
- *  con_int is the real interrupt routine that reads the
+ *  do_keyboard is the real interrupt routine that reads the
  *  keyboard scan-code and converts it into the appropriate
  *  ascii character(s).
  */
-_keyboard_interrupt:
-	cld
-	pushl %eax
-	pushl %ebx
-	pushl %ecx
-	pushl %edx
-	push %ds
-	push %es
-	movl $0x10,%eax
-	mov %ax,%ds
-	mov %ax,%es
+_do_keyboard:
 	xorl %eax,%eax		/* %eax is scan code */
 	inb $0x60,%al
 	pushl %eax
@@ -77,7 +80,14 @@
 1:	jmp 1f
 1:	movb $0x20,%al
 	outb %al,$0x20
+	cmpb $0,_kraw
+	je 1f
+	xorl %ebx,%ebx		/* if raw kbd, just put scancode */
 	popl %eax
+	sti
+	call put_queue
+	jmp postkey
+1:	popl %eax
 	movl $1,%ebx
 	cmpb $0xE0,%al
 	je end_intr
@@ -86,17 +96,12 @@
 	je end_intr
 	sti
 	call key_table(,%eax,4)
+postkey:
 	call _do_keyboard_interrupt
 	movl $0,%ebx
 end_intr:
-	movb %bl,e0
-	pop %es
-	pop %ds
-	popl %edx
-	popl %ecx
-	popl %ebx
-	popl %eax
-	iret
+	movb %bl,_ke0
+	ret
 
 /*
  * This routine fills the buffer with max 8 bytes, taken from
@@ -129,7 +134,7 @@
 ctrl:	movb $0x04,%al
 	jmp 1f
 alt:	movb $0x10,%al
-1:	cmpb $0,e0
+1:	cmpb $0,_ke0
 	je 2f
 	addb %al,%al
 2:	orb %al,_kmode
@@ -137,7 +142,7 @@
 unctrl:	movb $0x04,%al
 	jmp 1f
 unalt:	movb $0x10,%al
-1:	cmpb $0,e0
+1:	cmpb $0,_ke0
 	je 2f
 	addb %al,%al
 2:	notb %al
@@ -215,7 +220,7 @@
 	je cur2
 	testb $0x30,_kmode
 	jne _ctrl_alt_del
-cur2:	cmpb $0x01,e0		/* e0 forces cursor movement */
+cur2:	cmpb $0x01,_ke0		/* _ke0 forces cursor movement */
 	je cur
 	testb $0x03,_kmode	/* shift forces cursor */
 	jne cur
@@ -349,7 +354,7 @@
 
 alt_map:
 	.byte 0,0
-	.ascii "\0@\0$\0\0{[]}\\\0"
+	.ascii "\0@\243$\0\0{[]}\\\0"
 	.byte 0,0
 	.byte 0,0,0,0,0,0,0,0,0,0,0
 	.byte '~,13,0
@@ -433,7 +438,7 @@
 
 shift_map:
 	.byte 0,27
-	.ascii "!\"#$%^&*()_+"
+	.ascii "!\"\243$%^&*()_+"
 	.byte 127,9
 	.ascii "QWERTYUIOP{}"
 	.byte 13,0
@@ -654,7 +659,7 @@
  * the scan code for slash means that the numeric keypad
  * slash was pushed.
  */
-slash:	cmpb $1,e0
+slash:	cmpb $1,_ke0
 	jne do_self
 	cmpb $1,_kapplic
 	jne notmapplic
@@ -676,7 +681,7 @@
 	xorl %ebx,%ebx
 	jmp put_queue
 
-enter:	cmpb $1,e0
+enter:	cmpb $1,_ke0
 	jne do_self
 	cmpb $1,_kapplic
 	jne do_self
diff --git a/kernel/chr_drv/lp.c b/kernel/chr_drv/lp.c
index 0f6e88f..53d4c9b 100644
--- a/kernel/chr_drv/lp.c
+++ b/kernel/chr_drv/lp.c
@@ -3,12 +3,16 @@
   james_r_wiegand Exp james_r_wiegand $
 */
 
+/*
+ * Edited by Linus - cleaner interface etc. Still not using interrupts, so
+ * it eats more resources than necessary, but it was easy to code this way...
+ */
+
+#include <linux/sched.h>
 #define __LP_C__
 #include <linux/lp.h>
 
-#include <checkpoint.h>
-
-int lp_reset(int minor)
+static int lp_reset(int minor)
 {
 	int testvalue;
 
@@ -20,31 +24,7 @@
 	return LP_S(minor);
 }
 
-void lp_init(void)
-{
-	int offset = 0;
-	unsigned int testvalue = 0;
-	int count = 0;
-
-	/* take on all known port values */
-	for (offset = 0; offset < LP_NO; offset++) {
-		/* write to port & read back to check */
-		outb( LP_DUMMY, LP_B(offset));
-		for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
-			;
-		testvalue = inb(LP_B(offset));
-		if (testvalue != 255) {
-			LP_F(offset) |= LP_EXIST;
-			lp_reset(offset);
-			printk("lp_init: lp%d exists (%d)\n", offset, testvalue);
-			count++;
-		}
-	}
-	if (count == 0)
-		printk("lp_init: no lp devices found\n");
-}
-
-int lp_char(char lpchar, int minor)
+static int lp_char(char lpchar, int minor)
 {
 	int retval = 0;
 	unsigned long count  = 0; 
@@ -67,61 +47,92 @@
 	return LP_S(minor);
 }
 
-int lp_write(unsigned minor, char *buf, int count)
+static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
 {
 	int  retval;
-	int  loop;
-	int  tcount;
+	unsigned int minor = MINOR(inode->i_rdev);
 	char c, *temp = buf;
 
-	if (minor > LP_NO - 1)
+	if (minor >= LP_NO)
 		return -ENODEV;
 	if ((LP_F(minor) & LP_EXIST) == 0)
 		return -ENODEV;
-
-/* if we aren't the "owner task", check if the old owner has died... */
-	if (LP_T(minor) != current->pid && (LP_F(minor) & LP_BUSY)) {
-		for(tcount = 0; tcount < NR_TASKS; tcount++) { 
-			if (!task[tcount])
-				continue;
-			if (task[tcount]->state == TASK_ZOMBIE)
-				continue;
-			if (task[tcount]->pid == LP_T(minor)) {
-			        tcount = -1;
-				break;
-			}
-		}
-		if (tcount == -1)
-			return -EBUSY;
-	}
-
 	LP_T(minor) = current->pid;
 	LP_F(minor) |= LP_BUSY;
 	LP_R(minor) = count;
 	temp = buf;
-
-	for (loop = 0 ; loop < count ; loop++, temp++) {
-		c = get_fs_byte(temp);
+	while (count > 0) {
+		c = get_fs_byte(temp++);
 		retval = lp_char(c, minor);
-		LP_R(minor)--;
+		count--;
 		if (retval & LP_POUTPA) {
 			LP_F(minor) |= LP_NOPA;
-			return loop?loop:-ENOSPC;
+			return temp-buf?temp-buf:-ENOSPC;
 		} else
 			LP_F(minor) &= ~LP_NOPA;
 
 		if (!(retval & LP_PSELECD)) {
 			LP_F(minor) &= ~LP_SELEC;
-			return loop?loop:-EFAULT;
+			return temp-buf?temp-buf:-EFAULT;
 		} else
 			LP_F(minor) &= ~LP_SELEC;
 
     /* not offline or out of paper. on fire? */
 		if (!(retval & LP_PERRORP)) {
 			LP_F(minor) |= LP_ERR;
-			return loop?loop:-EIO;
+			return temp-buf?temp-buf:-EIO;
 		} else
 			LP_F(minor) &= ~LP_SELEC;
 	}
-	return count;
+	return temp-buf;
+}
+
+static int lp_read(struct inode * inode, struct file * file, char * buf, int count)
+{
+	return -EINVAL;
+}
+
+static int lp_lseek(struct inode * inode, struct file * file, off_t offset, int origin)
+{
+	return -EINVAL;
+}
+
+static int lp_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
+{
+	return -ENOTDIR;
+}
+
+static struct file_operations lp_fops = {
+	lp_lseek,
+	lp_read,
+	lp_write,
+	lp_readdir,
+	NULL,		/* lp_close */
+	NULL,		/* lp_select */
+	NULL		/* lp_ioctl */
+};
+
+void lp_init(void)
+{
+	int offset = 0;
+	unsigned int testvalue = 0;
+	int count = 0;
+
+	chrdev_fops[6] = &lp_fops;
+	/* take on all known port values */
+	for (offset = 0; offset < LP_NO; offset++) {
+		/* write to port & read back to check */
+		outb( LP_DUMMY, LP_B(offset));
+		for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
+			;
+		testvalue = inb(LP_B(offset));
+		if (testvalue != 255) {
+			LP_F(offset) |= LP_EXIST;
+			lp_reset(offset);
+			printk("lp_init: lp%d exists (%d)\n", offset, testvalue);
+			count++;
+		}
+	}
+	if (count == 0)
+		printk("lp_init: no lp devices found\n");
 }
diff --git a/kernel/chr_drv/mem.c b/kernel/chr_drv/mem.c
new file mode 100644
index 0000000..db3138f
--- /dev/null
+++ b/kernel/chr_drv/mem.c
@@ -0,0 +1,238 @@
+/*
+ *  linux/kernel/chr_drv/mem.c
+ *
+ *  (C) 1991  Linus Torvalds
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+
+static int read_ram(struct inode * inode, struct file * file,char * buf, int count)
+{
+	return -EIO;
+}
+
+static int write_ram(struct inode * inode, struct file * file,char * buf, int count)
+{
+	return -EIO;
+}
+
+static int read_mem(struct inode * inode, struct file * file,char * buf, int count)
+{
+	unsigned long addr;
+	char *tmp;
+	unsigned long pde, pte, page;
+	int i;
+
+	if (count < 0)
+		return -EINVAL;
+	addr = file->f_pos;
+	tmp = buf;
+	while (count > 0) {
+		pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
+		if (!((pte = *((unsigned long *) pde)) & 1))
+			break;
+		pte &= 0xfffff000;
+		pte += (addr >> 10) & 0xffc;
+		if (((page = *((unsigned long *) pte)) & 1) == 0)
+			break;
+/*
+		if ((page & 2) == 0)
+			un_wp_page((unsigned long *) pte);
+*/
+		page &= 0xfffff000;
+		page += addr & 0xfff;
+		i = 4096-(addr & 0xfff);
+		if (i > count)
+			i = count;
+		memcpy_tofs(tmp,(void *) page,i);
+		addr += i;
+		tmp += i;
+		count -= i;
+	}
+	file->f_pos = addr;
+	return tmp-buf;
+}
+
+static int write_mem(struct inode * inode, struct file * file,char * buf, int count)
+{
+	unsigned long addr;
+	char *tmp;
+	unsigned long pde, pte, page;
+	int i;
+
+	if (count < 0)
+		return -EINVAL;
+	addr = file->f_pos;
+	tmp = buf;
+	while (count > 0) {
+		pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
+		if (!((pte = *((unsigned long *) pde)) & 1))
+			break;
+		pte &= 0xfffff000;
+		pte += (addr >> 10) & 0xffc;
+		if (((page = *((unsigned long *) pte)) & 1) == 0)
+			break;
+		if ((page & 2) == 0)
+			un_wp_page((unsigned long *) pte);
+		page &= 0xfffff000;
+		page += addr & 0xfff;
+		i = 4096-(addr & 0xfff);
+		if (i > count)
+			i = count;
+		memcpy_fromfs((void *) page,tmp,i);
+		addr += i;
+		tmp += i;
+		count -= i;
+	}
+	file->f_pos = addr;
+	return tmp-buf;
+}
+
+static int read_kmem(struct inode * inode, struct file * file,char * buf, int count)
+{
+	unsigned long p = file->f_pos;
+
+	if (count < 0)
+		return -EINVAL;
+	if (p >= HIGH_MEMORY)
+		return 0;
+	if (count > HIGH_MEMORY - p)
+		count = HIGH_MEMORY - p;
+	memcpy_tofs(buf,(void *) p,count);
+	file->f_pos += count;
+	return count;
+}
+
+static int write_kmem(struct inode * inode, struct file * file,char * buf, int count)
+{
+	unsigned long p = file->f_pos;
+
+	if (count < 0)
+		return -EINVAL;
+	if (p >= HIGH_MEMORY)
+		return 0;
+	if (count > HIGH_MEMORY - p)
+		count = HIGH_MEMORY - p;
+	memcpy_fromfs((void *) p,buf,count);
+	file->f_pos += count;
+	return count;
+}
+
+static int read_port(struct inode * inode,struct file * file,char * buf, int count)
+{
+	unsigned int i = file->f_pos;
+	char * tmp = buf;
+
+	while (count-- > 0 && i < 65536) {
+		put_fs_byte(inb(i),tmp);
+		i++;
+		tmp++;
+	}
+	file->f_pos = i;
+	return tmp-buf;
+}
+
+static int write_port(struct inode * inode,struct file * file,char * buf, int count)
+{
+	unsigned int i = file->f_pos;
+	char * tmp = buf;
+
+	while (count-- > 0 && i < 65536) {
+		outb(get_fs_byte(tmp),i);
+		i++;
+		tmp++;
+	}
+	file->f_pos = i;
+	return tmp-buf;
+}
+
+/*
+ * The memory devices use the full 32 bits of the offset, and so we cannot
+ * check against negative addresses: they are ok. The return value is weird,
+ * though, in that case (0).
+ *
+ * also note that seeking relative to the "end of file" isn't supported:
+ * it has no meaning, so it returns -EINVAL.
+ */
+static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
+{
+	switch (orig) {
+		case 0:
+			file->f_pos = offset;
+			return file->f_pos;
+		case 1:
+			file->f_pos += offset;
+			return file->f_pos;
+		default:
+			return -EINVAL;
+	}
+	if (file->f_pos < 0)
+		return 0;
+	return file->f_pos;
+}
+
+static int mem_read(struct inode * inode, struct file * file, char * buf, int count)
+{
+	switch (MINOR(inode->i_rdev)) {
+		case 0:
+			return read_ram(inode,file,buf,count);
+		case 1:
+			return read_mem(inode,file,buf,count);
+		case 2:
+			return read_kmem(inode,file,buf,count);
+		case 3:
+			return 0;	/* /dev/null */
+		case 4:
+			return read_port(inode,file,buf,count);
+		default:
+			return -ENODEV;
+	}
+}
+
+static int mem_write(struct inode * inode, struct file * file, char * buf, int count)
+{
+	switch (MINOR(inode->i_rdev)) {
+		case 0:
+			return write_ram(inode,file,buf,count);
+		case 1:
+			return write_mem(inode,file,buf,count);
+		case 2:
+			return write_kmem(inode,file,buf,count);
+		case 3:
+			return count;	/* /dev/null */
+		case 4:
+			return write_port(inode,file,buf,count);
+		default:
+			return -ENODEV;
+	}
+}
+
+static int mem_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
+{
+	return -ENOTDIR;
+}
+
+static struct file_operations mem_fops = {
+	mem_lseek,
+	mem_read,
+	mem_write,
+	mem_readdir,
+	NULL,		/* mem_close */
+	NULL,		/* mem_select */
+	NULL		/* mem_ioctl */
+};
+
+void chr_dev_init(void)
+{
+	chrdev_fops[1] = &mem_fops;
+	tty_init();
+	lp_init();
+}
diff --git a/kernel/chr_drv/pty.c b/kernel/chr_drv/pty.c
index aed5b6e..0647ce8 100644
--- a/kernel/chr_drv/pty.c
+++ b/kernel/chr_drv/pty.c
@@ -12,8 +12,9 @@
  *	void spty_write(struct tty_struct * queue);
  */
 
-#include <linux/tty.h>
 #include <linux/sched.h>
+#include <linux/tty.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 
diff --git a/kernel/chr_drv/serial.c b/kernel/chr_drv/serial.c
index bd55ec1..f626071 100644
--- a/kernel/chr_drv/serial.c
+++ b/kernel/chr_drv/serial.c
@@ -13,9 +13,10 @@
  * and all interrupts pertaining to serial IO.
  */
 
-#include <linux/tty.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/tty.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index 511860a..8e376bb 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -11,7 +11,7 @@
  * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
  */
 
-#include <ctype.h>
+#include <linux/ctype.h>
 #include <errno.h>
 #include <signal.h>
 #include <unistd.h>
@@ -272,7 +272,7 @@
 					/* (but restart after we continue) */
 }
 
-int tty_read(unsigned channel, char * buf, int nr, unsigned short flags)
+static int read_chan(unsigned int channel, struct file * file, char * buf, int nr)
 {
 	struct tty_struct * tty;
 	struct tty_struct * other_tty = NULL;
@@ -304,7 +304,7 @@
 			current->timeout = time + jiffies;
 		time = 0;
 	}
-	if (flags & O_NONBLOCK)
+	if (file->f_flags & O_NONBLOCK)
 		time = current->timeout = 0;
 	if (minimum>nr)
 		minimum = nr;
@@ -355,12 +355,12 @@
 		return b-buf;
 	if (current->signal & ~current->blocked)
 		return -ERESTARTSYS;
-	if (flags & O_NONBLOCK)
+	if (file->f_flags & O_NONBLOCK)
 		return -EAGAIN;
 	return 0;
 }
 
-int tty_write(unsigned channel, char * buf, int nr)
+static int write_chan(unsigned int channel, struct file * file, char * buf, int nr)
 {
 	static cr_flag=0;
 	struct tty_struct * tty;
@@ -412,14 +412,62 @@
 	return 0;
 }
 
-void chr_dev_init(void)
+static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
 {
+	return read_chan(current->tty,file,buf,count);
 }
 
+static int ttyx_read(struct inode * inode, struct file * file, char * buf, int count)
+{
+	return read_chan(MINOR(inode->i_rdev),file,buf,count);
+}
+
+static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
+{
+	return write_chan(current->tty,file,buf,count);
+}
+
+static int ttyx_write(struct inode * inode, struct file * file, char * buf, int count)
+{
+	return write_chan(MINOR(inode->i_rdev),file,buf,count);
+}
+
+static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
+{
+	return -EBADF;
+}
+
+static int tty_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
+{
+	return -ENOTDIR;
+}
+
+static struct file_operations tty_fops = {
+	tty_lseek,
+	tty_read,
+	tty_write,
+	tty_readdir,
+	NULL,		/* tty_close */
+	NULL,		/* tty_select */
+	tty_ioctl	/* tty_ioctl */
+};
+
+static struct file_operations ttyx_fops = {
+	tty_lseek,
+	ttyx_read,
+	ttyx_write,
+	tty_readdir,
+	NULL,		/* ttyx_close */
+	NULL,		/* ttyx_select */
+	tty_ioctl	/* ttyx_ioctl */
+};
+
 void tty_init(void)
 {
 	int i;
 
+	chrdev_fops[4] = &ttyx_fops;
+	chrdev_fops[5] = &tty_fops;
 	for (i=0 ; i < QUEUES ; i++)
 		tty_queues[i] = (struct tty_queue) {0,0,0,0,""};
 	rs_queues[0] = (struct tty_queue) {0x3f8,0,0,0,""};
@@ -507,5 +555,4 @@
 	rs_init();
 	printk("%d virtual consoles\n\r",NR_CONSOLES);
 	printk("%d pty's\n\r",NR_PTYS);
-	lp_init();
 }
diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c
index a8594f0..9601268 100644
--- a/kernel/chr_drv/tty_ioctl.c
+++ b/kernel/chr_drv/tty_ioctl.c
@@ -6,6 +6,7 @@
 
 #include <errno.h>
 #include <termios.h>
+#include <sys/types.h>
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -19,6 +20,7 @@
 extern int do_screendump(int arg);
 extern int kill_pg(int pgrp, int sig, int priv);
 extern int tty_signal(int sig, struct tty_struct *tty);
+extern int vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg);
 
 static unsigned short quotient[] = {
 	0, 2304, 1536, 1047, 857,
@@ -203,18 +205,20 @@
 	return 0;
 }
 
-int tty_ioctl(int dev, int cmd, int arg)
+int tty_ioctl(struct inode * inode, struct file * file,
+	unsigned int cmd, unsigned int arg)
 {
 	struct tty_struct * tty;
 	struct tty_struct * other_tty;
 	int pgrp;
+	int dev;
 
-	if (MAJOR(dev) == 5) {
+	if (MAJOR(inode->i_rdev) == 5) {
 		dev = current->tty;
 		if (dev<0)
 			return -EINVAL;
 	} else
-		dev=MINOR(dev);
+		dev = MINOR(inode->i_rdev);
 	tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);
 
 	if (IS_A_PTY(dev))
@@ -355,6 +359,6 @@
 					return -EINVAL;
 			}
 		default:
-			return -EINVAL;
+			return vt_ioctl(tty, dev, cmd, arg);
 	}
 }
diff --git a/kernel/chr_drv/vt.c b/kernel/chr_drv/vt.c
new file mode 100644
index 0000000..549cb93
--- /dev/null
+++ b/kernel/chr_drv/vt.c
@@ -0,0 +1,170 @@
+/*
+ *  kernel/chr_drv/vt.c
+ *
+ *  (C) 1992 obz under the linux copyright
+ */
+
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/kd.h>
+#include <sys/vt.h>
+
+#include <asm/io.h>
+#include <asm/segment.h>
+
+#include <linux/sched.h>
+#include <linux/tty.h>
+#include <linux/kernel.h>
+
+#include "vt_kern.h"
+
+/*
+ * console (vt and kd) routines, as defined by usl svr4 manual
+ */
+
+struct vt_info vt_info[MAX_CONSOLES];
+
+extern int NR_CONSOLES;
+extern unsigned char kleds;
+extern unsigned char kraw;
+extern unsigned char ke0;
+
+extern int sys_ioperm(unsigned long from, unsigned long num, int on);
+extern void set_leds(void);
+
+/*
+ * these are the valid i/o ports we're allowed to change. they map all the
+ * video ports
+ */
+#define GPFIRST 0x3b4
+#define GPLAST 0x3df
+#define GPNUM (GPLAST - GPFIRST + 1)
+
+/*
+ * turns on sound of some freq. 0 turns it off.
+ * stolen from console.c, so i'm not sure if its the correct interpretation
+ */
+static int
+kiocsound(unsigned int freq)
+{
+	if (freq == 0) {
+		/* disable counter 2 */
+		outb(inb_p(0x61)&0xFC, 0x61);
+	}
+	else {
+		/* enable counter 2 */
+		outb_p(inb_p(0x61)|3, 0x61);
+		/* set command for counter 2, 2 byte write */
+		outb_p(0xB6, 0x43);
+		/* select desired HZ */
+		outb_p(freq & 0xff, 0x42);
+		outb((freq >> 8) & 0xff, 0x42);
+	}
+	return 0;
+}
+
+int
+vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg)
+{
+	switch (cmd) {
+	case KIOCSOUND:
+		return kiocsound((unsigned int)arg);
+
+	case KDGKBTYPE:
+		verify_area((void *) arg, sizeof(unsigned char));
+		put_fs_byte(KB_101, (unsigned char *) arg);
+		return 0;
+
+	case KDADDIO:
+	case KDDELIO:
+		/*
+		 * KDADDIO and KDDELIO may be able to add ports beyond what
+		 * we reject here, but to be safe...
+		 */
+		if (arg < GPFIRST || arg > GPLAST)
+			return -EINVAL;
+		return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
+
+	case KDENABIO:
+	case KDDISABIO:
+		return sys_ioperm(GPFIRST, GPNUM, (cmd == KDENABIO)) ? -ENXIO : 0;
+
+	case KDSETMODE:
+		/*
+		 * currently, setting the mode from KD_TEXT to KD_GRAPHICS
+		 * doesn't do a whole lot. i'm not sure if it should do any
+		 * restoration of modes or what...
+		 */
+		switch (arg) {
+		case KD_GRAPHICS:
+			break;
+		case KD_TEXT0:
+		case KD_TEXT1:
+			arg = KD_TEXT;
+		case KD_TEXT:
+			break;
+		default:
+			return -EINVAL;
+		}
+		vt_info[fg_console].mode = arg;
+		return 0;
+	case KDGETMODE:
+		verify_area((void *) arg, sizeof(unsigned long));
+		put_fs_long(vt_info[fg_console].mode, (unsigned long *) arg);
+		return 0;
+
+	case KDMAPDISP:
+	case KDUNMAPDISP:
+		/*
+		 * these work like a combination of mmap and KDENABIO.
+		 * this could be easily finished.
+		 */
+		return -EINVAL;
+
+	case KDSKBMODE:
+		if (arg == K_RAW) {
+			kraw = 1;
+			ke0 = 0;
+		}
+		else if (arg == K_XLATE) {
+			kraw = 0;
+		}
+		else
+			return -EINVAL;
+		return 0;
+	case KDGKBMODE:
+		verify_area((void *) arg, sizeof(unsigned long));
+		put_fs_long(kraw ? K_RAW : K_XLATE, (unsigned long *) arg);
+		return 0;
+
+	case KDGETLED:
+		verify_area((void *) arg, sizeof(unsigned char));
+		put_fs_byte((((kleds & 1) ? LED_SCR : 0) |
+			     ((kleds & 2) ? LED_NUM : 0) |
+			     ((kleds & 4) ? LED_CAP : 0)),
+			    (unsigned char *) arg);
+		return 0;
+	case KDSETLED:
+		if (arg & ~7)
+			return -EINVAL;
+		kleds = (((arg & LED_SCR) ? 1 : 0) |
+			 ((arg & LED_NUM) ? 2 : 0) |
+			 ((arg & LED_CAP) ? 4 : 0));
+		set_leds();
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+void
+vt_init(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CONSOLES; ++i) {
+		vt_info[i].mode = KD_TEXT;
+	}
+}
diff --git a/kernel/chr_drv/vt_kern.h b/kernel/chr_drv/vt_kern.h
new file mode 100644
index 0000000..d90bf82
--- /dev/null
+++ b/kernel/chr_drv/vt_kern.h
@@ -0,0 +1,8 @@
+#ifndef _VT_KERN_H
+#define _VT_KERN_H
+
+extern struct vt_info {
+	int mode;			/* KD_TEXT, ... */
+} vt_info[MAX_CONSOLES];
+
+#endif /* _VT_KERN_H */
diff --git a/kernel/exit.c b/kernel/exit.c
index 50f6146..5253ab2 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -287,8 +287,10 @@
 	current->root = NULL;
 	iput(current->executable);
 	current->executable = NULL;
-	iput(current->library);
-	current->library = NULL;
+	for (i=0; i<current->numlibraries; i++) {
+		iput(current->libraries[i].library);
+		current->libraries[i].library = NULL;
+	}	
 	current->state = TASK_ZOMBIE;
 	current->exit_code = code;
 	current->rss = 0;
diff --git a/kernel/fork.c b/kernel/fork.c
index ad65fb1..89277ab 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -11,6 +11,7 @@
  * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
  */
 #include <errno.h>
+#include <stddef.h>
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -106,6 +107,12 @@
 	*p = *current;	/* NOTE! this doesn't copy the supervisor stack */
 	p->state = TASK_UNINTERRUPTIBLE;
 	p->pid = last_pid;
+	p->p_pptr = current;
+	p->p_cptr = NULL;
+	p->p_ysptr = NULL;
+	if (p->p_osptr = current->p_cptr)
+		p->p_osptr->p_ysptr = p;
+	current->p_cptr = p;
 	p->counter = p->priority;
 	p->signal = 0;
 	p->alarm = 0;
@@ -135,11 +142,19 @@
 	p->tss.fs = fs & 0xffff;
 	p->tss.gs = gs & 0xffff;
 	p->tss.ldt = _LDT(nr);
-	p->tss.trace_bitmap = 0x80000000;
+	p->tss.trace_bitmap = offsetof(struct tss_struct,io_bitmap) << 16;
+	for (i = 0; i<IO_BITMAP_SIZE ; i++)
+		p->tss.io_bitmap[i] = ~0;
 	if (last_task_used_math == current)
 		__asm__("clts ; fnsave %0 ; frstor %0"::"m" (p->tss.i387));
 	if (copy_mem(nr,p)) {
 		task[nr] = NULL;
+		if (p->p_pptr->p_cptr == p)
+			p->p_pptr->p_cptr = p->p_osptr;
+		if (p->p_osptr)
+			p->p_osptr->p_ysptr = p->p_ysptr;
+		if (p->p_ysptr)
+			p->p_ysptr->p_osptr = p->p_osptr;
 		free_page((long) p);
 		return -EAGAIN;
 	}
@@ -152,17 +167,11 @@
 		current->root->i_count++;
 	if (current->executable)
 		current->executable->i_count++;
-	if (current->library)
-		current->library->i_count++;
+	for (i=0; i < current->numlibraries ; i++)
+		if (current->libraries[i].library)
+			current->libraries[i].library->i_count++;
 	set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
 	set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
-	p->p_pptr = current;
-	p->p_cptr = 0;
-	p->p_ysptr = 0;
-	p->p_osptr = current->p_cptr;
-	if (p->p_osptr)
-		p->p_osptr->p_ysptr = p;
-	current->p_cptr = p;
 	p->state = TASK_RUNNING;	/* do this last, just in case */
 	return p->pid;
 }
diff --git a/kernel/ioport.c b/kernel/ioport.c
new file mode 100644
index 0000000..cdca95a
--- /dev/null
+++ b/kernel/ioport.c
@@ -0,0 +1,94 @@
+/*
+ *	linux/kernel/ioport.c
+ *
+ * This contains the io-permission bitmap code - written by obz, with changes
+ * by Linus.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+
+#include <sys/types.h>
+#include <errno.h>
+
+#define _IODEBUG
+
+#ifdef IODEBUG
+static char * ios(unsigned long l)
+{
+	static char str[33] = { '\0' };
+	int i;
+	unsigned long mask;
+
+	for (i = 0, mask = 0x80000000; i < 32; ++i, mask >>= 1)
+		str[i] = (l & mask) ? '1' : '0';
+	return str;
+}
+
+static void dump_io_bitmap(void)
+{
+	int i, j;
+	int numl = sizeof(current->tss.io_bitmap) >> 2;
+
+	for (i = j = 0; j < numl; ++i)
+	{
+		printk("%4d [%3x]: ", 64*i, 64*i);
+		printk("%s ", ios(current->tss.io_bitmap[j++]));
+		if (j < numl)
+			printk("%s", ios(current->tss.io_bitmap[j++]));
+		printk("\n");
+	}
+}
+#endif
+
+/*
+ * this changes the io permissions bitmap in the current task.
+ */
+int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
+{
+	unsigned long froml, lindex, tnum, numl, rindex, mask;
+	unsigned long *iop;
+
+	froml = from >> 5;
+	lindex = from & 0x1f;
+	tnum = lindex + num;
+	numl = (tnum + 0x1f) >> 5;
+	rindex = tnum & 0x1f;
+
+	if (!suser())
+		return -EPERM;
+	if (froml * 32 + tnum > sizeof(current->tss.io_bitmap) * 8 - 8)
+		return -EINVAL;
+
+#ifdef IODEBUG
+	printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off"));
+#endif
+
+	if (numl) {
+		iop = (unsigned long *)current->tss.io_bitmap + froml;
+		if (lindex != 0) {
+			mask = (~0 << lindex);
+			if (--numl == 0 && rindex)
+				mask &= ~(~0 << rindex);
+			if (turn_on)
+				*iop++ &= ~mask;
+			else
+				*iop++ |= mask;
+		}
+		if (numl) {
+			if (rindex)
+				--numl;
+			mask = (turn_on ? 0 : ~0);
+			while (numl--)
+				*iop++ = mask;
+			if (numl && rindex) {
+				mask = ~(~0 << rindex);
+				if (turn_on)
+					*iop++ &= ~mask;
+				else
+					*iop++ |= mask;
+			}
+		}
+	}
+	return 0;
+}
diff --git a/kernel/math/Makefile b/kernel/math/Makefile
index 3c06183..79e3276 100644
--- a/kernel/math/Makefile
+++ b/kernel/math/Makefile
@@ -40,51 +40,46 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-add.s add.o : add.c ../../include/linux/math_emu.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/types.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+add.s add.o : add.c ../../include/linux/math_emu.h ../../include/linux/sched.h ../../include/linux/head.h \
+  ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
   ../../include/sys/resource.h 
-compare.s compare.o : compare.c ../../include/linux/math_emu.h \
-  ../../include/linux/sched.h ../../include/linux/head.h \
-  ../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+compare.s compare.o : compare.c ../../include/linux/math_emu.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
   ../../include/sys/resource.h 
-convert.s convert.o : convert.c ../../include/linux/math_emu.h \
-  ../../include/linux/sched.h ../../include/linux/head.h \
-  ../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+convert.s convert.o : convert.c ../../include/linux/math_emu.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
   ../../include/sys/resource.h 
-div.s div.o : div.c ../../include/linux/math_emu.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/types.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+div.s div.o : div.c ../../include/linux/math_emu.h ../../include/linux/sched.h ../../include/linux/head.h \
+  ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
   ../../include/sys/resource.h 
-ea.s ea.o : ea.c ../../include/stddef.h ../../include/linux/math_emu.h \
-  ../../include/linux/sched.h ../../include/linux/head.h \
-  ../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+ea.s ea.o : ea.c ../../include/stddef.h ../../include/linux/math_emu.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
   ../../include/sys/resource.h ../../include/asm/segment.h 
-error.s error.o : error.c ../../include/signal.h ../../include/sys/types.h \
-  ../../include/linux/sched.h ../../include/linux/head.h \
-  ../../include/linux/fs.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/sys/param.h \
-  ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h 
-get_put.s get_put.o : get_put.c ../../include/signal.h ../../include/sys/types.h \
-  ../../include/linux/math_emu.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/linux/mm.h ../../include/linux/kernel.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
-  ../../include/sys/resource.h ../../include/asm/segment.h 
-emulate.s emulate.o : emulate.c ../../include/linux/config.h 
-mul.s mul.o : mul.c ../../include/linux/math_emu.h ../../include/linux/sched.h \
-  ../../include/linux/head.h ../../include/linux/fs.h \
-  ../../include/sys/types.h ../../include/linux/mm.h \
-  ../../include/linux/kernel.h ../../include/signal.h \
-  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
+emulate.s emulate.o : emulate.c ../../include/signal.h ../../include/sys/types.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h 
+error.s error.o : error.c ../../include/signal.h ../../include/sys/types.h ../../include/linux/sched.h \
+  ../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h 
+get_put.s get_put.o : get_put.c ../../include/signal.h ../../include/sys/types.h ../../include/linux/math_emu.h \
+  ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
+  ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
+  ../../include/asm/segment.h 
+mul.s mul.o : mul.c ../../include/linux/math_emu.h ../../include/linux/sched.h ../../include/linux/head.h \
+  ../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
+  ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
+  ../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
   ../../include/sys/resource.h 
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 051241d..4602fc2 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -219,19 +219,11 @@
 	return 0;
 }
 
-/* Perform ptrace(request, pid, addr, data) syscall */
-int sys_ptrace(unsigned long *buffer)
+int sys_ptrace(long request, long pid, long addr, long data)
 {
-	long request, pid, data;
-	long addr;
 	struct task_struct *child;
 	int childno;
 
-	request = get_fs_long(buffer++);
-	pid = get_fs_long(buffer++);
-	addr = get_fs_long(buffer++); /* assume long = void * */
-	data = get_fs_long(buffer++);
-
 	if (request == 0) {
 		/* set the ptrace bit in the proccess flags. */
 		current->flags |= PF_PTRACED;
diff --git a/kernel/sched.c b/kernel/sched.c
index 3c274e6..098d096 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -46,21 +46,12 @@
 
 void show_state(void)
 {
-	static int lock = 0;
 	int i;
 
-	cli();
-	if (lock) {
-		sti();
-		return;
-	}
-	lock = 1;
-	sti();
 	printk("\rTask-info:\n\r");
 	for (i=0 ; i<NR_TASKS ; i++)
 		if (task[i])
 			show_task(i,task[i]);
-	lock = 0;
 }
 
 #define LATCH (1193180/HZ)
diff --git a/kernel/sys.c b/kernel/sys.c
index 4dd1059..a919028 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -15,7 +15,7 @@
 #include <sys/utsname.h>
 #include <sys/param.h>
 #include <sys/resource.h>
-#include <string.h>
+#include <linux/string.h>
 
 /*
  * this indicates wether you can reboot with ctrl-alt-del: the deault is yes
@@ -30,6 +30,21 @@
 
 extern int session_of_pgrp(int pgrp);
 
+int sys_getpriority()
+{
+	return -ENOSYS;
+}
+
+int sys_setpriority()
+{
+	return -ENOSYS;
+}
+
+int sys_profil()
+{
+	return -ENOSYS;
+}
+
 int sys_ftime()
 {
 	return -ENOSYS;
@@ -378,7 +393,8 @@
 {
 	int i;
 
-	if (!name) return -ERROR;
+	if (!name)
+		return -EINVAL;
 	verify_area(name,sizeof *name);
 	for(i=0;i<sizeof *name;i++)
 		put_fs_byte(((char *) &thisname)[i],i+(char *) name);
diff --git a/kernel/sys_call.S b/kernel/sys_call.S
new file mode 100644
index 0000000..e6f7766
--- /dev/null
+++ b/kernel/sys_call.S
@@ -0,0 +1,369 @@
+/*
+ *  linux/kernel/sys_call.S
+ *
+ *  (C) 1991  Linus Torvalds
+ */
+
+/*
+ * sys_call.S  contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all interrupts
+ * and faults that can result in a task-switch.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ * Stack layout in 'ret_from_system_call':
+ * 	ptrace needs to have all regs on the stack.
+ *	if the order here is changed, it needs to be 
+ *	updated in fork.c:copy_process, signal.c:do_signal,
+ *	ptrace.c and ptrace.h
+ *
+ *	 0(%esp) - %ebx
+ *	 4(%esp) - %ecx
+ *	 8(%esp) - %edx
+ *       C(%esp) - %esi
+ *	10(%esp) - %edi
+ *	14(%esp) - %ebp
+ *	18(%esp) - %eax
+ *	1C(%esp) - %ds
+ *	20(%esp) - %es
+ *      24(%esp) - %fs
+ *	28(%esp) - %gs
+ *	2C(%esp) - orig_eax
+ *	30(%esp) - %eip
+ *	34(%esp) - %cs
+ *	38(%esp) - %eflags
+ *	3C(%esp) - %oldesp
+ *	40(%esp) - %oldss
+ */
+
+SIG_CHLD	= 17
+
+EBX		= 0x00
+ECX		= 0x04
+EDX		= 0x08
+ESI		= 0x0C
+EDI		= 0x10
+EBP		= 0x14
+EAX		= 0x18
+DS		= 0x1C
+ES		= 0x20
+FS		= 0x24
+GS		= 0x28
+ORIG_EAX	= 0x2C
+EIP		= 0x30
+CS		= 0x34
+EFLAGS		= 0x38
+OLDESP		= 0x3C
+OLDSS		= 0x40
+
+/*
+ * these are offsets into the task-struct.
+ */
+state		= 0
+counter		= 4
+priority	= 8
+signal		= 12
+sigaction	= 16		# MUST be 16 (=len of sigaction)
+blocked		= (33*16)
+
+/*
+ * offsets within sigaction
+ */
+sa_handler	= 0
+sa_mask		= 4
+sa_flags	= 8
+sa_restorer	= 12
+
+ENOSYS = 38
+
+/*
+ * Ok, I get parallel printer interrupts while using the floppy for some
+ * strange reason. Urgel. Now I just ignore them.
+ */
+.globl _system_call,_timer_interrupt,_sys_execve
+.globl _device_not_available, _coprocessor_error
+.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
+.globl _double_fault,_coprocessor_segment_overrun
+.globl _invalid_TSS,_segment_not_present,_stack_segment
+.globl _general_protection,_irq13,_reserved
+.globl _alignment_check,_page_fault
+.globl _keyboard_interrupt
+
+#define SAVE_ALL \
+	cld; \
+	push %gs; \
+	push %fs; \
+	push %es; \
+	push %ds; \
+	pushl %eax; \
+	pushl %ebp; \
+	pushl %edi; \
+	pushl %esi; \
+	pushl %edx; \
+	pushl %ecx; \
+	pushl %ebx; \
+	movl $0x10,%edx; \
+	mov %dx,%ds; \
+	mov %dx,%es; \
+	movl $0x17,%edx; \
+	mov %dx,%fs
+
+#define ACK_FIRST(mask) \
+	inb $0x21,%al; \
+	jmp 1f; \
+1:	jmp 1f; \
+1:	orb $(mask),%al; \
+	outb %al,$0x21; \
+	jmp 1f; \
+1:	jmp 1f; \
+1:	movb $0x20,%al; \
+	outb %al,$0x20
+
+#define ACK_SECOND(mask) \
+	inb $0xA1,%al; \
+	jmp 1f; \
+1:	jmp 1f; \
+1:	orb $mask,%al; \
+	outb %al,$0xA1; \
+	jmp 1f; \
+1:	jmp 1f; \
+1:	movb $0x20,%al; \
+	outb %al,$0x20
+	jmp 1f; \
+1:	jmp 1f; \
+1:	outb %al,$0xA0
+
+#define UNBLK_FIRST(mask) \
+	inb $0x21,%al; \
+	jmp 1f; \
+1:	jmp 1f; \
+1:	andb $~(mask),%al; \
+	outb %al,$0x21
+
+#define UNBLK_SECOND(mask) \
+	inb $0xA1,%al; \
+	jmp 1f; \
+1:	jmp 1f; \
+1:	andb $~(mask),%al; \
+	outb %al,$0xA1
+
+.align 2
+bad_sys_call:
+	movl $-ENOSYS,EAX(%esp)
+	jmp ret_from_sys_call
+.align 2
+reschedule:
+	pushl $ret_from_sys_call
+	jmp _schedule
+.align 2
+_system_call:
+	pushl %eax		# save orig_eax
+	SAVE_ALL
+	cmpl _NR_syscalls,%eax
+	jae bad_sys_call
+	call _sys_call_table(,%eax,4)
+	movl %eax,EAX(%esp)		# save the return value
+ret_from_sys_call:
+	cmpw $0x0f,CS(%esp)		# was old code segment supervisor ?
+	jne 2f
+	cmpw $0x17,OLDSS(%esp)		# was stack segment = 0x17 ?
+	jne 2f
+1:	movl _current,%eax
+	cmpl _task,%eax			# task[0] cannot have signals
+	je 2f
+	cmpl $0,state(%eax)		# state
+	jne reschedule
+	cmpl $0,counter(%eax)		# counter
+	je reschedule
+	movl signal(%eax),%ebx
+	movl blocked(%eax),%ecx
+	notl %ecx
+	andl %ebx,%ecx
+	bsfl %ecx,%ecx
+	je 2f
+	btrl %ecx,%ebx
+	movl %ebx,signal(%eax)
+	incl %ecx
+	pushl %ecx
+	call _do_signal
+	popl %ecx
+	testl %eax, %eax
+	jne 1b			# see if we need to switch tasks, or do more signals
+2:	popl %ebx
+	popl %ecx
+	popl %edx
+	popl %esi
+	popl %edi
+	popl %ebp
+	popl %eax
+	pop %ds
+	pop %es
+	pop %fs
+	pop %gs
+	addl $4,%esp 		# skip the orig_eax
+	iret
+
+.align 2
+_irq13:
+	pushl %eax
+	xorb %al,%al
+	outb %al,$0xF0
+	movb $0x20,%al
+	outb %al,$0x20
+	jmp 1f
+1:	jmp 1f
+1:	outb %al,$0xA0
+	popl %eax
+_coprocessor_error:
+	pushl $-1		# mark this as an int. 
+	SAVE_ALL
+	pushl $ret_from_sys_call
+	jmp _math_error
+
+.align 2
+_device_not_available:
+	pushl $-1		# mark this as an int
+	SAVE_ALL
+	pushl $ret_from_sys_call
+	clts				# clear TS so that we can use math
+	movl %cr0,%eax
+	testl $0x4,%eax			# EM (math emulation bit)
+	je _math_state_restore
+	pushl $0		# temporary storage for ORIG_EIP
+	call _math_emulate
+	addl $4,%esp
+	ret
+
+.align 2
+_keyboard_interrupt:
+	pushl $-1
+	SAVE_ALL
+	ACK_FIRST(2)
+	sti
+	call _do_keyboard
+	cli
+	UNBLK_FIRST(2)
+	jmp ret_from_sys_call
+
+.align 2
+_timer_interrupt:
+	pushl $-1		# mark this as an int
+	SAVE_ALL
+	incl _jiffies
+	movb $0x20,%al		# EOI to interrupt controller #1
+	outb %al,$0x20
+	movl CS(%esp),%eax
+	andl $3,%eax		# %eax is CPL (0 or 3, 0=supervisor)
+	pushl %eax
+	call _do_timer		# 'do_timer(long CPL)' does everything from
+	addl $4,%esp		# task switching to accounting ...
+	jmp ret_from_sys_call
+
+.align 2
+_sys_execve:
+	lea (EIP+4)(%esp),%eax  # don't forget about the return address.
+	pushl %eax
+	call _do_execve
+	addl $4,%esp
+	ret
+
+_divide_error:
+	pushl $0 		# no error code
+	pushl $_do_divide_error
+error_code:
+	push %fs
+	push %es
+	push %ds
+	pushl %eax
+	pushl %ebp
+	pushl %edi
+	pushl %esi
+	pushl %edx
+	pushl %ecx
+	pushl %ebx
+	cld
+	movl $-1, %eax
+	xchgl %eax, ORIG_EAX(%esp)	# orig_eax (get the error code. )
+	xorl %ebx,%ebx			# zero ebx
+	mov %gs,%bx			# get the lower order bits of gs
+	xchgl %ebx, GS(%esp)		# get the address and save gs.
+	pushl %eax			# push the error code
+	lea 52(%esp),%edx
+	pushl %edx
+	movl $0x10,%edx
+	mov %dx,%ds
+	mov %dx,%es
+	movl $0x17,%edx
+	mov %dx,%fs
+	call *%ebx
+	addl $8,%esp
+	jmp ret_from_sys_call
+
+_debug:
+	pushl $0
+	pushl $_do_int3		# _do_debug
+	jmp error_code
+
+_nmi:
+	pushl $0
+	pushl $_do_nmi
+	jmp error_code
+
+_int3:
+	pushl $0
+	pushl $_do_int3
+	jmp error_code
+
+_overflow:
+	pushl $0
+	pushl $_do_overflow
+	jmp error_code
+
+_bounds:
+	pushl $0
+	pushl $_do_bounds
+	jmp error_code
+
+_invalid_op:
+	pushl $0
+	pushl $_do_invalid_op
+	jmp error_code
+
+_coprocessor_segment_overrun:
+	pushl $0
+	pushl $_do_coprocessor_segment_overrun
+	jmp error_code
+
+_reserved:
+	pushl $0
+	pushl $_do_reserved
+	jmp error_code
+
+_double_fault:
+	pushl $_do_double_fault
+	jmp error_code
+
+_invalid_TSS:
+	pushl $_do_invalid_TSS
+	jmp error_code
+
+_segment_not_present:
+	pushl $_do_segment_not_present
+	jmp error_code
+
+_stack_segment:
+	pushl $_do_stack_segment
+	jmp error_code
+
+_general_protection:
+	pushl $_do_general_protection
+	jmp error_code
+
+_alignment_check:
+	pushl $_do_alignment_check
+	jmp error_code
+
+_page_fault:
+	pushl $_do_page_fault
+	jmp error_code
diff --git a/kernel/sys_call.s b/kernel/sys_call.s
deleted file mode 100644
index 8d7a982..0000000
--- a/kernel/sys_call.s
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- *  linux/kernel/system_call.s
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- *  system_call.s  contains the system-call low-level handling routines.
- * This also contains the timer-interrupt handler, as some of the code is
- * the same. The hd- and flopppy-interrupts are also here.
- *
- * NOTE: This code handles signal-recognition, which happens every time
- * after a timer-interrupt and after each system call. Ordinary interrupts
- * don't handle signal-recognition, as that would clutter them up totally
- * unnecessarily.
- *
- * Stack layout in 'ret_from_system_call':
- * 	ptrace needs to have all regs on the stack.
- *	if the order here is changed, it needs to be 
- *	updated in fork.c:copy_process, signal.c:do_signal,
- *	ptrace.c ptrace.h
- *
- *	 0(%esp) - %ebx
- *	 4(%esp) - %ecx
- *	 8(%esp) - %edx
- *       C(%esp) - %esi
- *	10(%esp) - %edi
- *	14(%esp) - %ebp
- *	18(%esp) - %eax
- *	1C(%esp) - %ds
- *	20(%esp) - %es
- *      24(%esp) - %fs
- *	28(%esp) - %gs
- *	2C(%esp) - orig_eax
- *	30(%esp) - %eip
- *	34(%esp) - %cs
- *	38(%esp) - %eflags
- *	3C(%esp) - %oldesp
- *	40(%esp) - %oldss
- */
-
-SIG_CHLD	= 17
-
-EBX		= 0x00
-ECX		= 0x04
-EDX		= 0x08
-ESI		= 0x0C
-EDI		= 0x10
-EBP		= 0x14
-EAX		= 0x18
-DS		= 0x1C
-ES		= 0x20
-FS		= 0x24
-GS		= 0x28
-ORIG_EAX	= 0x2C
-EIP		= 0x30
-CS		= 0x34
-EFLAGS		= 0x38
-OLDESP		= 0x3C
-OLDSS		= 0x40
-
-state	= 0		# these are offsets into the task-struct.
-counter	= 4
-priority = 8
-signal	= 12
-sigaction = 16		# MUST be 16 (=len of sigaction)
-blocked = (33*16)
-
-# offsets within sigaction
-sa_handler = 0
-sa_mask = 4
-sa_flags = 8
-sa_restorer = 12
-
-nr_system_calls = 82
-
-ENOSYS = 38
-
-/*
- * Ok, I get parallel printer interrupts while using the floppy for some
- * strange reason. Urgel. Now I just ignore them.
- */
-.globl _system_call,_timer_interrupt,_sys_execve
-.globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
-.globl _device_not_available, _coprocessor_error
-
-.align 2
-bad_sys_call:
-	pushl $-ENOSYS
-	jmp ret_from_sys_call
-.align 2
-reschedule:
-	pushl $ret_from_sys_call
-	jmp _schedule
-.align 2
-_system_call:
-	cld
-	pushl %eax		# save orig_eax
-	push %gs
-	push %fs
-	push %es
-	push %ds
-	pushl %eax		# save eax.  The return value will be put here.
-	pushl %ebp
-	pushl %edi
-	pushl %esi
-	pushl %edx		
-	pushl %ecx		# push %ebx,%ecx,%edx as parameters
-	pushl %ebx		# to the system call
-	movl $0x10,%edx		# set up ds,es to kernel space
-	mov %dx,%ds
-	mov %dx,%es
-	movl $0x17,%edx		# fs points to local data space
-	mov %dx,%fs
-	cmpl _NR_syscalls,%eax
-	jae bad_sys_call
-	call _sys_call_table(,%eax,4)
-	movl %eax,EAX(%esp)		# save the return value
-2:	movl _current,%eax
-	cmpl $0,state(%eax)		# state
-	jne reschedule
-	cmpl $0,counter(%eax)		# counter
-	je reschedule
-ret_from_sys_call:
-	movl _current,%eax
-	cmpl _task,%eax			# task[0] cannot have signals
-	je 3f
-	cmpw $0x0f,CS(%esp)		# was old code segment supervisor ?
-	jne 3f
-	cmpw $0x17,OLDSS(%esp)		# was stack segment = 0x17 ?
-	jne 3f
-	movl signal(%eax),%ebx
-	movl blocked(%eax),%ecx
-	notl %ecx
-	andl %ebx,%ecx
-	bsfl %ecx,%ecx
-	je 3f
-	btrl %ecx,%ebx
-	movl %ebx,signal(%eax)
-	incl %ecx
-	pushl %ecx
-	call _do_signal
-	popl %ecx
-	testl %eax, %eax
-	jne 2b		# see if we need to switch tasks, or do more signals
-3:
-	popl %ebx
-	popl %ecx
-	popl %edx
-	popl %esi
-	popl %edi
-	popl %ebp
-	popl %eax
-	pop %ds
-	pop %es
-	pop %fs
-	pop %gs
-	addl $4,%esp 		# skip the orig_eax
-	iret
-
-.align 2
-_coprocessor_error:
-	cld
-	pushl $-1		# mark this as an int. 
-	push %gs
-	push %fs
-	push %es
-	push %ds
-	pushl %eax		# save eax.
-	pushl %ebp
-	pushl %edi
-	pushl %esi
-	pushl %edx
-	pushl %ecx
-	pushl %ebx
-	movl $0x10,%eax
-	mov %ax,%ds
-	mov %ax,%es
-	movl $0x17,%eax
-	mov %ax,%fs
-	pushl $ret_from_sys_call
-	jmp _math_error
-
-.align 2
-_device_not_available:
-	cld
-	pushl $-1		# mark this as an int
-	push %gs
-	push %fs
-	push %es
-	push %ds
-	pushl %eax		
-	pushl %ebp
-	pushl %edi
-	pushl %esi
-	pushl %edx
-	pushl %ecx
-	pushl %ebx
-	movl $0x10,%eax
-	mov %ax,%ds
-	mov %ax,%es
-	movl $0x17,%eax
-	mov %ax,%fs
-	pushl $ret_from_sys_call
-	clts				# clear TS so that we can use math
-	movl %cr0,%eax
-	testl $0x4,%eax			# EM (math emulation bit)
-	je _math_state_restore
-	pushl $0		# temporary storage for ORIG_EIP
-	call _math_emulate
-	addl $4,%esp
-	ret
-
-.align 2
-_timer_interrupt:
-	cld
-	pushl $-1		# mark this as an int
-	push %gs
-	push %fs
-	push %es
-	push %ds
-	pushl %eax
-	pushl %ebp
-	pushl %edi
-	pushl %esi
-	pushl %edx		
-	pushl %ecx
-	pushl %ebx
-	movl $0x10,%eax
-	mov %ax,%ds
-	mov %ax,%es
-	movl $0x17,%eax
-	mov %ax,%fs
-	incl _jiffies
-	movb $0x20,%al		# EOI to interrupt controller #1
-	outb %al,$0x20
-	movl CS(%esp),%eax
-	andl $3,%eax		# %eax is CPL (0 or 3, 0=supervisor)
-	pushl %eax
-	call _do_timer		# 'do_timer(long CPL)' does everything from
-	addl $4,%esp		# task switching to accounting ...
-	jmp ret_from_sys_call
-
-.align 2
-_sys_execve:
-	lea (EIP+4)(%esp),%eax  # don't forget about the return address.
-	pushl %eax
-	call _do_execve
-	addl $4,%esp
-	ret
-
-_hd_interrupt:
-	cld
-	pushl %eax
-	pushl %ecx
-	pushl %edx
-	push %ds
-	push %es
-	push %fs
-	movl $0x10,%eax
-	mov %ax,%ds
-	mov %ax,%es
-	movl $0x17,%eax
-	mov %ax,%fs
-	movb $0x20,%al
-	outb %al,$0xA0		# EOI to interrupt controller #1
-	jmp 1f			# give port chance to breathe
-1:	jmp 1f
-1:	outb %al,$0x20
-	andl $0xfffeffff,_timer_active
-	xorl %edx,%edx
-	xchgl _do_hd,%edx
-	testl %edx,%edx
-	jne 1f
-	movl $_unexpected_hd_interrupt,%edx
-1:	call *%edx		# "interesting" way of handling intr.
-	pop %fs
-	pop %es
-	pop %ds
-	popl %edx
-	popl %ecx
-	popl %eax
-	iret
-
-_floppy_interrupt:
-	cld
-	pushl %eax
-	pushl %ecx
-	pushl %edx
-	push %ds
-	push %es
-	push %fs
-	movl $0x10,%eax
-	mov %ax,%ds
-	mov %ax,%es
-	movl $0x17,%eax
-	mov %ax,%fs
-	movb $0x20,%al
-	outb %al,$0x20		# EOI to interrupt controller #1
-	xorl %eax,%eax
-	xchgl _do_floppy,%eax
-	testl %eax,%eax
-	jne 1f
-	movl $_unexpected_floppy_interrupt,%eax
-1:	call *%eax		# "interesting" way of handling intr.
-	pop %fs
-	pop %es
-	pop %ds
-	popl %edx
-	popl %ecx
-	popl %eax
-	iret
-
-_parallel_interrupt:
-	cld
-	pushl %eax
-	movb $0x20,%al
-	outb %al,$0x20
-	popl %eax
-	iret
diff --git a/kernel/traps.c b/kernel/traps.c
index 797bb79..89b65f3 100644
--- a/kernel/traps.c
+++ b/kernel/traps.c
@@ -10,7 +10,7 @@
  * to mainly kill the offending process (probably by giving it a signal,
  * but possibly by killing it outright if necessary).
  */
-#include <string.h>
+#include <linux/string.h>
 
 #include <linux/head.h>
 #include <linux/sched.h>
diff --git a/kernel/vsprintf.c b/kernel/vsprintf.c
index 06b910e..8ce9873 100644
--- a/kernel/vsprintf.c
+++ b/kernel/vsprintf.c
@@ -10,7 +10,7 @@
  */
 
 #include <stdarg.h>
-#include <string.h>
+#include <linux/string.h>
 
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)	((c) >= '0' && (c) <= '9')
diff --git a/lib/Makefile b/lib/Makefile
index 83a543f..78afc1e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -11,7 +11,7 @@
 LD	=ld
 LDFLAGS	=-s -x
 CC	=gcc -nostdinc -I../include
-CPP	=cpp -nostdinc -I../include
+CPP	=gcc -E -nostdinc -I../include
 
 .c.s:
 	$(CC) $(CFLAGS) \
@@ -40,32 +40,33 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-_exit.s _exit.o : _exit.c ../include/unistd.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/utime.h 
-close.s close.o : close.c ../include/unistd.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/utime.h 
-ctype.s ctype.o : ctype.c ../include/ctype.h 
-dup.s dup.o : dup.c ../include/unistd.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/utime.h 
+_exit.s _exit.o : _exit.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+  ../include/sys/param.h ../include/sys/resource.h ../include/utime.h 
+close.s close.o : close.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+  ../include/sys/param.h ../include/sys/resource.h ../include/utime.h 
+ctype.s ctype.o : ctype.c ../include/linux/ctype.h 
+dup.s dup.o : dup.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+  ../include/sys/param.h ../include/sys/resource.h ../include/utime.h 
 errno.s errno.o : errno.c 
-execve.s execve.o : execve.c ../include/unistd.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/utime.h 
-malloc.s malloc.o : malloc.c ../include/linux/kernel.h ../include/linux/mm.h \
+execve.s execve.o : execve.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+  ../include/sys/param.h ../include/sys/resource.h ../include/utime.h 
+malloc.s malloc.o : malloc.c ../include/linux/kernel.h ../include/linux/mm.h ../include/linux/fs.h \
+  ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/signal.h \
   ../include/asm/system.h 
-open.s open.o : open.c ../include/unistd.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/utime.h ../include/stdarg.h 
-setsid.s setsid.o : setsid.c ../include/unistd.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/utime.h 
-string.s string.o : string.c ../include/string.h 
-wait.s wait.o : wait.c ../include/unistd.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/utime.h ../include/sys/wait.h 
-write.s write.o : write.c ../include/unistd.h ../include/sys/stat.h \
-  ../include/sys/types.h ../include/sys/times.h ../include/sys/utsname.h \
-  ../include/utime.h 
+open.s open.o : open.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+  ../include/sys/param.h ../include/sys/resource.h ../include/utime.h ../include/stdarg.h 
+setsid.s setsid.o : setsid.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+  ../include/sys/param.h ../include/sys/resource.h ../include/utime.h 
+string.s string.o : string.c ../include/linux/string.h 
+wait.s wait.o : wait.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+  ../include/sys/param.h ../include/sys/resource.h ../include/utime.h ../include/sys/wait.h 
+write.s write.o : write.c ../include/unistd.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/times.h ../include/sys/utsname.h \
+  ../include/sys/param.h ../include/sys/resource.h ../include/utime.h 
diff --git a/lib/ctype.c b/lib/ctype.c
index 877e629..f1103a9 100644
--- a/lib/ctype.c
+++ b/lib/ctype.c
@@ -4,7 +4,7 @@
  *  (C) 1991  Linus Torvalds
  */
 
-#include <ctype.h>
+#include <linux/ctype.h>
 
 char _ctmp;
 unsigned char _ctype[] = {0x00,			/* EOF */
diff --git a/lib/string.c b/lib/string.c
index 1182e63..ebbdfff 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -11,4 +11,4 @@
 #define extern
 #define inline
 #define __LIBRARY__
-#include <string.h>
+#include <linux/string.h>
diff --git a/mm/Makefile b/mm/Makefile
index 27b2f4e..c60e25b 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -22,7 +22,7 @@
 	$(CC) $(CFLAGS) \
 	-S -o $*.s $<
 
-OBJS	= memory.o swap.o
+OBJS	= memory.o swap.o mmap.o
 
 mm.o: $(OBJS)
 	$(LD) -r -o mm.o $(OBJS)
@@ -37,14 +37,17 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-memory.o : memory.c ../include/signal.h ../include/sys/types.h \
-  ../include/asm/system.h ../include/linux/sched.h ../include/linux/head.h \
-  ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h \
-  ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h \
+memory.o : memory.c ../include/signal.h ../include/sys/types.h ../include/asm/system.h \
+  ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
+  ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h \
   ../include/sys/time.h ../include/time.h ../include/sys/resource.h 
-swap.o : swap.c ../include/string.h ../include/errno.h \
-  ../include/linux/mm.h ../include/linux/fs.h ../include/sys/types.h \
-  ../include/sys/dirent.h ../include/limits.h ../include/linux/kernel.h \
-  ../include/signal.h ../include/sys/stat.h ../include/linux/sched.h \
-  ../include/linux/head.h ../include/sys/param.h ../include/sys/time.h \
-  ../include/time.h ../include/sys/resource.h 
+mmap.o : mmap.c ../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \
+  ../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
+  ../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/segment.h \
+  ../include/asm/system.h ../include/errno.h ../include/sys/mman.h 
+swap.o : swap.c ../include/errno.h ../include/sys/stat.h ../include/sys/types.h \
+  ../include/linux/mm.h ../include/linux/fs.h ../include/sys/dirent.h ../include/limits.h \
+  ../include/linux/kernel.h ../include/signal.h ../include/linux/string.h ../include/linux/sched.h \
+  ../include/linux/head.h ../include/sys/param.h ../include/sys/time.h ../include/time.h \
+  ../include/sys/resource.h 
diff --git a/mm/memory.c b/mm/memory.c
index 8e93a1b..866a5cb 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -186,6 +186,159 @@
 }
 
 /*
+ * a more complete version of free_page_tables which performs with page
+ * granularity.
+ */
+int
+unmap_page_range(unsigned long from, unsigned long size)
+{
+	unsigned long page, page_dir;
+	unsigned long *page_table, *dir;
+	unsigned long poff, pcnt, pc;
+
+	if (from & 0xfff)
+		panic("unmap_page_range called with wrong alignment");
+	if (!from)
+		panic("unmap_page_range trying to free swapper memory space");
+	size = (size + 0xfff) >> 12;
+	dir = (unsigned long *) ((from >> 20) & 0xffc); /* _pg_dir = 0 */
+	poff = (from >> 12) & 0x3ff;
+	if ((pcnt = 1024 - poff) > size)
+		pcnt = size;
+
+	for ( ; size > 0; ++dir, size -= pcnt,
+	     pcnt = (size > 1024 ? 1024 : size)) {
+		if (!(page_dir = *dir))	{
+			poff = 0;
+			continue;
+		}
+		if (!(page_dir & 1)) {
+			printk("unmap_page_range: bad page directory.");
+			continue;
+		}
+		page_table = (unsigned long *)(0xfffff000 & page_dir);
+		if (poff) {
+			page_table += poff;
+			poff = 0;
+		}
+		for (pc = pcnt; pc--; page_table++) {
+			if (page = *page_table) {
+				--current->rss;
+				*page_table = 0;
+				if (1 & page)
+					free_page(0xfffff000 & page);
+				else
+					swap_free(page >> 1);
+			}
+		}
+		if (pcnt == 1024) {
+			free_page(0xfffff000 & page_dir);
+			*dir = 0;
+		}
+	}
+	invalidate();
+	for (page = 0; page < CHECK_LAST_NR ; page++)
+		last_pages[page] = 0;
+	return 0;
+}
+
+/*
+ * maps a range of physical memory into the requested pages. the old
+ * mappings are removed. any references to nonexistent pages results
+ * in null mappings (currently treated as "copy-on-access")
+ *
+ * permiss is encoded as cxwr (copy,exec,write,read) where copy modifies
+ * the behavior of write to be copy-on-write.
+ *
+ * due to current limitations, we actually have the following
+ *		on		off
+ * read:	yes		yes
+ * write/copy:	yes/copy	copy/copy
+ * exec:	yes		yes
+ */
+int
+remap_page_range(unsigned long from, unsigned long to, unsigned long size,
+		 int permiss)
+{
+	unsigned long *page_table, *dir;
+	unsigned long poff, pcnt;
+
+	if ((from & 0xfff) || (to & 0xfff))
+		panic("remap_page_range called with wrong alignment");
+	dir = (unsigned long *) ((from >> 20) & 0xffc); /* _pg_dir = 0 */
+	size = (size + 0xfff) >> 12;
+	poff = (from >> 12) & 0x3ff;
+	if ((pcnt = 1024 - poff) > size)
+		pcnt = size;
+
+	while (size > 0) {
+		if (!(1 & *dir)) {
+			if (!(page_table = (unsigned long *)get_free_page())) {
+				invalidate();
+				return -1;
+			}
+			*dir++ = ((unsigned long) page_table) | 7;
+		}
+		else
+			page_table = (unsigned long *)(0xfffff000 & *dir++);
+		if (poff) {
+			page_table += poff;
+			poff = 0;
+		}
+
+		for (size -= pcnt; pcnt-- ;) {
+			int mask;
+
+			mask = 4;
+			if (permiss & 1)
+				mask |= 1;
+			if (permiss & 2) {
+				if (permiss & 8)
+					mask |= 1;
+				else
+					mask |= 3;
+			}
+			if (permiss & 4)
+				mask |= 1;
+
+			if (*page_table) {
+				--current->rss;
+				if (1 & *page_table)
+					free_page(0xfffff000 & *page_table);
+				else
+					swap_free(*page_table >> 1);
+			}
+
+			/*
+			 * i'm not sure of the second cond here. should we
+			 * report failure?
+			 * the first condition should return an invalid access
+			 * when the page is referenced. current assumptions
+			 * cause it to be treated as demand allocation.
+			 */
+			if (mask == 4 || to >= HIGH_MEMORY)
+				*page_table++ = 0;	/* not present */
+			else {
+				++current->rss;
+				*page_table++ = (to | mask);
+				if (to > LOW_MEM) {
+					unsigned long frame;
+					frame = to - LOW_MEM;
+					frame >>= 12;
+					mem_map[frame]++;
+				}
+			}
+			to += PAGE_SIZE;
+		}
+		pcnt = (size > 1024 ? 1024 : size);
+	}
+	invalidate();
+	for (to = 0; to < CHECK_LAST_NR ; to++)
+		last_pages[to] = 0;
+	return 0;
+}
+
+/*
  * This function puts a page in memory at the wanted address.
  * It returns the physical address of the page gotten, 0 if
  * out of memory (either when trying to access page-table or
@@ -410,6 +563,7 @@
 static int share_page(struct inode * inode, unsigned long address)
 {
 	struct task_struct ** p;
+	int i;
 
 	if (inode->i_count < 2 || !inode)
 		return 0;
@@ -422,7 +576,10 @@
 			if (inode != (*p)->executable)
 				continue;
 		} else {
-			if (inode != (*p)->library)
+			for (i=0; i < (*p)->numlibraries; i++)
+				if (inode == (*p)->libraries[i].library)
+					break;
+			if (i >= (*p)->numlibraries)
 				continue;
 		}
 		if (try_to_share(address,*p))
@@ -482,8 +639,18 @@
 	address &= 0xfffff000;
 	tmp = address - tsk->start_code;
 	if (tmp >= LIBRARY_OFFSET ) {
-		inode = tsk->library;
-		block = 1 + (tmp-LIBRARY_OFFSET) / BLOCK_SIZE;
+		inode = NULL;
+		block = 1;
+		i = tsk->numlibraries;
+		while (i-- > 0) {
+			if (tmp < (tsk->libraries[i].start +
+			   tsk->libraries[i].length)) {	
+				inode = tsk->libraries[i].library;
+				block = 1 + (tmp - tsk->libraries[i].start) / 
+					BLOCK_SIZE;
+				break;
+			}
+		}
 	} else if (tmp < tsk->end_data) {
 		inode = tsk->executable;
 		block = 1 + tmp / BLOCK_SIZE;
@@ -493,7 +660,7 @@
 	}
 	if (!inode) {
 		++tsk->min_flt;
-		if (tmp > tsk->brk && tsk == current && 
+		if (tmp < LIBRARY_OFFSET && tmp > tsk->brk && tsk == current && 
 			LIBRARY_OFFSET - tmp > tsk->rlim[RLIMIT_STACK].rlim_max)
 				do_exit(SIGSEGV);
 		get_empty_page(address);
@@ -546,15 +713,7 @@
 	int i,j,k,free=0,total=0;
 	int shared = 0;
 	unsigned long * pg_tbl;
-	static int lock = 0;
 
-	cli();
-	if (lock) {
-		sti();
-		return;
-	}
-	lock = 1;
-	sti();
 	printk("Mem-info:\n\r");
 	for(i=0 ; i<PAGING_PAGES ; i++) {
 		if (mem_map[i] == USED)
@@ -595,7 +754,6 @@
 		}
 	}
 	printk("Memory found: %d (%d)\n\r",free-shared,total);
-	lock = 0;
 }
 
 
diff --git a/mm/mmap.c b/mm/mmap.c
new file mode 100644
index 0000000..a8ea628
--- /dev/null
+++ b/mm/mmap.c
@@ -0,0 +1,196 @@
+/*
+ *	linux/mm/mmap.c
+ *
+ * Written by obz.
+ */
+#include <sys/stat.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+/*
+ * description of effects of mapping type and prot in current implementation.
+ * this is due to the current handling of page faults in memory.c. the expected
+ * behavior is in parens:
+ *
+ * map_type	prot
+ *		PROT_NONE	PROT_READ	PROT_WRITE	PROT_EXEC
+ * MAP_SHARED	r: (no) yes	r: (yes) yes	r: (no) yes	r: (no) no
+ *		w: (no) yes	w: (no) copy	w: (yes) yes	w: (no) no
+ *		x: (no) no	x: (no) no	x: (no) no	x: (yes) no
+ *		
+ * MAP_PRIVATE	r: (no) yes	r: (yes) yes	r: (no) yes	r: (no) no
+ *		w: (no) copy	w: (no) copy	w: (copy) copy	w: (no) no
+ *		x: (no) no	x: (no) no	x: (no) no	x: (yes) no
+ *
+ * the permissions are encoded as cxwr (copy,exec,write,read)
+ */
+#define MTYP(T) ((T) & MAP_TYPE)
+#define PREAD(T,P) (((P) & PROT_READ) ? 1 : 0)
+#define PWRITE(T,P) (((P) & PROT_WRITE) ? (MTYP(T) == MAP_SHARED ? 2 : 10) : 0)
+#define PEXEC(T,P) (((P) & PROT_EXEC) ? 4 : 0)
+#define PERMISS(T,P) (PREAD(T,P)|PWRITE(T,P)|PEXEC(T,P))
+
+#define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
+			  current->start_code + current->end_code)
+
+extern int remap_page_range(unsigned long from, unsigned long to,
+			    unsigned long size, int permiss);
+extern int unmap_page_range(unsigned long from, unsigned long size);
+
+static caddr_t
+mmap_chr(unsigned long addr, size_t len, int prot, int flags,
+	 struct inode *inode, unsigned long off)
+{
+	int major, minor;
+	extern unsigned long HIGH_MEMORY;
+
+	major = MAJOR(inode->i_rdev);
+	minor = MINOR(inode->i_rdev);
+
+	/*
+	 * for character devices, only /dev/mem may be mapped. when the
+	 * swapping code is modified to allow arbitrary sources of pages,
+	 * then we can open it up to regular files.
+	 */
+
+	if (major != 1 || minor != 1)
+		return (caddr_t)-ENODEV;
+
+	/*
+	 * we only allow mappings from address 0 to HIGH_MEMORY, since thats
+	 * the range of our memory [actually this is a lie. the buffer cache
+	 * and ramdisk occupy higher memory, but the paging stuff won't
+	 * let us map to it anyway, so we break it here].
+	 *
+	 * this call is very dangerous! because of the lack of adequate
+	 * tagging of frames, it is possible to mmap over a frame belonging
+	 * to another (innocent) process. with MAP_SHARED|MAP_WRITE, this
+	 * rogue process can trample over the other's data! we ignore this :{
+	 * for now, we hope people will malloc the required amount of space,
+	 * then mmap over it. the mm needs serious work before this can be
+	 * truly useful.
+	 */
+
+	if (len > HIGH_MEMORY || off > HIGH_MEMORY - len) /* avoid overflow */
+		return (caddr_t)-ENXIO;
+
+	if (remap_page_range(addr, off, len, PERMISS(flags, prot)))
+		return (caddr_t)-EAGAIN;
+	
+	return (caddr_t)addr;
+}
+
+caddr_t
+sys_mmap(unsigned long *buffer)
+{
+	unsigned long base, addr;
+	unsigned long len, limit, off;
+	int prot, flags, fd;
+	struct file *file;
+	struct inode *inode;
+
+	addr = (unsigned long)	get_fs_long(buffer);	/* user address space*/
+	len = (size_t)		get_fs_long(buffer+1);	/* nbytes of mapping */
+	prot = (int)		get_fs_long(buffer+2);	/* protection */
+	flags = (int)		get_fs_long(buffer+3);	/* mapping type */
+	fd = (int) 		get_fs_long(buffer+4);	/* object to map */
+	off = (unsigned long)	get_fs_long(buffer+5);	/* offset in object */
+
+	if (fd >= NR_OPEN || fd < 0 || !(file = current->filp[fd]))
+		return (caddr_t) -EBADF;
+	if (addr > TASK_SIZE || (addr+(unsigned long) len) > TASK_SIZE)
+		return (caddr_t) -EINVAL;
+	inode = file->f_inode;
+
+	/*
+	 * do simple checking here so the lower-level routines won't have
+	 * to. we assume access permissions have been handled by the open
+	 * of the memory object, so we don't do any here.
+	 */
+
+	switch (flags & MAP_TYPE) {
+	case MAP_SHARED:
+		if ((prot & PROT_WRITE) && !(file->f_mode & 2))
+			return (caddr_t)-EINVAL;
+		/* fall through */
+	case MAP_PRIVATE:
+		if (!(file->f_mode & 1))
+			return (caddr_t)-EINVAL;
+		break;
+
+	default:
+		return (caddr_t)-EINVAL;
+	}
+
+	/*
+	 * obtain the address to map to. we verify (or select) it and ensure
+	 * that it represents a valid section of the address space. we assume
+	 * that if PROT_EXEC is specified this should be in the code segment.
+	 */
+	if (prot & PROT_EXEC) {
+		base = get_base(current->ldt[1]);	/* cs */
+		limit = get_limit(0x0f);		/* cs limit */
+	} else {
+		base = get_base(current->ldt[2]);	/* ds */
+		limit = get_limit(0x17);		/* ds limit */
+	}
+
+	if (flags & MAP_FIXED) {
+		/*
+		 * if MAP_FIXED is specified, we have to map exactly at this
+		 * address. it must be page aligned and not ambiguous.
+		 */
+		if ((addr & 0xfff) || addr > 0x7fffffff || addr == 0 ||
+		    (off & 0xfff))
+			return (caddr_t)-EINVAL;
+		if (addr + len > limit)
+			return (caddr_t)-ENOMEM;
+	} else {
+		/*
+		 * we're given a hint as to where to put the address.
+		 * that we still need to search for a range of pages which
+		 * are not mapped and which won't impact the stack or data
+		 * segment.
+		 * in linux, we only have a code segment and data segment.
+		 * since data grows up and stack grows down, we're sort of
+		 * stuck. placing above the data will break malloc, below
+		 * the stack will cause stack overflow. because of this
+		 * we don't allow nonspecified mappings...
+		 */
+		return (caddr_t)-ENOMEM;
+	}
+
+	/*
+	 * determine the object being mapped and call the appropriate
+	 * specific mapper. the address has already been validated, but
+	 * not unmapped
+	 */
+	if (S_ISCHR(inode->i_mode))
+		addr = (unsigned long)mmap_chr(base + addr, len, prot, flags,
+					       inode, off);
+	else
+		addr = (unsigned long)-ENODEV;
+	if ((long)addr > 0)
+		addr -= base;
+
+	return (caddr_t)addr;
+}
+
+int sys_munmap(unsigned long addr, size_t len)
+{
+	unsigned long base, limit;
+
+	base = get_base(current->ldt[2]);	/* map into ds */
+	limit = get_limit(0x17);		/* ds limit */
+
+	if ((addr & 0xfff) || addr > 0x7fffffff || addr == 0 ||
+	    addr + len > limit)
+		return -EINVAL;
+	if (unmap_page_range(base + addr, len))
+		return -EAGAIN; /* should never happen */
+	return 0;
+}
diff --git a/mm/swap.c b/mm/swap.c
index 819bbe3..ba41399 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -9,11 +9,11 @@
  * Started 18.12.91
  */
 
-#include <string.h>
 #include <errno.h>
+#include <sys/stat.h>
 
 #include <linux/mm.h>
-#include <sys/stat.h>
+#include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/head.h>
 #include <linux/kernel.h>
@@ -149,6 +149,12 @@
 /*
  * Go through the page tables, searching for a user page that
  * we can swap out.
+ *
+ * Here it's easy to add a check for tasks that may not be swapped out:
+ * loadable device drivers or similar. Just add an entry to the task-struct
+ * and check it at the same time you check for the existence of the task.
+ * The code assumes tasks are page-table aligned, but so do other parts
+ * of the memory manager...
  */
 int swap_out(void)
 {
@@ -156,12 +162,18 @@
 	static int page_entry = -1;
 	int counter = VM_PAGES;
 	int pg_table;
+	struct task_struct * p;
 
 check_dir:
 	if (counter < 0)
 		goto no_swap;
 	if (dir_entry >= 1024)
 		dir_entry = FIRST_VM_PAGE>>10;
+	if (!(p = task[dir_entry >> 4])) {
+		counter -= 1024;
+		dir_entry++;
+		goto check_dir;
+	}
 	if (!(1 & (pg_table = pg_dir[dir_entry]))) {
 		if (pg_table) {
 			printk("bad page-table at pg_dir[%d]: %08x\n\r",
@@ -184,10 +196,7 @@
 		goto check_dir;
 	}
 	if (try_to_swap_out(page_entry + (unsigned long *) pg_table)) {
-		if (! task[dir_entry >> 4])
-			printk("swapping out page from non-existent task\n\r");
-		else
-			task[dir_entry >> 4]->rss--;
+		p->rss--;
 		return 1;
 	}
 	goto check_table;