\input texinfo @c -*-texinfo-*-
@c *********************************************************************
@c
@c  This is a TEXINFO file. It generates both TEX documentation and
@c  the "on line" documentation "info" files.
@c
@c  The file is structured like a programming language. Each chapter
@c  starts with a chapter comment.
@c
@c  Menus list the subsections so that an online inforeader can parse
@c  the file hierachically.
@c
@c  Each time you add or change a node, you need to update the
@c  menus and forward/backward references. You can do this from
@c  emacs automatically by writing:
@c
@c  ESC-x texinfo-every-node-update
@c  ESC-x texinfo-all-menus-update
@c  ESC-x texinfo-master-menu
@c
@c In practice you can just type the first few letters and hit TAB
@c to write these long names.
@c
@c  Last change: MB 31/08/95
@c
@c ***********************************************************************
@c %** start of header
@setfilename unix.info
@settitle The unix programming environment
@setchapternewpage odd
@c %** end of header
 
@include version.texi
 
@titlepage
@title The unix programming environment
@subtitle Edition @value{EDITION}, @value{UPDATED}
 
@author Mark Burgess
@author Centre of Science and Technology
@author Faculty of Engineering, Oslo College
 
@c @smallbook
 
@page
@vskip 0pt plus 1filll
@ifinfo
Copyright @copyright{} 1996/7 Mark Burgess
 
   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
 
   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the section entitled "GNU General Public License" is included
exactly as in the original, and provided that the entire resulting
derived work is distributed under the terms of a permission notice
identical to this one.
 
   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that the section entitled "GNU General Public License"
may be included in a translation approved by the author instead of in
the original English.
@end ifinfo
Copyright @copyright{} 1996/7 Mark Burgess
 
   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
 
   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the section entitled "GNU General Public License" is included
exactly as in the original, and provided that the entire resulting
derived work is distributed under the terms of a permission notice
identical to this one.
 
   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that the section entitled "GNU General Public License"
may be included in a translation approved by the author instead of in
the original English.
@end titlepage

@ifinfo
@node Top, Comment, (dir), (dir)
@top UNIX
 
@end ifinfo
 
@c **********************************************************************
@c INTRO
@c **********************************************************************
 
@unnumbered Foreword
 
This is a revised version of the UNIX compendium which is
available in printed form and online via the WWW and info
hypertext readers. It forms the basis for a one or two semester
course in UNIX. The most up-to-date version of this manual
can be found at 

@smallexample
http://www.iu.hioslo.no/~mark/unix/unix.html.
@end smallexample

It is a reference guide which contains enough to help you to find what
you need from other sources. It is not (and probably can never be)
a complete and self-contained work. Certain topics are covered
in more detail than others. Some topics are included for future
reference and are not intended to be part of an introductory course,
but will probably be useful later. The chapter on X11 programming
has been deleted for the time being.

Comments to Mark.Burgess@@iu.hioslo.no
 
Oslo, June 1996
 
@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@menu
* Comment::                     
* Overview::                    
* Getting started::             
* The login environment::       
* Files and access::            
* C shell::                     
* Bourne shell::                
* Perl::                        
* WWW and CGI programming::     
* C programming::               
* Network programming::         
* Programming idioms::          
* Variable Index::              
* Concept Index::               
@end menu

@node Comment, Overview, Top, Top
@unnumbered Welcome

If you are coming to unix for the first time, from a Windows or
MacIntosh environment, be prepared for a rather different culture than
the one you are used to. Unix is not about `products' and off-the-shelf
software, it is about open standards, free software and the ability to
change just about everything.

@itemize @bullet

@item 
What you personally might perceive as user friendliness in other
systems, others might perceive as annoying time wasting. Unix offers you
just about every level of friendliness and unfriendliness, if you choose
your programs right. In this book, we take the programmer's point of
view.

@item 
Unix is about functionality, not about simplicity. Be prepared
for powerful, not necessarily `simple' solutions.

@end itemize

@noindent
You should approach Unix the way you should approach any new
system: with an open mind. The journey begins...


@node Overview, Getting started, Comment, Top
@chapter Overview
 
@emph{In this manual the word "host" is used to refer to a single computer
system -- i.e.  a single machine which has a name termed its "hostname".}

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@menu
* What is unix?::               
* Flavours of unix::            
* How to use this reference guide::  
* NEVER-DOs in UNIX::           
* What you should know before starting::  
* The superuser and nobody::    
* The file hierarchy  ::        
* Symbolic links::              
* Hard links::                  
@end menu

@node What is unix?, Flavours of unix, Overview, Overview
@section What is unix?

@cindex UNIX
@cindex UNIX history
Unix is one of the most important operating system in use
today, perhaps even @emph{the} most important. Since its invention
around the beginning of the 1970s it has been an object of continual
research and development. UNIX is not popular because it is the best
operating system one could imagine, but because it is an extremely
flexible system which is easy to extend and modify. It is an ideal
platform for developing new ideas.  

Much of the success of UNIX may be attributed to the rapid pace of its
development (a development to which all of its users have been able to
contribute) its efficiency at running programs and the many powerful
tools which have been written for it over the years, such as the C
programming language, @code{make}, shell, @code{lex} and @code{yacc} and
many others.  UNIX was written by programmers for programmers. It is
popular in situations where a lot of computing power is required and for
database applications, where timesharing is critical. In contrast to
some operating systems, UNIX performs equally well on large scale
computers (with many processors) and small computers which fit in your
suitcase!

All of the basic mechanisms required of a multi-user operating system
are present in UNIX. During the last few years it has become ever more
popular and has formed the basis of newer, though less mature, systems
like NT.  One reason for this that now computers have now become powerful
enough to run UNIX effectively.  UNIX places burdens on the resources of
a computer, since it expects to be able to run potentially many programs
simultaneously.

@cindex DOS
If you are coming to UNIX from DOS you may well be used to using
applications software or helpful interactive utilities to solve every
problem. UNIX is not usually like this: the operating system has much
greater functionality and provides the possibilities for making your
own, so it is less common to find applications software which implements
the same things. UNIX has long been in the hands of academics who are
used to making their own applications or writing their own programs,
whereas as the DOS world has been driven by businesses who are willing
to spend money on software.  For that reason commerical UNIX software is
often very expensive and therefore not available at this college. On the
other hand, the flexibility of UNIX means that it is easy to write
programs and it is possible to fetch gigabytes of @emph{free software} from the
internet to suit your needs. It may not look like what you are used to
on your PC, but then you have to remember that UNIX users are a
different kind of animal altogether

Like all operating systems, UNIX has many faults. The biggest problem
for any operating system is that it evolves without being redesigned.
Operating systems evolve as more and more patches and hacks are applied
to solve day-to-day problems. The result is either a mess which works
somehow (like UNIX) or a blank refusal to change (like DOS or
MacIntosh).  From a practical perspective, Unix is important and
successful because it is a multi-process system which

@itemize @bullet

@item
has an enormous functionality built in, and the capacity to
adapt itself to changing technologies,

@item
is relatively portable,

@item
is good at sharing resources (but not so good at security),

@item
has tools which are each developed to do @emph{one thing well},

@item
allows these tools to be combined in every imaginable way,
using pipes and channeling of data streams,

@item
incorporates networking almost trivially, because all the right
mechanisms are already there for providing services and sharing,
building client-server pairs etc,.

@item
it is very adaptable and is often used to develop
new ideas because of the rich variety of tools it possesses.

@end itemize

Unix has some problems: it is old, it contains a lot of rubbish which no
one ever bothered to throw away. Although it develops quickly (at light
speed compared to either DOS or MacIntosh) the user interface has been
the slowest thing to change. Unix is not user-friendly for beginners, it
is user-friendly for advanced users: it is made for users who
@emph{know} about computing. It sometimes makes simple things difficult,
but above all it makes things possible!

The aim of this introduction is to

@itemize @bullet

@item
introduce the unix system basics and user interface,

@item
develop the unix philosophy of using and combining tools,

@item
learn how to make new tools and write software,

@item
learn how to understand existing software.

@end itemize

@noindent
To accomplish this task, we must first learn something about
the shell (the way in which UNIX starts programs). Later we shall
learn how to solve more complex problems using Perl and C.
Each of these is a language which can be used to put UNIX to
work. We must also learn when to use which tool, so that
we do not waste time and effort. Typical uses for these 
different interfaces are

@table @emph

@item shell
Command line interaction, making scripts which perform simple
jobs such as running programs in batch, installing new software,
simple system configuration and administration.
@cindex shell

@item perl
Text interpretation, text formatting, output filters, mail
robots, WWW cgi (common gateway interface) scripts in forms,
password testing, simple database manipulation, simple client-server
applications.
@cindex perl

@item C
Nearly all of UNIX is written in C. Any program which cannot
be solved quickly using shell or perl can be written in C.
One advantage is that C is a compiled language and many simple
errors can be caught at compile time.
@cindex C

@end table

Much of UNIX's recent popularity has been a result of its networking
abilities: unix is the backbone of the internet. No other widely
available system could keep the internet alive today.

Once you have mastered the unix interface and philosophy you
will find that i) the PC and MacIntosh window environments seem
to be easy to use, but simplistic and primitive by comparison; ii) UNIX is far
from being the perfect operating system---it has a whole different
set of problems and flaws.
@cindex Windows on PC
@cindex MacIntosh
@cindex PC windows

The operating system of the future will not be UNIX as we see
it today, nor will is be DOS or MacIntosh, but one thing is for
certain: it will owe a lot to the UNIX operating system and will
contain many of the tools and mechanisms we shall describe below.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Flavours of unix, How to use this reference guide, What is unix?, Overview
@section Flavours of unix

@cindex AT&T
@cindex BSD
@cindex System V
@cindex System 5

Unix is not a single operating system. It has branched out in many
different directions since it was introduced by AT&T. The most
important @samp{fork()} in its history happened early on when the
university of Berkeley, California created the BSD (Berkeley Software
Distribution), adding network support and the C-shell.

Here are some of
the most common implementations of unix.

@table @emph
@item BSD:
 Berkeley, BSD

@item SunOS:
Sun Microsystems, BSD/sys 5

@item Solaris:
Sun Microsystems,  Sys 5/BSD

@item Ultrix:
Digital Equipment Corperation, BSD

@item OSF 1:
Digital Equipment Corperation, BSD/sys 5

@item HPUX:
Hewlett-Packard, Sys 5

@item AIX:
IBM, Sys 5 / BSD

@item IRIX:
Silicon Graphics, Sys 5

@item GNU/Linux: 
GNU, BSD/Posix

@end table

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node How to use this reference guide, NEVER-DOs in UNIX, Flavours of unix, Overview
@section How to use this reference guide

This programming guide is something between a user manual and a tutorial.
The information contained here should be sufficient to get you started
with the unix system, but it is far from complete.

To use this programming guide, you will need to work through the basics
from each chapter. You will find that there is much more information here than
you need straight away, so try not to be overwhelmed by the amount of material.
Use the contents and the indices at the back to find the information
you need. If you are following a one-semester UNIX course, you should
probably concentrate on the following:

@itemize @bullet
@item
The remainder of this introduction
@item
The detailed knowledge of the C shell
@item
An appreciation of the Bourne shell
@item
A detailed knowledge of Perl, guided by chapter 6. This chapter provides
pointers on how to get started in perl. It is not a substitute for the
perl book.
@item
Everything in chapter 7 about C programming. This chapter is written in note
form, since it is assumed that you know a lot about C programming already.
@item
A sound appreciation of chapter 8 on network programming.

@end itemize

The @emph{only} way to learn UNIX is to sit down and try it. As with any
new thing, it is a pain to get started, but once you are started, you
will probably come to agree that UNIX contains a wealth of possibilities,
perhaps more than you had ever though was possible or useful!

One of the advantages of the UNIX system is that the entire UNIX manual
is available on-line. You should get used to looking for information in
the online manual pages. For instance, suppose you do not remember
how to create a new directory, you could do the following:

@smallexample
nexus% man -k dir

dir             ls (1)          - list contents of directories
dirname         dirname (1)     - strip non-directory suffix from file name
dirs            bash (1)        - bash built-in commands, see bash(1)
find            find (1)        - search for files in a directory hierarchy
ls              ls (1)          - list contents of directories
mkdir           mkdir (1)       - make directories
pwd             pwd (1)         - print name of current/working directory
rmdir           rmdir (1)       - remove empty directories
@end smallexample

@cindex Making directories
@vindex mkdir
@cindex mkdir
@cindex apropos
@vindex apropos
@vindex man -k
@cindex Finding commands
@noindent
The @samp{man -k} command looks for a keyword in the manual and lists
all the references it finds. The command @samp{apropos} is completely
equivalent to @samp{man -k}.  Having discovered that the command to
create a directory is @samp{mkdir} you can now look up the specific
manaul page on @samp{mkdir} to find out how to use it:

@smallexample
man mkdir
@end smallexample

@noindent
Some but no all of the UNIX commands also have a help option which is
activated with the @samp{-h} or @samp{--help} command-line option.
@cindex Help function for commands
@vindex -h
@vindex --help

@smallexample
dax% mkdir --help
Usage: mkdir [OPTION] DIRECTORY...
 
  -p, --parents     no error if existing, make parent directories as needed
  -m, --mode=MODE   set permission mode (as in chmod), not 0777 - umask
      --help        display this help and exit
      --version     output version information and exit
dax% 
 
@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node NEVER-DOs in UNIX, What you should know before starting, How to use this reference guide, Overview
@section NEVER-DO's in UNIX

@cindex Never do in unix 

There are some things that you should never do in UNIX. Some of these
will cause you more serious problems
than others. You can make your own list as you discover more.

@itemize @bullet

@item
You should NEVER EVER switch off the power on a Unix computer unless you
know what you are doing.  A Unix machine is not like a PC running
DOS. Even when you are not doing anything, the system is working in the
background. If you switch off the power, you could interrupt the system
while it is writing to the disk drive and destroy your disk. You must
also remember that several users might be using the system even though
you cannot see them: they do not have to be sitting at the machine, they
could be logged in over the network. If you switch off the power, you
might ruin their valuable work.

@item 
Once you have deleted a UNIX file using @code{rm} it is impossible
to recover it! Don't use wildcards with @code{rm} without thinking
quite carefully about what you are doing! It has happened to very many
users throughout the history of UNIX that one tries to type
@smallexample
rm *~
@end smallexample
but instead, by a slip of the hand, one writes
@smallexample
rm * ~
@end smallexample
Unix then takes these wildcards in turn, so that the first command is
@code{rm *} which deletes all of your files! BE CAREFUL!

@cindex undelete
@cindex delete

@item
 Don't ever call a program or an important file @file{core}. Many
scripts go around deleting files called @file{core} because the, when a
program crashes, UNIX dumps the entire kernel image to a file called
@file{core} and these files use up a lot of disk space. If you call a
file @file{core} it might get deleted!
@cindex core

@item
 Don't call test programs @code{test}. There is a UNIX command
which is already called test and chances are that when you try to
run your program you will start the UNIX command instead. This
can cause a lot of confusion because the UNIX command doesn't seem
to do very much at all!
@end itemize
@cindex test programs
@cindex test, don't call your program this

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node What you should know before starting, The superuser and nobody, NEVER-DOs in UNIX, Overview
@section What you should know before starting

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* One library::                 
* Unix commands are files::     
* Kernel and shell::            
* The role of C::               
* Stdin::                       
@end menu

@node One library, Unix commands are files, What you should know before starting, What you should know before starting
@subsection One library: several interfaces

The core of unix is the library of functions (written in C) which
access the system. Everything you do on a unix system goes through
this set of functions. However, you can choose your own interface
to these library functions. Unix has very many different interfaces
to its libraries in the form of languages and command interpreters.

You can use the functions directly in C, or you can use command
programs like @samp{ls}, @samp{cd} etc. These functions just
provide a simple user interface to the C calls. You can also use
a variety of `script' languages: C-shell, Bourne shell, Perl, Tcl, scheme.
You choose the interface which solves your problem most easily.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Unix commands are files::     
* Kernel and shell::            
* The role of C::               
* Stdin::                       
@end menu

@node Unix commands are files, Kernel and shell, One library, What you should know before starting
@subsection Unix commands are files


@cindex Commands as files
@cindex Built in commands
@cindex shell

With the exception of a few simple commands which are built into the command
interpreter (shell), all unix commands and programs consist of
executable files. In other words, there is a separate 
executable file for each command. This makes it extremely simple
to add new commands to the system. One simply makes a program with
the desired name and places it in the appropriate directory.

@cindex Commands path
@cindex @code{PATH}
@cindex @code{path}
Unix commands live in special directories
(usually called @code{bin} for binary files). The location of
these directories is recorded in a variable called @code{path} or
@code{PATH} which is used by the system to search for
binaries. We shall return to this in more detail in later chapters.



@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Kernel and shell, The role of C, Unix commands are files, What you should know before starting
@subsection Kernel and Shell

@cindex kernel
@cindex shell
Since users cannot command the kernel directly, UNIX has a command language
known as the @emph{shell}. The word shell implies a layer around the
kernel. A shell is a user interface, or command interpreter. 

There are two main versions of the shell, plus a number of enhancements.

@table @emph
@item /bin/sh
The Bourne Shell. The shell is most often used for writing system scripts. 
It is part of the original unix system.
@cindex Bourne shell
@vindex @file{/bin/sh}
@cindex @file{sh}

@item /bin/csh
The C-shell. This was added to unix by the Berkeley workers.
The commands and syntax resemble C code. C-shell is better suited for
interactive work than the Bourne shell.
@cindex C shell
@cindex @file{csh}
@vindex @file{/bin/csh}
@end table

@cindex tcsh
@cindex bash
@cindex ksh
The program @code{tcsh} is a public-domain enhancement of the csh and is
in common use. Two improved versions of the Bourne shell also exist:
@code{ksh}, the Korn shell and @code{bash}, the Bourne-again shell.

Although the shells are mainly tools for typing in commands (which are
excutable files to be loaded and run), they contain features such as
aliases, a command history, wildcard-expansions and job control
functions which provide a comfortable user environment.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node The role of C, Stdin, Kernel and shell, What you should know before starting
@subsection The role of C

@cindex Role of C in unix
@cindex C, role in unix

Most of the unix kernel and daemons are written in the C programming
language @footnote{In particular they are written in Kernighan and
Ritchie C, not the newer ANSI standard C.}.  Calls to the kernel and to
services are made through functions in the standard C library. The
commands like @code{chmod}, @code{mkdir} and @code{cd} are all C
functions. The binary files of the same name @code{/bin/chmod},
@code{/bin/mkdir} etc. are just trivial "wrapper" programs for these C
functions.
@cindex Wrapper functions
@cindex C library calls and shell commands
@cindex Shell commands and C library calls

Until @emph{Solaris 2}, the C compiler was a standard part of the UNIX
operating system, thus C is the most natural language to program in
in a UNIX environment. Some tools are provided for C programmers:

@table @emph
@item dbx
A symbolic debugger. Also @emph{gdb}, @emph{xxgdb} @emph{ddd}.
@cindex Debugger for C

@item make
A development tool for compiling large programs.
@cindex make

@item lex
A `lexer'. A program which generates C code to recognize
words of text.
@cindex lex

@item  yacc
A `parser'. This is a tool which generates C code for
checking the syntax of groups of textual words.
@cindex yacc

@item rpcgen
A protocol compiler which generates C code from a higher
level langauge, for programming RPC applications.
@cindex rpcgen

@end table

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Stdin,  , The role of C, What you should know before starting
@subsection Stdin, stdout, stderr

Unix has three logical @emph{streams} or @emph{files} which are always
open and are available to any program.

@cindex I/O streams
@cindex Standard input
@cindex Standard output
@cindex Standard error
@vindex stdin
@vindex stdout
@vindex stderr

@table @emph
@item stdin
The standard input - file descriptor 0.
@item stdout
The standard output - file descriptor 1.
@item stderr
The standard error - file descriptor 2.
@end table

The names are a part of the C language and are defined as
pointers of type @code{FILE}.

@smallexample
#include <stdio.h>

/* FILE *stdin, *stdout, *stderr; */

fprintf(stderr,"This is an error message!\n");

@end smallexample

@noindent
The names are `logical' in the sense that they do not refer to
a particular device, or a particular place for information to 
come from or go. Their role is analogous to the `.' and `..'
directories in the filesystem. Programs can write to these
files without worrying about where the information comes from or
goes to. The user can personally define these places by
@emph{redirecting standard I/O}. This is discussed in the next
chapter.
@vindex .
@vindex ..
@cindex . directory
@cindex .. directory
@cindex Error messages

A separate stream is kept for error messages so that error output
does not get mixed up with a program's intended output.

@c -------------------------------------------------------------------------------
@c SECTION
@c -------------------------------------------------------------------------------

@node The superuser and nobody, The file hierarchy  , What you should know before starting, Overview
@section The superuser (root) and @emph{nobody}

When logged onto a UNIX system directly, the user whose name is
@code{root} has unlimited access to the files on the system. @code{root}
can also become any other user without having to give a
password. @code{root} is reserved for the system administrator or
@emph{trusted users}.
@cindex root user
@cindex superuser

Certain commands are forbidden to normal users. For example, a regular
user should not be able to halt the system, or change the ownership
of files (see next paragraph). These things are reserved for the
@code{root} or @emph{superuser}.

In a networked environment, @code{root} has no automatic authority on
remote machines. This is to prevent the system administrator of one
machine in Canada from being able to edit files on another in China.  He
or she must log in directly and supply a password in order to gain
access privileges. On a network where files are often accessible in
principle to anyone, the username @code{root} gets mapped to the user
@code{nobody}, who has no rights at all.
@cindex nobody

@c -------------------------------------------------------------------------------
@c SECTION
@c -------------------------------------------------------------------------------

@node The file hierarchy  , Symbolic links, The superuser and nobody, Overview
@section The file hierarchy

@cindex File hierarchy
@cindex Hierarchy, file

Unix has a hierachical filesystem, which makes use of directories and
sub-directories to form a tree. The root of the tree is called the root
filesystem or `/'.  Although the details of where every file is located
differ for different versions of unix, some basic features are the
same. The main sub-directories of the root directory together with the
most important file are shown in the figure. Their contents are as
follows.

@table @file

@item /bin
Executable (binary) programs. On most systems this is
a separate directory to /usr/bin. In SunOS, this is a pointer (link) to
/usr/bin.
@vindex @file{/bin}

@item  /etc
Miscellaneous programs and configuration files. This directory
has become very messy over the history of UNIX and has become a dumping
ground for almost anything. Recent versions of unix have begun to
tidy up this directory by creating subdirectories @file{/etc/mail},
@file{/etc/services} etc!
@vindex @file{/etc}

@item  /usr
This contains the main meat of UNIX. This is where application software
lives, together with all of the basic libraries used by the OS.
@vindex @file{/usr}

@item  /usr/bin
More executables from the OS.
@vindex @file{/usr/bin}

@item  /usr/local
This is where users' custom software is normally added.
@vindex @file{/usr/local}

@item  /sbin
A special area for statically linked system binaries.  They are
placed here to distinguish commands used solely by the
system administrator from user commands and so that they lie
on the system root partition where they are guaranteed to be
accessible during booting.
@vindex @file{/sbin}

@item  /sys
This holds the configuration data which go to build the
system kernel. (See below.)
@vindex @file{/sys}

@item  /export

Network servers only use this. This contains the disk space set aside for
client machines which do not have their own disks. It is like a `virtual disk'
for diskless clients.
@vindex @file{/export}

@item  /dev, /devices

A place where all the `logical devices' are collected. These are
called `device nodes' in unix and are created by @code{mknod}. Logical
devices are UNIX's official entry points for writing to devices. For instance,
@code{/dev/console} is a route to the system console, while @code{/dev/kmem}
is a route for reading kernel memory. Device nodes enable devices to be
treated as though they were files.
@vindex @file{/dev}
@vindex @file{/devices}

@item  /home

(Called @emph{/users} on some systems.) Each user has a separate login
directory where files can be kept. These are normally stored under
@code{/home} by some convention decided by the system administrator.
@vindex @file{/home}
@vindex @file{/users}

@item  /var
System 5 and mixed systems have a separate directory for spooling. Under
old BSD systems, @code{/usr/spool} contains spool queues and system
data.  @code{/var/spool} and @code{/var/adm} etc are used for holding
queues and system log files.
@vindex @file{/var}
@vindex @file{/vr/spool}
@vindex @file{/var/adm}

@item  /vmunix
This is the program code for the unix @emph{kernel} (see below). 
On HPUX systems with file is called @file{hp-ux}. On
linux it is called @file{linux}.
@vindex @file{vmunix}
@cindex Kernel

@item /kernel
On newer systems the kernel is built up from a number of modules
which are placed in this directory.

@end table

@noindent
Every unix directory contains two `virtual' directories marked
by a single dot and two dots. 

@smallexample
ls -a
.   ..
@end smallexample
@cindex . directory
@cindex .. directory

@noindent
The single dot represents the directory one is already in (the current
directory). The double dots mean the directory one level up the tree
from the current location. Thus, if one writes

@smallexample
cd /usr/local
cd ..
@end smallexample

@noindent
the final directory is @code{/usr}. The single dot is very useful in
C programming if one wishes to read `the current directory'. Since
this is always called `.' there is no need to keep track of what the
current directory really is.

`.' and `..' are `hard links' to the true
directories.
@cindex Hard links

@c -------------------------------------------------------------------------------
@c SECTION
@c -------------------------------------------------------------------------------

@node Symbolic links, Hard links, The file hierarchy  , Overview
@section Symbolic links

@cindex Soft links
@cindex Symbolic links
@vindex @code{ln -s}
@cindex @code{ln -s}

A symbolic link is a pointer or an alias to another file. The command
@smallexample
ln -s fromfile /other/directory/tolink
@end smallexample
@noindent
makes the file @code{fromfile} appear to exist at @code{/other/directory/tolink}
simultaneously. The file is not copied, it merely appears to be a
part of the file tree in two places. Symbolic links can be made to
both files and directories.

A symbolic link is just a small file which contains the name of the real
file one is interested in. It cannot be opened like an ordinary file,
but may be read with the C call @code{readlink()} @xref{lstat and readlink}.
If we remove the file a symbolic link
points to, the link remains -- it just points nowhere.

@c -------------------------------------------------------------------------------
@c SECTION
@c -------------------------------------------------------------------------------

@node Hard links,  , Symbolic links, Overview
@section Hard links

@cindex Hard links
@vindex @code{ln}


A @emph{hard link} is a duplicate @emph{inode} in the filesystem which
is in every way equivalent to the original file inode.  If a file is
pointed to by a hard link, it cannot be removed until the link is
removed.  If a file has @math{n} hard links -- all of them must be removed
before the file can be removed.  The number of hard links to a file is
stored in the filesystem @emph{index node} for the file.
@cindex inodes
@cindex Index nodes




@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node Getting started, The login environment, Overview, Top
@chapter Getting started

If you have never met unix, or another multiuser system before,
then you might find the idea daunting. There are several things
you should know. 

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@menu
* Logging in::                  
* Mouse buttons::               
* Reading mail::                
* Simple commands::             
* Text editing and word processing::  
@end menu

@node Logging in, Mouse buttons, Getting started, Getting started
@section Logging in

Each time you use unix you must log on to the system by typing a
username and a password.  Your login name is sometimes called an
`account' because some unix systems implement strict quotas for 
computer resources which have to be paid for with real
money@footnote{This is seldom true these days.}.

@cartouche
@example

  login: mark
  password:

@end example
@end cartouche

Once you have typed in your password, you are `logged on'. What
happens then depends on what kind of system you are logged onto
and how. If you have a colour monitor and keyboard in front of you,
with a graphical user interface, you will see a number of
windows appear, perhaps a menu bar. You then use a mouse and
keyboard just like any other system.

This is not the only way to log onto unix. You can also log in
remotely, from another machine, using the @code{telnet} or @code{rlogin}
@cindex telnet
@cindex Logging on
programs. If you use these programs, you will normally only get a text
or command line interface (though graphics can still be arranged).

Once you have logged in, a short message will be printed (called Message
of the Day or motd) and you will see the C-shell prompt: the name of the
host you are logged onto followed by a percent sign, e.g.

@cartouche
@example

  SunOS Release 5.5 Version Generic [UNIX(R) System V Release 4.0]
  Copyright (c) 1983-1995, Sun Microsystems, Inc.

  Please report problems to sysadm@@iu.hioslo.no

  dax% 

@end example
@end cartouche

@noindent
Remember that every unix machine is a separate entity: it is not like
logging onto a PC system where you log onto the `network' i.e. the PC
file server. Every unix machine is a server. The network, in unix-land,
has lots of players.

The first thing you should do once you have logged on is to set a
reliable password. A poor password might be okay on a PC which is not
attached to a large network, but once you are attached to the internet,
you have to remember that the whole world will be trying to crack your
password. Don't think that no one will bother: some people really have
nothing better to do.  A password should not contain any word that could
be in a list of words (in any language), or be a simple concatenation of
a word and a number (e.g. mark123).  It takes seconds to crack such a
password. Choose instead something which is easy to remember. Feel free
to use the PIN number from your bankers card in your password! This will
leave you with fewer things to remember. e.g. Ma9876rk). Passwords can
be up to eight characters long.

Some sites allow you to change your password
anywhere. Other sites require you to log onto a special machine to
change your password:

@cartouche
@example

 dax% 
 dax% passwd
 Change your password on host nexus
 You cannot change it here
 dax% rlogin nexus
 password: ******

 nexus% passwd
 Changing password for mark
 Enter login password: ********
 Enter new password: ********
 Reenter new passwd: ********

@end example
@end cartouche
@noindent
You will be prompted for your old password and your new
password twice. If your network is large, it might take the system up to
an hour or two to register the change in your password, so don't forget
the old one right away!

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@menu
* Mouse buttons::               
@end menu

@node Mouse buttons, Reading mail, Logging in, Getting started
@section Mouse buttons

Unix has three mouse buttons. On some PC's running GNU/Linux or some other
PC unix, there are only two, but the middle mouse button can be
simulated by pressing both mouse buttons simultaneously.  The mouse
buttons have the following general functions. They may also have additional
functions in special software.
@table @emph

@item index finger
This is used to select and click on objects.
It is also used to mark out areas and copy by dragging.
This is the button you normally use. 

@item middle finger
Used to pull down menus. It is also used to paste a marked
area somewhere at the mouse position.

@item outer finger
Pulls down menus.

@end table
@noindent
On a left-handed system right and left are reversed.


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Reading mail, Simple commands, Mouse buttons, Getting started
@section  E-mail

Reading electronic mail on unix is just like any other system, but there
are many programs to choose from. There are very old programs from the
seventies such as

@example
mail
@end example
@noindent
and there are fully graphical mail programs such as
@example
tkrat
mailtool
@end example
Choose the program you like best. Not all of the programs support modern
multimedia extensions because of their age. Some programs like
@code{tkrat} have immediate mail notification alerts. To start a mail
program you just type its name. If you have an icon-bar, you can click
on the mail-icon.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Simple commands, Text editing and word processing, Reading mail, Getting started
@section Simple commands

Inexperienced computer users often prefer to use file-manager
programs to avoid typing anything. With a mouse you can click
your way through directories and files without having to type
anything (e.g. the @code{fmgr} or @code{tkdesk} programs).
More experienced users generally find this to be slow and
tedious after a while and prefer to use written commands. 
Unix has many short cuts and keyboard features which make
typed commands extremely fast and much more powerful than
use of the mouse.

If you come from a DOS environment, the unix commands can be a little
strange. Because they stem from an era when keyboards had to be hit with
hammer force, and machines were very slow, the command names are
generally as short as possible, so they seem pretty cryptic. Some
familar ones which DOS borrowed from unix include,

@example
cd
mkdir
@end example
@noindent
which change to a new directory and make a new directory respectively.
To list the files in the current directory you use,
@example
ls
@end example
@noindent
To rename a file, you `move' it:
@example
mv @var{old-name} @var{new-name}
@end example

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Text editing and word processing,  , Simple commands, Getting started
@section Text editing and word processing

Text editing is one of the things which people spend most
time doing on any computer. It is important to distingiush
text editing from word processing. On a PC or MacIntosh, you are
perhaps used to Word or WordPerfect for writing documents.

Unix has a Word-like program called @code{lyx}, but for the most part
Unix users do not use word processors. It is more common in the unix
community to write all documents, regardless of whether they are
letters, books or computer programs, using a non-formatting text
editor. (Unix word processors like @code{Framemaker} do exist, but they
are very expensive. A version of MS-Word also exists for some unices.)
Once you have written a document in a normal text editor, you call up
a text formatter to make it pretty. You might think this strange, but
the truth of the matter is that this two-stage process gives you the
most power and flexibilty---and that is what most unix folks like.

For writing programs, or anything else, you edit a file by typing:
@example

 emacs myfile

@end example
@noindent
@code{emacs} is one of dozens of text-editors. It is not the simplest or
most intuitive, but it is the most powerful and if you are going to
spend time learning an editor, it wouldn't do any harm to make it this
one.  You could also click on emacs' icon if you are relying on a window
system.  Emacs is almost certainly the most powerful text editor that
exists on any system. It is not a word-processor, it not for formatting
printed documents, but it can be linked to almost any other program in
order to format and print text. It contains a powerful programming
language and has many intelligent features.  We shall not go into the
details of document formatting in this book, but only mention that
programs like @code{troff} and @code{Tex} or @code{Latex} are used for
this purpose to obtain typset-quality printing. Text formatting is an
area where Unix folks do things differently to PC folks.


@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node The login environment, Files and access, Getting started, Top
@chapter The login environment

@cindex Environment, unix user
@cindex User environment
@cindex Login environment

Unix began as a timesharing mainframe system in the seventies, when the
only terminals available were text based @emph{teletype} terminals or
@emph{tty}-s.  Later, the Massachusetts Institute of Technology (MIT)
developed the X-windows interface which is now a standard across UNIX
platforms. Because of this history, the X-window system works as a
front end to the standard UNIX shell and interface, so to understand
the user environment we must first understand the shell.
@cindex X-windows

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@menu
* Shells::                      
* UNIX command overview::       
* Terminals::                   
* The X window system::         
* Multiple screens::            
@end menu

@node Shells, UNIX command overview, The login environment, The login environment
@section Shells

@cindex Command interpreter
A shell is a command interpreter. In the early days of unix, a shell was
the only way of issuing commands to the system. Nowadays many window-based
application programs provide menus and buttons to perform simple commands,
but the UNIX shell remains the most powerful and flexible way of interacting
with the system.

@cindex @emph{init}
After logging in and entering a password, the unix process @emph{init}
starts a shell for the user logging in. Unix has several different kinds
of shell to choose from, so that each user can pick his/her favourite
command interface. The type of shell which the system starts at login is
determined by the user's entry in the @emph{passwd} database.
On most systems, the standard login shell is a variant of the C-shell.

Shells provide facilities and commands which

@itemize @bullet

@item 
Start and stop processes (programs)

@item
Allow two processes to communicate through a @emph{pipe}

@item
Allow the user to redirect the flow of input or output

@item
Allow simple command line editing and command history

@item
Define aliases to frequently used commands

@item
Define global "environment" variables which are used to configure
the default behaviour of a variety of programs. These lie in an
"associated array" for each process and may be seen with the
@samp{env} command. Environment variables are inherited by all
processes which are started from a shell.
@cindex Environment variables

@item
Provide wildcard expansion (joker notation) of filenames using @samp{*,?,[]}
@cindex Wildcards

@item
Provide a simple script language, with tests and loops, so that users
can combine system programs to create new programs of their own.

@item
Change and remember the location of the current working directory, or
location within the file hierarchy.

@end itemize

The shell does not contain any more specific functions---all other commands, such
as programs which list files or create directories etc., are executable
programs which are independent of the shell.  When you type @samp{ls},
the shell looks for the executable file called @samp{ls} in a special
list of directories called @emph{the command path} and attempts to start
this program.  This allows such programs to be developed and replaced
independently of the actual command interpreter.

Each shell which is started can be customized and configured by editing
a setup file. For the C-shell and its variants this file is called
@file{.cshrc}, and for the Bourne shell and its variants it is called
@file{.profile}. (Note that files which begin with leading dots are not
normally visible with the @samp{ls} command. Use @samp{ls -a} to view these.)
Any commands which are placed in these files are interpreted by the shell
before the first command prompt is issued. These files are typically
used to define a command search path and terminal characteristics.

@emph{On each new command line you can use the cursor keys to edit the line.
The up-arrow browses back through earlier commands. @kbd{CTRL-a} takes
you to the start of the line. @kbd{CTRL-e} takes you to the end of the
line. The @key{TAB} can be used to save typing with the `completion'
facility @xref{Command/filename completion}.}

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Shell commands generally::    
* Environment and shell variables::  
* Wildcards::                   
* Regular expressions::         
* Nested shells and reverse apostrophes::  
@end menu

@node Shell commands generally, Environment and shell variables, Shells, Shells
@subsection Shell commands generally

Shell commands are commands like @code{cp}, @code{mv},
@code{passwd}, @code{cat}, @code{more}, @code{less}, @code{cc},
@code{grep}, @code{ps} etc..

