--- /dev/null
+.TH SEMEX 1 "July 10, 1992"
+.SH NAME
+semex -- exerciser for System V semaphore operations
+.SH SYNOPSIS
+semex
+.SH DESCRIPTION
+This is an interactive exerciser for the semctl(2), semget(2) and
+semop(2) system calls of System V UNIX. You can use it to experiment with
+the semaphore features in order to understand them better. It includes
+on-line help.
+.PP
+Calls that might cause semex to block (semop(2) with negative operation
+values) are handed to a forked copy of semex. Semex's children emit reports
+just before they block and when they unblock, to enable the user to track
+what's going on.
+.PP
+Semex can also be used as a semaphores interface for scripts. Command
+prompting is suppressed if stdin isn't a tty; so are the verbose
+descriptions of actions performed that it normally emits, and the
+process-forking described above.
+.SH COMMANDS
+All arguments of every command are optional; the code tries to give
+reasonable defaults to any you leave off. Anytime a `semid' or `semnum'
+argument is given, the default semid or semnum for future commands is set
+to it.
+
+ c(reate) key nsems -[ce] perms -- create semaphore group
+
+This calls semget(2). The `key' argument should be a long, the `nsems'
+argument an int. The third (flags) argument of the semget(2) call is
+created from the third and fourth arguments of this command; flags
+`c' and `e' stand for IPC_CREAT and IPC_EXCL respectively and `perms'
+should be at least three digits of octal permission mask.
+.PP
+The `current semaphore group id' (semid) is set to the return value
+of this command.
+.PP
+The default arguments are `0L 1 - 0660' (note that 0L = IPC_PRIVATE).
+
+ f(ind) semid -- select a semaphore group by id
+
+This changes semex's notion of the current semaphore group id. If the
+argument is omitted, the current value is simply printed out.
+
+ i(ndex) semnum -- select a semaphore index
+
+This changes semex's notion of the current semaphore index. If the
+argument is omitted, the current value is simply printed out.
+
+ d(o) op -[un] -- do a semaphore operation
+
+This command does a semop(2) call. The first argument of the call will
+be the currently selected semaphore id. The third argument (number of
+operations) will be 1. The (struct sembuf *) second argument will point
+to a single operation structure.
+.PP
+The sem_num field of this structure is set to the `current semaphore
+index' value set by the `n' command (normally 1). The sem_op field is set
+to the value of the `op' command argument (which should be an integer). The
+sem_flg field is set according to the flags in the third command argument;
+`u' stands for SEM_UNDO, `n' for IPC_NOWAIT.
+.PP
+The argument defaults are `0 -'.
+
+ v(alue) semid semnum -- query a semaphore's semval
+
+This command displays the return of a semctl(semid, semnum, GETVAL). If
+semnum is omitted it defaults to the currently selected semaphore index. If
+semid is omitted it defaults to the currently selected semaphore id.
+
+ p(id) semid semnum -- query a semaphore's sempid
+
+This command displays the return of a semctl(semid, semnum, GETPID). If
+semnum is omitted it defaults to the currently selected semaphore index. If
+semid is omitted it defaults to the currently selected semaphore id.
+
+ n(cnt) semid semnum -- query a semaphore's semncnt
+
+This command displays the return of a semctl(semid, semnum, GETNCNT). If
+semnum is omitted it defaults to the currently selected semaphore index. If
+semid is omitted it defaults to the currently selected semaphore id.
+
+ z(cnt) semid semnum -- query a semaphore's semzcnt
+
+This command displays the return of a semctl(semid, semnum, GETZCNT). If
+semnum is omitted it defaults to the currently selected semaphore index. If
+semid is omitted it defaults to the currently selected semaphore id.
+
+ s(et) semval -- set the value of a semaphore
+
+This command does a semop(2) call using the SETVAL command to set
+the value of the currently selected semaphore. The first argument of the call
+will be the currently selected semaphore id. The second argument of the call
+will be the currently selected semaphore index. The fourth (value) argument
+will be the semval argument of the command (which defaults to 0 if omitted).
+
+ m(mask) semid uid gid mode -- query/set a semaphore's mode
+
+The m command with no arguments displays the uid, gid and mode
+of the currently selected semaphore group. With one argument, it displays
+this information for the given semaphore group. With two or more arguments
+it sets whatever portions of the mode and ownership data are given; uid and
+gid should be decimal integers and mode at least three digits of octal.
+
+ r(emove) semid -- remove a semaphore group
+
+Do a semctl(2) to remove a semaphore group. If the semid argument is
+omitted, the currently selected semaphore group will be removed.
+
+ l(ist) -- run ipcs -sbopt
+
+This is just a convenience. It displays data on active semaphores.
+
+ x(it) -- exit
+
+Exit semex. Child semex processes created by 'd' commands will get SIGHUP
+and die gracefully.
+
+ ! cmd -- execute a shell command
+
+Escape to a shell.
+
+ ? -- print this help message
+
+In addition, typing a newline will simply display the value of the
+currently selected semaphore (newline is a synonym for the `v' command).
+.SH NOTE
+The AT&T documentation entries for semop(2) tell lies about the type of
+the second argument. System V Release 1 claims the type is
+
+ struct sembuf (*)[]
+
+and its lint library entry is correspondingly broken. Release 2 claims
+that the type is
+
+ struct sembuf **
+
+but its lint library checks for the correct type, which is
+
+ struct sembuf *
+
+as one can actually deduce from the description text for both entries.
+System V Release 3 and 4 seems to get this right.
+.SH BUGS
+The 'p' and 'v' commands are not Dyskstra's P and V operations.
+.PP
+There is no way for semex to specify more than one semaphore op at once
+in semop(2).
+.PP
+There is no support for exercising the GETALL or SETALL modes of semctl(2).
+.SH AUTHOR
+Eric S. Raymond <esr@snark.thyrsus.com>
+