ag@elgar.UUCP (Keith Gabryelski) (01/24/89)
A few days ago I was paging through my SCO XENIX 2.3.1 Release Notes and found, on page 44 (section 16), a section describing 4BSD enhancements to the current release of SCO XENIX. select(S) was mentioned specifically. I checked the rest of the 2.3 manuals to see if there was a clue on how to access select(); no dice. I tried my 2.2 dev sys libraries to see if it had been supported in previous releases and just not mentioned; negative. I decided to see if I could get select() to work on my system. And that is what this article is about. I checked /xenix and found: % nm xenix | grep select nm: xenix: too many symbols to sort # chuckle 0020:00015bec T _select Bingo! I also found <sys/select.h> (which has a comment about the select(2) system call. :-) ). When a system call is made in a C program on a Unix system (eg open(2)), it actually links in a file from libc.a (/lib/libc.a) (in this case `open.o') written in assembly that loads a register with a system call number and causes an exception to occur. The `trap' instruction is used on the 68000, on a vax it's `chmk', and on a 370 it's `svc'. Control is transfered to the kernel which (in the case of this particular exception) will index the register into a table (called the sysent table) to get the address of the actual routine in kernel memory to call (_open). At least under SCO XENIX this algorithm is modified somewhat. When a system call is made in a C program on a SCO XENIX system (eg open(S)), it links in a file from libc.a (/lib/386/Slibc.a) (in this case `open.o') written in assembly that loads the register `eax' with a system call number and jumps to 7:0 which (a guess) is mapped to an instruction that switches into supervisory mode and jumps to the routine ioint (??) in the kernel address space. The interrupt routine hands the system call number (along with the user given arguments) to _trap with figures out what to sysent table to use (there are a few under SCO XENIX) and does the right thing. The _open routine (in libc.a's open.o) would probably look something like: ; ; open - open a file for reading or writing ; title open .386 SYSNUM equ 5 ; open's system call number is `5'. extrn _errno:dword public _open _TEXT segment dword use32 public 'CODE' assume cs: _TEXT _open proc near mov eax, SYSNUM ; Get system call number. ; ; I don't even pretend to understand masm syntax. I tried ; the following line (and variations) without any success. ; ; call far 7:0 ; Switch to kernel and call SYSNUM. ; ; Don't laugh, it works. ; db 9ah dw 0,0 dw 7 jb short _cerror ; below == error. xor eax, eax ; zero return value (no error). ret ; done. _cerror: mov _errno, eax ; Save error code in _errno. mov eax, -1 ; Return -1 (as error). ret ; done. _open endp _TEXT ends end Under SCO XENIX the sysent table (struct sysent in <sys/systm.h>) looks something like: struct sysent { unsigned char sy_ret; /* Type of return value (int, void ...) */ unsigned char sy_arg386; /* Number of 386 words args on stack */ unsigned char sy_nlarg286; /* # of 286 large model word args on stack */ unsigned char sy_nmarg286; /* 286 Small Middle: max # of args */ unsigned sy_argmask; /* Argument types on stack. */ int (*sy_call)(); /* System call address in kernel */ } sy_ret is the type return of the value this system call returns. `0' seems to be INT and `6' is probably void. sy_arg386 is the number of words the arguments for this system call take on the stack. sy_nlarg286 and sy_nmarg286 are similar to sy_arg386 but used for doing 286 stuff. I don't plan on mentioning the 286 stuff in this article that much, it just isn't interesting to me. sy_argmask is the type of args on the stack using the following table: NUM | SYMBOL | 386 | 286L | EXPLANATION 0 | | | | Arg not used. 1 | DATAP | 2 | 1 | Arg is a data pointer; seg + address 2 | TEXTP | 2 | 1 | Arg is a text pointer; seg + address 3 | CONST | 1 | 1 | Arg is an int-sized constant 4 | UCONST | 1 | 1 | Arg is an unsigned int-sized constant 5 | LCONST | 1 | 1 | Arg is a long-sized constant 6 | FDATAP | 1 | 1 | Arg is FAR data pointer. 7 | SODATAP | 2 | | 386: 32-bit offset. | | | 1 | 286: low word is 16 bit data pointer offset, | | | | high word is 16 bit selector. 8 | SOTEXTP | 2 | | 386: 32-bit offset. | | | 1 | 286: low word is 16 bit text pointer offset, | | | | high word is 16 bit selector. Each nybble in sy_argmask represents one argument passed to the system call. Bits 0-3 represent arg one; 4-7 arg two; 8-12 arg three; etc. A total of eight arguments (4 bits times 8 args = 32 bits in an int) can be passed to a function (although MASK, a macro used to make sysent's sy_argmask field is limited to six arguments). NUM is the number (put in each nybble) represented by the SYMBOL (in <sys/systm.h>) that corresponds to the arg type EXPLANATION and takes [386|286] (depending on the model you are using) words on the user stack. So, for the open() system call: sy_argmask is 0x00000331 and sy_arg386 is 0x04. open(char *path, int oflag, int mode); ^^^^^^ ^^^ ^^^ DATAP CONST CONST sy_call is the pointer to the function in kernel memory that should handle this system call request. The sysent table on my system looks something like: Syscal Num | ret| 386| L | SM | Arg Types | System Call sysent: 00 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _nosys 01 | 00 | 02 | 01 | 05 | 0 0 0 0 0 0 0 1 | _rexit 02 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _fork 03 | 00 | 04 | 03 | 03 | 0 0 0 0 0 4 1 3 | _read 04 | 00 | 04 | 03 | 03 | 0 0 0 0 0 4 1 3 | _write 05 | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 3 1 | _open 06 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _close 07 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _wait 08 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 1 | _creat 09 | 00 | 04 | 02 | 03 | 0 0 0 0 0 0 1 1 | _link 0a | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _unlink 0b | 00 | 04 | 02 | 03 | 0 0 0 0 0 0 1 1 | _exec 0c | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _chdir 0d | 00 | 00 | 00 | 05 | 0 0 0 0 0 0 0 0 | _gtime 0e | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 3 1 | _mknod 0f | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 1 | _chmod 10 | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 3 1 | _chown 11 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 7 | _brk 12 | 00 | 04 | 02 | 03 | 0 0 0 0 0 0 1 1 | _stat 13 | 00 | 04 | 03 | 05 | 0 0 0 0 0 3 5 3 | _seek 14 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _getpid 15 | 00 | 05 | 03 | 03 | 0 0 0 0 0 3 1 1 | _smount 16 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _sumount 17 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 4 | _setuid 18 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _getuid 19 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 5 | _stime 1a | 00 | 05 | 04 | 03 | 0 0 0 0 3 1 3 3 | _ptrace 1b | 00 | 01 | 01 | 04 | 0 0 0 0 0 0 0 3 | _alarm 1c | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 1 3 | _fstat 1d | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _pause 1e | 00 | 04 | 02 | 03 | 0 0 0 0 0 0 1 1 | _utime 1f | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 1 3 | _stty 20 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 1 3 | _gtty 21 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 1 | _saccess 22 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _nice 23 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | 24 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _sync 25 | 00 | 02 | 02 | 03 | 0 0 0 0 0 0 3 3 | _kill 26 | 00 | 00 | 01 | 00 | 0 0 0 0 0 0 0 0 | 27 | 00 | 00 | 02 | 00 | 0 0 0 0 0 0 0 0 | 28 | 00 | 00 | 03 | 00 | 0 0 0 0 0 0 0 0 | 29 | 00 | 02 | 02 | 03 | 0 0 0 0 0 0 3 3 | _dup 2a | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _pipe 2b | 00 | 02 | 01 | 05 | 0 0 0 0 0 0 0 1 | _times 2c | 06 | 08 | 05 | 03 | 0 0 0 1 4 8 4 1 | _profil 2d | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _lock 2e | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 4 | _setgid 2f | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _getgid 30 | 00 | 03 | 02 | 02 | 0 0 0 0 0 0 2 3 | _ssig 31 | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 3 | _msgsys 32 | 06 | 07 | 04 | 03 | 0 0 0 0 5 5 1 3 | _sysi86 33 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _sysacct 34 | 00 | 00 | 01 | 06 | 0 0 0 0 0 0 0 3 | _shmsys 35 | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 3 | _semsys 36 | 00 | 04 | 03 | 03 | 0 0 0 0 0 7 3 3 | _ioctl 37 | 00 | 00 | 04 | 00 | 0 0 0 0 0 0 0 0 | 38 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 39 | 00 | 00 | 05 | 00 | 0 0 0 0 0 0 0 0 | 3a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 3b | 00 | 06 | 03 | 03 | 0 0 0 0 0 1 1 1 | _exece 3c | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _umask 3d | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _chroot 3e | 00 | 00 | 06 | 00 | 0 0 0 0 0 0 0 0 | 3f | 00 | 00 | 07 | 00 | 0 0 0 0 0 0 0 0 | 40 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 41 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 42 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 43 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 44 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 45 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 46 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 47 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 48 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 49 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4d | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4e | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4f | 00 | 00 | 08 | 00 | 0 0 0 0 0 0 0 0 | 50 | 00 | 00 | 09 | 00 | 0 0 0 0 0 0 0 0 | 51 | 00 | 04 | 03 | 03 | 0 0 0 0 0 4 1 3 | _getdents 52 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 53 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 54 | 00 | 00 | 0a | 00 | 0 0 0 0 0 0 0 0 | 55 | 00 | 06 | 04 | 03 | 0 0 0 0 3 1 1 3 | _getmsg 56 | 00 | 06 | 04 | 03 | 0 0 0 0 3 1 1 3 | _putmsg 57 | 00 | 05 | 03 | 03 | 0 0 0 0 0 3 5 1 | _poll 58 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 59 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5d | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5e | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5f | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 60 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 61 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 62 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 63 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 64 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 65 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 66 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 67 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 68 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 69 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6d | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6e | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6f | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 70 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 71 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 72 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 73 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 74 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 75 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 76 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 77 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 78 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 79 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7d | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7e | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7f | 00 | 05 | 05 | 0a | 0 0 0 0 0 0 0 0 | _clocal _v7sysent: 00 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | 01 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _ftime 02 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 03 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nullsys 04 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 05 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 06 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 07 | 00 | 05 | 05 | 0a | 0 0 0 0 0 0 0 0 | _clocal 08 | 00 | 00 | 00 | 08 | 0 0 0 0 0 0 0 0 | _cxenix 09 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 0a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 0b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys _s3sysent: 01 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | 02 | 00 | 06 | 04 | 03 | 0 0 0 0 3 3 1 1 | _statfs 03 | 00 | 05 | 04 | 03 | 0 0 0 0 3 3 1 3 | _fstatfs 04 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _setpgrp 05 | 00 | 00 | 00 | 08 | 0 0 0 0 0 0 0 0 | _cxenix 06 | 00 | 04 | 03 | 03 | 0 0 0 0 0 1 3 3 | _uadmin 07 | 00 | 00 | 00 | 09 | 0 0 0 0 0 0 0 0 | _utssys 08 | 00 | 03 | 03 | 03 | 0 0 0 0 0 3 3 3 | _fcntl 09 | 00 | 03 | 02 | 05 | 0 0 0 0 0 0 5 3 | _ulimit 0a | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 1 | _rmdir 0b | 00 | 00 | 02 | 03 | 0 0 0 0 0 0 3 1 | _mkdir 0c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys _svidsysent: 01 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | 02 | 00 | 06 | 04 | 03 | 0 0 0 0 3 3 1 1 | _statfs 03 | 00 | 05 | 04 | 03 | 0 0 0 0 3 3 1 3 | _fstatfs 04 | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 3 | _setpgrp 05 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 06 | 00 | 00 | 03 | 03 | 0 0 0 0 0 1 3 3 | _uadmin 07 | 00 | 00 | 00 | 09 | 0 0 0 0 0 0 0 0 | _utssys 08 | 00 | 00 | 03 | 03 | 0 0 0 0 0 3 3 3 | _fcntl 09 | 00 | 00 | 02 | 05 | 0 0 0 0 0 0 5 3 | _ulimit 0a | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 1 | _rmdir 0b | 00 | 00 | 02 | 03 | 0 0 0 0 0 0 3 1 | _mkdir 0c | 00 | 00 | 03 | 03 | 0 0 0 0 0 0 0 0 | _nosys _clentry: used for oem CLOCAL routines. Empty on my system. _cxentry: used for SCO added stuff. 00 | 00 | 05 | 03 | 03 | 0 0 0 0 0 4 7 1 | _shutdown 01 | 00 | 04 | 03 | 03 | 0 0 0 0 0 7 3 3 | _locking 02 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 1 | _creatsem 03 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _opensem 04 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _sigsem 05 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _waitsem 06 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _nbwaitsem 07 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _rdchk 08 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 4 | _stkgrow 09 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 0a | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 5 3 | _chsize 0b | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _ftime 0c | 00 | 02 | 01 | 05 | 0 0 0 0 0 0 0 5 | _nap 0d | 00 | 05 | 04 | 01 | 0 0 0 0 3 4 3 1 | _sdget 0e | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 7 | _sdfree 0f | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 7 | _sdenter 10 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 7 | _sdleave 11 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 7 | _sdgetv 12 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 7 | _sdwaitv 13 | 00 | 05 | 03 | 01 | 0 0 0 0 0 7 5 3 | _brkctl 14 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 15 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 1 3 | _nfs_sys 16 | 00 | 04 | 03 | 03 | 0 0 0 0 0 1 3 3 | _msgctl 17 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 5 | _msgget 18 | 00 | 05 | 04 | 03 | 0 0 0 0 3 3 1 3 | _msgsnd 19 | 06 | 07 | 05 | 03 | 0 0 0 3 5 3 1 3 | _msgrcv 1a | 00 | 05 | 04 | 03 | 0 0 0 0 7 3 4 3 | _semctl 1b | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 3 5 | _semget 1c | 00 | 04 | 03 | 03 | 0 0 0 0 0 4 1 3 | _semop 1d | 00 | 04 | 03 | 03 | 0 0 0 0 0 1 3 3 | _shmctl 1e | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 4 5 | _shmget 1f | 00 | 04 | 03 | 06 | 0 0 0 0 0 3 7 3 | _shmat 20 | 00 | 04 | 03 | 03 | 0 0 0 0 0 1 3 3 | _proctl 21 | 00 | 03 | 00 | 06 | 0 0 0 0 0 0 3 7 | _execseg 22 | 00 | 02 | 00 | 03 | 0 0 0 0 0 0 0 7 | _unexecseg 23 | 00 | 00 | 03 | 03 | 0 0 0 0 0 5 5 1 | _swapon 24 | 00 | 09 | 05 | 03 | 0 0 0 1 1 1 1 3 | _select I couldn't really figure out how uadmin() was accessed. libc's uadmin.o links in a routine that calls system call 0x37. Hmmm... The _cxentry is accessed by (documented in the programmer's reference under System Calls) setting a bit in the system call number. It seems as though it actually shifts the system call number up half a word and puts 0x28 in the low order halfword. Now we see that select() exists as a cxenix function (number 0x24), There is also poll(), putmsg(), and getmsg() -- streams stuff. Since the tty device is not a streams device (actually it looks as if the streams stuff has been nulled out -- look at the master file for more information) it is highly unlikely that these routines will do anything useful. Infact, they don't. Change the SYSNUM (and symbols) in the example open.s above to their appropriate values to try out the streams routines. select.s looks something like: ; select ; ; ; title select .386 SYSNUM equ 2428h extrn _errno:dword public _select _TEXT segment dword use32 public 'CODE' assume cs: _TEXT _select proc near mov eax, SYSNUM ; Get system call number. ; ; I don't even pretend to understand masm syntax. I tried ; the following line (and variations) without any success. ; ; call far 7:0 ; Switch to kernel and call SYSNUM. ; ; Don't laugh, it works. ; db 9ah dw 0,0 dw 7 jb short _cerror ; below == error. xor eax, eax ; zero return value (no error). ret ; done. _cerror: mov _errno, eax ; Save error code in _errno. mov eax, -1 ; Return -1 (as error). ret ; done. _select endp _TEXT ends end There is a header file you'll need in <sys/select.h> which has some information in it. A Synopsis of the SCO XENIX implementation: #include <sys/select.h> nfds = select(width readfds, writefds, exceptfds, timeout) int width, *readfds, *writefds, *exceptfds; struct timeval *timeout; /* timeval is a pointer to a structure */ I tested select() and found it to be half way implemented. It seems as if there must be some extra field in struct cdevsw <sys/conf.h>. So, I guess I wait 'til 3.2. Pax, Keith Ps, FYI. Pps, if I made a mistake in my description of system call handling on SCO XENIX or what not, please correct me. Ppps, `call far 7:0' seems really reasonable to me. -- ag@elgar.CTS.COM Keith Gabryelski ...!{ucsd, crash}!elgar!ag
ag@elgar.UUCP (Keith Gabryelski) (01/25/89)
select.s and open.s will be much more reasonable if you remove the lines containing `xor eax,eax'. My apologies, I do not know what came over me. pax, Keith Ps, I have syscall.s which allows one to execute a system call with arguments of the form: syscall(sysnum, arg1, arg2, arg2, ... ); If there is sufficient interest, I will post it. -- ag@elgar.CTS.COM Keith Gabryelski ...!{ucsd, crash}!elgar!ag
ag@elgar.UUCP (Keith Gabryelski) (01/28/89)
I posted this a week ago and it seems it never got out. Here it is again. From ag Mon Jan 23 22:58:37 PST 1989 A few days ago I was paging through my SCO XENIX 2.3.1 Release Notes and found, on page 44 (section 16), a section describing 4BSD enhancements to the current release of SCO XENIX. select(S) was mentioned specifically. I checked the rest of the 2.3 manuals to see if there was a clue on how to access select(); no dice. I tried my 2.2 dev sys libraries to see if it had been supported in previous releases and just not mentioned; negative. I decided to see if I could get select() to work on my system. And that is what this article is about. I checked /xenix and found: % nm xenix | grep select nm: xenix: too many symbols to sort # chuckle 0020:00015bec T _select Bingo! I also found <sys/select.h> (which has a comment about the select(2) system call. :-) ). When a system call is made in a C program on a Unix system (eg open(2)), it actually links in a file from libc.a (/lib/libc.a) (in this case `open.o') written in assembly that loads a register with a system call number and causes an exception to occur. The `trap' instruction is used on the 68000, on a vax it's `chmk', and on a 370 it's `svc'. Control is transfered to the kernel which (in the case of this particular exception) will index the register into a table (called the sysent table) to get the address of the actual routine in kernel memory to call (_open). At least under SCO XENIX this algorithm is modified somewhat. When a system call is made in a C program on a SCO XENIX system (eg open(S)), it links in a file from libc.a (/lib/386/Slibc.a) (in this case `open.o') written in assembly that loads the register `eax' with a system call number and jumps to 7:0 which (a guess) is mapped to an instruction that switches into supervisory mode and jumps to the routine ioint (??) in the kernel address space. The interrupt routine hands the system call number (along with the user given arguments) to _trap with figures out what to sysent table to use (there are a few under SCO XENIX) and does the right thing. The _open routine (in libc.a's open.o) would probably look something like: ; ; open - open a file for reading or writing ; title open .386 SYSNUM equ 5 ; open's system call number is `5'. extrn _errno:dword public _open _TEXT segment dword use32 public 'CODE' assume cs: _TEXT _open proc near mov eax, SYSNUM ; Get system call number. ; ; I don't even pretend to understand masm syntax. I tried ; the following line (and variations) without any success. ; ; call far 7:0 ; Switch to kernel and call SYSNUM. ; ; Don't laugh, it works. ; db 9ah dw 0,0 dw 7 jb short _cerror ; below == error. ret ; done. _cerror: mov _errno, eax ; Save error code in _errno. mov eax, -1 ; Return -1 (as error). ret ; done. _open endp _TEXT ends end Under SCO XENIX the sysent table (struct sysent in <sys/systm.h>) looks something like: struct sysent { unsigned char sy_ret; /* Type of return value (int, void ...) */ unsigned char sy_arg386; /* Number of 386 words args on stack */ unsigned char sy_nlarg286; /* # of 286 large model word args on stack */ unsigned char sy_nmarg286; /* 286 Small Middle: max # of args */ unsigned sy_argmask; /* Argument types on stack. */ int (*sy_call)(); /* System call address in kernel */ } sy_ret is the type return of the value this system call returns. `0' seems to be INT and `6' is probably void. sy_arg386 is the number of words the arguments for this system call take on the stack. sy_nlarg286 and sy_nmarg286 are similar to sy_arg386 but used for doing 286 stuff. I don't plan on mentioning the 286 stuff in this article that much, it just isn't interesting to me. sy_argmask is the type of args on the stack using the following table: NUM | SYMBOL | 386 | 286L | EXPLANATION 0 | | | | Arg not used. 1 | DATAP | 2 | 1 | Arg is a data pointer; seg + address 2 | TEXTP | 2 | 1 | Arg is a text pointer; seg + address 3 | CONST | 1 | 1 | Arg is an int-sized constant 4 | UCONST | 1 | 1 | Arg is an unsigned int-sized constant 5 | LCONST | 1 | 1 | Arg is a long-sized constant 6 | FDATAP | 1 | 1 | Arg is FAR data pointer. 7 | SODATAP | 2 | | 386: 32-bit offset. | | | 1 | 286: low word is 16 bit data pointer offset, | | | | high word is 16 bit selector. 8 | SOTEXTP | 2 | | 386: 32-bit offset. | | | 1 | 286: low word is 16 bit text pointer offset, | | | | high word is 16 bit selector. Each nybble in sy_argmask represents one argument passed to the system call. Bits 0-3 represent arg one; 4-7 arg two; 8-12 arg three; etc. A total of eight arguments (4 bits times 8 args = 32 bits in an int) can be passed to a function (although MASK, a macro used to make sysent's sy_argmask field is limited to six arguments). NUM is the number (put in each nybble) represented by the SYMBOL (in <sys/systm.h>) that corresponds to the arg type EXPLANATION and takes [386|286] (depending on the model you are using) words on the user stack. So, for the open() system call: sy_argmask is 0x00000331 and sy_arg386 is 0x04. open(char *path, int oflag, int mode); ^^^^^^ ^^^ ^^^ DATAP CONST CONST sy_call is the pointer to the function in kernel memory that should handle this system call request. The sysent table on my system looks something like: Syscal Num | ret| 386| L | SM | Arg Types | System Call sysent: 00 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _nosys 01 | 00 | 02 | 01 | 05 | 0 0 0 0 0 0 0 1 | _rexit 02 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _fork 03 | 00 | 04 | 03 | 03 | 0 0 0 0 0 4 1 3 | _read 04 | 00 | 04 | 03 | 03 | 0 0 0 0 0 4 1 3 | _write 05 | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 3 1 | _open 06 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _close 07 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _wait 08 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 1 | _creat 09 | 00 | 04 | 02 | 03 | 0 0 0 0 0 0 1 1 | _link 0a | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _unlink 0b | 00 | 04 | 02 | 03 | 0 0 0 0 0 0 1 1 | _exec 0c | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _chdir 0d | 00 | 00 | 00 | 05 | 0 0 0 0 0 0 0 0 | _gtime 0e | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 3 1 | _mknod 0f | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 1 | _chmod 10 | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 3 1 | _chown 11 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 7 | _brk 12 | 00 | 04 | 02 | 03 | 0 0 0 0 0 0 1 1 | _stat 13 | 00 | 04 | 03 | 05 | 0 0 0 0 0 3 5 3 | _seek 14 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _getpid 15 | 00 | 05 | 03 | 03 | 0 0 0 0 0 3 1 1 | _smount 16 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _sumount 17 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 4 | _setuid 18 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _getuid 19 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 5 | _stime 1a | 00 | 05 | 04 | 03 | 0 0 0 0 3 1 3 3 | _ptrace 1b | 00 | 01 | 01 | 04 | 0 0 0 0 0 0 0 3 | _alarm 1c | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 1 3 | _fstat 1d | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _pause 1e | 00 | 04 | 02 | 03 | 0 0 0 0 0 0 1 1 | _utime 1f | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 1 3 | _stty 20 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 1 3 | _gtty 21 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 1 | _saccess 22 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _nice 23 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | 24 | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _sync 25 | 00 | 02 | 02 | 03 | 0 0 0 0 0 0 3 3 | _kill 26 | 00 | 00 | 01 | 00 | 0 0 0 0 0 0 0 0 | 27 | 00 | 00 | 02 | 00 | 0 0 0 0 0 0 0 0 | 28 | 00 | 00 | 03 | 00 | 0 0 0 0 0 0 0 0 | 29 | 00 | 02 | 02 | 03 | 0 0 0 0 0 0 3 3 | _dup 2a | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _pipe 2b | 00 | 02 | 01 | 05 | 0 0 0 0 0 0 0 1 | _times 2c | 06 | 08 | 05 | 03 | 0 0 0 1 4 8 4 1 | _profil 2d | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _lock 2e | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 4 | _setgid 2f | 00 | 00 | 00 | 03 | 0 0 0 0 0 0 0 0 | _getgid 30 | 00 | 03 | 02 | 02 | 0 0 0 0 0 0 2 3 | _ssig 31 | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 3 | _msgsys 32 | 06 | 07 | 04 | 03 | 0 0 0 0 5 5 1 3 | _sysi86 33 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _sysacct 34 | 00 | 00 | 01 | 06 | 0 0 0 0 0 0 0 3 | _shmsys 35 | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 3 | _semsys 36 | 00 | 04 | 03 | 03 | 0 0 0 0 0 7 3 3 | _ioctl 37 | 00 | 00 | 04 | 00 | 0 0 0 0 0 0 0 0 | 38 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 39 | 00 | 00 | 05 | 00 | 0 0 0 0 0 0 0 0 | 3a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 3b | 00 | 06 | 03 | 03 | 0 0 0 0 0 1 1 1 | _exece 3c | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _umask 3d | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _chroot 3e | 00 | 00 | 06 | 00 | 0 0 0 0 0 0 0 0 | 3f | 00 | 00 | 07 | 00 | 0 0 0 0 0 0 0 0 | 40 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 41 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 42 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 43 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 44 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 45 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 46 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 47 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 48 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 49 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4d | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4e | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 4f | 00 | 00 | 08 | 00 | 0 0 0 0 0 0 0 0 | 50 | 00 | 00 | 09 | 00 | 0 0 0 0 0 0 0 0 | 51 | 00 | 04 | 03 | 03 | 0 0 0 0 0 4 1 3 | _getdents 52 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 53 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 54 | 00 | 00 | 0a | 00 | 0 0 0 0 0 0 0 0 | 55 | 00 | 06 | 04 | 03 | 0 0 0 0 3 1 1 3 | _getmsg 56 | 00 | 06 | 04 | 03 | 0 0 0 0 3 1 1 3 | _putmsg 57 | 00 | 05 | 03 | 03 | 0 0 0 0 0 3 5 1 | _poll 58 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 59 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5d | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5e | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 5f | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 60 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 61 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 62 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 63 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 64 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 65 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 66 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 67 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 68 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 69 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6d | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6e | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 6f | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 70 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 71 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 72 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 73 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 74 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 75 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 76 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 77 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 78 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 79 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7d | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7e | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 7f | 00 | 05 | 05 | 0a | 0 0 0 0 0 0 0 0 | _clocal _v7sysent: 00 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | 01 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _ftime 02 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 03 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nullsys 04 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 05 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 06 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 07 | 00 | 05 | 05 | 0a | 0 0 0 0 0 0 0 0 | _clocal 08 | 00 | 00 | 00 | 08 | 0 0 0 0 0 0 0 0 | _cxenix 09 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 0a | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 0b | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys _s3sysent: 01 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | 02 | 00 | 06 | 04 | 03 | 0 0 0 0 3 3 1 1 | _statfs 03 | 00 | 05 | 04 | 03 | 0 0 0 0 3 3 1 3 | _fstatfs 04 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _setpgrp 05 | 00 | 00 | 00 | 08 | 0 0 0 0 0 0 0 0 | _cxenix 06 | 00 | 04 | 03 | 03 | 0 0 0 0 0 1 3 3 | _uadmin 07 | 00 | 00 | 00 | 09 | 0 0 0 0 0 0 0 0 | _utssys 08 | 00 | 03 | 03 | 03 | 0 0 0 0 0 3 3 3 | _fcntl 09 | 00 | 03 | 02 | 05 | 0 0 0 0 0 0 5 3 | _ulimit 0a | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 1 | _rmdir 0b | 00 | 00 | 02 | 03 | 0 0 0 0 0 0 3 1 | _mkdir 0c | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys _svidsysent: 01 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | 02 | 00 | 06 | 04 | 03 | 0 0 0 0 3 3 1 1 | _statfs 03 | 00 | 05 | 04 | 03 | 0 0 0 0 3 3 1 3 | _fstatfs 04 | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 3 | _setpgrp 05 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 06 | 00 | 00 | 03 | 03 | 0 0 0 0 0 1 3 3 | _uadmin 07 | 00 | 00 | 00 | 09 | 0 0 0 0 0 0 0 0 | _utssys 08 | 00 | 00 | 03 | 03 | 0 0 0 0 0 3 3 3 | _fcntl 09 | 00 | 00 | 02 | 05 | 0 0 0 0 0 0 5 3 | _ulimit 0a | 00 | 00 | 01 | 03 | 0 0 0 0 0 0 0 1 | _rmdir 0b | 00 | 00 | 02 | 03 | 0 0 0 0 0 0 3 1 | _mkdir 0c | 00 | 00 | 03 | 03 | 0 0 0 0 0 0 0 0 | _nosys _clentry: used for oem CLOCAL routines. Empty on my system. _cxentry: used for SCO added stuff. 00 | 00 | 05 | 03 | 03 | 0 0 0 0 0 4 7 1 | _shutdown 01 | 00 | 04 | 03 | 03 | 0 0 0 0 0 7 3 3 | _locking 02 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 1 | _creatsem 03 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _opensem 04 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _sigsem 05 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _waitsem 06 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _nbwaitsem 07 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 3 | _rdchk 08 | 00 | 01 | 01 | 03 | 0 0 0 0 0 0 0 4 | _stkgrow 09 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 0a | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 5 3 | _chsize 0b | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 1 | _ftime 0c | 00 | 02 | 01 | 05 | 0 0 0 0 0 0 0 5 | _nap 0d | 00 | 05 | 04 | 01 | 0 0 0 0 3 4 3 1 | _sdget 0e | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 7 | _sdfree 0f | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 7 | _sdenter 10 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 7 | _sdleave 11 | 00 | 02 | 01 | 03 | 0 0 0 0 0 0 0 7 | _sdgetv 12 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 7 | _sdwaitv 13 | 00 | 05 | 03 | 01 | 0 0 0 0 0 7 5 3 | _brkctl 14 | 00 | 00 | 00 | 00 | 0 0 0 0 0 0 0 0 | _nosys 15 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 1 3 | _nfs_sys 16 | 00 | 04 | 03 | 03 | 0 0 0 0 0 1 3 3 | _msgctl 17 | 00 | 03 | 02 | 03 | 0 0 0 0 0 0 3 5 | _msgget 18 | 00 | 05 | 04 | 03 | 0 0 0 0 3 3 1 3 | _msgsnd 19 | 06 | 07 | 05 | 03 | 0 0 0 3 5 3 1 3 | _msgrcv 1a | 00 | 05 | 04 | 03 | 0 0 0 0 7 3 4 3 | _semctl 1b | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 3 5 | _semget 1c | 00 | 04 | 03 | 03 | 0 0 0 0 0 4 1 3 | _semop 1d | 00 | 04 | 03 | 03 | 0 0 0 0 0 1 3 3 | _shmctl 1e | 00 | 04 | 03 | 03 | 0 0 0 0 0 3 4 5 | _shmget 1f | 00 | 04 | 03 | 06 | 0 0 0 0 0 3 7 3 | _shmat 20 | 00 | 04 | 03 | 03 | 0 0 0 0 0 1 3 3 | _proctl 21 | 00 | 03 | 00 | 06 | 0 0 0 0 0 0 3 7 | _execseg 22 | 00 | 02 | 00 | 03 | 0 0 0 0 0 0 0 7 | _unexecseg 23 | 00 | 00 | 03 | 03 | 0 0 0 0 0 5 5 1 | _swapon 24 | 00 | 09 | 05 | 03 | 0 0 0 1 1 1 1 3 | _select I couldn't really figure out how uadmin() was accessed. libc's uadmin.o links in a routine that calls system call 0x37. Hmmm... The _cxentry is accessed by (documented in the programmer's reference under System Calls) setting a bit in the system call number. It seems as though it actually shifts the system call number up half a word and puts 0x28 in the low order halfword. Now we see that select() exists as a cxenix function (number 0x24), There is also poll(), putmsg(), and getmsg() -- streams stuff. Since the tty device is not a streams device (actually it looks as if the streams stuff has been nulled out -- look at the master file for more information) it is highly unlikely that these routines will do anything useful. Infact, they don't. Change the SYSNUM (and symbols) in the example open.s above to their appropriate values to try out the streams routines. select.s looks something like: ; select ; ; ; title select .386 SYSNUM equ 2428h extrn _errno:dword public _select _TEXT segment dword use32 public 'CODE' assume cs: _TEXT _select proc near mov eax, SYSNUM ; Get system call number. ; ; I don't even pretend to understand masm syntax. I tried ; the following line (and variations) without any success. ; ; call far 7:0 ; Switch to kernel and call SYSNUM. ; ; Don't laugh, it works. ; db 9ah dw 0,0 dw 7 jb short _cerror ; below == error. ret ; done. _cerror: mov _errno, eax ; Save error code in _errno. mov eax, -1 ; Return -1 (as error). ret ; done. _select endp _TEXT ends end There is a header file you'll need in <sys/select.h> which has some information in it. A Synopsis of the SCO XENIX implementation: #include <sys/select.h> nfds = select(width readfds, writefds, exceptfds, timeout) int width, *readfds, *writefds, *exceptfds; struct timeval *timeout; /* timeval is a pointer to a structure */ I tested select() and found it to be half way implemented. It seems as if there must be some extra field in struct cdevsw <sys/conf.h>. So, I guess I wait 'til 3.2. Pax, Keith Ps, FYI. Pps, if I made a mistake in my description of system call handling on SCO XENIX or what not, please correct me. Ppps, `call far 7:0' seems really reasonable to me. Pppps, Here is syscall.s with some documentation. --- ag@elgar.CTS.COM Keith Gabryelski ...!{ucsd, crash}!elgar!ag #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # syscall.s # syscall.S # This archive created: Fri Jan 27 10:13:42 1989 export PATH; PATH=/bin:$PATH if test -f 'syscall.s' then echo shar: will not over-write existing file "'syscall.s'" else cat << \SHAR_EOF > 'syscall.s' ; ; syscall ; ; title syscall .386 extrn _errno:dword public _syscall _TEXT segment dword use32 public 'CODE' assume cs: _TEXT _syscall proc near pop ebx ; Get return address. mov eax,[esp] ; Get system call number. ; ; I don't even pretend to understand masm syntax. I tried ; the following line (and variations) without any success. ; ; call far 7:0 ; Switch to kernel and call SYSNUM. ; ; Don't laugh, it works. ; db 9ah dw 0,0 dw 7 push ebx ; Push return address. ; This also puts the stack frame ; back to its correct length. jb short _cerror ; below == error. ret ; done _cerror: mov _errno, eax ; Save error code in _errno. mov eax, -1 ; Return -1 (as error). ret ; done. _syscall endp _TEXT ends end SHAR_EOF fi # end of overwriting check if test -f 'syscall.S' then echo shar: will not over-write existing file "'syscall.S'" else cat << \SHAR_EOF > 'syscall.S' .TH SYSCALL S .DA "January 24, 1989" .SH Name syscall - Call a system subroutine. .SH Syntax .nf syscall (sysnum[, arg1][, arg2][,...]) int sysnum; .fi .SH Description .B sysnum is the System Call Number (defined below) that should be called. All arguments, sans .B sysnum, are passed unchanged to the system call. A System Call Number is a unique number that identifies a kernel subroutine that a user may call. The following table should be used for SCO XENIX 2.3 System Call Numbers: .RS .nf 00 _nosys | 10 _chown | 20 _gtty | 30 _ssig 01 _rexit | 11 _brk | 21 _saccess | 31 _msgsys 02 _fork | 12 _stat | 22 _nice | 32 _sysi86 03 _read | 13 _seek | 23 | 33 _sysacct 04 _write | 14 _getpid | 24 _sync | 34 _shmsys 05 _open | 15 _smount | 25 _kill | 35 _semsys 06 _close | 16 _sumount | 26 | 36 _ioctl 07 _wait | 17 _setuid | 27 | 37 08 _creat | 18 _getuid | 28 | 38 _nosys 09 _link | 19 _stime | 29 _dup | 39 0a _unlink | 1a _ptrace | 2a _pipe | 3a _nosys 0b _exec | 1b _alarm | 2b _times | 3b _exece 0c _chdir | 1c _fstat | 2c _profil | 3c _umask 0d _gtime | 1d _pause | 2d _lock | 3d _chroot 0e _mknod | 1e _utime | 2e _setgid | 3e 0f _chmod | 1f _stty | 2f _getgid | 3f 40 _nosys | 50 | 60 _nosys | 70 _nosys 41 _nosys | 51 _getdents | 61 _nosys | 71 _nosys 42 _nosys | 52 _nosys | 62 _nosys | 72 _nosys 43 _nosys | 53 _nosys | 63 _nosys | 73 _nosys 44 _nosys | 54 | 64 _nosys | 74 _nosys 45 _nosys | 55 _getmsg | 65 _nosys | 75 _nosys 46 _nosys | 56 _putmsg | 66 _nosys | 76 _nosys 47 _nosys | 57 _poll | 67 _nosys | 77 _nosys 48 _nosys | 58 _nosys | 68 _nosys | 78 _nosys 49 _nosys | 59 _nosys | 69 _nosys | 79 _nosys 4a _nosys | 5a _nosys | 6a _nosys | 7a _nosys 4b _nosys | 5b _nosys | 6b _nosys | 7b _nosys 4c _nosys | 5c _nosys | 6c _nosys | 7c _nosys 4d _nosys | 5d _nosys | 6d _nosys | 7d _nosys 4e _nosys | 5e _nosys | 6e _nosys | 7e _nosys 4f | 5f _nosys | 6f _nosys | 7f _clocal .fi .RE SCO XENIX also supplies a table for XENIX add-ons (ie, non-sv/v7/s3 system calls), this table is called the cxenix table. To access cxenix() fuctions use the following table: .RS .nf 28 _shutdown | 828 _stkgrow | 1028 _sdleave 128 _locking | 928 _nosys | 1128 _sdgetv 228 _creatsem | a28 _chsize | 1228 _sdwaitv 328 _opensem | b28 _ftime | 1328 _brkctl 428 _sigsem | c28 _nap | 1428 _nosys 528 _waitsem | d28 _sdget | 1528 _nfs_sys 628 _nbwaitsem | e28 _sdfree | 1628 _msgctl 728 _rdchk | f28 _sdenter | 1728 _msgget 1828 _msgsnd | 2028 _proctl 1928 _msgrcv | 2128 _execseg 1a28 _semctl | 2228 _unexecseg 1b28 _semget | 2328 _swapon 1c28 _semop | 2428 _select 1d28 _shmctl 1e28 _shmget 1f28 _shmat .fi .RE .SH Return Value syscall() does not return a value per se. The return value is the return value from the system called invoked. The return value is undefined if an invalid system call made, although the process will receive a SIGSYS signal. .SH Example The following two lines are equivalent in that they will both call open() with three arguments; "/tmp/foobar" as path, O_CREAT|O_RDWR as oflag, and 0666 as mode: .RS open("/tmp/foobar", O_CREAT|O_RDWR, 0666); syscall(5, "/tmp/foobar", O_CREAT|O_RDWR, 0666); .RE The following two lines will invoke nap() with an argument of (long)10. .RS nap(10L); syscall(0xc28, 10L); .RE .SH Author syscall was written by Keith Gabryelski (ag@wheaties.ai.mit.edu). It is public domain. SHAR_EOF fi # end of overwriting check # End of shell archive exit 0 -- ag@elgar.CTS.COM Keith Gabryelski ...!{ucsd, crash}!elgar!ag
daveh@marob.MASA.COM (Dave Hammond) (01/28/89)
In article <40@elgar.UUCP> ag@elgar.UUCP (Keith Gabryelski) bares
the truth about SCO's as-yet-unimplemented select() syscall.
On further investigation, I found the macros used to manipulate select()
file descriptor sets (FD_SET, FD_CLR, FD_ZERO, FD_ISSET) are already
present in <sys/types.h>.
--
Dave Hammond
...!uunet!masa.com!{marob,dsix2}!daveh
larryd1@killer.Dallas.TX.US (Larry Clark) (04/02/89)
I just updated my development environment to the latest greatest release of the 386 development system SCO offers and after reading the new docs I notice the the select() call is now supported. Does any one on the net have source that shows examples of how to use it?? I hate to reinvent the wheel. Larry D. Clark
csch@netcs.UUCP (Clemens Schrimpe) (06/24/89)
ivar@acc.uu.no (Ivar Hosteng) writes: <> I have experienced some problems using the select call in Xenix 386 V2.3.2. <> It does not seems to detect when a pipe gets ready to been read from. This is, because there is no provision to select on pipes! Why? The stuff is almost totally ported 1:1 from the Berkeley code and in BSD pipes should consist of AF_UNIX sockets, on which you can naturally select. I was very angry, when I found this out after hours of digging with adb in the kernel. But I also tried the same on a SUN under SunOS 4.0 and it doesn't work either ... seems to be a common illness ??? (I wonder, because the code for that is very simple ... ??? ...) <> I also <> have trouble using select on a serial port. When I do that the input <> turns into garbage. This does not occur when I use select on the <> multiscreen ttys (tty01-tty12). Hehe - we had just the same! Here is the solution (thanks to my colleague Stefan Koehler, who took one look at my screen, into which I had starred for hours, to find it ...) Select is implemented by an undocumented ioctl (0xFFFF == IOC_SELECT -> [sys/slect.h]) which is handled by ttiocom() for all devices using the standard SYS-V linediscipline! The ioctl-routine for the serial devices [sioioctl()] just calls ttiocom() [after some undefinable VPIX stuff ???] and if it returns NON-ZERO it calls sioparam(), which adjusts certain parameters and garbles the output! OK so far. Now: The Bug lies in the ttiocom-code within the check for IOC_SELECT. After detecting the IOC_SELECT, the ttiocom calls the select-code and returns NOTHING, which means that if EAX is non-zero (randomly) sioparam() is called and garbles the output. The Fix: (quick and dirty) Write a routine called "ttiocom", which might look like this: ttiocom(ttyp, com, arg, flag) struct tty *ttyp; int com, arg, flag; /* there should be better types for this :-) */ { if (com == IOC_SELECT) { ttselect(ttyp, flag); return(0); /*** THIS IS IMPORTANT ***/ } return(Ttiocom(ttyp, com ,arg, flag)); } Compile something like this, then use whatever you have (GNU-Emacs is great in patching strings in binaries) to patch /usr/sys/sys/libsys.a to change the original ttiocom into Ttiocom ! Link in your code and -by some magic reason- experience a full blown select on your System V / Xenix machine!!! Have fun playing around with it - Clemens Schrimpe, netCS Informationstechnik GmbH Berlin -- UUCP: csch@netcs BITNET: csch@db0tui6.BITNET ARPA/NSF: csch@garp.mit.edu PSI: PSI%45300033047::CSCH PHONE: +49-30-24 42 37 FAX: +49-30-24 38 00 BTX: 0303325016-0003 TELEX: 186672 net d
wht@tridom.uucp (Warren Tucker) (06/26/89)
In article <172@prmmbx.UUCP>, csch@netcs.UUCP (Clemens Schrimpe) writes: > in BSD pipes should consist of AF_UNIX sockets Pipes aren't implemented as sockets in Sys V-derived systems :-) -- ------------------------------------------------------------------- Warren Tucker, Tridom Corporation ...!gatech!emory!tridom!wht Sforzando (It., sfohr-tsahn'-doh). A direction to perform the tone or chord with special stress, or marked and sudden emphasis.
ivar@acc.uu.no (Ivar Hosteng) (06/27/89)
Thanks for your answer to the serial problem. I have tried your solution, but when i have linked the new kernel the computer refused to boot. It came to the Z in the boot sequence then it rebooted. I suppose you have to link in the new ttiocom routine into the kernal to make the change. If not could you be a little more spesific about how you links this program into a program? Here is my ttiocom.c in case i have made a mistake somwere: ---------------------- #include <sys/types.h> #include <sys/select.h> #include <sys/tty.h> ttiocom(ttyp, com, arg, flag) struct tty *ttyp; int com, arg, flag; { if (com == IOC_SELECT) { ttselect(ttyp,flag); return(0); } return(ttiocom(ttyp, com, arg, flag)); } ------------- I compiled this with the command cc -c ttiocom.c I changed my link_xenix file to this: -------------- [ -f xenix ] && mv xenix xenix- ld -Rd 1000 -D 18 -B 20 -A 0 -i -u start -o xenix \ start.o c.o ../io/mousconf.o uts.o oem.o space.o tab.o kid.o \ ../sys/ttiocom.o ../ml/libml.a ../mdep/libmdep.a ../sys/libsys.a \ ../xnet/libxnstub.a ../io/libio.a ../io/libiostub.a exit $? ------- I also did extract the object files from libsys.a with ar -x libsys.a and editet tty.o to rename the ttiocom() to Ttiocom(). Then i used the command ar -rc slibsys.a *.o to remake the library. After using ranlib on it i used the link_xenix and hdinstall to install the new kernel. I would be glad if sombody could tell me what i do wrong here.
jim@applix.UUCP (Jim Morton) (06/30/89)
> >SCO: Thanks for fixing the select() call bug from 2.3.1 to 2.3.2 ! > ... that the select() call was now supported, I thought I'd investigate.. > The first thing I noticed was a total lack of mention of it in the > documentation (or am I missing something?). > ... aid of the manuals wrote a test program to poll a couple of fifo's. > This worked fine! Okay, move the code to the Xenix box and try to run > it there... No way will it work! The select() call is documented in the 2.3 select(S) manual page, and the code is in the libc library. Also, I just found out yesterday that to have select() work on FIFOS you need to get SLS fix #xnx141, which just got submitted. I believe this fix requires Xenix 2.3.2. -- Jim Morton, APPLiX Inc., Westboro, MA ...uunet!applix!jim jim@applix.com
ivar@acc.uu.no (Ivar Hosteng) (07/23/89)
I have experienced some problems using the select call in Xenix 386 V2.3.2. It does not seems to detect when a pipe gets ready to been read from. I also have trouble using select on a serial port. When I do that the input turns into garbage. This does not occur when I use select on the multiscreen ttys (tty01-tty12). I am writing a communication program allowing the use of Norwegian (special) characters (they all have values greater than 128), that resembles cu. Instead of forking off two processes to read the keyboard and the serial line I am trying to use the select call to detect when a character is ready from the keyboard or the serial port. But when the select call screws up like this it isn't possible to use the select call. If anyone have a solution to this problem I would be glad to hear from you. Please email answers, I will summarize. -- Ivar E. Hosteng, Advanced Computer Consultans, Oslo, Norway Internet: ivar@acc.uu.no UUCP: ...!{uunet,mcvax,ifi}!acc.uu.no!ivar 'Just what do you think you are doing Dave?' -HAL9000
chad@csd4.csd.uwm.edu (D. Chadwick Gibbons) (09/19/89)
There was a discussion a month or so ago about the problems with the select system call under SCO XENIX 2.3.2. If possible, could the people so involved contact me through email? I believe there was a discussion on temporary fixes until SCO released an update.
jeff@questar.QUESTAR.MN.ORG (Jeff Holmes) (01/11/90)
Could someone who understands the select() system call better than I do tell me... if there is any way to get select() to tell me HOW MANY characters there are in the buffer that are waiting to be read, similar to using FIONREAD with ioctl() under BSD? Thank you, Jeff -- Jeff Holmes DOMAIN: jeff@questar.mn.org Questar Data Systems UUCP: amdahl!bungia!questar!jeff St. Paul, MN 55121 AT&T: +1 612 688 0089
bill@zycor.UUCP (Bill Mahoney) (03/07/90)
I am writing some software that gets moved onto an HP running HPUX. Interestingly, although XENIX and HPUX both support select() "stolen" from BSD, they are slightly different. On XENIX if you select on an FD that is a normal pipe, it returns true always, but a select on a named pipe works as I would expect. On HPUX, both wait for data before returning true. It doesn't really matter (I can't change it, afterall), but I am curious as to which way is supposed to be the "right" way. -- Bill Mahoney //STEPLIB DD DSN=SYS2.LINKLIB,DSP=SHR bill@zycor.UUCP //SYSPRINT DD SYSOUT=A .... Huh? Wha? Oh! It was only a bad dream!
pgd@bbt.se (P.Garbha) (06/10/90)
In the Xenix 2.3.1 /lib/386/Slibtinfo.a library the select() system
call is disabled, by including a routine like:
select()
{
return -1;
}
I find that very strange, since there exist a select() system call
in the kernel (but not in any lib*).
What could ever be the reason to make this dummy routine?
If a program using the select() system call is ported to Xenix,
wouldn't you rather get an "undefined" error message, than a
broken program?