Very few commands are actually built into the shell command line
interpreter, in the way that they are in DOS -- commands are mostly
programs which exist as files. When we type a command, the shell
searches for a program with the same name and tries to execute it. The
file must be executable, or a @code{Command not found} error will
result. To see what actually happens when you type a command like
@code{gcc}, try typing in the following C-shell commands @emph{directly
into a C-shell}. (We shall discuss these commands soon.)

@smallexample
  foreach dir ( $path )       # for every directory in the list path
    if ( -x $dir/gcc ) then   # if the file is executable
      echo Found $dir/gcc     # Print message found!
      break                   # break out of loop
    else
      echo Searching $dir/gcc 
    endif
  end
@end smallexample

@noindent
The output of this command is something like

@smallexample
  Searching /usr/lang/gcc
  Searching /usr/openwin/bin/gcc
  Searching /usr/openwin/bin/xview/gcc
  Searching /physics/lib/framemaker/bin/gcc
  Searching /physics/motif/bin/gcc
  Searching /physics/mutils/bin/gcc
  Searching /physics/common/scripts/gcc
  Found /physics/bin/gcc
@end smallexample
If you type
@smallexample
  echo $path
@end smallexample
you will see the entire list of directories which are searched by the shell.
If we had left out the `break' command, we might have discovered that
UNIX often has several programs with the same name, in different directories!
For example,
@smallexample
/bin/mail
/usr/ucb/mail
/bin/Mail

/bin/make
/usr/local/bin/make.
@end smallexample
Also, different versions of unix have different conventions for placing the
commands in directories, so the path list needs to be different for
different types of unix machine. In the C-shell a few basic commands
like @code{cd} and @code{kill} are built into the shell (as in DOS).

You can find out which directory a command is stored in using the
@smallexample
which
@end smallexample
command. For example
@smallexample
nexus% which cd
cd: shell built-in command.
nexus% which cp
/bin/cp
nexus% 
@end smallexample
@code{which} only searches the directories in @code{$path} and quits after
the first match, so if there are several commands with the same name,
you will only see the first of them using which.
@cindex path
@cindex Command path

Finally, in the C-shell, the @code{which} command is built in. In the
Bourne shell it is a program:
@smallexample
nexus% which which
which: shell built-in command.
nexus% sh
$ which which
/bin/which
$ exit
nexus%
@end smallexample
Take a look at the script @code{/usr/ucb/which}. It is a script written
in the C-shell.
@cindex which command
@vindex which

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Environment and shell variables, Wildcards, Shell commands generally, Shells
@subsection Environment and shell variables

@cindex Environment variables
Environment variables are variables which the shell keeps. They are
normally used to configure the behaviour of utility programs like
@code{lpr} (which sends a file to the printer) and @code{mail} (which
reads and sends mail) so that special options do not have to be typed in
every time you run these programs.

Any program can read these variables to find out how you have
configured your working environment. We shall meet these variables
frequently. Here are some important variables

@vindex PATH
@vindex TERM
@vindex DISPLAY
@vindex LD_LIBRARY_PATH
@vindex HOST
@vindex PRINTER
@vindex HOME
@smallexample
PATH             # The search path for shell commands (sh)
TERM             # The terminal type (sh and csh)
DISPLAY          # X11 - the name of your display
LD_LIBRARY_PATH  # Path to search for object and shared libraries
HOST             # Name of this unix host
PRINTER          # Default printer (lpr)
HOME             # The path to your home directory (sh)

path             # The search path for shell commands (csh)
term             # The terminal type (csh)
noclobber        # See below under redirection
prompt           # The default prompt for csh
home             # The path to your home directory (csh)

@end smallexample
These variables fall into two groups. Traditionally the first group
always have names in uppercase letters and are called @emph{environment
variables}, whereas variables in the second group have names with
lowercase letters and are called @emph{shell variables}-- but this is
only a convention. The uppercase variables are @emph{global variables},
whereas the lower case variables are @emph{local variables}. Local
variables are not defined for programs or sub-shells started by the
current shell, while global variables are inherited by all sub-shells.
@cindex Global variables
@cindex Variables, global
@cindex Local variables
@cindex Variables, local

The Bourne-shell and the C-shell use these conventions differently and not
always consistently.  You will see how to define these below. For now
you just have to know that you can use the following commands from the
C-shell to list these variables. The command @code{env} can be used
in either C-shell or Bourne shell to see all of the defined environment
variables.
@cindex @code{env} command
@vindex env

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Wildcards, Regular expressions, Environment and shell variables, Shells
@subsection Wildcards

@cindex Wildcards
@cindex Joker notation
@vindex ?
@vindex *
@vindex []
@cindex Matching filenames

Sometimes you want to be able to refer to several files in one go. For
instance, you might want to copy all files ending in `.c' to a new
directory. To do this one uses @emph{wildcards}. Wildcards are characters
like @code{* ?} which stand for any character or group of characters.
In card games the joker is a `wild card' which can be substituted for
any other card. Use of wildcards is also called @emph{filename substitution}
in the unix manuals, in the sections on @code{sh} and @code{csh}.

The wildcard symbols are,

@table @samp
@item ?
Match single character. e.g. @code{ls /etc/rc.????}

@item *
Match any number of characters. e.g. @code{ls /etc/rc.*}

@item [...]
Match any character in a list enclosed by these brackets. e.g. @code{ls [abc].C}

@end table

@noindent
Here are some examples and explanations.

@table @samp

@item /etc/rc.????
Match all files in /etc whose first three
characters are @code{rc.} and are 7 characters long.

@item *.c
Match all files ending in `.c' i.e. all C programs.

@item *.[Cc]
List all files ending on `.c' or `.C' i.e. all C and C++ programs.

@item *.[a-z] 
Match any file ending in .a, .b, .c, ... up to .z etc.
@end table

@noindent
@cindex Matching filenames
It is important to understand that @emph{the shell expands wildcards}. When
you type a command, the program is not invoked with an argument that
contains @code{*} or @code{?}. The shell expands the special characters
first and invokes commands with the entire list of files which
match the patterns. The programs never see the wildcard characters, only
the list of files they stand for. To see this in action, you can type
@smallexample
echo /etc/rc.*
@end smallexample
which gives
@smallexample
/etc/rc /etc/rc.boot /etc/rc.ip /etc/rc.local /etc/rc.local% 
/etc/rc.local~ /etc/rc.single /etc/rc~
@end smallexample
All shell commands are invoked with a command line of this form. This
has an important corollary. It means that multiple renaming @emph{cannot work}!

Unix files are renamed using the @code{mv} command. In many microcomputer
operating systems one can write
@smallexample
rename *.x *.y
@end smallexample

@noindent
which changes the file extension of all files ending in `.x' to the same
name with  a `.y' extension. This cannot work in unix, because the
shell tries expands everything before passing the arguments to the
command line.

@emph{The local shell variable @code{noglob} switches off wildcard expansion in
the C shell, but you still cannot rename multiple files using @code{mv}.
Some free-software programs make this possible.}

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Regular expressions, Nested shells and reverse apostrophes, Wildcards, Shells
@subsection Regular expressions

@cindex Matching strings
@cindex Regular expressions
@cindex Expressions, regular
The wildcards belong to the shell. They are used for matching
filenames. UNIX has a more general and widely used mechanism for
matching @emph{strings}, this is through @emph{regular expressions}.

Regular expressions are used by the @code{egrep} utility, text editors
like @code{ed}, @code{vi} and @code{emacs} and @code{sed} and @code{awk}.
They are also used in the C programming language 
for matching input as well as in the Perl programming language and @code{lex}
tokenizer. Here are some examples using the @code{egrep} command
which print lines from the file @code{/etc/rc} which match certain
conditions. The @code{} contruction is part of @code{egrep}. Everything
in between these symbols is a regular expression. Notice that
special shell symbols @code{! * &} have to be preceded with a backslash
@code{\} in order to prevent the shell from expanding them!
@cindex @code{egrep} command

@smallexample

# Print all lines beginning with a comment #

egrep '(^#)'           /etc/rc

# Print all lines which DON'T begin with #

egrep '(^[^#])'        /etc/rc

# Print all lines beginning with e, f or g.

egrep '(^[efg])'       /etc/rc 

# Print all lines beginning with uppercase

egrep '(^[A-Z])'       /etc/rc

# Print all lines NOT beginning with uppercase

egrep '(^[^A-Z])'      /etc/rc 

# Print all lines containing ! * &

egrep '([\!\*\&])'     /etc/rc 

# All lines containing ! * & but not starting #

egrep '([^#][\!\*\&])' /etc/rc 
@end smallexample

@noindent
Regular expressions are made up of the following `atoms'.

@noindent
These examples assume that the file @file{/etc/rc} exists.
If it doesn't exist on the machine you are using, try to
find the equivalent by, for instance, replacing
@code{/etc/rc} with @code{/etc/rc*} which will try to
find a match beginning with the rc.

@vindex . in regular expressions
@vindex ^ in regular expressions
@vindex $ in regular expressions
@vindex [] in regular expressions
@vindex * in regular expressions
@vindex + in regular expressions
@vindex ? in regular expressions
@cindex . in regular expressions
@cindex ^ in regular expressions
@cindex $ in regular expressions
@cindex [] in regular expressions
@cindex * in regular expressions
@cindex + in regular expressions
@cindex ? in regular expressions

@table @samp
@item .
Match any single character except the end of line.
@item ^
Match the beginning of a line as the first character.
@item $
Match end of line as last character.
@item [..]
Match any character in the list between the square brackets.(see below).
@item *
Match zero or more occurrances of the preceding expression.
@item + 
Match one or more occurrences of the preceding expression.
@item ?
Match zero or one occurrance of the preceding expression.
@end table

You can find a complete list in the unix manual pages. The square
brackets above are used to define a @emph{class} of characters to be
matched. Here are some examples,

@itemize @bullet 

@item 
If the square brackets contain a list of
characters, $[a-z156]$ then a single occurrance of any character in the
list will match the regular expression: in this case any lowercase
letter or the numbers 1, 5 and 6.

@item 
If the first character in the brackets is the caret
symbol @samp{^} then any character @emph{except} those in the list will
be matched. 

@item 
Normally a dash or minus sign @samp{-} means a range of characters.
If it is the first character after the @samp{[} or after @samp{[^} then it
is treated literally.
@end itemize

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Nested shells and reverse apostrophes,  , Regular expressions, Shells
@subsection Nested shell commands and ``


@vindex `` shell construction
@vindex `...`

The backwards apostrophes `...` can be used in all shells and also in
the programming language Perl.  When these are encountered in a
string the shell tries to execute the command inside the quotes and
replace the quoted expression by the result of that command. For example: 
@smallexample
unix% echo "This system's kernel type is `/bin/file /vmunix`"
This system's kernel type is /vmunix: sparc executable not stripped 

unix% foreach file ( `ls /etc/rc*` )
? echo I found a config file $file
? echo Its type is `/bin/file $file`
? end

I found a config file /etc/rc
Its type is /etc/rc: executable shell script
I found a config file /etc/rc.boot
Its type is /etc/rc.boot: executable shell script
I found a config file /etc/rc.ip
Its type is /etc/rc.ip: executable shell script
I found a config file /etc/rc.local
Its type is /etc/rc.local: ascii text
I found a config file /etc/rc.local~
Its type is /etc/rc.local~: ascii text
I found a config file /etc/rc.single
Its type is /etc/rc.single: executable shell script
I found a config file /etc/rc~
Its type is /etc/rc~: executable shell script

@end smallexample

This is how we insert the result of a shell command into a text string or
variable.
@cindex Inserting a command into a string
@cindex Result of a command into a string
@cindex Getting command output into a string

@c -------------------------------------------------------------------------------
@c SECTION
@c -------------------------------------------------------------------------------


@node UNIX command overview, Terminals, Shells, The login environment
@section UNIX command overview

@menu
* Keys::                        
* Alternative shells::          
* terminal emulators::          
* Remote login::                
* Text editors::                
* File handling::               
* File browsers::               
* Access control::              
* Extracting from files::       
* Locating files::              
* Disk usage::                  
* Other users::                 
* Contacting users::            
* Mail::                        
* File transfer::               
* Compilers::                   
* Interpreted languages::       
* System statistics::           
* System identity::             
* Internet resources::          
* Text/postscript::             
* Pictures/graphics::           
* Miscellaneous::               
@end menu

@node Keys, Alternative shells, UNIX command overview, UNIX command overview
@subsection Important keys

@table @key

@item CTRL-A
Jump to start of line. If @samp{screen} is active, this
prefixes all control key commands for @samp{screen} and then
the normal @kbd{CTRL-A} is replaced by @kbd{CTRL-a a}.

@cindex @key{CTRL-A}
@vindex @key{CTRL-A}

@item CTRL-C
Interrupt or break key. Sends signal 15 to a process.
@cindex @key{CTRL-C}
@vindex @key{CTRL-C}

@item CTRL-D
Signifies @samp{EOF} (end of file) or shows expansion
matches in command/filename completion @xref{Command/filename completion}.

@cindex @key{CTRL-D}
@vindex @key{CTRL-D}


@item CTRL-E
Jump to end of line.

@cindex @key{CTRL-E}
@vindex @key{CTRL-E}


@item CTRL-L
Clear screen in newer shells and in emacs. Same as @samp{clear}
in the shell.
@cindex @key{CTRL-L}
@vindex @key{CTRL-L}


@item CTRL-Z
Suspend the present process, but do not destroy it. This sends
signal 18 to the process.

@cindex @key{CTRL-Z}
@vindex @key{CTRL-Z}

@end table

@c ----------------------------------------------

@node Alternative shells, terminal emulators, Keys, UNIX command overview
@subsection Alternative shells

@cindex @key{Shells, various}

@table @code

@item bash
The Bourne Again shell, an improved sh.
@cindex bash

@item csh
The standard C-shell.
@cindex csh

@item jsh
The same as sh, with C-shell style job control.
@cindex jsh

@item ksh
The Korn shell, an improved sh.
@cindex ksh

@item sh
The original Bourne shell.
@cindex sh

@item sh5
On ULTRIX systems the standard Bourne shell is
quite stupid. sh5 corresponds to the normal Bourne shell
on these systems.
@cindex sh5

@item tcsh
An improved C-shell.
@cindex tcsh

@item zsh
An improved sh.
@cindex zsh

@end table

@c ----------------------------------------------

@node terminal emulators, Remote login, Alternative shells, UNIX command overview
@subsection Window based terminal emulators

@cindex Terminals
@cindex Command window

@table @code

@item xterm
The standard X11 terminal window.

@cindex @samp{xterm}
@vindex @samp{xterm}

@item shelltool, cmdtool
Openwindows terminals from Sun Microsystems. These are
not completely X11 compatible during copy/paste operations.


@cindex @samp{shelltool}
@vindex @samp{shelltool}

@cindex @samp{cmdtool}
@vindex @samp{cmdtool}




@item screen
This is not a window in itself, but allows you to emulate
having several windows inside a single (say) xterm window.
The user can switch between different windows and open new
ones, but can only see one window at a time @xref{Multiple screens}.

@cindex @samp{screen}
@vindex @samp{screen}


@end table

@c ----------------------------------------------

@node Remote login, Text editors, terminal emulators, UNIX command overview
@subsection Remote shells and logins

@table @code

@item rlogin
Login onto a remote unix system.


@cindex @samp{rlogin}
@vindex @samp{rlogin}



@item rsh
Open a shell on a remote system (require access rights).

@cindex @samp{rsh}
@vindex @samp{rsh}


@item telnet
Open a connection to a remove system using the telnet
protocol.

@cindex @samp{telnet}
@vindex @samp{telnet}



@end table

@c ----------------------------------------------

@node Text editors, File handling, Remote login, UNIX command overview
@subsection Text editors

@table @code

@item ed
An ancient line-editor.

@cindex @samp{ed}
@vindex @samp{ed}


@item vi
Visual interface to @code{ed}. This is the only "standard"
unix text editor supplied by vendors.

@cindex @samp{vi}
@vindex @samp{vi}


@item emacs
The most powerful UNIX editor. A fully configurable, user
programmable editor which works under X11 and on tty-terminals.

@cindex @samp{emacs}
@vindex @samp{emacs}


@item xemacs
A pretty version of emacs for X11 windows.

@cindex @samp{xemacs}
@vindex @samp{xemacs}


@item pico
A tty-terminal only editor, comes as part of the PINE mail
package.

@cindex @samp{pico}
@vindex @samp{pico}


@item xedit
A test X11-only editor supplied with X-windows.

@cindex @samp{xedit}
@vindex @samp{xedit}


@item textedit
A simple X11-only editor supplied by Sun Microsystems.

@cindex @samp{textedit}
@vindex @samp{textedit}


@end table

@c ----------------------------------------------

@node File handling, File browsers, Text editors, UNIX command overview
@subsection File handling commands

@table @code

@item ls
List files in specified directory (like @code{dir} on other
systems).

@cindex @samp{ls command}
@vindex @samp{ls}


@item cp
Copy files.

@cindex @samp{cp} command
@vindex @samp{cp}


@item mv
Move or rename files.

@cindex @samp{mv} command
@cindex Renaming files
@cindex Moving files
@vindex @samp{mv}


@item touch
Creates an empty new file if none exists, or updates date
and time stamps on existing files.

@cindex @samp{touch} command
@vindex @samp{touch}
@cindex Creating files
@cindex Time stamp, updating
@cindex Date stamp, updating
@cindex Updating file time stamp

@item rm, unlink
Remove a file or link (delete).

@cindex @samp{rm} command
@vindex @samp{unlink}

@cindex @samp{unlink} command
@vindex @samp{unlink}


@item mkdir, rmdir
Make or remove a directory. A directory must be empty in order
to be able to remove it.

@cindex @samp{mkdir} command
@vindex @samp{mkdir}
@cindex Creating directories
@cindex Directories, creating
@cindex Directories, deleting
@cindex @samp{rmdir} command
@vindex @samp{rmdir}

@item cat
Concatenate or join together a number of files. The output is
written to the standard output by default. Can also be used
to simply print a file on screen.

@cindex @samp{cat} command
@vindex @samp{cat}


@item lp, lpr
Line printer. Send a file to the default printer, or the printer
defined in the @samp{PRINTER} evironment variable.
@cindex @samp{PRINTER} variable
@vindex @samp{PRINTER}
@cindex @samp{lp} command
@vindex @samp{lp}

@cindex @samp{lpr} command
@vindex @samp{lp}
@cindex Printing a file

@item lpq, lpstat
Show the status of the print queue.

@cindex @samp{lpq}
@vindex @samp{lpq}
@cindex Printer queue
@cindex Printer status
@cindex @samp{lpstat}
@vindex @samp{lpstat}

@end table

@c ----------------------------------------------

@node File browsers, Access control, File handling, UNIX command overview
@subsection File browsing

@table @code

@item more
Shows one screen full at a time. Possibility to search for
a string and edit the file. This is like 
@samp{type @var{file} | more} in DOS.

@cindex @samp{more} command
@vindex @samp{more}
@cindex Viewing a file
@cindex Browsing through a file
@cindex @samp{type} in DOS

@item less
An enhanced version of more.

@cindex @samp{less} command
@vindex @samp{less}

@cindex nc
@cindex mc
@item mc
Midnight commander, a free version of the `Norton Commander'
PC utility for unix. (Only for non-serious UNIX users...)

@item fmgr
A window based file manager with icons and all that nonsense.


@end table

@c ----------------------------------------------

@node Access control, Extracting from files, File browsers, UNIX command overview
@subsection Ownership and granting access permission

@cindex Access control
@cindex Granting permission
@table @code

@item chmod
Change file access mode.

@cindex @samp{chmod} command
@vindex @samp{chmod}
@cindex Changing file mode
@cindex File mode, changing

@item chown, chgrp
Change owner and group of a file. The GNU version of @code{chown}
allows both these operations to be performed together using
the syntax @code{chown @var{owner}.@var{group} @var{file}}.

@cindex @samp{chown} command
@vindex @samp{chown}

@cindex @samp{chgrp} command
@vindex @samp{chgrp}

@item acl
On newer Unices, Access control lists allow access to be granted
on a per-user basis rather than by groups.

@cindex Access control lists
@cindex ACLs

@cindex @samp{fmgr} file manager
@vindex @samp{fmgr}


@end table

@c ----------------------------------------------

@node Extracting from files, Locating files, Access control, UNIX command overview
@subsection Extracting from and rebuilding files

@table @code

@item cut
Extract a column in a table

@cindex @samp{cut} command
@vindex @samp{cut}

@item paste
Merge several files so that each file becomes a column in
a table.

@cindex @samp{paste} command
@vindex @samp{paste}


@item sed
A batch text-editor for searching, replacing and selecting
text without human intervention.

@cindex @samp{sed} editor
@vindex @samp{sed}


@item awk
A prerunner to the Perl language, for extracting and modifying
textfiles.

@cindex @samp{awk}
@vindex @samp{awk}

@item rmcr
Strip carriage return (ASCII 13) characters from a file.
Useful for converting DOS files to unix.

@end table

@c ----------------------------------------------

@node Locating files, Disk usage, Extracting from files, UNIX command overview
@subsection Locating files

@table @code

@item find
Search for files from a specified directory using various
criteria.

@cindex @samp{find} command
@vindex @samp{find}

@item locate
Fast search in a global file database for files containing
a search-string.

@cindex @samp{locate} command
@vindex @samp{locate}


@item whereis
Look for a command and its documentation on the system.

@cindex @samp{whereis} command
@vindex @samp{whereis}


@end table

@c ----------------------------------------------

@node Disk usage, Other users, Locating files, UNIX command overview
@subsection Disk usage.

@cindex Disk usage.

@table @code

@item du
Show number of blocks used by a file or files.

@cindex @samp{du} command
@vindex @samp{du}


@item df
Show the state of usage for one or more disk partitions.

@cindex @samp{df} command
@vindex @samp{df}


@end table

@c ----------------------------------------------

@node Other users, Contacting users, Disk usage, UNIX command overview
@subsection Show other users logged on

@table @code

@item users
Simple list of other users.

@cindex @samp{users} command
@vindex @samp{users}


@item finger
Show who is logged onto this and other systems.

@cindex @samp{finger} service
@vindex @samp{finger}


@item who
List of users logged into this system.

@cindex @samp{who} command
@vindex @samp{who}


@item w
Long list of who is logged onto this system and what they
are doing.

@cindex @samp{w} command
@vindex @samp{w}


@end table

@node Contacting users, Mail, Other users, UNIX command overview
@subsection Contacting other users

@table @code

@item write
Send a simple message to the named user, end with @key{CTRL-D}.
The command @samp{mesg n} switches off messages receipt.

@cindex Sending messages
@cindex Messages
@cindex @samp{write} command
@vindex @samp{write}
@cindex @samp{mesg}
@vindex @samp{mesg}



@item talk
Interactive two-way conversation with named user.

@cindex @samp{talk} service
@vindex @samp{talk}


@item irc
Internet relay chat. A conferencing system for realtime
multi-user conversations, for addicts and losers.

@cindex @samp{IRC}
@cindex Internet relay chat
@vindex @samp{irc}


@end table

@c ----------------------------------------------

@node Mail, File transfer, Contacting users, UNIX command overview
@subsection Mail senders/readers
@cindex Mail clients

@table @code

@item mail
The standard (old) mail interface.

@item Mail
Another mail interface.

@item elm
Electronic Mail program. Lots of functionality but poor
support for multimedia.

@cindex @samp{elm} mailer
@vindex @samp{elm}

              
@item pine
Rumours (untrue) are that pine stands for Pine is Not Elm;
it actually stands for nothing at all.
Improved support for multimedia but very
slow and rather stupid at times. Some of the best features of
elm have been removed!

@cindex @samp{pine} mailer
@vindex @samp{pine}


@item mailtool
Sun's openwindows client program.

@item rmail
A mail interface built into the emacs editor.

@cindex @samp{rmail} in emacs
@vindex @samp{rmail}

@item netscape mail
A mail interface built into the netscape navigator.

@item zmail
A commerical mail package.

@cindex @samp{zmail} client
@vindex @samp{zmail}

@item tkrat
A graphical mail reader which supports most MIME types, written
in tcl/tk. This program has a nice feel and allows you to create
a searchable database of old mail messages, but has a hopeless
locking mechanism.

@end table

@c ----------------------------------------------

@node File transfer, Compilers, Mail, UNIX command overview
@subsection File transfer

@cindex File transfer

@table @code

@item ftp
The File Transfer program - copies files to/from a remote host.

@cindex @samp{ftp} program
@vindex @samp{ftp}


@item ncftp
An enhanced ftp for anonymous login.

@cindex @samp{ncftp} program
@vindex @samp{ncftp}

@end table

@c ----------------------------------------------

@node Compilers, Interpreted languages, File transfer, UNIX command overview
@subsection Compilers
@cindex Compilers

@table @code

@item cc
The C compiler.

@cindex @samp{cc}
@vindex @samp{cc}


@item CC
The C++ compiler.

@cindex @samp{CC}
@vindex @samp{CC}


@item gcc
The GNU C compiler.

@cindex @samp{gcc}
@vindex @samp{gcc}


@item g++
The GNU C++ compiler.

@cindex @samp{g++}
@vindex @samp{g++}


@item ld
The system linker/loader.

@cindex @samp{ld} loader/linker
@vindex @samp{ld}


@item ar
Archive library builder.

@cindex @samp{ar} archiver
@vindex @samp{ar}


@item dbx
A symbolic debugger.

@cindex @samp{dbx} debugger
@cindex Debugger
@vindex @samp{dbx}


@item gdb
The GNU symbolic debugger.

@cindex @samp{gdb} debugger
@vindex @samp{gdb}


@item xxgdb
The GNU debugger with a windown driven front-end.
@item ddd
A motif based front-end to the gdb debugger.
@vindex ddd

@end table


@cindex @samp{xxgdb}
@cindex Debugger GUI
@vindex @samp{xxgdb}

@c ----------------------------------------------

@node Interpreted languages, System statistics, Compilers, UNIX command overview
@subsection Other interpreted languages

@table @code

@item perl
Practical extraction an report language.

@item tcl
A perl-like language with special support for
 building user interfaces and command shells.

@cindex @samp{TCL}
@vindex @samp{tcl}


@item scheme
A lisp-like extensible scripting language from GNU.


@cindex scheme

@item mercury
A prolog-like language for artificial intelligence.
@cindex Mercury

@end table

@node System statistics, System identity, Interpreted languages, UNIX command overview
@subsection Processes and system statistics

@table @code
@item ps
List system process table.

@cindex @samp{ps} command
@vindex @samp{ps}


@item vmstat
List kernel virtual-memory statistics.

@cindex @samp{vmstat} virtual memory stats
@vindex @samp{vmstat}


@item netstat
List network connections and statistics.

@cindex @samp{netstat} network statistics
@vindex @samp{netstat}


@item rpcinfo
Show rpc information.

@cindex @samp{rpcinfo}
@vindex @samp{rcpinfo}


@item showmount
Show clients mounting local filesystems.

@cindex @samp{showmount}
@cindex Mounted file systems
@vindex @samp{showmount}
@end table

@node System identity, Internet resources, System statistics, UNIX command overview
@subsection System identity

@table @code

@item uname
Display system name and operating system release.

@cindex @samp{System details}
@vindex @samp{uname}
@cindex Operating system name
@cindex System name




@item hostname
Show the name of this host.

@cindex @samp{hostname} command
@vindex @samp{hostname}


@item domainname
Show the name of the local NIS domain. Normally this is
chosen to be the same as the BIND/DNS domain, but it
need not be.

@cindex @samp{domainname} command
@vindex @samp{domainname}
@cindex Domainname


@item nslookup
Interrogate the DNS/BIND name service (hostname to IP address
conversion).

@cindex @samp{nslookup} command
@vindex @samp{nslookup}


@end table
 
@c ----------------------------------------------

@node Internet resources, Text/postscript, System identity, UNIX command overview
@subsection Internet resources

@cindex Internet resources
@table @code
   
@item archie, xarchie
Search the internet ftp database for files.

@cindex @samp{archie} program
@vindex @samp{archie}
@cindex FTP resources, finding
@cindex Finding FTP files
@cindex @samp{xarchie} client
@vindex @samp{xarchie}

@item xrn, fnews
Read news (browser).

@cindex @samp{xrn} news reader
@vindex @samp{xrn}

@cindex @samp{fnews} news reader
@vindex @samp{fnews}

@item netscape, xmosaic
Read world wide web (WWW) (browser).

@cindex @samp{mosaic}
@vindex @samp{xmosaic}


@end table

@c ----------------------------------------------

@node Text/postscript, Pictures/graphics, Internet resources, UNIX command overview
@subsection Text formatting and postscript

@cindex Postscript viewers
@cindex Text formatting
@table @code

@item tex, latex
Donald Knuth's text formatting language, pronounced "tek"
(the x is really a greek "chi"). Used widely
for technical publications. Compiles to dvi (device independent)
file format.

@cindex @samp{tex}
@vindex @samp{tex}

@cindex @samp{latex}
@vindex @samp{latex}



@item texinfo
A hypertext documentation system using tex and "info"
format. This is the GNU documentation system.
This UNIX guide is written in texinfo!!!

@cindex Hypertext
@cindex @samp{texinfo} system
@vindex @samp{texinfo}



@item xdvi
View a tex dvi file on screen.

@vindex @samp{xdvi}

@item dvips
Convert dvi format into postscript.

@cindex dvi to postscript
@vindex @samp{dvips}


@item ghostview, ghostscript
View a postscript file on screen.

@cindex @samp{ghostview} postscript previewer
@vindex @samp{ghostview}

@cindex @samp{ghostscript} "GNU postscript" interpreter
@vindex @samp{ghostscript}



@end table

@c ----------------------------------------------

@node Pictures/graphics, Miscellaneous, Text/postscript, UNIX command overview
@subsection Picture editors and processors

@cindex Picture processing

@table @code

@item xv
Handles, edits and processes pictures in a variety of
standard graphics formats (gif, jpg, tiff etc).
Use @code{xv -quit} to place a picture on your root window.

@cindex @samp{xv} picture processor
@vindex @samp{xv}
@cindex gif
@cindex jpg
@cindex tiff

@item xpaint
A simple paint program.

@cindex @samp{xpaint} program
@vindex @samp{xpaint}
@cindex Painting program

@item xfig
A line drawing figure editor. Produces postscript, tex,
and a variety of other output formats.

@cindex @samp{xfig} drawing program
@vindex @samp{xfig}
@cindex Drawing program


@item xsetroot
Load an X-bitmap image into the screen (root window)
background. Small images are tiled.

@cindex @samp{Background picture}
@vindex @samp{setroot}


@end table

@c ----------------------------------------------

@node Miscellaneous,  , Pictures/graphics, UNIX command overview
@subsection Miscellaneous

@table @code

@item date
Print the date and time.

@cindex @samp{date} command
@vindex @samp{date}
@cindex Time and date

@item ispell
Spelling checker.

@cindex Spelling checker
@vindex @samp{ispell}


@item xcalc
A graphical calculator.

@cindex Calculator, X windows
@vindex @samp{xcalc}


@item dc,bc
Text-based calculators.

@cindex Calculator, shell
@vindex @samp{dc}


@item xclock
A clock!

@item ping
Send a "sonar" ping to see if another unix host is alive.

@cindex @samp{Sonar} ping
@vindex @samp{ping}
@cindex Testing reponse from other hosts.

@end table

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Terminals, The X window system, UNIX command overview, The login environment
@section Terminals

@cindex tty
@cindex Teletype terminal
@cindex xterm program
In order to communicate with a user, a shell needs to have access to a
terminal. Unix was designed to work with many different kinds of
terminals.  Input/output commands in Unix read and write to a virtual
terminal. In @emph{reality} a terminal might be a text-based Teletype
terminal (called a @emph{tty} for short) or a graphics based terminal;
it might be 80-characters wide or it might be wider or narrower. Unix
take into account these possibility by defining a number of instances of
terminals in a more or less object oriented way.

Each user's terminal has to be configured before cursor based input/output
will work correctly. Normally this is done by choosing one of a number of
standard terminal types a list which is supplied by the system. In practice
the user defines the value of the environment variable @samp{TERM} to
an appropriate name. Typical examples are @samp{vt100} and @samp{xterm}.
If no standard setup is found, the terminal can always be configured
manually using UNIX's most cryptic and opaque of commands: @samp{stty}.

The job of configuring terminals is much easier now that hardware is more
standard. Users' terminals are usually configured centrally by the system
administrator and it is seldom indeed that one ever has to choose anything
other than @samp{vt100} or @samp{xterm}.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node The X window system, Multiple screens, Terminals, The login environment
@section The X window system

Because UNIX originated before windowing technology was available, the
user-interface was not designed with windowing in mind. The X window
system attempts to be like a virtual machine park, running a different
program in each window. Although the programs appear on one screen, they
may in fact be running on unix systems anywhere in the world, with only
the output being local to the user's display.  The standard shell
interface is available by running an X client application called
@samp{xterm} which is a graphical front-end to the standard UNIX
textual interface.

@cindex rlogin program
The @samp{xterm} program provides a virtual terminal using the X windows
graphical user interface. It works in exactly the same way as a @emph{tty}
terminal, except that standard graphical facilities like copy and paste
are available. Moreover, the user has the convenience of being able
to run a different shell in every window. For example, using the @samp{rlogin}
command, it is possible to work on the local system in one window, and on
another remote system in another window. The X-window environment allows
one to cut and paste between windows, regardless of which host the shell
runs on.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Components of X::             
* How to set up X windows::     
* X displays and authority::    
@end menu

@node Components of X, How to set up X windows, The X window system, The X window system
@subsection The components of the X-window system

The X11 system is based on the client-server model. You might wonder why
a window system would be based on a model which was introduced for
interprocess communication, or network communication. 
The answer is straightforward.
@cindex X window system

The designers of the X window system realized that network communication
was to be the paradigm of the next generation of computer systems.
They wanted to design a system of windows which would enable a user to sit
at a terminal in Massachusetts and work on a machine in Tokyo -- and
still be able to get high quality windows displayed on their terminal.
The aim of X windows from the beginning is to create a @emph{distributed}
window environment.

