diff options
author | Robert de Bath <rdebath@poboxes.com> | 1997-02-25 20:42:19 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:38:07 +0200 |
commit | 4c36e9a0c125ccfff37aa440dab2cf58c4152fff (patch) | |
tree | a5d9c84ba2661029ddb2223dacd50529a361c3d5 /libc/i386sys | |
parent | f8de35da65c5d93bb733073cf40da154bc1c0748 (diff) | |
parent | 9696d7b0e1f3a1b0f5fd4a0428eb75afe8ad4ed6 (diff) | |
download | dev86-4c36e9a0c125ccfff37aa440dab2cf58c4152fff.tar.gz |
Import Dev86src-0.0.11.tar.gzv0.0.11
Diffstat (limited to 'libc/i386sys')
-rw-r--r-- | libc/i386sys/Config | 1 | ||||
-rw-r--r-- | libc/i386sys/Makefile | 52 | ||||
-rw-r--r-- | libc/i386sys/dirent.c | 106 | ||||
-rw-r--r-- | libc/i386sys/exec.c | 292 | ||||
-rw-r--r-- | libc/i386sys/mksyscall | 143 | ||||
-rw-r--r-- | libc/i386sys/signal.c | 99 | ||||
-rw-r--r-- | libc/i386sys/syscall.dat | 155 | ||||
-rw-r--r-- | libc/i386sys/syslibc.c | 255 |
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 |