Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - kcc-4/include/usys.doc
There are 9 other files named usys.doc in the archive. Click here to see a list.
	USYS.DOC - KCC Un*x System-call simulation

	This file documents various things about the USYS library routines,
which are intended to provide simulation and support for Un*x system
call functions.

	Specifications for the interfaces were taken from the March
1984 4.2BSD Unix Programmer's Manual (UPM), plus the 4.3BSD man pages,
and all code here works as described in those references unless
otherwise documented.

	Implementors should also read the CODSYS.DOC file in the
source directory.
Contents:
	Intro - listing format
	Summary of USYS routines
	Definitions
	Individual Routine Descriptions (as needed)

Library function listing format:

Name		Module		Port-status	Comments
(routine name)	(source file)	(see below)

	Port-status code:
		E = file #includes "c-env.h" for environment config.
		<sys> - runs on the given sys, one of: T20,10X,T10,WAITS,ITS.
		*10 = portable to all PDP-10 OS (T20,10X,T10,WAITS,ITS)
		* = fully portable (either no OS-dependent stuff, or a
			fully-portable conditional exists)

	Comments:
		"U" means the call is USYS_macro enclosed and cannot be
			interrupted by signals.
		"-" means it isn't enclosed
			(this better be cuz interrupts don't affect the call!)
		"I" means it is interruptible (i.e. can return EINTR error).
		"IC" means interrupts may be continued within the call.
USYS function summary:				Src: lib/usys/

Name		Module	Port-status	Comments

access		ACCESS	T20,10X		U 10X only partial.
alarm		ALARM	T20		U
brk		SBRK	*10		U
chdir		CHDIR	T20,10X		U
chmod		CHMOD	T20,10X		U
chown		CHOWN	T20,10X		U
close		CLOSE	T20,10X,ITS	U
creat		OPEN	T20,10X		U
dup		DUP	*10		U
dup2		DUP	*10		U
errno	(data)	URT	*10		-
exec[lv][ep]	FORK	T20,10X		U
exit		EXIT	*10		-
fchmod		CHMOD	T20,10X		U
fchown		CHOWN	T20,10X		U
fcntl		FCNTL	*10		U
fork		FORKEX	T20,10X		U
forkexec	FORKEX	T20,10X		U KCC-specific routine.
fstat		STAT	T20,10X		U (also: xfstat)
ftime		TIME	*10		-
geteuid		GETUID	T20,10X		U
getpid		GETPID	*10		U see format note.
gettimeofday	TIME	*10		-
getuid		GETUID	T20,10X		U
gtty		SGTTY	T20		U
ioctl		IOCTL	T20		UIC Partial.
kill		SIGVEC	T20,10X		U
lseek		LSEEK	T20,10X		U
open		OPEN	T20,10X		U (Uses BSD flags; mode not supported)
pause		PAUSE	*10		-I Always returns with EINTR
pipe		PIPE	T20		U (monitor must have PIP: device)
psignal		PSIGNA	*10		-
raise		SIGVEC	T20,10X		U (ANSI function, not syscall)
read		READ	T20,10X		U
rename		RENAME	T20,10X		U
sbrk		SBRK	*10		U
sigblock	SIGVEC	T20,10X		U
signal		SIGNAL	T20,10X		U
sigpause	SIGVEC	T20,10X		UI Always returns with EINTR
sigreturn	SIGVEC	T20,10X		U
sigsetmask	SIGVEC	T20,10X		U
sigstack	SIGVEC	T20,10X		U
sigvec		SIGVEC	T20,10X		U
sleep		SLEEP	*10		-I (returns no value)
stat		STAT	T20,10X		U (also: xstat)
stty		SGTTY	T20		U
tell		LSEEK	T20,10X		U
time		TIME	*10		- (also: tadl_xxx routines)
times		TIMES	*10		-
unlink		UNLINK	T20,10X,ITS	U (10X doesn't expunge)
utime		UTIME	T20,10X		U
vfork		FORK	T20,10X		U
wait		WAIT	T20,10X		UIC
write		WRITE	T20,10X,ITS	UIC
_exit		EXIT	*10		U
_runtm		URT	*10		(internal) C programs start here.
_urtsud (data)	URTSUD	*10		(internal) Runtime startup defs.
DEFINITIONS:

	The UPM introduction contains some definitions which provide
a convenient way to start describing how the KCC simulations differ from
Un*x; some concepts are supported and others are not.

Process ID (PID):	Supported, see long description.
Parent Process ID:	Supported, see long description.

Process Group ID:	not implemented
TTY Group ID:		not implemented

Real User ID:		Supported.
	The user ID on T20/10X is the "user number".

Real Group ID:		not implemented
Effective UID, GID, and Access Groups: not implemented
Super-user:		not implemented
Special Processes:	not implemented

File Descriptor (FD):	Supported.
	Small non-negative integers in the range 0 to 63 inclusive.
	FDs 0, 1, and 2 correspond to standard input, output, and error output.
	On T20/10X these are initially set to the JFNs .PRIIN, .PRIOU, .CTTRM.
	You can obtain the JFN for a FD by using the fcntl() call.

File Name:	Supported.
	On T20/10X, up to 39 chars per component.  Must be 7-bit ASCII.
	Can quote with ^V.

Path Name:	Supported.
	Un*x style / paths are permitted, where foo/ is taken to mean foo
	is a subdirectory of the current directory.

	If the monitor worked right, a filespec of the form "C:foo/bar.h" could
	be turned into "C:<.foo>bar.h", assuming standard-type relative
	directory fixes, and we would win.  But no.  Instead, we have to do
	the work manually: the logical device is recursively expanded until
	an end device-directory pair is found, at which point the file
	lookup is tried.  If it fails, the expansion/traversal continues.

Directory:	Supported.
	<.> and <..> work on some T20 systems (Stanford mods).

Root Directory and Current Working Directory:
	A directory of the form "/foo" is taken to mean "<foo>".
	The notion of a current working directory is supported.

File Access Permissions:
	Each set of T20/10X owner, group, and world access bits
	corresponds to a set of Un*x owner, group, and other bits.
		Un*x	T20/10X
		04	040	Read access
		02	020	Write access
		01	010	Execute access
		-	04	Append access
		-	02	Directory listing access
		-	01	-
	Thus, a call such as "chmod(foo.bar, 0644)" will set the T20/10X
	protection of "foo.bar" to 604040.
	There is no way a user program can either read or set the last
	three T20/10X protection bits, except by doing a CHFDB% itself.
	Finally, there is no T20/10X counterpart to the set-UID or set-GID
	bits.

Sockets and Address Families: not implemented (yet!)
ERRORS:

	The global "errno" is set by all failing USYS calls.
The standard UN*X error numbers from <errno.h> are used where possible,
although a few T20-specific error codes have been defined.  See <errno.h>
for details.
	There is currently no easy way to find out what TOPS-20/TENEX
error (if any) caused errno to be set.  The best one can do is find the
most recent error for the process with GETER%.  Perhaps someday this will
be improved.

Exceptions:
	ftime, time, gettimeofday, times
	getpid
	_exit (never returns)
PROCESS ID (PID):	Long Description

PID values are generated by:
	(1) getpid() - self process ID.  This must not change over
		the lifetime of the process!
	(2) fork() - to identify the child process.
	(3) wait() - to identify the child process that stopped.
		This should match the value returned by fork().

PID values are used by:
	(1) kill() - to send signals to self, child, or parent.
		(It is rare to send them anywhere else.)
	(2) Code that checks the return value of wait().
	(3) Code that generates unique filenames, port numbers, or the like
		which should not conflict with those of any other
		active process.

	For ITS, TOPS-10, and WAITS the PID is simply the job #, a
small positive integer; zero and negative PIDs will never be seen, as
job 0 is the monitor itself and no system can support 2**35 jobs.

	However, TENEX (and hence TOPS-20) has never had a notion of a
unique process identifier, except internally inside the monitor; this
fork ID is simply not accessible to the user.  Fork handles are all
relative, in an obscene attempt to prevent programs from referencing
any process they shouldn't.  This makes it impossible to implement
getpid() in a straightforward way.  The subterfuge I have resorted to
is as follows:

	T20 PID = <IPCF PID>,,<frk #><job #>
		<IPCF PID> - Left half of a PID generated by MUTIL% for process
			This is guaranteed by system to be unique.
		<frk #> - low 9 bits of relative fork handle, in 0777000.
		<job #> - low 9 bits of job number, in 0777.

	getpid() remembers the value generated on first call and
returns that thereafter.  This satisfies the uniqueness and constancy
criterion, as well as being efficient.
	fork() and wait() convert the relative fork handles from
CFORK% and GFRKS% to a child PID with a zero LH but with the other
fields set.  Since relative fork handles are from 400000 to 400777, we
only need the low 9 bits.
	fork() in the new child process copies the saved getpid()
value, if any; this is its parent's PID and may be used by kill().  The
saved value is then cleared so if the child calls getpid() it will generate
its own unique value.
	kill() checks its PID argument first against the saved
getpid() value to see if a signal is being sent to itself.  If not it then
sees whether it matches that of its parent (if any) and sends a signal
to .FHSUP if so.  Otherwise, if the LH is 0 it assumes the signal is
being sent to a child, and generates the appropriate relative fork
handle from the 9 bits in the PID value.  Note: There is no good way
to identify "miscellaneous" signals generated by another process (PSIs
on the "CHNmisc" channel); only those PSIs uniquely mapped to a single
signal can be successfully sent between processes.

	This scheme fails only if PIDs are somehow passed from one
process to another either via pipe, file, or vfork() shared memory, since
the result of a child's getpid() won't match what its parent's fork()
returned.  But this should practically never happen.

TENEX:
	On TENEX, which doesn't have IPCF, we just use GFRKS% to
locate our fork within the job fork structure and hope the resulting
number, which we stick in the LH, doesn't change.  At least TENEX
doesn't have extended addressing either so we can munch the GFRKS%
data on the stack.
OPEN() - Some I/O details:

	The open() call has several additional flags which are intended to
help specify the proper actions on TOPS-20/TENEX systems, since the
defaults assumed by open() may not always be correct.

		Standard BSD flags:
	O_RDONLY	open for reading only
	O_WRONLY	open for writing only
	O_RDWR		open for reading and writing
	O_NDELAY	do not block on open		(not supported)
	O_APPEND	append on each write
	O_CREAT		create file if it does not exist
	O_TRUNC		truncate size to 0
	O_EXCL		error if create and file exists

		KCC-specific flags (not portable)
	O_BINARY		Open in binary (9-bit byte) mode
	O_CONVERTED		Force LF-conversion
	O_UNCONVERTED		Force NO LF-conversion
	O_BSIZE_7		Force 7-bit bytesize
	O_BSIZE_8		Force 8-bit bytesize
	O_BSIZE_9		Force 9-bit bytesize

		TOPS-20 and TENEX specific flags
	O_T20_WILD		Allow wildcards on GTJFN%
	O_T20_WROLD		For writes, do NOT use GJ%FOU
	O_T20_SYS_LOG		logical device is system-wide!
	O_T20_THAWED		Open file for thawed access

	The BSD flags behave as per the UPM documentation, and the T20
flags are fairly straightforward.  The KCC flags however are more subtle;
they affect the characteristics of the I/O that will be done, rather than
how a file will be found or created.  The two decisions that must be made
are: (1) Bytesize, and (2) LF-conversion.  These are explained below.
	
BYTESIZE:
	The decision of which bytesize to use for I/O is somewhat
complicated.  The bytesize on UN*X is always 8 bits, but on PDP-10s it
can be anything from 0 to 36 bits.  The algorithm we use is as follows:
	If a byte size (one of 7, 8, or 9) is explicitly requested, use that.
	Otherwise, for a new file, use 9 if O_BINARY, else 7.
		   for an old file, use the file's bytesize.
			A size of 0 or 36 is treated as for a new file.
			Any other size is simply used.  If this is not
			one of 7, 8, or 9 then the results are unpredictable.

LF-CONVERSION:
	UN*X text files use the convention that a LF alone is a
"newline", whereas PDP-10 systems use CRLF together.  Thus, the normal
mode of I/O uses LF-conversion, wherein read() converts a input CRLF
sequence to LF, and write() converts an output LF to CRLF.  The algorithm
used to determine whether LF-conversion should be done is:
	Conversion is normally only done if the bytesize is 7.
		Any other size implies NO conversion.
	However, this default can be overriden by certain flags:
		If O_CONVERTED is set, conversion is ALWAYS done.
		If O_UNCONVERTED or O_BINARY is set, conversion is NEVER done.
LSEEK() - Problems with LF-conversion

	lseek() deals only with system-level file pointers.  When no
LF-conversion is being done, this corresponds exactly to the UN*X notion
of a file position, namely the # of bytes offset from the start of the file,
and it is possible to create your own file positions arithmetically.

	However, when LF-conversion is being done then this is not possible;
the position returned by lseek will correspond to the system's position,
rather than to the number of bytes fed through read() or write().  In this
case you can only lseek to a position previously returned by lseek() itself.
(Note that 0 is a special case that always works).  Typically the pointer
returned will be larger than the number of bytes read or written thus far,
since the system is aware of the CR's in the file even though the C program
isn't.
FORKEXEC() - New KCC-specific call

	This call is intended to combine the functions of fork() and
exec() so that a user program that wants to perform the very common
procedure of first calling fork() and then having the child call exec()
can now simply use forkexec() and accomplish the same thing much faster.

	The calling sequence is simply:
		#include <frkxec.h>
		int forkexec(fxp);
		struct frkxec *fxp;

	See the include file for details on the contents of the frkxec
structure and the flags that can be provided.

	All of the exec*() functions call forkexec() with FX_NOFORK set.
TTY Handling:

	The library supports many (though not all) of the Un*x TTY
functions.  The primary means of getting information about the TTY and
setting TTY parameters is with the ioctl() call.  All 4.3BSD TTY-related
ioctl functions are recognized, although not all are completely supported.
In particular, all requests to "get" data structures will always return
as much information as is available; attempting to "set" some elements of
these structures may or may not work, as described in the following comments.

IOCTL function comments:

FIONREAD - Get # bytes to read on FD.  Supported.

TIOCGETP - Get sgttyb parameters, same as V6/V7 gtty().  Supported.
TIOCSETP - Set sgttyb parameters, same as V6/V7 stty().  Supported.
	sg_ispeed, sg_ospeed	Can read and set.
	sg_erase	Cannot set to anything but DEL (fails if you try).
	sg_kill		Cannot set to anything but ^U  (fails if you try).
	sg_flags	The following flags are used:
			RAW, CRMOD, ECHO, CBREAK
			All other flags are ignored, esp. LCASE and TANDEM.

TIOCSETN - V7: same as TIOCSETP, but without flushing TTY input.  Supported.
TIOCEXCL - V7: set exclusive use of tty		(not implemented).
TIOCNXCL - V7: reset exclusive use of tty	(not implemented).
TIOCHPCL - V7: Hang up on last close		(not implemented).
TIOCFLUSH - V7: Flush TTY input and output buffers.  Supported.

All other functions are for BSD4.3.

TIOCSTI  - Simulate terminal input. Supported.
TIOCSBRK - Set   break bit.		(not implemented)
TIOCCBRK - Clear break bit.		(not implemented)
TIOCSDTR - Set   data terminal ready.	(not implemented)
TIOCCDTR - Clear data terminal ready.	(not implemented)
TIOCGPGRP - Get pgrp of tty.		(not implemented)
TIOCSPGRP - Set pgrp of tty.		(not implemented)

TIOCGETC - Get special characters (tchars). Supported.
TIOCSETC - Set special characters (tchars). Supported (sort of).
	t_intrc and t_quitc (for SIGINT and SIGQUIT) are initially -1 but
		can be set to any control character.  Note that because
		chars are unsigned, the initial value when converted to
		an integer is 0777, not -1!
	No other elements of tchars can be set to anything but what they
	already are:
		t_stopc = ^S, t_startc = ^Q, t_eofc = ^Z, t_brkc = -1


TIOCLBIS - Set   bits in local mode word.	(not implemented)
TIOCLBIC - Clear bits in local mode word.	(not implemented)
TIOCLGET - Get local mode mask.			(not implemented)
TIOCLSET - Set local mode mask.			(not implemented)

TIOCSLTC - Set local special chars (ltchars).  Supported.
TIOCGLTC - Get local special chars (ltchars).  Supported (sort of).
	None of these chars can be set to anything but what they already are:
	t_suspc = ^C, t_dsuspc = ^C, t_rprntc = ^R, t_flushc = ^O,
	t_werasc = ^W, t_lnextc = ^V

TIOCGETD - Get line discipline.  Supported.
TIOCSETD - Set line discipline.  Supported (sort of).
	The line discipline is always NTTYDISC and cannot be set otherwise.

TIOCGWINSZ - Get window size info.  Supported.
TIOCSWINSZ - Set window size info.  Supported.
	ws_col and ws_row correspond to the terminal's width and height.
		Both can be read and set.
	ws_xpixel and wx_ypixel are initially 0 but can be set and then read.
Signals:

	Signals are complicated, both on Un*x and T20/10X.  The KCC
implementation by default attempts to support the 4.3BSD signal
mechanism, which uses a variety of system calls.  For those planning
to use signals, the file SIGNAL.DOC should be consulted.