/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #if !__FIRST_ARG_IN_AX__ #ifdef __AS386_16__ #ifdef __MSDOS__ #include #include #include int errno; #ifdef L_dos_start static char * argdef[2] = { "C" }; char ** __argv =argdef; char ** environ =argdef+1; int __argc =1; void (*__cleanup)() = 0; #asm .data export ___envseg ___envseg: .word 0 export ___psp ___psp: .word 0 .text export _exit export __exit _exit: ! exit(rv) function mov bx,sp push [bx+2] ! Copy the `rv` for the exit fuctions. 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: inc sp inc sp __exit: ! _exit(rv) mov bx,sp mov ax,[bx+2] mov ah,#$4c int #$21 dos_1_exit: int #$20 .text export ___cstartup ! Crt0 startup ___cstartup: mov ax,#$3000 ! Get DOS version int $21 cmp al,#2 ! DOS 2+ is Ok jb dos_1_exit mov dx,cs ! Current CS add dx,#__segoff ! This var generated by the linker mov ds,dx ! Correct DS mov [___psp],es ! PSP segment seg es mov ax,[$2c] mov [___envseg],ax ! Enviroment Segment ! Now need to free some RAM seg es mov bx,[2] ! Top of Ram mov ax,ds add ax,#4096 ! Top of 64k data seg jc use_tor ! Oops, wrapped cmp ax,bx jnc use_tor ! Bigger than tor mov bx,ax use_tor: mov ax,cs ! Work out how big the memseg is needed sub bx,ax mov ah,#$4A ! Set it int $21 jnc set_stack ! Good. ! Ooops, problem.. ! BX is now how big it can be so set that. ! FIXME should check for BSS v Stack overlap mov ah,#$4A int $21 set_stack: ! Now set SS to the same as DS sub bx,#__segoff ! And SP to the top of available memory. mov cl,#4 shl bx,cl sub bx,#2 mov ss,dx mov sp,bx zap_bss: ! Clear the BSS mov es,dx ! ES now data seg mov di,#__edata mov cx,#__end sub cx,di xor ax,ax cld rep stosb call ___mkargv ! Fetch the arguments and enviroment push [_environ] push [___argv] push [___argc] mov si,#auto_start ! Pointer to first autostart function auto_run: call [si] ! Call the function 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. push ax ! At the end the last called was main() push it`s call _exit ! return val and call exit(); bad_exit: jmp bad_exit ! Exit returned !! loc 2 .word _main ! Segment 2 is the trailing pointers, main and the .word call_exit ! routine to call exit. data_start: .text #endasm __E_nosys() { #asm .text export sys_call5 export sys_call4 export sys_call3 export sys_call2 export sys_call1 export sys_call0 sys_call5: ! Trap the unemulated Linux86 syscalls sys_call4: sys_call3: sys_call2: sys_call1: sys_call0: #endasm errno = ENOSYS; return -1; } #endif #ifdef L___mkargv extern char ** environ; extern char ** __argv; extern int __argc; __mkargv() { int length, i, argc=1, s=0; char *ptr, *p; __set_es(__psp); /* Pointer to the args */ length = __peek_es(0x80); /* Length of cmd line */ if( length > 0 ) { ptr = (char*) sbrk(length+1); /* Allocate some space */ for(i=0; i= 'a' && ch <= 'z' ) || ( ch >= '0' && ch <= '9' ) || ch == ':' || ch == '%' || ch == '-' || ch == '$' ) ; else if( ch >= 'A' && ch <= 'Z' ) ch = ch-'A'+'a'; else if( ch == '.' && dot == 0 ) dot = 1; else if( ch == '/' || ch == '\\' ) { dot = 0; ch = '\\'; } else ch = '_'; *p++ = ch; } *p++ = '\0'; return str; } #endif #ifdef L_dos_read int read(fd, ptr, len) int fd; char *ptr; unsigned len; { #asm mov bx,sp mov cx,[bx+6] mov dx,[bx+4] mov bx,[bx+2] mov ah,#$3f int #$21 jnc readok mov ax,#-1 readok: #endasm } #endif #ifdef L_dos_write int write(fd, ptr, len) int fd; char *ptr; unsigned len; { #asm mov bx,sp mov cx,[bx+6] mov dx,[bx+4] mov bx,[bx+2] mov ah,#$40 int #$21 jnc writeok mov ax,#-1 writeok: #endasm } #endif #ifdef L_dos_open int open(fname, type, cmode) char * fname; int type; int cmode; { register char * nname = __fconv(fname); int creat_mode = 0; int rv; if( (cmode & 0222) == 0 ) creat_mode = 1; /* BzzzT. Assume these flags both mean the merge of them */ /* BzzzT. Also ignore O_EXCL */ if( type & (O_TRUNC|O_CREAT) ) rv = __dos_creat(nname, creat_mode); else /* Warn, this assumes the standard vals for O_RDWR, O_RDONLY, O_WRONLY */ rv = __dos_open(nname, type&O_ACCMODE); if( rv < 0 ) errno=ENOENT; return rv; } __dos_open(fname, mode) { #asm mov bx,sp mov dx,[bx+2] ;ds:dx points to source string mov al,[bx+4] ;access code mov ah,#$3d ;ask for a open int #$21 jnc openok ;return handle if no error mov ax,#-1 ;return -1 if error openok: #endasm } __dos_creat(fname) char * fname; { #asm mov bx,sp mov dx,[bx+2] ;ds:dx points to source string xor cx,cx ;normal attributes mov ah,#$3c ;ask for a create int #$21 jnc creok ;return handle if no error mov ax,#-1 ;return -1 if error creok: #endasm } #endif #ifdef L_dos_close close(fd) { #asm mov bx,sp mov bx,[bx+2] ;file handle mov ah,#$3e ;ask for a close int #$21 mov ax,0 ;return 0 if no error jnc closeok mov ax,#-1 ;return -1 if error closeok: #endasm } #endif #ifdef L_dos_unlink unlink(fname) char * fname; { #asm mov bx,sp push [bx+2] call ___fconv inc sp inc sp mov dx,ax ;ds:dx points to source string mov ah,#$41 ;ask for a unlink int #$21 mov ax,0 ;assume no errors jnc unlok mov ax,#-1 ;return -1 if error unlok: #endasm } #endif #ifdef L_dos_lseek long lseek(fd, offset, mode) int fd, mode; long offset; { #asm mov bx,sp mov al,[bx+8] ;mode of seek (0 to 2) mov dx,[bx+4] ;cx:dx is long offset mov cx,[bx+6] mov bx,[bx+2] ;file handle mov ah,#$42 int #$21 ;do the lseek jnc seekok mov ax,#-1 ;return -1 if error mov dx,ax seekok: #endasm } #endif #ifdef L_dos_segalloc unsigned int __segalloc(paracount) unsigned int paracount; { #asm mov bx,sp mov bx,[bx+2] mov ah,#$48 int $21 jnc ok mov ax,#0 ok: #endasm } #endif #ifdef L_dos_segfree unsigned int __segfree(segno) unsigned int segno; { #asm push es mov bx,sp mov es,[bx+4] mov ah,#$49 int $21 jc err mov ax,#0 err: pop es #endasm } #endif #ifdef L_dos_setvect void __setvect(i,j) int i; long j; { #asm mov bx,sp mov ax,[bx+2] mov dx,[bx+4] mov bx,[bx+6] push ds test bx,bx jnz got_seg mov bx,cs got_seg: mov ds,bx mov ah,#$25 int $21 pop ds #endasm } #endif #ifdef L_dos_getvect long __getvect(vecno) int vecno; { #asm mov bx,sp mov ax,[bx+2] mov ah,#$35 push es int #$21 mov dx,es mov ax,bx pop es #endasm } #endif #ifdef L_dos_getmod int __dos_getmod(fname) { #asm #if __FIRST_ARG_IN_AX__ mov dx,ax #else mov bx,sp mov dx,[bx+2] #endif mov ax,#$4300 int #$21 jnc statok mov cx,#-1 statok: mov ax,cx #endasm } #endif #ifdef L_dos_stat int __dos_stat(fname, dtaptr) { #asm mov bx,sp #if __FIRST_ARG_IN_AX__ mov cx,ax mov dx,[bx+2] #else mov dx,[bx+4] #endif mov ah,#$1A ; Set DTA to requested int #$21 #if __FIRST_ARG_IN_AX__ mov ax,cx #else mov dx,[bx+2] #endif mov ax,#$4300 ; Locate the file int #$21 jc nonesuch mov ax,#$4e00 ; Get all the available information. int #$21 jc nonesuch xor ax,ax ret nonesuch: mov ax,#2 mov _errno,ax mov ax,#-1 #endasm } #endif #ifdef L_dos_isatty isatty(fd) int fd; { #asm mov bx,sp mov bx,[bx+2] mov ah,#$44 mov al,#0 int #$21 xor ax,ax test dx,#$80 jz not_tty inc ax not_tty: #endasm } #endif #endif /* __MSDOS__ */ #endif /* __AS386_16__ */ #endif /* !__FIRST_ARG_IN_AX__ */ /* # Name No Args Flag, comment CHDIR 12 1 TIME 13 1 * No long return val, arg _must_ exist. 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 3 * Need more args & no ELKS UMOUNT 22 1 . No ELKS SETUID 23 1 GETUID 24 1 * This gets both uid and euid STIME 25 2 . No ELKS should be 1 LONG arg PTRACE 26 X + ALARM 27 2 ? No unused return. FSTAT 28 2 PAUSE 29 0 UTIME 30 2 STTY 31 2 . ELKS ain't got this and it'll probably change GTTY 32 2 . ELKS ain't got this and it'll probably change ACCESS 33 2 NICE 34 1 FTIME 35 1 . ELKS ain't got this. SYNC 36 0 KILL 37 2 RENAME 38 2 MKDIR 39 2 RMDIR 40 1 DUP 41 X - Using nasty fcntl function PIPE 42 1 TIMES 43 1 PROF 44 X + SETGID 46 1 GETGID 47 1 * This gets both gid and egid SIGNAL 48 2 + ACCT 51 X + PLOCK 53 X + IOCTL 54 3 FCNTL 55 3 EXEC 59 2 ? UMASK 60 1 CHROOT 61 1 SIGACTION 71 X SIGSUSPEND 72 X SIGPENDING 73 X SIGPROCMASK 74 X SIGRETURN 75 X REBOOT 76 3 . No ELKS and the magic number will be diff. */