%					-*- LaTeX -*-
\documentclass[landscape]{slides}
\usepackage{graphics}
\usepackage{color}

%\makeatletter
%\newcommand{\ps@umiacsslide}{%
%    \renewcommand{\@evenfoot}{\@empty}
%    \renewcommand{\@oddfoot}{\@empty}
%    \renewcommand{\@evenhead}{\hfil UMIACS\hfil}%
%    \renewcommand{\@oddhead}{\hfil SCAIMU\hfil}%
%%    \let\@mkboth\@gobbletwo
%%    \let\sectionmark\@gobble
%%    \let\subsectionmark\@gobble
%}
\settoheight{\headheight}{\includegraphics{logo-small.eps}}
\setlength{\topmargin}{0pt}
%\setlength{\headheight}{2cm}
\makeatletter
\renewcommand{\ps@slide}{%
    \renewcommand{\@evenfoot}{\@empty}
%    \renewcommand{\@oddfoot}{\@empty}
\renewcommand{\@oddfoot}{\hfil\theslide}
    \renewcommand{\@evenhead}{\hfil UMIACS\hfil}%
%    \renewcommand{\@oddhead}{\hfil UMIACS\hfil}%
    \renewcommand{\@oddhead}{\includegraphics{logo-small.eps}\hfil}
}

