summaryrefslogtreecommitdiff
path: root/libc/i386sys
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1997-02-25 20:42:19 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:38:07 +0200
commit4c36e9a0c125ccfff37aa440dab2cf58c4152fff (patch)
treea5d9c84ba2661029ddb2223dacd50529a361c3d5 /libc/i386sys
parentf8de35da65c5d93bb733073cf40da154bc1c0748 (diff)
parent9696d7b0e1f3a1b0f5fd4a0428eb75afe8ad4ed6 (diff)
downloaddev86-4c36e9a0c125ccfff37aa440dab2cf58c4152fff.tar.gz
Import Dev86src-0.0.11.tar.gzv0.0.11
Diffstat (limited to 'libc/i386sys')
-rw-r--r--libc/i386sys/Config1
-rw-r--r--libc/i386sys/Makefile52
-rw-r--r--libc/i386sys/dirent.c106
-rw-r--r--libc/i386sys/exec.c292
-rw-r--r--libc/i386sys/mksyscall143
-rw-r--r--libc/i386sys/signal.c99
-rw-r--r--libc/i386sys/syscall.dat155
-rw-r--r--libc/i386sys/syslibc.c255
8 files changed, 1103 insertions, 0 deletions
diff --git a/libc/i386sys/Config b/libc/i386sys/Config
new file mode 100644
index 0000000..1bf0110
--- /dev/null
+++ b/libc/i386sys/Config
@@ -0,0 +1 @@
+sys386: Linux-i386 system call routines
diff --git a/libc/i386sys/Makefile b/libc/i386sys/Makefile
new file mode 100644
index 0000000..ef01ac9
--- /dev/null
+++ b/libc/i386sys/Makefile
@@ -0,0 +1,52 @@
+# 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.
+
+LSRC=syslibc.c
+LOBJ=__cstart3.o time.o abort.o wait.o waitpid.o wait3.o killpg.o setpgrp.o \
+ sleep.o usleep.o
+
+ESRC=exec.c
+EOBJ=execl.o execv.o execle.o execlp.o execvp.o
+
+DSRC=dirent.c
+DOBJ=opendir.o closedir.o readdir.o
+
+ifeq ($(LIB_CPU)-$(LIB_OS),i386-ELKS)
+OBJ=$(LOBJ3) $(LOBJ) $(EOBJ) $(DOBJ)
+SYSCALLS=syscalls
+
+CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS)
+
+all: $(SYSCALLS) $(LIBC)($(OBJ))
+ @:
+
+syscalls: syscall.mak
+ $(MAKE) -f syscall.mak LIBC="$(LIBC)" CFLAGS="$(CFLAGS)"
+
+syscall.mak: mksyscall syscall.dat
+ sh mksyscall
+
+$(LIBC)($(LOBJ)): $(LSRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(AR) $(ARFLAGS) $@ $*.o
+ $(RM) $*.o
+
+$(LIBC)($(DOBJ)): $(DSRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(AR) $(ARFLAGS) $@ $*.o
+ $(RM) $*.o
+
+$(LIBC)($(EOBJ)): $(ESRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(AR) $(ARFLAGS) $@ $*.o
+ $(RM) $*.o
+else
+all:
+ @:
+endif
+
+clean:
+ rm -f *.o libc.a
+ rm -f syscall.c syscall.mak
+
diff --git a/libc/i386sys/dirent.c b/libc/i386sys/dirent.c
new file mode 100644
index 0000000..8f7574c
--- /dev/null
+++ b/libc/i386sys/dirent.c
@@ -0,0 +1,106 @@
+
+#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 __AS386_16__
+#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
+#else
+
+/* This is for 386 linux */
+
+#ifdef L_readdir
+struct dirent *
+readdir(dirp)
+DIR *dirp;
+{
+ int cc;
+
+ cc = __readdir(dirp->dd_fd, dirp->dd_buf, 1);
+ if (cc <= 0)
+ return 0;
+ if (cc>1) dirp->dd_buf->d_name[cc] = 0;
+
+ return dirp->dd_buf;
+}
+#endif
+
+#endif
diff --git a/libc/i386sys/exec.c b/libc/i386sys/exec.c
new file mode 100644
index 0000000..411b744
--- /dev/null
+++ b/libc/i386sys/exec.c
@@ -0,0 +1,292 @@
+
+#include <errno.h>
+#include <sys/stat.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
+
+#ifdef L_execlp
+int
+execlp(fname, arg0)
+char * fname, *arg0;
+{
+ return execvp(fname, &arg0);
+}
+#endif
+
+#ifdef L_execvp
+int
+execvp(fname, argv)
+char * fname, **argv;
+{
+ char *pname = fname, *path;
+ int besterr = ENOENT;
+ int flen, plen;
+ char * bp = sbrk(0);
+
+ if( *fname != '/' && (path = getenv("PATH")) != 0 )
+ {
+ flen = strlen(fname)+2;
+
+ for(;path;)
+ {
+ if( *path == ':' || *path == '\0' )
+ {
+ tryrun(fname, argv);
+ if( errno == EACCES ) besterr = EACCES;
+ if( *path ) path++; else break;
+ }
+ else
+ {
+ char * p = strchr(path, ':');
+ if(p) *p = '\0';
+ plen = strlen(path);
+ pname = sbrk(plen+flen);
+
+ strcpy(pname, path);
+ strcat(pname, "/");
+ strcat(pname, fname);
+
+ tryrun(pname, argv);
+ if( errno == EACCES ) besterr = EACCES;
+
+ brk(pname);
+ pname = fname;
+ if(p) *p++ = ':';
+ path=p;
+ }
+ }
+ }
+
+ tryrun(pname, argv);
+ brk(bp);
+ if( errno == ENOENT || errno == 0 ) errno = besterr;
+ return -1;
+}
+
+static int tryrun(pname, argv)
+char * pname;
+char ** argv;
+{
+static char *shprog[] = {"/bin/sh", "", 0};
+ struct stat st;
+
+ if( stat(pname, &st) < 0 ) return;
+ if( !S_ISREG(st.st_mode) ) return;
+
+#ifdef __AS386_16__
+ __execvve(pname, (void*)0, argv, environ);
+ if( errno == ENOEXEC )
+ {
+ shprog[1] = pname;
+ __execvve(shprog[0], shprog, argv, environ);
+ }
+#else
+ execve(pname, argv, environ);
+ /* FIXME - running /bin/sh in 386 mode */
+#endif
+}
+
+#ifdef __AS386_16__
+static int
+__execvve(fname, interp, argv, envp)
+char * fname;
+char ** interp;
+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=interp; p && *p && argv_len >= 0; p++)
+ {
+ argv_count++; argv_len += strlen(*p)+1;
+ }
+ 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=interp; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ 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
+#endif
diff --git a/libc/i386sys/mksyscall b/libc/i386sys/mksyscall
new file mode 100644
index 0000000..d9b7f3a
--- /dev/null
+++ b/libc/i386sys/mksyscall
@@ -0,0 +1,143 @@
+# 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 for the 386
+#
+# 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
+
+rm -f syscall.c syscall.mak
+
+tr '[A-Z]' '[a-z]' < syscall.dat | \
+awk '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_32__\n");
+ printf("#asm\n");
+ printf(" .text\n");
+ printf(" .align 4\n");
+ printf("#endasm\n\n");
+
+ COMPACT=0;
+}
+/^[ ]*#/ { next; }
+/^[ ]*$/ { next; }
+{
+ if( $2 > max_call ) max_call = $2;
+
+ if( $3 == "x" || $3 == "" ) next;
+ else if( $4 == "-" ) next;
+ else if( $4 == "*" ) funcname="__" $1;
+ else funcname=$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");
+ printf("export _%s\n", funcname);
+ printf("_%s:\n", funcname);
+
+ # Inline assembler max to 5 args (20 bytes)
+ if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 ))
+ {
+ if( $3 == 0 )
+ {
+ printf(" mov eax,#%d\n", $2);
+ }
+ else
+ {
+ printf("#if __FIRST_ARG_IN_AX__\n");
+ printf(" mov edx,#%d\n", $2);
+ printf("#else\n");
+ printf(" mov eax,#%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 >= 1 ) printf(" mov ebx,eax\n");
+ if( $3 >= 2 ) printf(" mov ecx,[esp+4]\n");
+ if( $3 >= 3 ) printf(" mov edx,[esp+8]\n");
+ if( $3 >= 4 ) printf(" push esi\n");
+ if( $3 >= 4 ) printf(" mov esi,[esp+16]\n");
+ if( $3 >= 5 ) printf(" push edi\n");
+ if( $3 >= 5 ) printf(" mov edi,[esp+24]\n");
+ if( $3 >= 1 ) printf("#else\n");
+ if( $3 >= 1 ) printf(" mov ebx,[esp+4]\n");
+ if( $3 >= 2 ) printf(" mov ecx,[esp+8]\n");
+ if( $3 >= 3 ) printf(" mov edx,[esp+12]\n");
+ if( $3 >= 4 ) printf(" push esi\n");
+ if( $3 >= 4 ) printf(" mov esi,[esp+20]\n");
+ if( $3 >= 5 ) printf(" push edi\n");
+ if( $3 >= 5 ) printf(" mov edi,[esp+28]\n");
+ if( $3 >= 1 ) printf("#endif\n");
+ printf(" mov eax,#%d\n", $2);
+ printf(" int $80\n");
+
+ if( $3 >= 5 ) printf(" pop edi\n");
+ if( $3 >= 4 ) printf(" pop esi\n");
+
+ printf(" test eax,eax\n");
+ printf(" jl syscall_err\n");
+ printf(" ret\n");
+ printf("syscall_err:\n");
+ printf(" neg eax\n");
+ printf(" mov [_errno],eax\n");
+ printf(" mov eax,#-1\n");
+ printf(" ret\n");
+ }
+ printf("#endasm\n");
+ printf("#endif\n\n");
+}
+END{
+
+ printf("#endif /* __AS386_32__ */\n\n");
+ printf("#endif /* __MSDOS__ */\n\n");
+ printf("%s\n", obj) > "syscall.mak";
+ printf "\n" > "syscall.mak";
+
+}' > syscall.c
+
+cat >> syscall.mak <<\!
+
+CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS)
+
+all: $(LIBC)($(OBJ))
+ @:
+
+$(LIBC)($(OBJ)): syscall.dat
+ $(CC) $(CFLAGS) -DL_$* syscall.c -c -o $*.o
+ $(AR) $(ARFLAGS) $@ $*.o
+ $(RM) $*.o
+!
+
+exit $?
diff --git a/libc/i386sys/signal.c b/libc/i386sys/signal.c
new file mode 100644
index 0000000..dad3389
--- /dev/null
+++ b/libc/i386sys/signal.c
@@ -0,0 +1,99 @@
+
+#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;
+
+ switch(rv)
+ {
+ case 0: return SIG_DFL;
+ case 1: return SIG_IGN;
+ 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/i386sys/syscall.dat b/libc/i386sys/syscall.dat
new file mode 100644
index 0000000..da9ad6c
--- /dev/null
+++ b/libc/i386sys/syscall.dat
@@ -0,0 +1,155 @@
+
+#
+# Name No Args Flag, comment
+#
+# . = Ok, with comment
+# * = Needs libc code (Prefix __)
+# - = Obsolete/not required
+#
+# Name N C
+setup 0 X
+exit 1 1 *
+fork 2 0
+vfork 2 0 . Fake alias of fork
+read 3 3
+write 4 3
+open 5 3
+close 6 1
+waitpid 7 3
+creat 8 2
+link 9 2
+unlink 10 1
+execve 11 3
+chdir 12 1
+time 13 1
+dv32_mknod 14 3 * Has correct args for 32bit dev_t
+chmod 15 2
+chown 16 3
+break 17 X - This is done in a special function
+oldstat 18 X -
+lseek 19 3
+getpid 20 0
+mount 21 5
+umount 22 1
+setuid 23 1
+getuid 24 0
+stime 25 1
+ptrace 26 4
+alarm 27 1
+oldfstat 28 X -
+pause 29 0
+utime 30 2
+stty 31 X -
+gtty 32 X -
+access 33 2
+nice 34 1
+ftime 35 1
+sync 36 0
+kill 37 2
+rename 38 2
+mkdir 39 2
+rmdir 40 1
+dup 41 1
+pipe 42 1
+times 43 1
+prof 44 X -
+brk 45 1 - need to save brk_addr & -ve is valid return.
+setgid 46 1
+getgid 47 0
+signal 48 2
+geteuid 49 0
+getegid 50 0
+acct 51 1
+phys 52 X -
+lock 53 X -
+ioctl 54 3
+fcntl 55 3
+mpx 56 X -
+setpgid 57 2
+ulimit 58 2
+oldolduname 59 X -
+umask 60 1
+chroot 61 1
+dv32_ustat 62 2 * Has correct args for 32bit dev_t
+dup2 63 2
+getppid 64 0
+getpgrp 65 0
+setsid 66 0
+sigaction 67 3
+siggetmask 68 0
+sigsetmask 69 1
+setreuid 70 2
+setregid 71 2
+sigsuspend 72 1
+sigpending 73 1
+sethostname 74 2
+setrlimit 75 2
+getrlimit 76 2
+getrusage 77 2
+gettimeofday 78 2
+settimeofday 79 2
+getgroups 80 2
+setgroups 81 2
+select 82 1 * select's arg is &arg1
+symlink 83 2
+oldlstat 84 X -
+readlink 85 3
+uselib 86 1
+swapon 87 2
+reboot 88 3
+readdir 89 3 * Takes the fd not a ddptr
+mmap 90 1 * Is a pointer to a buffer with the 6 args.
+munmap 91 2
+truncate 92 2
+ftruncate 93 2
+fchmod 94 2
+fchown 95 2
+getpriority 96 2
+setpriority 97 3
+profil 98 X - glibc has userspace
+statfs 99 2
+fstatfs 100 2
+ioperm 101 3
+socketcall 102 2 * This is a lib internal for socket stuff
+klog 103 X
+setitimer 104 3
+getitimer 105 2
+dv32_stat 106 2 * Has correct args for 32 bit dev_t
+dv32_lstat 107 2 * Has correct args for 32 bit dev_t
+dv32_fstat 108 2 * Has correct args for 32 bit dev_t
+olduname 109 X -
+iopl 110 1
+vhangup 111 0
+idle 112 0 - System internal
+vm86 113 1
+wait4 114 4
+swapoff 115 1
+sysinfo 116 1
+ipc 117 5 * SYSV ipc entry point
+fsync 118 1
+sigreturn 119 1 * Signal internal
+clone 120 2
+setdomainname 121 2
+uname 122 1
+modify_ldt 123 X
+adjtimex 124 1
+mprotect 125 3
+sigprocmask 126 3
+create_module 127 X - Module handling, NO WAY!
+init_module 128 X
+delete_module 129 X
+get_kernel_syms 130 X
+quotactl 131 X
+getpgid 132 1
+fchdir 133 1
+bdflush 134 2
+sysfs 135 3
+personality 136 1 * Linux specific.
+afs_syscall 137 X
+setfsuid 138 1
+setfsgid 139 1
+_llseek 140 X
+getdents 141 3 * New style readdir ?
+_newselect 142 X
+flock 143 2
+syscall_flock 143 X
diff --git a/libc/i386sys/syslibc.c b/libc/i386sys/syslibc.c
new file mode 100644
index 0000000..60dda42
--- /dev/null
+++ b/libc/i386sys/syslibc.c
@@ -0,0 +1,255 @@
+/* Copyright (C) 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 <errno.h>
+#include <time.h>
+#include <sys/times.h>
+
+/* MSDOS has it's own versions */
+#ifndef __MSDOS__
+#ifdef __AS386_32__
+
+/********************** Function __cstartup *******************************/
+
+#ifdef L___cstart3
+
+void (*__cleanup)() = 0;
+char ** environ;
+
+#asm
+ loc 2
+call_main:
+ .long _main ! Segment 2 is the trailing pointers, main and the
+ .long call_exit ! routine to call exit.
+#if __FIRST_ARG_IN_AX__
+ .data
+saved_arg1:
+ .long 0
+#endif
+ .data
+loop_safe:
+ .long 0
+ .text
+
+export ___mkargv
+___mkargv: ! BCC Tells linker to init argv ... none needed.
+
+export ___cstartup
+___cstartup: ! Crt0 startup (Linux style)
+ mov eax,[esp]
+ test eax,eax
+ jz call_exit ! If argc == 0 this is being called by ldd, exit.
+ mov eax,[esp+8]
+ mov [_environ],eax
+#if __FIRST_ARG_IN_AX__
+ pop [saved_arg1] ! Argc will go into eax
+#endif
+
+ mov ebx,#auto_start ! Pointer to first autostart function
+auto_run:
+#if __FIRST_ARG_IN_AX__
+ mov eax,[saved_arg1]
+#endif
+ mov [loop_safe],ebx
+ mov ebx,[ebx]
+ test ebx,ebx
+ jz no_func
+ call ebx ! Call the function
+no_func:
+ mov ebx,[loop_safe]
+ add ebx,#4 ! next
+ jmp auto_run ! And round for the next.
+
+call_exit: ! Last item called by above.
+ pop ebx ! Be tidy.
+#if !__FIRST_ARG_IN_AX__
+ push eax ! 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],eax
+#else
+ push [esp+4] ! Copy the `rv` for the exit fuctions.
+#endif
+ mov ebx,[___cleanup] ! Call exit, normally this is `__do_exit`
+ test ebx,ebx
+ je no_clean ! But it`s default is null
+ call ebx
+no_clean:
+#if __FIRST_ARG_IN_AX__
+ mov eax,[saved_arg1]
+#else
+ add esp,#4
+#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 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 wait3 **************************************/
+
+#ifdef L_wait3
+int
+wait3(status, opts, usage)
+int * status;
+int opts;
+struct rusage * usage;
+{
+ return wait4(-1, status, opts, usage);
+}
+#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 killpg ************************************/
+
+#ifdef L_killpg
+int
+killpg(pid, sig)
+int pid;
+int sig;
+{
+ if(pid == 0)
+ pid = getpgrp();
+ if(pid > 1)
+ return kill(-pid, sig);
+ errno = EINVAL;
+ return -1;
+}
+#endif
+
+/********************** Function setpgrp ************************************/
+
+#ifdef L_setpgrp
+int
+setpgrp()
+{
+ return setpgid(0,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
+
+/********************** Function usleep ************************************/
+
+#ifdef L_usleep
+#include <sys/time.h>
+void
+usleep(useconds)
+unsigned long useconds;
+{
+ struct timeval timeout;
+ timeout.tv_sec = useconds%1000000L;
+ timeout.tv_usec = useconds/1000000L;
+ select(1, NULL, NULL, NULL, &timeout);
+}
+#endif
+
+/********************** THE END ********************************************/
+
+#endif /* __MSDOS__ */
+#endif