[comp.unix.xenix] select

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?