\newcommand{\heading}[1]{%
  \begin{center}
    \large\textbf{\underline{#1}}
  \end{center}
  \vspace{1ex minus 1ex}}

\newcommand{\code}[1]{\texttt{#1}}
\newcommand{\sh}{\code{sh}}
\newcommand{\bull}{$\bullet$}

\begin{document}
%\thispagestyle{umiacsslide}
%\pagestyle{umiacsslide}
\pagestyle{slide}

\begin{slide}
\begin{center}
{\Huge Bourne Shell Programming}
\vskip1cm
{\large Andrew Arensburger}
\end{center}
\end{slide}

\begin{slide}
\heading{A Simple Script}
\begin{verbatim}
#!/bin/sh
# Rotate procmail log files
cd /homes/arensb/Mail
rm procmail.log.6       # This is redundant
mv procmail.log.5 procmail.log.6
mv procmail.log.4 procmail.log.5
mv procmail.log.3 procmail.log.4
mv procmail.log.2 procmail.log.3
mv procmail.log.1 procmail.log.2
mv procmail.log.0 procmail.log.1
mv procmail.log procmail.log.0
\end{verbatim}
\end{slide}

\begin{slide}
\heading{Variables}
%\begingroup
%\begin{itemize}
%\setlength{\itemsep}{0pt}
\bull Set with VAR=\textit{value}\\
\bull Refer to value with \$VAR or \$\{VAR\}\\
\bull Export a variable with \code{export} VAR\\
\bull Unset a variable with \code{unset} VAR
%\end{itemize}
%\endgroup

\bigskip
\hrule

\begin{verbatim}
#!/bin/sh
COLOR=yellow

echo The color is $COLOR
echo This seems ${COLOR}ish
\end{verbatim}
\end{slide}

\begin{slide}

\heading{Local and Environment Variables}

\bull Local variables are local.\\
\bull Environment variables are passed on to subprocesses.\\
\bull Turn a local variable into an environment variable with
\begin{quote}
\code{export}~VAR
\end{quote}

\bigskip
\hrule

\begin{verbatim}
#!/bin/sh
NETSCAPE_HOME=/usr/imports/libdata

CLASSPATH=$NETSCAPE_HOME/classes
export CLASSPATH

$NETSCAPE_HOME/bin/netscape.bin
\end{verbatim}
\end{slide}

\begin{slide}
\heading{Special variables}
%\begin{center}
\begingroup
\settowidth{\leftmargin}{\code{\$1}, \code{\$2}\ldots\code{\$9}}
\addtolength{\leftmargin}{1em}
\begin{itemize}
\setlength{\itemsep}{0em plus 0pt minus 0pt}
\setlength{\labelsep}{2em}
\item[\code{\$1}, \code{\$2}\ldots\code{\$9}]
	Command-line arguments.
\item[\code{\$0}]
	Script name.
\item[\code{\$*}, \code{\$@}]
	All command-line arguments.
\item[\code{\$\#}]
	Number of command-line arguments.
\item[\code{\$?}]
	Exit status of last command.
\item[\code{\$-}]
	\sh\ options.
\item[\code{\$\$}]
	PID of the current process.
\item[\code{\$|}]
	PID of the last background command.
\item[\code{\$IFS}]
	Input Field Separator.
\end{itemize}
\endgroup
%\end{center}
\end{slide}

\begin{slide}
\heading{Variable constructs}
\begingroup
\settowidth{\leftmargin}{\code{\$\{}VAR\code{:?}[\textit{expression}]\code{\}}}
\addtolength{\leftmargin}{1em}
\begin{itemize}
\setlength{\itemsep}{0em plus 0pt minus 0pt}
\item[\code{\$\{}VAR\code{:-}\textit{expression}\code{\}}]
	Use default value.
\item[\code{\$\{}VAR\code{:=}\textit{expression}\code{\}}]
	Set default value.
\item[\code{\$\{}VAR\code{:?}{[\textit{expression}]}\code{\}}]
	Die if VAR is not set.
\item[\code{\$\{}VAR\code{:+}\textit{expression}\code{\}}]
	\textit{expression} if VAR is set.
%\item[\code{\$\{\#}VAR\code{\}}]
%	String length of \$VAR.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{Patterns and Globbing}

\begingroup
\begin{itemize}
\setlength{\itemsep}{0pt}
\item[\code{*}]
	Matches zero or more characters.
\item[\code{?}]
	Matches exactly one character.
\item[\code{[}\textit{range}\code{]}]
	Matches any character in \textit{range}.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{Quoting Strings}

\bull Backslash escapes the next character.\\
\bull Single quotes just quote.\\
\bull Double quotes expand variables.\\
\bull Backquotes expand to the output of a command.

\bigskip
\hrule

\begin{verbatim}
echo \$foo == $foo
echo '* MAKE   $$$   FAST *'
echo "The file is  $filename"
echo `whoami`

echo "The time is `date`"
\end{verbatim}%$
\end{slide}

\begin{slide}
\heading{Built-in Commands}

\begingroup
\settowidth{\leftmargin}{\code{\{} \textit{commands} \code{; \}},\code{(}\textit{commands}\code{)}}
\addtolength{\leftmargin}{-1cm}
\begin{itemize}
\setlength{\itemsep}{0em plus 0pt minus 0pt}
\item[\code{\{} \textit{commands} \code{; \}},\code{(}\textit{commands}\code{)}]
	Executes \textit{commands} in a subshell.
\item[\code{:} (colon)]
	Does nothing.
\item[\code{.} \textit{filename}]
	Reads in the specified filename.
\item[\code{bg} {[\textit{job}]}, \code{fg} {[\textit{job}]}]
	Background, foreground.
\item[\code{cd} {[\textit{dir}]}]
	Sets the current directory.
\item[\code{pwd}]
	Prints the current directory.
\item[\code{echo} {[\textit{args}]}]
	Prints \textit{args} to standard output.
\item[\code{eval} \textit{args}]
	Evaluates \textit{args} as a \sh\ expression.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{Built-in Commands (cont.)}

\begingroup
\settowidth{\leftmargin}{\code{\{} \textit{commands} \code{; \}},\code{(}\textit{commands}\code{)}}
\addtolength{\leftmargin}{-1cm}
\begin{itemize}
\setlength{\itemsep}{0em plus 0pt minus 0pt}
\item[\code{exec} \textit{command}]
	Replaces the shell with \textit{command}.
\item[\code{exit} {[\textit{n}]}]
	Exits the current shell with exit code \textit{n}.
\item[\code{kill} {[\code{-}\textit{sig}]} \code{\%}\textit{job}]
	Sends signal \textit{sig} to the specified job.
\item[\code{read} \textit{name\ldots}]
	Reads one line from standard input.
\item[\code{set} {[\code{+}/\code{-}\textit{flag}]} {[\textit{arg}]}]
	Sets \sh\ options or command-line arguments.
\item[\code{test} \textit{expression}]
	Evaluates a boolean expression.
\item[\code{trap} {[\textit{command} \textit{sig}]}\ldots]
	Traps one or more signals.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{Built-in Commands (cont.)}

\begingroup
\settowidth{\leftmargin}{\code{\{} \textit{commands} \code{; \}},\code{(}\textit{commands}\code{)}}
\addtolength{\leftmargin}{-1cm}
\begin{itemize}
\setlength{\itemsep}{0em plus 0pt minus 0pt}
\item[\code{ulimit}]
	Prints or sets system limits on resource usage.
\item[\code{umask} {[\textit{nnn}]}]
	Sets the umask.
\item[\code{wait} {[\textit{n}]}]
	Waits for a background process to exit.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{\code{if}}
\begin{quote}
\begin{tabbing}
\code{if} \= \textit{condition} \code{; then}\\
	\> \textit{commands}\\
$[$\code{elif} \textit{condition} \code{; then}\\
	\> \textit{commands}$]\ldots$\\
$[$\code{else}\\
	\> \textit{commands}$]$\\
\code{fi}
\end{tabbing}
\end{quote}

\hrule

\begingroup
\small
\begin{verbatim}
#!/bin/sh
myname=`whoami`

if [ $myname = root ]; then
        echo "Welcome to FooSoft 3.0"
else
        echo "You must be root to run this script"
        exit 1
fi
\end{verbatim}%$
\endgroup
\end{slide}

\begin{slide}
\heading{\code{while}}
\begin{quote}
\begin{tabbing}
\code{while} \= \textit{condition}\code{; do}\\
	\> \textit{commands}\\
\code{done}
\end{tabbing}
\end{quote}
\end{slide}

\begin{slide}
\heading{\code{for}}

\begin{quote}
\begin{tabbing}
\code{for} \= \textit{var} \code{in} \textit{list}\code{; do}\\
	\> \textit{commands}\\
\code{done}
\end{tabbing}
\end{quote}

\hrule
\begin{verbatim}
#!/bin/sh
for i in foo bar baz "do be do"; do
        echo $i
done
\end{verbatim}%$
\end{slide}

\begin{slide}
\heading{\code{case}}
\begin{quote}
\begin{tabbing}
\code{case} \= \textit{expression} \code{in}\\
	\> \textit{pattern}\code{)} \= \\
		\>\> \textit{commands}\\
		\>\> \code{;;}\\
	\> \ldots\\
\code{esac}
\end{tabbing}
\end{quote}

\hrule

\begingroup
\small
\begin{verbatim}
case $filename in
        *.jpg) echo "It's a JPEG file"
               ;;
        *.gif) echo "It's a GIF file"
               ;;
        *)     echo "Unknown file type"
               ;;
esac
\end{verbatim}%$
\endgroup
\end{slide}

\begin{slide}
\heading{I/O Redirection}
\begingroup
\settowidth{\leftmargin}{\textit{command1} \code{\&\&} \textit{command2}}
\addtolength{\leftmargin}{1em}
\begin{itemize}
\setlength{\itemsep}{0pt}
\item[\code{<} \textit{filename}]
	Read stdin from \textit{filename}.
\item[\code{>} \textit{filename}]
	Write stdout to \textit{filename}.
\item[\code{>>} \textit{filename}]
	Appends stdout to \textit{filename}.
\item[\code{<<}\textit{word}]
	Reads stdin up to \textit{word}.
\item[\code{<\&}\textit{digit}]
	Use file descriptor \textit{digit} as standard input.
\item[\code{>\&}\textit{digit}]
	Use file descriptor \textit{digit} as standard output.
\item[\code{<\&-}]
	Close standard input.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{I/O Redirection (cont.)}
\begingroup
\settowidth{\leftmargin}{\textit{command1} \code{\&\&} \textit{command2}}
\addtolength{\leftmargin}{1em}
\begin{itemize}
\setlength{\itemsep}{0pt}
\item[\code{>\&-}]
	Close standard output.
\item[\textit{command1} \code{|} \textit{command2}]
	Connect \textit{command1}'s stdout to \textit{command2}'s stdin.
\item[\textit{command1} \code{\&\&} \textit{command2}]
	Execute \textit{command2} iff \textit{command2} succeeds.
\item[\textit{command1} \code{||} \textit{command2}]
	Execute \textit{command2} iff \textit{command1} fails.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{I/O Redirection Examples}

\begin{verbatim}
echo "Danger! Danger, Will Robinson!" 1>&2

line=13
cat <<EOT
An error occurred on line $line.
See page 98 of the manual for details.
EOT
\end{verbatim}%$
\end{slide}

\begin{slide}
\heading{Functions}
\begin{quote}
\begin{tabbing}
\textit{name} \= \code{() \{}\\
	\> \textit{commands}\\
\code{\}}
\end{tabbing}
\end{quote}

\bigskip
\hrule

\begin{verbatim}
fancyls() {
    echo "***** Files in $1:"
    ls "$1"
    echo "***** There are `ls -1 ${dir} | wc -l` files in $1"
}

fancyls /tmp
\end{verbatim}
\end{slide}

\begin{slide}
\heading{Useful utilities}
\begingroup
\begin{itemize}
\setlength{\itemsep}{0pt}
\item basename
\item dirname
\item {[}
\item echo
\item awk\\
	\code{awk -F : '\{print \$1, \$3 \}' /etc/passwd}
\item sed\\
	\code{sed -e 's/foo/bar/g'}
\item tee
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{\code{test}}
\begingroup
\settowidth{\leftmargin}{\code{-w} \textit{filename}}
\addtolength{\leftmargin}{1em}
\begin{itemize}
\setlength{\itemsep}{0pt}
\item[\code{-e} \textit{filename}]
	True if \textit{filename} exists.
\item[\code{-d} \textit{filename}]
	True if \textit{filename} exists and is a directory.
\item[\code{-f} \textit{filename}]
	True if \textit{filename} exists and is a plain file.
\item[\code{-h} \textit{filename}]
	True if \textit{filename} exists and is a symbolic link.
\item[\code{-r} \textit{filename}]
	True if \textit{filename} exists and is readable.
\item[\code{-w} \textit{filename}]
	True if \textit{filename} exists and is writable.
\item[\code{-n} \textit{string}]
	True if the length of \textit{string} is non-zero.
\item[\code{-z} \textit{string}]
	True if the length of \textit{string} is zero.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{\code{test} (cont.)}
\begingroup
\settowidth{\leftmargin}{\code{-w} \textit{filename}}
\addtolength{\leftmargin}{1em}
\begin{itemize}
\setlength{\itemsep}{0pt}
\item[\textit{string}]
	True if \textit{string} is not the empty string.
\item[\textit{s1} \code{=} \textit{s2}]
	True if the strings \textit{s1} and \textit{s2} are identical.
\item[\textit{s1} \code{!=} \textit{s2}]
	True if the strings \textit{s1} and \textit{s2} are not
	identical.
\item[\textit{n1} \code{-eq} \textit{n2}]
	True if the numbers \textit{n1} and \textit{n2} are equal.
\item[\textit{n1} \code{-ne} \textit{n2}]
	True if the numbers \textit{n1} and \textit{n2} are not equal.
\item[\textit{n1} \code{-gt} \textit{n2}]
	True if the number \textit{n1} is greater than \textit{n2}.
\item[\textit{n1} \code{-ge} \textit{n2}]
	True if the number \textit{n1} is greater than or equal to
	\textit{n2}.
\item[\textit{n1} \code{-lt} \textit{n2}]
	True if the number \textit{n1} is less than \textit{n2}.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{\code{test} (cont.)}
\begingroup
\settowidth{\leftmargin}{\code{-w} \textit{filename}}
\addtolength{\leftmargin}{1em}
\begin{itemize}
\setlength{\itemsep}{0pt}
\item[\textit{n1} \code{-le} \textit{n2}]
	True if the number \textit{n1} is less than or equal to
	\textit{n2}.
\item[\code{!} \textit{expression}]
	Negates \textit{expression}.
\item[\textit{expr1} \code{-a} \textit{expr2}]
	True if both expressions, \textit{expr1} and \textit{expr2}
	are true.
\item[\textit{expr1} \code{-o} \textit{expr2}]
	True if either expression, \textit{expr1} or \textit{expr2} is
	true.
\item[\code{(} \textit{expression} \code{)}]
	True if \textit{expression} is true. This allows expressions
	to nest.
\end{itemize}
\endgroup
\end{slide}

\begin{slide}
\heading{Debugging}
\begin{itemize}
\setlength{\itemsep}{0pt}
\item Trace statements
\item \code{sh -n}
\item \code{sh -x}
\end{itemize}

And that's about it, unfortunately.
\end{slide}

\begin{slide}
\heading{Style}
\begin{itemize}
\setlength{\itemsep}{0pt}
\item Prefer simple, linear application.
\item Put customization variables at the top.
\item Use functions sparingly.
\item Multi-line strings.
\item Use \code{: \$\{}\textsl{VAR}\code{:=}\textit{value}\code{\}} to set
	defaults.
\end{itemize}
\end{slide}

\begin{slide}
\heading{Paranoia}
\begin{itemize}
\setlength{\itemsep}{0pt}
%\item No setuid scripts, {\Huge EVER!}
\item No setuid scripts, {\Huge \textcolor{red}{EVER!}}
\item \code{IFS=}
\item Set \code{\$PATH}
\item Quote all variables.
\item Watch out for empty or bogus values.
\end{itemize}

\hrule
\begin{verbatim}
if [ x"$answer" = xyes ]; then
\end{verbatim}
\end{slide}

\end{document}
