UNIX Systems Programming for SVR4
UNIX Systems Programming for SVR4
By David A Curry
O’Reilly & Associates, July 1996
xxi + 596 pages, £24.50
ISBN: 1-56592-163-1
This book aims to teach the reader how to write systems programs in C for UNIX SVR4 (System V Release 4). In sixteen chapters and five appendices of clearly written prose, it manages to achieve this. It is not aimed at the novice programmer (it is assumed the reader is familiar with C programming and UNIX), and so jumps fairly quickly into the meaty stuff. All of the examples in the book are written in ANSI C.
The book focuses on three major variants of SVR4: HP-UX 10.0; Silicon Graphics’ IRIX 5.3; and Sun’s Solaris 2.x. Solaris is covered up to 2.5, so the book is very up to date.
Chapter one contains the almost obligatory UNIX history lesson, with some nice notes on SVR4’s standards compliance (eg ANSI, POSIX, and XPG/3). The rest of the chapter describes the various compilers used to test the source code, and for completeness’ sake, outlines the BSD compatibility package.
Chapter two describes what the author calls ’utility routines’. Topics
dealt with in this chapter include character and byte string manipulation
(the str* and mem* functions prototyped in string.h); dynamic memory
(the malloc family, and free); temporary files; and parsing command line
arguments. Each section (in this and subsequent chapters) describes what
the group of functions does, often with a code example, and usually ends
in a very handy “Porting Notes” subsection. The latter is invaluable for
highlighting the subtle differences in implementation between the various
flavours of SVR4, and also offers help to those porting old BSD-style
programs. The chapter ends with a description of a few miscellaneous
routines that didn’t fit into one of the other categories: string to number
conversion; printing error messages; pausing a program; and exiting.
In chapters three and four, the author discusses the low level I/O functions
and the standard I/O library. In the (fairly short) first of these, the
low level I/O functions (i.e., those that take a file descriptor as an
argument) are described. These include open; close;
read; write; lseek; and
the file descriptor duplication functions, dup and dup2. Rather more space
is devoted to chapter four, which deals with the standard I/O library. This
contains the routines prototyped in stdio.h, and the functions typically
take a file pointer as an argument. Also covered is line input and output
(with a strong warning against using gets, which I was pleased to see);
buffered and formatted I/O; and file pointer repositioning.
Chapter five talks about files and directories. It starts off with a brief
overview of filesystem concepts, before focusing on SVR4’s idea of a
filesystem (i.e., regular and special files, and directories). Next is a
section called Removable Filesystems; I believe this is a bit of a misnomer,
and perhaps the section should have been called “Mountable Filesystems”: to
me, removable implies the media can (easily) be removed from the machine,
for example CD-ROMs. The concept of the inode is introduced, and other
file types (e.g., hard and soft links; FIFOs; and UNIX domain sockets) are
described. Next, the stat family are presented, followed by (amongst others)
access; chmod; and the chown family.
Creating and deleting directories are
then covered, as is the concept of a working directory, and the directory
manipulation functions prototyped in dirent.h. The chapter concludes with
an ls-like program, which brings together most of the concepts discussed.
In chapter six, special purpose file operations are covered. It kicks off
with a discussion of file descriptor attributes, and how to get/set them
with ioctl and fcntl. In the next section, managing multiple file
descriptors with select and poll are discussed. This is followed by sections
on file and record locking, and memory mapped files. The /dev/fd filesystem
is given a brief once-over, and the chapter concludes with a quick look at the
umask, chroot, and sync functions.
Chapter seven talks about the time of day functions, starting with obtaining the current time and timezone, and progresses through converting the machine time to a human readable format, and vice versa.
Chapter eight takes a comprehensive look at users and groups. It starts
by explaining the difference between login names and user IDs, and covers the
concepts of real and effective user and group IDs. The passwd,
group, shadow, utmp[x], wtmp[x],
lastlog, and shells files are then discussed, as are the
functions that manipulate them. The chapter ends with a useful recipe on
how to write SUID (set user id) and SGID (set group id) programs, adapted
from Matt Bishop’s paper, How To Write a Setuid Program.
System configuration and resource limits are covered in chapter nine, which
starts off with a discussion about the utsname and sysinfo functions. This is
followed by a description of sysconf et al, before the process resource limits
and resource utilisation functions wrap up the chapter.
Chapter ten discusses signals, going from their concepts, to advanced signal concepts, covering topics such as basic signal handling; reliable and unreliable signals; signals and system calls; and using signals for timeouts. The chapter ends with section on porting BSD signals to SVR4.
Chapter eleven discusses processes at some length. After covering the
concepts, e.g., PIDs (process IDs), process groups, and controlling terminals,
process termination and simple process execution (i.e., using system (3)) is
covered. An in-depth look at fork and exec follows. A look at I/O
redirection, job control, and timing process execution concludes the chapter.
In chapter twelve, POSIX and pre-POSIX terminal control is discussed; the pre-POSIX discussion is further sub-divided into System V and BSD styles. The chapter ends by discussing terminal window size.
IPC (interprocess communication) is the subject matter for chapter thirteen—from pipes to semaphore protected shared memory. FIFOs, message queues, and UNIX domain sockets are also discussed, although the latter is just a primer; the more advanced material is covered in chapters fourteen and fifteen.
Chapters fourteen and fifteen cover networking with sockets and TLI (transport layer interface) respectively. Not being a networking book, the details are glossed over somewhat (even though the chapters comprise seventy pages between them). Instead, the reader is pointed at the acknowledged references in the area: Rich Steven’s UNIX Network Programming (for sockets), and Steve Rago’s UNIX System V Network Programming (for TLI).
The final chapter discusses everything that doesn’t fit into one of the preceding chapters! Topics include error logging; searching; passwords; database management; regular expressions, etc.
With the exception of appendix A (which outlines the changes in ANSI cf
K&R C), the appendices cover some of the more esoteric subjects. Appendix B
talks about accessing filesystem data structures (concentrating on Solaris
2.x, as the functions differ from one implementation to another). Appendix C
covers the /proc filesystem, while appendix D describes pseudo-terminals. The
last appendix briefly discusses accessing the network at the link level. A
comprehensive index completes the book.
I suppose the potential purchaser of this book will be comparing it to Rich Stevens’ tome, Advanced Programming in the UNIX Environment. My opinion is that the books complement each other nicely. Certainly, Stevens’ book is four years older (it isn’t SVR4 specific), and so may seem a bit dated in places, but on the other hand, it does cover some material not in UNIX Systems Programming, most notably, daemons: I was quite disappointed not to see even an appendix on such an important topic.
It would have been nice if the book had a lay flat binding, but apart from a couple of minor typos (and mixed case identifiers—ugh!), it is refreshingly easy (for a reference book) to read. Thoroughly recommended, and a welcome addition to my bookshelf.
Reviewer’s Bio
Rich Teer runs his own C/UNIX consultancy, Risc Key Developments Ltd. He is currently working in the OS Group at SunService in Camberley, and can be reached at richard.teer@rkdltd.demon.co.uk, or on the web at www.rkdltd.demon.co.uk.
