1 /* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
2 * This file is part of the Linux-8086 C library and is distributed
3 * under the GNU Library General Public License.
6 #if !__FIRST_ARG_IN_AX__
18 static char * defarg
[2] = { "C" };
19 static char ** def_environ
=defarg
+1;
20 void (*__cleanup
)() = 0;
36 _exit
: ! exit(rv
) function
38 push
[bx
+2] ! Copy the `rv`
for the exit fuctions
.
39 mov bx
,[___cleanup
] ! Call exit
, normally
this is `__do_exit`
41 je no_clean
! But it`s
default is null
55 export ___cstartup
! Crt0 startup
57 mov ax
,#$3000 ! Get DOS version
59 cmp al
,#2 ! DOS 2+ is Ok
62 mov dx
,cs
! Current CS
63 add dx
,#__segoff ! This var generated by the linker
64 mov ds
,dx
! Correct DS
66 mov
[___psp
],es
! PSP segment
69 mov
[___envseg
],ax
! Enviroment Segment
71 ! Now need to free some RAM
73 mov bx
,[2] ! Top of Ram
75 add ax
,#4096 ! Top of 64k data seg
76 jc use_tor
! Oops
, wrapped
78 jnc use_tor
! Bigger than tor
81 mov ax
,cs
! Work out how big the memseg is needed
87 ! BX is now how big it can be so set that
.
88 ! FIXME should check
for BSS v Stack overlap
92 set_stack
: ! Now set SS to the same as DS
93 sub bx
,#__segoff ! And SP to the top of available memory.
100 zap_bss
: ! Clear the BSS
101 mov es
,dx
! ES now data seg
110 push
[_def_environ
] ! Defaults
for when nothing is used
.
116 mov si
,#auto_start ! Pointer to first autostart function
121 call bx
! Call the function
125 jmp auto_run
! And round
for the next
.
127 call_exit
: ! Last item called by above
.
129 push ax
! At the end the last called was
main() push it`s
130 call _exit
! return val
and call
exit();
132 jmp bad_exit
! Exit returned
!!
135 .word _main
! Segment
2 is the trailing pointers
, main
and the
136 .word call_exit
! routine to call exit
.
154 sys_call5
: ! Trap the unemulated Linux86 syscalls
171 loc
1 ! Make sure the pointer is in the correct segment
172 auto_func
: ! Label
for bcc
-M to work
.
173 .word ___mkargv
! Pointer to the autorun function
174 .text
! So the function after is also in the correct seg
.
178 __mkargv(__argc
, __argv
)
182 int length
, i
, argc
=1, s
=0;
183 unsigned char *ptr
, *p
;
184 __set_es(__psp
); /* Pointer to the args */
185 length
= __peek_es(0x80); /* Length of cmd line */
188 ptr
= (char*) sbrk(length
+1); /* Allocate some space */
190 for(i
=0; i
<length
; i
++) /* Copy it in. */
192 ptr
[i
] = __peek_es(0x81+i
);
193 if( ptr
[i
] > ' ' && s
== 0 ) { argc
++; s
=1; }
194 if( ptr
[i
] <= ' ' && s
== 1 ) s
=0;
199 __argv
= (char**) sbrk((argc
+1)*sizeof(char*));
200 __argv
[0] = p
; /* TODO: The real command can be found */
204 * TODO: This needs to understand quoting and wildcards
208 for(i
=0; i
<length
; i
++)
210 if( ptr
[i
] > ' ' && s
== 0 ) { __argv
[argc
++] = ptr
+i
; s
=1; }
211 if( ptr
[i
] <= ' ' && s
== 1 ) { ptr
[i
] = '\0'; s
=0; }
222 loc
1 ! Make sure the pointer is in the correct segment
223 auto_func
: ! Label
for bcc
-M to work
.
224 .word ___mkenvp
! Pointer to the autorun function
225 .text
! So the function after is also in the correct seg
.
231 __mkenvp(__argc
, __argv
, __envp
)
238 * Note must write to __envp argument but not touch __argv or __argc
244 /* This function converts filenames from unix like to DOS. */
249 static char buf1
[66], buf2
[66], *str
= 0;
250 register char *p
, ch
;
253 if( strcmp("/dev/tty", fname
) == 0 ) return "CON:";
255 if( str
== buf1
) str
= buf2
; else str
= buf1
;
258 if( strncmp("/mnt/", fname
, 5) == 0 )
260 strcpy(p
, "A:"); p
+=2; fname
+=4;
264 * open("/name/*", ...); looks for an environ var PATH_name=c:\x\y\z
267 while((ch
= *fname
++) && p
< str
+65)
269 if( ( ch
>= 'a' && ch
<= 'z' )
270 || ( ch
>= '0' && ch
<= '9' )
271 || ch
== ':' || ch
== '%' || ch
== '-' || ch
== '$' )
273 else if( ch
>= 'A' && ch
<= 'Z' )
275 else if( ch
== '.' && dot
== 0 )
277 else if( ch
== '/' || ch
== '\\' )
292 static char errno_xlate
[] = {
293 0, EINVAL
, ENOENT
, ENOENT
, EMFILE
, EACCES
, EBADF
, EFAULT
, ENOMEM
,
294 EFAULT
, ENOMEM
, EINVAL
, EINVAL
, EINVAL
, EINVAL
, ENODEV
, EPERM
, EXDEV
,
295 ENFILE
, EROFS
, ENODEV
, ENXIO
, EINVAL
, EIO
, EINVAL
, ESPIPE
, EIO
, EIO
,
296 EAGAIN
, EIO
, EIO
, EIO
, EBUSY
, EBUSY
, ENODEV
, EFAULT
, ENOLCK
, EFAULT
,
322 extern unsigned _doserrno
;
325 /* No error? No change. */;
326 else if( _doserrno
>= sizeof(errno_xlate
)
327 || errno_xlate
[_doserrno
] == EFAULT
)
328 errno
= 16384+_doserrno
;
330 errno
= errno_xlate
[_doserrno
];
380 open(fname
, type
, cmode
)
385 register char * nname
= __fconv(fname
);
389 static int xlate_mode
[] = {
390 #ifdef OPEN_LIKE_UNIX
396 O_WRONLY
|O_DENYWRITE
,
402 if( (cmode
& 0222) == 0 ) creat_mode
= 1;
404 /* BzzzT. Assume these flags both mean the merge of them */
405 /* BzzzT. Also ignore O_EXCL */
406 if( type
& (O_TRUNC
|O_CREAT
) )
407 rv
= __dos_creat(nname
, creat_mode
);
411 /* If we would open in compatibility mode make it a little more unixy */
412 if( type
& O_DENYMODE
)
413 rv
= __dos_open(nname
, type
&(O_ACCMODE
|O_DENYMODE
|O_SETFD
));
415 rv
= __dos_open(nname
, xlate_mode
[type
&O_ACCMODE
]);
420 __dos_open(fname
, mode
)
424 mov dx
,[bx
+2] ;ds
:dx points to source string
425 mov al
,[bx
+4] ;access code
426 mov ah
,#$3d ;ask for a open
428 jnc openok
;return handle
if no error
439 mov dx
,[bx
+2] ;ds
:dx points to source string
440 xor cx
,cx
;normal attributes
441 mov ah
,#$3c ;ask for a create
443 jnc creok
;return handle
if no error
455 mov bx
,[bx
+2] ;file handle
456 mov ah
,#$3e ;ask for a close
458 mov ax
,0 ;return 0 if no error
476 mov dx
,ax
;ds
:dx points to source string
477 mov ah
,#$41 ;ask for a unlink
479 mov ax
,0 ;assume no errors
489 lseek(fd
, offset
, mode
)
495 mov al
,[bx
+8] ;mode of
seek (0 to
2)
496 mov dx
,[bx
+4] ;cx
:dx is
long offset
498 mov bx
,[bx
+2] ;file handle
500 int #$21 ;do the lseek
509 #ifdef L_dos_segalloc
511 __segalloc(paracount
)
512 unsigned int paracount
;
592 #if __FIRST_ARG_IN_AX__
610 __dos_stat(fname
, dtaptr
)
614 #if __FIRST_ARG_IN_AX__
620 mov ah
,#$1A ; Set DTA to requested
622 #if __FIRST_ARG_IN_AX__
627 mov ax
,#$4300 ; Locate the file
630 mov ax
,#$4e00 ; Get all the available information.
665 write(2, "Abnormal program termination\r\n", 30);
671 bdos(dosfn
, dosdx
, dosal
)
673 unsigned dosdx
, dosal
;
681 mov dx
,_bdos
.dosdx
[bx
]
682 mov cx
,_bdos
.dosfn
[bx
]
683 mov ax
,_bdos
.dosal
[bx
]
694 #endif /* __MSDOS__ */
695 #endif /* __AS386_16__ */
696 #endif /* !__FIRST_ARG_IN_AX__ */
699 # Name No Args Flag, comment
701 TIME 13 1 * No long return val, arg _must_ exist.
705 BRK 17 1 * This is only to tell the system
707 GETPID 20 1 * This gets both pid & ppid
708 MOUNT 21 3 * Need more args & no ELKS
709 UMOUNT 22 1 . No ELKS
711 GETUID 24 1 * This gets both uid and euid
712 STIME 25 2 . No ELKS should be 1 LONG arg
714 ALARM 27 2 ? No unused return.
718 STTY 31 2 . ELKS ain't got this and it'll probably change
719 GTTY 32 2 . ELKS ain't got this and it'll probably change
722 FTIME 35 1 . ELKS ain't got this.
728 DUP 41 X - Using nasty fcntl function
733 GETGID 47 1 * This gets both gid and egid
747 REBOOT 76 3 . No ELKS and the magic number will be diff.