When I log onto my friend's Hewlett Packard workstation to use the text
editor (because I don't like the one on my EUNUCHS workstation) I want
it to work correctly on my screen, with my keyboard -- even though my
workstation is manufactured by a different company. I also want the
colours to be right despite the fact that the HP machine uses a
completely different video hardware to my machine. When I press the
curly brace key @code{@{}, I want to see a curly brace, and not some
hieroglyphic because the HP station uses a different keyboard.

These are the problems which X tries to address. In a network
environment we need a @emph{common window system} which will work on any
kind of hardware, and hide the differences between different machines as
far as possible. But it has to be flexible enough to allow us to change
all of the things we don't like -- to choose our own colours, and the
kind of window borders we want etc. Other windowing systems (like
Microsoft windows) ignore these problems and thereby lock the user
to a single vendors products and a single operating system. (That, of course,
is no accident.)

The way X solves this problem is to use the client server model. Each program
which wants to open a window on somebody's compute screen is a
client of the @emph{X window service}. To get something drawn on a user's
screen, the client asks a server on the host of interest to draw windows
for it. No client ever draws anything itself -- it asks the server to do it
on its behalf. There are several reasons for this:

@itemize @bullet

@item 
The clients can all talk a common `window language' or @emph{protocol}.
We can hide the difference between different kinds of hardware by making
the @emph{machine-specific} part of drawing graphics entirely a problem
of implementing the server on the particular hardware. 
When a new type of hardware comes along,
we just need to modify the server -- none of the clients need to be
modified.
@cindex X protocol

@item
We can contact different servers and send our output to different
hardware -- thus even though a program is running on a CPU in Tokyo,
it can ask the server in Massachusetts to display its window for it.

@item 
When more than one window is on a user's display, it eventually
becomes necessary to move the windows around and then figure out
which windows are on top of which other windows etc. If all of the
drawing information is kept in a server, it is straightforward to
work out this information. If every client drew where it wanted to,
it would be impossible to know which window was supposed to be
on top of another.
@cindex X display
@cindex Display, X
@end itemize

In X, the window manager is  a different program to the server
which does the drawing of graphics -- but the client-server idea
still applies, it just has one more piece to its puzzle.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node How to set up X windows, X displays and authority, Components of X, The X window system
@subsection How to set up X windows

The X windows system is large and complex and not particularly user
friendly. When you log in to the system, X reads two files in your home
directory which decide which applications will be started what they will
look like. The files are called
@vindex .xsession
@cindex .xsession file
@cindex Setting up the x environment

@table @emph

@item .Xsession
This file is a shell script which starts up a number of applications
as background processes and exits by calling a window manager. Here
is a simple example file

@smallexample
#!/bin/csh
#
# .xsession file
#
#

setenv PATH /usr/bin:/bin:/local/gnu/bin:/usr/X11R6/bin

#
# List applications here, with & at the end
# so they run in the background
#

  xterm -T NewTitle -sl 1000 -geometry 90x45+16+150 -sb &
  xclock &
  xbiff -geometry 80x80+510+0 &

# Start a window manager. Exec replaces this script with
# the fvwm process, so that it doesn't exist as a separate
# (useless) process.

  exec /local/bin/fvwm

@end smallexample

@item .Xdefaults
This file specifies all of the resources which X programs use. It can be
used to change the colours used by applications, or font types etc. The subject
of X-rescources is a large one and we don't have time for it here. Here
is a simple example, which shows how you can make your over-bright xterm
and emacs windows less bright grey shade.

@smallexample
xterm*background: LightGrey
Emacs*background: grey92
Xemacs*background: grey92
@end smallexample

@end table

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node X displays and authority,  , How to set up X windows, The X window system
@subsection X displays and authority

In the terminology used by X11, every client program has to contact a
@emph{display} in order to open a window.  A display is a virtual screen
which is created by the X server on a particular host. X can create
several separate displays on a given host, though most machines only have one.
@cindex DISPLAY variable
@cindex X display

When an X client program wants to open a window, it looks in the UNIX
environment variable @samp{DISPLAY} for the IP address of a host
which has an X server it can contact. For example, if we wrote
@example
setenv DISPLAY myhost:0
@end example 
the client would try to contact the X server on `myhost' and ask for
a window on display number zero (the usual display). If we wrote
@example
setenv DISPLAY 198.112.208.35:0
@end example

@noindent
the client would try to open 
display zero on the X server at the host with the IP
address @samp{198.112.208.35}.

Clearly there must be some kind of security mechanism to prevent just
anybody from opening windows on someone's display. X has two such
mechanisms:
@cindex X windows authentification
@cindex X windows access

@table @emph

@cindex xhost mechanism
@item xhost
This mechanism is now obsolete. The @samp{xhost} command is used to define
a list of hosts which are allowed to open windows on the user's display.
It cannot destinguish between individual users. i.e. the command
@code{xhost yourhost} would allow @emph{anyone} using yourhost to
access the local display. This mechanism is only present for backward
compatibility with early versions of X windows. Normally one should
use the command @code{xhost -} to exclude all others from accessing the
display.

@item Xauthority
@cindex Xauthority mechanism
@cindex X access control
The Xauthority mechanism has replaced the xhost scheme. It provides
a security mechanism which can distinguish individual users, not just hosts.
In order for a user to open a window on a display, he/she must have
a ticket---called a "magic cookie". This is a binary file 
called @file{.Xauthority} which is created in the user's home directory
when he/she first starts the X-windows system. Anyone who does
not have a recent copy of this file cannot open windows or read the
display of the user's terminal. This mechanism is based on the idea
that the user's home directory is available via NFS on all hosts he/she
will log onto, and thus the owner of the display will always have access
to the magic cookie, and will therefore always be able to open windows
on the display. Other users must obtain a copy of the file in order
to open windows there. The command @code{xauth} is an
interactive utility used for controlling the contents of the @file{.Xauthority}
file. See the @samp{xauth} manual page for more information.

@end table

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Multiple screens,  , The X window system, The login environment
@section Multiple screens

The window paradigm has been very successful in many ways, but anyone
who has used a window system knows that the screen is simply not big
enough for all the windows one would like! Unix has several solutions to
this problem.
@cindex Screens
@cindex Multiple screens

One solution is to attach several physical screens to a terminal.
The X window system can support any number of physical screens of
different types. A graphical designer might want a high resolution
colour screen for drawing and a black and white screen for writing
text, for instance. The disadvantage with this method is the cost
of the hardware.

A cheaper solution is to use a window manager such as @samp{fwvm} which
creates a virtual screen of unlimited size on a single monitor. As the
mouse pointer reaches the edge of the true screen, the window manager
replaces the display with a new "blank screen" in which to place
windows. A miniaturized image of the windows on a control panel acts as
a map which makes it possible to find the applications on the virtual
screen.

Yet another possibility is to create virtual displays inside a single
window. In other words, one can collapse several shell windows into a
single @samp{xterm} window by running the program @samp{screen}.  The
screen command allows you to start several shells in a single window
(using @key{CTRL-a CTRL-c}) and to switch between them (by typing
@key{CTRL-a CTRL-n}). It is only possible to see one shell window at a
time, but it is still possible to cut and paste between windows and one
has a considerable saving of space.  The @samp{screen} command also
allows you to suspend a shell session, log out, log in again later and
resume the session precisely where you left off.

Here is a summary of some useful screen commands:

@table @kbd

@item screen
Start the screen server.

@item screen -r
Resume a previously suspended screen session if possible.

@item CTRL-a CTRL-c
Start a new shell on top of the others (a fresh `screen') in the
current window.

@item CTRL-a CTRL-n
Switch to the next `screen'.

@item CTRL-a CTRL-a
Switch to the last screen used.

@item CTRL-a a
When screen is running, @kbd{CTRL-a} is used for screen commands and
cannot therefore be used in its usual shell meaning of `jump to start
of line'. @kbd{CTRL-a a} replaces this.

@item CTRL-a CTRL-d
Detach the screen session from the current window so that it
can be resumed later. It can be resumed
with the @samp{screen -r} command.

@item CTRL-a ?
Help screen.

@end table

@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node Files and access, C shell, The login environment, Top
@chapter Files and access

To prevent all users from being able to access all files on the system, unix
records information about @emph{who} creates files and also who is allowed
to access them later.

@cindex Access to files
@cindex Permissions on files
@cindex Access rights
@cindex File access permission
Each user has a unique @emph{username} or @emph{loginname} together with
a unique @emph{user id} or @emph{uid}. The user id is a number, whereas the login
name is a text string -- otherwise the two express the same information.
A file belongs to user A if it is @emph{owned} by user A. User A then
decides whether or not other users can read, write or execute the
file by setting the @emph{protection bits} or the @emph{permission} of the
file using the command @code{chmod}.

@cindex groups
@cindex @file{/etc/group}
In addition to user identities, there are groups of users. The idea of
a group is that several named users might want to be able to read
and work on a file, without other users being able to access it.
Every user is a member of at least one group, called the @emph{login
group} and each group has both a textual name and a number (@emph{group id}). 
The @emph{uid} and @emph{gid} of each user is recorded in the
file @code{/etc/passwd} (See chapter 6). Membership of other groups
is recorded in the file @code{/etc/group} or on some systems @code{/etc/logingroup}.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@menu
* Protection bits::             
* chmod::                       
* Umask::                       
* s-bit and t-bit::             
@end menu

@node Protection bits, chmod, Files and access, Files and access
@section Protection bits

@cindex File protection bits
@cindex Protection bits
@cindex Access bits
@cindex Long file listing
@cindex @code{ls -l}
The following output is from
the command @code{ls -lag} executed on a SunOS type machine.
@smallexample

lrwxrwxrwx  1 root     wheel           7 Jun  1  1993 bin -> usr/bin
-r--r--r--  1 root     bin        103512 Jun  1  1993 boot
drwxr-sr-x  2 bin      staff       11264 May 11 17:00 dev
drwxr-sr-x 10 bin      staff        2560 Jul  8 02:06 etc
drwxr-sr-x  8 root     wheel         512 Jun  1  1993 export
drwx------  2 root     daemon        512 Sep 26  1993 home
-rwxr-xr-x  1 root     wheel      249079 Jun  1  1993 kadb
lrwxrwxrwx  1 root     wheel           7 Jun  1  1993 lib -> usr/lib
drwxr-xr-x  2 root     wheel        8192 Jun  1  1993 lost+found
drwxr-sr-x  2 bin      staff         512 Jul 23  1992 mnt
dr-xr-xr-x  1 root     wheel         512 May 11 17:00 net
drwxr-sr-x  2 root     wheel         512 Jun  1  1993 pcfs
drwxr-sr-x  2 bin      staff         512 Jun  1  1993 sbin
lrwxrwxrwx  1 root     wheel          13 Jun  1  1993 sys->kvm/sys
drwxrwxrwx  6 root     wheel         732 Jul  8 19:23 tmp
drwxr-xr-x 27 root     wheel        1024 Jun 14  1993 usr
drwxr-sr-x 10 bin      staff         512 Jul 23  1992 var
-rwxr-xr-x  1 root     daemon    2182656 Jun  4  1993 vmunix

@end smallexample
The first column is a textual representation of the protection bits for
each file. Column two is the number of hard links to the file (See exercises
below). The third and fourth columns are the user name and group name
and the remainder show the file size in bytes and the creation date.
Notice that the directories @code{/bin} and @code{/sys} are
symbolic links to other directories.

There are sixteen protection bits for a UNIX file, but only
twelve of them can be changed by users. These twelve are split into four groups
of three. Each three-bit number corresponds to one @emph{octal} number.

The leading four invisible bits gives information about the type of file: is
the file a @emph{plain file}, a @emph{directory} or a @emph{link}. In the
output from @code{ls} this is represented by a single character:
@code{-}, @code{d} or @code{l}. 

The next three bits set the
so-called @emph{s-bits} and @emph{t-bit} which are explained below.

The remaining three groups of three bits set flags which indicate
whether a file can be read @samp{r}, written to @samp{w} or executed
@samp{x} by (i) the user who created them, (ii) the other users who are
in the group the file is marked with, and (iii) any user at all.

@cindex Text form of access bits
@cindex Access bits, text form

For example, the permission

@example
Type Owner Group Anyone
  d  rwx   r-x   ---
@end example

@noindent
tells us that the file is a directory, which can be read and written
to by the owner, can be read by others in its group, but not by
anyone else.

@emph{Note about directories.  It is impossible to @code{cd} to a
directory unless the @code{x} bit is set. That is, directories must be
`executable' in order to be accessible.}

Here are some examples of the relationship between binary, octal
and the textual representation of file modes.
@cindex Access bits, octal form

@example
Binary  Octal   Text

 001      1       x 
 010      2       w 
 100      4       r 
 110      6      rw-
 101      5      r-x  
  -      644   rw-r--r--

@end example

@noindent
It is well worth becoming familiar with the octal number representation
of these permissions.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node chmod, Umask, Protection bits, Files and access
@section chmod

@cindex @code{chmod} command
The @code{chmod} command changes the permission or @emph{mode} of a file. Only
the owner of the file or the superuser can change the permission.
Here are some examples of its use. Try them.

@smallexample
# make read/write-able for everyone
chmod a+w myfile    

# add the 'execute' flag for directory 
chmod u+x mydir/   

# open all files for everyone 
chmod 755 *        

# set the s-bit on my-dir's group
chmod g+s mydir/    

# descend recursively into directory opening all files
chmod -R a+r dir    
@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Umask, s-bit and t-bit, chmod, Files and access
@section Umask

@cindex @code{umask} variable
@cindex s-bit
@cindex setuid bit
@cindex setgid bit

When a new file gets created, the operating system must decide what 
default protection bits to set on that file. The variable @code{umask} decides this.
@code{umask} is normally set by each user in his or her @code{.cshrc}
file (see next chapter). For example
@smallexample
umask 077    # safe
umask 022    # liberal
@end smallexample

@noindent
According the UNIX documentation, the value of @code{umask} is
@samp{XOR}ed (exclusive @samp{OR}) with a value of @code{666 & umask}
for plain files or @code{777 & umask} for directories in order to find
out the standard protection. Actually this is not quite true: @samp{umask}
only removes bits, it never sets bits which were not already set
in @code{666}. For instance

@cindex @code{umask} variable
@example
umask               Permission 

077                 600 (plain)
077                 700 (dir)  
022                 644 (plain)
022                 755 (dir)  
@end example
The correct rule for computing permissions is not XOR but @samp{NOT AND}.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Making programs executable::  
* chown and chgrp::             
* Making a group::              
@end menu

@node Making programs executable, chown and chgrp, Umask, Umask
@subsection Making programs executable

@cindex Masking programs executable
@cindex Executable, making programs

A unix program is normally executed by typing its pathname. 
If the @code{x} execute bit is not set on the file, this will generate
a `Permission denied' error. This protects the system from
interpreting nonsense files as programs. To make a program executable
for someone, you must therefore ensure that they can execute
the file, using a command like

@example
chmod u+x @var{filename}
@end example

@noindent
This command would set execute permissions for the owner of the file;
@example
chmod ug+x @var{filename}
@end example

@noindent
would set execute permissions for the owner and for any users in the
same group as the file.  Note that script programs must also be readable
in order to be executable, since the shell has the interpret them by
reading.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node chown and chgrp, Making a group, Making programs executable, Umask
@subsection chown and chgrp

@cindex @code{chown} command
@cindex @code{chgrp} command

These two commands change the ownership and the group ownership of a
file. Only the superuser can change the ownership of a file on most
systems. This is to prevent users from being able to defeat quota
mechanisms.  (On some systems, which do not implement quotas, ordinary
users can give a file away to another user but not get it back again.)
The same applies to group ownership.


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Making a group,  , chown and chgrp, Umask
@subsection Making a group

Normally users other than root cannot define their own groups. This
is a weakness in Unix from older times which no one seems to be in a hurry
to change. At Oslo College, Computer Science, we use a local solution
whereby users can edit a file to create their own groups. This file is
called @file{/iu/nexus/local/iu/etc/iu-group}. The format of the group
file is:

@smallexample
@var{group-name}::@var{group-number}:@var{comma-separated-list-of-users}
@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node s-bit and t-bit,  , Umask, Files and access
@section s-bit and t-bit (sticky bit)

@cindex Sticky bit
@cindex s-bit
@cindex t-bit

The @code{s} and @code{t} bits have special uses. They are described
as follows.

@example
Octal     Text       Name 

4000      chmod u+s  Setuid bit
2000      chmod g+s  Setgid bit
1000      chmod +t   Sticky bit
@end example

@noindent
The effect of these bits differs for plain files and directories and
differ between different versions of UNIX. You should check the manual
page @code{man sticky} to find out about your system! The following is
common behaviour.

For executable files, the setuid bit tells UNIX that @emph{regardless of
who runs the program} it should be executed with the permissions and
rights of owner of the file. This is often used to allow normal users
limited access to @code{root} privileges. A @emph{setuid-root} program
is executed as @code{root} for any user. The setgid bit sets the group
execution rights of the program in a similar way.

In BSD unix, if the setgid bit is set on a directory then any new
files created in that directory assume the group ownership of the
parent directory and not the logingroup of the user who created the
file. This is standard policy under system 5.

A directory for which the sticky bit is set restrict the deletion of
files within it. A file or directory
inside a directory with the t-bit set can
only be deleted or renamed by its owner or the superuser. This is
useful for directories like the mail spool area and @code{/tmp}
which must be writable to everyone, but should not allow a user
to delete another user's files.

(Ultrix) If an executable file is marked with a sticky bit, it is held in the
memory or system swap area. It does not have to be fetched from
disk each time it is executed. This saves time for frequently
used programs like @code{ls}.

(Solaris 1) If a non-executable file is marked with the sticky bit, it
will @emph{not} be held in the disk page cache -- that is, it is never
copied from the disk and held in RAM but is written to directly.
This is used to prevent certain files from using up valuable memory.

On some systems (e.g. ULTRIX), only the superuser can set the sticky bit.
On others (e.g. SunOS) any user can create a sticky directory.


@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node C shell, Bourne shell, Files and access, Top
@chapter C shell

The C shell is the command interpreter which you use to run programs and
utilities. It contains a simple programming language for writing
tailor-made commands, and allows you to join together unix commands
with pipes. It is a configurable environment, and once you know it well,
it is the most efficient way of working with unix.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@menu
* .cshrc and .login::           
* Defining variables with set and setenv::  
* Arrays::                      
* Pipes and redirection::       
* tee and script::              
* Command history::             
* Command/filename completion::  
* Single and double quotes::    
* Job control::                 
* Scripts with argumemts::      
* subshells::                   
* Tests and conditions::        
* Loops in csh::                
* Input from the user::         
* Extracting parts of a pathname::  
* Arithmetic::                  
* Examples::                    
@end menu

@node .cshrc and .login, Defining variables with set and setenv, C shell, C shell
@section .cshrc and .login files

@cindex @file{.cshrc} file
@cindex @file{.login} file
@cindex Login evironment
@cindex C shell setup files
@cindex Setting up the C shell

Most users run the C-shell @file{/bin/csh} as their login environment,
or these days, preferably the @file{tcsh} which is an improved version
of csh.  When a user logs in to a UNIX system the C-shell starts by
reading some files which configure the environment by defining
variables like @code{path}.

@itemize @bullet
@item 
The file @file{.cshrc} is searched for in your home directory.
i.e. @file{~/.cshrc}.  If it is found, its contents are interpreted by
the C-shell as C-shell instructions, before giving you the command
prompt@footnote{Under HPUX, two other files are also read by the
C-shell. These are called @file{/etc/csh.login} and @file{/etc/src.csh},
enabling some standard set-up to be configured globally. GNU/Linux has a
similar system. On solaris systems @file{/etc/.login} is read.}.

@item 
If and only if this is the @emph{login shell} (not a sub-shell that
you have started after login) then the file @file{~/.login} is searched
for and executed.
@end itemize

@noindent
With the advent of the X11 windowing system, this has changed slightly.
Since the window system takes over the entire login procedure, users
never get to run `login shells', since the login shell is used up
by the X11 system. On an X-terminal or host running X the @file{.login} file
normally has no effect. 

With some thought, the @file{.login} file can be eliminated entirely,
and we can put everything into the @code{.cshrc}  file.
Here is a very simple example @file{.cshrc} file.

@smallexample
#
# .cshrc - read in by every csh that starts.
#

# Set the default file creation mask
umask 077

# Set the path
set path=( /usr/local/bin /usr/bin/X11 /usr/ucb /bin /usr/bin . )

# Exit here if the shell is not interactive
if ( $?prompt == 0 ) exit

# Set some variables

set noclobber notify filec nobeep
set history=100
@cindex Setting the prompt
@cindex Prompt, redefining
set prompt="`hostname`%"
set prompt2 = "%m %h>"    # tcsh, prompt for foreach and while

setenv PRINTER myprinter
setenv LD_LIBRARY_PATH /usr/lib:/usr/local/lib:/usr/openwin/lib

# Aliases are shortcuts to unix commands

alias passwd  yppasswd
alias dir     'ls -lg \!* | more'
alias sys     'ps aux | more'
alias h       history
@end smallexample

It is possible to make a much more complicated .cshrc file than this.
The advent of distributed computing and NFS (Network file system)
means that you might log into many different machines running
different versions of unix. The command path would have to be set
differently for each type of machine.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Defining variables with set and setenv, Arrays, .cshrc and .login, C shell
@section Defining variables with set, setenv

We have already seen in the examples above how to define variables in
C-shell. Let's formalize this. To define a local variable -- that is,
one which will not get passed on to programs and sub-shells running
under the current shell, we write

@smallexample
set local = "some string"
set myname = "`whoami`"
@end smallexample

@noindent
These variables are then referred to by using the dollar @samp{$} symbol.
i.e. The value of the variable @samp{local} is @samp{$local}.

@smallexample
echo $local $myname
@end smallexample

@noindent
Global variables, that is variables which all sub-shells inherit from
the current shell are defined using @samp{setenv}

@smallexample
setenv GLOBAL "Some other string"
setenv MYNAME "`who am i`"
@end smallexample

@noindent
Their values are also referred to using the @samp{$} symbol. Notice that
@code{set} uses an @samp{=} sign while @samp{setenv} does not.
@cindex @code{set} command
@cindex Local variables in csh
@cindex @code{setenv} command
@cindex Global variables in csh

Variables can be also created without a value. The shell uses this
method to switch on and off certain features, using variables
like @samp{noclobber} and @samp{noglob}. For instance
@smallexample
nexus% set flag
nexus% if ($?flag) echo 'Flag is set!'
Flag is set!
nexus% unset flag
nexus% if ( $?flag ) echo 'Flag is set!'
nexus% 
@end smallexample

@noindent
The operator @samp{$?@var{variable}} is @samp{true} if @var{variable}
exists and @samp{false} if it does not. It does not matter whether
the variable holds any information.
@vindex set
@vindex unset
@cindex @code{unset} command

The commands @samp{unset} and @samp{unsetenv} can be used to undefine
or delete variables when you don't want them anymore.
@cindex Undefining variables

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Arrays, Pipes and redirection, Defining variables with set and setenv, C shell
@section Arrays

@cindex Arrays in csh
@cindex () operators to make array in csh
@vindex () in csh

A useful facility in the C-shell is the ability to make arrays out of
strings and other variables. The round parentheses @samp{(..)} do this.
For example, look at the following commands.
@smallexample
nexus% set array = ( a b c d )
nexus% echo $array[1]
a
nexus% echo $array[2]
b
nexus% echo $array[$#array]
d

nexus% set noarray = ( "a b c d" )
nexus% echo $noarray[1]
a b c d
nexus% echo $noarray[$#noarray]
a b c d
@end smallexample

@noindent
The first command defines an array containing the elements @samp{a b c d}.
The elements of the array are referred to using square brackets @samp{[..]}
and the first element is @samp{$array[1]}. The last element is 
@samp{$array[4]}. @emph{NOTE: this is not the same as in C or C++ where
the first element of the array is the zeroth element!}

The special operator @samp{$#} returns the number of elements in an array.
This gives us a simple way of finding the end of the array.
For example
@smallexample
nexus% echo $#path
23

nexus% echo "The last element in path is $path[$#path]"
The last element in path is .
@end smallexample

@noindent
To find the next last element we need to be able to do arithmetic. We'll
come back to this later.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Pipes and redirection, tee and script, Arrays, C shell
@section Pipes and redirection in csh

@cindex Pipes
@cindex @samp{|} symbol
@vindex |
@vindex >
@vindex <
@vindex >>
@vindex <<
@vindex &
@cindex Redirection of stdio
@cindex Standard I/O, redirection

The symbols 
@smallexample
              <  >  >>  <<  |  &
@end smallexample
@noindent
have a special meaning in the shell. By default, most commands take their
input from the file @samp{stdin} (the keyboard) and write
their output to the file @samp{stdout} and their error messages to the
file @samp{stderr} (normally, both of these output files are defined to be
the current terminal device @samp{/dev/tty}, or @samp{/dev/console}).

@samp{stdin}, @samp{stdout} and @samp{stderr}, known collectively as
@samp{stdio}, can be redefined or @emph{redirected} so that 
information is taken from
or sent to a different file. The output direction can be
changed with the symbol @samp{>}. For example,

@cindex Output, sending to a file
@smallexample
echo testing > myfile
@end smallexample

@noindent
produces a file called @file{myfile} which contains the string `testing'.
The single @samp{>} (greater than) sign always creates a new file, whereas
the double @samp{>>} appends to the end of a file, if it already exists.
So the first of the commands
@smallexample
echo blah blah >> myfile
echo Newfile > myfile
@end smallexample

@noindent
adds a second line to @samp{myfile} after `testing', whereas the second
command writes over @file{myfile} and ends up with just one line
`Newfile'.

Now suppose we mistype a command
@smallexample
ehco test > myfile
@end smallexample

@noindent
The command @samp{ehco} does not exist and so the error message
@samp{ehco: Command not found} appears on the terminal. This error
message was sent to @emph{stderr} -- so even though we redirected output
to a file, the error message appeared on the screen to tell us that
an error occurred. Even this can be changed. @samp{stderr} can also
be redirected by adding an ampersand @samp{&} character 
to the @samp{>} symbol. The command
@smallexample
ehco test >& myfile
@end smallexample
@noindent
results in the file @file{myfile} being created, containing the
error message `ehco: Command not found'.

The input direction can be changed using the @samp{<} symbol
for example
@smallexample
/bin/mail mark < message
@end smallexample

@noindent
would send the file @samp{message} to the user @samp{mark} by
electronic mail. The mail program takes its input from the file
instead of waiting for keyboard input.

@cindex @code{noclobber} variable
@cindex Protecting files from overwrite with @samp{>}
@cindex @code{noclobber} overwrite protection
There are some refinements to the redirection symbols. First of all,
let us introduce the C-shell variable @samp{noclobber}. If this variable
is set with a command like
@smallexample
set noclobber
@end smallexample

@noindent
then files will not be overwritten by the @samp{>} command. If one
tries to redirect output to an existing file, the following happens.
@smallexample
unix% set noclobber
unix% touch blah        # create an empty file blah
unix% echo test > blah
blah: File exists.
@end smallexample

If you are nervous about overwriting files, then you can set @samp{noclobber}
in your @file{.cshrc} file. @samp{noclobber} can be overridden using
the pling @samp{!} symbol. So
@smallexample
unix% set noclobber
unix% touch blah        # create an empty file blah
unix% echo test >! blah
@end smallexample

@noindent
writes over the file @samp{blah} even though @samp{noclobber} is set.

Here are some other combinations of redirection symbols

@cindex Appending to a file with @samp{>>}
@table @samp
@item >>
 Append, including @samp{stderr}
@item >>!
Append, ignoring @samp{noclobber}
@item >>&!
Append @samp{stdout}, @samp{stderr}, ignore @samp{noclobber}
@item <<
See below.
@end table

@noindent
The last of these commands reads from the standard input until it
finds a line which contains a word. It then feeds all of this input
into the program concerned. For example,
@smallexample
nexus% mail mark <<quit
nexus 1> Hello mark
nexus 2> Nothing much to say...
nexus 2> so bye
nexus 2> 
nexus 2> quit
Sending mail...
Mail sent!
@end smallexample

@noindent
The mail message contains all the lines up to, but not including `marker'.
This method can also be used to print text verbatim from a file
without using multiple echo commands. Inside a script one
may write:
@cindex Formatting text in a file
@cindex Printing multiple lines

@smallexample
cat << "marker";

           MENU

    1) choice 1
    2) choice 2
    ...

marker
@end smallexample
The @code{cat} command writes directly to @code{stdout} and the
input is redirected and taken directly from the script file.
@vindex <<
@cindex Input over many lines


@cindex Pipe
@cindex @samp{|} symbol
A very useful construction is the `pipe' facility.  Using the @samp{|}
symbol one can feed the @samp{stdout} of one program straight into
the @samp{stdin} of another program. Similarly with @samp{|&} both
@samp{stdout} and @samp{stderr} can be piped into the input of another
program. This is very convenient. For instance, look up the following
commands in the manual and try them.

@cindex Piping to more to prevent scrolling
@smallexample
ps aux | more
echo 'Keep on sharpenin them there knives!' | mail henry
vmstat 1 | head
ls -l /etc | tail
@end smallexample

@noindent
Note that when piping both standard input and standard error to another
program, the two files @emph{do not mix synchronously}. Often @samp{stderr}
appears first.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node tee and script, Command history, Pipes and redirection, C shell
@section @samp{tee} and @samp{script}

@cindex @samp{tee} command
@cindex Splitting output to several files
@cindex Copy of output to file
@cindex Output to file
Occasionally you might want to have a copy of what you see on your
terminal sent to a file. @samp{tee} and @samp{script} do this. For
instance,
@smallexample
find / -type l  -print | tee myfile
@end smallexample

@noindent
sends a copy of the output of @samp{find} to the file `myfile'. @samp{tee}
can split the output into as many files as you want:

@smallexample
@var{command} | tee @var{file1} @var{file2} ....
@end smallexample

@noindent
You can also choose to record the output an entire shell session using
the @samp{script} command.
@smallexample
nexus% script mysession
Script started, file is mysession

nexus% echo Big brother is scripting you
Big brother is scripting you

nexus% exit
exit
Script done, file is mysession
@end smallexample

@noindent
The file `mysession' is a text file which contains a transcript of the
session.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Command history, Command/filename completion, tee and script, C shell
@section Command history

@cindex Command history
@cindex Up arrow
The history feature in C-shell means that you do not have to type
commands over and over again. In the @samp{tcsh} version of the C shell,
and the @samp{bash} version of the Bourne shell, you can use the @key{UP
ARROW} key to browse back through the list of commands you have typed
previously.

In the normal C-shell (@samp{csh}) there are three
main commands.
@table @samp
@item !!
Execute the last command again.

@item !-3
Execute the third last command again.

@item !4
Execute command number 4.
@end table

The first of these simply repeats the last command. The second
counts backwards from the last command to three commands-ago. The
final command gives an absolute number. The absolute command number
can be seen by typing @samp{history}.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Command/filename completion, Single and double quotes, Command history, C shell
@section Command/filename completion

@cindex Filename completion
@cindex Command completion
@cindex @key{TAB} completion key
In the @samp{tcsh} extension of the C-shell, you can save hours worth
of typing errors by using the completion mechanism. This feature is
based on the @key{TAB} key.

The idea is that if you type half a filename and press @key{TAB},
the shell will try to guess the remainder of the filename. It does
this by looking at the files which match what you have already typed
and trying to fill in the rest. If there are several files which
match, the shell sounds the "bell" or beeps. You can then
type @key{CTRL-D} to obtain a list of the possible alternatives.
Here is an example: suppose you have just a single file in the
current directory called @file{very_long_filename}, typing

@smallexample
more @key{TAB}
@end smallexample

@noindent
results in the following appearing on the command line
@smallexample
more very_long_filename
@end smallexample

@noindent
The shell was able to identify a unique file. Now suppose that
you have two files called @file{very_long_filename} and @file{very_big_filename},
typing
@smallexample
more @key{TAB}
@end smallexample

@noindent
results in the following appearing on the command line
@smallexample
more very_
@end smallexample

@noindent
and the shell beeps, indicating that the choice was not unique and
a decision is required. Next, you type @key{CTRL-D} to see which files
you ahve to choose from and the shell lists them and returns you to
the command line, exactly where you were. You now choose
@file{very_long_filename} by typing @samp{l}. This is enough to
uniquely identify the file. Pressing the @key{TAB} key again
results in
@smallexample
more very_long_filename
@end smallexample

@noindent
on the screen.  As long as you have written enough to select a file
uniquely, the shell will be able to complete the name for you.

Completion also works on shell commands, but it is a little slower since
the shell must serach through all the directories in the command
path to complete commands.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Single and double quotes, Job control, Command/filename completion, C shell
@section Single and double quotes

@cindex Single and double quotes
@cindex @key{'} and @key{"}
@vindex '
@vindex "
@vindex `
@cindex Backwards quotes
@cindex @key{`} symbol and embedded shells
@cindex Embedded shell

Two kinds of quotes can be used in shell apart from the
backward quotes we mentioned above. The essential difference
between them is that certain
shell commands work inside @emph{double} quotes but not inside single 
quotes. For example
@smallexample

nexus% echo /etc/rc.*
/etc/rc.boot /etc/rc.ip /etc/rc.local 

nexus% echo "/etc/rc.*"
/etc/rc.*

nexus% echo "`who am i`  -- my name is $user ???"
nexus!mark     ttyp7   Jul 13 10:16  -- my name is mark ???

nexus% echo '`who am i`  -- my name is $user ???'
`who am i`  -- my name is $user ???

@end smallexample
We see that the single quotes prevent @emph{variable substitution}
and @emph{sub-shells}. Wildcards do not work inside either single or
double quotes.
@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Job control, Scripts with argumemts, Single and double quotes, C shell
@section Job control, break key, @samp{fg}, @samp{bg}

@cindex Job control
@cindex Foreground process
@cindex Background process

So far we haven't mentioned UNIX's ability to multitask. In the Bourne
shell (@samp{sh}) there are no facilities for controlling several user
processes @footnote{Newer versions of the Bourne shell, like the Korn
shell and Bourne-again-shell do have these facilities.}. C-shell
provides some commands for starting and stopping processes.  These
originate from the days before windows and X11, so some of them may seem
a little old-fashioned. They are still very useful nonetheless.

Let's begin by looking at the commands which are true for any shell.
Most programs are run in the @emph{foreground} or @emph{interactively}.
That means that they are connected to the standard input and send their
output to the standard output.  A program can be made to run in the
background, if it does not need to use the standard I/O. For example, a
program which generates output and sends it to a file could run in the
background. In a window environment, programs which create their own
windows can also be started as background processes, leaving standard
I/O in the shell free.

@emph{Background processes run independently of what you are doing in the 
foreground.}

@c ..............................
@c SUBSECTION
@c ..............................

@menu
* Processes and signals::       
* Child processes and zombies::  
* Builtins::                    
@end menu

@node Processes and signals, Child processes and zombies, Job control, Job control
@subsection Unix Processes and BSD signals

@cindex @samp{find} command
@cindex Processes
@cindex Background process

A background process is started using the special charcter @samp{&} at
the end of the command line.
@smallexample
find / -name '*lib*' -print >& output  &
@end smallexample

@noindent
The final @samp{&} on the end of this line means that the job will be
run in the background. Note that this is not confused with the
redirection operator @samp{>&} since it must be the last character on
the line. The command above looks for any files in the system containing
the string `lib' and writes the list of files to a file called
`output'. This might be a useful way of searching for missing libraries
which you want to include in your environment variable
@samp{LD_LIBRARY_PATH}.  Searching the enire disk from the root
directory @samp{/} could take a long time, so it pays to run this in the
background.

If we want to see what processes are running, we can use the
@samp{ps} command. @samp{ps} without any arguments lists all of
your processes, i.e. all processes owned by the user name you
logged in with. @samp{ps} takes many options, for instance
@samp{ps auxg} will list all processes in gruesome detail.
(The "g" is for group, not gruesome!)
@samp{ps} reads the kernel's process tables directly.

Processes can be stopped and started, or killed one and for all.
The @samp{kill} command does this. There are, in fact, two versions
of the @samp{kill} command. One of them is built into the C-shell
and the other is not. If you use the C-shell then you will never
care about the difference. We shall nonetheless mention the
special features of the C-shell built-ins below. The kill command
takes a number called a @emph{signal} as an argument and another
number called the @emph{process identifier} or @emph{PID} for short.
Kill send signals to processes. Some of these are fatal and some
are for information only. The two commands

@smallexample
kill -15 127
kill 127

@end smallexample

@noindent
are identical. They both send signal 15 to PID 127. This is
the normal @emph{termination} signal and it is often enough to
stop any process from running.

Programs can choose to ignore certain signals by trapping
signals with a special handler. One signal they cannot
ignore is signal 9.

@smallexample
kill -9  127
@end smallexample

@noindent
is a sure way of killing PID 127. Even though the process dies, it
may not be removed from the kernel's process table if it has
a parent (see next section).

Here is the complete list of unix signals which the kernel send to
processes in different circumstances.

@smallexample
1   "SIGHUP",         /* hangup */
2   "SIGINT",         /* interrupt */
3   "SIGQUIT",        /* quit */
4   "SIGILL",         /* illegal instruction (not reset when caught) */
5   "SIGTRAP",        /* trace trap (not reset when caught) */
6   "SIGIOT/SIGABRT", /* IOT instruction */
7   "SIGEMT",         /* EMT instruction */
8   "SIGFPE",         /* floating point exception */
9   "SIGKILL",        /* kill (cannot be caught or ignored) */
10  "SIGBUS",         /* bus error */
11  "SIGSEGV",        /* segmentation violation */
12  "SIGSYS",         /* bad argument to system call */
13  "SIGPIPE",        /* write on a pipe with no one to read it */
14  "SIGALRM",        /* alarm clock */
15  "SIGTERM",        /* software termination signal from kill */
16  "SIGURG",         /* urgent condition on IO channel */
17  "SIGSTOP",        /* sendable stop signal not from tty */
18  "SIGTSTP",        /* stop signal from tty */
19  "SIGCONT",        /* continue a stopped process */
20  "SIGCHLD/SIGCLD", /* to parent on child stop or exit */
21  "SIGTTIN",        /* to readers pgrp upon background tty read */
22  "SIGTTOU",        /* like TTIN for output if (tp->t_local&LTOSTOP) */
23  "SIGIO/SIGPOLL",  /* input/output possible signal */
24  "SIGXCPU",        /* exceeded CPU time limit */
25  "SIGXFSZ",        /* exceeded file size limit */
26  "SIGVTALRM",      /* virtual time alarm */
27  "SIGPROF",        /* profiling time alarm */
28  "SIGWINCH",       /* window changed */
29  "SIGLOST",        /* resource lost (eg, record-lock lost) */
30  "SIGUSR1",        /* user defined signal 1 */
31  "SIGUSR2"

@end smallexample

We have already mentioned 15 and 9 which are the main signals
for users. Signal 1, or @samp{HUP} can be sent to certain programs
by the superuser. For instance
@smallexample
kill -1   <inetd>
kill -HUP <inetd>
@end smallexample

@noindent
which forces @samp{inetd} to reread its configuration file. Sometimes
it is useful to @emph{suspend} a process temporarily and then
@emph{restart} it later. 
@smallexample
kill -18 <PID>       # suspend process <PID>
kill -19 <PID>       # resume process <PID>
@end smallexample

@c ..............................
@c SUBSECTION
@c ..............................

@node Child processes and zombies, Builtins, Processes and signals, Job control
@subsection Child Processes and zombies

When you start a process from a shell, regardless of whether it is
a background process or a foreground process, the new process becomes
a @emph{child} of the original shell. Remember that the shell is just
a unix process itself. Moreover, if one of the children starts a new
process then it will be a child of the child (a grandchild?)! 
Processes therefore form
@emph{hierachies}. Several children can have a common @emph{parent}.

If we kill a parent, then (unless the child has detached itself from the
parent) all of its children die too. If a child dies, the parent is not
affected. Sometimes when a child is killed, it does not die but becomes
"defunct" or a zombie process. This means that the child has a parent
which is @emph{waiting} for it to finish. If the parent has not yet been
informed that the child has died, for example because it has been
suspended itself, then the dead child is not removed from the kernel's
process table. When the parent wakes up and receives the message that
the child has terminated, the process entry for the dead child can be
removed.

@c ..............................
@c SUBSECTION
@c ..............................

@node Builtins,  , Child processes and zombies, Job control
@subsection C-shell builtins: @samp{jobs}, @samp{kill}, @samp{fg},@samp{bg}, break key

@cindex Starting shell jobs
@cindex @samp{fg} command
@cindex @samp{bg} command
@cindex Job numbers in csh

Now let's look at some commands which are built into the C-shell for
starting and stopping processes.  C-shell refers to user programs as
`jobs' rather than processes -- but there is no real difference. The
added bonus of the C-shell is that each shell has a @emph{job number} in
addition to its PID. The job numbers are simpler and are private for the
shell, whereas the PIDs are assigned by the kernel and are often very
large numbers which are difficult to to remember. When a command is
executed in the shell, it is assigned a job number. If you never run any
background jobs then there is only ever one job number: 1, since every
job exits before the next one starts. However, if you run background
tasks, then you can have several jobs "active" at any time. Moreover, by
@emph{suspending} jobs, C-shell allows you to have several interactive
programs running on the same terminal -- the @samp{fg} and @samp{bg}
commands allow you to move commands from the background to the
foreground and vice-versa.

Take a look at the following shell session.
@smallexample
nexus% emacs myfile &
[1] 4990
nexus% 

  ( other commands ... , edit myfile and close emacs )


[1]    Exit 70                emacs myfile
@end smallexample

@noindent
When a background job is done, the shell prints a message at a suitable
moment between prompts.

@smallexample
[1]  Done    emacs myfile
@end smallexample

@noindent
This tells you that job number 1 finished normally. If the job
exits abnormally then the word `Done' may be replaced by some other
message. For instance, if you kill the job, it will say 
@cindex @samp{kill} command
@smallexample
unix% kill %12
[12] Terminated     textedit file
@end smallexample

@noindent
You can list the jobs you have running using the @samp{jobs} command.
The output looks something like
@smallexample
[1]  + Running                textedit c.tex
[3]    Running                textedit glossary.tex
[4]    Running                textedit net.tex
[5]    Running                textedit overview.tex
[6]    Running                textedit perl.tex
[7]    Running                textedit shell.tex
[8]    Running                textedit sysadm.tex
[9]    Running                textedit unix.tex
[10]   Running                textedit x11.tex
[11] - Running                shelltool
[15]   Suspended              emacs myfile
@end smallexample

@noindent
@cindex Suspending a job
@cindex Moving a job to the background
@cindex Job, moving to background
@cindex Process. moving to background

To suspend a program 
which you are running in the foreground
 you can type @key{CTRL-z} (this is like sending a @samp{kill -18}
signal from the keyboard).  @footnote{This does not seem to work in
solaris?!}  You can suspend any number of programs and then restart them
one at a time using @samp{fg} and @samp{bg}. If you want job 5 to be
restarted in the foreground, you would type

@smallexample
fg %5
@end smallexample

@noindent
When you have had enough of job 5, you can type CTRL-z to suspend it
and then type

@noindent
@smallexample
fg %6
@end smallexample

@noindent
to activate job 6.  Provided a job does not want to send output to
@samp{stdout}, you can restart any job in the background, using a
command like.
@smallexample
bg %4
@end smallexample

@emph{This method of working was useful before windows were available.}
@emph{Using @samp{fg} and @samp{bg}, you can edit several files}
@emph{or work on several programs without have to quit to}
@emph{move from one to another.}


See also some related commands for
batch processing @samp{at}, @samp{batch} and @samp{atq}, @samp{cron}.

@cindex Break key
@cindex Panic button
NOTE: @key{CTRL-c} sends a @samp{kill -2} signal, which send a standard
interrupt message to a program. This is always a safe way to interrupt
a shell command.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node Scripts with argumemts, subshells, Job control, C shell
@section Scripts with arguments

@cindex Script, making
@cindex Making a script
@cindex Writing a script

One of the useful features of the shell is that you can use the normal
unix commands to make programs called @emph{scripts}. To make a script,
you just create a file containing shell commands you want to execute and
make sure that the first line of the file looks like the following example.

@smallexample
#!/bin/csh -f
#
# A simple script: check for user's mail
#
#

set path = ( /bin /usr/ucb )               # Set the local path

cd /var/spool/mail                         # Change dir

foreach uid ( * )

   echo "$uid has mail in the intray! "    # space prevents an error!

end

@end smallexample

@cindex @samp{#!program} sequence
The sequence @samp{#!/bin/csh} means that the following commands are to
be fed into @file{/bin/csh}. The two symbols @samp{#!} must be the very
first two characters in the file.  The @samp{-f} option means that your
@samp{.cshrc} file is not read by the shell when it starts up.  The file
containing this script must be executable (see @samp{chmod}) and must be
in the current path, like all other programs.

@cindex Command line arguments
@cindex Argument vector in csh
@cindex @samp{argv}
@cindex Arguments, command line
Like C programs, C-shell scripts can accept command line arguments.
Suppose you want to make a program to say hello to some other
users who are logged onto the system.
@smallexample
say-hello mark sarah mel 
@end smallexample

@noindent
To do this you need to know the names that were typed on the command
line. These names are copied into an array in the C-shell called
the @emph{argument vector}, or @samp{argv}. To read these arguments,
you just treat @samp{argv} as an array.

@cindex @code{foreach} example
@cindex @code{write} example
@smallexample
#!/bin/csh -f
#
# Say hello
#

foreach name ( $argv )

   echo Saying hello to $name
   echo "Hello from $user! " | write $name

end

@end smallexample
The elements of the array can be referred to 
as @samp{argv[1]}..@samp{argv[$#argv]} as usual. They can also be referred
to as @samp{$1}..@samp{$3} upto the last acceptable number. This makes
C-shell compatible with the Bourne shell as far as arguments are
concerned. One extra flourish in this method is that you can also
refer to the name of the program itself as @samp{$0}.
For example,
@smallexample
#!/bin/csh -f

echo This is program $0 running for $user
@end smallexample

@noindent
@samp{$argv} represents all the arguments. You can also use
@samp{$*} from the Bourne shell.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------

@node subshells, Tests and conditions, Scripts with argumemts, C shell
@section Sub-shells ()

@cindex Subshells and ()
@cindex () and subshells

The C-shell does not allow you to define subroutines or functions, but
you can create a local shell, with its own private variables by
enclosing commands in parentheses.
@smallexample
#!/bin/csh

cd /etc

( cd /usr/bin; ls * ) > myfile

pwd

@end smallexample
This program changes the working directory to /etc and then executes
a subshell which @emph{inside the brackets} changes directory to
/usr/bin and lists the files there. The output of this private
shell are sent to a file `myfile'. At the end we print out the
current working directory just to show that the @samp{cd} command
in brackets had no effect on the main program.

Normally both parentheses must be on the same line.
If a subshell command line gets too long, so that the brackets are not
on the same line, you have to use backslash characters to continue the
lines,
@smallexample

(  command \
   command \
   command \
)
@cindex Continuing long lines
@cindex Long lines, continuing

@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Tests and conditions, Loops in csh, subshells, C shell
@section Tests and conditions

@cindex Tests and conditions in csh
@cindex @code{if..then..else} in csh

No programming language would be complete without tests and loops.
C-shell has two kinds of decision structure: the @samp{if..then..else}
and the @samp{switch} structure. These are closely related to their
C counterparts. The syntax of these is
@smallexample
if (@var{condition}) @var{command}

if (@var{condition}) then
   command
   command..
else
   command
   command..
endif

@cindex @code{switch..case} in csh

switch (@var{string})

  case @var{one}: 
              commands
              breaksw

  case @var{two}: 
              commands
              breaksw

  ...

endsw

@end smallexample

In the latter case, no commands should appear on the same line as a `case'
statement, or they will be ignored. Also, if the @samp{breaksw}
commands are omitted, then control flows through all the commands
for case 2, case 3 etc, exactly as it does in the C programming
language.

We shall consider some examples
of these statements in a moment, but first it is worth listing some
important tests which can be used in @samp{if} questions to find
out information about files.
@cindex Testing files
@vindex -r @var{file}
@vindex -w @var{file}
@vindex -e @var{file}
@vindex -z @var{file}
@vindex -f @var{file}
@vindex -d @var{file}

@table @samp
@item -r @var{file}
True if the file exists and is readable
@item -w @var{file}
True if the file exists and is writable
@item -x @var{file}
True if the file exists and is executable
@item -e @var{file} 
True if the file simply exists
@item -z @var{file}
True if the file exists and is empty
@item -f @var{file}
True if the file is a plain file
@item -d @var{file}
True if the file is a directory
@end table


We shall also have need of the following comparision operators.

@cindex Comparison operators in csh
@cindex Operators in csh
@vindex @samp{==}
@vindex @samp{!=}
@vindex @samp{>}
@vindex @samp{<}
@vindex @samp{>=}
@vindex @samp{<=}
@vindex @samp{=~}
@vindex @samp{!~}


@table @samp
@item ==
is equal to (string comparison)
@item !=
is not equal to
@item >
is greater than
@item <
is less than
@item >=
is greater than or equal to
@item <=
is less than or equal to
@item =~ 
matches a wildcard
@item !~
does not match a wildcard
@end table

The simplest way to learn about these statements is to use them, so we
shall now look at some examples.

@smallexample
#!/bin/csh -f
#
#  Safe copy from <arg[1]> to <arg[2]>
#
#

if ($#argv != 2) then

  echo "Syntax: copy <from-file> <to-file>"
  exit 0

endif

if ( -f $argv[2] ) then

   echo "File exists. Copy anyway?"

   switch ( $< )                     # Get a line from user

      case y:
               breaksw

      default:
               echo "Doing nothing!"
               exit 0

   endsw

endif

echo -n "Copying $argv[1] to $argv[2]..."
cp $argv[1] $argv[2]
echo done

endif
@end smallexample

This script tries to copy a file from one location to another. If the
user does not type exactly two arguments, the script quits with a
message about the correct syntax. Otherwise it tests to see whether
a plain file has the same name as the file the user wanted to copy
to. If such a file exists, it asks the user if he/she wants to
continue before proceding to copy.


@c ---------------------
@c Subsection
@c ---------------------

@menu
* Switch example::              
@end menu

@node Switch example,  , Tests and conditions, Tests and conditions
@subsection Switch example: configure script

@cindex @samp{uname} command
@cindex System identity and @samp{uname}
Here is another example which compiles a software package.  
This is a problem we shall return to later @xref{Make}. The problem
this script tries to address is the following. There are many different
versions of UNIX and they are not exactly compatible with one
another. The program this file compiles has to work on any kind of UNIX,
so it tries first to determine what kind of UNIX system the script is
being run on by calling @samp{uname}. Then it defines a variable
@samp{MAKE} which contains the path to the `make' program which will
build @emph{software}. The make program reads a file called `Makefile'
which contains instructions for compiling the program, but this file
needs to know the type of UNIX, so the script first copies a file
`Makefile.src' using @samp{sed} replace a dummy string with the real
name of the UNIX. Then it calls make and sets the correct permission on
the file using @samp{chmod}.
@cindex @samp{sed}, search and replace
@cindex Swapping text strings

@cindex Make software script
@cindex Build software script
@cindex Compiler script
@smallexample
#!/bin/csh -f
#################################################
#
#
# CONFIGURE Makefile AND BUILD software
#
#
#################################################

set NAME = ( `uname -r -s` )

switch ($NAME[1])

   case SunOS*:
                  switch ($NAME[2])

                     case 4*:
                              setenv TYPE SUN4
                              setenv MAKE /bin/make
                              breaksw
                     case 5*:
                              setenv TYPE SOLARIS
                              setenv MAKE /usr/ccs/bin/make
                              breaksw

                  endsw
                  breaksw

   case ULTRIX*:
                  setenv TYPE ULTRIX
                  setenv MAKE /bin/make
                  breaksw
   case HP-UX*:
                  setenv TYPE HPuUX
                  setenv MAKE /bin/make
                  breaksw
   case AIX*:
                  setenv TYPE AIX
                  setenv MAKE /bin/make
                  breaksw

   case OSF*:
                  setenv TYPE OSF
                  setenv MAKE /bin/make
                  breaksw
   case IRIX*:
                  setenv TYPE IRIX
                  setenv MAKE /bin/make
                  breaksw

   default:
                  echo Unknown architecture $NAME[1]

endsw

 # Generate Makefile from source file

sed s/HOSTTYPE/$TYPE/ Makefile.src > Makefile

echo "Making software. Type CTRL-C to abort and edit Makefile"

$MAKE software         # call make to build program
chmod 755 software     # set correct protection

@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Loops in csh, Input from the user, Tests and conditions, C shell
@section Loops in csh

@cindex Loops in csh
@cindex @code{foreach}
@cindex @code{repeat}
@cindex @code{while}
@vindex foreach
@vindex repeat
@vindex while

The C-shell has three loop structures: @samp{repeat}, @samp{while}
and @samp{foreach}. We have already seen some examples of the @samp{foreach}
loop.

The structure of these loops is as follows
@smallexample
repeat @var{number-of-times} @var{command}


while ( @var{test expression} )

   @var{commands}

end


foreach  @var{control-variable}  ( @var{list-or-array} )

   @var{commands}

end

@end smallexample

@noindent
@cindex @samp{continue} in csh
@vindex continue
The commands @samp{break} and @samp{continue}
can be used to break out of the loops at any
time. Here are some examples.

@smallexample
repeat 2 echo "Yo!" | write mark
@end smallexample
@noindent

This sends the message "Yo!" to mark's terminal twice.
@smallexample
repeat 5 echo `echo "Shutdown time! Log out now" | wall ; sleep 30` ; halt
@end smallexample

@noindent
This example repeats the command `echo Shutdown time...'
five times at 30 second intervals, before shutting down the system.
Only the superuser can run this command! Note the strange
construction with `echo echo'. This is to force the repeat command
to take two shell commands as an argument. (Try to explain
why this works for yourself.)

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Input from the user, Extracting parts of a pathname, Loops in csh, C shell
@section Input from the user

@cindex Input in csh
@cindex @samp{$<} operator
@vindex breaksw
@cindex @samp{breaksw}

@smallexample

# Test a user response

echo "Answer y/n (yes or no)"

set valid = false

while ( $valid == false )

   switch ( $< )

      case y: 
              echo "You answered yes"
              set valid = true
              breaksw

      case n: 
              echo "You answered no"
              set valid = true
              breaksw

      default:
              echo "Invalid reponse, try again"
              breaksw

   endsw

end
@end smallexample

@noindent
Notice that it would have been simpler to replace the two lines
@smallexample
  set valid = true
  breaksw
@end smallexample

@noindent
by a single line @samp{break}. @samp{breaksw} jumps out of the switch
construction, after which the @samp{while} test fails. @samp{break}
jumps out of the entire while loop.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Extracting parts of a pathname, Arithmetic, Input from the user, C shell
@section Extracting parts of a pathname

@cindex Parts of a filename
@vindex :h
@vindex :t
@vindex :e
@vindex :r
@cindex Extracting filename components

A path name consists of a number of different parts:
@itemize @bullet
@item 
The path to the directory where a file is held.
@item 
The name of the file itself.
@item 
The file extension (after a dot).
@end itemize

By using one of the following modifiers, we can extract these
different elements.

@table @samp
@item :h 
The path to the file 
@item :t
The filename itself 
@item :e
The file extension 
@item :r
The complete file-path minus the file extension 
@end table

Here are some examples and the results:
@smallexample
set f = ~/progs/c++/test.C

echo $f:h    

 /home/mark/progs/c++

echo $f:t    

  test.C

echo $f:e    

   C
echo $f:r    

   /home/mark/progs/c++/test
@end smallexample

@noindent


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Arithmetic, Examples, Extracting parts of a pathname, C shell
@section Arithmetic

Before using these features in a real script, we need one more possibility:
numerical addition, subtraction and multiplication etc.

@cindex Arithemtic operations in csh
@vindex @samp{+}
@vindex @samp{+=}
@vindex @samp{++}
@vindex @samp{-}
@vindex @samp{-=}
@vindex @samp{--}
@vindex @samp{==} equal to (compare)
@vindex @samp{>} greater than
@vindex @samp{<} less than
@vindex @samp{||} logical OR
@vindex @samp{|} OR
@vindex @samp{&} AND
@vindex @samp{^} XOR
@vindex @samp{>>} shift
@vindex @samp{<<} shift
@vindex @samp{!} not
@vindex @samp{=} assignment


To tell the C-shell that you want to perform an operation on numbers
rather than strings, you use the @samp{@@} symbol followed by a space.
Then the following operations are possible.
@smallexample
@@ var = 45                      # Assign a numerical value to var
echo $var                       # Print the value

@@ var = $var + 34               # Add 34 to var
@@ var += 34                     # Add 34 to var

@@ var -= 1                      # subtract 1 from var
@@ var *= 5                      # Multiply var by 5

@@ var /= 3                      # Divide var by 3 (integer division)
@@ var %= 3                      # Remainder after dividing var by 3

@@ var++                         # Increment var by 1
@@ var--                         # Decrement var by 1

@@ array[1] = 5                  # Numerical array

@@ logic = ( $x > 6 && $x < 10)  # AND
@@ logic = ( $x > 6 || $x < 10)  # OR
@@ false = ! $var                # Logical NOT

@@ bits = ( $x | $y )            # Bitwise OR 
@@ bits = ( $x ^ $y )            # Bitwise XOR
@@ bits = ( $x & $y )            # Bitwise AND

@@ shifted = ( $var >> 2 )       # Bitwise shift right
@@ back    = ( $var << 2 )       # Bitwise shift left
@end smallexample
These operators are precisely those found in the C 
programming language.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Examples,  , Arithmetic, C shell
@section Examples

The following script uses the operators in the last two sections
to take a list of files with a given file extension (say @samp{.doc})
and change it for another (say @samp{.tex}). This is a partial
solution to the limitation of not being able to do multiple
renames in shell.

@smallexample
#!/bin/csh -f
#############################################################
#
# Change file extension for multiple files
#
#############################################################

if ($#argv < 2) then
  echo Syntax: chext oldpattern newextension
  echo "e.g: chext *.doc tex "
  exit 0
endif

mkdir /tmp/chext.$user                 # Make a scratch area

set newext="$argv[$#argv]"             # Last arg is new ext
set oldext="$argv[1]:e"

echo "Old extenstion was ($oldext)""
echo "New extension ($newext) -- okay? (y/n)"

switch( $< )

   case y:
           breaksw
   default: 
           echo "Nothing done."
           exit 0
endsw


##############################################################
# Remove the last file extension from files
##############################################################

@ i = 0

foreach file ($argv)

  @ i++
  if ( $i == $#argv ) break
  cp $file /tmp/chext.$user/$file:r        # temporary store

end

###############################################################
# Add .newext file extension to files
###############################################################

set array = (`ls /tmp/chext.$user`)

foreach file ($array)

  if ( -f $file.$newext ) then
    echo  destination file $file.$newext exists. No action taken.
    continue
  endif

  cp /tmp/chext.$user/$file $file.$newext
  rm $file.$oldext

end

rm -r /tmp/chext.$user


@end smallexample


Here is another example to try to decipher. Use the manual pages to
find out about @samp{awk}. This script can be written much more
easily in Perl or C, as we shall see in the next chapters. It is
also trivially implemented as a script in the system administration
language cfengine.

@smallexample
#!/bin/csh -f
###########################################################
#
# KILL all processes owned by $argv[1] with PID > $argv[2]
#
###########################################################

@cindex @samp{whoami} command

if ("`whoami`" != "root") then
  echo Permission denied
  exit 0
endif

if ( $#argv < 1 || $#argv > 2 ) then
  echo Usage: KILL username lowest-pid
  exit 0
endif

if ( $argv[1] == "root") then
  echo No! Too dangerous -- system will crash
  exit 0
endif

############################################################
# Kill everything
############################################################

if ( $#argv == 1 ) then

  set killarray = ( `ps aux |  awk '@{ if ($1 == user) \
@{printf "%s ",$2@}@}' user=$argv[1]` )

  foreach process ($killarray)

     kill -1 $process
     kill -15 $process > /dev/null
     kill -9 $process > /dev/null

     if ("`kill -9 $process | egrep -e 'No such process'`" == "") then
        echo "Warning - $process would not die - try again"
     endif
  end

#############################################################
# Start from a certain PID
#############################################################

else if ( $#argv == 2 ) then

  set killarray = ( `ps aux |  awk '@{ if ($1 == user && $2 > uid) \
@{printf "%s ",$2@}@}' user=$argv[1] uid=$argv[2]` )

  foreach process ($killarray)

@cindex @samp{sleep} command
     kill -1 $process > /dev/null
     kill -15 $process
     sleep 2
     kill -9 $process > /dev/null

     if ("`kill -9 $process | egrep -e 'No such process'`" == "") then
        echo "Warning - $process would not die - try again"
     endif
  end

endif

@end smallexample

@noindent
This program would be better written in C or Perl.


@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node Bourne shell, Perl, C shell, Top
@chapter Bourne shell

@cindex Bourne shell
Programmers who are used to C or C++ often find it easier to program in
C-shell because there are strong similarities between the two.  The
Bourne shell is somewhat different in style, but is structured in a way
which makes it better suited to more complicated script writing,
especially for system administrators. Also it is closer to the kernels
own exec mechanism.  The Bourne shell allows subroutines and default
values for parameters. Most of the system scripts in UNIX are written in
the Bourne shell.

The principles of the Bourne shell are largely the same as those for the C-shell,
so we shall skip fairly quickly through the details. Historically,
the Bourne shell came before the C shell.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@menu
* .profile::                    
* Variables and export::        
* stdin stdout stderr::         
* Arithmetic in sh::            
* Scripts and arguments::       
* Return codes::                
* Tests in sh::                 
* Input in sh::                 
* Loops in sh::                 
* Procedures and traps::        
* setuid setgid scripts::       
* Limitations of shell::        
* Ex4::                         
@end menu

@node .profile, Variables and export, Bourne shell, Bourne shell
@section .profile

@vindex .profile
@vindex .cshrc
@cindex @file{.profile} set up in sh
The @samp{.profile} file is the Bourne shell's answer to @samp{.cshrc}.
This file is read by interactive @file{/bin/sh} shells on starting
up. On Sun systems the file @file{/etc/profile} is also read. On
@samp{HPUX} machines, the file @file{/etc/src.sh} is read.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Variables and export, stdin stdout stderr, .profile, Bourne shell
@section Variables and export

@cindex Global variables in sh
@cindex Local variables in sh
Local and global variables are both defined using the syntax
@smallexample
VARIABLE="Some string"
VAR=13
@end smallexample

@noindent
It is important that there be no space between the variable and the
equals sign. By default these variables are @emph{local}. To make them
global (so that child processes will inherit them) we use the
command
@smallexample
export VARIABLE
@end smallexample

@cindex @samp{EXPORT} command in sh
@noindent
This adds the variable to the process @emph{environment}. It is the analogue of
making `environment variables' with @code{setenv} in C shell.
The command
@smallexample
set -a
@end smallexample

@noindent
changes the default so that all variables, after the command are
created @emph{global}.

Arrays or lists are often simulated in shell by sandwiching the colon @samp{:}
symbol between items
@smallexample
PATH=/bin:/usr/bin:/etc:/local/bin:.

LD_LIBARAY_PATH=/usr/lib:/usr/openwin/lib:/local/lib
@end smallexample

@noindent
but there is no real facility for arrays in the Bourne shell. Note that
the UNIX @samp{cut} command can be used to extract the elements of
the list. Loops can also read such lists directly @xref{Loops in sh}.
A Perl script can also be used.

The value of a variable is given by the dollar symbol as in C-shell. It
is also possible to use @emph{curly braces} around the variable name to
`protect' the variable from interfering text. For example:
@smallexample
$ animal=worm  
$ echo book$animal
bookworm
$ thing=book
$ echo $thingworm
                       (nothing..)
$ echo $@{thing@}worm
bookworm

@end smallexample

@noindent
Default values can be given to variables in the Bourne shell. The
following commands illustrate this.

@smallexample
echo $@{var-"No value set"@}
echo $@{var="Octopus"@}
echo $@{var+"Forced value"@}
echo $@{var?"No such variable"@}
@end smallexample

@noindent
The first of these prints out the contents of @samp{$var}, if it is
defined. If it is not defined the variable is substituted for the
string "No value set". The value of @samp{var} is not changed by this
operation. It is only for convenience.

The second command has the same effect as the first, but here the value
of @samp{$var} is actually changed to "Octopus" if @samp{$var}
is not set.

The third version is slightly peculiar. If @samp{$var} is @emph{already}
set, its value will be forced to be "Forced value", otherwise it is
left undefined.

Finally the last instance issues an error message "No such variable"
if @samp{$var} is not defined.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node stdin stdout stderr, Arithmetic in sh, Variables and export, Bourne shell
@section Stdin, stdout and stderr

In the Bourne shell, the standard input/output files are referred to
by numbers rather than by names.
@cindex Standard I/O in sh

@table @emph
@item stdin
File number 0
@item stdout
File number 1
@item stderr
File number 2
@end table

@noindent
The default routes for these files can be changed by @emph{redirection}.
The redirection commands are more complicated than in C-shell, but they
are also more flexible. Here is a comparison.
@cindex Redirecting stdio in sh
@cindex @samp{1>} in sh
@cindex @samp{2>} in sh
@cindex @samp{2>&1} in sh

@smallexample
sh                           csh               Description

command > file            command > file      Stdout to file 
command 1> file           command > file      Stdout to file 
command 2> errs            (No analogue)      Stderr only to file errs 
command 1> file 2>&1      command >& file     stdout and stderr to file 
command 1> file 2> errs    (No analogue)      stdout to file, stderr to errs 
@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Arithmetic in sh, Scripts and arguments, stdin stdout stderr, Bourne shell
@section Arithmetic in sh

@cindex Arithemtic in sh

Arithmetic is performed entirely `by proxy'. There are no internal
arithmetic operators as in the C-shell. To evaluate an expression
we call the @samp{expr} command or the @samp{bc}
precision calculator. Here are some examples of @samp{expr}
@smallexample
a=`expr $a+1`                 # increment a
a=`expr 4 + 10 \* 5`          # 4+10*5
check = `expr $a \> $b`       # true=1, false=0. True if $a > $b
@end smallexample

@noindent
@samp{expr} is very sensitive to spaces and backslash characters.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Scripts and arguments, Return codes, Arithmetic in sh, Bourne shell
@section Scripts and arguments

Scripts are created by making an executable file which begins
with the sequence of characters

@cindex Scripts in sh, making
@cindex Making scripts in sh
@cindex @samp{#!program} sequence

@smallexample
#!/bin/sh
@end smallexample

@noindent
Although we didn't discuss it before, this construction is quite
general: any executable file which begins with a sequence
@smallexample
#!myprogram -option
@end smallexample

@noindent
will cause the shell to attempt to execute
@smallexample
myprogam -option filename
@end smallexample

@noindent
where @var{filename} is the name of the file.

@cindex Command line arguments in sh

If a script is to accept arguments then these can be referred to as
@samp{ $1 $2 $3..$9}. There is a logical limit of nine arguments to
a script, but in practice it is possibile to get around this
limitation. @samp{$0} is the name of the script itself.

Here is a simple script in the Bourne shell which prints out
all its arguments.
@cindex @code{for} loop in sh
@smallexample

#!/bin/sh
#
# Print all arguments (version 1)
#

for arg in $*
do
  echo Argument $arg
done

echo Total number of arguments was $#

@end smallexample

@noindent
The @samp{$*} symbol stands for the entire list of arguments (like
@samp{$argv} in C-shell) and @samp{$#} is the total number of
arguments (like @samp{$#argv} in C-shell).

Another way of achieving the same is to use the @samp{shift} command.
We shall meet this again in the Perl programming language. @samp{shift}
takes the first argument from the argument list and deletes it, moving
all of the other arguments down one number -- this is how we can
handle long lists of arguments in @samp{sh}.
@cindex @code{while} loop in sh
@cindex @code{shift} operator on strings

@smallexample
#!/bin/sh
#
#  Print all arguments (version 2)
#

while ( true )
do
  arg=$1;
  shift;
  echo $arg was an argument;
  if [ $# -eq 0 ]; then
    break
  fi
done

@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Return codes, Tests in sh, Scripts and arguments, Bourne shell
@section Return codes

@cindex Return codes
@cindex Decisions and return codes in sh

All programs which execute in UNIX return a value through the C 
@samp{return} command. There is a convention that a return value
of zero (0) means that everything went well, whereas any
other value implies that some error occurred. The return
value is usually the value returned in @samp{errno}, the
extenal error variable in C.

Shell scripts can
test for these values either by placing the command
directly inside an `if' test, or by testing the variable @samp{$?}
which is always set to the return code of the last command.
Some examples are given following the next two sections.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Tests in sh, Input in sh, Return codes, Bourne shell
@section Tests and conditionals

@cindex Tests in sh

The Bourne shell has the usual array of tests. They are written as
follows. Notice that @samp{test} is itself not a part of the shell,
but is a program which works out conditions and provides a return
code. See the manual page on @samp{test} for more details.

@vindex @samp{-f} in sh
@vindex @samp{-d} in sh
@vindex @samp{-r} in sh
@vindex @samp{-w} in sh
@vindex @samp{-x} in sh
@vindex @samp{-s} in sh
@vindex @samp{-g} in sh
@vindex @samp{-u} in sh
@vindex @samp{=} in sh
@vindex @samp{!=} in sh
@vindex @samp{-eq} in sh
@vindex @samp{-ne} in sh
@vindex @samp{-gt} in sh
@vindex @samp{-lt} in sh
@vindex @samp{-ge} in sh
@vindex @samp{-le} in sh
@vindex @samp{!} in sh
@vindex @samp{-a} in sh
@vindex @samp{-o} in sh

@table @code
@item test -f @var{file} 
True if the file is a plain file 
@item test -d @var{file}  
True if the file is a directory
@item test -r @var{file}  
True if the file is readable
@item test -w @var{file}  
True if the file is writable
@item test -x @var{file}  
True if the file is executable
@item test -s @var{file}  
True if the file contains something
@item test -g @var{file}  
True if setgid bit is set
@item test -u @var{file}  
True if setuid bit is set
@item test s1 = s2      
True if strings s1 and s2 are equal
@item test s1 != s2     
True if strings s1 and s2 are unequal
@item test @var{x} -eq @var{y}  
True if the integers @var{x} and @var{y} are numerically equal
@item test @var{x} -ne @var{y}  
True if integers are not equal
@item test @var{x} -gt @var{y}  
True if @var{x} is greater than @var{y}
@item test @var{x} -lt @var{y}  
True if @var{x} is less than @var{y}
@item test @var{x} -ge @var{y}  
True if @var{x}>=@var{y}
@item test @var{x} -le @var{y} 
 True if @var{x} <= @var{y}
@item !  
Logical NOT operator
@item -a  
Logical AND
@item -o  
Logical OR
@end table

Note that an alternate syntax for writing these commands if to use the
square brackets, instead of writing the word test.
@cindex @samp{test} in sh
@cindex @samp{[]} for test in sh
@smallexample
 [ $x -lt $y ]   "=="    test $x -lt $y
@end smallexample

@cindex @code{if..then..else..fi} in sh

The conditional structures have the following syntax.
@smallexample
if @var{unix-command}
then
   @var{command}
else
   @var{commands}
fi
@end smallexample

@noindent 
The @samp{else} clause is, of course, optional.
As noted before, the first unix command could be @emph{anything}, since
every command has a return code. The result is TRUE if it evaluates
to @emph{zero} and false otherwise (in contrast to the conventions in most
languages). 
Multiple tests can be made using
@smallexample
if @var{unix-command}
then
   @var{commands}
elif @var{unix-command}
then
   @var{commands}
elif @var{unix-command}
then
   @var{commands}
else
   @var{commands}
fi
@end smallexample

@noindent
where @samp{elif} means `else-if'.

The equivalent of the C-school's @samp{switch} statement is a more
Pascal-like @samp{case} structure.
@smallexample
case @var{unix-command-or-variable} in

   wildcard1) @var{commands} ;;
   wildcard2) @var{commands} ;;
   wildcard3) @var{commands} ;;

esac
@end smallexample

@noindent
This structure uses the wildcards to match the output of the command
or variable in the first line. The first pattern which matches gets
executed.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Input in sh, Loops in sh, Tests in sh, Bourne shell
@section Input from the user in sh

In shell you can read the value of a variable using the @samp{read}
command, with syntax

@smallexample
read @var{variable}
@end smallexample
@noindent
This reads in a string from the keyboard and terminates on a newline
character. Another way to do this is to use the @samp{input}
command to access a particular logical device. The keyboard device
in the current terminal is @file{/dev/tty}, so that one writes
@smallexample
@var{variable} = `line < /dev/tty`
@end smallexample
@noindent
which fetches a single line from the user.

@cindex Input in sh
Here are some examples of these commands.
First a program which asks yes or no...
@smallexample
#!/bin/sh
#
# Yes or no
#

echo "Please answer yes or no: "

answer=`line < /dev/tty` 

case $answer in

  y* | Y* | j* | J* )  echo YES!! ;;

  n* | N* )            echo NO!! ;;

  *)                   echo "Can't you answer a simple question?"

esac

echo The end
@end smallexample

@noindent
Notice the use of pattern matching and the @samp{|} `OR' symbol.
@smallexample
#!/bin/sh
#
# Kernel check
#

if test ! -f /vmunix          # Check that the kernel is there!
then
   echo "This is not BSD unix...hmmm"
   if [ -f /hp-ux ]
   then
      echo "It's a Hewlett Packard machine!"
   fi
elif [ -w /vmunix ]
then
   echo "HEY!! The kernel is writable my me!";
else
   echo "The kernel is write protected."
   echo "The system is safe from me today."
fi
@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Loops in sh, Procedures and traps, Input in sh, Bourne shell
@section Loops in sh

@cindex Loops in sh
@cindex @samp{while} in sh

The loop structures in the Bourne shell have the following syntax.
@smallexample
while @var{unix-command}
do
  commands
done
@end smallexample

@noindent
The first command will most likely be a test but, as before, it
could in principle be any UNIX command. The @samp{until} loop,
reminiscent of BCPL, carries out a task until its argument evaluates
to TRUE.
@smallexample
until @var{unix-command}
do
    commands
done
@end smallexample

@cindex @samp{until}
@noindent
Finally the @samp{for} structure has already been used above.
@smallexample
for @var{variable} in @var{list}
do
   @var{commands}
done
@end smallexample

Often we want to be able to use an array of values as the list which
@code{for} parses, but Bourne shell has no array variables. This
problem is usually solved by making a long string separated by, for
example, colons. For example, the @code{$PATH} variable has the
form
@smallexample
PATH = /usr/bin:/bin:/local/gnu/bin
@end smallexample

@cindex @samp{IFS} variable in sh
@cindex Redefining list separator in sh
@cindex Loops and list separators
@noindent
Bourne shell allows us to split such a string on whatever character
we wish. Normally the split is made on spaces, but the variable
@samp{IFS} can be defined with a replacement. To make a loop over
all directories in the command path we would therefore write
@smallexample
IFS=:

for name in $PATH; do

   @var{commands}

done

@end smallexample

@noindent
The best way to gain experience with these commands is through some
examples.
@smallexample
#!/bin/sh
#
# Get text from user repeatedly
#

echo "Type away..."

while read TEXT
do

   echo You typed $TEXT

   if [ "$TEXT" = "quit" ]; then
      echo "(So I quit!)"
      exit 0
   fi

done

echo "HELP!"

@end smallexample

@noindent
@cindex @key{CTRL-D} and EOF
@cindex End of file @key{CTRL-D}
This very simple script is a typical use for a while-loop. It
gets text repeatedly until the user type `quit'. Since read
never returns `false' unless an error occurs or it detects
an EOF (end of file) character @key{CTRL-D}, it will never
exit without some help from an `if' test. If it does receive
a @key{CTRL-D} signal, the script prints `HELP!'.


@smallexample
#!/bin/sh
#
# Watch in the background for a particular user
# and give alarm if he/she logs in
#
# To be run in the background, using &
#

if [ $# -ne 1 ]; then
  echo "Give the name of the user as an argument" > /dev/tty
  exit 1
fi

echo "Looking for $1"

until users | grep -s $1
do
   sleep 60
done

echo "!!! WAKE UP !!!" > /dev/tty
echo "User $1 just logged in" > /dev/tty

@end smallexample

This script uses @samp{grep} in `silent mode' (-s option). i.e. grep never
writes anything to the terminal. The only thing we are interested
in is the return code the piped command produces. If `grep'
detects a line containing the username we are interested in,
then the result evaluates to TRUE and the sleep-loop exits.

Our final example is the kind of script which is useful for
a system administrator. It transfers over the Network Information
Service database files so that a slave server is up to date.
All we have to do is make a list of the files and place it in a
@samp{for} loop. The names used below are the actual names
of the NIS maps, well known to system administrators.
@smallexample
#!/bin/sh
#
# Update the NIS database maps on a client server. This program
# shouldn't have to be run, but sometimes things go wrong and we
# have to force a download from the main sever.
#
PATH=/etc/yp:/usr/etc/yp:$PATH

MASTER=myNISserver

for map in auto.direct auto.master ethers.byaddr ethers.byname\
           group.bygid group.byname hosts.byaddr hosts.byname\
           mail.aliases netgroup.byhost netgroup.byuser netgroup\
           netid.byname networks.byaddr networks.byname passwd.byname\
           passwd.byuid priss.byname protocols.byname protocols.bynumber\
           rpc.bynumber services.byname services usenetgroups.byname;
do
  ypxfr $1 -h $MASTER $map
done

@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Procedures and traps, setuid setgid scripts, Loops in sh, Bourne shell
@section Procedures and traps

@cindex Procedures and subroutines in sh
@cindex Signal handler in sh
@cindex Interrupt handler in sh
@cindex Traps in sh

One of the worthy features of the Bourne shell is that it allows
you to define @emph{subroutines} or @emph{procedures}. Subroutines
work just like subroutines in any other programming language. They are
executed in same shell (not as a sub-process).

Here is an interesting program which demonstrates two useful
things at the same time. First of all, it shows how to make
a hierachical subroutine structure using the Bourne shell.
Secondly, it shows how the @samp{trap} directive can be used
to trap signals, so that Bourne shell programs can exit safely
when they are killed or when CTRL-C is typed.


@smallexample
#!/bin/sh
#
#  How to make a signal handler in Bourne Shell
#  using subroutines
#

#####################################################
# Level 2
#####################################################

ReallyQuit()
@{
while true
do
  echo "Do you really want to quit?"
  read answer

  case $answer in

     y* | Y* ) return 0;;
     *)        echo "Resuming..."
               return 1;;

  esac

done
@}

#####################################################
# Level 1
#####################################################

SignalHandler()

@{
if ReallyQuit           # Call a function
then
   exit 0
else
   return 0
fi
@}

#####################################################
# Level 0 : main program
#####################################################

trap SignalHandler 2 15  # Trap kill signals 2 and 15

echo "Type some lines of text..."

while read text
do

   echo "$text - CTRL-C to exit"

done

@end smallexample

Note that the logical tree structure of this program is upside down
(the highest level comes at the bottom). This is because all subroutines
must be defined before they are used.

This example concludes our brief survey of the Bourne shell.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node setuid setgid scripts, Limitations of shell, Procedures and traps, Bourne shell
@section setuid and setgid scripts

@cindex SetUID scripts
@cindex Root privileges

The superuser @samp{root} is the only privileged user in UNIX. All other
users have only restricted access to the system. Usually this is desirable,
but sometimes it is a nuisance.

A setuid script is a script which has its @emph{setuid-bit} set.  When
such a script is executed by a user, it is run with all the rights and
privileges of the owner of the script. All of the commands in the script
are executed as the owner of the file and not with the user-id of the person who ran
the script. If the owner of the setuid script is @samp{root} then the
commands in the script are run with @emph{root privileges}!

Setuid scripts are clearly a touchy security issue. When giving
away one's rights to another user (especially those of @samp{root})
one is tempting hackers. Setuid scripts should be @emph{avoided}.

A setgid program is almost the same, but only the group id is set to
that of the owner of the file. Often the effect is the same.

An example of a setuid program is the @samp{ps} program. @samp{ps}
lists all of the processes running in the kernel. In order to
do this it needs permission to access the private data structures
in the kernel. By making @samp{ps} setgid root, it allows ordinary
users to be able to read as much as the writers of @samp{ps}
thought fit, but no more.

Naturally, only the superuser can make a file setuid or setgid root.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Limitations of shell, Ex4, setuid setgid scripts, Bourne shell
@section Summary: Limitations of shell programming

@cindex Limitations of shell programs

To summarize the last two long and oppressive chapters we shall take a
step back from the details and look at what we have achieved.

The idea behind the shell is to provide a user
interface, with access to the system's facilities at a simple level.
In the 70's user interfaces were not deisgned to be user-friendly.
The UNIX shell is not particularly use friendly, but it is very powerful.
Perhaps it would have been enough to provide only commands to allow users
to write C programs. Since all of the system functions are
available from C, that would certainly allow everyone to do what
anything that UNIX can do. But shell programming is much more
@emph{immediate} than C. It is an environment of @emph{frequently used tools}.
Also for quick programming solutions: C is a compiled language, whereas the
shell is an interpreter. A quick shell program can solve many
problems in no time at all, without having to compile anything.

Shell programming is only useful for `quick and easy' programs. To use
it for anything serious is an abuse.  Programming difficult things in
shell is clumsy, and it is difficult to get returned-information (like
error messages) back in a useful form. Besides, shell scripts are
slow compared to real programs since they involve starting
a new program for each new command.

These difficulties are solved partly by Perl, which we shall consider
next -- but in the final analysis, real programs of substance
need to be written in C. Contrary to popular belief, this is
not more difficult than programming in the shell -- in fact, many
things are much simpler, because all of the shell commands originated
as C functions. The shell is an extra layer of the UNIX onion which
we have to battle our way through to get where we're going.

Sometimes it is helpful to be shielded from @emph{low level} details
-- sometimes it is a @emph{hindrance}. In the remaining chapters
we shall consider more involved programming needs.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Ex4,  , Limitations of shell, Bourne shell
@section Exercises

@enumerate
@item 
Write an improved @samp{which} command in C-shell.

@item 
Make a counter program which records in a file how many times
you log in to your account. You can call this in your .cshrc file.

@item 
Make a Bourne shell script to kill all the processes owned by a particular
user. (Note, that if you are not the superuser, you cannot kill processes
owned by other users.)

@item 
Write a script to replace the @samp{rm} command with something
safer. Think about a way of implementing @samp{rm} so that it is
possible to get deleted files back again in case of emergencies. This is
not possible using the normal @samp{rm} command. Hint: save files
in a hidden directory @samp{.deleted}. Make your script delete
files in the @samp{.deleted} directory if they are older than
a week, so that you don't fill up the disk with rubbish.

@item 
Suppose you have a bunch of files with a particular file-extension:
write a script in csh to change the extension to something else. e.g.
to change *.C into *.c. Give the old and new extensions as arguments to
the script.

@item 
Write a program in sh to search for files in the current directory
which contain a certain string. e.g. search for all files which contain
the word "if". Hint: use the "find" command.

@item 
Use the manual pages to find out about the commands @samp{at},
@samp{batch} and @samp{atq}. Test these commands by executing the
shell command @samp{date} at some time of your choice. Use the @samp{-m}
option so that the result of the job is mailed to you.
@cindex @samp{batch} command
@cindex @samp{at} command

@item 
Write a script in sh or csh to list all of the files bigger
than a certain size starting from the current directory, and including
all subdirectories. This kind of program is useful for system administrators
when a disk becomes full.
@end enumerate


@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node Perl, WWW and CGI programming, Bourne shell, Top
@chapter Perl

@cindex Perl
So far, we have been looking at shell programming for performing
fairly simple tasks. Now let's extend the idea of shell programming
to cover more complex tasks like systems programming and network
communications. Perl is a language which was designed to retain the
immediateness of shell languages, but at the same time capture some
of the flexibility of C. Perl is an acronym for @emph{Practical extraction
and report language}. In this chapter, we shall not aim to teach Perl
from scratch -- the best way to learn it is to use it! Rather
we shall concentrate on demonstrating some principles.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@menu
* sed awk cut paste::           
* Perl structure::              
* Perl variables::              
* Loops and conditionals::      
* Files in perl::               
* Perl subroutines::            
* die::                         
* stat()::                      
* Perl examples::               
* Pattern matching::            
* search and replace::          
* WWW example::                 
* WWW example 2::               
* Other functions::             
* Perl summary::                
* Ex5::                         
* Proj5::                       
@end menu

@node sed awk cut paste, Perl structure, Perl, Perl
@section Sed and awk, cut and paste

@cindex @samp{sed} batch editor
@cindex @samp{awk} pattern extractor
@cindex @samp{cut}
@cindex @samp{paste}

One of the reasons for using Perl is that it is extremely good at
textfile handling--one of the most important things for UNIX users, and
particularly useful in connection with CGI script processing on the
World Wide Web.  It has simple built-in constructs for searching and
replacing text, storing information in arrays and retrieving them in
sorted form. All of the these things have previously been possible using
the UNIX shell commands
@smallexample
sed
awk
cut
paste
@end smallexample

@noindent
but these commands were designed to work primarily in the Bourne shell
and are a bit @samp{awk}ward to use for all but the simplest applications.

@table @samp
@item sed
is a stream editor. It takes command line instructions, reads input from
the stream @code{stdin} and produces output on @emph{stdout} according
to those instructions. @samp{sed} works line by line from the start of a
textfile.

@item awk
is a pattern matching and processing language. It takes a textfile and
reads it line by line, matching @emph{regular expressions} and acting on
them. @samp{awk} is powerful enough to have conditional instructions
like @samp{if..then..else} and uses C's @samp{printf} construction for
output.

@item cut
Takes a line of input and cuts it into @emph{fields},
separated by some character. For instance, a normal line of text is
a string of words separated by spaces. Each word is a different field. 
@samp{cut} can be used, for instance, to pick out the third column in a
table. Any character can be specified as the separator.

@item paste
is the logical opposite of cut. It concatenates @math{n}
files, and makes each line in the file into a column of a table. For instance,
@samp{paste one two three} would make a table in which the first
column consisted of all lines in @samp{one}, the second of all lines
in @samp{two} and the third of all lines in @samp{three}. If one file
is longer than the others, then some columns have blank spaces.
@end table

Perl unifies all of these operations and more. It also
makes them much simpler.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Perl structure, Perl variables, sed awk cut paste, Perl
@section Program structure

To summarize Perl, we need to know about the structure of a Perl
program, the conditional constructs it has, its loops and its variables.
In the latest versions of Perl (Perl 5), you can write object oriented
programs of great complexity. We shall not go into this depth, for the
simple reason that Perl's strength is not as a general programming
language but as a specialized language for textfile handling.  The
syntax of Perl is in many ways like the C programming language, but
there are important differences.

@itemize @bullet

@item 
Variables do not have @emph{types}. They are interpreted
in a context sensitive way. The operators which acts upon variables
determine whether a variable is to be considered a string or as an integer etc.
@cindex Perl variables and types
@cindex Types in perl

@item
Although there are no types, Perl defines @emph{arrays} of
different kinds. There are three different kinds of array, labelled by the
symbols @samp{$}, @samp{@@}  and @samp{%}.
@cindex Arrays in perl

@item 
Perl keeps a number of standard variables with special names
e.g. @samp{$_ @@ARGV} and @samp{%ENV}. Special attention should be paid
to these. They are very important!
@cindex Argument vector in perl
@cindex Command line arguments in perl
@cindex Environment variables in perl

@item 
The shell reverse
apostrophe notation @code{`command`} can be used to execute UNIX
programs and get the result into a Perl variable.
@cindex @samp{`..`} in perl

@end itemize

Here is a simple `structured hello world' program in Perl. Notice
that subroutines are called using the @samp{&} symbol. There is
no special way of marking the main program -- it is simply
that part of the program which starts at line 1.


@smallexample
#!/local/bin/perl
#
# Comments
#

&Hello();
&World;

# end of main

sub Hello
   @{
   print "Hello";
   @}


sub World
   @{
   print "World\n";
   @}


@end smallexample

@noindent
The parentheses on subroutines are optional, if there are no parameters passed.
Notice that each line must end in a semi-colon.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Perl variables, Loops and conditionals, Perl structure, Perl
@section Perl variables

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Scalar variables::            
* The default scalar variable::  
* Array variables::             
* Array commands::              
* Associated arrays::           
* Array example::               
@end menu

@node Scalar variables, The default scalar variable, Perl variables, Perl variables
@subsection  Scalar variables

@cindex Scalar variables in perl
@cindex Strings in perl
@cindex Perl, strings and scalar

In Perl, variables do not have to be declared before they are used.
Whenever you use a new symbol, Perl automatically adds the symbol to
its symbol table and initializes the variable to the empty
string.

It is important to understand that there is no 
practical difference between zero and the empty string in perl -- except in the way that you, the user, choose to
use it. Perl makes no distinction between strings and integers or any other
types of data -- except when it wants to interpret them. For instance,
to compare two variables as strings is not the same as comparing them
as integers, even if the string contains a textual representation of an
integer. Take a look at the following program.

@smallexample
#!/local/bin/perl
#
# Nothing!
#

print "Nothing == $nothing\n";

print "Nothing is zero!\n" if ($nothing == 0);

if ($nothing eq "")
   @{
   print STDERR "Nothing is really nothing!\n";
   @}

$nothing = 0;

print "Nothing is now $nothing\n";
@end smallexample

@noindent
The output from this program is

@smallexample

Nothing == 
Nothing is zero!
Nothing is really nothing!
Nothing is now 0

@end smallexample

@cindex Interpretation of values in perl

There are several important things to note here. First of all, we never
declare the variable `nothing'.  When we try to write its value, perl
creates the name and associates a NULL value to it i.e. the empty
string. There is no error. Perl knows it is a variable because of the
@samp{$} symbol in front of it. All @emph{scalar} variables are
identified by using the dollar symbol.

@cindex @samp{eq} and @samp{==} in perl
@vindex @samp{eq}
@vindex @samp{==}

Next, we compare the value of @samp{$nothing} to the integer `0' using
the integer comparison symbol @samp{==}, and then we compare it to the
empty string using the string comparison symbol @samp{eq}.  Both tests
are true! That means that the empty string is interpreted as having a
numerical value of zero. In fact @emph{any string} which does not form a
valid integer number has a numerical value of zero.

Finally we can set @samp{$nothing} explicitly to a valid integer
string zero, which would now pass the first test, but fail the
second.

As extra spice, this program also demonstrates two different ways
of writing the @samp{if} command in perl.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node The default scalar variable, Array variables, Scalar variables, Perl variables
@subsection  The default scalar variable.

The special variable @samp{$_} is used for many purposes in Perl.
It is used as a buffer to contain the result of the last operation,
the last line read in from a file etc. It is so general that many
functions which act on scalar variables work by default on @samp{$_}
if no other argument is specified. For example,
@smallexample
print;
@end smallexample

@noindent
is the same as
@smallexample
print $_;
@end smallexample

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Array variables, Array commands, The default scalar variable, Perl variables
@subsection  Array (vector) variables

@cindex Arrays (normal) in perl
The complement of scalar variables is arrays. An array, in Perl is
identified by the @samp{@@} symbol and, like scalar variables, is
allocated and initialized dynamically.
@smallexample

@@array[0] = "This little piggy went to market";
@@array[2] = "This little piggy stayed at home";

print "@@array[0] @@array[1] @@array[2]";

@end smallexample

@noindent
The index of an array is always understood to be a number, not
a string, so if you use a non-numerical string to refer to an array
element, you will always get the zeroth element, since a non-numerical
string has an integer value of zero.

An important array which every program defines is
@smallexample
@@ARGV
@end smallexample

@noindent
This is the argument vector array, and contains the commands line arguments
by analogy with the C-shell variable @samp{$argv[]}.

Given an array, we can find the last element by using the @samp{$#}
operator. For example,
@smallexample
$last_element = $ARGV[$#ARGV];
@end smallexample

@noindent
Notice that each element in an array is a scalar variable. The @samp{$#}
cannot be interpreted directly as the number of elements in the array,
as it can in the C-shell. You should experiment with the value of this
quantity -- it often necessary to add 1 or 2 to its value in order to
get the behaviour one is used to in the C-shell.

Perl does not support multiple-dimension arrays directly, but it is
possible to simulate them yourself. (See the Perl book.)

@cindex Argument vector in perl
@cindex Command line arguments in perl

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Array commands, Associated arrays, Array variables, Perl variables
@subsection  Special array commands

The @samp{shift} command acts on arrays and returns and removes the
first element of the array. Afterwards, all of the elements are shifted
down one place. So one way to read the elements of an array in order is
to repeatedly call @samp{shift}.

@smallexample
$next_element=shift(@@myarray);
@end smallexample

@cindex @samp{shift} and arrays in perl
@cindex @samp{shift} and arrays
@noindent
Note that, if the array argument is omitted, then @samp{shift}
works on @samp{@@ARGV} by default.

@cindex @samp{split} command
@cindex @samp{split} and arrays
@cindex Arrays and @samp{split}
Another useful function is @samp{split}, which takes a string and turns
it into an array of strings. @samp{split} works by choosing a character
(usually a space) to delimit the array elements, so a string containing
a sentence separated by spaces would be turned into an array of
words. The syntax is

@smallexample
@@array = split;                       # works with spaces on $_
@@array = split(pattern,string);       # Breaks on pattern
($v1,$v2...) = split(pattern,string); # Name array elements with scalars
@end smallexample

@noindent
In the first of these cases, it is assumed that the variable @samp{$_}
is to be split on whitespace characters. In the second case, we decide
on what characterthe split is to take place and on what string the
function is to act. For instance

@smallexample
@@new_array = split(":","name:passwd:uid:gid:gcos:home:shell");
@end smallexample

@noindent
The result is a seven element array called @samp{@@new_array}, where
@samp{$new_array[0]} is @samp{name} etc.

@noindent
In the final example, the left hand side shows that we wish to capture
elements of the array in a named set of scalar variables.  If the
number of variables on the lefthand side is fewer than the number of
strings which are generated on the right hand side, they are
discarded. If the number on the left hand side is greater, then the
remainder variables are empty.



@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Associated arrays, Array example, Array commands, Perl variables
@subsection  Associated arrays

@cindex Arrays (associated) in perl
One of the very nice features of Perl is the ability to use one string
as an index to another string in an array. For example, we can make a
short encyclopaedia of zoo animals by constructing an associative array
in which the keys (or indices) of the array are the names of animals, and
the contents of the array are the information about them.

@smallexample

$animals@{"Penguin"@} = "A suspicious animal, good with cheese crackers...";
$animals@{"dog"@} = "Plays stupid, but could be a cover...";

if ($index eq "fish")
   @{ 
   $animals@{$index@} = "Often comes in square boxes. Very cold.";
   @}

@end smallexample

@noindent
An entire associated array is written @samp{%array}, while the elements
are @samp{$array@{$key@}}.

Perl provides a special associative array for every program called @samp{%ENV}.
This contains the @emph{environment variables} defined in the parent
shell which is running the Perl program. For example
@smallexample
print "Username = $ENV@{"USER"@}\n";

$ld = "LD_LIBRARY_PATH";
print "The link editor path is $ENV@{$ld@}\n";

@end smallexample

@cindex Environment variables in perl
@noindent
To get the current path into an ordinary array, one could write,
@smallexample
@@path_array= split(":",$ENV@{"PATH"@});
@end smallexample

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Array example,  , Associated arrays, Perl variables
@subsection  Array example program

Here is an example which prints out a list of files in a specified
directory, in order of their UNIX protection bits. The @emph{least}
protected file files come first.

@smallexample
#!/local/bin/perl
#
# Demonstration of arrays and associated arrays.
# Print out a list of files, sorted by protection,
# so that the least secure files come first.
#
# e.g.     arrays <list of words>
#          arrays *.C
#
############################################################


print "You typed in ",$#ARGV+1," arguments to command\n";

if ($#ARGV < 1)  
   @{
   print "That's not enough to do anything with!\n";
   @}

while ($next_arg = shift(@@ARGV))   
   @{
   if ( ! ( -f $next_arg || -d $next_arg))
      @{
      print "No such file: $next_arg\n";
      next;
      @}

   ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size) = stat($next_arg);
   $octalmode = sprintf("%o",$mode & 0777);

   $assoc_array@{$octalmode@} .= $next_arg.
            " : size (".$size."), mode (".$octalmode.")\n";
   @}

print "In order: LEAST secure first!\n\n";

foreach $i (reverse sort keys(%assoc_array))
   @{
   print $assoc_array@{$i@};
   @}

@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Loops and conditionals, Files in perl, Perl variables, Perl
@section Loops and conditionals

@cindex For loops in perl
@cindex @code{for} loop in perl
@cindex @code{foreach} loop in perl
Here are some of the most commonly used decision-making
constructions and loops in Perl. The following is not a
comprehensive list -- for that, you will have to look
in the Perl bible: @emph{Programming Perl}, by Larry Wall
and Randal Schwartz. The basic pattern follows the C
programming language quite closely. In the
case of the @samp{for} loop, Perl has both the C-like
version, called @samp{for} and a @samp{foreach} command
which is like the C-shell implementation.

@cindex @samp{if} in perl
@cindex @samp{unless} in perl
@cindex @samp{while} in perl
@cindex @samp{do..while} in perl
@smallexample
if (@var{expression})
   @{
   block;
   @}
else
   @{
   block;
   @}

command if (@var{expression});

unless (@var{expression})
   @{
   block;
   @}
else
   @{
   block;
   @}

while (@var{expression})
   @{
   block;
   @}

do
   @{
   block;
   @}
while (@var{expression});

for (@var{initializer}; @var{expression}; @var{statement})
   @{
   block;
   @}

foreach @var{variable}(@var{array})
   @{
   block;
   @}

@end smallexample

@noindent
In all cases, the @samp{else} clauses may be omitted.

Strangely, perl does not have a @samp{switch} statement, but the Perl book
describes how to make one using the features provided.

 
@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* The for loop::                
* The foreach loop::            
* Iterating over elements in arrays::  
* Iterating over lines in a file::  
@end menu

@node The for loop, The foreach loop, Loops and conditionals, Loops and conditionals
@subsection The for loop

The for loop is exactly like that in C or C++ and is used
to iterate over a numerical index, like this:

@smallexample

for ($i = 0; $i < 10; $i++)
   @{
   print $i, "\n";
   @}

@end smallexample
@cindex For loop

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node The foreach loop, Iterating over elements in arrays, The for loop, Loops and conditionals
@subsection The foreach loop

The foreach loop is like its counterpart in the C shell. It
is used for reading elements one by one from a regular array.
For example,

@smallexample

foreach $i ( @@array )
   @{
   print $i, "\n";
   @}

@end smallexample
@cindex Foreach loop

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Iterating over elements in arrays, Iterating over lines in a file, The foreach loop, Loops and conditionals
@subsection Iterating over elements in arrays

One of the main uses for @samp{for} type loops is to iterate
over successive values in an array. This can be done in
two ways which show the essential difference between
@code{for} and @code{foreach}. 

If we want to fetch each value in an array in turn, without caring about
numerical indices, the it is simpest to use the @code{foreach} loop.
@cindex Iteration over arrays

@smallexample

 @@array = split(" ","a b c d e f g");

 foreach $var ( @@array )
    @{
    print $var, "\n";
    @}

@end smallexample

@noindent
This example prints each letter on a separate line.
If, on the other hand, we are interested in the index,
for the purposes of some calculation, then the @code{for}
loop is preferable.

@smallexample

 @@array = split(" ","a b c d e f g");

 for ($i = 0; $i <= $#array; $i++)
    @{
    print $array[$i], "\n";
    @}

@end smallexample

@noindent
Notice that, unlike the for-loop idiom in C/C++, the limit
is @samp{$i <= $#array}, i.e. `less than or equal to' rather
than `less than'. This is because the @samp{$#} operator
does not return the number of elements in the array but
rather the last element.

Associated arrays are slightly different, since they do not
use numerical keys. Instead they use a set of strings,
like in a database, so that you can use one string to look
up another. In order to iterate over the values in the array
we need to get a list of these strings. The @code{keys}
command is used for this.
@vindex keys
@cindex Associated arrays, iteration

@smallexample
 $assoc@{"mark"@} = "cool";
 $assoc@{"GNU"@} = "brave";
 $assoc@{"zebra"@} = "stripy";

 foreach $var ( keys %assoc )
    @{
    print "$var , $assoc@{$var@} \n";
    @}
@end smallexample

@noindent
The order of the keys is not defined in the above example,
but you can choose to sort them alphabetically by writing

@smallexample
 foreach $var ( sort keys %assoc )
@end smallexample

@noindent
instead.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Iterating over lines in a file,  , Iterating over elements in arrays, Loops and conditionals
@subsection Iterating over lines in a file

Since Perl is about file handling we are very interested in
reading files. Unlike C and C++, perl likes to read files
line by line. The angle brackets are used for this, @xref{Files in perl}.
Assuming that we have some file handle @samp{<file>}, for instance
@samp{<STDIN>}, we can always read the file line by line
with a while-loop like this.

@smallexample

 while ($line = <file>)
    @{
    print $line;
    @}

@end smallexample

@noindent
Note that @code{$line} includes the end of line character on the end
of each line. If you want to remove it, you should add a `chop'
command:

@smallexample

 while ($line = <file>)
    @{
    chop $line;
    print "line = ($line)\n";
    @}

@end smallexample
@cindex Iterating over files
@cindex Files, iterating over lines

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Files in perl, Perl subroutines, Loops and conditionals, Perl
@section Files in perl

@cindex Files in perl
@cindex Standard I/O in perl
@cindex @samp{open} command in perl
@cindex @samp{close} command in perl
Opening files is straightforward in Perl. Files must be opened
and closed using -- wait for it -- the commands
@samp{open} and @samp{close}. You should be careful to
close files after you have finished with them -- especially
if you are writing @emph{to} a file. Files are buffered
and often large parts of a file are not actually written
until the @samp{close} command is received.

Three files are, of course, always open for every program,
namely @samp{STDIN}, @samp{STDOUT}and @samp{STDERR}.

Formally, to open a file, we must obtain a file descriptor
or file handle. This is done using @samp{open};

@cindex @samp{<>} filehandle in perl
@cindex File handles in perl
@smallexample
open (file_descrip,"Filename");
@end smallexample
@noindent
The angular brackets @samp{<..>} are used to read from the file.
For example,

@smallexample
$line = <file_descrip>;
@end smallexample

@noindent
reads one line from the file associated with @samp{file_descrip}.

Let's look at some examples of filing opening.
Here is how we can implement UNIX's @samp{cut} and @samp{paste}
commands in perl:

@cindex Cut as a perl script
@smallexample
#!/local/bin/perl
#
# Cut in perl
#


 # Cut second column

while (<>)
   @{
   @@cut_array = split;

   print "@@cut_array[1]\n";
   @}

@end smallexample

@noindent
This is the simplest way to open a file. The empty file
descriptor @samp{<>} tells perl to take the argument of the
command as a filename and open that file for reading.
This is really short for @samp{while($_=<STDIN>)} with the
standard input redirected to the named file.

@cindex Paste as a perl script
The @samp{paste}program can be written as follows:

@smallexample
#!/local/bin/perl
#
# Paste in perl
#
# Two files only, syntax : paste file 1file2
#

open (file1,"@@ARGV[0]") || die "Can't open @@ARGV[0]\n";
open (file2,"@@ARGV[1]") || die "Can't open @@ARGV[1]\n";

while (($line1 = <file1>) || ($line2 = <file2>))
   @{
   chop $line1;
   chop $line2;

   print "$line1	$line2\n";    # tab character between
   @}

@end smallexample


Here we see more formally how to read from two separate
files at the same time. Notice that, by putting the
read commands into the test-expression for the @samp{while}
loop, we are using the fact that @samp{<..>} returns
a non-zero (true) value unless we have reached the
end of the file.

To write and append to files, we use the shell redirection symbols
inside the @samp{open} command.
@smallexample
open(fd,"> filename");    # open file for writing
open(fd,">> filename");   # open file for appending
@end smallexample

@noindent
We can also open a pipe from an arbitrary UNIX command
and receive the output of that command as our input:
@smallexample
open (fd,"/bin/ps aux | ");
@end smallexample

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Simplest perl program::       
* == and eq::                   
* chop::                        
@end menu

@node Simplest perl program, == and eq, Files in perl, Files in perl
@subsection A simple perl program

Let us now write the simplest perl program which illustrates
the way in which perl can save time. We shall write it in three
different ways to show what the short cuts mean. Let us implement
the @samp{cat} command, which copies files to the standard output.
The simplest way to write this is perl is the following:

@smallexample

#!/local/bin/perl

while (<>)
   @{
    print;
   @}

@end smallexample

@noindent
Here we have made heavy use of the many default assumptions which perl
makes. The program is simple, but difficult to understand for
novices. First of all we use the default file handle @code{<>} which
means, take one line of input from a default file.  This object returns
true as long as it has not reached the end of the file, so this loop
continues to read lines until it reaches the end of file.  The default
file is standard input, unless this script is invoked with a command
line argument, in which case the argument is treated as a filename and
perl attempts to open the argument-filename for reading. The
@code{print} statement has no argument telling it what to print, but
perl takes this to mean: print the default variable @samp{$_}.

We can therefore write this more explicitly as follows:

@smallexample

#!/local/bin/perl

open (HANDLE,"$ARGV[1]");

while (<HANDLE>)
   @{
    print $_;
   @}
@end smallexample

@noindent
Here we have simply filled in the assumptions explicitly.
The command @samp{<HANDLE>} now reads a single line from the
named file-handle into the default variable @samp{$_}.
To make this program more general, we can elimiate the defaults
entirely.

@smallexample

#!/local/bin/perl

open (HANDLE,"$ARGV[1]");

while ($line=<HANDLE>)
   @{
    print $line;
   @}
@end smallexample

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node == and eq, chop, Simplest perl program, Files in perl
@subsection  == and @samp{eq}

Be careful to distinguish between the comparison operator for integers
@samp{==} and the corresponding operator for strings @samp{eq}. These
do not work in each other's places so if you get the wrong comparison
operator your program might not work and it is quite difficult to
find the error.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node chop,  , == and eq, Files in perl
@subsection  chop

@cindex Truncating strings in perl
@cindex Perl, truncating strings
@cindex @samp{chop} command in perl

The command @samp{chop} cuts off the last character of a string.
This is useful for removing newline characters when reading
files etc. The syntax is
@smallexample
chop;         # chop $_;

chop $scalar; # remove last character in $scalar
@end smallexample




@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Perl subroutines, die, Files in perl, Perl
@section Perl subroutines

@cindex Subroutines in perl

Subroutines are indicated, as in the example above, by the ampersand
@samp{&} symbol. When parameters are passed to a Perl subroutine, they
are handed over as an array called @samp{@@_}. Which is analogous
to the @samp{$_} variable. Here is a simple example:

@smallexample
#!/local/bin/perl

$a="silver";
$b="gold";

&PrintArgs($a,$b);

# end of main

sub PrintArgs

   @{
   ($local_a,$local_b) = @@_;

   print "$local_a, $local_b\n";
   @}

@end smallexample
@cindex Local variables in perl
@cindex Parameters in perl functions



@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node die, stat(), Perl subroutines, Perl
@section die - exit on error

@cindex Exiting on errors in perl
@cindex @samp{die}
@cindex Errors in perl
When a program has to quit and give a message, the @samp{die}
command is normally used. If called without an argument,
Perl generates its own message including a line number at which
the error occurred. To include your own message,
you write

@smallexample
die "My message....";
@end smallexample

@noindent
If the string is terminated with a @samp{\n} newline character,
the line number of the error is not printed, otherwise Perl
appends the line number to your string.

When opening files, it is common to see the syntax:
@smallexample
open (filehandle,"Filename") || die "Can't open...";
@end smallexample

@noindent
The logical @samp{OR} symbol is used, because @samp{open}
returns true if all goes well, in which case the right
hand side is never evaluated. If @samp{open} is false,
then die is executed. You can decide for yourself whether
or not you think this is good programming style -- we mention
it here because it is common practice.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node stat(), Perl examples, die, Perl
@section The @code{stat()} idiom

The unix library function @code{stat()} is used to find out information
about a given file. This function is available both in C and in Perl.
In perl, it returns an array of values. Usually we are interested in
knowing the access permissions of a file. @code{stat()} is called
using the syntax

@smallexample

@@array = stat ("@var{filename}");

@end smallexample

@noindent
or alternatively, using a named array

@smallexample

($device,$inode,$mode) = stat("@var{filename}");

@end smallexample

The value returned in the @var{mode} variable is a bit-pattern,
@xref{Protection bits}. The most useful way of treating these
bit patterns is to use octal numbers to interpret their meaning.

To find out whether a file is readable or writable to a group of
users, we use a programming idiom which is very common for dealing
with bit patterns: first we define a mask which zeroes out all
of the bits in the mode string except those which we are
specifically interested in. This is done by defining a mask
value in which the bits we want are set to 1 and all others are
set to zero. Then we AND the mask with the mode string. If the
result is different from zero then we know that all of the
bits were also set in the mode string.
As in C, the bitwise AND operator in perl is called @samp{&}.

For example, to test whether a file is writable to other users
in the same group as the file, we would write the following.

@smallexample

$mask = 020;   # Leading 0 means octal number

($device,$inode,$mode) = stat("@var{file}");

if ($mode & $mask)
   @{
   print "File is writable by the group\n";
   @}

@end smallexample

@noindent
Here the 2 in the second octal number means "write", the fact that
it is the second octal number from the right means that it refers
to "group". Thus the result of the if-test is only true if that
particular bit is true. We shall see this idiom in action below.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Perl examples, Pattern matching, stat(), Perl
@section Perl example programs

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Passwd example program::      
* Fork example::                
* Database example::            
@end menu

@node Passwd example program, Fork example, Perl examples, Perl examples
@subsection  The passwd program and @samp{crypt()} function

Here is a simple implementation of the UNIX @samp{passwd}
program in Perl.
@cindex @file{passwd} file
@cindex Encryption
@cindex @samp{stty} and switching off term echo
@cindex Terminal echo and @samp{stty}
@vindex @code{crypt()}

@smallexample
#!/local/bin/perl
#
# A perl version of the passwd program.
#
# Note - the real passwd program needs to be much more
# secure than this one. This is just to demonstrate the
# use of the crypt() function.
#
#############################################################

print "Changing passwd for $ENV@{'USER'@} on $ENV@{'HOST'@}\n";


system 'stty','-echo';
print "Old passwd: ";

$oldpwd = <STDIN>;
chop $oldpwd;

($name,$coded_pwd,$uid,$gid,$x,$y,$z,$gcos,$home,$shell) 
                                 = getpwnam($ENV@{"USER"@});

if (crypt($oldpwd,$coded_pwd) ne $coded_pwd)
   @{
   print "\nPasswd incorrect\n";
   exit (1);
   @}

$oldpwd = "";                         # Destroy the evidence!

print "\nNew passwd: ";

$newpwd = <STDIN>;

print "\nRepeat new passwd: ";

$rnewpwd = <STDIN>;

chop $newpwd;
chop $rnewpwd;

if ($newpwd ne $rnewpwd)
   @{
   print "\n Incorrectly typed. Password unchanged.\n";
   exit (1);
   @}

@vindex @code{rand()}
$salt = rand();
$new_coded_pwd = crypt($newpwd,$salt);

print "\n\n$name:$new_coded_pwd:$uid:$gid:$gcos:$home:$shell\n";


@end smallexample

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Fork example, Database example, Passwd example program, Perl examples
@subsection  Example with @samp{fork()}

The following example uses the @samp{fork} function to
start a daemon which goes into the background and watches the
system to which process is using the greatest amount of
CPU time each minute. A pipe is opened from the BSD @samp{ps}
command.
@vindex @code{fork()}
@cindex Forking new processes

@smallexample
#!/local/bin/perl
#
# A fork() demo. This program will sit in the background and
# make a list of the process which uses the maximum CPU average
# at 1 minute intervals. On a quiet BSD like system this will
# normally be the swapper (long term scheduler).
#

$true = 1;
$logfile="perl.cpu.logfile";

print "Max CPU logfile, forking daemon...\n";

if (fork())
   @{
   exit(0);
   @} 

while ($true) 
   @{
   open (logfile,">> $logfile") || die "Can't open $logfile\n";
   open (ps,"/bin/ps aux |") || die "Couldn't open a pipe from ps !!\n";

   $skip_first_line = <ps>;
   $max_process = <ps>;
   close(ps);

   print logfile $max_process;
   close(logfile);
   sleep 60;

   ($a,$b,$c,$d,$e,$f,$g,$size) = stat($logfile);

   if ($size > 500)
      @{
      print STDERR "Log file getting big, better quit!\n";
      exit(0);
      @}
   @}


@end smallexample

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Database example,  , Fork example, Perl examples
@subsection  Example reading databases

@cindex Database support
@cindex User database support

Here is an example program with several of the above features
demonstrated simultaneously. This following program lists
all users who have home directories on the current host.
If the home area has sub-directories, corresponding to
groups, then this is specified on the command line. The
word `home' causes the program to print out the home
directories of the users.

@smallexample
#!/local/bin/perl
##################################################################
#
# allusers - list all users on named host, i.e. all
#            users who can log into this machine. 
#
# Syntax: allusers group
#         allusers mygroup home
#         allusers myhost group home
#
# NOTE : This command returns only users who are registered on
#        the current host. It will not find users which cannot
#        be validated in the passwd file, or in the named groups
#        in NIS. It assumes that the users belonging to
#        different groups are saved in subdirectories of
#        /home/hostname.
#
##################################################################

&arguments();

die "\n" if ( ! -d "/home/$server" );

$disks = `/bin/ls -d /home/$server/$group`;

foreach $home (split(/\s/,$disks))
   @{
   open (LS,"cd $home; /bin/ls $home |") || die "allusers: Pipe didn't open";

   while (<LS>)
      @{
      $exists = "";
      ($user) = split;
      ($exists,$pw,$uid,$gid,$qu,$cm,$gcos,$dir)=getpwnam($user);

      if ($exists)
         @{
         if ($printhomes)
            @{
            print "$dir\n";
            @}
         else
            @{
            print "$user\n";
            @}
         @}
      @}
   close(LS);
   @}

########################################################

sub arguments
   @{
   $printhomes = 0;
   $group = "*";
   $server = `/bin/hostname`;
   chop $server;

   foreach $arg (@@ARGV)
      @{
      if (substr($arg,0,1) eq "u")
         @{
         $group = $arg;
         next;
         @}

      if ($arg eq "home")
         @{
         $printhomes = 1;
         next;
         @}

      $server= $arg;     #default is to interpret as a server.
      @}
   @}

@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Pattern matching, search and replace, Perl examples, Perl
@section Pattern matching and extraction

Perl has regular expression operators for identifying patterns. The
operator
@smallexample

     /@var{regular expression}/
 
@end smallexample
@noindent
returns true of false depending on whether the regular expression matches the
contents of @code{$_}. For example

@smallexample

  if (/perl/)
     @{
     print "String contains perl as a substring";
     @}

  if (/(Sat|Sun)day/)
     @{
     print "Weekend day....";
     @}
@end smallexample
The effect is rather like the @code{grep} command.
To use this operator on other variables you would write:
@smallexample

  $variable =~ /@var{regexp}/

@end smallexample
Regular expression can contain parenthetic sub-expressions, e.g.
@smallexample

  if (/(Sat|Sun)day (..)th (.*)/)
     @{
     $first = $1;
     $second = $2;
     $third = $3;
     @}
@end smallexample
@noindent
in which case perl places the objects matched by such sub-expressions
in the variables @code{$1}, @code{$2} etc.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node search and replace, WWW example, Pattern matching, Perl
@section Searching and replacing text

@cindex @samp{sed} as a perl script
@cindex Pattern matching in perl
@cindex Pattern replacement in perl
@noindent
The @samp{sed}-like function for replacing all occurances of a string
is easily implemented in Perl using

@smallexample
while (<input>)
   @{
   s/$search/$replace/g;
   print output;
   @}
@end smallexample

@noindent
This example replaces the string inside the default variable. To replace
in a general variable we use the operator @samp{=~}, with syntax:

@smallexample
$variable =~ s/@var{search}/@var{replace}/
@end smallexample

Here is an example of some of this operator in use. The following is a
program which searches and replaces a string in several files.  This is
useful program indeed for making a change globally in a group of files!
The program is called `file-replace'.

@smallexample
#!/local/bin/perl
##############################################################
#
# Look through files for findstring and change to newstring
# in all files.
#
##############################################################

#
# Define a temporary file and check it doesn't exist
#

$outputfile = "tmpmarkfind";
unlink $outputfile;

#
# Check command line for list of files
#

if ($#ARGV < 0)
   @{
   die "Syntax: file-replace [file list]\n";
   @}

print "Enter the string you want to find (Don't use quotes):\n\n:";
$findstring=<STDIN>;
chop $findstring;

print "Enter the string you want to replace with (Don't use quotes):\n\n:";
$replacestring=<STDIN>;
chop $replacestring;

#

print "\nFind: $findstring\n";
print "Replace: $replacestring\n";
print "\nConfirm (y/n)  ";
$y = <STDIN>;
chop $y;

if ( $y ne "y")
   @{
   die "Aborted -- nothing done.\n";
   @}
else
   @{
   print "Use CTRL-C to interrupt...\n";
   @}

#
# Now shift default array @@ARGV to get arguments 1 by 1
#

while ($file = shift)      
   @{
   if ($file eq "file-replace")
      @{
      print "Findmark will not operate on itself!";
      next;
      @}

   #
   # Save existing mode of file for later
   #

   ($dev,$ino,$mode)=stat($file);

   open (INPUT,$file) || warn "Couldn't open $file\n";
   open (OUTPUT,"> $outputfile") || warn "Can't open tmp";

   $notify = 1;

   while (<INPUT>)
      @{
      if (/$findstring/ && $notify)
         @{
         print "Fixing $file...\n";
         $notify = 0;
         @}
      s/$findstring/$replacestring/g;
@cindex Searching and replacing in perl (example)
      print OUTPUT;
      @}

   close (OUTPUT);

   #
   # If nothing went wrong (if outfile not empty)
   # move temp file to original and reset the
   # file mode saved above
   #

@vindex -z in perl
   if (! -z $outputfile)
      @{
      rename ($outputfile,$file);
@vindex @samp{rename} in perl
      chmod ($mode,$file);
      @}
   else
      @{
      print "Warning: file empty!\n.";
      @}
   @}
@end smallexample

@noindent
Similarly we can search for lines containing a string. Here is
the grep program written in perl

@smallexample
#!/local/bin/perl
#
# grep as a perl program
#

# Check arguments etc

while (<>)
   @{
   print if (/$ARGV[1]/);
   @}

@end smallexample
@noindent
The operator @samp{/@var{search-string}/} returns true if the search
string is a substring of the default variable @code{$_}. To search
an arbitrary string, we write
@smallexample
 .... if (@var{teststring} =~ /@var{search-string}/);
@end smallexample

@noindent
Here @var{teststring} is searched for occurrances of @var{search-string}
and the result is true if one is found.
@cindex Pattern matching in perl

In perl you can use regular expressions to search for text patterns.
Note however that, like all regular expression dialects, perl has
its own conventions. For example the dollar sign does not mean
"match the end of line" in perl, instead one uses the @samp{\n} symbol.
Here is an example program which illustrates the use of regular expressions
in perl:

@smallexample
#!/local/bin/perl
#
# Test regular expressions in perl
#
# NB - careful with \ $ * symbols etc. Use '' quotes since
#      the shell interprets these!
#

open (FILE,"regex_test");

$regex = $ARGV[$#ARGV];

print "Looking for $ARGV[$#ARGV] in file...\n";

while (<FILE>)
   @{
   if (/$regex/)
      @{
      print;
      @}
   @}


#
# Test like this:
#
#  regex '.*'       - prints every line (matches everything)
#  regex '.'        - all lines except those containing only blanks 
#                     (. doesn't match ws/white-space)
#  regex '[a-z]'    - matches any line containing lowercase
#  regex '[^a-z]'   - matches any line containg something which is 
#                     not lowercase a-z
#  regex '[A-Za-z]' - matches any line containing letters of any kind
#  regex '[0-9]'    - match any line containing numbers
#  regex '#.*'      - line containing a hash symbol followed by anything
#  regex '^#.*'     - line starting with hash symbol (first char)
#  regex ';\n'      - match line ending in a semi-colon
#

@end smallexample

@noindent
Try running this program with the test data on the following file
which is called @file{regex_test} in the example program.

@smallexample


# A line beginning with a hash symbol

JUST UPPERCASE LETTERS

just lowercase letters

Letters and numbers 123456

123456

A line ending with a semi-colon;

Line with a comment # COMMENT...

@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node WWW example, WWW example 2, search and replace, Perl
@section Example: convert mail to WWW pages

Here is an example program which you could use to automatically
turn a mail message of the form

@smallexample
From: Newswire
To: Mail2html
Subject: Nothing happened

On the 13th February at kl. 09:30 nothing happened. No footprints
were found leading to the scene of a terrible murder, no evidence
of a struggle .... etc etc

@end smallexample

@noindent
into an html-file for the world wide web. The program works
by extracting the message body and subject from the mail
and writing html-commands around these to make a web page.
The subject field of the mail becomes the title. The other headers
get skipped, since the script searches for lines containing the
sequence "colon-space" or @samp{: }. A regular expression
is used for this.

@smallexample
#!/local/bin/perl
#
# Make HTML from mail
#

&BeginWebPage();
&ReadNewMail();
&EndWebPage();


##########################################################

sub BeginWebPage

@{
    print "<HTML>\n";
    print "<BODY>\n";
@}

##########################################################

sub EndWebPage

@{
    print "</BODY>\n";
    print "</HTML>\n";
@}

##########################################################

sub ReadNewMail

@{
while (<>)
   @{
   if (/Subject:/)   # Search for subject line
      @{
      # Extract subject text...

      chop;
      ($left,$right) = split(":",$_);
      print "<H1> $right </H1>\n";
      next;
      @}
   elsif (/.*: .*/)   # Search for - anything: anything
      @{
      next;           # skip other headers
      @}

   print;
   @} 
@}

@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node WWW example 2, Other functions, WWW example, Perl
@section Generate WWW pages automagically

The following program scans through the password database and
build a standardized html-page for each user it finds there. It
fills in the name of the user in each case. Note the use of
the @samp{<<} operator for extended input, already used in the
context of the shell, @xref{Pipes and redirection}. This allows
us to format a whole passage of text, inserting variables at
strategic places, and avoid having to the @code{print} over
many lines.

@smallexample

#!/local/bin/perl
#
# Build a default home page for each user in /etc/passwd
#
#

####################################################################
# Level 0 (main)
####################################################################

$true = 1;
$false = 0;

# First build an associated array of users and full names

setpwent();

while ($true)
   @{
   ($name,$passwd,$uid,$gid,$quota,$comment,$fullname) = getpwent;
   $FullName@{$name@} = $fullname;
   print "$name - $FullName@{$name@}\n";
   last if ($name eq "");
   @}

print "\n";

# Now make a unique filename for each page and open a file

foreach $user (sort keys(%FullName))
   @{
   next if ($user eq "");

   print "Making page for $user\n";
   $outputfile = "$user.html";

   open (OUT,"> $outputfile") || die "Can't open $outputfile\n";

   &MakePage;

   close (OUT);
   @}


####################################################################
# Level 1
####################################################################

sub MakePage

@{
print OUT <<ENDMARKER;

<HTML>
<BODY>
<HEAD><TITLE>$FullName@{$user@}'s Home Page</TITLE></HEAD>
<H1>$FullName@{$user@}'s Home Page</H1>

Hi welcome to my home page. In case you hadn't
got it yet my name is: $FullName@{$user@}...

I study at <a href=http://www.iu.hioslo.no>H&oslash;gskolen i Oslo</a>.

</BODY>
</HTML>
 
ENDMARKER
@}
 
@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Other functions, Perl summary, WWW example 2, Perl
@section Other supported functions

Perl has very many functions which come directly from the C library.
To give a taster, a few are listed here. The Perl book contains
a comprehensive description of these.

@table @emph
@item Fork
The standard UNIX fork command for spawning new processes.
@item Sockets
Support for network socket communication.
@item Directories
Directory opening and handling routines.
@item Databases
Reading from the password files and the host databases is supported through
the standard C functions @samp{getpasswdbyname} etc. dressed up to look like Perl.
@item Crypt
The password encryption function.
@item Regexp
Regular expressions and pattern matching, search and replace functions
as in @samp{sed}.
@item Operators
Perl has the full set of C's logical operators.
@item File testing
Tests from the shell like @samp{if (-f file)}.
@end table

@noindent
Here are some of the most frequently used functions

@table @code
@item chmod
Change the file mode of a file. e.g. @code{chmod 755,@var{filename}}
@item chdir
Change the current working directory. e.g. @code{chdir /etc}
@item stat
Get info about permissions, ownership and type of a file.
@item open
Open a  file for reading, @samp{>} writing, @samp{|} as a pipe.
@item close
Close an open file handle.
@item system
Execute a shell command as a child process. e.g. @code{system "ls";}
@item split
Split a string variable into an array of elements, by searching for a
special character (space or @samp{:} etc.)
e.g. @code{@@array=split(":",$string)}.
@item rename
Rename a file. e.g. @code{rename @var{old name} @var{new-name}}
@item mkdir
Make a new directory. @code{mkdir @var{newdir}}
@item shift
Read the first element of an array and delete it, shifting all the
array elements down by one. (e.g. @code{$first=shift(@@array);)}.
@item chop
Chops off the last character of a string. Often used for deleting the
end-of-line character when reading from a file.
@item oct
Interprets a number as octal (converts to decimal). e.g.
@code{$decimal = oct(755);}
@item kill
Send a kill signal to a list of processes. 
e.g. @code{kill -9, @var{pid1},@var{pid2}...}
@end table

@noindent
You should explore Perl's possibilities yourself. Perl is a good alternative
to the shell which has much of the power of C and is therefore
ideal for simple and more complex system programming tasks.
If you intend to be a system administrator for UNIX systems, you could
do much worse than to read the Perl book and learn Perl inside out.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Perl summary, Ex5, Other functions, Perl
@section Summary

The Practical Extraction and Report Language is a powerful tool which
goes beyond shell programming, but which retains much of the
immediateness of shell programming in a more formal programming
environment.

The success of Perl has led many programmers to use it exclusively.  In
the next section, I would like to argue that programming directly in C
is not much harder. In fact it has advantages in the long run. The power
of Perl is that it is as @emph{immediate} as shell programming. If you
are inexperienced, Perl is a little easier than C because many features
are ready programmed into the language, but with time one also builds up
a repertoire of C functions which can do the same tricks.



@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Ex5, Proj5, Perl summary, Perl
@section Exercises

@enumerate

@item 
Write a progam which prints out all of its arguments alphabetically
together with the first and the last, and the number of arguments.

@item 
Write a program which prints out the pathname of the home directory
for a given user. The user's login name should be given as an argument.

@item 
Write a program called `search-replace' which looks for a given
string in a list of files and replaces it with a new string. You should
be able to specify a list of files using ordinary unix wildcards. e.g.
@samp{search-replace search-string replace-string *.text}. This is a
dangerous operation! What if the user types the strings incorrectly?
How can you may the program safer?

@item 
Write a program which opens a pipe from @samp{ps} and computes the
total cpu-time used by each user. Print the results in order of maximum
to minimum. Hint: use an associated array to store the information.

@item 
Write a program which forks and goes into the background. Make the
program send you mail when some other user of your choice logs in. 
Use sleep to check only every few minutes.

@item 
Open a pipe from @samp{find} and collect statistics over how many
files there are in all of your sub-directories.
@end enumerate

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Proj5,  , Ex5, Perl
@section Project

Write a program which checks the `sanity' of your UNIX system. 
@enumerate
@item Check that the password file /etc/passwd is not writable
by general users.
@item Check that the processes @samp{cron} and @samp{sendmail} are running.

@item Check that, if the file @samp{/etc/exports} 
or @file{/etc/dfs/dfstab} exists, the @emph{nfsd} daemon
is running.

@item Check that if the filesystem table @samp{/etc/fstab} (or its
equivalent on non-BSD systems) contains NFS mounted filesystems, the
@samp{biod} or @samp{nfsiod} daemon is running.

@item Check that the file @samp{/etc/resolv.conf} contains the correct
domain name. It
may or may not be the same as that returned by the shell 
command @samp{domainname}. If it is not the same, you should
print the message `NIS domain has different name to DNS domain'.

@end enumerate

@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node WWW and CGI programming, C programming, Perl, Top
@chapter WWW and CGI programming

CGI stands for the Common Gateway Interface. It is the name
given to scripts which can be executed from within pages of the
world wide web. Although it is possible to use any language in
CGI programs (hence the word `common'), the usual choice is
Perl, because of the ease with which Perl can handle text.

The CGI interface is pretty unintelligent, in order to
be as general as possible, so we need to do a bit of work in
order to make scripts work.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@menu
* Permissions::                 
* Protocols::                   
* HTML coding::                 
* Perl and the web::            
* PHP and the web::             
@end menu

@node Permissions, Protocols, WWW and CGI programming, WWW and CGI programming
@section Permissions

The key thing about the WWW which often causes a lot of confusion
is that the W3 service runs with a user ID of `nobody'. The purpose
of this is to ensure that nobody has the right to read or write files
unless they are opened very explicitly by the user who owns them. 

In order for files to be readable on the WWW, they must have file mode
@samp{644} and they must lie in a directory which has mode
@samp{755}. In order for a CGI program to be executable, it must have
permission @samp{755} and in order for such a program to write to
a file in a user's directory, it must be possible for the file
to be created (if necessary) and everyone must be able to write
to it. That means that files which are written to by the WWW must have
mode @samp{666} and must either exist already or lie in a directory
with permission @samp{777}@footnote{You could also set the sticky bit
@samp{1777} in order to prevent malicious users from deleting
your file.}.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Protocols, HTML coding, Permissions, WWW and CGI programming
@section Protocols

CGI script programs communicate with W3 browsers using a very simple
protocol. It goes like this:

@itemize @bullet

@item
A web page sends data to a script using the `forms' interface.  Those
data are concatenated into @emph{a single line}. The data in separate
fields of a form are separated by @samp{&} signs. New lines are replaced
by the text @samp{%0D%0A}, which is the DOS ASCII representation of a
newline, and spaces are replaced by @samp{+} symbols.

@item
A CGI script reads this single line of text on the standard input.

@item
The CGI script replies to the web browser. The first line
of the reply @emph{must} be a line which is tells the browser
what mime-type the data are sent in. Usually, a CGI script
replies in HTML code, in which case the first line in the
reply must be:

@smallexample
  Content-type: text/html
@end smallexample
@cindex CGI protocol
@cindex Mime types in W3
@noindent
This must be followed by a blank line.

@end itemize

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node HTML coding, Perl and the web, Protocols, WWW and CGI programming
@section HTML coding of forms

To start a CGI program from a web page we use a @emph{form}
@cindex Forms in HTML
 which is a part of the HTML code enclosed with the parentheses

@smallexample

 <FORM method="POST" ACTION="/cgi-script-alias/program.pl">
     ...
 </FORM>
@end smallexample

@noindent
The method `post' means that the data which get typed into
this form will be piped into the CGI program via its standard
input. The `action' specifies which program you want to start.
Note that
@cindex Script aliases in W3
you cannot simply use the absolute path of the file, for security
reasons. You must use something called a `script alias' to tell the web
browser where to find the program. If you do not have a script alias
defined for you personally, then you need to get one from your system
administrator.  By using a script alias, no one from outside your site
can see where your files are located, only that you have a `cgi-bin'
area somewhere on your system.

Within these parentheses, you can arrange to collect different kinds of
input. The simplest kind of input is just a button which starts
the CGI program. This has the form
@smallexample

 <INPUT TYPE="submit" VALUE="Start my program">

@end smallexample

@noindent
This code creates a button. When you click on it the program
in your `action' string gets started. More generally, you will
want to create input boxes where you can type in data. To create
a single line input field, you use the following syntax:
@smallexample

 <INPUT NAME="variable-name" SIZE=40>

@end smallexample
@noindent
This creates a single line text field of width 40 characters.  This is
not the limit on the length of the string which can be typed into the
field, only a limit on the amount which is visible at any time. It is
for visual formatting only.  The NAME field is used to identify the data
in the CGI script.  The string you enter here will be sent to the CGI
script in the form @samp{variable-name=value of input...}.  Another type
of input is a text area. This is a larger box where one can type in text
on several lines. The syntax is:
@smallexample

 <TEXTAREA NAME="variable-name" ROW=50 COLS=50>

@end smallexample
@noindent
which means: create a text area of fifty rows by fifty columns
with a prompt to the left of the box. Again, the size has only
to do with the visual formatting, not to do with limits
on the amount of text which can be entered.

As an example, let's create a WWW page with a complete
form which can be used to make a guest book, or order
form.

@smallexample
<HTML>
<HEAD>
<TITLE>Example form</TITLE>
<!-- Comment: Mark Burgess, 27-Jan-1997 -->
<LINK REV="made" HREF="mailto:mark@@iu.hioslo.no">
</HEAD>
<BODY>
<CENTER><H1>Write in my guest book...</H1></CENTER>
<HR>

<CENTER><H2>Please leave a comment using the form below.</H2><P>
<FORM method="POST" ACTION="/cgi-bin-mark/comment.pl">

Your Name/e-mail: <INPUT NAME="variable1" SIZE=40> <BR><BR>

<P>
<TEXTAREA NAME="variable2" cols=50 rows=8></TEXTAREA>
<P>

<INPUT TYPE=submit VALUE="Add message to book">
<INPUT TYPE=reset VALUE="Clear message">
</FORM>

<P>

</BODY>
</HTML>

@end smallexample
@noindent

The reset button clears the form. When the submit button is pressed,
the CGI program is activated.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Perl and the web, PHP and the web, HTML coding, WWW and CGI programming
@section Perl and the web


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@menu
* Interpreting the data::       
* A complete guestbook example::  
@end menu

@node Interpreting the data, A complete guestbook example, Perl and the web, Perl and the web
@subsection Interpreting data from forms

To interpret and respond to the data in a form, we must write a program
which satsifies the protocol above, @xref{Protocols}.  We use
perl as a script langauge.  The simplest valid CGI script is the
following:

@smallexample

#!/local/bin/perl

 #
 # Reply with proper protocol
 #

print "Content-type: text/html\n\n";

 #
 # Get the data from the form ...
 #

$input = <STDIN>;

 #
 # ... and echo them back
 #

print $input, "\n Done! \n";

@end smallexample

@noindent
Although rather banal, this script is a useful starting point for CGI
programming, because it shows you just how the input arrives at the
script from the HTML form. The data arrive all in a single, enormously
long line, full of funny characters. The first job of any script is to
decode this line.

Before looking at how to decode the data, we should make an important
point about the protocol line. If a web browser does not get this
`Content-type' line from the CGI script it returns with an error:

@example

500 Server Error

The server encountered an internal error or misconfiguration and was
unable to complete your request.

Please contact the server administrator, and inform them of the time 
the error occurred, and anything you might have done that may have 
caused the error.

Error: HTTPd: malformed header from script www/cgi-bin/comment.pl 

@end example

@noindent
Before finishing your CGI script, you will probably ecounter this error
several times. A common reason for getting the error is a syntax error
in your script. If your program contains an error, the first thing a
browser gets in return is not the `Content-type' line, but an error
message.  The browser does not pass on this error message, it just
prints the uninformative message above.

If you can get the above script to work, then you are ready to
decode the data which are sent to the script. The first thing
is to use perl to split the long line into an array of lines, by
splitting on @samp{&}. We can also convert all of the @samp{+}
symbols back into spaces. The script now looks like this:

@smallexample
#!/local/bin/perl

 #
 # Reply with proper protocol
 #

print "Content-type: text/html\n\n";

 #
 # Get the data from the form ...
 #

$input = <STDIN>;

 #
 # ... and echo them back
 #

print "$input\n\n\n";

$input =~ s/\+/ /g;

 #
 # Now split the lines and convert
 #

@@array = split('&',$input);

foreach $var ( @@array )
   @{
   print "$var\n";
   @}

print "Done! \n";

@end smallexample

@noindent
We now have a series of elements in our array. The output from this
script is something like this:

@smallexample

variable1=Mark+Burgess&variable2=%0D%0AI+just+called+to+say+ @var{(wrap)}
....%0D%0A...hey+pig%2C+nothing%27s+working+out+the+way+I+planned
variable1=Mark Burgess variable2=%0D%0AI just called to say  @var{(wrap)}
....%0D%0A...hey pig%2Cnothing%27s working out the way I planned Done! 

@end smallexample
@noindent
As you can see, all control characters are converted into the form @samp{%XX}.
We should now try to do something with these. Since we are usually not interested
in keeping new lines, or any other control codes, we can simply null-out these
with a line of the form

@smallexample

$input =~ s/%..//g;

@end smallexample
@noindent
The regular expression @samp{%..} matches anything beginning with a percent
symbol followed by two characters. The resulting output is then free of
these symbols. We can then separate the variable contents from their names
by splitting the input. Here is the complete code:

@smallexample
#!/local/bin/perl

 #
 # Reply with proper protocol
 #

print "Content-type: text/html\n\n";

 #
 # Get the data from the form ...
 #

$input = <STDIN>;

 #
 # ... and echo them back
 #

print "$input\n\n\n";

$input =~ s/%..//g;

$input =~ s/\+/ /g;

@@array = split('&',$input);

foreach $var ( @@array )
   @{
   print "$var<br>";
   @}

print "<hr>\n";

($name,$variable1) = split("variable1=",$array[0]);
($name,$variable2) = split("variable2=",$array[1]);

print "<br>var1 = $variable1<br>";
print "<br>var2 = $variable2<br>";

print "<br>Done! \n";

@end smallexample
@noindent
and the output

@cartouche
@smallexample
variable1=Mark+Burgess&variable2=%0D%0AI+just+called+to+say @var{(wrap)}
+....%0D%0A...hey+pig%2C+nothing%27s+working+out+the+way+I+planned
variable1=Mark Burgess
variable2=I just called to say .......hey pig nothings working @var{(wrap)}
 out the way I planned 


var1 = Mark Burgess

var2 = I just called to say .......hey pig nothings working out  @var{(wrap)}
the way I planned 

Done! 
@end smallexample
@end cartouche

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node A complete guestbook example,  , Interpreting the data, Perl and the web
@subsection A complete guestbook example in perl

Let us now use this technique to develop a guest book aplication.
Based on the code above, analyze the following code.

@smallexample
#!/local/bin/perl
####################################################################
#
# Guest book
#
####################################################################

$guestbook_page = "/iu/nexus/ud/mark/www/tmp/cfguest.html";

$tmp_page = "/iu/nexus/ud/mark/www/tmp/guests.tmp";
  
$remote_host = $ENV@{"REMOTE_HOST"@};

print "Content-type: text/html\n\n";
print "<br><hr><br>\n";
print "Thank you for submitting your comment!<br><br>\n";
print "best wishes,<br><br>";
print "-Mark<br><br><br>";
print "Return to <a href=http://www.iu.hioslo.no/~mark/menu.html>menu</a>\n";

$input = <STDIN>;

$input =~ s/%..//g;

$input =~ s/\+/ /g;

@@array = split('&',$input);

($skip,$name) = split("var1=",$array[0]);
($skip,$message) = split("var2=",$array[1]);

if (! open (PAGE, $guestbook_page)) 
   @{
   print "Content-type: text/html\n\n";
   print "couldn't open guestbook page file!";
   @}

if (! open (TMP, "+>$tmp_page"))
   @{
   print "Content-type: text/html\n\n";
   print "couldn't open temporary output file!"; 
   @}

while ($line = <PAGE>)
   @{
   if ($line =~ /<h3>Number of entries: (..)/)
      @{
      $entry_no = $1;
      $entry_no++;
      $line = "<h3>Number of entries: $entry_no </h3>\n";
      @}

    if ($line =~ /<!-- LAST ENTRY -->/)
       @{
       $date = `date +"%A, %b %d %Y"`;	
       print TMP "<b>Entry $date from host: $remote_host</b>\n<p>\n";
       print TMP "From: $name\n<p>\n";
       print TMP $message;
       print TMP "\n<hr>\n";
       @}

    print TMP "$line";
    @}
    
close PAGE;
close TMP;

if (! rename ($tmp_page, $guestbook_page))
   @{
   print "Oops! Rename operation failed!\n";
   @}

chmod (0600, $guestbook_page);

@end smallexample

This script works by reading through the old guest book file, opening a
new copy of the guest book file and appending a new messages at the
end. The end of the message section (not counting the @samp{</HTML>}
tags) is marked by a comment line. 

@smallexample
<!-- LAST ENTRY -->
@end smallexample

@noindent
Note that a provisional guest book file has to exist in the first place.
The script writes to a new file and then swaps the new file for the old
one. The guest book file looks something like this:
@smallexample
<html><head>
<title>Comments</title>
</head>
<body>
<h1>My guest book</h1>
 
<b>Entry no.  Wednesday, Feb 28 1996
 from host: dax</b>
<p>
From: Mark.Burgess@@iu.hioslo.no
<p>
Just to start the ball rolling....
 
<hr>

<b>Entry no.  Tuesday, Mar 26 1996
 from host: enterprise.subspace.net</b>
<p>
From: spock@@enterprise
<p>
Registering a form of energy never before encountered.
 
<!-- LAST ENTRY -->
 
</body> <address><a href="http://www.iu.hioslo.no/~mark">Mark
Burgess</a> - Mark.Burgess@@iu.hioslo.no</addre ss> </html>


@end smallexample
The directory in which this file lies needs to be writable to
the user nobody (the WWW user) and the files within need to be
deletable by nobody but no one else. Some users try to make
guest book scripts setuid-themselves in order to overcome the
problem that httpd runs with uid nobody, but this opens many
security issues. In short it is asking for trouble. Unfortunately
an ordinary user cannot use @code{chown} in order to give access
only to the WWW user nobody, so this approach needs the cooperation
of the system administrator. Nevertheless this is the most secure
approach.
Try to work through this example step for step.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node PHP and the web,  , Perl and the web, WWW and CGI programming
@section PHP and the web

The PHP 3 language makes the whole business of web programming rather
simpler than perl. It hides the business of translating variables
from forms into new variables in a CGI program and it even allows you
to embed active code into you HTML pages. PHP has special support for
querying data in an SQL database like MySQL or Oracle. PHP documentation
lives at @uref{http://www.php.net}.

@menu
* Embedded PHP::                
* PHP and forms::               
@end menu

@node Embedded PHP, PHP and forms, PHP and the web, PHP and the web
@subsection Embedded PHP

PHP code can be embedded inside HTML pages provided your WWW server is
configurered with PHP support. PHP code lives inside a tag with the
general form
@smallexample

  <?php @var{code...}  ?>

@end smallexample
@noindent
For example, we could use this to import one file into another
and print out a table of numbers:
@smallexample
<html>
<body>

<?php 

include "file.html" 

for ($i = 0; $i < 10; $i++)
   @{
   print "Counting $i<br>";
   @}

?>

</body>
</html>
@end smallexample
This makes it easy to generate WWW pages with a fixed visual layout:

@smallexample
<?php
#
# Standard layout
#

# Set $title, $comment and $contents

##########################################################################

print "<body>\n";
print "<img src=img/header.gif>";

print "<h1>"$title</h1>";
print "<em>$comment</em>";
print "<blockquote>\n";

include $contents;

print ("</blockquote>\n");
print ("</body>\n");
print ("</html>\n");

@end smallexample

@noindent
Variables are easily set by calling PHP code in the form of a CGI program
from a form.

@node PHP and forms,  , Embedded PHP, PHP and the web
@subsection PHP and forms

PHP is particularly good at dealing with forms, as a CGI scripting
langauge. Consider the following form:

@smallexample
<html>
<body>
<form action="/cgi-bin-scriptalias/spititout.php" method="post">

    Name:  <input type="text" name="personal[name]"><br>
    Email: <input type="text" name="personal[email]"><br>
    Preferred language:
    <select multiple name="language[]">
        <option value="English">English
        <option value="Norwegian">Norwegian
        <option value="Gobbledigook">Gobbledigook
    </select>
    
    <input type=image src="image.gif" name="sub">

</form>
</body>
</html>
@end smallexample
This produces a page into which one types a name and email address
and chooses a language from a list of three possible choices. When the
user clicks on a button marked by the file @file{image.gif} the
form is posted. Here is a program which unravels the data sent to the
CGI program:

@smallexample

#!/local/bin/php

<?php
#
# A CGI program which handles a form
# Variables a translated automatically
#

$title = "This page title";
$comment = "This pages talks about the following.....";

##########################################################################

echo "<body>";
echo "<h1>$title</h1>";
echo "<em>$comment</em>";
echo "<blockquote>\n";

###

 echo "Your name is $personal[name]<br><br>";
 echo "Your email is $personal[email]<br><br>";

 echo "Language options: ";
 echo "<table> ";

 for ($i = 0; strlen($language[$i]) > 0; $i++)
    @{
    echo "<tr><td bgcolor=#ff0000>Variable language[$i] = $language[$i]</td></tr>";
    @}

 if ($language[0] == "Norwegian")
    @{
    echo "Hei alle sammen<p>";
    @}
 else
    @{
    echo "Greetings everyone, this page will be in English<p>";
    @}

 echo "</table> ";

###

echo ("</blockquote>\n");
echo ("</body>\n");
echo ("</html>\n");
?>


@end smallexample

@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node C programming, Network programming, WWW and CGI programming, Top
@chapter C programming

@emph{This section is not meant to teach you C. It is a guide to using C
in UNIX and it is assumed that you have a working knowledge of the
language. See the GNU C-Tutorial for an introduction to basics.}

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@menu
* Shell or C?::                 
* C program structure::         
* UNIX calls and POSIX::        
* Compiling C::                 
* Make::                        
* argv argc envp::              
* Environment variables in C::  
* C files and dirs::            
* File test macros::            
* Process control::             
* A more secure popen::         
* Traps and signals::           
* Regular expressions in C::    
* DES encryption::              
* ioctl::                       
* Database example in C::       
* lex and yacc::                
* Ex 6::                        
@end menu

@node Shell or C?, C program structure, C programming, C programming
@section Shell or C?

@cindex C programming
In the preceding chapters we have been looking at ways to get simple
programming tasks done. The immediateness of the script languages is a
great advantage when we just want to get a job done as quickly as
possible.  Scripts lend themselves to simple system administration tasks
like file processing, but they do not easily lend themselves to more
serious programs.

@cindex Wrappers
Although some system administrators have grown to the idea that shell
programming is easier, I would argue that this is not really true.
First of all, most of the UNIX shell commands are just wrapper programs
for C function calls. Why use the wrapper when you can use the real
thing? Secondly, the C function calls return data in pointers and
structures which are very easy to manipulate, whereas piping the output
of shell programs into others can be a very messy and awkward way of
working.  Here are some of the reasons why we also need a more
traditional programming language like C.

@enumerate

@item 
The shell languages do not allow us to create an acceptable
user-interface, like X-windows, or the curses (cursor manipulation)
library. They are mainly intended for file-processing. (Though
recently the @emph{Tk} library has provided a way of creating
user interfaces in Tcl and Perl.)
@cindex Curses
@cindex X windows
@cindex Tk library

@item 
Shell commands read their input line-by-line. Not all input
is generated in this simple way -- we also need to be able to read
through lines i.e. the concept of a  @emph{data stream}. 

@item 
More advanced data structures are needed for most applications, such
as linked lists and binary trees, acyclic graphs etc. 

@item 
Compilers help to sort out simple typographical and logical errors
by compile-time checking source code. 

@item 
Compiled code is faster than interpreted code.

@item 
Many tools have been written to help in the programming of C code
(dbx, lex, yacc etc.).
@cindex @samp{lex}
@cindex @samp{yacc}

@end enumerate

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node C program structure, UNIX calls and POSIX, Shell or C?, C programming
@section C program structure

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* C structure::                 
* Macros and declarations::     
* Several files::               
@end menu

@node C structure, Macros and declarations, C program structure, C program structure
@subsection  The form of a C program

A C program consists of a set of function, beginning
with the main program:


@smallexample

main ()   /* This is a comment */

@{

Commands ...


@}

@end smallexample

The source code of a C program can be divided into several text files.
C compiles all functions separately; the linker @code{ld} joins them all
up at the end. This means that we can plan out a strategy for writing
large programs in a clear and efficient manner. 

NOTE: C++ style comments @samp{//...} are not allowed by most
C compilers.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Macros and declarations, Several files, C structure, C program structure
@subsection  Macros and declarations

Most Unix systems now have ANSI C compatible compilers, but this has not
always been the case. Most UNIX programs written in a version
of C which is older than the ANSI standard, so you will need an
appreciation of old Kernighan and Ritchie C conventions for C
programming. See for example my C book.

An obvious difference between ANSI C and K&R C is that the C++
additions to the language are not included. Here are some useful
points to remember.
@cindex ANSI C
@cindex Kernighan and Ritchie C

@itemize @bullet
@item 
K&R C does not allow @samp{const} data, it uses the C preprocessor with
@samp{#define} instead. i.e. intead of
@smallexample

const int blah = 1;

@end smallexample
@noindent
use
@smallexample
#define blah 1
@end smallexample

@noindent
Remember that the hash symbol @samp{#} must be the first character on
a line under UNIX.
@item 
K&R C doesn't use function prototypes or declarations of the form:
@smallexample

void function (char *string, int a, int b)

@{
@}

@end smallexample
@noindent
Instead one writes:
@smallexample

void function (string, a, b)

char *string;
int a,b;

@{
@}

@end smallexample
@end itemize

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Several files,  , Macros and declarations, C program structure
@subsection  Several files

Most unix programs are very large and are split up into many files.
Remember, when you split up programs into several files, you must
declare variables as @samp{extern} in file A if they are really declared
in file B.  in which you want to use them. This tells the compiler that
it should not try to create local storage for the variable, because this was
already done in another file.

@cindex Splitting C into many files.
@cindex @code{extern} variables

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node UNIX calls and POSIX, Compiling C, C program structure, C programming
@section A note about UNIX system calls and standards

@cindex POSIX standard
Most of the system calls in UNIX return data in the form of @samp{struct}
variables. Sometimes these are structures used by the operating system
itself -- in other cases they are just put together so that programmers
can handle a packet of data in a convenient way.

If in doubt, you can find the definitions of these structures in the
relevant include files under @file{/usr/include}.

Since UNIX comes in many flavours the system calls are not always
compatible and may have different options and arguments. Because
of this there is a number of standardizing organizations for UNIX.
One of them is POSIX which is an organization run by the
major UNIX vendors. Programs written for UNIX are now
expected to be POSIX compliant. This is not something you need to
think about at the level of this course, but you should certainly
remember that there exist programming standards and that these should
be adhered to. The aim is to work towards a single standard UNIX.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Compiling C, Make, UNIX calls and POSIX, C programming
@section Compiling: @samp{cc}, @samp{ld} and @file{a.out}

The C compiler on the unix system is traditionally called @samp{cc} and
has always been a traditional part of every Unix environment. Recently
several Unix vendors have stopped including the C compiler as a part of
their operating systems and instead sell a compiler separately.
Fortunately there is a public domain Free Software version of the
compiler called @samp{gcc} (the GNU C compiler). We shall use this in
all the examples.

To compile a program consisting of several files of code,
we first compile all of the separate pieces without trying to link
them. There are therefore two stages: first we turn @samp{.c}
files into @samp{.o} files. This compiles code but does not
fix any address references. Then we link all @samp{.o}
files into the final executable, including any libraries
which are used.

@cindex Compiling programs
@cindex Multiple C files, compiling
Let's suppose we have files @file{a.c}, @file{b.c} and @file{c.c}.
We write:
@smallexample 

  gcc -c a.c b.c c.c

@end smallexample
This creates files @samp{a.o}, @samp{b.o} and @samp{c.o}.
Next we link them into one file called `myprog'.
@smallexample

  gcc -o myprog  a.o b.o c.o

@end smallexample

@noindent
If the naming option @samp{-o myprog} is not used, the link @samp{ld}
uses the default name @emph{a.out} for the executable file.
@cindex @file{a.out}

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Libraries and LD_LIBRARY_PATH::  
* Include files::               
* Shared and static libraries::  
* Important paths::             
@end menu

@node Libraries and LD_LIBRARY_PATH, Include files, Compiling C, Compiling C
@subsection  Libraries and @samp{LD_LIBRARY_PATH}

@vindex @samp{LD_LIBRARY_PATH}
@cindex libc
@cindex libm
@cindex libcurses
@cindex Library path for C loader
@cindex @samp{-L} option to @code{cc}
The resulting file is called @samp{myprog} and includes references only
to the standard library @samp{libc}. If we wish to link in the math
library @samp{libm} or the cursor movement library @samp{libcurses} --
or in general, a library called @samp{libBLAH} , we need to use the
@samp{-l} directive.

@smallexample

gcc -o myprog files.o  -lm -lcurses -lBLAH

@end smallexample

@noindent
The compiler looks for a suitable library in all of the directories
listed in the environment variable @samp{LD_LIBRARY_PATH}. Alternatively
we can add a directory to the search path by using the @samp{-L}.
option:
@smallexample

gcc -o myprog files.o -L/usr/local/lib -lm -lcurses -lBLAH 

@end smallexample

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Include files, Shared and static libraries, Libraries and LD_LIBRARY_PATH, Compiling C
@subsection  Include files

@cindex Include files
Normally the compiler looks for include files only in the
directory @file{/usr/include}. We can add further paths to search
using the @samp{-I} option.
@smallexample

gcc -o myprog file.c  -I/usr/local/include -I/usr/local/X11/include

@end smallexample
@cindex @samp{-I} option to @code{cc}
@cindex Include file search path

Previously, Unix libraries have been in @file{a.out} code format, but
recent releases of unix have gone over to a more efficient and flexible
format called ELF (executable and linking format).

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Shared and static libraries, Important paths, Include files, Compiling C
@subsection  Shared and static libraries


@cindex Static linking
@cindex Shared libraries
Libraries are collections of C functions which the operating system
creators have written for our convenience. The source code for such a
library is just the source for a collection of functions -- there is no
@code{main} program.

There are two kinds of library used by modern operating systems:
@emph{archive libraries} or static libraries 
and @code{shared libraries} or dynamical libraries. An archive
library has a name of the form
@smallexample

 lib@var{name}.a

@end smallexample
@noindent
When an archive library is linked to a program, it is appended
lock, stock and barrel to the program code. This uses a lot
of disk space and makes the size of the compiled program very large.
Shared libraries (shared objects @samp{so} or shared archives @samp{sa}
generally have names of the form)
@smallexample

  lib@var{name}.so
  lib@var{name}.sa

@end smallexample
@noindent
often with version numbers appended. When a program is
linked with a shared library the code is not appended
to the program. Instead pointers to the shared objects
are created and the library is loaded at runtime,
thus avoiding the problem of having to store the library
effectively multiple times on the disk.

To make an archive library we compile all of
the functions we wish to include in the library

@smallexample

gcc -c function1.c function2.c ...

@end smallexample

@noindent
and then join the files using the @samp{ar} command.

@smallexample

ar rcv libMYLIB.a function1.o
ar rcv libMYLIB.a function2.o

@end smallexample

@noindent
To make a shared library one provides an option to the linker
program. The exact method is different in different operating systems,
so you should look at the manual page for @code{ld} on your system.
Under SunOS 4 we take the object files @samp{*.o} and run
@smallexample

 ld -o libMYLIB.so.1.1 -assert pure-text *.o

@end smallexample
Under HPUX, we write
@smallexample

 ld -b -o libMYLIB.so.1.1 *.o

@end smallexample
With the GNU linker, you write
@smallexample

 ld -shared -o libMYLIB.so.1.1 *.o

@end smallexample

NOTE: when you add a shared library to the system under SunOS or
GNU/Linux you must run the command @samp{ldconfig}, making sure that the
path to the library is included in @samp{LD_LIBRARY_PATH}. SunOS and
GNU/Linux use a cache file @file{/etc/ld.so.cache} to keep current
versions of libraries. GNU/Linux also uses a configuration file called
@file{/etc/ld.so.conf}.
@cindex @file{ld.so.cache}
@cindex @file{ldconfig}

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Important paths,  , Shared and static libraries, Compiling C
@subsection Knowing about important paths: directory structure

It is important to understand how the C compiler finds the files it needs.
We have already mentioned the @samp{-I} and @samp{-L} options to the 
compilation command line. In general, all system include files can be
found in the directory @file{/usr/include} and subdirectories of this
directory.  All system libraries can be found in @file{/usr/lib}.

Many packages build their own libraries and keep the relevant files
in separate directories so that if the system gets reinstalled, they
do not get deleted. This is true for example of the X-windows system.
The include and library files for this are typically kept in
directories which look something like @file{/usr/local/X11R5/include}
and @file{/usr/X11R6/lib}. That means that we need to give all of
this information to the compiler. Compiling a program becomes
a complicated task in many cases so we need some kind of script
to help us perform the task. The Unix tool @code{make} was designed
for this purpose.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Make, argv argc envp, Compiling C, C programming
@section Make

Nowadays compilers are often sold with fancy user environments driven by
menus which make it easier to compile programs.  Unix has similar
environments but all of them use shell-based command line compilation
beneath the surface. That is because UNIX programmers are used to
writing large and complex programs which occupy many directories and
subdirectories.  Each directory has to be adapted or configured to fit the
particular flavour of Unix system it is being compiled upon. Interactive
user environments are very poor at performing this kind of service. UNIX
solves the problem of compiling enormous @emph{trees} of software (such
as the unix system itself!) by using a compilation language called
@samp{make}. Such language files can be generated automatically by
scripts, allowing very complex programs to configure and compile
themselves from a single control script.
@cindex Compiling huge programs

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* Compiling large programs::    
* Makefiles::                   
* Suffix rules for C++::        
@end menu

@node Compiling large programs, Makefiles, Make, Make
@subsection  Compiling large projects

Typing lines like
@smallexample

  cc -c file1.c file2.c ...
  cc -o target file1.o ....

@end smallexample
@noindent

repeatedly to compile a complicated program can be a real nuisance. One
possibility would therefore be to keep all the commands in a script.
This could waste a lot of time though. Suppose you are working on a big
project which consists of many lines of source code -- but are editing
only one file. You really only want to recompile the file you are
working on and then relink the resulting object file with all of the
other object files. Recompiling the other files which hadn't changed
would be a waste of time.  But that would mean that you would have to
change the script each time you change what you need to compile.

A better solution is to use the @samp{make} command. @samp{make} was
designed for precisely this purpose. To use @samp{make}, we create
a file called @file{Makefile} in the same directory as our program.
@samp{make} is a quite general program for building software. It is
not specifically tied to the C programming language---
it can be used in any programming language.

A @samp{make} configuration file, called a @file{Makefile}, contains
rules which describe how to compile or build all of the pieces of
a program.  For example, even without telling it specifically,
@code{make} knows that in order to go from @samp{prog.c} to
@samp{prog.o} the command @samp{cc -c prog.c} must be executed.  A
Makefile works by making such associations.  The Makefile contains a
list of all of the files which compose the program and rules as to how
to get to the finished product from the source.

The idea is that, to compile a program, we just have to type @kbd{make}.
@samp{make} then reads the Makefile and compiles all of the parts which
need compiling. It does not recompile files which have not changed since
the last compilation! How does it do this? @samp{make} works by
comparing the time-stamp on the file it needs to create with the
time-stamp on the file which is to be compiled. If the compiled version
exists and is newer than its source then the source does not need to be
recompiled.

To make this idea work in practice, @samp{make} has to know how to
go through the steps of compiling a program. Some default rules are
defined in a global configuration file, e.g.
@smallexample

/usr/include/make/default.mk

@end smallexample

@noindent
Let's consider an example of what happens for the the three files
@file{a.c}, @file{b.c} and @file{c.c} in the example above -- and
let's not worry about what the Makefile looks like yet. 

The first time we compile, only the `.c' files exist. When we type
@samp{make}, the program looks at its rules and finds that it
has to make a file called `myprog'. To make this
it needs to execute the command
@smallexample

  gcc -o myprog  a.o b.o c.o

@end smallexample

@noindent
So it looks for `a.o' etc and doesn't find them.  It now goes to a kind
of subroutine and looks to see if it has any rules for making files
called `.o' and it discovers that these are made by compiling with the
@samp{gcc -c} option. Since the files do not exist, it does this.  Now
the files `a.o b.o c.o' exist and it jumps back to the original problem
of trying to make `myprog'.  All the files it needs now exist and so it
executes the command and builds `myprog'.

If we now edit `a.c', and type @samp{make} once again -- it goes
through the same procedure as before but now it finds all of the
files. So it compares the dates on the files -- if the source
is newer than the result, it recompiles. 

By using this recursive method, @samp{make} only compiles those
parts of a program which need compiling.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Makefiles, Suffix rules for C++, Compiling large programs, Make
@subsection  Makefiles

@cindex Suffix rules in Makefiles
@cindex Dependencies in Makefiles

To write a Makefile, we have to tell @samp{make} about @emph{dependencies}.
The dependencies of a file are all of those files which are required
to build it. Thus, the dependencies of `myprog' are `a.o', `b.o'
and `c.o'. The dependencies of `a.o' are simply `a.c',
the dependencies of `b.o' are `b.c' and so on.

A Makefile consists of rules of the form:

@smallexample
target : dependencies
@key{TAB}                   rule;

@end smallexample

@noindent
The target is the thing we want to build, the dependenices are
like subroutines to be executed first if they do not exist. Finally
the rule is to be executed if all if the dependenices exist; it takes
the dependencies and turns them into the target.
There are two important things to remember:

@itemize @bullet
@item
The file names must start on the first character of
a line.
@item 
There must be a @key{TAB} character at the beginning
of every rule or action. If there are spaces instead of tabs, or no
tab at all, @samp{make} will signal an error. This bizarre feature
can cause a lot of confusion.
@end itemize

@noindent
Let's look at an example Makefile for a program which consists of two
course files @file{main.c} and @file{other.c} and which makes use of a
library called @file{libdb} which lies in the directory @file{/usr/local/lib}.
Our aim is to build a program called @code{database}:

@smallexample

#
# Simple Makefile for `database'
#

# First define a macro

OBJ = main.o other.o

CC = gcc
CFLAGS = -I/usr/local/include
LDFLAGS = -L/usr/local/lib -ldb
INSTALLDIR = /usr/local/bin

#
# Rules start here. Note that the $@@ variable becomes the name of the
# executable file. In this case it is taken from the $@{OBJ@} variable
#

database: $@{OBJ@}
          $@{CC@} -o $@@ $@{OBJ@} $@{LDFLAGS@}

#
# If a header file changes, normally we need to recompile everything.
# There is no way that make can know this unless we write a rule which
# forces it to rebuild all .o files if the header file changes...
#

$@{OBJ@}: $@{HEADERS@}

#
# As well as special rules for special files we can also define a
# "suffix rule". This is a rule which tells us how to build all files
# of a certain type. Here is a rule to get .o files from .c files.
# The $< variable is like $? but is only used in suffix rules.
#

.c.o: 
          $@{CC@} -c $@{CFLAGS@} $<


#######################################################################
# Clean up
#######################################################################

 #
 # Make can also perform ordinary shell command jobs
 # "make tidy" here performs a cleanup operation
 #

clean:
         rm -f $@{OBJ@}
         rm -f y.tab.c lex.yy.c y.tab.h
         rm -f y.tab lex.yy
         rm -f *% *~ *.o
         rm -f mconfig.tab.c mconfig.tab.h a.out
         rm -f man.dvi man.aux man.log man.toc
         rm -f cfengine.tar.gz cfengine.tar cfengine.tar.Z
         make tidy
         rm -f cfengine

install: $@{INSTALLDIR@}/database
        cp database $@{INSTALLDIR@}/database

@end smallexample

@noindent
The Makefile above can be invoked in several ways.
@smallexample

make
make database
make clean
make install

@end smallexample

@noindent
If we simple type @samp{make} i.e. the first of these choices, @samp{make}
takes the first of the rules it finds as the object to build. In this
case the rule is `database', so the first two forms above are equivalent.

On the other hand, if we type 
@smallexample
make clean
@end smallexample

@noindent
then execution starts at the rule for `clean', which is normally used
to remove all files except the original source code. Make `install'
causes the compiled program to be installed at its intended destination.

@samp{make} uses some special variables (which resemble the special
variables used in Perl -- but don't confuse them). The most useful one
is @samp{$@@} which represents the current @emph{target} -- or the
object which @samp{make} would like to compile. i.e. as @samp{make}
checks each file it would like to compile, @samp{$@@} is set to the
current filename.

@table @code

@item $@@
This evaluates to the current target i.e. the name of the object
you are currently trying to build. It is normal to use this as the
final name of the program when compiling

@item $?
This is used only outside of suffix rules and means the name of all the
files which must be compiled in order to build the current target.
@smallexample
target: file1.o file2.o
@key{TAB} cc -o $@@ $?
@end smallexample

@item $<
This is only used in suffix rules. It has the same meaning as @samp{$?}
but only in suffix rules. It stands for the pre-requisite, or the file
which must be compiled in order to make a given object.


@vindex $@@ in make
@vindex $? in make
@vindex $< in make

@end table

Note that, because @samp{make} has some default rules defined in its
configuration file, a single-file C program can be compiled
very easily by typing 
@smallexample
make filename.c
@end smallexample

@noindent
This is equivalent to
@smallexample
cc -c filename.c
cc -o filename filename.o
@end smallexample

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node Suffix rules for C++,  , Makefiles, Make
@subsection  New suffix rules for C++

Standard rules for C++ are not often built into UNIX systems at the
time of writing, but we can create them in our own Makefiles very easily.
Here we shall use the GNU compiler g++'s conventions for 
C++ files. Here is a sample Makefile for using C++. Note
that the @samp{.SUFFIXES} command must be used to declare new endings
or file extensions.
@cindex C++ suffix rules
@cindex Make rules for C++

@smallexample
##################################################################
#
# This is the Makefile for g++
#
##################################################################

OBJ = cpp-prog.o X.o Y.o Z.o

CCPLUS = g++

.SUFFIXES: .C .o .h 

#
# Program Rules
#


filesys: $@{OBJ@}
         $(CCPLUS) -o filesys $(OBJ)

#
#  Extra dependencies on the header file
# (if the header file changes, we need to rebuild *.o)
#

cpp-prog.o: filesys.h
X.o: filesys.h
Y.o: filesys.h
Z.o: filesys.h

#
# Suffix rules
#

.C.o: 
         $(CCPLUS) -c $<


@end smallexample

The general rule here tells @code{make} that a @file{.o} file
can be created from a @file{.C} file by executing the
command @samp{$(CCPLUS) -c}. (This is identical to the
C case, exept for the name of the compiler). The extra
dependencies tell @code{make} that, if we change the header
file @file{filesys.h}, then we must recompile all the files
which read in @file{filesys.h}, since this could affect all of
these. Finally, the highest level rule says that to make
@file{filesys} from the @file{.o} files, we have to run
@samp{$(CCPLUS) -o filesys *.o}.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node argv argc envp, Environment variables in C, Make, C programming
@section The @code{argv}, @code{argc} and @code{envp} paramters

When we write C programs which reads command line arguments, they are
fed to us as an array of strings called the argument vector.  The
mechanisms for the C-shell and Perl are derived from the C argument
vector.  To read in the command line, we write
@cindex The arguement vector in C
@cindex Command line arguments in C
@vindex @code{argv} in C
@vindex @code{argc} in C
@cindex @code{envp} in C
@cindex Environment variables in C

@smallexample

main (argc,argv,envp)

int argc;
char *argv[], *envp[];

@{
printf ("The first argument was %s\n",argv[1]);
@}
@end smallexample

@noindent
Argument zero is the name of the program itself and @samp{argv[argc-1]}
is the last argument. The above definitions are in Kernighan and Ritchie
C style. In ANSI C, the arguments can be declared using prototype:

@smallexample
main (int argc, char **argv)

@{

@}
@end smallexample

@noindent
The array of strings @samp{envp[]} is a list of values of the
@emph{environment variables} of the system, formatted by
@smallexample
NAME=value
@end smallexample

@noindent
This gives C programmers access to the shell's global environment.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Environment variables in C, C files and dirs, argv argc envp, C programming
@section Environment variables in C

@cindex Environment variables in C
@cindex @code{getenv() function}
@vindex @code{getenv()}

In addition to the @samp{envp} vector, it is possible to access the
environment variables through the call @samp{getenv()}. This is used as
follows; suppose we want to access the shell environment variable @samp{$HOME}.
@smallexample
char *string;

string = getenv("HOME");
@end smallexample

@noindent
@samp{string} is now a pointer to static but public data. You should not
use @samp{string} as if it were you're own property because it will be
used again by the system. Copy it's contents to another string before
using the data.
@smallexample
char buffer[500];

strcpy (buffer,string);
@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node C files and dirs, File test macros, Environment variables in C, C programming
@section Files and directories

All of the regular C functions from the standard library are available
to Unix programmers. The standard functions only address the issue
of reading and writing to files however, they do not deal with operating
system specific attributes such as file permissions and file types.
Nor is there a mechanisms for obtaining lists of files within a
directory. The reason for these omissions is that they are operating
system dependent. To find out about these other attributes POSIX describes
some standard Unix system calls.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* opendir and readir::          
* stat::                        
* lstat and readlink::          
@end menu

@node opendir and readir, stat, C files and dirs, C files and dirs
@subsection  opendir, readdir

@cindex @code{opendir} command
@cindex @code{closedir} command
@cindex @code{readdir} command
@cindex dirent directory interface

Files and directories are handled by functions defined in the header
file @file{dirent.h}. In earlier UNIX systems the file @file{dir.h} was
used -- and the definitions were slightly different, but not much. To
get a list of files in a directory we must open the directory and read
from it -- just like a file. (A directory is just a file which contains
data on its entries). The commands are
@smallexample
opendir
closedir
readdir
@end smallexample

@noindent
See the manual pages for dirent.  These functions return pointers to a
@code{dirent} structure which is defined in the file
@file{/usr/include/dirent.h}. Here is an example @code{ls} command
which lists the contents of the directory @file{/etc}. This header
defines a structure

@smallexample

struct dirent 
   @{
   off_t                d_off;		/* offset of next disk dir entry */
   unsigned long        d_fileno;	/* file number of entry */
   unsigned short       d_reclen;	/* length of this record */
   unsigned short       d_namlen;	/* length of string in d_name */
   char	                d_name[255+1];	/* name (up to MAXNAMLEN + 1) */
   @};

@end smallexample
@noindent
which can be used to obtain information from the directory nodes.

@smallexample

#include <stdio.h>
#include <dirent.h>

main ()

@{ DIR *dirh;
  struct dirent *dirp;
  static char mydir[20] = "/etc";
  
if ((dirh = opendir(mydir)) == NULL)
   @{
   perror("opendir");
   return;
   @}

for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
   @{
   printf("Got dir entry: %s\n",dirp->d_name);
   @}

closedir(dirh);
@}

@end smallexample
@noindent
Notice that reading from a directory is like reading from a file
with @code{fgets()},
but the entries are filenames rather than lines of text.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node stat, lstat and readlink, opendir and readir, C files and dirs
@subsection @code{stat()}


@cindex Information about file properties
@cindex Statistics about a file
@cindex @code{stat()}
@cindex @code{lstat()}

To determine the file properties or @emph{statistics} we use the
function call @samp{stat()} or its corollory @samp{lstat()}. Both these
functions find out information about files (permissions, owner, filetype
etc).  The only difference between them is the way in which they treat
symbolic links.  If @samp{stat} is used on a symbolic link, it stats the
file the link points to rather than the link itself. If @samp{lstat} is
used, the data refer to the link.  Thus, to detect a link, we must use
@samp{lstat}, @xref{lstat and readlink}.

The data in the `stat' structure are defined in the file
@file{/usr/include/sys/stat.h}.  Here are the most important structures.

@smallexample

struct	stat 
   @{
   dev_t        st_dev;             /* device number*/
   ino_t        st_ino;             /* file inode */
   mode_t       st_mode;            /* permission */
   short        st_nlink;           /* Number of hardlinks to file */
   uid_t        st_uid;             /* user id */
   gid_t        st_gid;             /* group id */
   dev_t        st_rdev; 
   off_t        st_size;            /* size in bytes */
   time_t       st_atime;           /* time file last accessed */
   time_t       st_mtime;           /* time file contents last modified */
   time_t       st_ctime;           /* time last attribute change */
   long         st_blksize;
   long         st_blocks;
   @};

@end smallexample


@c .....................................................
@c SUBSECTION
@c .....................................................
 
@node lstat and readlink,  , stat, C files and dirs
@subsection  lstat and readlink

@cindex @code{readlink()}
@cindex Links, where do they point?
@cindex Links in C

The function @samp{stat()} treats symbolic links as though they
were the files they point to. In other words, if we use @samp{stat()}
to read a symbolic link, we end up reading the file the link points
to and not the link itself---
we never see symbolic links. To avoid this problem, there is a different
version of the stat function called @samp{lstat()} which is identical
to @samp{stat()} except that it treats links as links and @emph{not} as
the files they point to. This means that we can test whether a file is a
symbolic link, only if we use @samp{lstat()}. (See the next paragraph.)

Once we have identified a file to be a symbolic link, we use the
@samp{readlink()} function to obtain the name of the file the
link points to.
@smallexample

#define bufsize 512
char buffer[bufsize];

readlink("/path/to/file",buffer,bufsize);

@end smallexample

@noindent
The result is returned in the string buffer.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node File test macros, Process control, C files and dirs, C programming
@section @code{stat()} test macros

@cindex Macros for stat
@cindex Permissions, determining in C
@cindex File type, determining in C

As we have already mentioned, the Unix mode bits contain not only
information about what permissions a file has, but also bits describing the
type of file -- whether it is a directory or a link etc. There are macros
defined in UNIX to extract this information from the @samp{st_mode}
member of the @samp{stat} structure. They are defined in the @samp{stat.h}
headerfile. Here are some examples.

@smallexample
#define	S_ISBLK(m)    /* is block device */
#define	S_ISCHR(m)    /* is character device */
#define	S_ISDIR(m)    /* is directory */
#define	S_ISFIFO(m)   /* is fifo pipe/socket */
#define	S_ISREG(m)    /* is regular (normal) file */

#define	S_ISLNK(m)    /* is symbolic link */  /* Not POSIX */
#define	S_ISSOCK(m)   /* is a lock */


#define	S_IRWXU 	/* rwx, owner */
#define		S_IRUSR /* read permission, owner */
#define		S_IWUSR /* write permission, owner */
#define		S_IXUSR	/* execute/search permission, owner */
#define	S_IRWXG		/* rwx, group */
#define		S_IRGRP	/* read permission, group */
#define		S_IWGRP	/* write permission, grougroup */
#define		S_IXGRP	/* execute/search permission, group */
#define	S_IRWXO		/* rwx, other */
#define		S_IROTH	/* read permission, other */
#define		S_IWOTH	/* write permission, other */
#define		S_IXOTH	/* execute/search permission, other */

@end smallexample
These return true or false when acting on the mode member.
Here is an example @xref{readdir example}.
@smallexample

struct stat statvar;

stat("file",&statvar); 

/* test return values */

if (S_ISDIR(statvar.st_mode))
   @{
   printf("Is a directory!");
   @}

@end smallexample


@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* readdir example::             
@end menu

@node readdir example,  , File test macros, File test macros
@subsection Example filing program

The following example program demonstrates the use of the directory
functions in @code{dirent} and the @code{stat} function call.

@smallexample
/********************************************************************/
/*                                                                  */
/* Reading directories and `statting' files                         */
/*                                                                  */
/********************************************************************/

#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>


#define DIRNAME "/."
#define bufsize 255

/********************************************************************/

main ()


@{ DIR *dirh;
  struct dirent *dirp;
  struct stat statbuf;
  char *pathname[bufsize];
  char *linkname[bufsize];
 
if ((dirh = opendir(DIRNAME)) == NULL)
   @{
   perror("opendir");
   exit(1);
   @}
 
for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
   @{
   if (strcmp(".",dirp->d_name) == 0 || strcmp("..",dirp->d_name) == 0)
      @{
      continue;
      @}
 
   if (strcmp("lost+found",dirp->d_name) == 0)
      @{
      continue;
      @}

   sprintf(pathname,"%s/%s",DIRNAME,dirp->d_name);

   if (lstat(pathname,&statbuf) == -1)                /* see man stat */
     @{
     perror("stat");
     continue;
     @}

   if (S_ISREG(statbuf.st_mode))
      @{
      printf("%s is a regular file\n",pathname);
      @};

   if (S_ISDIR(statbuf.st_mode))
      @{
      printf("%s is a directory\n",pathname);
      @}

   if (S_ISLNK(statbuf.st_mode))
      @{
      bzero(linkname,bufsize);                         /* clear string */
      readlink(pathname,linkname,bufsize);
      printf("%s is a link to %s\n",pathname,linkname);
      @}

   printf("The mode of %s is %o\n\n",pathname,statbuf.st_mode & 07777);
   @}

closedir(dirh);
@}

@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Process control, A more secure popen, File test macros, C programming
@section Process control, @code{fork()}, @code{exec()}, @code{popen()} and system

There is a number of ways in which processes can interact with one
another and in which we can control their behaviour. We shall not go
into great detail in this course, only provide examples for
reference. 

The UNIX @samp{fork()} function is used to create child processes.  
This is the basis of all `heavyweight' multitasking under unix.
Here is a simple example of fork in which we start a child process
from within a program and wait for it to finish. Note that
the code for the parent and the child is is the same file. The
only thing that distinguishes parent from child is the value
returned by the fork function.

When @samp{fork()} is called, it duplicates the entire current
process so that two parallel processes are then running. The only
difference between these is that the child process (the copy)
gets a return value of zero from @samp{fork()}, whereas the
parent gets a return value equal to the process identifier
(pid) of the child. This value can be used by the parent
to send messages or to wait for the child. Here we show a
simple example in which the @samp{wait(NULL)} command is used
to wait for the last child spawned by the parent.

@smallexample
/**************************************************************/
/*                                                            */
/*  A brief demo of the UNIX process duplicator fork().       */
/*                                                            */
/**************************************************************/

#include <stdio.h>


/***************************************************************/

main ()

@{ int pid, cid;

pid = getpid();

printf ("Fork demo! I am the parent (pid = %d)\n",pid);

if (! fork())
   @{
   cid = getpid();
   printf ("I am the child (cid = %d) of (pid=%d)\n",cid,pid);
   ChildProcess();
   exit(0);
   @}


printf("Parent waiting here for the child...\n");

wait(NULL);

printf("Child finished, parent quitting too!\n");
@}

/**************************************************************/

ChildProcess()

@{ int i;

for (i = 0; i < 10; i++)
   @{
   printf ("%d...\n",i);
   sleep(1);
   @}
@}

@end smallexample

Another possibility is that we might want to execute a program and
wait to find out what the result of the program is before
continuing. There are two ways to do this. The first is a variation
on the theme above and uses @code{fork()}.

Let's create a function which runs a shell command from within
a C program, and determines its return value. We make the 
result a boolean (integer) value, so that the function returns
`true' if the shell command exits normally, @xref{Return codes}.

@smallexample
if (ShellCommandReturnsZero(@var{shell-command}))
   @{
   printf ("Command %s went ok\n",@var{shell-command});
   @}

@end smallexample

@noindent
To do this we first have to fork a new process and then
use one of the @code{exec} commands to load a new
code image on top of the new process.
@cindex Starting
shell commands from C This sounds complicated, but it is necessary
because of the way unix handles processes.  If we had no use for the
return value, we could simply execute a shell command using the
@code{system("shell command")} function, (which does all this for us)
but when @code{system()} exits, we can only tell if the command was
executed successfully or unsuccessfully---we learn nothing about what
actually failed (the shell or command which was executed under the
shell?)  If we require detailed information about what happened to the
child process then we need to do the following.

@smallexample
#include <sys/types.h>
#include <sys/wait.h>

  /* Send complete command as a string */
  /* including all arguments           */

ShellCommandReturnsZero(comm)

char *comm;

@{ int status, i, argc;
  pid_t pid;
  char arg[maxshellargs][bufsize];
  char **argv;

/* Build argument array for execv call*/

for (i = 0; i < maxshellargs; i++)
   @{
   bzero (arg[i],bufsize);
   @}

argc = SplitCommand(comm,arg);

if ((pid = fork()) < 0)
   @{
   FatalError("Failed to fork new process");
   @}
else if (pid == 0)                     /* child */
   @{
   argv = malloc((argc+1)*sizeof(char *));

   for (i = 0; i < argc; i++)
      @{
      argv[i] = arg[i];
      @}

   argv[i] = (char *) NULL;

   if (execv(arg[0],argv) == -1)
      @{
      yyerror("script failed");
      perror("execvp");
      exit(1);
      @}
   @}
else                                    /* parent */
   @{
   if (wait(&status) != pid)
      @{
      printf("Wait for child failed\n");
      perror("wait");
      return false;
      @}
   else
      @{
      if (WIFSIGNALED(status))
         @{
         printf("Script %s returned: %s\n",comm,WTERMSIG(status));
         return false;
         @}

      if (! WIFEXITED(status))
         @{
         return false;
         @}

      if (WEXITSTATUS(status) == 0)
         @{
         return true;
         @}
      else
         @{
         return false;
         @}
      @}
   @}

@}

/*******************************************************************/

SplitCommand(comm,arg)
 
char *comm, arg[maxshellargs][bufsize];
 
@{ char *sp;
  int i = 0, j;
  char buff[bufsize];
 
for (sp = comm; *sp != NULL; sp++)
   @{
   bzero(buff,bufsize);
 
   if (i >= maxshellargs-1)
      @{
      yyerror("Too many arguments in embedded script");
      FatalError("Use a wrapper");
      @}
 
   while (*sp == ' ' || *sp == '\t')
      @{
      sp++;
      @}
 
   switch (*sp)
      @{
      case '\"': sscanf (++sp,"%[^\"]",buff);
                 break;
      case '\'': sscanf (++sp,"%[^\']",buff);
                 break;
      default:   sscanf (sp,"%s",buff);
                 break;
      @}
 
   for (j = 0; j < bufsize; j++)
      @{
      arg[i][j] = buff[j];
      @}
 
   sp += strlen(arg[i]);
   i++;
   @}
return (i);
@}

@end smallexample

@noindent
In this example, the script waits for the exit signal from the child
process before continuing. The return value from the child is
available from the wait function with the help of a set of macros
defined in @file{/usr/include/sys/wait.h}. The value is
given by @code{WTERMSIG(status)}.
@cindex Waiting for child processes
@cindex @file{wait.h}
@cindex @code{WTERMSIG(status)}

In the final example, we can open a pipe to a
process directly in a C program
as though it were a file, by using the function @code{popen()}.
@cindex @code{popen()}
@cindex Pipes in C
@cindex Opening a pipe in C
Pipes may be opened for reading or for writing, in exactly the same
way as a file is opened. The child process is automatically
synchronized with the parent using this method. Here is a 
program which opens a unix command for reading (both stdout and
stderr) from the child process are piped into the program.
Notice that the syntax used in this call is that used by
the Bourne shell, since this is build deeply into the unix
execution design.

@smallexample

#define bufsize 1024

FILE *pp;
char VBUFF[bufsize];

...

if ((pp = popen( "/sbin/mount -va 2<&1","r")) == NULL)
   @{
   printf("Failed to open pipe\n");
   return errorcode;
   @}
 
while (!feof(pp))
   @{
   fgets(VBUFF,bufsize,pp);

   /* Just write the output to stdout */

   printf ("Pipe read: %s\n",VBUFF);
   @}
 
pclose(pp);


@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node A more secure popen, Traps and signals, Process control, C programming
@section A more secure @code{popen()}

One problem with the @code{popen()} system call is that it uses a
shell to execute the command it obtains a pipe to. In the past this
has been used to allow Unix security breaches, using a so-called 
@code{IFS} attack which can trick the shell into executing a program with
the name of the first node in the directory of the executable. For instance,if the pipe was to open the program @file{/bin/ps}, this coudl be tricked
into executing a program in the current working directory of the process
called @file{bin} with argument @samp{ps}.

The solution is not to use a shell at all, but to replace @code{popen()}
with a version which calls @code{exec()} directly. Here is a safe
version from the source code of cfengine:

@smallexample

#define bufsize      4096
#define maxshellargs 20

pid_t *CHILD;
int    MAXFD = 20; /* Max number of simultaneous pipes */

/***************************************************************/

FILE *cfpopen(command, type)
    
char *command, *type;

 @{ char arg[maxshellargs][bufsize];
   int i, argc, pd[2];
   char **argv;
   pid_t pid;
   FILE *pp = NULL;

 if ((*type != 'r' && *type != 'w') || (type[1] != '\0'))
    @{
    errno = EINVAL;
    return NULL;
    @}
 
 if (CHILD == NULL)   /* first time */
    @{
    if ((CHILD = calloc(MAXFD,sizeof(pid_t))) == NULL)
       @{
       return NULL;
       @}
    @}

 if (pipe(pd) < 0)  /* Create a pair of descriptors to this process */
    @{
    return NULL;
    @}

 if ((pid = fork()) == -1)
    @{
    return NULL;
    @}
 
 if (pid == 0)
    @{
    switch (*type)
       @{
       case 'r':

                 close(pd[0]);        /* Don't need output from parent */

                 if (pd[1] != 1)
                    @{
                    dup2(pd[1],1);    /* Attach pp=pd[1] to our stdout */
                    dup2(pd[1],2);    /* Merge stdout/stderr */
                    close(pd[1]);
                    @}

                 break;

       case 'w':

                 close(pd[1]);

                 if (pd[0] != 0)
                    @{
                    dup2(pd[0],0);
                    close(pd[0]);
                   @}
       @}

    for (i = 0; i < MAXFD; i++)
       @{
       if (CHILD[i] > 0)
          @{
          close(CHILD[i]);
          @}

       argc = SplitCommand(command,arg);
       argv = (char **) malloc((argc+1)*sizeof(char *));

       if (argv == NULL)
          @{
          FatalError("Out of memory");
          @}
       
       for (i = 0; i < argc; i++)
          @{
          argv[i] = arg[i];
          @}

       argv[i] = (char *) NULL;

       if (execv(arg[0],argv) == -1)
          @{
          sprintf(OUTPUT,"Couldn't run %s",arg[0]);
          CfLog(cferror,OUTPUT,"execv");
          @}

       _exit(1);
       @}
    @}
 else
    @{
    switch (*type)
       @{
       case 'r':

                 close(pd[1]);
      
                 if ((pp = fdopen(pd[0],type)) == NULL)
                    @{
                    return NULL;
                    @}
                 break;
      
       case 'w':

                 close(pd[0]);
      
                 if ((pp = fdopen(pd[1],type)) == NULL)
                    @{
                    return NULL;
                    @}
       @}

    CHILD[fileno(pp)] = pid;
    return pp;
    @}
 @}


/***************************************************************/

cfpclose(pp)

FILE *pp;

@{ int fd, status;
  pid_t pid;

Debug("cfpclose(pp)\n");

if (CHILD == NULL)  /* popen hasn't been called */
   @{
   return -1;
   @}

fd = fileno(pp);

if ((pid = CHILD[fd]) == 0)
   @{
   return -1;
   @}

CHILD[fd] = 0;

if (fclose(pp) == EOF)
   @{
   return -1;
   @}

Debug("cfpopen - Waiting for process %d\n",pid); 

#ifdef HAVE_WAITPID

while(waitpid(pid,&status,0) < 0)
   @{
   if (errno != EINTR)
      @{
      return -1;
      @}
   @}
 
 return status; 
 
#else
      
 if (wait(&status) != pid)
    @{
    return -1;
    @}
 else
    @{
    if (WIFSIGNALED(status))
       @{
       return -1;
       @}
    
    if (! WIFEXITED(status))
       @{
       return -1;
       @}
    
    return (WEXITSTATUS(status));
    @}
#endif
@}

/*******************************************************************/
/* Command exec aids                                               */
/*******************************************************************/

SplitCommand(comm,arg)

char *comm, arg[maxshellargs][bufsize];

@{ char *sp;
  int i = 0, j;
  char buff[bufsize];

for (sp = comm; sp < comm+strlen(comm); sp++)
   @{
   bzero(buff,bufsize);

   if (i >= maxshellargs-1)
      @{
      CfLog(cferror,"Too many arguments in embedded script","");
      FatalError("Use a wrapper");
      @}

   while (*sp == ' ' || *sp == '\t')
      @{
      sp++;
      @}

   switch (*sp)
      @{
      case '\0': return(i-1);

      case '\"': sscanf (++sp,"%[^\"]",arg[i]);
                 break;
      case '\'': sscanf (++sp,"%[^\']",arg[i]);
                 break;
      case '`':  sscanf (++sp,"%[^`]",arg[i]);
                 break;
      default:   sscanf (sp,"%s",arg[i]);
                 break;
      @}

   sp += strlen(arg[i]);
   i++;
   @}

return (i);
@}

@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Traps and signals, Regular expressions in C, A more secure popen, C programming
@section Traps and signals

Processes can receive signals from the UNIX kernel at any time.
Some of these signals terminate the execution of the program.
This can cause problems if the program is in the middle of critical
activity such as writing to a file. For that reason we can trap
signals and provide our own routine for handling them in a special way.

A signal handler is made by calling the function @samp{signal()} for
each signal and by specifying a pointer to a function which will be
called in the event of a signal. For example:
@smallexample

main ()

@{ int HandleSignal();

signal(SIGTERM,HandleSignal);
@}


HandleSignal()

@{
/* Tidy up and exit cleanly */

exit(0);
@}

@end smallexample
@samp{SIGTERM} is the usual signal sent by the command @samp{kill}. There are
many other signals which can be sent to programs. Here is list.
You have to decide for yourself whether or not you want to
provide your own signal handling function.
To ignore a signal, you write
@smallexample

signal(SIG@var{type},SIG_IGN);

@end smallexample
@noindent
To remove a signal handler and re-activate a signal, you write
@smallexample

signal(SIG@var{type},SIG_DFL);

@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Regular expressions in C, DES encryption, Traps and signals, C programming
@section Regular expressions

A regular expression is a pattern for matching strings of text.
We have met regular expressions earlier in connection with the
shell and Perl. Naturally these earlier encounters have their
roots in C functions for handling expressions. A regular
expression is used by first `compiling' it into a convenient
data structure. Then a matching function is used to compare the
expression with a test string. In this example program we show
how a regular expression typed in as an argument to the program
is found within strings of input entered on the keyboard.


@smallexample

#include <stdio.h>
#include <regex.h>

main (argc,argv)

int argc;
char **argv;

@{
 char buffer[1024];
 regex_t rx;
 regmatch_t match;
 size_t nmatch = 1;

 if (regcomp(&rx, argv[1], REG_EXTENDED) != 0)
    @{
    perror("regcomp");
    return;
    @}

 while (!feof(stdin))
    @{
    fgets(buffer,1024,stdin);
    
    if (regexec(&rx,buffer,1,&match,0) == 0)
       @{
       printf("Matched:(%s) at %d to %d",buffer,match.rm_so,match.rm_eo);
       @}

    @}

regfree(&rx);
@}

@end smallexample

Here is an example of its use. The
output of the program is in @emph{italics} 

@smallexample

% a.out xyz
this is a string
another string
an xyz string
@emph{Matched: (an xyz string
) at 3 to 6}
another xyz zyxxyz string
@emph{Matched: (another xyz xyz string
) at 8 to 11}

% a.out 'xyz|abc'
This is a string
An abc string
@emph{Matched: (An abc string
) at 3 to 6}
Or an xyz string
@emph{Matched: (Or an xyz string
) at 6 to 9}

@end smallexample
If you don't want the match data set @code{&pm} to @code{NULL}. To get
an exact match rather than a substring check that the bounds are 0 and
@code{strlen(argv[1])-1}.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node DES encryption, ioctl, Regular expressions in C, C programming
@section DES encryption

Encryption with the SSLeay library, compile with command

@smallexample

  gcc crypto.c -I/usr/local/ssl/include -L/usr/local/ssl/lib -lcrypto

@end smallexample
Example of normal triple DES encryption which works only on an 8-byte
buffer:
@smallexample

/*****************************************************************************/
/*                                                                           */
/* File: crypto.c                                                            */
/*                                                                           */
/* Compile with:  gcc program.c  -lcrypto   (SSLeay)                         */
/*                                                                           */
/*****************************************************************************/

#include <stdio.h>
#include <des.h>

#define bufsize 1024

    /* Note how this truncates to 8 characters */

main ()

@{ char in[bufsize],out[bufsize],back[bufsize];
  des_cblock key1,key2,key3,seed = @{0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10@};
  des_key_schedule ks1,ks2,ks3;

strcpy(in,"1 2 3 4 5 6 7 8 9 a b c d e f g h i j k");

des_random_seed(seed);

des_random_key(key1);
des_random_key(key2);
des_random_key(key3);
 
des_set_key((C_Block *)key1,ks1);
des_set_key((C_Block *)key2,ks2);
des_set_key((C_Block *)key3,ks3);
des_ecb3_encrypt((C_Block *)in,(C_Block *)out,ks1,ks2,ks3,DES_ENCRYPT);

printf("Encrypted [%s] into [%s]\n",in,out);

des_ecb3_encrypt((C_Block *)out,(C_Block *)back,ks1,ks2,ks3,DES_DECRYPT);

printf("and back to.. [%s]\n",back); 
@}

@end smallexample
Triple DES, chaining mode, for longer strings (which must be a multiple of
8 bytes):
@smallexample

/*****************************************************************************/
/*                                                                           */
/* File: crypto.c                                                            */
/*                                                                           */
/* Compile with:  gcc program.c  -lcrypto   (SSLeay)                         */
/*                                                                           */
/*****************************************************************************/

#include <stdio.h>
#include <des.h>

#define bufsize 1024

    /* This can be used on arbitrary length buffers */

main ()

@{ char in[bufsize],out[bufsize],back[bufsize],workvec[bufsize];
  des_cblock key1,key2,key3,seed = @{0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10@};
  des_key_schedule ks1,ks2,ks3;

strcpy(in,"1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z");

des_random_seed(seed);

des_random_key(key1);
des_random_key(key2);
des_random_key(key3);
 
des_set_key((C_Block *)key1,ks1);
des_set_key((C_Block *)key2,ks2);
des_set_key((C_Block *)key3,ks3);

/* This work vector can be intialized t anything ...*/

memset(workvec,0,bufsize);

des_ede3_cbc_encrypt((C_Block *)in,(C_Block *)out,(long)strlen(in),
           ks1,ks2,ks3,(C_Block *)workvec,DES_ENCRYPT);

printf("Encypted [%s] into [something]\n",in);

/* .. but this must be initialized the same as above */

memset(workvec,0,bufsize);

/* Note that the length is the original length, not strlen(out) */

des_ede3_cbc_encrypt((C_Block *)out,(C_Block *)back,(long)strlen(in),
           ks1,ks2,ks3,(C_Block *)workvec,DES_DECRYPT);

printf("and back to.. [%s]\n",back); 
@}





@end smallexample


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node ioctl, Database example in C, DES encryption, C programming
@section Device control: ioctl
@cindex @code{ioctl()}
@vindex ioctl()

The C function @samp{ioctl} (I/O control) is used to send special
control commands to devices like the disk and the network interface.
The syntax of the function is
@smallexample
int ioctl(fd, request, arg)
int fd, request;
long arg;
@end smallexample

@noindent
The first parameter is normally as device handle or socket descriptor.
The second is a control parameter. Lists of valid control parameters are
normally defined in the system `include' files for a particular
device. They are device and system dependent so you need a local manual
and som detective work to find out what they are.
 The final parameter is a pointer to a variable which
receives return data from the device.

@samp{ioctl} commands are device specific, by their nature. The commands
for the ethernet interface device are only partially standardized, for
example.  We could read the ethernet device (which is called `le0' on a
Sun workstation), using the following command:
@smallexample

# include <sys/socket.h>      /* Typical includes for internet */
# include <sys/ioctl.h>
# include <net/if.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <netdb.h>
# include <sys/protosw.h>
# include <net/route.h>

struct ifreq IFR;
int sk;
struct sockaddr_in sin;

strcpy(IFR.ifr_name,"le0");
IFR.ifr_addr.sa_family = AF_INET;

if ((sk = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP)) == -1)
   @{
   perror("socket");
   exit(1);
   @}

if (ioctl(sk,SIOCGIFFLAGS, (caddr_t) &IFR) == -1) 
   @{
   perror ("ioctl");
   exit(1);
   @}
@end smallexample

We shall not go into the further details of @samp{ioctl}, but simply note
its role in system programming.



@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Database example in C, lex and yacc, ioctl, C programming
@section Database example (Berkeley db)

@smallexample

DBT key,value;
DB *dbp;
DBC *dbcp;
db_recno_t recno;

if ((errno = db_open(CHECKSUMDB,DB_BTREE, DB_CREATE, 0664, NULL, NULL, &dbp)) != 0)
   @{
   sprintf(OUTPUT,"cfd: couldn't open checksum database %s\n",CHECKSUMDB);
   CfLog(cferror,OUTPUT,"db_open");
   return false;
   @}
 
bzero(&value,sizeof(value)); 
bzero(&key,sizeof(key));       
      
key.data = filename;
key.size = strlen(filename)+1;
value.data = dbvalue;
value.size = sizeof(dbvalue); 
   
if ((errno = dbp->del(dbp,NULL,&key,0)) != 0)
   @{
   CfLog(cferror,"","db_store");
   @}
  
key.data = filename;
key.size = strlen(filename)+1;
   
if ((errno = dbp->put(dbp,NULL,&key,&value,0)) != 0)
   @{
   CfLog(cferror,"put failed","db->put");
   @}      

if ((errno = dbp->get(dbp,NULL,&key,&value,0)) == 0)
   @{
   /* Not found ... */
   return;
   @}

dbp->close(dbp,0);

@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node lex and yacc, Ex 6, Database example in C, C programming
@section Text parsing tools: @samp{lex} and @samp{yacc}

@cindex Lexer
@cindex Parser
@cindex @samp{yacc}

@emph{This section is a taster only. You only need to know what lex and
yacc are, not how they work.}

@samp{lex} and @samp{yacc} are two tools for the C programmer who wishes
to make a text parser. A text parser is a program which reads a text file
and interprets the symbols in it. Every programming language must
include a text parser, for instance.

The @samp{yacc} (yet another compiler compiler) program generates C
code which parses a textfile, given a description of the syntax
rules for the file. In other words, we define the logical structure
of the text file, according to the way we wish to interpret it
and give the rules to @samp{yacc}. @samp{yacc} produces C code
from this which does the job.

@samp{lex} is a `lexer'. It is normally used together with @samp{yacc}. 
@samp{lex} @emph{tokenizes} or identifies symbols in
a file. What that means is that it reads in a file and matches
@emph{types} of string in the file which are defined in terms of
regular expressions by the programmer, and returns symbolic
values for those strings.

Although @samp{lex} can be used by independently of @samp{yacc}, it
is normally used to identify the different @emph{types} of string which
define the syntax of a file. For example, suppose @samp{yacc} 
was parsing a C program. On the beginning of a line, it
might expect to find either a variable name or a preprocessor symbol.
A variable name is just a string consisting of characters from
the set @samp{0-9a-Z_}, whereas a preprocessor command always 
starts with the character @samp{#}. @samp{yacc} passes control to @samp{lex}
which reads the file and matches the first object on the line.
If it finds a variable, it returns to @samp{yacc} a @emph{token} 
which is a number or value
corresponding to `variable'. Similarly, if it finds a preprocessor
command, it returns a token for that. If it doesn't match either
type it returns something else and @samp{yacc} signals a syntax error.

Here is a @samp{yacc} file which parses a file 
consisting of lines of the form
a+b, where $a$ and $b$ are numbers -- 
any other syntax is incorrect.
We could have used this later in the example
program for the client-server example, @xref{Sockets}.

You can learn more about lex and yacc in @emph{"Lex and Yacc", J. Levine,
T. Mason and D. Brown, O'Reilly and Assoc.}

@smallexample
%@{
/*******************************************************************/
/*                                                                 */
/*  PARSER for a + b protocol                                      */
/*                                                                 */
/* The section between the single %'s gets copied verbatim into    */
/* the resulting C code yacc generates -- including this comment!  */
/*                                                                 */
/*******************************************************************/

#include <stdio.h>

extern char *yytext;

%@}

%token NUMBER PLUS

%%

specification:       @{ yyerror("Warning: invalid statement");@}
                     | statement;

statement:            NUMBER PLUS NUMBER;

@end smallexample

@noindent
The lexer to go with this parser generates the tokens NUMBER and PLUS
used by @samp{yacc}:

@smallexample
%@{
/*******************************************************************/
/*                                                                 */
/*  LEXER for a + b protocol                                       */
/*                                                                 */
/* Returns token types NUMBER and PLUS to yacc, one at a time      */
/*                                                                 */
/*******************************************************************/


#include "y.tab.h"       /* yacc produces this -- need this line! */


%@}


number    [0-9]+
plus      [+]

%%


number                 @{
                       return NUMBER;
                       @}

plus                   @{
                       return PLUS;
                       @}

.                      @{
                       return yytext[0];
                       @}

%%

/* EOF */

@end smallexample

The main program which uses @samp{yacc} and @samp{lex} looks like this:

@smallexample

extern FILE *yyin;

main ()

@{

if ((yyin = fopen("My_Input_File","r")) == NULL)      /* Open file */
   @{
   printf("Can't open file\n");
   exit (1);
   @}

while (!feof(yyin))
   @{ 
   yyparse();
   @}

fclose (yyin);
@}
@end smallexample




@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Ex 6,  , lex and yacc, C programming
@section Exercises

@enumerate

@item 
Write a daemon program with a signal handler which makes a log
of the heaviest (maximum cpu) process running, every five minutes. The
program should exit if the log file becomes greater than 5-kbytes.

@item
Rewrite in C the perl program which lists all the files in
the current directory containing a certain string.

@item
Write a version of `more' which prints control characters safely.
See the @samp{cat -e} command.

@item
Write a Makefile to create a shared library from a number of object files.

@end enumerate

@c **********************************************************************
@c CHAPTER
@c **********************************************************************

@node Network programming, Programming idioms, C programming, Top
@chapter Network Programming

Client-server communication is the basis of modern operating system
technology. The Unix socket mechanism makes stream-based communication
virtually transparent.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@menu
* Sockets::                     
* Multithreading a server::     
* System databases::            
* DNS::                         
* C and NFS::                   
* Ex 7::                        
@end menu

@node Sockets, Multithreading a server, Network programming, Network programming
@section Socket streams

Analogous to filestreams are @emph{sockets} or TCP/IP @emph{network
connections}. A socket is a two-way (read/write) pseudo-file node. An
open socket stream is like an open file-descriptor.  Berkeley sockets
are part of the standard C library.

There are two main kinds of socket: TCP/IP sockets and Unix domain
sockets.  Unix sockets can be used to provide local interprocess
communication using a filestream communication protocol. TCP/IP sockets
open file descriptors across the network.
@cindex Sockets
@cindex TCP/IP
@cindex @code{INADDR_ANY}
A TCP/IP socket is
a file stream associated with an IP address and a port number.
We write to a socket descriptor just as with a file descriptor, either
with @code{write()} or using @code{send()}.

When sending binary data over a network we have to be careful about
machine level representations of data.
Operating systems (actually the hardware they run on) fall into
two categories known as @emph{big endian} and @emph{little endian}. The
names refer to the @emph{byte-order} of numerical representations.
@cindex Byte order
@cindex Network byte order
@cindex Big endian
@cindex Little endian
The names indicate how large integers (which require say 32 bits or more)
are stored in memory. Little endian systems store the least significant byte
first, while big endian systems store the most significant byte first.
For example, the representation of the number 34,677,374 has either of
these forms.

@smallexample

          -----------------------------------
  Big    |   2    |   17   |  34    |   126  |
          -----------------------------------

          -----------------------------------
  Little |   126  |   34   |  17    |   2    |
          -----------------------------------

@end smallexample

Obviously if we are transferring data from one host to another, both
hosts have to agree on the data representation otherwise there would be
disastrous consequences. This means that there has to be a common
standard of @emph{network byte ordering}.  For example, Solaris (SPARC
hardware) uses network byte ordering (big endian), while GNU/Linux
(Intel hardware) uses the opposite (little endian). This means that
Intel systems have to convert the format every time something is
transmitted over the network. Unix systems provide generic functions
for converting between host-byteorder and network-byteorder for small
and long integer data:
@smallexample

   htonl,  htons,  ntohl, ntohs

@end smallexample
@noindent
Here we list two example programs which show how to make a client-server
pair.  The server enters a loop, and listens for connections from any
clients (the generic address @samp{INADDR_ANY} is a wildcard for any
address on the current local network segment). The client program sends
requests to the server as a protocol in the form of a string of the type
@samp{a + b}. Normally @samp{a} and @samp{b} are numbers, in which case
the server returns their sum to the client.  If the message has the
special form @samp{halt + *}, where the star is arbitrary, then the
server shuts down. Any other form of message results in an error, which
the server signals to the client.

The basic structure of the client-server components in terms of
system calls is this:

@smallexample

Client:

  socket()             @var{Create a socket}
  connect()            @var{Contact a server socket (IP + port)}

    while (?)
       @{
       send()          @var{Send to server}
       recv()          @var{Receive from server}
       @}

Server:

   socket()            @var{Create a socket}
   bind()              @var{Associates the socket with a fixed address}
   listen()            @var{Create a listen queue}

   while()
      @{
      reply=accept()   @var{Accept a connection request}
      recv()           @var{Receive from client}
      send()           @var{Send to client}
      @}

@end smallexample
 
@smallexample
/**********************************************************************/
/*                                                                    */
/* The client part of a client-server pair. This simply takes two     */
/* numbers and adds them together, returning the result to the client */
/*                                                                    */
/* Compiled with:                                                     */
/*                   cc server.c                                      */
/*                                                                    */
/* User types:                                                        */
/*                   3 + 5                                            */
/*                   a + b                                            */
/*                   halt + server                                    */
/**********************************************************************/

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>


#define PORT 9000                   /* Arbitrary non-reserved port */
#define HOST "nexus.iu.hioslo.no"
#define bufsize 20

/**********************************************************************/
/* Main                                                               */
/**********************************************************************/

main (argc,argv)

int argc;
char *argv[];

@{ struct sockaddr_in cin; 
  struct hostent *hp;
  char buffer[bufsize];
  int sd;

if (argc != 4)
   @{
   printf("syntax: client a + b\n");
   exit(1);
   @}

@cindex @code{gethostbyname()}
if ((hp = gethostbyname(HOST)) == NULL)
   @{
   perror("gethostbyname: ");
   exit(1);
   @}

memset(&cin,0,sizeof(cin));             /* Another way to zero memory */

cin.sin_family = AF_INET;
cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
cin.sin_port = htons(PORT);

printf("Trying to connect to %s = %s\n",HOST,inet_ntoa(cin.sin_addr));

@cindex @code{socket()}
if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
   @{
   perror("socket");
   exit(1);
   @}

@cindex @code{connect()}
if (connect(sd,&cin,sizeof(cin)) == -1)
   @{
   perror("connect");
   exit(1);
   @}

sprintf(buffer,"%s + %s",argv[1],argv[3]);

@cindex @code{send()}
if (send(sd,buffer,strlen(buffer),0) == -1)
   @{
   perror ("send");
   exit(1);
   @}

@cindex @code{recv()}
if (recv(sd,buffer,bufsize,0) == -1)
   @{
   perror("recv");
   exit (1);
   @}

printf ("Server responded with %s\n",buffer);

close (sd);
unlink("./socket");
@}

@end smallexample






@smallexample
/**********************************************************************/
/*                                                                    */
/* The server part of a client-server pair. This simply takes two     */
/* numbers and adds them together, returning the result to the client */
/*                                                                    */
/* Compiled with:                                                     */
/*                   cc server.c                                      */
/*                                                                    */
/**********************************************************************/

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>


#define PORT 9000
#define bufsize 20
#define queuesize 5
#define true 1
#define false 0

/**********************************************************************/
/* Main                                                               */
/**********************************************************************/

main ()

@{ struct sockaddr_in cin; 
  struct sockaddr_in sin;
  struct hostent *hp;
  char buffer[bufsize];
  int sd, sd_client, addrlen;


memset(&sin,0,sizeof(sin));       /* Another way to zero memory */
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;          /* Broadcast address */
sin.sin_port = htons(PORT);


if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
   @{
   perror("socket");
   exit(1);
   @}

@cindex @code{bind()}
if (bind(sd,&sin,sizeof(sin)) == -1)  /* Must have this on server */
   @{
   perror("bind");
   exit(1);
   @}

@cindex @code{listen()}
if (listen(sd,queuesize) == -1)
   @{
   perror("listen");
   exit(1);
   @}

@cindex @code{accept()}
while (true)
  @{
  if ((sd_client = accept(sd,&cin,&addrlen)) == -1)
      @{
      perror("accept");
      exit(1);
      @}

   if (recv(sd_client,buffer,sizeof(buffer),0) == -1)
      @{
      perror("recv");
      exit(1);
      @}

   if (!DoService(buffer))
      @{
      break;
      @}

   if (send(sd_client,buffer,strlen(buffer),0) == -1)
      @{
      perror("send");
      exit(1);
      @}

   close (sd_client);
   @}

close (sd);
printf("Server closing down...\n");
@}


/**************************************************************/

DoService(buffer)

char *buffer;

  /* This is the protocol section. Here we must */
  /* check that the incoming data are sensible  */

@{ int a=0,b=0;

printf("Received: %s\n",buffer);
sscanf(buffer,"%d + %d\n",&a,&b);

if (a > 0 && b> 0)
   @{
   sprintf(buffer,"%d + %d = %d",a,b,a+b);
   return true;
   @}
else
   @{
   if (strncmp("halt",buffer,4) == 0)
     @{
     sprintf(buffer,"Server closing down!");
     return false;
     @}
   else
     @{
     sprintf(buffer,"Invalid protocol");
     return true;
     @}
   @}
@}

@end smallexample

@noindent
In the example we use `streams' to implement a typical input/output
behaviour for C. A stream interface is a so-called reliable protocol.
@cindex Reliable socket protocol
There are other kinds of sockets too, called @emph{unrealiable}, or UDP
sockets.  Features to notice on the server are that we must bind to a
specific address. The client is always implicitly bound to an address
since a socket connection always originates from the machine on which
the client is running. On the server however we want to know which
addresses we shall be receiving requests from. In the above example we
use the generic wildcard address @samp{INADDR_ANY} which means that any
host can connect to the server. Had we been more specific, we could have
limited communication to two machines only.

By calling @samp{listen()} we set up a queue for incoming connections.
Rather than forking a separate process to handle each request we
set up a queue of a certain depth. If we exceed this depth then
new clients rtying to connect will be refused connection.

The @samp{accept} call is the mechanism which extracts a `reply handle'
from the socket. Using the handle obtained from this call we can reply
to the client without having to open a special socket explicitly.

An improved server side connection can be setup, reading the
service name from @file{/etc/services} and setting reusable
socket options to avoid busy signals, like this:
@smallexample

  struct sockaddr_in cin, sin; 
  struct servent *server;
  int sd, addrlen = sizeof(cin);
  int portnumber, yes=1;

  if ((server = getservbyname(@var{service-name},"tcp")) == NULL)
      @{
      CfLog(cferror,"Couldn't get cfengine service","getservbyname");
      exit (1);
      @}
   
   bzero(&cin,sizeof(cin));
   
 /*  Service returns network byte order */

   sin.sin_port = (unsigned short)(server->s_port);
   sin.sin_addr.s_addr = INADDR_ANY;
   sin.sin_family = AF_INET; 
   
   if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
      @{
      CfLog(cferror,"Couldn't open socket","socket");
      exit (1);
      @}
   
   if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, 
                      (char *) &yes, sizeof (int)) == -1)
      @{
      CfLog(cferror,"Couldn't set socket options","sockopt");
      exit (1);
      @}
   
   
   if (bind(sd,(struct sockaddr *)&sin,sizeof(sin)) == -1)
      @{
     
      @}

 /* etc */

@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Multithreading a server, System databases, Sockets, Network programming
@section Multithreading a server

All the arguments must be collected into a struct, since only
one argument pointer can be sent to the pthread functions.

@smallexample

#include <pthread.h>


SpawnCfGetFile(args)

struct cfd_thread_arg *args;

@{ pthread_t tid;
  void *CfGetFile();

pthread_attr_init(&PTHREADDEFAULTS);
pthread_attr_setdetachstate(&PTHREADDEFAULTS,PTHREAD_CREATE_DETACHED);
   
if (pthread_create(&tid,&PTHREADDEFAULTS,CfGetFile,args) != 0)
   @{
   CfLog(cferror,"pthread_create failed","create");
   CfGetFile(args);
   @}
   
pthread_attr_destroy(&PTHREADDEFAULTS);
@}

/***************************************************************/

void *CfGetFile(args)

struct cfd_thread_arg *args;

@{ pthread_mutex_t mutex;

if (pthread_mutex_lock(&mutex) != 0)
   @{
   CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");
   free(args->replyfile);  /* from strdup in each thread */
   DeleteConn(args->connect);
   free((char *)args);
   return NULL;
   @}

ACTIVE_THREADS++;   /* Global variable */

if (pthread_mutex_unlock(&mutex) != 0)
   @{
   CfLog(cferror,"pthread_mutex_unlock failed","unlock");
   @}
  

 /* send data */
 
if (pthread_mutex_lock(&mutex) != 0)
   @{
   CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");
   return;
   @}
 
ACTIVE_THREADS--;
   
if (pthread_mutex_unlock(&mutex) != 0)
   @{
   CfLog(cferror,"pthread_mutex_unlock failed","unlock");
   @}

#endif 

return NULL;
@}

@end smallexample  

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node System databases, DNS, Multithreading a server, Network programming
@section System databases

@cindex NIS
@cindex Network information service
@cindex Network databases
@cindex Database maps


The C library calls which query the databases are, amongst others,
@smallexample
getpwnam            @var{get password data by name}
getpwuid            @var{get password data by uid}
getgrnam            @var{get group data by name}
gethostent          @var{get entry in hosts database}
getnetgrent         @var{get entry in netgroups database}
getservbyname       @var{get servive by name}
getservbyport       @var{get service by port}
get protobyname     @var{get protocol by name}
@end smallexample

@noindent
For a complete list and how to use these, see the UNIX manual.
@cindex @code{getpwnam()}
@cindex @code{getpwuid()}
@cindex @code{getgrnam()}
@cindex @code{gethostent()}
@cindex @code{getnetgrent()}
@cindex @code{getservbyname()}
@cindex @code{getservbyport()}

The following example shows how to read the password file of the
system. The functions used here can be used regardless of whether
the network information service (NIS) is in use. The data are
returned in a structure which is defined in @samp{/usr/include/pwd.h}.


@smallexample
/******************************************************************/
/*                                                                */
/* Read the passwd file by name and sequentially                  */
/*                                                                */
/******************************************************************/

#include <unistd.h>
#include <pwd.h>

main ()

@{ uid_t uid;
   struct passwd *pw;

uid = getuid();

pw = getpwuid(uid);

printf ("Your login name is %s\n",pw->pw_name);

printf ("Now here comes the whole file!\n\n");

setpwent();
 
while (getpwent())
   @{
   printf ("%s:%s:%s\n",pw->pw_name,pw->pw_gecos,pw->pw_dir);
   @}
                   
endpwent();
@}


@end smallexample

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node DNS, C and NFS, System databases, Network programming
@section DNS - The Domain Name Service

@cindex DNS
@cindex The domain name service
@cindex BIND
@cindex Berkeley Internet Name Domain (BIND)
The second network database service is that which converts host and
domain names into IP numbers and vice versa. This is the domain
name service, usually implemented by the BIND 
(Berkeley Internet Name Domain) software.
The information here concerns version 4.9 of this software.

@c .....................................................
@c SUBSECTION
@c .....................................................
 
@menu
* gethostbyname::               
@end menu

@node gethostbyname,  , DNS, DNS
@subsection  gethostbyname()

This is perhaps the most important function form hostname
lookup. @samp{gethostbyname()} gets its information either from files,
NIS or DNS. Its behaviour is configured by the files mentioned above,
@xref{DNS}.  It is used to look up the IP address of a named host
(including domain name if DNS is used).  On the configurable systems
described above, the full list of servers is queried until a reply is
obtained.  The order in which the different services are queried is
important here since DNS returns a @emph{fully qualified name}
@cindex Fully qualified name
(host name plus domain name) whereas NIS and the @file{/etc/hosts} file
database return only a hostname.

gethostbyname returns data in the form of a pointer to a static
data structure. The syntax is
@smallexample
#include <netdb.h>

@cindex @code{gethostbyname()}
struct hostent *hp;

hp = gethostbyname("myhost.domain.country")
@end smallexample

@noindent
The resulting structure varies on different implementations
of UNIX, but the `old BSD standard' is of the form:
@smallexample

struct  hostent 
   @{
   char    *h_name;        /* official name of host */
   char    **h_aliases;    /* alias list */
   int     h_addrtype;     /* host address type */
   int     h_length;       /* length of address */
   char    **h_addr_list;  /* list of addresses from name server */
   @};

#define h_addr  h_addr_list[0]  /* address, for backward compatiblity */

@end smallexample

@noindent
The structure contains a list of addresses and or aliases from the
nameserver. The interesting quantity is usually extracted by means
of the macro @samp{h_addr}
whcih gives the first value in the address list, 
though officially one should examine the whole list now.

This value is a pointer which can be converted into a text form
by the following hideous type transformation:
@smallexample

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

struct sockaddr_in sin;

cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;

printf("IP address = %s\n",inet_ntoa(cin.sin_addr));

@end smallexample

See the client program in the first section of this chapter for an
example of its use.


@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node C and NFS, Ex 7, DNS, Network programming
@section  C support for NFS

The support for NFS mounting in the standard C library is through
two sources. NFS is based on the Sun's RPC system, so the basic
calls are only instances of standard RPC protocols.

@cindex NFS and C support
The C functions in the standard input/output library can be used to
access NFS filesystems.  Since NFS imitates the UNIX filesystem as
closely as possible, NFS filesystems can be mounted in exactly the same
way as ordinary filesystems. Unfortunately, the C functions which
perform the mount operation in UNIX and depressingly non-standard. They
differ on almost every implementation of UNIX.

The basic function which mounts a filesystem, in @samp{mount} (see
@kbd{man (2) mount}). The mount table is stored in a file
@emph{/etc/mtab} on BSD systems (again the name varies wildly from UNIX
to UNIX, mnttab on HPUX for instance).  The file @emph{/etc/rmtab} on an
NFS server contains a list of remote-mounted filesystems which are
mounted by remote clients.  C functions exist which can read the
filesystem tables and place the resulting data in C struct types. Alas,
these struct defintions are also quite different on different
systems. See @file{/usr/include/sys/mount.h}, so the user wishing to
write system-independent code is confounded at the lowest level.

@c -----------------------------------------------------------------------
@c SECTION
@c -----------------------------------------------------------------------
 
@node Ex 7,  , C and NFS, Network programming
@section Exercises

@enumerate
@item 
Use @samp{gethostbyname()} to make a simple program like @samp{nslookup}
which gives the internet address of a named host.

@item 
Modify the client server example above to make a `remote ls'
command called @samp{rls}. You should be able to use the syntax
@smallexample
rls (options) hostname:/path/to/file 
@end smallexample
@end enumerate


@c **********************************************************************
@c APPENDIX
@c **********************************************************************

@node Programming idioms, Variable Index, Network programming, Top
@appendix Summary of programming idioms.

@table @emph

@item True and false

@smallexample

# C shell

  True   - non-zero/non-empty value
  False  - zero or null string

# Bourne shell

  True   - 0 returned by shell command
  False  - non-zero returned by shell command

  ( Note that "test" converts from C shell style to Bourne shell)

# Perl

  True   - non-zero/non-empty value
  False  - zero or null string

/* C */

  True   - non zero integer
  False  - zero integer
@end smallexample

@item Input from tty

@smallexample
# C shell

   $<

# Bourne shell

   line
   read

# Perl

   <STDIN>

/* C */

   scanf

@end smallexample

@item Redirection of I/O

@smallexample

# C  shell

  @var{command}  >  file
  @var{command}  >& file
  @var{command}  >> file
  @var{command1} |  @var{command2}

# Bourne shell

  @var{command}  > file
  @var{command}  > file 2>&1
  @var{command}  >> file
  @var{command1} | @var{command2}

# Perl

  open (HANDLE,">file")
  open (HANDLE,">file 2>&1")
  open (HANDLE,">>file")
  open (HANDLE,"command1 |")
  open (HANDLE,"| command2")

/* C */

  fopen ("file","w"); printf(..)
  fopen ("file","w"); printf(..); fprintf(stderr,..)
  fopen ("file","a"); printf(..)
  popen ("@var{command1}","r")
  popen ("@var{command2}","w")

@end smallexample

@item Loops and tests

@smallexample

/* C */ Shell

  foreach end         if then else endif
  while end           switch case breaksw endsw
  repeat

# Bourne shell

  while do done       if then else fi
  until do done       case in esac
  for in do done

# Perl

  while               if then else
  for                 unless else
  foreach
  until
  do while
  do until

/* C */

  while               if then else
  do while            switch case
  for

@end smallexample

@item Arguments from command line

@smallexample
# C shell

  $argv[]
  $#argv

# Bourne Shell

  $1, $2, $3...  $*
  $#

# Perl

  $ARGV[]
  $#ARGV

/* C */

  char argv[][]
  int  argc
@end smallexample

@item Arithmetic
@smallexample
# C shell

   @ a = $b + $c

# Bourne shell

   a = `expr $b + $c`

# Perl

   $a = $b + $c;

/* C */

   a = b + c;
@end smallexample

@item Numerical comparison
@smallexample
# C shell

   if ( $x == $y ) then
   endif

# Bourne shell

   if [ $x -eq $y ]; then
   fi

# Perl

   if ( $x == $y )
      @{
      @}

/* C */

   if ( x == y )
      @{
      @}
@end smallexample

@item String comparison
@smallexample

# C shell

   if ( $x == $y ) then
   endif

# Bourne shell

   if [ $x = $y ]; then
   fi

# Perl

   if ( $x eq $y ) then
      @{
      @}

/* C */

   if (strcmp(x,y) == 0)
      @{
      @}

@end smallexample

@item Opening a file
@smallexample

# C shell, Bourne shell - cannot be done (pipes only)

# Perl

    open (READ_HANDLE,"filename");
    open (WRITE_HANDLE,"> filename");
    open (APPEND_HANDLE,">> filename");

/* C */

    FILE *fp;

    fp = fopen ("file","r");
    fp = fopen ("file","w");
    fp = fopen ("file","a");

@end smallexample

@item Opening a directory
@smallexample

# C shell

   foreach dir ( @var{directory}/* )
      ...
   end

# Bourne shell

   for dir in @var{directory}/* ;
   do
     ...
   done

# Perl

   opendir (HANDLE,"@var{directory}") || die;

   while ($entry = readdir(HANDLE))
      @{
      @}

   closedir(HANDLE);

# C

   #include <dirent.h>
   DIR *dirh;
   struct dirent *dirp;

   if ((dirh = opendir(name)) == NULL)
      @{
      perror("opendir")
      exit(1);
      @}

   for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
      @{
      ...  /* dirp->d_name points to child */
      @}

   closedir(dirh);
   

@end smallexample

@item Testing file types
@smallexample

# C shell

    if ( -f file )  # plain file
    if ( -d file )  # directory

# Bourne shell

    if [ -f file ]  # plain file
    if [ -d file ]  # directory

# Perl

    if ( -f file )  # plain file
    if ( -d file )  # directory
    if ( -l file )  # symbolic link

/* C */

     #include <sys/stat.h>

     struct stat statvar;

     stat("file", &statvar);

     if (S_ISREG(statvar.mode))  /* plain file */
     if (S_ISDIR(statvar.mode))  /* directory  */

     lstat("file", &statvar);

     if (S_ISLNK(statvar.mode))  /* symbolic link */

@end smallexample


@end table

@c **********************************************************************
@c INDEX
@c **********************************************************************

@node Variable Index, Concept Index, Programming idioms, Top
@unnumbered Command and Variable Index

@printindex vr

@node Concept Index,  , Variable Index, Top
@unnumbered Concept Index

@printindex cp

@contents

@bye



