summaryrefslogtreecommitdiff
path: root/libc/syscall
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-03-24 21:25:23 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:29:54 +0200
commitdcc973ea3e31710429858c99d4f040334ac67c06 (patch)
tree8883b902eb18eba489957b7f03caa491fd7992a7 /libc/syscall
parentfe22c37817ce338fbbc90b239320248c270957fa (diff)
downloaddev86-dcc973ea3e31710429858c99d4f040334ac67c06.tar.gz
Import Dev86-0.0.5.tar.gzv0.0.5
Diffstat (limited to 'libc/syscall')
-rw-r--r--libc/syscall/Config1
-rw-r--r--libc/syscall/Makefile44
-rw-r--r--libc/syscall/TODO7
-rw-r--r--libc/syscall/dirent.c84
-rw-r--r--libc/syscall/execve.c114
-rw-r--r--libc/syscall/getinfo.c32
-rw-r--r--libc/syscall/mksyscall300
-rw-r--r--libc/syscall/setjmp.c50
-rw-r--r--libc/syscall/signal.c94
-rw-r--r--libc/syscall/syscall.dat147
-rw-r--r--libc/syscall/syslibc.c330
11 files changed, 1203 insertions, 0 deletions
diff --git a/libc/syscall/Config b/libc/syscall/Config
new file mode 100644
index 0000000..472e74b
--- /dev/null
+++ b/libc/syscall/Config
@@ -0,0 +1 @@
+syscall: Linux-8086 system call routines
diff --git a/libc/syscall/Makefile b/libc/syscall/Makefile
new file mode 100644
index 0000000..2cc4494
--- /dev/null
+++ b/libc/syscall/Makefile
@@ -0,0 +1,44 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+LSRC=syslibc.c
+LOBJ=__cstartup.o time.o lseek.o getpid.o getppid.o \
+ getuid.o geteuid.o getgid.o getegid.o \
+ dup2.o dup.o abort.o wait.o waitpid.o sleep.o
+
+ESRC=execve.c
+EOBJ=execve.o execl.o execv.o execle.o
+
+DSRC=dirent.c
+DOBJ=opendir.o closedir.o readdir.o
+
+ifeq ($(PLATFORM),i86-DOS)
+OBJ=setjmp.o
+else
+OBJ=$(LOBJ) $(DOBJ) $(EOBJ) signal.o setjmp.o execve.o
+endif
+
+all: mksyscall syscall.dat $(OBJ)
+ sh mksyscall
+
+clean:
+ rm -f *.o libc.a syscall.c syscall.mak call_tab.v defn_tab.v
+
+libc.a: mksyscall syscall.dat $(OBJ)
+ sh mksyscall libc.a
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+$(LOBJ): $(LSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(LSRC)
+
+$(DOBJ): $(DSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(DSRC)
+
+$(EOBJ): $(ESRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ESRC)
+
diff --git a/libc/syscall/TODO b/libc/syscall/TODO
new file mode 100644
index 0000000..90085d9
--- /dev/null
+++ b/libc/syscall/TODO
@@ -0,0 +1,7 @@
+It appears that a 386 version of the syscall libs is also wanted ...
+
+SYSV IPC, there's and __ipc syscall and the hardware can manage messages and
+semaphores.
+
+Idea, for RPC syscall, seperate all the FD related calls from the system ones
+IIRC all the single FD related ones have the FD in arg0
diff --git a/libc/syscall/dirent.c b/libc/syscall/dirent.c
new file mode 100644
index 0000000..bbb3c13
--- /dev/null
+++ b/libc/syscall/dirent.c
@@ -0,0 +1,84 @@
+
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <malloc.h>
+
+#ifdef L_opendir
+DIR *
+opendir(dname)
+const char *dname;
+{
+ struct stat st;
+ int fd;
+ DIR *p;
+
+ if (stat(dname, &st) < 0)
+ return 0;
+
+ if (!S_ISDIR(st.st_mode))
+ {
+ errno = ENOTDIR;
+ return 0;
+ }
+ if ((fd = open(dname, O_RDONLY)) < 0)
+ return 0;
+
+ p = malloc(sizeof(DIR));
+ if (p == 0)
+ {
+ close(fd);
+ return 0;
+ }
+
+ p->dd_buf = malloc(sizeof(struct dirent));
+ if (p->dd_buf == 0)
+ {
+ free(p);
+ close(fd);
+ return 0;
+ }
+ p->dd_fd = fd;
+ p->dd_loc = p->dd_size = 0;
+
+ return p;
+}
+#endif
+
+#ifdef L_closedir
+int
+closedir(dirp)
+DIR *dirp;
+{
+ int fd;
+ fd = dirp->dd_fd;
+ free(dirp->dd_buf);
+ free(dirp);
+ return close(fd);
+}
+#endif
+
+#ifdef L_readdir
+/*
+ * This currently assumes we see a v. simple diectory structure, it's
+ * probably faked!
+ */
+struct dirent *
+readdir(dirp)
+DIR *dirp;
+{
+ int cc;
+ cc = read(dirp->dd_fd, dirp->dd_buf, sizeof(struct dirent));
+
+ if (cc <= 0)
+ return 0;
+ if (cc != sizeof(struct dirent))
+ {
+ errno = EBADF;
+ return 0;
+ }
+ return dirp->dd_buf;
+}
+#endif
diff --git a/libc/syscall/execve.c b/libc/syscall/execve.c
new file mode 100644
index 0000000..aee7182
--- /dev/null
+++ b/libc/syscall/execve.c
@@ -0,0 +1,114 @@
+
+#include <errno.h>
+
+extern char ** environ;
+
+#ifdef L_execl
+int
+execl(fname, arg0)
+char * fname, *arg0;
+{
+ return execve(fname, &arg0, environ);
+}
+#endif
+
+#ifdef L_execv
+int
+execv(fname, argv)
+char * fname, **argv;
+{
+ return execve(fname, argv, environ);
+}
+#endif
+
+#ifdef L_execle
+int
+execle(fname, arg0)
+char *fname, *arg0;
+{
+ char ** envp = &arg0;
+ while(*envp) envp++;
+ return execve(fname, &arg0, envp+1);
+}
+#endif
+
+#ifdef L_execve
+int
+execve(fname, argv, envp)
+char * fname;
+char ** argv;
+char ** envp;
+{
+ char **p;
+ int argv_len=0, argv_count=0;
+ int envp_len=0, envp_count=0;
+ int stack_bytes;
+ unsigned short * pip;
+ char * pcp, * stk_ptr, *baseoff;
+ int rv;
+
+ /* How much space for argv */
+ for(p=argv; p && *p && argv_len >= 0; p++)
+ {
+ argv_count++; argv_len += strlen(*p)+1;
+ }
+
+ /* How much space for envp */
+ for(p=envp; p && *p && envp_len >= 0; p++)
+ {
+ envp_count++; envp_len += strlen(*p)+1;
+ }
+
+ /* tot it all up */
+ stack_bytes = 2 /* argc */
+ + argv_count * 2 + 2 /* argv */
+ + argv_len
+ + envp_count * 2 + 2 /* envp */
+ + envp_len;
+
+ /* Allocate it */
+ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0
+ || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+/* Sanity check
+ printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n",
+ argv_count, argv_len, envp_count, envp_len, stack_bytes);
+*/
+
+ /* Now copy in the strings */
+ pip=(unsigned short *) stk_ptr;
+ pcp=stk_ptr+2*(1+argv_count+1+envp_count+1);
+
+ /* baseoff = stk_ptr + stack_bytes; */
+ baseoff = stk_ptr;
+ *pip++ = argv_count;
+ for(p=argv; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ *pip++ = 0;
+
+ for(p=envp; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ *pip++ = 0;
+
+ rv = __exec(fname, stk_ptr, stack_bytes);
+ /* FIXME: This will probably have to interpret '#!' style exe's */
+ sbrk(-stack_bytes);
+ return rv;
+}
+#endif
diff --git a/libc/syscall/getinfo.c b/libc/syscall/getinfo.c
new file mode 100644
index 0000000..a5ab89a
--- /dev/null
+++ b/libc/syscall/getinfo.c
@@ -0,0 +1,32 @@
+
+#define PERM_GETINFO 0x100
+#define PERM_GETGROUP 0x200
+
+struct {
+ int pid;
+ int ppid;
+ int uid;
+ int gid;
+ int euid;
+ int egid;
+}
+ __info_safe;
+
+getgroups(count, locn)
+int count;
+void * locn;
+{
+ if( count < 0 ) {errno = EINVAL; return -1; }
+ return __permissions(PERM_GETGROUP, count, locn);
+}
+
+getpid()
+{
+ __permissions(PERM_GETINFO, 6, &__info_safe);
+ return __info_safe.pid;
+}
+
+getppid()
+{
+ return __permissions(PERM_GETITEM(1) /*, 0, 0 */);
+}
diff --git a/libc/syscall/mksyscall b/libc/syscall/mksyscall
new file mode 100644
index 0000000..1e98836
--- /dev/null
+++ b/libc/syscall/mksyscall
@@ -0,0 +1,300 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+#
+# This script generates the 'simple' system calls.
+#
+# Each call is put into it's own object file, if the semantics of the
+# call are not correct UNIX then the 4th field in the dat file has a
+# marker and the function is generated with a __ prefix.
+#
+#
+# Different levels of squeeze
+# 0 = each is complete
+# 1 = Short codes calling common function
+
+COMPACT=1
+
+rm -f syscall.c syscall.mak call_tab.v defn_tab.v
+
+tr '[A-Z]' '[a-z]' < syscall.dat | \
+awk -v COMPACT=$COMPACT 'BEGIN{
+ print "# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>" > "syscall.mak";
+ print "# This file is part of the Linux-8086 C library and is distributed" > "syscall.mak";
+ print "# under the GNU Library General Public License." > "syscall.mak";
+ print "# " > "syscall.mak";
+ print "# This file is automatically generated\n" > "syscall.mak"
+
+ print "/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>";
+ print " * This file is part of the Linux-8086 C library and is distributed";
+ print " * under the GNU Library General Public License.";
+ print " * ";
+ print " * This file is automatically generated */\n"
+ obj="OBJ=";
+
+ print "/* Standard start */\n\n"
+ printf("#ifndef __MSDOS__\n");
+ printf("#ifdef __AS386_16__\n");
+ printf("#asm\n");
+ printf(" .text\n");
+ printf(" .even\n");
+ printf("#endasm\n\n");
+
+ {
+ obj=obj "__syscall.o __syscall4.o ";
+ print "/* Shared system call code */\n"
+ printf("#ifdef L___syscall\n", funcname);
+ printf("#asm\n");
+ printf("#if __FIRST_ARG_IN_AX__\n");
+
+ printf("export sys_call3\nsys_call3:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov cx,[bx+2]\n");
+ printf(" mov bx,[bx+4]\n");
+ # ax=arg1 bx=arg3 cx=arg2 dx=arg0
+ printf(" xchg ax,bx\n");
+ # ax=arg3 bx=arg1 cx=arg2 dx=arg0
+ printf(" xchg ax,dx\n");
+ # ax=arg0 bx=arg1 cx=arg2 dx=arg3
+ printf(" jmp sys_call0\n\n");
+
+ printf("export sys_call2\nsys_call2:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov cx,[bx+2]\n");
+ printf(" mov bx,ax\n");
+ printf(" mov ax,dx\n");
+ printf(" jmp sys_call0\n\n");
+
+ printf("export sys_call1\nsys_call1:\n");
+ printf(" mov bx,ax\n");
+ printf(" mov ax,dx\n");
+ printf("#else\n");
+ printf("export sys_call3\nsys_call3:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov dx,[bx+6]\n");
+ printf(" mov cx,[bx+4]\n");
+ printf(" mov bx,[bx+2]\n");
+ printf(" jmp sys_call0\n\n");
+
+ printf("export sys_call2\nsys_call2:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov cx,[bx+4]\n");
+ printf(" mov bx,[bx+2]\n");
+ printf(" jmp sys_call0\n\n");
+
+ printf("export sys_call1\nsys_call1:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov bx,[bx+2]\n");
+ printf("#endif\n\n");
+
+ printf("export sys_call0\nsys_call0:\n");
+ printf(" int $80\n");
+ printf(" test ax,ax\n");
+ printf(" jge syscall_ok\n");
+ printf(" neg ax\n");
+ printf(" mov [_errno],ax\n");
+ printf(" mov ax,#-1\n");
+ printf("syscall_ok:\n");
+ printf(" ret\n");
+ printf("#endasm\n");
+ printf("#endif\n\n");
+
+ print "/* Shared system call code, syscalls with 4/5 args */\n"
+ printf("#ifdef L___syscall4\n", funcname);
+ printf("#asm\n");
+ printf("#if __FIRST_ARG_IN_AX__\n");
+
+ printf("export sys_call4\nsys_call4:\n");
+ printf("export sys_call5\nsys_call5:\n");
+ printf(" mov bx,sp\n");
+ printf(" push si\n");
+ printf(" mov si,[bx+8]\n");
+ printf(" push di\n");
+ printf(" mov di,[bx+6]\n");
+ printf(" mov cx,[bx+2]\n");
+ printf(" mov bx,[bx+4]\n");
+ # ax=arg1 bx=arg3 cx=arg2 dx=arg0
+ printf(" xchg ax,bx\n");
+ # ax=arg3 bx=arg1 cx=arg2 dx=arg0
+ printf(" xchg ax,dx\n");
+ # ax=arg0 bx=arg1 cx=arg2 dx=arg3
+ printf("#else\n");
+ printf("export sys_call4\nsys_call4:\n");
+ printf("export sys_call5\nsys_call5:\n");
+ printf(" mov bx,sp\n");
+ printf(" push si\n");
+ printf(" mov si,[bx+10]\n");
+ printf(" push di\n");
+ printf(" mov di,[bx+8]\n");
+ printf(" mov dx,[bx+6]\n");
+ printf(" mov cx,[bx+4]\n");
+ printf(" mov bx,[bx+2]\n");
+ printf("#endif\n\n");
+
+ printf(" int $80\n");
+ printf(" pop di\n");
+ printf(" pop si\n");
+ printf(" test ax,ax\n");
+ printf(" jge syscall_ok\n");
+ printf(" neg ax\n");
+ printf(" mov [_errno],ax\n");
+ printf(" mov ax,#-1\n");
+ printf("syscall_ok:\n");
+ printf(" ret\n");
+ printf("#endasm\n");
+ printf("#endif\n\n");
+ }
+}
+/^[ ]*#/ { next; }
+/^[ ]*$/ { next; }
+{
+ if( $2 > max_call ) max_call = $2;
+ if( !($2 in calltab) )
+ callwas[$2] = " /* " $1 " */";
+
+ if( $3 == "x" || $3 == "" ) next;
+ else if( $4 == "-" ) next;
+ else if( $4 == "*" ) funcname="__" $1;
+ else funcname=$1;
+
+ calltab[$2] = $1;
+
+ if( length(obj) > 60 )
+ {
+ printf("%s\t\\\n", obj) > "syscall.mak";
+ obj=" ";
+ }
+ obj=obj funcname ".o ";
+
+ printf "/* CALL %s */\n\n", $0;
+
+ printf("#ifdef L_%s\n", funcname);
+ printf("#asm\n", funcname);
+ printf("export _%s\n", funcname);
+ printf("_%s:\n", funcname);
+
+ # Inline assembler max to 5 args (10 bytes)
+ if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 ))
+ {
+ if( $3 == 0 )
+ {
+ printf(" mov ax,#%d\n", $2);
+ }
+ else
+ {
+ printf("#if __FIRST_ARG_IN_AX__\n");
+ printf(" mov dx,#%d\n", $2);
+ printf("#else\n");
+ printf(" mov ax,#%d\n", $2);
+ printf("#endif\n");
+ }
+ printf(" br sys_call%d\n", $3);
+ }
+ else
+ {
+ if( $3 >= 1 )
+ printf("#if __FIRST_ARG_IN_AX__\n");
+ if( $3 >= 2 )
+ printf(" mov bx,sp\n");
+ if( $3 >= 5 )
+ printf(" push si\n");
+ if( $3 >= 5 )
+ printf(" mov si,[bx+8]\n");
+ if( $3 >= 4 )
+ printf(" push di\n");
+ if( $3 >= 4 )
+ printf(" mov di,[bx+6]\n");
+ if( $3 >= 3 )
+ printf(" mov dx,[bx+4]\n");
+ if( $3 >= 2 )
+ printf(" mov cx,[bx+2]\n");
+ if( $3 >= 1 )
+ printf(" mov bx,ax\n");
+ if( $3 >= 1 )
+ printf("#else\n");
+ if( $3 >= 1 )
+ printf(" mov bx,sp\n");
+ if( $3 >= 5 )
+ printf(" push si\n");
+ if( $3 >= 5 )
+ printf(" mov si,[bx+10]\n");
+ if( $3 >= 4 )
+ printf(" push di\n");
+ if( $3 >= 4 )
+ printf(" mov di,[bx+8]\n");
+ if( $3 >= 3 )
+ printf(" mov dx,[bx+6]\n");
+ if( $3 >= 2 )
+ printf(" mov cx,[bx+4]\n");
+ if( $3 >= 1 )
+ printf(" mov bx,[bx+2]\n");
+ if( $3 >= 1 )
+ printf("#endif\n");
+
+ printf(" mov ax,#%d\n", $2);
+
+ printf(" int $80\n");
+
+ if( $3 >= 4 )
+ printf(" pop di\n");
+ if( $3 >= 5 )
+ printf(" pop si\n");
+
+ printf(" test ax,ax\n");
+ printf(" jl syscall_err\n");
+ printf(" ret\n");
+ printf("syscall_err:\n");
+ printf(" neg ax\n");
+ printf(" mov [_errno],ax\n");
+ printf(" mov ax,#-1\n");
+ printf(" ret\n");
+ }
+ printf("#endasm\n");
+ printf("#endif\n\n");
+}
+END{
+
+ for(i=0; i<=max_call; i++)
+ if( i in calltab )
+ {
+ printf("#ifndef sys_%s\n", calltab[i]) > "defn_tab.v";
+ printf("#define sys_%s sys_enosys\n", calltab[i]) > "defn_tab.v";
+ printf("#endif\n\n") > "defn_tab.v";
+ }
+
+ for(i=0; i<=max_call; i++)
+ if( i in calltab )
+ printf("/* %3d */ sys_%s,\n", i, calltab[i]) > "call_tab.v";
+ else
+ printf("/* %3d */ sys_enosys,%s\n", i, callwas[i]) > "call_tab.v";
+
+ printf("#endif /* __AS386_16__ */\n\n");
+ printf("#endif /* __MSDOS__ */\n\n");
+ printf("%s\n", obj) > "syscall.mak";
+ printf "\n" > "syscall.mak";
+
+}' > syscall.c
+
+cat >> syscall.mak <<\!
+
+TOP=..
+include $(TOP)/Make.defs
+
+all: $(OBJ)
+
+libc.a: $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+$(OBJ): syscall.dat mksyscall
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ syscall.c
+!
+
+rv=$?
+if [ "$rv" != 0 ]
+then exit $rv
+fi
+
+export MAKELEVEL
+MAKELEVEL=0
+exec make -f syscall.mak $1
diff --git a/libc/syscall/setjmp.c b/libc/syscall/setjmp.c
new file mode 100644
index 0000000..52c3ff1
--- /dev/null
+++ b/libc/syscall/setjmp.c
@@ -0,0 +1,50 @@
+
+#include <setjmp.h>
+
+#if __AS386_16__
+
+int
+setjmp(env)
+jmp_buf env;
+{
+#asm
+ pop cx ! PC
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx] ! TOS is prt -> env
+#endif
+ mov [bx+0],cx ! PC
+ mov [bx+2],sp ! This registers are all that may be constant.
+ mov [bx+4],bp
+ mov [bx+6],si ! Is saving these the "right thing" ?
+ mov [bx+8],di
+ xor ax,ax
+ jmp cx
+#endasm
+}
+
+void
+longjmp(env, rv)
+jmp_buf env;
+int rv;
+{
+#asm
+ pop cx ! pc
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax ! env->
+#else
+ pop bx ! env->
+#endif
+ pop ax ! rv
+ mov cx,[bx+0] ! PC
+ mov sp,[bx+2]
+ mov bp,[bx+4]
+ mov si,[bx+6]
+ mov di,[bx+8]
+ jmp cx
+#endasm
+}
+
+#endif
diff --git a/libc/syscall/signal.c b/libc/syscall/signal.c
new file mode 100644
index 0000000..dbeac4a
--- /dev/null
+++ b/libc/syscall/signal.c
@@ -0,0 +1,94 @@
+
+#ifndef __MSDOS__
+#ifdef __AS386_16__
+
+#include <errno.h>
+#include <signal.h>
+
+typedef __sighandler_t Sig;
+
+extern int __signal __P((int, __sighandler_t));
+static Sig system_signal();
+
+Sig __sigtable[_NSIG-1];
+
+/*
+ * Signal handler.
+ *
+ */
+
+/*
+ * KERNEL INTERFACE:
+ * It is assumed the kernel will never give us a signal we haven't
+ * _explicitly_ asked for!
+ *
+ * The Kernel need only save space for _one_ function pointer
+ * (to system_signal) and must deal with SIG_DFL and SIG_IGN
+ * in kernel space.
+ *
+ * When a signal is required the kernel must set all the registers as if
+ * returning from a interrupt normally then push the number of the signal
+ * to be generated, push the current pc value, then set the pc to the
+ * address of the 'system_signal' function.
+ */
+
+Sig
+signal(number, pointer)
+int number;
+Sig pointer;
+{
+ Sig old_sig;
+ int rv;
+ if( number < 1 || number >= _NSIG ) { errno=EINVAL; return SIG_ERR; }
+
+ if( pointer == SIG_DFL || pointer == SIG_IGN )
+ rv = __signal(number, pointer);
+ else
+ rv = __signal(number, (__sighandler_t) system_signal);
+
+ if( rv < 0 ) return SIG_ERR;
+
+ old_sig = __sigtable[number-1];
+ __sigtable[number-1] = pointer;
+
+ return old_sig;
+}
+
+#asm
+ .text
+_system_signal: ! When this is called by the kernel the stack contains
+ pushf ! in order:
+ push ax !
+ push bx ! The signal number, (NOS)
+ push cx ! The program counter, (TOS)
+ push dx !
+ push si ! It does NOT contain the CS register or the flags.
+ push di ! This means it cannot be unraveled by an iret.
+ push bp
+ push es ! Note also only ES segment register is saved.
+ mov bx,sp ! Unlike minix the rv from a system call is in AX.
+ mov bx,[bx+20]
+#if __FIRST_ARG_IN_AX__
+ mov ax,bx
+#else
+ push bx ! NB this is _unchecked_, do we want to ?
+#endif
+ add bx,bx
+ mov bx,[bx+___sigtable-2] ! Offset by 2 cause no entry for signal 0
+ call bx ! Do we want to check BX for 0 or 1 ?
+ inc sp
+ inc sp
+ pop es
+ pop bp
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ popf
+ ret #2 ! Get rid of the signum too.
+#endasm
+
+#endif /* __AS386_16__ */
+#endif /* __MSDOS__ */
diff --git a/libc/syscall/syscall.dat b/libc/syscall/syscall.dat
new file mode 100644
index 0000000..d83be4f
--- /dev/null
+++ b/libc/syscall/syscall.dat
@@ -0,0 +1,147 @@
+#
+# Name No Args Flag, comment
+#
+# . = Ok, with comment
+# * = Needs libc code (Prefix __)
+# - = Obsolete/not required
+#
+# WARNING!
+# This file is used to generate includes for ELKSemu too.
+# This file is continually changing, when you upgrade you _MUST_ ensure
+# that ELKSemu is of a matching build!
+#
+# Calls that use one fd
+READ 3 3
+WRITE 4 3
+CLOSE 6 1
+LSEEK 19 3 * NB 2nd arg is a ptr to long not a long.
+FSTAT 28 2
+IOCTL 54 3 . Make this and fcntl the same ?
+FCNTL 55 3
+FCHMOD 94 X
+FCHOWN 95 X
+FSYNC 118 1
+FCHDIR 133 X
+LLSEEK 140 X
+READV 145 X
+WRITEV 146 X
+FLOCK 143 X - Use fcntl
+DUP 41 1 - Using nasty fcntl function
+
+#
+SETUP 0 X
+EXIT 1 1 * C exit does stdio, _exit in crt0
+FORK 2 0
+OPEN 5 3
+WAIT4 7 4
+VFORK 8 0 . Needed for 8086
+GETINFO 49 1 - Possible? Gets pid,ppid,uid,euid etc
+LINK 9 2
+UNLINK 10 1
+EXEC 11 3 * Minix style exec
+CHDIR 12 1
+GETTIMEOFDAY 13 2 . time() exists only in libc
+MKNOD 14 3
+CHMOD 15 2
+CHOWN 16 3
+BRK 17 1 * This is only to tell the system
+STAT 18 2
+GETPID 20 1 * This gets both pid & ppid
+MOUNT 21 5
+UMOUNT 22 1
+SETUID 23 1
+GETUID 24 1 * This gets both uid and euid
+SETTIMEOFDAY 25 2 . STIME should _NOT_ exist even as a libc.
+STIME 25 2 - This must NOT exist - even as a libc.
+PTRACE 26 4
+ALARM 27 2
+PAUSE 29 0
+UTIME 30 2
+ACCESS 33 2
+NICE 34 1 .
+FTIME 35 1 - Use gettimeofday
+SYNC 36 0
+KILL 37 2
+RENAME 38 2
+MKDIR 39 2
+RMDIR 40 1
+PIPE 42 1
+TIMES 43 1
+PROF 44 X
+SETGID 46 1
+GETGID 47 1 * This gets both gid and egid
+SIGNAL 48 2 * Have put the despatch table in user space.
+ACCT 51 1
+PHYS 52 X
+LOCK 53 X
+MPX 56 X
+SETPGID 57 2
+ULIMIT 58 2
+UMASK 60 1
+CHROOT 61 1
+USTAT 62 2
+GETPGRP 65 X
+SETSID 66 X
+SIGACTION 67 X
+SGETMASK 68 X
+SSETMASK 69 X
+SETREUID 70 X
+SETREGID 71 X
+SIGSUSPEND 72 X
+SIGPENDING 73 X
+SETHOSTNAME 74 2
+SETRLIMIT 75 X
+GETRLIMIT 76 X
+REBOOT 76 3 . The magic number is 0xfee1,0xdead,...
+GETRUSAGE 77 X
+GETGROUPS 80 2
+SETGROUPS 81 2
+SYMLINK 83 2
+LSTAT 84 2
+READLINK 85 3
+SWAPON 87 X
+REBOOT 88 X
+MUNMAP 91 X
+TRUNCATE 92 X
+FTRUNCATE 93 X
+GETPRIORITY 96 X
+SETPRIORITY 97 X
+PROFIL 98 X
+STATFS 99 X
+FSTATFS 100 X
+SOCKETCALL 102 X
+SYSLOG 103 X
+SETITIMER 104 X
+GETITIMER 105 X
+UNAME 109 1
+VHANGUP 111 0
+SWAPOFF 115 X
+SYSINFO 116 X - Use /proc
+IPC 117 5 * This is for all SYSV IPC
+SIGRETURN 119 X
+SETDOMAINNAME 121 X
+ADJTIMEX 124 X
+MPROTECT 125 X
+SIGPROCMASK 126 X
+QUOTACTL 131 X
+GETPGID 132 1
+SYSFS 135 X
+PERSONALITY 136 X
+SETFSUID 138 X
+SETFSGID 139 X
+GETDENTS 141 X
+SELECT 142 5 *
+MSYNC 144 X
+GETSID 147 X
+FDATASYNC 148 X
+SYSCTL 149 X
+MUNLOCK 151 X
+MUNLOCKALL 153 X
+SCHED_SETPARAM 154 X
+SCHED_GETPARAM 155 X
+SCHED_SETSCHEDULER 156 X
+SCHED_GETSCHEDULER 157 X
+SCHED_YIELD 158 X
+SCHED_GET_PRIORITY_MAX 159 X
+SCHED_GET_PRIORITY_MIN 160 X
+SCHED_RR_GET_INTERVAL 161 X
diff --git a/libc/syscall/syslibc.c b/libc/syscall/syslibc.c
new file mode 100644
index 0000000..1e604e8
--- /dev/null
+++ b/libc/syscall/syslibc.c
@@ -0,0 +1,330 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <sys/types.h>
+#include <time.h>
+
+/* MSDOS has it's own versions */
+#ifndef __MSDOS__
+#ifdef __AS386_16__
+
+/********************** Function __cstartup *******************************/
+
+#ifdef L___cstartup
+
+void (*__cleanup)() = 0;
+char ** environ;
+
+#asm
+ loc 2
+call_main:
+ .word _main ! Segment 2 is the trailing pointers, main and the
+ .word call_exit ! routine to call exit.
+#if __FIRST_ARG_IN_AX__
+ .data
+saved_arg1:
+ .word 0
+#endif
+#if __CALLER_SAVES__
+ .data
+loopy_safe:
+ .word 0
+#endif
+ .text
+
+export ___cstartup
+___cstartup: ! Crt0 startup
+ pop cx ! Argc
+ mov bx,sp ! Calculate ptrs to argv and envp
+ mov ax,cx
+ inc ax
+ shl ax,#1
+ add ax,bx
+ push ax ! Push Envp
+ mov [_environ],ax ! And save
+ push bx ! Push argv
+#if __FIRST_ARG_IN_AX__
+ mov [saved_arg1],cx
+#else
+ push cx ! Push argc
+#endif
+
+ mov si,#auto_start ! Pointer to first autostart function
+auto_run:
+#if __FIRST_ARG_IN_AX__
+ mov ax,[saved_arg1]
+#endif
+#if __CALLER_SAVES__
+ mov [loopy_safe],si
+#endif
+ call [si] ! Call the function
+#if __CALLER_SAVES__
+ mov si,[loopy_safe]
+#endif
+ inc si ! SI at next
+ inc si
+ jmp auto_run ! And round for the next.
+
+call_exit: ! Last item called by above.
+ pop bx ! Be tidy.
+#if !__FIRST_ARG_IN_AX__
+ push ax ! At the end the last called was main() push it`s
+#endif
+ call _exit ! return val and call exit();
+bad_exit:
+ jmp bad_exit ! Exit returned !!
+
+export _exit
+export __exit
+_exit: ! exit(rv) function
+#if __FIRST_ARG_IN_AX__
+ mov [saved_arg1],ax
+#else
+ mov bx,sp
+ push [bx+2] ! Copy the `rv` for the exit fuctions.
+#endif
+ mov bx,[___cleanup] ! Call exit, normally this is `__do_exit`
+ test bx,bx
+ je no_clean ! But it`s default is null
+ call bx
+no_clean:
+#if __FIRST_ARG_IN_AX__
+ mov ax,[saved_arg1]
+#else
+ inc sp
+ inc sp
+#endif
+__exit: ! _exit(rv)
+ br ___exit ! This is just an alias for __exit();
+
+#endasm
+
+#endif
+
+/********************** Function time ************************************/
+
+#ifdef L_time
+time_t time(where)
+time_t *where;
+{
+ struct timeval rv;
+ if( gettimeofday(&rv, (void*)0) < 0 ) return -1;
+ if(where) *where = rv.tv_sec;
+ return rv.tv_sec;
+}
+#endif
+
+/********************** Function lseek ************************************/
+
+#ifdef L_lseek
+off_t lseek(fd, posn, where)
+int fd;
+off_t posn;
+int where;
+{
+ off_t __lseek();
+ if( __lseek(fd, &posn, where) < 0 ) return -1;
+ else return posn;
+}
+#endif
+
+/********************** Function getpid ************************************/
+
+#ifdef L_getpid
+int getpid()
+{
+ int ppid;
+ return __getpid(&ppid);
+}
+#endif
+
+/********************** Function getppid ************************************/
+
+#ifdef L_getppid
+int getppid()
+{
+ int ppid;
+ __getpid(&ppid);
+ return ppid;
+}
+#endif
+
+/********************** Function getuid ************************************/
+
+#ifdef L_getuid
+int getuid()
+{
+ int euid;
+ return __getuid(&euid);
+}
+#endif
+
+/********************** Function geteuid ************************************/
+
+#ifdef L_geteuid
+int geteuid()
+{
+ int euid;
+ __getuid(&euid);
+ return euid;
+}
+#endif
+
+/********************** Function getgid ************************************/
+
+#ifdef L_getgid
+int getgid()
+{
+ int egid;
+ return __getgid(&egid);
+}
+#endif
+
+/********************** Function getegid ************************************/
+
+#ifdef L_getegid
+int getegid()
+{
+ int egid;
+ __getgid(&egid);
+ return egid;
+}
+#endif
+
+/********************** Function dup2 ************************************/
+
+#ifdef L_dup2
+
+#include <fcntl.h>
+
+int dup2(ifd, ofd)
+int ifd;
+{
+ return fcntl(ifd, F_DUPFD, ofd);
+}
+#endif
+
+/********************** Function dup ************************************/
+
+#ifdef L_dup
+#include <sys/param.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* This is horribly complicated, there _must_ be a better way! */
+
+int
+dup(fd)
+int fd;
+{
+ int nfd;
+ extern int errno;
+ int oerr = errno;
+
+ errno = 0;
+ for(nfd=0; nfd<NR_OPEN; nfd++)
+ {
+ if( fcntl(nfd, F_GETFD) < 0 )
+ break;
+ }
+ if( nfd == NR_OPEN ) { errno = EMFILE ; return -1; }
+ errno = oerr;
+ if( fcntl(fd, F_DUPFD, nfd) < 0 )
+ {
+ if( errno == EINVAL ) errno = EMFILE;
+ return -1;
+ }
+ return nfd;
+}
+#endif
+
+/********************** Function abort ************************************/
+
+#ifdef L_abort
+#include <signal.h>
+
+int abort()
+{
+ signal(SIGABRT, SIG_DFL);
+ kill(SIGABRT, getpid()); /* Correct one */
+ pause(); /* System may just schedule */
+ signal(SIGKILL, SIG_DFL);
+ kill(SIGKILL, getpid()); /* Can't trap this! */
+ __exit(255); /* WHAT!! */
+}
+#endif
+
+/********************** Function wait ************************************/
+
+#ifdef L_wait
+int
+wait(status)
+int * status;
+{
+ return wait4(-1, status, 0, (void*)0);
+}
+#endif
+
+/********************** Function waitpid ************************************/
+
+#ifdef L_waitpid
+int
+waitpid(pid, status, opts)
+int pid;
+int * status;
+int opts;
+{
+ return wait4(pid, status, opts, (void*)0);
+}
+#endif
+
+/********************** Function sleep ************************************/
+
+#ifdef L_sleep
+#include <signal.h>
+
+/* This uses SIGALRM, it does keep the previous alarm call but will lose
+ * any alarms that go off during the sleep
+ */
+
+static void alrm() { }
+
+unsigned int sleep(seconds)
+unsigned int seconds;
+{
+ void (*last_alarm)();
+ unsigned int prev_sec;
+
+ prev_sec = alarm(0);
+ if( prev_sec <= seconds ) prev_sec = 1; else prev_sec -= seconds;
+
+ last_alarm = signal(SIGALRM, alrm);
+ alarm(seconds);
+ pause();
+ seconds = alarm(prev_sec);
+ signal(SIGALRM, last_alarm);
+ return seconds;
+}
+#if 0
+ /* Is this a better way ? If we have select of course :-) */
+#include <sys/time.h>
+unsigned int
+sleep(seconds)
+unsigned int seconds;
+{
+ struct timeval timeout;
+ time_t start = time((void*)0);
+ timeout.tv_sec = seconds;
+ timeout.tv_usec = 0;
+ select(1, NULL, NULL, NULL, &timeout);
+ return seconds - (time((void*)0) - start);
+}
+#endif
+#endif
+
+/********************** THE END ********************************************/
+
+#endif /* __AS386_16__ */
+#endif /* __MSDOS__ */