source: vendor/emx/current/src/os2/syscall.c

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 26.8 KB
Line 
1/* syscall.c -- emx system calls
2 Copyright (c) 1994-1998 by Eberhard Mattes
3
4This file is part of emx.
5
6emx is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11emx is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with emx; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.
20
21As special exception, emx.dll can be distributed without source code
22unless it has been changed. If you modify emx.dll, this exception
23no longer applies and you must remove this paragraph from all source
24files for emx.dll. */
25
26
27#define INCL_DOSEXCEPTIONS
28#define INCL_DOSMISC
29#define INCL_DOSNLS
30#define INCL_DOSPROCESS
31#define INCL_VIO
32#include <os2emx.h>
33#include <sys/signal.h>
34#include <sys/errno.h>
35#include "emxdll.h"
36#include "tcpip.h"
37#include "version.h"
38#include <sys/nls.h>
39#include <sys/timeb.h>
40#include <sys/time.h>
41#include <sys/ulimit.h>
42
43static void bad_spec (syscall_frame *f);
44static ULONG do_syserrno (void);
45static ULONG do_setsyserrno (ULONG errcode);
46static void do_memupr (char *dst, ULONG size);
47static int do_ctype (unsigned char *dst, int *errnop);
48static void do_scrsize (int *dst);
49static ULONG do_read_kbd (ULONG flags);
50static unsigned do_sleep (unsigned sec);
51
52
53void sys_call (syscall_frame *f)
54{
55 int err_no;
56
57 if (debug_flags & DEBUG_SYSCALL)
58 oprintf ("%u: syscall 7f%.2x\r\n", my_pid, (unsigned)f->b.al);
59
60 f->e.eflags &= ~FLAG_C;
61
62 switch (f->b.al)
63 {
64 case 0x00:
65
66 /* __sbrk() */
67
68 f->e.eax = do_sbrk (f->e.edx);
69 break;
70
71 case 0x01:
72
73 /* __brk() */
74
75 f->e.eax = do_brk (f->e.edx);
76 break;
77
78 case 0x02:
79
80 /* __ulimit()
81
82 In: ECX Command code (must be UL_GMEMLIM or UL_OBJREST)
83 EDX New limit (currently ignored)
84
85 Out: EAX Return value:
86 greatest possible break value for UL_GMEMLIM
87 remaining bytes in current heap object for UL_OBJREST
88 ECX errno (0 if successful)
89
90 Get greatest possible break value or remaining number of
91 bytes in current heap object. */
92
93 switch (f->e.ecx)
94 {
95 case UL_GMEMLIM:
96 /* Note: As this is the limit for brk(), not for sbrk(), we
97 don't return 512M. */
98 f->e.eax = top_heap_obj != NULL ? top_heap_obj->end : 0;
99 f->e.ecx = 0;
100 break;
101 case UL_OBJREST:
102 f->e.eax = (top_heap_obj != NULL
103 ? top_heap_obj->end - top_heap_obj->brk : 0);
104 f->e.ecx = 0;
105 break;
106 default:
107 f->e.eax = (ULONG)(-1);
108 f->e.ecx = EINVAL;
109 break;
110 }
111 break;
112
113 case 0x03:
114
115 /* __vmstat() */
116
117 if (f->e.ecx >= 4)
118 ((ULONG *)f->e.ebx)[0] = 0;
119 if (f->e.ecx >= 8)
120 ((ULONG *)f->e.ebx)[1] = 0;
121 break;
122
123 case 0x04:
124
125 /* __umask1() */
126
127 f->e.eax = umask_bits1;
128 umask_bits1 &= ~f->e.edx;
129 break;
130
131 case 0x05:
132
133 /* __getpid() */
134
135 f->e.eax = my_pid;
136 break;
137
138 case 0x06:
139
140 /* __spawnve() */
141
142 err_no = do_spawn ((struct _new_proc *)f->e.edx, &f->e.eax);
143 if (err_no != 0)
144 {
145 f->e.eax = err_no;
146 f->e.eflags |= FLAG_C;
147 }
148 break;
149
150 case 0x08:
151
152 /* __ptrace()
153
154 In: EBX Request code (see /emx/include/sys/ptrace.h)
155 EDI Process ID
156 EDX Address
157 ECX Data
158
159 Out: EAX Result
160 ECX errno (0 if successful)
161
162 Debugging support */
163
164 f->e.eax = do_ptrace (f->e.ebx, f->e.edi, f->e.edx, f->e.ecx, &f->e.ecx);
165 break;
166
167 case 0x09:
168
169 /* __wait()
170
171 In: --
172
173 Out: EAX Process ID of child process (-1 if no children)
174 ECX errno
175 EDX Termination status
176
177 Wait for child process. There are two cases:
178
179 (1) when debugging, return the value stored by
180 __ptrace(). Waiting for other processes is not possible
181
182 (2) examine process table; sit on `process_death'. */
183
184 f->e.eax = do_wait (&f->e.edx, &f->e.ecx);
185 break;
186
187 case 0x0a:
188
189 /* __version()
190
191 In: --
192
193 Out: EAX Version number
194 Bits 0..7: version letter ('a'..'z')
195 Bits 8..15: minor version number ('0'..'9')
196 Bits 16..23: 0x2e ('.')
197 Bits 24..31: major version number ('0'..'9')
198 EBX Environment:
199 Bit 0: VCPI
200 Bit 1: XMS
201 Bit 2: VDISK.SYS 3.3
202 Bit 3: DESQview
203 Bit 4: 287
204 Bit 5: 387
205 Bit 6: 486 (not implemented)
206 Bit 7: DPMI 0.9 (not implemented)
207 Bit 8: DPMI 1.0 (not implemented)
208 Bit 9: OS/2 2.0
209 Bit 10: -t option given
210 Bits 6..31: 0 (reserved for future expansion)
211 ECX Revision index
212 EDX 0 (reserved for future expansion)
213
214 Return emx version. */
215
216 f->e.eax = (VERSION[3] | (VERSION[2] << 8)
217 | (VERSION[1] << 16) | (VERSION[0] << 24));
218 f->e.ebx = 0x0a20; /* OS/2 2.0, 387, -ac */
219 if (opt_trunc)
220 f->e.ebx |= 0x400; /* Set -t bit */
221 f->e.ecx = REV_INDEX;
222 f->e.edx = 0;
223 break;
224
225 case 0x0b:
226
227 /* __memavail() */
228
229 f->e.eax = 0;
230 break;
231
232 case 0x0c:
233
234 /* __signal()
235
236 In: ECX Signal number
237 EDX Address of signal handler or SIG_ACK, SIG_DFL, SIG_IGN
238
239 Out: EAX Previous value (success) or SIG_ERR (error)
240
241 Set signal handler. */
242
243 f->e.eax = (ULONG)do_signal (f->e.ecx, (sigfun *)f->e.edx, f);
244 break;
245
246 case 0x0d:
247
248 /* __kill()
249
250 In: ECX Signal number
251 EDX Process ID
252
253 Out: EAX 0 if successful, -1 otherwise
254 ECX errno
255
256 Send a signal to a process. If PID is the process ID of this
257 process, send the signal to thread 1. Under OS/2, a process
258 cannot send a signal to itself using DosSendSignalException:
259 DosRaiseException must be used instead. */
260
261 f->e.eax = do_kill (f->e.ecx, f->e.edx, f, &err_no);
262 f->e.ecx = err_no;
263 break;
264
265 case 0x0e:
266
267 /* __raise()
268
269 In: ECX Signal number
270
271 Out: EAX 0 if successful, a non-zero value otherwise
272 ECX errno (0 if successful)
273
274 Raise a signal (in current process). */
275
276 if (f->e.ecx >= NSIG || !signal_valid [f->e.ecx])
277 {
278 f->e.eax = (ULONG)(-1);
279 f->e.ecx = EINVAL;
280 }
281 else
282 {
283 do_raise (f->e.ecx, f);
284 f->e.eax = 0;
285 f->e.ecx = 0;
286 }
287 break;
288
289 case 0x0f:
290
291 /* __uflags()
292
293 In: ECX Mask (only bits set to 1 in ECX will be changed)
294 EDX New values of the bits selected by ECX
295
296 Out: EAX Previous set of flags
297
298 Set user flags. */
299
300 f->e.eax = uflags;
301 uflags = (uflags & ~f->e.ecx) | (f->e.edx & f->e.ecx);
302 break;
303
304 case 0x10:
305
306 /* __unwind()
307
308 Unwind signal handlers for longjmp() -- old version. */
309
310 unwind (exc_reg_ptr, NULL);
311 break;
312
313 case 0x11:
314
315 /* __core() */
316
317 if (layout_flags & L_FLAG_LINK386)
318 {
319 f->e.eax = EACCES;
320 f->e.eflags |= FLAG_C;
321 }
322 else
323 {
324 core_regs_i (f);
325 f->e.eax = core_main (f->e.ebx);
326 if (f->e.eax != 0)
327 f->e.eflags |= FLAG_C;
328 }
329 break;
330
331 case 0x12:
332
333 /* __portaccess() */
334
335 f->e.eax = 0;
336 break;
337
338 case 0x13:
339
340 /* __memaccess () */
341
342 f->e.eax = EACCES;
343 f->e.eflags |= FLAG_C;
344 break;
345
346 case 0x14:
347
348 /* __ioctl2()
349
350 In: EBX Handle
351 ECX Request code
352 EDX Argument
353
354 Out: EAX Return value
355 ECX errno
356
357 Unix-like termio ioctl(). */
358
359 f->e.eax = do_ioctl2 (f->e.ebx, f->e.ecx, f->e.edx, &err_no);
360 f->e.ecx = err_no;
361 break;
362
363 case 0x15:
364
365 /* __alarm()
366
367 In: EDX Seconds
368
369 Out: EAX Time remaining
370
371 Set alarm clock. */
372
373 f->e.eax = set_alarm (f->e.edx);
374 break;
375
376 case 0x17:
377
378 /* __sleep()
379
380 In: EDX Seconds
381
382 Out: EAX Remaining time if interrupted by signal, or 0
383
384 Suspend process. */
385
386 f->e.eax = do_sleep (f->e.edx);
387 break;
388
389 case 0x18:
390
391 /* __chsize()
392
393 In: EBX File handle
394 EDX File size
395
396 Out: CY Error
397 EAX errno (CY)
398
399 Set file size. */
400
401 f->e.eax = do_chsize (f->e.ebx, f->e.edx);
402 if (f->e.eax != 0)
403 f->e.eflags |= FLAG_C;
404 break;
405
406 case 0x19:
407
408 /* __fcntl()
409
410 In: EBX File handle
411 ECX Request code
412 EDX Argument
413
414 Out: EAX Return value
415 ECX errno (0 if successful)
416
417 Unix-like file control. */
418
419 f->e.eax = do_fcntl (f->e.ebx, f->e.ecx, f->e.edx, &err_no);
420 f->e.ecx = err_no;
421 break;
422
423 case 0x1a:
424
425 /* __pipe()
426
427 In: ECX Size of pipe
428 EDX Pointer to storage for two handles (two DWORDs)
429
430 Out: EAX 0 (success) or -1 (failure)
431 ECX errno (0 if successful)
432
433 Create unnamed pipe. */
434
435 f->e.ecx = do_pipe ((int *)f->e.edx, f->e.ecx);
436 if (f->e.ecx == 0)
437 f->e.eax = 0;
438 else
439 f->e.eax = (ULONG)(-1);
440 break;
441
442 case 0x1b:
443
444 /* __fsync()
445
446 In: EBX File handle
447
448 Out: EAX 0 (success) or -1 (failure)
449 ECX errno (0 if successful)
450
451 Update file system. */
452
453 f->e.eax = do_fsync (f->e.ebx, &err_no);
454 f->e.ecx = err_no;
455 break;
456
457 case 0x1c:
458
459 /* __fork()
460
461 Out: EAX Process ID or 0 (in new process) or -1 (failure)
462 ECX errno (0 if successful)
463
464 Duplicate process. */
465
466 f->e.eax = do_fork (f, &f->e.ecx);
467 break;
468
469 case 0x1d:
470
471 /* __scrsize()
472
473 In: EDX Pointer to structure
474
475 Out: --
476
477 Get number of rows and columns. */
478
479 do_scrsize ((int *)f->e.edx);
480 break;
481
482 case 0x1e:
483
484 /* __select()
485
486 In: EDX Pointer to structure
487
488 Out: EAX 0 (timeout), > 0 (ready) or -1 (failure)
489 ECX errno (0 if successful)
490
491 Synchronous I/O multiplexing. */
492
493 f->e.eax = do_select ((struct _select *)f->e.edx, &err_no);
494 f->e.ecx = err_no;
495 break;
496
497 case 0x1f:
498
499 /* __syserrno()
500
501 Out: EAX Error number
502
503 Return OS/2 error number for last syscall. */
504
505 f->e.eax = do_syserrno ();
506 break;
507
508 case 0x20:
509
510 /* __stat()
511
512 In: EDX Path name
513 EDI Pointer to structure
514
515 Out: EAX 0 (ok), -1 (error)
516 ECX errno (0 if successful)
517
518 Get information about a path name. */
519
520 f->e.eax = do_stat ((const char *)f->e.edx, (struct stat *)f->e.edi,
521 &err_no);
522 f->e.ecx = err_no;
523 break;
524
525 case 0x21:
526
527 /* __fstat()
528
529 In: EBX File handle
530 EDI Pointer to structure
531
532 Out: EAX 0 (ok), -1 (error)
533 ECX errno (0 if successful)
534
535 Get information about an open file. */
536
537 f->e.eax = do_fstat (f->e.ebx, (struct stat *)f->e.edi, &err_no);
538 f->e.ecx = err_no;
539 break;
540
541 case 0x23:
542
543 /* __filesys()
544
545 In: EDX Pointer to drive name
546 EDI Pointer to output buffer
547 ECX Size of output buffer
548
549 Out: EAX 0 (ok) or -1 (error)
550 ECX errno (0 if successful)
551
552 Get name of file-system driver. */
553
554 f->e.eax = do_filesys ((char *)f->e.edi, f->e.ecx,
555 (const char *)f->e.edx, &err_no);
556 f->e.ecx = err_no;
557 break;
558
559 case 0x24:
560
561 /* __utimes()
562
563 In: EDX Pointer to path name
564 ESI Pointer to array of structures
565
566 Out: EAX 0 (ok) or -1 (error)
567 ECX errno (0 if successful)
568
569 Set access and modification time of a file. */
570
571 f->e.eax = do_utimes ((const char *)f->e.edx,
572 (const struct timeval *)f->e.esi, &err_no);
573 f->e.ecx = err_no;
574 break;
575
576 case 0x25:
577
578 /* __ftruncate()
579
580 In: EBX File handle
581 EDX File size
582
583 Out: EAX 0 (ok), -1 (error)
584 ECX errno (0 if successful)
585
586 Truncate a file. */
587
588 f->e.ecx = do_ftruncate (f->e.ebx, f->e.edx);
589 if (f->e.ecx == 0)
590 f->e.eax = 0;
591 else
592 f->e.eax = (ULONG)(-1);
593 break;
594
595 case 0x26:
596
597 /* __clock()
598
599 Out: EAX Timer ticks of CPU time used, low-order 32 bits
600 EDX High-order 32 bits
601
602 Return CPU time used by this process. */
603
604 {
605 unsigned long long tmp;
606
607 tmp = get_clock (FALSE);
608 f->e.eax = (ULONG)tmp;
609 f->e.edx = (ULONG)(tmp >> 32);
610 }
611 break;
612
613 case 0x27:
614
615 /* __ftime()
616
617 In: EDX Pointer to structure
618
619 Get current time. */
620
621 do_ftime ((struct timeb *)f->e.edx);
622 break;
623
624 case 0x28:
625
626 /* __umask()
627
628 In: EDX New file permission mask
629
630 Out: EAX Previous file permission mask
631
632 Set file permission mask. */
633
634 f->e.eax = umask_bits;
635 umask_bits = f->e.edx;
636 break;
637
638 case 0x29:
639
640 /* __getppid()
641
642 Out: EAX Parent process ID
643
644 Get parent process ID. */
645
646 f->e.eax = init_pib_ptr->pib_ulppid;
647 break;
648
649 case 0x2a:
650
651 /* __nls_memupr()
652
653 In: EDX Pointer to buffer
654 ECX Size of buffer
655
656 Convert buffer to upper case. */
657
658 do_memupr ((char *)f->e.edx, f->e.ecx);
659 break;
660
661 case 0x2b:
662
663 /* __open()
664
665 In: EDX Pointer to file name
666 ECX Flags
667 EBX Size
668
669 Out: EAX Handle or -1 (failure)
670 ECX errno (0 if successful)
671
672 Open a file. */
673
674 f->e.eax = sys_open ((const char *)f->e.edx, f->e.ecx, f->e.ebx,
675 &err_no);
676 f->e.ecx = err_no;
677 break;
678
679 case 0x2c:
680
681 /* __newthread()
682
683 In: EDX Thread ID
684
685 Out: EAX 0 (success), -1 (failure)
686 ECX errno (0 if successful)
687
688 Notify emx of a thread, create thread data block. */
689
690 f->e.eax = new_thread (f->e.edx, &err_no);
691 f->e.ecx = err_no;
692 break;
693
694 case 0x2d:
695
696 /* __endthread()
697
698 In: EDX Thread ID
699
700 Out: EAX 0 (success), -1 (failure)
701 ECX errno (0 if successful)
702
703 Notify emx of the end of a thread, deallocate thread data
704 block. */
705
706 f->e.eax = end_thread (f->e.edx, &err_no);
707 f->e.ecx = err_no;
708 break;
709
710 case 0x2e:
711
712 /* __waitpid()
713
714 In: EDX Process ID
715 ECX Options
716
717 Out: EAX Process ID of child process (-1 if no children)
718 ECX errno
719 EDX Termination status
720
721 Wait for child process. */
722
723 f->e.eax = do_waitpid (f->e.edx, f->e.ecx, &f->e.edx, &f->e.ecx);
724 break;
725
726 case 0x2f:
727
728 /* __read_kbd()
729
730 In: EDX Flags (bit 0: echo, bit 1: wait, bit 2:sig)
731
732 Out: EAX Character (or -1)
733
734 Raw keyboard input. */
735
736 f->e.eax = do_read_kbd (f->e.edx);
737 break;
738
739 case 0x30:
740
741 /* __sleep2()
742
743 In: EDX Milliseconds
744
745 Out: EAX 0
746
747 Suspend process. */
748
749 DosSleep (f->e.edx);
750 f->e.eax = 0;
751 break;
752
753 case 0x31:
754
755 /* __unwind2()
756
757 Unwind signal handlers for longjmp(). */
758
759 unwind ((EXCEPTIONREGISTRATIONRECORD *)f->e.edx, NULL);
760 break;
761
762 case 0x32:
763
764 /* __pause()
765
766 Wait for signal. */
767
768 do_pause ();
769 break;
770
771 case 0x33:
772
773 /* __execname()
774
775 In: EDX Buffer
776 ECX Buffer size
777
778 Out: EAX 0 if successful, -1 otherwise
779
780 Get the name of the executable file. */
781
782 f->e.eax = execname ((char *)f->e.edx, f->e.ecx);
783 break;
784
785 case 0x34:
786
787 /* __initthread()
788
789 In: EDX Pointer to EXCEPTIONREGISTRATIONRECORD
790
791 Out: EAX 0 if successful, -1 otherwise
792
793 Install exception handler in new thread. */
794
795 f->e.eax = initthread ((EXCEPTIONREGISTRATIONRECORD *)f->e.edx);
796 break;
797
798 case 0x35:
799
800 /* __sigaction */
801
802 f->e.ecx = do_sigaction (f->e.ecx, (const struct sigaction *)f->e.edx,
803 (struct sigaction *)f->e.ebx);
804 if (f->e.ecx == 0)
805 f->e.eax = 0;
806 else
807 f->e.eax = (ULONG)(-1);
808 break;
809
810 case 0x36:
811
812 /* __sigpending */
813
814 f->e.ecx = do_sigpending ((sigset_t *)f->e.edx);
815 if (f->e.ecx == 0)
816 f->e.eax = 0;
817 else
818 f->e.eax = (ULONG)(-1);
819 break;
820
821 case 0x37:
822
823 /* __sigprocmask */
824
825 f->e.ecx = do_sigprocmask (f->e.ecx, (const sigset_t *)f->e.edx,
826 (sigset_t *)f->e.ebx, f);
827 if (f->e.ecx == 0)
828 f->e.eax = 0;
829 else
830 f->e.eax = (ULONG)(-1);
831 break;
832
833 case 0x38:
834
835 /* __sigsuspend */
836
837 f->e.ecx = do_sigsuspend ((const sigset_t *)f->e.edx);
838 if (f->e.ecx == 0)
839 f->e.eax = 0;
840 else
841 f->e.eax = (ULONG)(-1);
842 break;
843
844 case 0x39:
845
846 /* __imphandle */
847
848 f->e.eax = do_imphandle (f->e.edx, &err_no);
849 f->e.ecx = err_no;
850 break;
851
852 case 0x3b:
853
854 /* __getsockhandle */
855
856 f->e.eax = tcpip_getsockhandle (f->e.ebx, &err_no);
857 f->e.ecx = err_no;
858 break;
859
860 case 0x3c:
861
862 /* __socket */
863
864 f->e.eax = tcpip_socket (f->e.ecx, f->e.edx, f->e.ebx, &err_no);
865 f->e.ecx = err_no;
866 break;
867
868 case 0x3d:
869
870 /* __bind */
871
872 f->e.ecx = tcpip_bind (f->e.ebx, (void *)f->e.edx, f->e.ecx);
873 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
874 break;
875
876 case 0x3e:
877
878 /* __listen */
879
880 f->e.ecx = tcpip_listen (f->e.ebx, f->e.edx);
881 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
882 break;
883
884 case 0x3f:
885
886 /* __recv */
887
888 f->e.eax = tcpip_recv (f->e.ebx, (void *)f->e.edx, f->e.ecx, f->e.esi,
889 &err_no);
890 f->e.ecx = err_no;
891 break;
892
893 case 0x40:
894
895 /* __send */
896
897 f->e.eax = tcpip_send (f->e.ebx, (const void *)f->e.edx, f->e.ecx,
898 f->e.esi, &err_no);
899 f->e.ecx = err_no;
900 break;
901
902 case 0x41:
903
904 /* __accept */
905
906 f->e.eax = tcpip_accept (f->e.ebx, (void *)f->e.edx, (int *)f->e.ecx,
907 &err_no);
908 f->e.ecx = err_no;
909 break;
910
911 case 0x42:
912
913 /* __connect */
914
915 f->e.ecx = tcpip_connect (f->e.ebx, (void *)f->e.edx, f->e.ecx);
916 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
917 break;
918
919 case 0x43:
920
921 /* __getsockopt */
922
923 f->e.ecx = tcpip_getsockopt (f->e.ebx, f->e.edx, f->e.ecx,
924 (void *)f->e.esi, (int *)f->e.edi);
925 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
926 break;
927
928 case 0x44:
929
930 /* __setsockopt */
931
932 f->e.ecx = tcpip_setsockopt (f->e.ebx, f->e.edx, f->e.ecx,
933 (const void *)f->e.esi, f->e.edi);
934 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
935 break;
936
937 case 0x45:
938
939 /* __getsockname */
940
941 f->e.ecx = tcpip_getsockname (f->e.ebx, (void *)f->e.edx,
942 (int *)f->e.ecx);
943 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
944 break;
945
946 case 0x46:
947
948 /* __getpeername */
949
950 f->e.ecx = tcpip_getpeername (f->e.ebx, (void *)f->e.edx,
951 (int *)f->e.ecx);
952 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
953 break;
954
955 case 0x47:
956
957 /* __gethostbyname */
958
959 f->e.ecx = tcpip_gethostbyname ((const char *)f->e.edx,
960 (void **)f->e.ebx);
961 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
962 break;
963
964 case 0x48:
965
966 /* __gethostbyaddr */
967
968 f->e.ecx = tcpip_gethostbyaddr ((const char *)f->e.edx, f->e.ecx,
969 f->e.esi, (void **)f->e.ebx);
970 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
971 break;
972
973 case 0x49:
974
975 /* __getservbyname */
976
977 f->e.eax = tcpip_getservbyname ((const char *)f->e.edx,
978 (const char *)f->e.ecx,
979 (void **)f->e.ebx);
980 f->e.ecx = 0;
981 break;
982
983 case 0x4a:
984
985 /* __getservbyport */
986
987 f->e.eax = tcpip_getservbyport (f->e.edx, (const char *)f->e.ecx,
988 (void **)f->e.ebx);
989 f->e.ecx = 0;
990 break;
991
992 case 0x4b:
993
994 /* __getprotobyname */
995
996 f->e.eax = tcpip_getprotobyname ((const char *)f->e.edx,
997 (void **)f->e.ebx);
998 f->e.ecx = 0;
999 break;
1000
1001 case 0x4c:
1002
1003 /* __getprotobynumber */
1004
1005 f->e.eax = tcpip_getprotobynumber (f->e.edx, (void **)f->e.ebx);
1006 f->e.ecx = 0;
1007 break;
1008
1009 case 0x4d:
1010
1011 /* __getnetbyname */
1012
1013 f->e.eax = tcpip_getnetbyname ((const char *)f->e.edx,
1014 (void **)f->e.ebx);
1015 f->e.ecx = 0;
1016 break;
1017
1018 case 0x4e:
1019
1020 /* __getnetbyaddr */
1021
1022 f->e.eax = tcpip_getnetbyaddr (f->e.edx, (void **)f->e.ebx);
1023 f->e.ecx = 0;
1024 break;
1025
1026 case 0x4f:
1027
1028 /* __gethostname */
1029
1030 f->e.ecx = tcpip_gethostname ((char *)f->e.edx, f->e.ecx);
1031 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
1032 break;
1033
1034 case 0x50:
1035
1036 /* __gethostid */
1037
1038 f->e.ecx = tcpip_gethostid ((int *)f->e.ebx);
1039 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
1040 break;
1041
1042 case 0x51:
1043
1044 /* __shutdown */
1045
1046 f->e.ecx = tcpip_shutdown (f->e.ebx, f->e.edx);
1047 f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
1048 break;
1049
1050 case 0x52:
1051
1052 /* __recvfrom */
1053
1054 f->e.eax = tcpip_recvfrom ((const struct _recvfrom *)f->e.edx, &err_no);
1055 f->e.ecx = err_no;
1056 break;
1057
1058 case 0x53:
1059
1060 /* __sendto */
1061
1062 f->e.eax = tcpip_sendto ((const struct _sendto *)f->e.edx, &err_no);
1063 f->e.ecx = err_no;
1064 break;
1065
1066 case 0x54:
1067
1068 /* __impsockhandle */
1069
1070 f->e.eax = tcpip_impsockhandle (f->e.edx, f->e.ecx, &err_no);
1071 f->e.ecx = err_no;
1072 break;
1073
1074 case 0x57:
1075
1076 /* __ttyname()
1077
1078 In: EDX File handle
1079 EDI Pointer to output buffer
1080 ECX Size of output buffer
1081
1082 Out: EAX 0 (ok) or -1 (error)
1083 ECX errno (0 if successful)
1084
1085 Get name of device. */
1086
1087 f->e.eax = do_ttyname ((char *)f->e.edi, f->e.ecx, f->e.edx, &err_no);
1088 f->e.ecx = err_no;
1089 break;
1090
1091 case 0x58:
1092
1093 /* __settime()
1094
1095 In: EDX Pointer to struct timeval
1096
1097 Out: EAX 0 (ok) or -1 (error)
1098 ECX errno (0 if successful)
1099
1100 Set system time and time zone. */
1101
1102 f->e.eax = do_settime ((const struct timeval *)f->e.edx, &err_no);
1103 f->e.ecx = err_no;
1104 break;
1105
1106 case 0x59:
1107
1108 /* __profil()
1109
1110 In: EDX Pointer to struct _profil
1111
1112 Out: EAX 0 (ok) or -1 (error)
1113 ECX errno (0 if successful)
1114
1115 Sampling profiler. */
1116
1117 f->e.eax = do_profil ((const struct _profil *)f->e.edx, &err_no);
1118 f->e.ecx = err_no;
1119 break;
1120
1121 case 0x5a:
1122
1123 /* __nls_ctype()
1124
1125 In: EDX Pointer to buffer
1126
1127 Mark DBCS lead bytes. */
1128
1129 f->e.eax = do_ctype ((unsigned char *)f->e.edx, &err_no);
1130 f->e.ecx = err_no;
1131 break;
1132
1133 case 0x5b:
1134
1135 /* __setsyserrno()
1136
1137 In: EDX New error number
1138 Out: EAX Old error number
1139
1140 Return old OS/2 error number for last syscall. */
1141
1142 f->e.eax = do_setsyserrno (f->e.edx);
1143 break;
1144
1145 default:
1146 if (f->b.al > 0x39)
1147 {
1148 f->e.eax = (ULONG)(-1);
1149 f->e.ecx = ENOSYS;
1150 }
1151 else
1152 bad_spec (f);
1153 break;
1154 }
1155}
1156
1157
1158static void bad_spec (syscall_frame *f)
1159{
1160 oprintf ("Invalid syscall function code: 7f%.2x\r\n", (unsigned)f->b.al);
1161 quit (255);
1162}
1163
1164
1165static ULONG do_syserrno (void)
1166{
1167 thread_data *td;
1168
1169 td = get_thread ();
1170 if (td == NULL)
1171 return (ULONG)-1;
1172 return td->prev_sys_errno;
1173}
1174
1175
1176static ULONG do_setsyserrno (ULONG errcode)
1177{
1178 thread_data *td;
1179
1180 td = get_thread ();
1181 if (td == NULL)
1182 return (ULONG)-1;
1183 td->last_sys_errno = errcode;
1184 return td->prev_sys_errno;
1185}
1186
1187/* Convert a string to upper case. */
1188
1189static void do_memupr (char *dst, ULONG size)
1190{
1191 COUNTRYCODE cc;
1192
1193 cc.country = 0;
1194 cc.codepage = 0;
1195 DosMapCase (size, &cc, dst);
1196}
1197
1198
1199/* Mark DBCS lead bytes. */
1200
1201static int do_ctype (unsigned char *dst, int *errnop)
1202{
1203 ULONG rc;
1204 unsigned i;
1205
1206 rc = get_dbcs_lead ();
1207 if (rc != 0)
1208 {
1209 *errnop = set_error (rc);
1210 return -1;
1211 }
1212 for (i = 0; i < 256; ++i)
1213 if (_nls_is_dbcs_lead (i))
1214 dst[i] |= _NLS_DBCS_LEAD;
1215 else
1216 dst[i] &= ~_NLS_DBCS_LEAD;
1217 *errnop = 0;
1218 return 0;
1219}
1220
1221
1222/* Get the number of rows and columns of the screen. */
1223
1224static void do_scrsize (int *dst)
1225{
1226 static VIOMODEINFO vmi; /* Must not cross a 64K boundary */
1227
1228 vmi.cb = sizeof (vmi);
1229 VioGetMode (&vmi, 0);
1230 dst[0] = vmi.col;
1231 dst[1] = vmi.row;
1232}
1233
1234
1235static ULONG do_read_kbd (ULONG flags)
1236{
1237 UCHAR c;
1238
1239 if (kbd_input (&c, !(flags & 4), flags & 1, flags & 2, FALSE))
1240 return c;
1241 else
1242 return (ULONG)-1;
1243}
1244
1245
1246static unsigned do_sleep (unsigned sec)
1247{
1248 if (sec == 0)
1249 {
1250 DosSleep (0);
1251 return 0;
1252 }
1253 else
1254 {
1255 ULONG start, stop, elapsed;
1256
1257 /* TODO: Don't get interrupted by ignored signals (SIG_IGN). */
1258
1259 start = querysysinfo (QSV_TIME_LOW);
1260 if (DosSleep (1000 * sec) == 0)
1261 return 0;
1262 stop = querysysinfo (QSV_TIME_LOW);
1263 elapsed = stop - start;
1264 if (sec < elapsed)
1265 return 0;
1266 return sec - elapsed;
1267 }
1268}
Note: See TracBrowser for help on using the repository browser.