diff options
Diffstat (limited to 'libc/msdos/msdos.c')
-rw-r--r-- | libc/msdos/msdos.c | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/libc/msdos/msdos.c b/libc/msdos/msdos.c new file mode 100644 index 0000000..02c35db --- /dev/null +++ b/libc/msdos/msdos.c @@ -0,0 +1,540 @@ +/* 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. + */ + +#if !__FIRST_ARG_IN_AX__ +#ifdef __AS386_16__ +#ifdef __MSDOS__ + +#include <dos.h> +#include <fcntl.h> +#include <errno.h> +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<length; i++) /* Copy it in. */ + { + ptr[i] = __peek_es(0x81+i); + if( ptr[i] != ' ' && s == 0 ) { argc++; s=1; } + if( ptr[i] == ' ' && s == 1 ) s=0; + } + ptr[length]=0; + + p= __argv[0]; + __argv = (char**) sbrk((argc+1)*sizeof(char*)); + __argv[0] = p; /* FIXME: The real command can be found */ + __argc=argc; + + argc=1; s=0; + for(i=0; i<length; i++) + { + if( ptr[i] != ' ' && s == 0 ) { __argv[argc++] = ptr+i; s=1; } + if( ptr[i] == ' ' && s == 1 ) { ptr[i] = '\0'; s=0; } + } + __argv[argc] = 0; + } +} +#endif + +#ifdef L_dos__fconv +/* This function converts filenames from unix like to DOS. */ +char * +__fconv(fname) +char * fname; +{ +static char buf1[66], buf2[66], *str = 0; + register char *p, ch; + int dot = 0; + + if( strcmp("/dev/tty", fname) == 0 ) return "CON:"; + + if( str == buf1 ) str = buf2; else str = buf1; + + p = str; + if( strncmp("/mnt/", fname, 5) == 0 ) + { + strcpy(p, "A:"); p+=2; fname+=4; + } + /* + * POSS: + * open("/name/*", ...); looks for an environ var PATH_name=c:\x\y\z + */ + + while((ch = *fname++) && p < str+65) + { + if( ( ch >= '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_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_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. +*/ + |