% Linux Installation and Getting Started    -*- TeX -*-
% environment.tex
% Copyright (c) 1992, 1993 by Matt Welsh, Larry Greenfield and Karl Fogel
%
% This file is freely redistributable, but you must preserve this copyright 
% notice on all copies, and it must be distributed only as part of "Linux 
% Installation and Getting Started". This file's use is covered by
% the copyright for the entire document, in the file "copyright.tex".

\section{Customizing your Environment}

\index{environment!customizing|(}
The shell provides many mechanisms to customize your work environment. 
As we've mentioned before, the shell is more than a command 
interpreter---it is also a powerful programming language. While writing
shell scripts is an extensive subject, we'd like to introduce you to
some of the ways that you can simplify your work on a UNIX system by
using these advanced features of the shell.

As we have mentioned before, different shells use different syntaxes 
when executing shell scripts. For example, Tcsh uses a C-like syntax,
while Bourne shells use another type of syntax. In this section, we
won't be running into many of the differences between the two, but we
will assume that shell scripts are executed using the Bourne shell syntax.

\subsection{Shell scripts}\label{sec-shell-script}
\index{shell script!defined}
\index{commands!grouping with shell scripts}
Let's say that you use a series of commands often, and
would like to shorten the amount of required typing by grouping all
of them together into a single ``command''. For example, the commands
\begin{tscreen}
/home/larry\# {\em cat chapter1 chapter2 chapter3 $>$ book} \\
/home/larry\# {\em wc -l book} \\
/home/larry\# {\em lp book}
\end{tscreen}
would concatenate the files {\tt chapter1}, {\tt chapter2}, and
{\tt chapter3} and place the result in the file {\tt book}. Then, a
count of the number of lines in {\tt book} would be displayed, and
finally {\tt book} would be printed with the {\tt lp} command.

Instead of typing all of these commands, you could group them into a
{\bf shell script}. We described shell scripts briefly in 
Section~\ref{sec-shell-script}. The shell script used to run all of these
commands would look like
\begin{tscreen}\begin{verbatim}
#!/bin/sh
# A shell script to create and print the book

cat chapter1 chapter2 chapter3 > book
wc -l book
lp book
\end{verbatim}\end{tscreen}
If this script was saved in the file {\tt makebook}, you could simply
use the command
\begin{tscreen}
/home/larry\# {\em makebook}
\end{tscreen}
to run all of the commands in the script. Shell scripts are just
plain text files; you can create them with an editor such as {\tt emacs}
or {\tt vi} 
% \ifodd\igsascii {} \else
\footnote{{\tt vi} is covered in Section~\ref{sec-vi}.}.
% \fi

Let's look at this shell script. The first line, ``{\tt \#!/bin/sh}'',
identifies the file as a shell script, and tells the shell how to 
execute the script. It instructs the shell to pass the script to 
{\tt /bin/sh} for execution, where {\tt /bin/sh} is the shell program 
itself. Why is this important? On most UNIX systems, {\tt /bin/sh} is a
Bourne-type shell, such as Bash. By forcing the shell script to run
using {\tt /bin/sh}, we are ensuring that the script will run under a
Bourne-syntax shell (instead of, say, a C shell). This will cause your
script to run using the Bourne syntax even if you use Tcsh (or another 
C shell) as your login shell.

\index{shell scripts!comments in}
The second line is a {\em comment}. Comments begin with the character
``{\tt \#}'' and continue to the end of the line. Comments are
ignored by the shell---they are commonly used to identify the shell script 
to the programmer. 

The rest of the lines in the script are just commands, as you
would type them to the shell directly. In effect, the shell reads
each line of the script and runs that line as if you had typed it
at the shell prompt. 

\index{shell scripts!permissions for}
\index{permissions!for shell scripts}
Permissions are important for shell scripts. If you 
create a shell script, you must make sure that you have execute
permission on the script in order to run it\footnote{When you create text
files, the default permissions usually don't include execute permission.}.
The command
\begin{tscreen}
/home/larry\# {\em chmod u+x makebook}
\end{tscreen}
can be used to give yourself execute permission on the shell script
{\tt makebook}.

\subsection{Shell variables and the environment}
\index{shells!variables!defined}
\index{variables!shell}
\index{variables!in shell scripts}
\index{shell scripts!variables in}
The shell allows you to define {\bf variables}, as most programming
languages do. A variable is just a piece of data which is given the
name. 

\blackdiamond Note that Tcsh, as well as other C-type shells, use a 
different mechanism for setting variables than is described here. This
discussion assumes the use of a Bourne shell, such as Bash (which you're
probably using). See the Tcsh man page for details.

When you assign a value to a variable (using the ``{\tt =}'' operator), 
you can access the variable by prepending a ``{\tt \$}'' to the
variable name, as demonstrated below.
\begin{tscreen}
/home/larry\# {\em foo=``hello there''} 
\end{tscreen}
The variable {\tt foo} is given the value ``{\tt hello there}''. You 
can now refer to this value by the variable name, prefixed with a
``{\tt \$}'' character. The command
\begin{tscreen}
/home/larry\# {\em echo \$foo} \\
hello there \\
/home/larry\# 
\end{tscreen}
produces the same results as
\begin{tscreen}
/home/larry\# {\em echo ``hello there''} \\
hello there \\
/home/larry\# 
\end{tscreen}

These variables are internal to the shell. This means that only the
shell can access these variables. This can be useful in shell scripts;
if you need to keep track of a filename, for example, you can store
it in a variable, as above. Using the command {\tt set} will 
display a list of all defined shell variables. 

\index{shell variables!exporting to environment}
\index{export@{\tt export}}
However, the shell allows you to {\bf export} variables to the
{\bf environment}. The environment is the set of variables which
all commands that you execute have access to. Once you define a variable
inside the shell, exporting it makes that variable part of the environment
as well. The {\tt export} command is used to export a variable to
the environment.

\index{setenv@{\tt setenv}}
\blackdiamond Again, here we differ between Bash and Tcsh. If you're
using Tcsh, another syntax is used for setting environment variables (the
{\tt setenv} command is used). See the Tcsh man page for more information.

\index{variables!environment}
The environment is very important to the UNIX system. It allows you
to configure certain commands just by setting variables which the
commands know about. 

Here's a quick example. The environment variable {\tt PAGER} is used
by the {\tt man} command. It specifies the command to use to display
man pages one screenful at a time. If you set {\tt PAGER} to be the
name of a command, it will use that command to display the man pages,
instead of {\tt more} (which is the default).

Set {\tt PAGER} to ``{\tt cat}''. This will cause output from {\tt man}
to be displayed to the screen all at once, without breaking it up into
pages.
\begin{tscreen}
/home/larry\# {\em PAGER=``cat''}
\end{tscreen}
Now, export {\tt PAGER} to the environment.
\begin{tscreen}
/home/larry\# {\em export PAGER}
\end{tscreen}
Try the command {\tt man ls}. The man page should fly past your screen
without pausing for you.

Now, if we set {\tt PAGER} to ``{\tt more}'', the {\tt more} command
will be used to display the man page.
\begin{tscreen}
/home/larry\# {\em PAGER=``more''}
\end{tscreen}
Note that we don't have to use the {\tt export} command after we
change the value of {\tt PAGER}. We only need to export a variable
once; any changes made to it thereafter will automatically be propagated
to the environment.

The man pages for a particular command will tell you if the command
uses any environment variables; for example, the {\tt man} man page
explains that {\tt PAGER} is used to specify the pager command.
Some commands share environment variables; for example, many commands
use the {\tt EDITOR} environment variable to specify the default editor
to use when one is needed.


The environment is also used to keep track of important information
about your login session. An example is the {\tt HOME} environment
variable, which contains the name of your home directory.
\begin{tscreen}
/home/larry/papers\# {\em echo \$HOME} \\
/home/larry
\end{tscreen}

Another interesting environment variable is {\tt PS1}, which defines
the main shell prompt. For example,
\begin{tscreen}
/home/larry\# {\em PS1=``Your command, please: ''} \\
Your command, please: 
\end{tscreen}
To set the prompt back to our usual (which contains the current 
working directory followed by a ``{\tt \#}'' symbol), 
\begin{tscreen}
Your command, please: {\em PS1=``\verb-\w# -''} \\
/home/larry\# 
\end{tscreen}
The {\tt bash} man page describes the syntax used for setting the prompt. 

\subsubsection{The {\tt PATH} environment variable}
\index{environment!variables!PATH@{\tt PATH}}
When you use the {\tt ls} command, how does the shell
find the {\tt ls} executable itself? In fact, {\tt ls} is found
in {\tt /bin/ls} on most systems. The shell uses the environment variable
{\tt PATH} to locate executable files for commands which you type.

For example, your {\tt PATH} variable may be set to:
\begin{tscreen}
/bin:/usr/bin:/usr/local/bin:.
\end{tscreen}
This is a list of directories for the shell to search, each directory
separated by a ``{\tt :}''. When you use the command {\tt ls}, the
shell first looks for {\tt /bin/ls}, then {\tt /usr/bin/ls}, and so on.

Note that the {\tt PATH} has nothing to do with finding regular files. 
For example, if you use the command 
\begin{tscreen}
/home/larry\# {\em cp foo bar}
\end{tscreen}
The shell does not use {\tt PATH} to locate the files {\tt foo} and
{\tt bar}---those filenames are assumed to be complete. The shell only
uses {\tt PATH} to locate the {\tt cp} executable. 

This saves you a lot of time; it means that you don't have to remember where 
all of the command executables are stored. On many systems, executables are 
scattered about in many places, such as {\tt /usr/bin}, {\tt /bin}, or 
{\tt /usr/local/bin}. Instead of giving the command's full pathname (such 
as {\tt /usr/bin/cp}), you can simply set {\tt PATH} to the list of 
directories that you want the shell to automatically search.

Notice that {\tt PATH} contains ``{\tt .}'', which is the current working
directory. This allows you to create a shell script or program and run it as 
a command from your current directory, without having
to specify it directly (as in {\tt ./makebook}). If a directory isn't on
your {\tt PATH}, then the shell will not search it for commands to run---this 
includes the current directory.

\subsection{Shell initialization scripts}\label{sec-init-scripts}
\index{shell scripts!initializtion}
\index{initialization scripts!for shells}
In addition to shell scripts that you create, there are a number
of scripts that the shell itself uses for certain purposes. The
most important of these are your {\bf initialization scripts}, scripts
automatically executed by the shell when you login.

The initialization scripts themselves are simply shell scripts, as
described above. However, they are very useful in setting up your
environment by executing commands automatically when you 
login. For example, if you always use the {\tt mail} command to check your
mail when you login, you place the command in your
initialization script so it will be executed automatically.

\index{login shell!defined}
Both Bash and Tcsh distinguish between a {\bf login shell} and other
invocations of the shell. A login shell is a shell invoked at login time;
usually, it's the only shell which you'll use. However, if you ``shell out''
of another program, such as {\tt vi}, you start another instance of 
the shell, which isn't your login shell. In addition, whenever you run 
a shell script, you automatically start another instance of the shell to 
execute the script.

\index{shells!initializtion files}
\index{initialization files!for shells}
\index{/etc/profile@{\tt /etc/profile}}
\index{.bash\_profile@{\tt .bash\_profile}}
\index{.bashrc@{\tt .bashrc}}
\index{.profile@{\tt .profile}}
The initialization files used by Bash are: {\tt /etc/profile} (set up
by the system administrator, executed by all Bash users at login time),
{\tt \$HOME/.bash\_profile} (executed by a login Bash session), and
{\tt \$HOME/.bashrc} (executed by all non-login instances of Bash).
If {\tt .bash\_profile} is not present, {\tt .profile} is used instead.

\index{/etc/csh.login@{\tt csh.login}}
\index{.tcshrc@{\tt.tcshrc}}
Tcsh uses the following initialization scripts: {\tt /etc/csh.login} 
(executed by all Tcsh users at login time), {\tt \$HOME/.tcshrc} 
(executed a login time and by all new instances of Tcsh), and
{\tt \$HOME/.login} (executed at login time, following {\tt .tcshrc}). 
If {\tt .tcshrc} is not present, {\tt .cshrc} is used instead. 

To fully understand the function of these files, you'll need to learn
more about the shell itself. Shell programming is a complicated subject,
far beyond the scope of this book. See the man pages for {\tt bash} and/or
{\tt tcsh} to learn more about customizing your shell environment.

\index{environment!customizing|)}
