summaryrefslogtreecommitdiff
path: root/doselks
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-11-03 22:33:35 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:33:35 +0200
commitc218c617b5be443b7968308506969ad2b726d73c (patch)
tree0051f396af56133d24fcf2ab757fabc78c1a09bf /doselks
parent0936b9aeab611665645a4e6bafaded7ca76dd189 (diff)
parent0d2fbe9b1bd284ce2cad55be17e8f2c896031a25 (diff)
downloaddev86-c218c617b5be443b7968308506969ad2b726d73c.tar.gz
Import Dev86src-0.0.8.tar.gzv0.0.8
Diffstat (limited to 'doselks')
-rw-r--r--doselks/Makefile41
-rw-r--r--doselks/coroutine.c120
-rw-r--r--doselks/doselks.c302
-rw-r--r--doselks/doselks.h111
-rw-r--r--doselks/syscalls.c498
-rw-r--r--doselks/syscalls.h59
6 files changed, 1131 insertions, 0 deletions
diff --git a/doselks/Makefile b/doselks/Makefile
new file mode 100644
index 0000000..de3dd55
--- /dev/null
+++ b/doselks/Makefile
@@ -0,0 +1,41 @@
+
+CC=bcc
+CFLAGS=-Md
+LDFLAGS=-Md -s
+
+DISTFILES=Makefile syscalls.h doselks.h coroutine.c doselks.c syscalls.c
+
+# NB coroutine.o first then we can find it easily for breakpoints in CV.EXE
+OBJ=coroutine.o doselks.o syscalls.o
+
+all: doselks.com
+
+install:
+ # Err, Ok, but where do I install a dos program ?
+
+doselks.com: $(OBJ)
+ $(CC) $(LDFLAGS) -o doselks.com $(OBJ)
+
+syscalls.o: call_tab.v
+$(OBJ): doselks.h
+
+call_tab.v: dummy
+ -cp -p ../libc/syscall/call_tab.v . 2>/dev/null
+ -cp -p ../libc/syscall/defn_tab.v . 2>/dev/null
+
+distribution:
+ tar czf /tmp/doselks.tar.gz $(DISTFILES)
+
+dummy:
+
+clean:
+ rm -f $(OBJ) doselks.com
+
+realclean:
+ rm -f call_tab.v defn_tab.v
+ rm -f $(OBJ) doselks.com
+
+VVV=xx
+$(VVV).o: $(VVV).c
+ $(CC) $(CFLAGS) -A-l -A$(VVV).lst -c $(VVV).c
+
diff --git a/doselks/coroutine.c b/doselks/coroutine.c
new file mode 100644
index 0000000..259b7c1
--- /dev/null
+++ b/doselks/coroutine.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include "doselks.h"
+
+int in_process = 0;
+int intr_pending = 0;
+unsigned int current_ds, current_stack;
+struct process * proc;
+
+/***************************************************************************
+ * These two routines to make doselks and the user program into co-routines.
+ *
+ * The Server calls run_cpu which runs the client.
+ * The client then does an int $80 which calls elks_int.
+ * Elks_int then returns to the caller of run_cpu.
+ *
+ * The return value is the value of AX when the int $80 occured.
+ * On return ES is set to the DS of the client program.
+ *
+ * The instruction times are for the 286
+ *
+ * If we were using a 486 then using mov's would be faster on the 286 they
+ * are the same speed but push/pop is smaller.
+ */
+
+#asm
+ .data
+bx_temp: ! Tempoary storage for BX.
+ .word 0
+ .text ! The is where we store the current_ds in the _TEXT_ segment
+cs_current_ds: ! for the elks_int routine
+ .word 0
+#endasm
+
+unsigned int run_cpu()
+{
+#asm
+ mov ax,ds ; 2
+ seg cs ! Store ds for return
+ mov [cs_current_ds],ax ; 5
+
+ cli ! We`re messing! ; 3
+ test [_intr_pending],#$FFFF ! Last chance ...
+ jz skp
+ sti
+ xor ax,ax
+ ret
+skp:
+ push bp ; 3
+ push si ; 3
+ push di ; 3
+ mov [_current_stack],sp ; 5
+ mov ax,#1 ; 2
+ mov [_in_process],ax ; 5
+ mov sp,[_proc] ; 5
+ pop ax ! pppop ; 5
+ pop [bx_temp] ; 5
+ pop cx ; 5
+ pop dx ; 5
+ pop di ; 5
+ pop si ; 5
+ pop bp ; 5
+ pop es ; 5
+ mov bx,sp ! Switch to client stack ; 2
+ mov ss,[bx+8] ! SS ; 5
+ mov sp,[bx+10] ! SP ; 5
+ push [bx+6] ! flags ; 5
+ push [bx+4] ! CS ; 5
+ push [bx+2] ! PC ; 5
+ push [bx+0] ! DS ; 5
+ mov bx,[bx_temp] ; 5
+ pop ds ; 5
+ iret ; 17
+#endasm
+}
+
+unsigned int elks_int()
+{
+#asm
+.text
+ cli ; 3
+ push ds ; 3
+ push cs ; 3
+ pop ds ; 5
+ mov ds,[cs_current_ds] ; 5
+ mov [bx_temp],bx ; 3
+ mov bx,[_proc] ; 5
+ add bx,#16 ; 2
+ pop [bx+0] ! DS ; 5
+ pop [bx+2] ! PC ; 5
+ pop [bx+4] ! CS ; 5
+ pop [bx+6] ! flags ; 5
+ mov [bx+8],ss ! SS ; 3
+ mov [bx+10],sp ! SP ; 3
+
+ mov sp,bx ! Ready for pppppush ; 2
+ mov bx,ds ; 2
+ mov ss,bx ; 2
+
+ push es ! wheeee ; 3
+ push bp ; 3
+ push si ; 3
+ push di ; 3
+ push dx ; 3
+ push cx ; 3
+ push [bx_temp] ; 5
+ push ax ! This is the return value, handy ; 3
+
+ mov sp,[_current_stack] ; 5
+ mov bx,#1 ; 2
+ mov [_in_process],bx ; 5
+ sti ! Finished F**** around with the stack ; 2
+
+ mov bx,[_proc] ; 5
+ mov es,[bx+16] ! Set ES to the client`s DS ; 5
+ pop di ; 5
+ pop si ; 5
+ pop bp ; 5
+#endasm
+}
+
diff --git a/doselks/doselks.c b/doselks/doselks.c
new file mode 100644
index 0000000..3056e19
--- /dev/null
+++ b/doselks/doselks.c
@@ -0,0 +1,302 @@
+#include <stdio.h>
+#include "doselks.h"
+
+#define DEBUGGER
+
+void build_stack(/* char ** argv, char ** envp */);
+
+long elks_int_orig;
+union REGS regs;
+int process_running;
+int exit_code = 255;
+
+main(argc, argv, envp)
+int argc;
+char ** argv;
+char ** envp;
+{
+ int rv;
+
+ current_ds = __get_ds();
+ if( argc <= 1 )
+ {
+ printf("Usage: %s <8086_exe> [args]\n", argv[0]);
+ exit(exit_code);
+ }
+
+ proc = calloc(sizeof(struct process), 1);
+ if( proc == 0 )
+ printf("Unable to allocate memory for executable\n");
+ else if( (rv = loadexe(argv[1])) >= 0 )
+ {
+ proc->pid = 1;
+ proc->ppid = 1;
+ proc->pgrp = 1;
+ proc->umask = 022;
+ proc->next = proc;
+
+ build_stack(argv+1, envp);
+
+ elks_int_orig = __getvect(ELKSINT);
+ __setvect(ELKSINT, (long)elks_int);
+
+#ifndef MAKEME
+ run_executable();
+#else
+ dump_core();
+#endif
+
+ __setvect(ELKSINT, elks_int_orig);
+ }
+ else
+ {
+ if( rv == -ENOMEM )
+ printf("Unable to allocate memory for executable\n");
+ else
+ printf("Cannot execute %s\n", argv[1]);
+ }
+ return(exit_code);
+}
+
+int loadexe(fname)
+char * fname;
+{
+ char bbuf[1024];
+ long size;
+ unsigned int tsize, dsize;
+ struct elks_exec_hdr mh;
+ int i;
+ int fd = -1;
+ int err = ENOEXEC;
+
+ proc->text_seg = 0;
+ proc->data_seg = 0;
+
+ if( ( fd = open(fname, O_RDONLY|O_BINARY) ) < 0 )
+ goto no_exec;
+
+ /* Load the elks binary image and set it up in a suitable
+ * segment. Load CS and DS/SS according to image type.
+ */
+
+ if( read(fd, &mh,sizeof(mh))!=sizeof(mh)
+ || mh.hlen!=EXEC_HEADER_SIZE
+ || (mh.type!=ELKS_COMBID&&mh.type!=ELKS_SPLITID)
+ )
+ goto no_exec;
+
+ if(mh.type==ELKS_COMBID)
+ {
+ tsize = 0;
+ dsize = ((mh.tseg+mh.chmem + 0xF)>>4);
+ }
+ else
+ {
+ tsize = ((mh.tseg+0xF) >> 4);
+ dsize = ((mh.chmem+0xF) >> 4);
+ }
+ if(tsize)
+ {
+ if( (proc->text_seg = seg_allocate(tsize)) == 0)
+ goto no_mem;
+
+ proc->cs = proc->text_seg->seg;
+ }
+
+ if( (proc->data_seg = seg_allocate(dsize)) == 0 )
+ goto no_mem;
+
+ proc->ds = proc->data_seg->seg;
+ if(proc->text_seg == 0) proc->cs = proc->ds;
+
+#ifdef DEBUGGER
+ fprintf(stderr,"Executable - %s. tseg=0x%04lx dseg=0x%04lx bss=0x%04lx chmem=0x%04lx\n",
+ mh.type==ELKS_COMBID?"(impure)":"Sep I/D",
+ mh.tseg,mh.dseg,mh.bseg,mh.chmem);
+#endif
+
+ if(proc->text_seg)
+ {
+ for(size=0; size<mh.tseg; )
+ {
+ i = sizeof(bbuf); if( i>mh.tseg-size ) i=mh.tseg-size;
+
+ if(read(fd,bbuf,i)!=i)
+ goto no_exec;
+
+ __movedata(current_ds, (unsigned)bbuf, proc->cs, (int)size, i);
+ size += i;
+ }
+ }
+ else
+ mh.dseg += mh.tseg;
+
+ for(size=0; size<mh.dseg; )
+ {
+ i = sizeof(bbuf); if( i>mh.dseg-size ) i=mh.dseg-size;
+
+ if(read(fd,bbuf,i)!=i)
+ goto no_exec;
+
+ __movedata(current_ds, (unsigned)bbuf, proc->ds, (int)size, i);
+ size += i;
+ }
+
+ close(fd);
+
+ /* Zap the bss */
+ memset(bbuf, '\0', 1024);
+ mh.dseg += mh.bseg;
+ for(; size<mh.dseg; )
+ {
+ i = sizeof(bbuf); if( i>mh.dseg-size ) i=mh.dseg-size;
+
+ __movedata(current_ds, (unsigned)bbuf, proc->ds, (int)size, i);
+ size += i;
+ }
+
+ /*
+ * Load the VM86 registers
+ */
+
+ proc->ss=proc->ds;
+ proc->es=0; /* This will be preserved */
+ proc->sp=mh.chmem; /* Args stacked later */
+ proc->pc=0; /* Run from 0 */
+
+ /*
+ * Loaded
+ */
+
+ return 0;
+no_mem:;
+ err = ENOMEM;
+no_exec:;
+ seg_free(proc->text_seg);
+ seg_free(proc->data_seg);
+ if( fd > 0 ) close(fd);
+ return -err;
+}
+
+void
+build_stack(argv, envp)
+char ** argv; char ** envp;
+{
+ char buffer[1024];
+
+ char **p;
+ int argv_len=0, argv_count=0;
+ int envp_len=0, envp_count=0;
+ int stack_bytes;
+ unsigned short * pip;
+ char * pcp;
+
+ /* How much space for argv */
+ if(argv) for(p=argv; *p; p++)
+ {
+ argv_count++; argv_len += strlen(*p)+1;
+ }
+
+ /* How much space for envp */
+ if(envp) for(p=envp; *p; 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;
+
+ if( stack_bytes > sizeof(buffer)-2 )
+ {
+ printf("Environment too large\n");
+ exit(exit_code);
+ }
+ /* Allocate it */
+ proc->sp -= stack_bytes;
+
+#ifdef DEBUGGER
+ printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n",
+ argv_count, argv_len, envp_count, envp_len, stack_bytes);
+#endif
+
+ /* Now build the data */
+ pip=(unsigned short *) buffer;
+ pcp=buffer+sizeof(unsigned short *)*(1+argv_count+1+envp_count+1);
+
+ *pip++ = argv_count;
+ for(p=argv; *p; p++)
+ {
+ *pip++ = (pcp-buffer)+proc->sp;
+ strcpy(pcp, *p);
+ pcp += strlen(*p)+1;
+ }
+ *pip++ = 0;
+
+ for(p=envp; *p; p++)
+ {
+ *pip++ = (pcp-buffer)+proc->sp;
+ strcpy(pcp, *p);
+ pcp += strlen(*p)+1;
+ }
+ *pip++ = 0;
+ __movedata(current_ds, (unsigned)buffer,
+ proc->ds, proc->sp, stack_bytes);
+}
+
+/***************************************************************************/
+
+dump_core()
+{
+ char bbuf[1024];
+ int i, fd;
+ unsigned destseg;
+ printf("Not dumping core\n");
+
+/*
+ if( ( fd = open("core", O_WRONLY|O_BINARY|O_CREAT|O_TRUNC) ) < 0 )
+ {
+ return -1;
+ }
+
+ destseg = proc->memory;
+
+ for(i=0; i<(proc->memsize+63)/64; i++)
+ {
+ __movedata( destseg+i*64, 0, current_ds, (unsigned)bbuf, 1024);
+ if( write(fd, bbuf, 1024) < 0 )
+ printf("FAIL 7\n");
+ }
+
+ close(fd);
+*/
+}
+
+/***************************************************************************/
+
+seg_allocate(size)
+{
+ struct segment *nptr = calloc(sizeof(struct segment),1);
+
+ if( nptr == 0 ) return 0;
+
+ nptr->ref_count = 1;
+ nptr->size = size;
+ nptr->seg = __segalloc(size);
+ if( nptr->seg == 0 ) { free(nptr); return 0; }
+
+ return nptr;
+}
+
+seg_free(ptr)
+struct segment * ptr;
+{
+ if(ptr == 0) return;
+ if( --ptr->ref_count > 0 )
+ return;
+ __segfree(ptr->seg);
+ free(ptr);
+}
diff --git a/doselks/doselks.h b/doselks/doselks.h
new file mode 100644
index 0000000..6ea67eb
--- /dev/null
+++ b/doselks/doselks.h
@@ -0,0 +1,111 @@
+
+#include <ctype.h>
+#include <dos.h>
+#include <malloc.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+
+/* Function return vals */
+
+extern unsigned int elks_int();
+extern unsigned int run_cpu();
+
+/* Elks binary formats */
+
+#define EXEC_HEADER_SIZE 32
+
+struct elks_exec_hdr
+{
+ unsigned long type;
+#define ELKS_COMBID 0x04100301L
+#define ELKS_SPLITID 0x04200301L
+ unsigned long hlen;
+ unsigned long tseg;
+ unsigned long dseg;
+ unsigned long bseg;
+ unsigned long unused;
+ unsigned long chmem;
+ unsigned long unused2;
+};
+
+/* Elks cpu structure. */
+
+struct fd_ref {
+ int ftype;
+ union {
+ int i;
+ FILE * f;
+ } fd;
+} ;
+
+struct segment {
+ unsigned int seg;
+ unsigned int size;
+ int ref_count;
+};
+
+struct process
+{
+ unsigned int ax; /* NOTE The order of this is _closely_ related to */
+ unsigned int bx; /* the coroutine assembler */
+ unsigned int cx;
+ unsigned int dx;
+ unsigned int di;
+ unsigned int si;
+ unsigned int bp;
+ unsigned int es;
+
+ unsigned int ds; /* start +16 +0 */
+ unsigned int pc; /* start +16 +2 */
+ unsigned int cs; /* start +16 +4 */
+ unsigned int flgs; /* start +16 +6 */
+ unsigned int ss; /* start +16 +8 */
+ unsigned int sp; /* start +16 +10 */
+
+ /* From here down only accessed from C */
+ int pending_op;
+ struct process * next;
+
+ struct segment * text_seg;
+ struct segment * data_seg;
+
+ int pid;
+ int ppid;
+ int pgrp;
+ int umask;
+ int uid;
+ int gid;
+ int euid;
+ int egid;
+ int suid;
+ int sgid;
+ long ignmask, trpmask;
+ int sigtrap;
+
+ struct fd_ref fds[20];
+
+ struct rusage ruse;
+};
+
+extern struct process * proc;
+extern unsigned int current_ds, current_stack;
+extern int in_process;
+extern int process_running;
+extern int intr_pending;
+
+/* Elks syscall interface */
+
+#define ELKSINT 0x80
+typedef int (*Scallp)( /* int, int, int */ );
+extern Scallp syscalltab[];
+
+/******************************************************************************/
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
diff --git a/doselks/syscalls.c b/doselks/syscalls.c
new file mode 100644
index 0000000..a4f3e69
--- /dev/null
+++ b/doselks/syscalls.c
@@ -0,0 +1,498 @@
+#include <stdio.h>
+#include "doselks.h"
+#include "syscalls.h"
+
+/***************************************************************************/
+
+/* Need to use stdio for CR<->NL translation */
+#define MAX_FD 20
+FILE * tty_file[MAX_FD] = {stdin, stdout, stderr};
+
+int nextpid = 2;
+int proc_one = 1;
+
+/***************************************************************************/
+
+#define sys_exit elks_exit
+elks_exit(wait_stat)
+int wait_stat;
+{
+ struct process * cur;
+ int x;
+
+ if(wait_stat & 0x80) dump_core();
+
+ /* save wait_stat */
+ proc->ax = wait_stat;
+ if(proc->pid == 1) proc_one = 0;
+
+ process_running--;
+ seg_free(proc->text_seg);
+ seg_free(proc->data_seg);
+
+ for(cur=proc->next; cur!=proc; cur=cur->next)
+ if(cur->ppid == proc->pid)
+ cur->ppid = 1;
+
+ return 0;
+}
+
+#define sys_fork elks_fork
+elks_fork(bx, cx, dx)
+int bx, cx, dx;
+{
+ unsigned int size, i;
+ struct process * newproc;
+
+ if(nextpid<0) return -EINVAL; /* TODO: max 32k forks */
+
+ newproc = calloc(sizeof(struct process), 1);
+ if( newproc == 0 ) return -ENOMEM;
+
+ proc->pending_op = 0;
+ *newproc = *proc;
+ newproc->ppid = newproc->pid;
+ newproc->data_seg = seg_allocate(proc->data_seg->size);
+
+ if( newproc->data_seg == 0 )
+ {
+ free(newproc);
+ return -ENOMEM;
+ }
+ newproc->text_seg->ref_count++;
+
+ newproc->cs = newproc->text_seg->seg;
+ newproc->ds = newproc->data_seg->seg;
+ newproc->ss = newproc->ds;
+
+ newproc->pid = nextpid++;
+
+ /* Duplicate memory */
+ for(i=0; i<newproc->data_seg->size; i+=size )
+ {
+ size = 0xFFF;
+ if(size > newproc->data_seg->size-i) size = newproc->data_seg->size-i;
+
+ __movedata(proc->ds, i*16, newproc->ds, i*16, size*16);
+ }
+
+ proc->ax = newproc->pid;
+ newproc->ax = 0;
+ proc->next = newproc;
+ process_running++;
+ /* proc = newproc; */
+
+ return newproc->pid;
+}
+
+struct process *
+get_zombie(ppid, pid)
+int ppid, pid;
+{
+ struct process * prev, * cur, *running=0;
+ /* Process group, not defined */
+ if( pid < -1 ) return 0;
+ if( pid == 0 ) pid = -1;
+
+ for(prev=proc, cur=proc->next; cur!=proc; prev=cur, cur=cur->next)
+ {
+ if(cur->ppid == ppid && (pid == -1 || cur->pid == pid))
+ {
+ if(cur->pending_op != 1)
+ {
+ running = cur;
+ continue;
+ }
+ prev->next = cur->next;
+ cur->next = 0;
+ return cur;
+ }
+ }
+ return running;
+}
+
+#define sys_wait4 elks_wait4
+elks_wait4(bx, cx, dx, di, si)
+int bx, cx, dx, di, si;
+{
+ struct process * cur;
+ int cpid;
+
+ cur = get_zombie(proc->pid, bx);
+ if( cur == 0 ) return -ECHILD;
+
+ if( cur->pending_op != 1)
+ {
+ if( dx & WNOHANG )
+ return 0;
+ else
+ return -EINTR;
+ }
+
+ cpid = cur->pid;
+ if( cx ) __doke_es(cx, cur->ax);
+ if( di )
+ __movedata(current_ds, (unsigned)&(cur->ruse),
+ proc->ds, di, sizeof(struct rusage));
+ free(cur);
+ return cpid;
+}
+
+#define sys_exec elks_exec
+int elks_exec(bx, cx, dx)
+int bx, cx, dx;
+{
+ struct process oldproc;
+ char fname[128];
+ int ax;
+
+ oldproc = *proc;
+ __strnget_es(fname, bx, sizeof(fname)-1);
+ fname[sizeof(fname)-1] = '\0';
+
+ if( (ax=loadexe(fname)) != 0 )
+ {
+ *proc = oldproc;
+ return ax;
+ }
+
+ __movedata(oldproc.ds, cx, proc->ds, proc->sp-dx, dx);
+
+ /*
+ Fudge pointers.
+ */
+ proc->sp -= dx;
+
+ /* Args */
+ ax = proc->sp + 2;
+ __set_es(proc->ds);
+ while(__deek_es(ax) != 0 )
+ __doke_es(ax, __deek_es(ax)-dx), ax+=2;
+
+ /* env */
+ ax+=2;
+ while(__deek_es(ax) != 0 )
+ __doke_es(ax, __deek_es(ax)-dx), ax+=2;
+
+ seg_free(oldproc.text_seg);
+ seg_free(oldproc.data_seg);
+ return 0;
+}
+
+#define sys_read elks_read
+int elks_read(bx, cx, dx)
+int bx, cx, dx;
+{
+ register int ch, rv=0;
+ if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF;
+ do
+ {
+ ch = fgetc(tty_file[bx]);
+ if( ch == EOF ) break;
+ __poke_es(cx++, ch);
+ rv++;
+ }
+ while(--dx > 0 && stdio_pending(tty_file[bx]));
+
+ return rv;
+}
+
+#define sys_write elks_write
+int elks_write(bx, cx, dx)
+unsigned int bx, cx, dx;
+{
+ char ch[2];
+ register unsigned int i;
+ if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF;
+
+ for(i=dx; i>0; i--)
+ {
+ if( fputc(__peek_es(cx++), tty_file[bx]) == EOF )
+ return -1;
+ }
+ fflush(tty_file[bx]);
+ return dx;
+}
+
+#define sys_open elks_open
+int elks_open(bx, cx, dx)
+{
+ char fname[128];
+ int i;
+ char *mode = "";
+
+ __strnget_es(fname, bx, sizeof(fname)-1);
+ fname[sizeof(fname)-1] = '\0';
+
+ for(i=0; i<MAX_FD; i++)
+ {
+ if(tty_file[i] == 0) break;
+ }
+ if( i >= MAX_FD ) return -EMFILE;
+
+ /* Translate the mode; more or less */
+ switch(cx&O_ACCMODE)
+ {
+ case O_RDONLY:
+ mode="r";
+ break;
+ case O_WRONLY:
+ if( cx&O_APPEND ) mode="a";
+ else if( cx&O_TRUNC ) mode="w";
+ else mode="r+";
+ break;
+ case O_RDWR:
+ if( cx&O_APPEND ) mode="a+";
+ else if( cx&O_TRUNC ) mode="w+";
+ else mode="r+";
+ break;
+ }
+
+ if( ( tty_file[i] = fopen(fname, mode) ) == 0 )
+ {
+ if( errno == 0 ) return -ENOENT;
+ return -errno;
+ }
+ return i;
+}
+
+#define sys_close elks_close
+int elks_close(bx, cx, dx)
+{
+ if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF;
+ fclose(tty_file[bx]);
+ tty_file[bx] = 0;
+ return 0;
+}
+
+#define sys_lseek elks_lseek
+int elks_lseek(bx, cx, dx)
+{
+ long l;
+ if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF;
+
+ __movedata(proc->ds, cx, current_ds, &l, 4);
+
+ if( fseek(tty_file[bx], l, dx) < 0 ) return -ESPIPE;
+
+ l = ftell(tty_file[bx]);
+ __movedata(current_ds, &l, proc->ds, cx, 4);
+ return 0;
+}
+
+#define sys_brk elks_brk
+int elks_brk(bx, cx, dx)
+{
+ /* For the moment we don't care; libc does enough */
+ return 0;
+}
+
+#define sys_getpid elks_getpid
+int elks_getpid(bx, cx, dx)
+{
+ __doke_es(bx, proc->ppid);
+ return proc->pid;
+}
+
+#define sys_getuid elks_getuid
+int elks_getuid(bx, cx, dx)
+{
+ __doke_es(bx, proc->euid);
+ return proc->uid;
+}
+
+#define sys_getgid elks_getgid
+int elks_getgid(bx, cx, dx)
+{
+ __doke_es(bx, proc->egid);
+ return proc->gid;
+}
+
+#define sys_setuid elks_setuid
+int elks_setuid(bx, cx, dx)
+{
+ if( proc->euid == 0
+ || proc->uid == bx || proc->euid == bx || proc->suid == bx)
+ {
+ if( proc->euid == 0 )
+ proc->suid = proc->uid = bx;
+ proc->euid = bx;
+ }
+ else
+ return -EPERM;
+}
+
+#define sys_setgid elks_setgid
+int elks_setgid(bx, cx, dx)
+{
+ if( proc->euid == 0
+ || proc->gid == bx || proc->egid == bx || proc->sgid == bx)
+ {
+ if( proc->euid == 0 )
+ proc->sgid = proc->gid = bx;
+ proc->egid = bx;
+ }
+ else
+ return -EPERM;
+}
+
+#define sys_umask elks_umask
+int elks_umask(bx, cx, dx)
+{
+ cx= proc->umask;
+ proc->umask = (bx&0777);
+ return cx;
+}
+
+void sig_trap(signo)
+int signo;
+{
+ proc->sp -= 2;
+ __doke_es(proc->sp, signo);
+ proc->sp -= 2;
+ __doke_es(proc->sp, proc->pc);
+ proc->pc = proc->sigtrap;
+}
+
+#define sys_signal elks_signal
+int elks_signal(bx,cx,dx)
+{
+ int rv;
+ if( bx < 0 || bx >= NSIG ) return -EINVAL;
+ if( bx == SIGSTOP || bx == SIGKILL ) return 0;
+
+ proc->trpmask &= ~(1L<<bx);
+ proc->ignmask &= ~(1L<<bx);
+
+ if( cx == 0 ) /* Default */;
+ else if( cx == 1 ) proc->ignmask |= (1L<<bx);
+ else
+ {
+ proc->trpmask |= (1L<<bx);
+ proc->sigtrap = cx;
+ }
+
+ return 0;
+}
+
+#define sys_lstat elks_stat
+#define sys_stat elks_stat
+int elks_stat(bx,cx,dx)
+{
+ struct stat ms;
+ char fnamebuf[65];
+ char dtabuf[128]; /* I think this only needs 32 bytes ... but ... */
+ int v;
+ long ttime, tdate;
+
+ __strnget_es(fnamebuf, bx, sizeof(fnamebuf)-1);
+ fnamebuf[64] = '\0';
+
+ v = __dos_stat(fnamebuf, dtabuf);
+ if( v < 0 ) return -ENOENT;
+
+ ms.st_dev= *dtabuf;
+ ms.st_ino= 0;
+ ms.st_mode= ((dtabuf[0x15]&0x1)?0555:0777); /* + File or directory */
+ if (dtabuf[0x15]&0x10)
+ ms.st_mode |= S_IFDIR;
+ else
+ ms.st_mode |= S_IFREG;
+ ms.st_nlink= 1;
+ ms.st_uid= 0;
+ ms.st_gid= 0;
+ ms.st_rdev= 0;
+ ms.st_size= *(long*)(dtabuf+0x1A);
+
+ ttime = *((unsigned short*)(dtabuf+0x16));
+ ttime = ( ttime &0x1F) * 2
+ + ((ttime>>5) &0x2F) * 60
+ + ((ttime>>11) &0x1F) * 3600L;
+
+/* FIXME: This needs a julian day calculator .. */
+ tdate = *((unsigned short*)(dtabuf+0x18));
+ tdate = ((tdate) &0x1F) -32
+ + ((tdate>>5) &0x0F) * 31
+ + ((tdate>>9) &0x7F) * (31*12);
+
+ ms.st_mtime= tdate*86400L + ttime;
+ ms.st_atime= ms.st_mtime;
+ ms.st_ctime= ms.st_mtime;
+
+ /* copy &ms -> es:cx */
+ __movedata(current_ds, &ms, proc->ds, cx, sizeof(struct stat));
+
+ return 0;
+}
+
+/***************************************************************************/
+
+#define sys_enosys elks_enosys
+int elks_enosys(bx, cx, dx)
+int bx, cx, dx;
+{
+ printf("Unimplemented syscall(%d,0x%04x,0x%04x,0x%04x)\n",
+ proc->ax,proc->bx,proc->cx,proc->dx);
+ return -ENOSYS;
+}
+
+#include "defn_tab.v"
+
+Scallp syscalltab[] = {
+#include "call_tab.v"
+ elks_enosys
+};
+
+FILE * error;
+run_executable()
+{
+
+ register unsigned int r_ax;
+ register Scallp ptr;
+ process_running=1;
+
+ error = fopen("errlog", "w");
+
+ do
+ {
+ if( proc->pending_op == 0 )
+ {
+ fprintf(error, "Run %d AX=%-4d proc =%04x IP=%04x...",
+ proc->pid, proc->ax, proc, proc->pc); fflush(error);
+ proc->pending_op = run_cpu();
+ }
+ if( r_ax = proc->pending_op )
+ {
+ if( r_ax >= sizeof(syscalltab)/sizeof(Scallp) )
+ r_ax = 0;
+
+ fprintf(error, "%d: Call_%d(%04x, %04x, %04x) -> ",
+ proc->pid, r_ax, proc->bx, proc->cx, proc->dx);
+ fflush(error);
+
+ if( r_ax == 1 )
+ (void) elks_exit(proc->bx << 8);
+ else
+ {
+ __set_es(proc->ds);
+ if( (proc->ax = (*syscalltab[r_ax])(proc->bx, proc->cx, proc->dx,
+ proc->di, proc->si))
+ != (unsigned) -EINTR )
+ {
+ proc->pending_op = 0;
+ /*
+ fprintf(error, "%d\n", proc->ax);
+ fflush(error);
+ continue;
+ */
+ }
+ }
+ fprintf(error, "%d\n", proc->ax);
+ fflush(error);
+ }
+ intr_pending = 0; /* FIXME: deal with */
+ do { proc = proc->next; } while(proc->pending_op==1 && process_running);
+ }
+ while(process_running);
+}
+
diff --git a/doselks/syscalls.h b/doselks/syscalls.h
new file mode 100644
index 0000000..90c7a99
--- /dev/null
+++ b/doselks/syscalls.h
@@ -0,0 +1,59 @@
+extern int sys_exit __P((int, int, int));
+extern int sys_vfork __P((int, int, int));
+extern int sys_read __P((int, int, int));
+extern int sys_write __P((int, int, int));
+extern int sys_open __P((int, int, int));
+extern int sys_close __P((int, int, int));
+extern int sys_wait __P((int, int, int));
+extern int sys_creat __P((int, int, int));
+extern int sys_link __P((int, int, int));
+extern int sys_unlink __P((int, int, int));
+extern int sys_waitpid __P((int, int, int));
+extern int sys_chdir __P((int, int, int));
+extern int sys_time __P((int, int, int));
+extern int sys_mknod __P((int, int, int));
+extern int sys_chmod __P((int, int, int));
+extern int sys_chown __P((int, int, int));
+extern int sys_brk __P((int, int, int));
+extern int sys_stat __P((int, int, int));
+extern int sys_lseek __P((int, int, int));
+extern int sys_getpid __P((int, int, int));
+extern int sys_mount __P((int, int, int));
+extern int sys_umount __P((int, int, int));
+extern int sys_setuid __P((int, int, int));
+extern int sys_getuid __P((int, int, int));
+extern int sys_stime __P((int, int, int));
+extern int sys_ptrace __P((int, int, int));
+extern int sys_alarm __P((int, int, int));
+extern int sys_fstat __P((int, int, int));
+extern int sys_pause __P((int, int, int));
+extern int sys_utime __P((int, int, int));
+extern int sys_stty __P((int, int, int));
+extern int sys_gtty __P((int, int, int));
+extern int sys_access __P((int, int, int));
+extern int sys_nice __P((int, int, int));
+extern int sys_ftime __P((int, int, int));
+extern int sys_sync __P((int, int, int));
+extern int sys_kill __P((int, int, int));
+extern int sys_rename __P((int, int, int));
+extern int sys_mkdir __P((int, int, int));
+extern int sys_rmdir __P((int, int, int));
+extern int sys_pipe __P((int, int, int));
+extern int sys_times __P((int, int, int));
+extern int sys_prof __P((int, int, int));
+extern int sys_setgid __P((int, int, int));
+extern int sys_getgid __P((int, int, int));
+extern int sys_signal __P((int, int, int));
+extern int sys_acct __P((int, int, int));
+extern int sys_plock __P((int, int, int));
+extern int sys_ioctl __P((int, int, int));
+extern int sys_fcntl __P((int, int, int));
+extern int sys_exec __P((int, int, int));
+extern int sys_umask __P((int, int, int));
+extern int sys_chroot __P((int, int, int));
+extern int sys_sigaction __P((int, int, int));
+extern int sys_sigsuspend __P((int, int, int));
+extern int sys_sigpending __P((int, int, int));
+extern int sys_sigprocmask __P((int, int, int));
+extern int sys_sigreturn __P((int, int, int));
+extern int sys_reboot __P((int, int, int));