* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / linux86-0.16.17 / libc / msdos / msdos.c
blobae10b39b3bf4c8df80dbef2ef8efe2589b02a583
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.
4 */
6 #if !__FIRST_ARG_IN_AX__
7 #ifdef __AS386_16__
8 #ifdef __MSDOS__
10 #include <dos.h>
11 #include <fcntl.h>
12 #include <errno.h>
13 int errno;
14 unsigned _doserrno;
16 #ifdef L_dos_start
18 static char * defarg[2] = { "C" };
19 static char ** def_environ =defarg+1;
20 void (*__cleanup)() = 0;
22 #asm
23 .data
24 export ___envseg
25 ___envseg:
26 .word 0
28 export ___psp
29 ___psp:
30 .word 0
32 .text
34 export _exit
35 export __exit
36 _exit: ! exit(rv) function
37 mov bx,sp
38 push [bx+2] ! Copy the `rv` for the exit fuctions.
39 mov bx,[___cleanup] ! Call exit, normally this is `__do_exit`
40 test bx,bx
41 je no_clean ! But it`s default is null
42 call bx
43 no_clean:
44 inc sp
45 inc sp
46 __exit: ! _exit(rv)
47 mov bx,sp
48 mov ax,[bx+2]
49 mov ah,#$4c
50 int #$21
51 dos_1_exit:
52 int #$20
54 .text
55 export ___cstartup ! Crt0 startup
56 ___cstartup:
57 mov ax,#$3000 ! Get DOS version
58 int $21
59 cmp al,#2 ! DOS 2+ is Ok
60 jb dos_1_exit
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
67 seg es
68 mov ax,[$2c]
69 mov [___envseg],ax ! Enviroment Segment
71 ! Now need to free some RAM
72 seg es
73 mov bx,[2] ! Top of Ram
74 mov ax,ds
75 add ax,#4096 ! Top of 64k data seg
76 jc use_tor ! Oops, wrapped
77 cmp ax,bx
78 jnc use_tor ! Bigger than tor
79 mov bx,ax
80 use_tor:
81 mov ax,cs ! Work out how big the memseg is needed
82 sub bx,ax
83 mov ah,#$4A ! Set it
84 int $21
85 jnc set_stack ! Good.
86 ! Ooops, problem..
87 ! BX is now how big it can be so set that.
88 ! FIXME should check for BSS v Stack overlap
89 mov ah,#$4A
90 int $21
92 set_stack: ! Now set SS to the same as DS
93 sub bx,#__segoff ! And SP to the top of available memory.
94 mov cl,#4
95 shl bx,cl
96 sub bx,#2
97 mov ss,dx
98 mov sp,bx
100 zap_bss: ! Clear the BSS
101 mov es,dx ! ES now data seg
102 mov di,#__edata
103 mov cx,#__end
104 sub cx,di
105 xor ax,ax
108 stosb
110 push [_def_environ] ! Defaults for when nothing is used.
111 mov ax,#_defarg
112 push ax
113 mov ax,#1
114 push ax
116 mov si,#auto_start ! Pointer to first autostart function
117 auto_run:
118 mov bx,[si]
119 test bx,bx
120 jz no_entry
121 call bx ! Call the function
122 no_entry:
123 inc si ! SI at next
124 inc si
125 jmp auto_run ! And round for the next.
127 call_exit: ! Last item called by above.
128 pop bx ! Be tidy.
129 push ax ! At the end the last called was main() push it`s
130 call _exit ! return val and call exit();
131 bad_exit:
132 jmp bad_exit ! Exit returned !!
134 loc 2
135 .word _main ! Segment 2 is the trailing pointers, main and the
136 .word call_exit ! routine to call exit.
137 data_start:
139 .text
141 #endasm
143 __E_nosys()
145 #asm
146 .text
148 export sys_call5
149 export sys_call4
150 export sys_call3
151 export sys_call2
152 export sys_call1
153 export sys_call0
154 sys_call5: ! Trap the unemulated Linux86 syscalls
155 sys_call4:
156 sys_call3:
157 sys_call2:
158 sys_call1:
159 sys_call0:
161 #endasm
162 errno = ENOSYS;
163 return -1;
165 #endif
167 #ifdef L___mkargv
169 #ifdef __AS386_16__
170 #asm
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.
175 #endasm
176 #endif
178 __mkargv(__argc, __argv)
179 int __argc;
180 char ** __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 */
186 if( length > 0 )
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;
196 ptr[length]=0;
198 p= __argv[0];
199 __argv = (char**) sbrk((argc+1)*sizeof(char*));
200 __argv[0] = p; /* TODO: The real command can be found */
201 __argc=argc;
204 * TODO: This needs to understand quoting and wildcards
207 argc=1; s=0;
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; }
213 __argv[argc] = 0;
216 #endif
218 #ifdef L___mkenvp
220 #ifdef __AS386_16__
221 #asm
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.
226 #endasm
227 #endif
229 char ** environ = 0;
231 __mkenvp(__argc, __argv, __envp)
232 int __argc;
233 char ** __argv;
234 char ** __envp;
236 /* FIXME !!!
238 * Note must write to __envp argument but not touch __argv or __argc
241 #endif
243 #ifdef L_dos__fconv
244 /* This function converts filenames from unix like to DOS. */
245 char *
246 __fconv(fname)
247 char * fname;
249 static char buf1[66], buf2[66], *str = 0;
250 register char *p, ch;
251 int dot = 0;
253 if( strcmp("/dev/tty", fname) == 0 ) return "CON:";
255 if( str == buf1 ) str = buf2; else str = buf1;
257 p = str;
258 if( strncmp("/mnt/", fname, 5) == 0 )
260 strcpy(p, "A:"); p+=2; fname+=4;
263 * POSS:
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' )
274 ch = ch-'A'+'a';
275 else if( ch == '.' && dot == 0 )
276 dot = 1;
277 else if( ch == '/' || ch == '\\' )
279 dot = 0; ch = '\\';
281 else ch = '_';
283 *p++ = ch;
285 *p++ = '\0';
286 return str;
288 #endif
290 #ifdef L___exterror
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,
297 EFAULT, ENOSPC
300 __exterror()
302 #asm
303 export exterror
304 exterror:
305 push ds
306 push es
307 push di
308 push si
309 push bp
310 xor bx,bx
311 mov ah,#$59
312 int $21
313 pop bp
314 pop si
315 pop di
316 pop es
317 pop ds
318 mov __doserrno,ax
319 #endasm
321 int nerrno;
322 extern unsigned _doserrno;
324 if( _doserrno == 0 )
325 /* No error? No change. */;
326 else if( _doserrno >= sizeof(errno_xlate)
327 || errno_xlate[_doserrno] == EFAULT )
328 errno = 16384+_doserrno;
329 else
330 errno = errno_xlate[_doserrno];
332 return -1;
334 #endif
336 #ifdef L_dos_read
338 read(fd, ptr, len)
339 int fd;
340 char *ptr;
341 unsigned len;
343 #asm
344 mov bx,sp
345 mov cx,[bx+6]
346 mov dx,[bx+4]
347 mov bx,[bx+2]
348 mov ah,#$3f
349 int #$21
350 jnc readok
351 br exterror
352 readok:
353 #endasm
355 #endif
357 #ifdef L_dos_write
359 write(fd, ptr, len)
360 int fd;
361 char *ptr;
362 unsigned len;
364 #asm
365 mov bx,sp
366 mov cx,[bx+6]
367 mov dx,[bx+4]
368 mov bx,[bx+2]
369 mov ah,#$40
370 int #$21
371 jnc writeok
372 br exterror
373 writeok:
374 #endasm
376 #endif
378 #ifdef L_dos_open
380 open(fname, type, cmode)
381 char * fname;
382 int type;
383 int cmode;
385 register char * nname = __fconv(fname);
386 int creat_mode = 0;
387 int rv;
389 static int xlate_mode[] = {
390 #ifdef OPEN_LIKE_UNIX
391 O_RDONLY|O_DENYNONE,
392 O_WRONLY|O_DENYNONE,
393 O_RDWR|O_DENYNONE,
394 #else
395 O_RDONLY|O_DENYNONE,
396 O_WRONLY|O_DENYWRITE,
397 O_RDWR|O_DENYALL,
398 #endif
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);
409 else
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));
414 else
415 rv = __dos_open(nname, xlate_mode[type&O_ACCMODE]);
417 return rv;
420 __dos_open(fname, mode)
422 #asm
423 mov bx,sp
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
427 int #$21
428 jnc openok ;return handle if no error
429 br exterror
430 openok:
431 #endasm
434 __dos_creat(fname)
435 char * fname;
437 #asm
438 mov bx,sp
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
442 int #$21
443 jnc creok ;return handle if no error
444 br exterror
445 creok:
446 #endasm
448 #endif
450 #ifdef L_dos_close
451 close(fd)
453 #asm
454 mov bx,sp
455 mov bx,[bx+2] ;file handle
456 mov ah,#$3e ;ask for a close
457 int #$21
458 mov ax,0 ;return 0 if no error
459 jnc closeok
460 br exterror
461 closeok:
462 #endasm
464 #endif
466 #ifdef L_dos_unlink
467 unlink(fname)
468 char * fname;
470 #asm
471 mov bx,sp
472 push [bx+2]
473 call ___fconv
474 inc sp
475 inc sp
476 mov dx,ax ;ds:dx points to source string
477 mov ah,#$41 ;ask for a unlink
478 int #$21
479 mov ax,0 ;assume no errors
480 jnc unlok
481 br exterror
482 unlok:
483 #endasm
485 #endif
487 #ifdef L_dos_lseek
488 long
489 lseek(fd, offset, mode)
490 int fd, mode;
491 long offset;
493 #asm
494 mov bx,sp
495 mov al,[bx+8] ;mode of seek (0 to 2)
496 mov dx,[bx+4] ;cx:dx is long offset
497 mov cx,[bx+6]
498 mov bx,[bx+2] ;file handle
499 mov ah,#$42
500 int #$21 ;do the lseek
501 jnc seekok
502 call exterror
503 mov dx,ax
504 seekok:
505 #endasm
507 #endif
509 #ifdef L_dos_segalloc
510 unsigned int
511 __segalloc(paracount)
512 unsigned int paracount;
514 #asm
515 mov bx,sp
516 mov bx,[bx+2]
517 mov ah,#$48
518 int $21
519 jnc ok
520 mov ax,#0
522 #endasm
524 #endif
526 #ifdef L_dos_segfree
527 unsigned int
528 __segfree(segno)
529 unsigned int segno;
531 #asm
532 push es
533 mov bx,sp
534 mov es,[bx+4]
535 mov ah,#$49
536 int $21
537 jc err
538 mov ax,#0
539 err:
540 pop es
541 #endasm
543 #endif
545 #ifdef L_dos_setvect
546 void
547 __setvect(i,j)
548 int i;
549 long j;
551 #asm
552 mov bx,sp
553 mov ax,[bx+2]
554 mov dx,[bx+4]
555 mov bx,[bx+6]
556 push ds
557 test bx,bx
558 jnz got_seg
559 mov bx,cs
560 got_seg:
561 mov ds,bx
562 mov ah,#$25
563 int $21
564 pop ds
565 #endasm
567 #endif
569 #ifdef L_dos_getvect
570 long
571 __getvect(vecno)
572 int vecno;
574 #asm
575 mov bx,sp
576 mov ax,[bx+2]
577 mov ah,#$35
578 push es
579 int #$21
580 mov dx,es
581 mov ax,bx
582 pop es
583 #endasm
585 #endif
587 #ifdef L_dos_getmod
589 __dos_getmod(fname)
591 #asm
592 #if __FIRST_ARG_IN_AX__
593 mov dx,ax
594 #else
595 mov bx,sp
596 mov dx,[bx+2]
597 #endif
598 mov ax,#$4300
599 int #$21
600 jnc statok
601 br exterror
602 statok:
603 mov ax,cx
604 #endasm
606 #endif
608 #ifdef L_dos_stat
610 __dos_stat(fname, dtaptr)
612 #asm
613 mov bx,sp
614 #if __FIRST_ARG_IN_AX__
615 mov cx,ax
616 mov dx,[bx+2]
617 #else
618 mov dx,[bx+4]
619 #endif
620 mov ah,#$1A ; Set DTA to requested
621 int #$21
622 #if __FIRST_ARG_IN_AX__
623 mov ax,cx
624 #else
625 mov dx,[bx+2]
626 #endif
627 mov ax,#$4300 ; Locate the file
628 int #$21
629 jc nonesuch
630 mov ax,#$4e00 ; Get all the available information.
631 int #$21
632 jc nonesuch
633 xor ax,ax
635 nonesuch:
636 mov ax,#2
637 mov _errno,ax
638 mov ax,#-1
639 #endasm
641 #endif
643 #ifdef L_dos_isatty
644 isatty(fd)
645 int fd;
647 #asm
648 mov bx,sp
649 mov bx,[bx+2]
650 mov ah,#$44
651 mov al,#0
652 int #$21
653 xor ax,ax
654 test dx,#$80
655 jz not_tty
656 inc ax
657 not_tty:
658 #endasm
660 #endif
662 #ifdef L_dos_abort
663 abort()
665 write(2, "Abnormal program termination\r\n", 30);
666 _exit(3);
668 #endif
670 #ifdef L_bdos
671 bdos(dosfn, dosdx, dosal)
672 int dosfn;
673 unsigned dosdx, dosal;
675 #asm
676 _bdosptr = _bdos
677 mov bx,sp
678 push si
679 push di
681 mov dx,_bdos.dosdx[bx]
682 mov cx,_bdos.dosfn[bx]
683 mov ax,_bdos.dosal[bx]
684 mov ah,cl
686 int $21
688 pop di
689 pop si
690 #endasm
692 #endif
694 #endif /* __MSDOS__ */
695 #endif /* __AS386_16__ */
696 #endif /* !__FIRST_ARG_IN_AX__ */
699 # Name No Args Flag, comment
700 CHDIR 12 1
701 TIME 13 1 * No long return val, arg _must_ exist.
702 MKNOD 14 3
703 CHMOD 15 2
704 CHOWN 16 3
705 BRK 17 1 * This is only to tell the system
706 STAT 18 2
707 GETPID 20 1 * This gets both pid & ppid
708 MOUNT 21 3 * Need more args & no ELKS
709 UMOUNT 22 1 . No ELKS
710 SETUID 23 1
711 GETUID 24 1 * This gets both uid and euid
712 STIME 25 2 . No ELKS should be 1 LONG arg
713 PTRACE 26 X +
714 ALARM 27 2 ? No unused return.
715 FSTAT 28 2
716 PAUSE 29 0
717 UTIME 30 2
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
720 ACCESS 33 2
721 NICE 34 1
722 FTIME 35 1 . ELKS ain't got this.
723 SYNC 36 0
724 KILL 37 2
725 RENAME 38 2
726 MKDIR 39 2
727 RMDIR 40 1
728 DUP 41 X - Using nasty fcntl function
729 PIPE 42 1
730 TIMES 43 1
731 PROF 44 X +
732 SETGID 46 1
733 GETGID 47 1 * This gets both gid and egid
734 SIGNAL 48 2 +
735 ACCT 51 X +
736 PLOCK 53 X +
737 IOCTL 54 3
738 FCNTL 55 3
739 EXEC 59 2 ?
740 UMASK 60 1
741 CHROOT 61 1
742 SIGACTION 71 X
743 SIGSUSPEND 72 X
744 SIGPENDING 73 X
745 SIGPROCMASK 74 X
746 SIGRETURN 75 X
747 REBOOT 76 3 . No ELKS and the magic number will be diff.