• tee - Pipe fitting.

  • tee [ -ai ] [ file ...]

  • The tee utility copies standard input to standard output, making a copy in zero or more files. The output is unbuffered.

    The following options are available:

    -a Append the output to the files rather than overwriting them.

    -i Ignore the SIGINT signal.

    The following operands are available:

    file A pathname of an output file .

    The tee utility takes the default action for all signals, except in the event of the -i option.

    The tee utility exits 0 on success, and >0 if an error occurs.


  • The tee function is expected to be POSIX p1003.2 compatible.

  • GNO/Shell User's Manual , signal(2)

  • NAME

  • time - time a command

  • time command

  • The time command lets the specified command execute and then outputs the amount of elapsed real time, the time spent in the operating system, and the time spent in execution of the command. Times are reported in seconds and are written to standard error.

    The time command can be used to cause a command to be timed no matter how much

    CPU time it takes. For example:

    % /bin/time cp /etc/rc /usr/bill/rc

    0.1 real 0.0 user 0.0 sys

    % /bin/time nroff sample1 > sample1.nroff

    3.6 real 2.4 user 1.2 sys

    This example indicates that the cp command used negligible amounts of user ( user ) and system time ( sys ), and had an elapsed time ( real ) of 1/10 second (0.1). The nroff command used 2.4 seconds of user time and 1.2 seconds of system time, and required 3.6 seconds of elapsed time.


  • Times are measured to an accuracy of 1/60 second. Thus, the sum of the user and system times can be larger than the elapsed time, but this isn't likely.

  • NAME

  • tr - translate characters

  • tr [ -cds ] [ string1 [ string2 ] ]

  • tr copies the standard input to the standard output with substitution or deletion of selected characters. The arguments string1 and string2 are considered sets of characters. Any input character found in string1 is mapped into the character in the corresponding position within string2. When string2 is short, it is padded to the length of string1 by duplicating its last character.

    In either string the notation 'a - b' denotes a range of characters from a to b in increasing ASCII order. The character \, followed by 1, 2 or 3 octal digits stands for the character whose ASCII code is given by those digits. As with the shell, the escape character \, followed by any other character, escapes any special meaning for that character.

    When string2 is short, characters in string1 with no corresponding character in string2 are not translated.

    In either string the following abbreviation conventions introduce ranges of characters or repeated characters into the strings.

    [ a - z ]

    Stands for the string of characters whose ASCII codes run from character a to character z, inclusive.

    [ a * n ]

    Stands for n repetitions of a. If the first digit of n is 0, n is considered octal; otherwise, n is taken to be decimal. A zero or missing n is taken to be huge; this facility is useful for padding string2.


  • Any combination of the options -c, -d, or -s may be used:

    -c Complement the set of characters in string1 with respect to the universe of characters whose ASCII codes are 01 through 0377 octal;

    -d Delete all input characters in string1.

    -s Squeeze all strings of repeated output characters that are in string2 to single characters.


  • The following example creates a list of all the words in filename one per line in filename2, where a word is taken to be a maximal string of alphabetics. The second string is quoted to protect `\' from the shell. 012 is the ASCII code for NEWLINE.

    tr -cs A-Za-z '\012' < filename1 > filename2


  • conv(1), more(1)
  • BUGS

  • Will not handle ASCII NUL in string1 or string2. tr always deletes NUL from input.

  • NAME

  • unshar - extracts files from shar archives

  • unshar {-overwrite} {-nosort} file1 file2 ...

  • Unshar is a utility which extracts files from the ubiquitous Unix shar archives. It has the following advantages over existing unshar utilities:

    - Small and fast

    - Handles many cat and sed formats

    - Allows extraction of subdirectories

    - Understands ./file type filenames

    - Understands file continuation with >>

    - Sorts file list by Subject: line

    - Exits cleanly with CTRL-C

    Unshar treats quotes and imbedded escape sequences intelligently and handles all the cat and sed formats the author ever seen, including sed commands which strip off more than one letter. There may be some formats it won't handle, but I've yet to find them.

    Invoke unshar with as many archive filenames as you like. All the files in each archive will be extracted into the current directory. If a file already exists, unshar asks you how you want to handle it. Entering `Y' will overwrite the existing file with the version in the archive, `N' will skip past the file without extracting it, and `A' will overwrite this file and any other existing files without prompting you again. Including the -o flag on the command line causes files to always be overwritten.


  • Unshar scans through each archive specified on the command line, looking for lines beginning with `cat' or `sed'. All other lines are ignored. In particular, `echo' lines are not echoed. This way, you don't get a load of messages which are in any case fairly meaningless, because the operations they are describing are unsupported.

    When a shar archive contains a file for which a full pathname is given (as in source/file.c for example) unshar will create whatever directories are necessary. It also strips off leading /'s and ./'s, to make filenames understandable by GS/OS.

    Occasionally, a shar file distribution will contain a file too large to fit into a single shar archive (archives are typically limited to around 60K or so for transmission over Usenet). One method some archivers use to get around this is to split the large file into several smaller parts, and use the shell `>>' redirection operator to concatenate the parts together while extracting the files. In order for this to work properly, it is important that the archive files are extracted in the correct sequence; otherwise, all the pieces will get joined together in the wrong order.

    To assist with this, unshar does a prescan over all the files listed on the command line, and checks each file for a "Subject:" line. If it finds such a line, it scans it looking for any hints as to where the file comes in the sequence. Most shar files you feed to unshar will be directly from a Usenet sources or binaries group, and will include a volume and issue reference on the subject line. If unshar can't find such an issue reference, it will look for a Part number and use that instead.

    Unshar then extracts the archives starting with the lowest numbered file. This helps to ensure that those extra-large files are created correctly. You can tell when such a file is being created, because unshar says "Extending file" rather than "Unsharing file".

    If for some reason you want the files to be unarchived in the order listed on the command line, you can specify the `-n' (nosort) switch, and no sorting will take place.


  • V1.0 First release.

    V1.1 Added support for some more unusual uses of sed.

    Increased speed, and reduced size slightly.

    Fixed bug that truncated lines longer than 80 chars.

    V1.2 Added support for sorting by Subject: line

    Added support for file appending via >>

    Fixed small bug in detection of disk write errors


  • Eddy Carroll (EMAIL:

    Apple //gs port by Andy McFadden (

  • NAME

  • wc - display a count of lines, words and characters

  • wc [ -lwc ] [ filename ... ]

  • wc counts lines, words, and characters in filename s, or in the standard input if no filename appears. It also keeps a total count for all named files. A word is a string of characters delimited by SPACE, TAB, or NEWLINE characters.

  • When filename s are specified on the command line, their names will be printed along with the counts.

    The default is -lwc (count lines, words, and characters).

    -l Count lines.

    -w Count words.

    -c Count characters.


  • example% wc $USRMAN/csh.1 $USRMAN/sh.1 $USRMAN/telnet.1

    1876 11223 65895 /usr/share/man/man1/csh.1

    674 3310 20338 /usr/share/man/man1/sh.1

    260 1110 6834 /usr/share/man/man1/telnet.1

    2810 15643 93067 total


  • NAME

  • who - who is on the system

  • who [ who-file ] [ am I ]

  • Who, without an argument, lists the login name, terminal name, and login time for each current UNIX user.

    Without an argument, who examines the /etc/utmp file to obtain its information. If a file is given, that file is examined. Typically the given file will be /usr/adm/wtmp, which contains a record of all the logins since it was created. Then who lists logins, logouts, and crashes since the creation of the wtmp file. Each login is listed with user name, terminal name (with `/dev/' suppressed), and date and time. When an argument is given, logouts produce a similar line without a user name. Reboots produce a line with `x' in the place of the device name, and a fossil time indicative of when the system went down.

    With two arguments, as in `who am I' (and also `who are you'), who tells who you are logged in as.


  • /etc/utmp

  • getuid(2), utmp(5)

  • NAME

  • yes - be repetitively affirmative

  • yes [ expletive ]

  • Yes repeatedly outputs "y", or if expletive is given, that is output repeatedly. Termination is by interrupt.

  • NAME

  • alarm - set and reset alarm timer

  • #include <gno/gno.h>

    long int alarm(long int seconds);


  • alarm sets the counter on the calling process' alarm timer to the value specified in seconds. If seconds is (long int) 0, the alarm timer is disabled.

    When an alarm timer terminates (by counting down to 0), the calling process is sent a SIGALRM signal.


  • The amount of time previously remaining in the timer is returned. No errors are possible.

  • signal(2), sigpause(2)

  • NAME

  • dup,dup2 - duplicate open file descriptors

  • #include <gno/gno.h>

    int dup(int filedes);

    int dup2(int filedes, int filedes2);


  • Given the file descriptor of a valid open file, dup creates a new file descriptor that is synonymous with filedes. The new file descriptor is returned. The second form of the call forces an existing file descriptor filedes2 to refer to the same file as filedes. If filedes2 already refers to an open file, it is closed first.

  • dup returns the new file descriptor, and dup2 returns 0 if the calls are successful. In the event of an error, -1 is returned and errno is set as follows:

    [EBADF] filedes refers to an invalid file descriptor (not an open file)

    [EMFILE] no more files can be opened; process is at current limit (32).


  • fork(2), open(2)

  • NAME

  • execve - replace current process with an executable image from a file

  • #include <gno/gno.h>

    int execve(char *pathname, char *cmdline);


  • execve is the preferred method for loading program files to be executed under the GNO system. A new userID is allocated for the process, and the GS/OS System Loader is used to bring the executable file specified by pathname into memory. pathname can be a partial or complete path. The executable loaded replaces the executable associated with the current process.

    If the executable file does not contain an OMF Stack Segment (SEGKIND = $12), a default stack of 4096 bytes is allocated to the process. The direct-page pointer is set to the bottom of the stack memory (for C programs this is irrelevant).

    The parameter cmdline is the list of arguments to be passed to the new process (a copy is actually passed). C programs parse cmdline automatically, and the individual pieces can be accessed through the argc/argv arguments to main(). cmdline can be accessed from assembly langugage through the X (high-order word of cmdline) and Y (low-order word) registers. However, if the executable file is of file type S16 ($B3), the cmdline argument is ignored and the X&Y registers are set to null (i.e. the command line is only passed to an EXE executable). The 8 characters "BYTEWRKS" are prepended to cmdline before being passed to the process (this is the same identifier used by the ORCA shell). This Shell Identifier distinguishes the GNO and ORCA environments from others that don't support the full range of shell calls, and can be accessed from C with the library function shellid(). The A register is set to the userID allocated for the process.

    GS/OS prefixes 1 and 9 are set to the pathname of the directory containing the executable file; if the length of the path exceeds 64 characters prefix 1 is set to the null prefix (length 0).

    The following information is inherited by the new executable: current machine state, controlling TTY, process group ID, and prefixes 0 and 8.

    Caught signals are reset to the default action. Ignored signals remain ignored across the execve. Any signals in the parent's queue are not passed to the child, and the child is started with no signals blocked. The child inherits all the open files of its parent.


  • A successful execve does not return, as the current executable is replaced with the one specified in the call. If for some reason the call fails, execve returns SYSERR (-1), and errno is set to one of the following:

    [ENOENT] the pathname specified does not exist

    [EIO] some general I/O error occurred trying to load the executable

  • BUGS

  • ORCA/C 1.3 and previous ignore any stack space allocated for it by the GS/OS Loader (which execve calls) or by default in execve. Stack space in ORCA/C programs is determined by code in the .root object file, and can be set with the #pragma stacksize directive. Read the chapter on GNO Compliance in the GNO Kernel Reference Manual for more information on this topic. ORCA/C 2.0 and newer use the system-provided stack space.

  • exec(2), fork(2), wait(2), ioctl(2), tty(4), GNO Kernel Reference Manual

  • NAME

  • fork - start a new process from inside the current application space

  • #include <gno/gno.h>

    int fork(void *addr);


  • fork's argument addr is typically the address of a C function, although it can be any valid address inside the IIGS RAM space. fork creates a new entry in the process table, and sets up default settings for the new process. The process is allocated 1K (1024 bytes) of stack space, and the direct page is set to the beginning of this memory. The process is executed in 16-bit full native mode, and the registers upon entry to the routine are set as follows:

    A the userID assigned to the process

    X 0

    Y 0

    The child inherits the memory shadowing and machine state parameters of the parent, as well as signal blocking information and the ID of the controlling TTY. In addition, the child inherits all the open files of its parent.

    A forked process may share code with other children or the parent. However, this is only allowed in a forward manner; any forked process that exits by function return will be terminated. Note that any shared global variables will need to be moderated with some type of mutual exclusion, either the kernel semaphore(2) routines or custom routines. This includes C stdio routines.


  • fork returns the process ID of the child, or -1 (SYSERR) if an error occurs, in which case errno is set as follows:

    [ENOMEM] not enough memory to create the new process

    [EAGAIN] all process slots full; no more can be created


  • There is no way to pass parameters directly to a child with fork(). Use fork2() instead.

  • Most UNIX forks take no parameters; they copy the entire address space of the calling process and return with a different value in the parent and child. Due to hardware limitations, this sort of manipulation isn't possible on the IIgs. UNIX programs utilizing fork will have to be modified slightly to work under GNO.

  • fork2(2), exec(2), execve(2), wait(2), screate(2)

  • NAME

  • getpid, getpgrp, getppid - return information about processes

  • #include <gno/gno.h>

    int getpid(void);

    int getpgrp(int pid);

    int getppid(void);


  • The process ID is a unique value associated with a process, and is needed for many system calls. pid's can range from 0 (Kernel Null Process) to 32767. Some programs use getpid to seed random number generators. A much better approach on the IIGS is to use the horizontal and vertical positions of the electron gun, which can be obtained by reading the word value at absolute memory location $E0C02E.

    getpgrp returns the process group ID of the specified process, pid. This function is usually used when you wish to send a signal to all members of a process group using kill(2).


  • getpid: The process ID of the caller is returned. No errors are possible.

    getppid: The process ID of the caller's parent is returned. No errors are possible.

    getpgrp: The process group ID of the specified process is returned. In the event of an error, getpgrp returns -1 and sets errno to the appropriate error code:

    [ESRCH] pid is not a valid process ID


  • getpgrp() is provided solely for compatibility with previous versions of the UNIX operating system. The new Job Control interface should be used exclusively in new software.

  • fork(2), job control(2), ioctl(2), GNO Kernel Reference Manual

  • NAME

  • getuid, geteuid, getgid, getegid - get user and group identity

    getpgrp - get process group


  • #include <sys/types.h>

    uid_t = getuid(void)

    uid_t = geteuid(void)

    gid_t = getgid(void)

    gid_t = getegid(void)


  • Getuid returns the real user ID of the current process, geteuid the effective user ID. The real user ID identifies the person who is logged in. The effective user ID gives the process additional permissions during execution of "set-user-ID" mode processes, which use getuid to determine the real-user-id of the process that invoked them.

    Getgid returns the real group ID of the current process, getegid the effective group ID. The real group ID is specified at login time. The effective group ID is more transient, and determines additional access permission during execution of a ``set-group-ID'' process, and it is for such processes that getgid is most useful.


  • The setr*() functions are not currently implemented in GNO/ME, because set-uid and set-group-ID behavior is specific to the UNIX filesystem.

  • setreuid(2), setregid(2), setgid(3), tty(4)

  • NAME

  • intro - introduction to GNO system calls

  • This section describes, in alphabetical order, the system calls and kernel interfaces available for GNO. Certain distinctions of purpose are made in the headings.
  • Manual Page Command Syntax

  • Unless otherwise noted, calls described in the SYNOPSIS section of a manual page accept parameters and require the

    name [- option ...] [ cmdarg ...]


    [] Surround an option or cmdarg that is not required.

    ... Indicates multiple occurrences of the option or cmdarg.

    name The name of an executable file.

    option (Almost always preceded by a "-".)

    noargletter ... or,

    argletter optarg [,...]

    noargletter A single letter representing an option without an option-argument. Note that more than one noargletter option can be grouped after one "-".

    argletter A single letter representing an option requiring an option-argument.

    optarg An option-argument (character string) satisfying a preceding argletter. Note that groups of optargs following an argletter must be separated by white space and quoted.

    cmdarg Path name (or other command argument) not beginning with a "-", or "-" by itself indicating the standard input.


  • GNO/ME Kernel Reference Manual

  • NAME

  • ioctl - control device

  • #include <sys/ioctl.h>

    int ioctl(int fd, unsigned long request, void *argp)


  • Ioctl performs a variety of functions on open file descriptors. In particular, many operating characteristics of character special files (e.g. terminals) may be controlled with ioctl requests. The writeups of various devices in section 4 discuss how ioctl applies to them.

    An ioctl request has encoded in it whether the argument is an "in" parameter or "out" parameter, and the size of the argument argp in bytes. Macros and defines used in specifying an ioctl request are located in the file <sys/ioctl.h>.


  • If an error has occurred, a value of -1 is returned and errno is set to indicate the error.

  • Ioctl will fail if one or more of the following are true:

    [EBADF] Fd is not a valid descriptor.

    [ENOTTY] Fd is not associated with a character special device.

    [ENOTTY] The specified request does not apply to the kind of object that the descriptor fd references.

    [EINVAL] Request or argp is not valid.


  • execve(2), tty(4)

  • NAME

  • tcnewpgrp, settpgrp, tctpgrp - interface for the new job control model

  • #include <gno/gno.h>

    int tcnewpgrp(int fdtty);

    int settpgrp(int fdtty);

    int tctpgrp(int fdtty, int pid);


  • The job control interface is used to control what processes are ``in the foreground'' on a particular terminal. Every tty has a process group. Each process is a member of a process group. A process is a foreground process on a tty if and only if that process and the terminal belong to the same process group. Certain characters typed on a tty with a nonzero process group produce signals sent to every process which is a member of the group (e.g. ^C).

    A process is suspended (stopped) if it performs a sufficiently invasive operation on a tty with a different process group. This includes these job control calls, reads from a terminal, and writes to a terminal if configured to do so with ioctl(2). When a tty file is first opened, it is assigned process group 0; init has process group 0. As init launches login processes on various ttys, it assigns process groups to those ttys and processes.

    tcnewpgrp(fdtty): Allocates a new process group and assigns it to the terminal referred to by fdtty. If the calling process is not in the foreground, it is sent SIGTTOU.

    settpgrp(fdtty): Sets the current process to have the same process group as fdtty.

    tctpgrp(fdtty,pid): Sets the tty to the same process group as pid, where pid is the current process or a descendant of it.


  • The calls will return 0 if no error occurs; otherwise, they'll return -1 and set errno to one of the following:

    [EBADF] fdtty is not a valid file descriptor

    [ENOTTY] fdtty does not refer to a terminal file

    [ESRCH] pid is not a valid process identifier


  • Following are some example uses of the job control interface.

    • Forking a pipeline in a job-control shell: The shell starts with tcnewpgrp(fdtty), so that the tty is in the new process group before there are even any children. It then forks each process in the pipeline. Each process does settpgrp(fdtty), thus joining the new process group.

    • Handling a stopped child process: When the shell sees that a pipeline has stopped or exited, it does tctpgrp(fdtty,getpid()) to set the tty to its own process group. To resume the pipeline it does tctpgrp(fdtty,pid) where pid is one of the child processes, then sends SIGCONT.

    • Starting a process under a new tty: When, for instance, telnetd wants to grab a pseudo-tty, it opens the pty and forks a child process. The child does tcnewpgrp(fdtty) to give the tty a real process group, then settpgrp(fdtty) to place itself into the foreground.

    Security under this scheme is trivial. There is no way a process can join a process group except by settpgrp(), and that requires a descriptor open to a tty with that pgrp. To make a tty have that pgrp requires either tcnewpgrp(), in which case nobody else is using the pgrp, or tctpgrp(), which reduces to the first problem of having a process in the process group. End of security proof. (Wasn't that easy?) Note that `using' must be defined as use both by ttys and by processes; the system keeps a table of pgrps, each with a total tty + process reference count. When the reference count reaches zero, the pgrp is automatically deallocated.


  • ioctl(2), tty(4), signal(2), kill(2), GNO Shell Reference Manual

  • This job control interface was designed by Dan Bernstein ( He was inspired by Chris Torek, and dedicated the system to Mark Teitelbaum. The text of this manpage is derived from his original specifications.

    The GNO/ME implementation was written strictly from specs.

  • NAME

  • kill - send a signal to a process

  • #include <gno/gno.h>

    int kill(int pid, int sig)


  • kill is used to send a signal to a process or group of processes. Signals are software interrupts; they act just like hardware interrupts and can also be used for basic IPC (Inter-process communication). The various signals are described in signal(2).

    sig can be a signal number, or it can be 0, in which case no signal is sent, but error checking is done (this can be used to verify a process ID). If sig has been blocked (sigblock(2)), the signal is deferred until it is unblocked, and kill returns immediately. Any previously pending signals of the same sig are lost (i.e. signals are not stacked).

    If pid is 0, the signal is sent to all processes with the same process group ID as the caller, except for system processes.

    Processes may signal themselves, in which case the signal handler is invoked immediately (if one is installed).


  • Normally kill returns SYSOK (0). The following conditions can cause kill to return SYSERR (-1):

    [ESHRC] pid does not correspond to an existing process

    [EINVAL] sig specifies an invalid signal number


  • sigblock(2), signal(2), wait(2)
  • BUGS

  • Do not attempt to send signals from inside a CDA (Classic Desk Accessory) or interrupt handler.

  • NAME

  • pipe - create an interprocess communication channel

  • #include <gno/gno.h>

    int pipe(int filedes[2]);


  • The pipe system call creates an I/O mechanism called a pipe. The file descriptors returned can be used in read and write operations. When the pipe is written using the descriptor filedes[1] up to 4096 bytes of data are buffered before the writing process is suspended. A read using the descriptor filedes[0] will pick up the data.

    It is assumed that after the pipe has been set up, two (or more) cooperating processes (created by subsequent fork calls) will pass data through the pipe with Read and Write calls.

    The shell has a syntax to set up a linear array of processes connected by pipes.

    Read calls on an empty pipe (no buffered data) with only one end (all write file descriptors closed) returns an end-of-file.

    A signal (SIGPIPE) is generated if a write on a pipe with only one end is attempted.


  • The function value zero is returned if the pipe was created; -1 if an error occurred.

  • The pipe call will fail if:

    [EMFILE] Too many descriptors are active.

    [ENFILE] The system file table is full.

    [EFAULT] The fildes buffer is in an invalid area of the process's address space.


  • GNO Shell Users Manual, read(2), write(2), fork(2)
  • BUGS

  • Should more than 4096 bytes be necessary in any pipe among a loop of processes, deadlock will occur.

  • In the above text, mention is made to UNIX read and write calls. On the Apple IIgs, these refer to any system calls that do I/O, namely GS/OS ReadGS, WriteGS; TextTools calls; and C library I/O calls such as read, fread, etc.

  • NAME

  • screate, sdelete, swait, ssignal - semaphore operations

  • #include <gno/gno.h>

    int swait(int sem);

    int ssignal(int sem);

    int screate(int count);

    int sdelete(int sem);


  • screate is used to allocate a semaphore from the kernel semaphore manager. Semaphores are the most basic form of interprocess communication, and these routines provide the power necessary to solve a large number of synchronization and communication problems. (See an Operating Systems text).

    The initial count determines how many times swait can be called before processes are blocked. count must be >= 0, and is usually set to 1. screate returns a semaphore ID number as an integer. This ID must be used in all the other semaphore calls.

    sdelete releases the specified semaphore, and returns all processes that were blocked to a ready state.

    swait decrements the value of the semaphore (initially specified by count ) by 1. If the semaphore count is less than zero, the process is blocked and queued for release by ssignal.

    ssignal increments the semaphore count by one. If the semaphore count is less than zero, ssignal releases arbitrarily a process that had been blocked; FIFO operation is not guaranteed.


  • All the functions return SYSERR (-1) if an error occurs, and an OK (0) if no error occurs.
  • BUGS

  • There is currently no mechanism for deallocating semaphores that are orphaned by abnormal process termination.

  • These semaphore routines were designed for XINU, written by Douglas Comer.

  • NAME

  • setdebug - set debugging output options

  • #include <gno/gno.h>

    int setdebug(int options);


  • setdebug enables and disables various debugging routines built into the kernel. The routines display useful debugging information to stderr (except for dbgSIG, see BUGS). Debug output is enabled by setting the corresponding bit in options, according to the following table. To turn off all debugging output, options should be set to 0. The various debug options are #defined in <gno/gno.h>.

    dbgGSOS prints out the call numbers of any GS/OS or ORCA/shell calls that are made. The number is printed in hexadecimal format and is prefixed with a '$' character. For this and the other GS/OS call debug options, the entire call sequence is enclosed in parenthesis '()' to ease tracing multiple levels of calls.

    dbgPATH If this flag is set, every time a filename argument to a GS/OS or shell call is fully expanded the expanded version is displayed as follows: "EP: <fullpath>".

    dbgERROR For every GS/OS call that is made, if an error occurs the error code is printed in inverse lettering in hexidecimal format. The code is prefixed with a '#' to distinguish the error code from a call code on terminals that do not support inverse mode. If no error occurs on the call, no code is printed. This option has no effect unless dbgGSOS is also enabled.

    dbgSIG This flag enables signal tracing. Each time a signal is sent, whether by kill(2), job control or keyboard, the signal number and target process is displayed. The format is: "kill (-signum): pid: tpid".

    dbgSYSCALL The parameter lists to common system calls are displayed by this option flag. The actual format of the output varies from call to call. The calls that currently support this flag are execve(2), fork(2), and the job control routines.

    dbgPBLOCK The memory address of GS/OS and Shell parameter blocks is printed for each call. As with dbgERROR, this option has no effect unless dbgGSOS is also enabled.


  • setdebug returns the previous value of the debug options word.

  • fork(2),execve(2),ioctl(2),kill(2)
  • BUGS

  • Due to problems associated with signals that are sent during process termination, dbgSIG prints its information to standard output instead of standard error.

  • NAME

  • sigblock,sigmask - temporarily block signals

  • #include <signal.h>

    long sigblock(long mask);

    #define sigmask(signum)


  • sigblock is used to temporarily block the reception of signals. The input parameter mask is a bit vector that specifies which signals are to be blocked; a 1 in a bit n will block signal n+1. The mask is bitwise-ored with the current signal mask to create the new signal mask.

    sigmask is a macro that can be used to calculate signal masks for sigblock. It takes a signal number (signum) as an argument and returns a mask that can then be passed to sigblock.

    If a signal is sent to a process but is blocked, the event is recorded for later release by sigsetmask(2). Blocked signals are not stacked; further occurrences of a blocked signal will overwrite any previous pending signal of the same signum.

    It is not possible to block SIGKILL, SIGCONT, or SIGSTOP. This restriction is silently enforced by the system.


  • The previous value of the signal mask is returned.

  • kill(2), sigsetmask(2), signal(2)

  • NAME

  • signal - a simplified software signal interface

  • #include <signal.h>

    void (*signal(int sig; void (*func(void))(void)


  • Signals are a basic form of IPC (inter-process communication), and are generally used to notify a process of some atypical event (although there is little restriction on actual use). For example, signals are sent in each of the following situations: user typing certain chars at a terminal (^C, ^Z, etc.); execution of an invalid instruction; by request of another process (kill); stack overflow; a process making an input request while running in the background; an attempt to write to a pipe with no reader.

    Most signals cause termination, unless a handler is installed, or the signal is set to be ignored. Certain signals cannot have their default action modified; the system silently enforces this restriction. The following is a list of signals and default actions (taken from signal.h).

    SIGHUP 1 hangup

    SIGINT 2 interrupt

    SIGQUIT 3 quit

    SIGILL 4 illegal instruction

    SIGTRAP 5 trace trap

    SIGABRT 6 abort (generated by abort(3) routine)

    SIGEMT 7 emulator trap

    SIGFPE 8 arithmetic exception

    SIGKILL 9 kill (cannot be caught, blocked, or ignored)

    SIGBUS 10 bus error

    SIGSEGV 11 segmentation violation

    SIGSYS 12 bad argument to system call

    SIGPIPE 13 write on a pipe or other socket with no one to read it

    SIGALRM 14 alarm clock

    SIGTERM 15 software termination signal

    SIGURG 16@ urgent condition present on socket

    SIGSTOP 17 | + stop (cannot be caught, blocked, or ignored)

    SIGTSTP 18 | + stop signal generated from keyboard

    SIGCONT 19@ continue after stop (cannot be blocked)

    SIGCHLD 20@ child status has changed

    SIGCLD 20 System V name for SIGCHLD

    SIGTTIN 21 | + background read attempted from control terminal

    SIGTTOU 22 | + background write attempted to control terminal

    SIGIO 23@ input/output possible on a file descriptor

    SIGPOLL SIGIO System V name for SIGIO

    SIGXCPU 24 exceeded CPU time limit

    SIGUSR1 30 user defined signal 1

    SIGUSR2 31 user defined signal 2

    If func is SIG_DFL, the defult action for the signal is reinstalled. This is normally termination if the signal isn't ignored or caught. Signals marked with an @ are discarded, and signals marked with | + cause the process to stop. If func is SIG_IGN, any future occurences of the signal are discarded, as well as any pending instances. Any other value is treated as the address of a handler routine. The system will block further occurences of the signal before the handler is called, and will unblock the signal automatically upon return from the handler. The handler remains installed after return, unlike earlier UNIX signal facilities.

    If a signal occurs during certain system calls (wait(), and input from a TTY), the call is automatically restarted upon return from the handler.

    A forked child inherits all signal information, including pending signals and blocking and handler information. exec() and execve() restore all signal information to defaults and purge pending signals.


  • The signal handler should be defined as follows:

    void handler (int sig, int code)

    sig is the signal that invoked the handler, and code is additional information about the interrupt condition. Currently, code is always 0. The handler should probably also be compiled using the #pragma databank 1 directive, in the event the signal handler is not in the same bank as the C global data segment (the handler is called with the data bank equal to the program bank).


  • The previous action is returned on a successful call. Otherwise, -1 is returned. [EINVAL] will occur on any of the following conditions:

    sig specifies an invalid signal number.

    An attempt is made to ignore or supply a handler for SIGKILL or SIGSTOP.

    An attempt is made to ignore SIGCONT (by default SIGCONT is ignored).


  • ORCA/C already provides a signal() function, but it doesn't do a whole lot. GNO's signal.h file replaces the one that comes with ORCA.

  • execve(2), fork(2), kill(2), sigblock(2), sigsetmask(2), wait(2), tty(4)

  • NAME

  • sigpause - suspend process until a signal arrives

  • #include <signal.h>

    int sigpause(long int mask);


  • sigpause suspends execution of the calling process until a signal arrives. The mask parameter is assigned to the set of blocked signals (sigsetmask), and then the process is paused. When a signal arrives, the regular signal handler (if any) is executed, and then the original signal mask is restored before returning to the caller. Usually mask is 0 (zero) to pause until any signal arrives.

    sigpause is normally used in situations where one must protect a critical section. A typical use begins with sigblock to block a signal (and enable mutual exclusion); variables modified on the occurrence of that signal are then manipulated, code is executed, etc. To end the critical section and wait for more work, sigpuase is called.


  • sigpause always returns an error (-1) and sets errno to EINTR.

  • signal(2), sigblock(2), sigsetmask(2)

  • NAME

  • sigsetmask - set signal mask

  • #include <signal.h>

    long sigsetmask(long mask);

    #define sigmask(signum)


  • sigsetmask is usually used to restore signal masks after modification by sigblock. The parameter mask is the absolute value the process signal mask will be set to (compare to sigblock, which adds the argument to the set of blocked signals).

    If there are pending instances of signals which become unblocked by the sigsetmask call, they are 'released' into the system signal queue and their 'pending' status is cleared. The system signal queue is maintained by the kernel null process, and is used in situations where signals could not normally be sent (such as interrupt handlers).

    sigmask is a macro that can be used to calculate signal masks for sigsetmask. It takes a signal number, as listed in signal(2), as an argument and returns a mask corresponding to that signal.


  • The previous value of the signal mask is returned.

  • If somehow the process re-blocks a signal released by sigsetmask before the system signal queue processes it, it will be blocked and marked as pending. This can happen if a signal handler makes a sigblock call.

  • kill(2), sigblock(2), signal(2)

  • NAME

  • stat, fstat, lstat - return status information on indicated files

  • #include <sys/stat.h>

    int stat(const char *filename, struct stat *s_buf);

    int fstat(int filedes, struct stat *s_buf);

    int lstat(const char *filename, struct stat *s_buf);


  • These calls are used to retreive status information about files. They do much the same thing as the GS/OS call GetFileInfo, except that they return the information in a format compatible with UNIX's stat calls, and also provide information about pipes and GNO Character Devices.

    stat takes arguments filename, a NUL-terminated string naming the file to get information on, and s_buf, a pointer to a stat structure, defined in <sys/stat.h>. filename can be a partial or a complete path. The miscellaneous types in struct stat, below, are defined in <sys/types.h>, automatically included by stat.h.

    struct stat {

    dev_t st_dev; /* ID number of device file resides on */

    ino_t st_ino; /* inode number of file */

    unsigned short st_mode; /* type of file and mode */

    short st_nlink; /* number of links to file = 0 */

    uid_t st_uid; /* user id = 0 */

    gid_t st_gid; /* group id = 0 */

    dev_t st_rdev; /* device type ID */

    off_t st_size; /* length of file in bytes */

    time_t st_atime; /* last access time (same as mod time on Apple IIGS) */

    int st_spare1; /* reserved */

    time_t st_mtime; /* last modification time */

    int st_spare2; /* reserved */

    time_t st_ctime; /* file creation time */

    int st_spare3; /* reserved */

    long st_blksize; /* size in bytes of blocks on filesystem */

    long st_blocks; /* number of blocks file uses */

    long st_spare4[2]; /* reserved */


    The items marked 'reserved' are not currently used but are reserved for future expansion; do not use these fields for any reason. st_dev is the device number the file resides on. This number is the same as the GS/OS device ID number. st_rdev is not currently used, but may in the future designate a device type code.

    st_mode is a bit field representing access mode and type of the file. The flags in st_mode are as follows:

    #define S_IFDIR 0040000 /* directory */

    #define S_IFCHR 0020000 /* character special */

    #define S_IFBLK 0060000 /* block special */

    #define S_IFREG 0100000 /* regular */

    #define S_IFLNK 0120000 /* symbolic link */

    #define S_IFSOCK 0140000 /* socket or pipe */

    #define S_IREAD 0000400 /* read permission, owner */

    #define S_IWRITE 0000200 /* write permission, owner */

    #define S_IEXEC 0000100 /* file is an executable, owner */

    fstat is similar to stat except the argument is an open file descriptor filedes. If filedes refers to a character device or pipe, the entire s_buf is set to 0 and only st_mode and st_dev are set.

    lstat is similar to stat, but if the filename is a link then information is returned about the link file instead of the file linked to.


  • If the call completes without mishap, stat returns a 0. If an error occurs, stat returns -1 and sets errno to one of the following:

    [ENOENT] filename does not specify an existing file or directory

    [ENOTDIR] an element of filename is not an expected subdirectory

    fstat can additionally return

    [EBADF] filedes does not refer to an open file descriptor

  • BUGS

  • GNO does not yet support hard or symbolic file links on the IIGS. Therefore, lstat operates exactly like stat. But if there's a case where lstat might be appropriate at a time when links are supported, then use lstat instead and be ready for the future.

    fstat doesn't do anything clever with all the unused fields in struct stat when its argument is a pipe or terminal.

  • NAME

  • statfs - get file system statistics

  • #include <sys/vfs.h>

    int statfs(char *path, struct statfs *buf)

    int fstatfs(int fd, struct statfs *buf)


  • statfs returns information about a mounted file system. path is the path name of any file within the mounted filesystem. Buf is a pointer to a statfs structure defined as follows:

    typedef struct {

    long val[2];

    } fsid_t;

    struct statfs {

    long f_type; /* type of info, zero for now */

    long f_bsize; /* fundamental file system block size */

    long f_blocks; /* total blocks in file system */

    long f_bfree; /* free blocks */

    long f_bavail; /* free blocks available to non-superuser */

    long f_files; /* total file nodes in file system */

    long f_ffree; /* free file nodes in fs */

    fsid_t f_fsid; /* file system id */

    long f_spare[7]; /* spare for later */


    Fields that are undefined for a particular file system are set to -1. fstatfs returns the same information about an open file referenced by descriptor fd.


  • Upon successful completion, a value of 0 is returned. Otherwise, -1 is returned and the global variable errno is set to indicate the error.

  • statfs fails if one or more of the following are true:

    ENOTDIR A component of the path prefix of path is not a directory.

    EINVAL path contains a character with the high-order bit set.

    ENAMETOOLONG The length of a component of path exceeds 255 characters, or the length of path exceeds 1023 characters.

    ENOENT The file referred to by path does not exist.

    EACCES Search permission is denied for a component of the path prefix of path.

    EIO An I/O error occurred while reading from or writing to the file system.

    fstatfs fails if one or both of the following are true:

    EBADF fd is not a valid open file descriptor.

    EIO An I/O error occurred while reading from or writing to the file system