Friday, October 23, 2009

Identity Crisis




















Identity Crisis


One of the challenges to implementing effective security involves securing the identities. If security relies on proper identification, then it is natural to conclude that this linchpin in the security process is a high-risk area. Compromise the identity process, and you have compromised the security integrity of the application, the database, or both.




Spoofing


One particularly successful way to defeat good security is to play along with the security. Instead of trying to overcome the access controls and bypass the auditing, one can merely pretend to be someone else. Masquerading as another user, or spoofing, is the digital equivalent of identity theft that is discussed in the next section. This “someone else” can either be a privileged user or just another user. In both cases, spoofing can lead to disastrous results.


With spoofing, the security of the system can become an ally for the attacker. It may even help protect the information being stolen, manipulated, or copied by the spoofing hacker from other hackers! For example, it may not be difficult to copy or steal a digital certificate that is not properly secured. Digital certificates, which can act as digital identities, are small (roughly 10KB) and can be easily stored on many devices such as floppy disks, USB pen drives, and so on. If the certificate is stolen, it can then be used to falsely identify and authenticate a user. The security architecture of the network can include firewalls, network encryption, and intrusion detection systems, none of which can detect the spoofing actions being conducted.


This generally only happens if the certificate is not secured by some other factor such as a strong password or PIN. Certificate revocation, which exists in practically all applications that support digital certificates, resolves the illicit use of digital certificates but only when the user or administrator becomes aware that the theft has occurred.


There are countless ways to masquerade as someone else, but my main point is that user identity is critical to the security process. Ensuring the identity is secure by proper authentication, implementation, and monitoring is critical to ensuring effective overall security.





Identity Theft



Identity theft is a growing problem plaguing today’s world. This term simply describes the misuse and misrepresentation of information associated with one individual for the benefit of another. This unfortunate circumstance has escalated in recent years for numerous reasons. Your job is to ensure that you are not adding to the problem.


Protecting user identities can be just as important as protecting the data the identities get access to. Knowing as little as a person’s social security number and their date of birth, someone may be able to steal an identity to open a new bank account, apply for loans, buy expensive toys, or do countless other illegal activities under the guise of being someone else.


Why all this talk about identity theft in this book? Because a lot of the information that can be used to create false identities is siphoned from databases and poorly designed applications. The improper choice of an identifier could be a catalyst for identity theft.


Let’s look at a possible table structure to see what risks exist.


CREATE TABLE customers  (last_name VARCHAR2(50),
first_name VARCHAR2(50),
ssn VARCHAR2(11),
date_of_birth DATE);

The data in this table is clearly sensitive. Protecting access to the data in this table is an obvious security requirement. There is also a not-so-obvious security risk.


It wouldn’t be unusual for the application designer to use the SSN as the user’s identifier. This is very risky and considered to be a very bad decision. The reason is that user identifiers are sometimes required by application developers for testing or debugging, the DBAs for verifying database access, as well as the intended application users/end users that interact with the application on a daily basis.


As such, there is a significant risk that the SSN and the user’s name or date of birth would be handled inappropriately—written on paper and left on someone’s desk, or e-mailed in an insecure manner. This could lead to the inadvertent disclosure of this sensitive information. It is this type of practice that can lead to identity theft. You should carefully evaluate the identifiers you use to ensure that sensitive and privacy-related information is not being used to represent the user’s identity.




















About This Book









Introduction






Ubuntu Linux For Dummies tells you how you can use the fastest growing Linux distribution on the planet. Ubuntu Linux is very easy to use (even if you've only used Windows before) and provides a powerful platform on which to get your work done. Ubuntu is also fun to use!


You can use Ubuntu Linux as fast as you can rip the companion CD out of its plastic sleeve in the back of the book, pop it into your CD-ROM drive, and reboot your computer. Ubuntu Linux is available as a live Linux distribution, which means it boots directly from the CD-ROM included with this book, and you can start using it right away.


When you get the feel for Ubuntu Linux, you can install it on your computer from the Ubuntu Linux For Dummies CD-ROM. One of Ubuntu's strengths is — in my opinion — its easy-to-use installation system. Answer a handful of questions, and you've got yourself a full-blown Linux computer. Easy.


You'll also find that Ubuntu Linux works great as your everyday computer workstation. Ubuntu is designed to help you perform all of your primary tasks, such as word processing and Web browsing — and most of the other things you might want to do, such as instant messaging. If you've got a job for a PC, Ubuntu can do it for you.




About This Book


I wrote Ubuntu Linux For Dummies to help you get started using Ubuntu Linux and have some fun along the way. First, the book helps you get started using Ubuntu by covering the essentials, such as booting Ubuntu live and then installing it on your computer. After getting started, I explain how you can use Ubuntu's major components, such as networking, office productivity tools, and such. I use extensive examples to show exactly how to install, configure, and use the included software.









11.4 Expressions with NULL



[ Team LiB ]





11.4 Expressions with NULL


The combination of a NULL with an AND in a predicate will not give you the results you expect. A variable that is NULL has no value. Therefore, you cannot compare it to anything else with meaningful results. An expression of comparison with a NULL does not evaluate. When such an expression exists within an IF statement and there is an ELSE part, the code does not evaluate to TRUE, so it follows the ELSE path. From this, it can appear that the condition evaluates to FALSE. If you then reverse the logic in the IF test with a NOT operator, the same ELSE path is taken.


Consider two variables: OTHER_NAME and MY_NAME. A NULL initializes the variable OTHER_NAME.





my_name VARCHAR2(100) := 'SCOTT';
other_name VARCHAR2(10) := NULL;

The following expression does not evaluate:





IF (my_name = 'SCOTT' AND other_name = 'JOHN') THEN

Because this expression does not evaluate, it cannot possibly evaluate to TRUE. Hence, the following PL/SQL will follow the ELSE path.





set serveroutput on
DECLARE
my_name VARCHAR2(10) := 'SCOTT';
other_name VARCHAR2(10) := NULL;
BEGIN
IF (my_name = 'SCOTT' AND other_name = 'JOHN') THEN
dbms_output.put_line('CONDITION_TRUE');
ELSE
dbms_output.put_line('CONDITION_FALSE');
END IF;
END;

The result of this script is the following (notice the execution path follows the ELSE part).





CONDITION_FALSE
PL/SQL procedure successfully completed.
SQL>

Based on this outcome, the opposite of the IF condition should take the opposite execution path. That is, if we put a NOT before our test, then the code should NOT take the ELSE path and display CONDITION_TRUE. The following PL/SQL block is changed. The only change is to place a NOT in the IF statement.





set serveroutput on
DECLARE
my_name VARCHAR2(10) := 'SCOTT';
other_name VARCHAR2(10) := NULL;
BEGIN
IF NOT (my_name = 'SCOTT' AND other_name = 'JOHN') THEN
dbms_output.put_line('CONDITION_TRUE');
ELSE
dbms_output.put_line('CONDITION_FALSE');
END IF;
END;

The result of this script is the same.





CONDITION_FALSE
PL/SQL procedure successfully completed.
SQL>

Based on the preceding two PL/SQL blocks, the following is never true





(my_name = 'SCOTT' AND other_name = 'JOHN')

The following is also never true:





NOT (my_name = 'SCOTT' AND other_name = 'JOHN')

The conclusion from this is that PL/SQL conditions with an AND part and a NULL expression do not evaluate. They do not evaluate to TRUE; they do not evaluate to FALSE. If there is an ELSE part in the IF statement, the code will take that path.


A condition with the OR operator that includes at least one test that evaluates to TRUE will behave as expected. The following expression displays CONDITION_TRUE because, at least, the first part, MY_NAME=SCOTT is TRUE.





set serveroutput on
DECLARE
my_name VARCHAR2(10) := 'SCOTT';
other_name VARCHAR2(10) := NULL;
BEGIN
IF (my_name = 'SCOTT' OR other_name = 'JOHN') THEN
dbms_output.put_line('CONDITION_TRUE');
ELSE
dbms_output.put_line('CONDITION_FALSE');
END IF;
END;

This output is TRUE because at least MY_NAME=SCOTT is true.





CONDITION_TRUE
PL/SQL procedure successfully completed.
SQL>

When all parts of an OR condition do not evaluate, the entire expression does not evaluate. In this case, the statement is neither TRUE nor FALSE. The IF test fails to be TRUE because it does not evaluate. This takes the code to the ELSE part and leads one to believe that the condition does not evaluate to TRUE and must be FALSE. This is the case for the following:





set serveroutput on
DECLARE
my_name VARCHAR2(10) := 'SCOTT';
other_name VARCHAR2(10) := NULL;
BEGIN
IF (other_name = 'JOHN' OR other_name = 'SCOTT') THEN
dbms_output.put_line('CONDITION_TRUE');
ELSE
dbms_output.put_line('CONDITION_FALSE');
END IF;
END;

Because no part of the OR test evaluates, the entire test does not evaluate. The result of the preceding block is the following output.





CONDITION_FALSE
PL/SQL procedure successfully completed.
SQL>

Reversing the logic of the IF test does not reverse the execution path, as shown next.





set serveroutput on
DECLARE
my_name VARCHAR2(10) := 'SCOTT';
other_name VARCHAR2(10) := NULL;
BEGIN
IF NOT (other_name = 'JOHN' OR other_name = 'SCOTT') THEN
dbms_output.put_line('CONDITION_TRUE');
ELSE
dbms_output.put_line('CONDITION_FALSE');
END IF;
END;

The result is the same. The IF condition does not evaluate. It follows the execution of the ELSE path, shown here.





CONDITION_FALSE
PL/SQL procedure successfully completed.
SQL>

We can use the NVL operator in these situations.


NVL is a function that takes two arguments. If the first argument is NULL, the NVL function returns the second argument. For the following, NVL returns 1 when ARG is NULL.





NVL(arg, 1)

You can nest NVL functions. This allows you to select a NOT NULL value from a list of candidates. Consider variables: A, B, and C. You want A. If it is NULL, then use B. If that is NULL, then use C. If all are NULL, then use zero. The expression for this is:





NVL(A, NVL(B, NVL(C,0)))

For the following, we can replace OTHER_NAME with a blank only when it is NULL. This removes NULLs from the Boolean expression.





set serveroutput on
DECLARE
my_name VARCHAR2(10) := 'SCOTT';
other_name VARCHAR2(10) := NULL;
BEGIN
IF
NOT (NVL(other_name,' ') = 'JOHN' OR
NVL(other_name,' ') = 'SCOTT')
THEN
dbms_output.put_line('CONDITION_TRUE');
ELSE
dbms_output.put_line('CONDITION_FALSE');
END IF;
END;

The output from this block is:





CONDITION_TRUE
PL/SQL procedure successfully completed.
SQL>

In summary, use caution when writing PL/SQL procedures that have IN or IN OUT mode parameters and those parameters are to be embedded in IF statements with ELSE logic. Someone may call your procedure passing a NULL and the code will execute a path that makes no sense.


A strategy is to emphasize NOT NULL constraints in the schema tables. By applying NOT NULL constraints, the values read from select statements will not be NULL. A goal should be to reduce the number of NULL variables within an application.


You also have the NVL function as shown earlier. You can use the NVL operator in your SQL select statements. This can be an initial opportunity to translate a NULL to a blank or zero as you pull the data from the database.


You can replace database NULL defaults with a NOT NULL value (see Chapter 3). A SQL INSERT and UPDATE places a NULL into a column that is not referenced in the SQL statement. This is the default behavior. Consider a table column that stores a checkbook balance. Make the default a zero rather than NULL. PL/SQL code that queries checkbook data will get a zero rather than a NULL. The decision to use a zero default rather than a NULL is because the absence of money, in this case, is zero. This eliminates the concern with embedding a checkbook balance within Boolean expressions.





    [ Team LiB ]



    Command Summary








     

     










    Command Summary



    This section summarizes the shell's built-in commands. Actually, some of these commands (such as echo and test) may not be built in to the shell but must be provided as a utility by a POSIX-compliant system. They are built in to Bash and the Korn shell and are so often used in shell scripts that we decided to list them here anyway.



    The following commands are organized alphabetically for easy reference.



    The : Command



    General Format: :



    This is essentially a null command. It is frequently used to satisfy the requirement that a command appear.



    Example





    if who | grep jack > /dev/null

    then

    :

    else

    echo "jack's not logged in"

    fi



    The : command returns an exit status of zero.



    The . Command



    General Format: . file



    The "dot" command causes the indicated file to be read and executed by the shell, just as if the lines from the file were typed at that point. Note that file does not have to be executable, only readable. Also, the shell uses the PATH variable to find file.



    Example





    . progdefs Execute commands in progdefs



    The preceding command causes the shell to search the current PATH for the file progdefs. When it finds it, it reads and executes the commands from the file.



    Note that because file is not executed by a subshell, variables set and/or changed within file remain in effect after execution of the commands in file is complete.



    The alias Command



    General Format: alias name=string [name=string ...]



    The alias command assigns string to the alias name. Whenever name is used as a command, the shell substitutes string, performing command-line substitution after string is in place.



    Examples





    alias ll='ls �l'



    alias dir='basename $(pwd)'



    If an alias ends with a blank, the word following the alias is also checked to see whether it's an alias.



    The format





    alias name



    causes the alias for name to be printed out.



    alias with no arguments lists all aliases.



    alias returns an exit status of zero unless a name is given (as in alias name) for which no alias has been defined.



    The bg Command



    General Format: bg job_id



    If job control is enabled, the job identified by job_id is put into the background. If no argument is given, the most recently suspended job is put into the background.



    Example





    bg %2



    The break Command



    General Format: break



    Execution of this command causes execution of the innermost for, while, or until loop to be immediately terminated. Execution continues with the commands that immediately follow the loop.



    If the format





    break n



    is used, where n is an integer greater than or equal to 1, execution of the n innermost loops is automatically terminated.



    The case Command



    General Format:





    case value in

    patl) command

    command

    ...

    command;;

    pat2) command

    command

    ...

    command;;

    ...

    patn) command

    command

    ...

    command;;

    esac



    The word value is successively compared against patl, pat2, ..., patn until a match is found. The commands that appear immediately after the matching pattern are then executed until a double semicolon (;;) is encountered. At that point, execution of the case is terminated.



    If no pattern matches value, none of the commands inside the case are executed. The pattern * matches anything and is often used as the last pattern in a case as the "catchall" case.



    The shell metacharacters * (match zero or more characters), ? (match any single character), and [...] (match any single character enclosed between the brackets) can be used in patterns. The character | can be used to specify a logical ORing of two patterns, as in



    patl | pat2



    which means to match either patl or pat2.



    Examples





    case $1 in

    -l) lopt=TRUE;;

    -w) wopt=TRUE;;

    -c) copt=TRUE;;

    *) echo "Unknown option";;

    esac



    case $choice in

    [1-9]) valid=TRUE;;

    *) echo "Please choose a number from 1-9";;

    esac



    The cd Command



    General Format: cd directory



    Execution of this command causes the shell to make directory the current directory. If directory is omitted, the shell makes the directory specified in the HOME variable the current directory.



    If the shell variable CDPATH is null, directory must be a full directory path (for example, /users/steve/documents) or relative to the current directory (for example, documents, ../pat).



    If CDPATH is non-null and directory is not a full path, the shell searches the colon-delimited directory list in CDPATH for a directory containing directory.



    Examples





    $ cd documents/memos Change to documents/memos directory



    $ cd Change to HOME directory



    An argument of - causes the shell to make the previous directory the current directory. The pathname of the new current directory is printed out.



    Examples





    $ pwd

    /usr/lib/uucp

    $ cd /

    $ cd -

    /usr/lib/uucp

    $



    The cd command sets the shell variable PWD to the new current directory, and OLDPWD to the previous directory.



    The continue command



    General Format: continue



    Execution of this command from within a for, while, or until loop causes any commands that follow the continue to be skipped. Execution of the loop then continues as normal.



    If the format





    continue n



    is used, the commands within the n innermost loops are skipped. Execution of the loops then continue as normal.



    The echo Command



    General Format: echo args



    This command causes args to be written to standard output. Each word from args is delimited by a blank space. A newline character is written at the end. If args is omitted, the effect is to simply skip a line.



    Certain backslashed characters have a special meaning to echo as shown in Table A.8.





































































































    Table A.8. echo Escape Characters


    Character





    Prints





    \a





    Alert





    \b





    Backspace





    \c





    The line without a terminating newline





    \f





    Formfeed





    \n





    Newline





    \r





    Carriage return





    \t





    Tab character





    \v





    Vertical tab character





    \\





    Backslash character





    \0nnn





    The character whose ASCII value is nnn, where nnn is a one- to three-digit octal number that starts with a zero





    Remember to quote these characters so that the echo command interprets them and not the shell.



    Examples





    $ echo * List all files in the current directory

    bin docs mail mise src

    $ echo Skip a line



    $ echo 'X\tY' Print X and Y, separated by a tab

    X Y

    $ echo "\n\nSales Report" Skip two lines before displaying Sales Report



    Sales Report

    $ echo "Wake up!!\a" Print message and beep terminal

    Wake up!!

    $



    The eval Command



    General Format: eval args



    Execution of this command causes the shell to evaluate args and then execute the results. This is useful for causing the shell to effectively "double-scan" a command line.



    Example





    $ x='abc def'

    $ y='$x' Assign $x to y

    $ echo $y

    $x

    $ eval echo $y

    abc def

    $



    The exec Command



    General Format: exec command args



    When the shell executes the exec command, it initiates execution of the specified command with the indicated arguments. Unlike other commands executed as a new process, command replaces the current process (that is, no new process is created). After command starts execution, there is no return to the program that initiated the exec.



    If just I/O redirection is specified, the input and/or output for the shell is accordingly redirected.



    Examples





    exec /bin/sh Replace current process with sh



    exec < datafile Reassign standard input to datafile



    The exit Command



    General Format: exit n



    Execution of exit causes the current shell program to be immediately terminated. The exit status of the program is the value of the integer n, if supplied. If n is not supplied, the exit status is that of the last command executed prior to the exit.



    An exit status of zero is used by convention to indicate "success," and nonzero to indicate "failure" (such as an error condition). This convention is used by the shell in evaluation of conditions for if, while, and until commands, and with the && and || constructs.



    Examples





    who | grep $user > /dev/null

    exit Exit with status of last grep



    exit 1 Exit with status of 1

    if finduser If finduser returns an exit status of zero then...

    then

    ...

    fi



    Note that executing exit from a login shell has the effect of logging you off.



    The export Command



    General Format: export variables



    The export command tells the shell that the indicated variables are to be marked as exported; that is, their values are to be passed down to subshells.



    Examples





    export PATH PS1



    export dbhome x1 y1 date



    Variables may be set when exported using the form





    export variable=value...



    So lines such as





    PATH=$PATH:$HOME/bin; export PATH

    CDPATH=.:$HOME:/usr/spool/uucppublic; export CDPATH



    can be rewritten as





    export PATH=$PATH:$HOME/bin CDPATH=.:$HOME:/usr/spool/uucppublic



    The output of export with a �p argument is a list of the exported variables and their values in the form





    export variable=value



    or





    export variable



    if variable has been exported but not yet set.



    The false Command



    General Format: false



    The false command simply returns a nonzero exit status.



    The fc Command



    General Format: fc -e editor -lnr first last





    fc �s old=new first





    The fc command is used to edit commands in the command history. A range of commands is specified from first to last, where first and last can be either command numbers or strings; a negative number is taken as an offset from the current command number; a string specifies the most recently entered command beginning with that string. The commands are read into the editor and executed upon exit from the editor. If no editor is specified, the value of the shell variable FCEDIT is used; if FCEDIT is not set, ed is used.



    The -l option lists the commands from first to last (that is, an editor is not invoked). If the -n option is also selected, these commands are not preceded by command numbers.



    The -r option to fc reverses the order of the commands.



    If last is not specified, it defaults to first. If first is also not specified, it defaults to the previous command for editing and to -16 for listing.



    The �s option causes the selected command to be executed without editing it first. The format





    fc -s old=new first



    causes the command first to be re-executed after the string old in the command is replaced with new. If first isn't specified, the previous command is used, and if old=new isn't specified, the command is not changed.



    Examples





    fc -l List the last 16 commands



    fc -e vi sed Read the last sed command into vi



    fc 100 110 Read commands 100 to 110 into $FCEDIT



    fc -s Re-execute the previous command



    fc -s abc=def 104 Re-execute command 104, replacing abc with def



    The fg Command



    General Format: fg job_id



    If job control is enabled, the job specified by job_id is brought to the foreground. If no argument is given, the most recently suspended job, or the job last sent to the background is brought to the foreground.



    Example





    fg %2



    The for Command



    General Format:





    for var in wordl word2 ... wordn

    do

    command

    command

    ...

    done



    Execution of this command causes the commands enclosed between the do and done to be executed as many times as there are words listed after the in.



    The first time through the loop, the first word�wordl�is assigned to the variable var and the commands between the do and done executed. The second time through the loop, the second word listed�word2�is assigned to var and the commands in the loop executed again. This process continues until the last variable in the list�wordn�is assigned to var and the commands between the do and done executed. At that point, execution of the for loop is terminated. Execution then continues with the command that immediately follows the done.



    The special format





    for var

    do

    ...

    done



    indicates that the positional parameters "$1", "$2", ... are to be used in the list and is equivalent to





    for var in "$@"

    do

    ...

    done



    Example





    # nroff all of the files in the current directory

    for file in *

    do

    nroff -Tlp $file | lp

    done



    The getopts Command



    General Format: getopts options var



    This command processes command-line arguments. options is a list of valid single letter options. If any letter in options is followed by a :, that option takes a following argument on the command line, which must be separated from the option by at least one whitespace character.



    Each time getopts is called, it processes the next command-line argument. If a valid option is found, getopts stores the matching option letter inside the specified variable var and returns a zero exit status.



    If an invalid option is specified (that is, one not listed in options), getopts stores a ? inside var and returns with a zero exit status. It also writes an error message to standard error.



    If an option takes a following argument, getopts stores the matching option letter inside var and stores the following command-line argument inside the special variable OPTARG. If no arguments are left on the command line, getopts stores a ? inside var and writes an error message to standard error.



    If no more options remain on the command line (that is, if the next command-line argument does not begin with a -), getopts returns a nonzero exit status.



    The special variable OPTIND is also used by getopts. It is initially set to 1 and is adjusted each time getopts returns to indicate the number of the next command-line argument to be processed.



    The argument -- can be placed on the command line to specify the end of the command-line arguments.



    getopts supports stacked arguments, as in





    repx -iau



    which is equivalent to





    repx -i -a -u



    Options that take following arguments may not be stacked.



    If the format





    getopts options var args



    is used, getopts parses the arguments specified by args rather than the command-line arguments.



    Example





    usage="Usage: foo [-r] [-O outfile] infile"



    while getopts ro: opt

    do

    case "$opt"

    in

    r) rflag=1;;

    O) oflag=1

    ofile=$OPTARG;;

    \?) echo "$usage"

    exit 1;;

    esac

    done



    if [ $OPTIND -gt $# ]

    then

    echo "Needs input file!"

    echo "$usage"

    exit 2

    fi



    shift $((OPTIND � 1))

    ifile=$1

    ...



    The hash Command



    General Format: hash commands



    This command tells the shell to look for the specified commands and to remember what directories they are located in. If commands is not specified, a list of the hashed commands is displayed.



    If the format





    hash -r



    is used, the shell removes all commands from its hash list. Next time any command is executed, the shell uses its normal search methods to find the command.



    Examples





    hash rolo whoq Add rolo and whoq to hash list



    hash Print hash list



    hash -r Remove hash list



    The if Command



    General Format:





    if commandt

    then

    command

    command

    ...

    fi



    commandt is executed and its exit status tested. If it is zero, the commands that follow up to the fi are executed. Otherwise, the commands that follow up to the fi are skipped.



    Example





    if grep $sys sysnames > /dev/null

    then

    echo "$sys is a valid system name"

    fi



    If the grep returns an exit status of zero (which it will if it finds $sys in the file sysnames), the echo command is executed; otherwise it is skipped.



    The built-in command test is often used as the command following the if.



    Example





    if [ $# -eq 0 ]

    then

    echo "Usage: $0 [-l] file ..."

    exit 1

    fi



    An else clause can be added to the if to be executed if the command returns a nonzero exit status. In this case, the general format of the if becomes





    if commandt

    then

    command

    command

    ...

    else

    command

    command

    ...

    fi



    If commandt returns an exit status of zero, the commands that follow up to the else are executed, and the commands between the else and the fi are skipped. Otherwise, commandt returns a nonzero exit status and the commands between the then and the else are skipped, and the commands between the else and the fi are executed.



    Example





    if [ -z "$line" ]

    then

    echo "I couldn't find $name"

    else

    echo "$line"

    fi



    In the preceding example, if line has zero length, the echo command that displays the message I couldn't find $name is executed; otherwise, the echo command that displays the value of line is executed.



    A final format of the if command is useful when more than a two-way decision has to be made. Its general format is





    if commandl

    then

    command

    command

    ...

    elif command2

    then

    command

    command

    ...

    elif commandn

    then

    command

    command

    ...

    else

    command

    command

    ...

    fi



    commandl, command2, ..., commandn are evaluated in order until one of the commands returns an exit status of zero, at which point the commands that immediately follow the then (up to another elif, else, or fi) are executed. If none of the commands returns an exit status of zero, the commands listed after the else (if present) are executed.



    Example





    if [ "$choice" = a ]

    then

    add $*

    elif [ "$choice" = d ]

    then

    delete $*

    elif [ "$choice" = l ]

    then

    list

    else

    echo "Bad choice!"

    error=TRUE

    fi



    The jobs Command



    General Format: jobs



    The list of active jobs is printed. If the -l option is specified, detailed information about each job, including its process id, is listed as well. If the -p option is specified, only process ids are listed.



    If an optional job_id is supplied to the jobs command, just information about that job is listed.



    Example





    $ sleep 100 &

    [1] 1104

    $ jobs

    [1] + Running sleep 100 &

    $



    The kill Command



    General Format: kill -signal job



    The kill command sends the signal signal to the specified process, where job is a process id number or job_id, and signal is a number or one of the signal names specified in <signal.h> (see the description of trap later in the chapter). kill �l lists these names. A signal number supplied with the �l option lists the corresponding signal name. A process id used with the �l option lists the name of the signal that terminated the specified process (if it was terminated by a signal).



    The �s option can also be used when a signal name is supplied, in which case the dash before the name is not used (see the following example).



    If signal isn't specified, TERM is used.



    Examples





    kill -9 1234

    kill -HUP %2

    kill �s TERM %2

    kill %1



    Note that more than one process id can be supplied to the kill command on the command line.



    The newgrp Command



    General Format: newgrp group



    This command changes your real group id (GID) to group. If no argument is specified, it changes you back to your default group.



    Examples





    newgrp shbook Change to group shbook



    newgrp Change back to default group



    If a password is associated with the new group, and you are not listed as a member of the group, you will be prompted to enter it.



    newgrp �l changes you back to your login group.



    The pwd Command



    General Format: pwd



    This command tells the shell to print your working directory, which is written to standard output.



    Examples





    $ pwd

    /users/steve/documents/memos

    $ cd

    $ pwd

    /users/steve

    $



    The read Command



    General Format: read vars



    This command causes the shell to read a line from standard input and assign successive whitespace-delimited words from the line to the variables vars. If fewer variables are listed than there are words on the line, the excess words are stored in the last variable.



    Specifying just one variable has the effect of reading and assigning an entire line to the variable.



    The exit status of read is zero unless an end-of-file condition is encountered.



    Examples





    $ read hours mins

    10 19

    $ echo "$hours:$mins"

    10:19



    $ read num rest

    39 East 12th Street, New York City 10003

    $ echo "$num\n$rest"

    39

    East 12th Street, New York City 10003



    $ read line

    Here is an entire line \r

    $ echo "$line"

    Here is an entire line r

    $



    Note in the final example that any leading whitespace characters get "eaten" by the shell when read. You can change IFS if this poses a problem.



    Also note that backslash characters get interpreted by the shell when you read the line, and any that make it through (double backslashes will get through as a single backslash) get interpreted by echo if you display the value of the variable.



    A �r option to read says to not treat a \character at the end of a line as line continuation.



    The readonly Command



    General Format: readonly vars



    This command tells the shell that the listed variables cannot be assigned values. These variables may be optionally assigned values on the readonly command line. If you subsequently try to assign a value to a readonly variable, the shell issues an error message.



    readonly variables are useful for ensuring that you don't accidentally overwrite the value of a variable. They're also good for ensuring that other people using a shell program can't change the values of particular variables (for example, their HOME directory or their PATH). The readonly attribute is not passed down to subshells.



    readonly with a �p option prints a list of your readonly variables.



    Example





    $ readonly DB=/users/steve/database Assign value to DB and make it readonly

    $ DB=foo Try to assign it a value

    sh: DB: is read-only Error message from the shell

    $ echo $DB But can still access its value

    /users/steve/database

    $



    The return Command



    General Format: return n



    This command causes the shell to stop execution of the current function and immediately return to the caller with an exit status of n. If n is omitted, the exit status returned is that of the command executed immediately prior to the return.



    The set Command



    General Format: set options args



    This command is used to turn on or off options as specified by options. It is also used to set positional parameters, as specified by args.



    Each single letter option in options is enabled if the option is preceded by a minus sign (-), or disabled if preceded by a plus sign (+). Options can be grouped, as in





    set -fx



    which enables the f and x options.



    Table A.9 summarizes the options that can be selected.





































































































































    Table A.9. set Options


    Meaning





    Option





    --





    Don't treat subsequent args preceded by a - as options. If there are no arguments, the positional parameters are unset.





    -a





    Automatically export all variables that are subsequently defined or modified.





    -b





    If supported by the implementation, cause the shell to notify you when background jobs finish.





    -C





    Don't allow output redirection to overwrite existing files. >| can still be used to force individual files to be overwritten even if this option is selected.





    -e





    Exit if any command that gets executed fails or has a nonzero exit status.





    -f





    Disable filename generation.





    -h





    Add commands inside functions to the hash list as they are defined, and not as they are executed.





    -m





    Turn on the job monitor.





    -n





    Read commands without executing them (useful for checking for balanced do...dones, and if...fis).





    +o





    Write current option mode settings in command format.





    -o m





    Turn on option mode m (see Table A.10).





    -u





    Issue an error if a variable is referenced without having been assigned a value or if a positional parameter is referenced without having been set.





    -v





    Print each shell command line as it is read.





    -x





    Print each command and its arguments as it is executed, preceded by a +.





    Shell modes are turned on or off by using the -o and +o options, respectively, followed by an option name. These options are summarized in Table A.10.





















































































































    Table A.10. Shell Modes


    Mode





    Meaning





    allexport





    Same as -a.





    errexit





    Same as -e.





    ignoreeof





    The exit command must be used to leave the shell.





    monitor





    Same as -m.





    noclobber





    Same as -C.





    noexec





    Same as -n.





    noglob





    Same as -f.





    nolog





    Don't put function definitions in the history.





    nounset





    Same as -u.





    verbose





    Same as -v.





    vi





    The inline editor is set to vi.





    xtrace





    Same as -x.





    The command set -o without any following options has the effect of listing all shell modes and their settings.



    The shell variable $- contains the current options setting.



    Each word listed in args is set to the positional parameters $1, $2, ..., respectively. If the first word might start with a minus sign, it's safer to specify the -- option to set to avoid interpretation of that value.



    If args is supplied, the variable $# will be set to the number of parameters assigned after execution of the command.



    Examples





    set -vx Print all command lines as they are read,

    and each command and its arguments as

    it is executed



    set "$name" "$address" "$phone" Set $1 to $name, $2 to $address, and $3 to

    $phone



    set -- -1 Set $1 to -1



    set -o vi Turn on vi mode



    set +o verbose -o noglob Turn verbose mode off, noglob on



    The shift Command



    General Format: shift



    This command causes the positional parameters $1, $2, ..., $n to be "shifted left" one place. That is, $2 is assigned to $1, $3 to $2, ..., and $n to $n-1. $# is adjusted accordingly.



    If the format





    shift n



    is used instead, the shift is to the left n places.



    Examples





    $ set a b c d

    $ echo "$#\n$*"

    4

    a b c d

    $ shift

    $ echo "$#\n$*"

    3

    b c d

    $ shift 2

    $ echo "$#\n$*"

    1

    d

    $



    The test Command



    General Format:





    test condition



    or





    [ condition ]



    The shell evaluates condition and if the result of the evaluation is TRUE, returns a zero exit status. If the result of the evaluation is FALSE, a nonzero exit status is returned. If the format [ condition ] is used, a space must appear immediately after the [ and before the ].



    condition is composed of one or more operators as shown in Table A.11. The -a operator has higher precedence than the -o operator. In any case, parentheses can be used to group subexpressions. Just remember that the parentheses are significant to the shell and so must be quoted. Operators and operands (including parentheses) must be delimited by one or more spaces so that test sees them as separate arguments.



    test is often used to test conditions in an if, while, or until command.



    Examples





    # see if perms is executable



    if test -x /etc/perms

    then

    ...

    fi



    # see if it's a directory or a normal file that's readable



    if [ -d $file -o \( -f $file -a -r $file \) ]

    then

    ...

    fi





































































































































































































































































































    Table A.11. test Operators


    Operator





    Returns TRUE (zero exit status) if





    File Operators





    -b file





    file is a block special file





    -c file





    file is a character special file





    -d file





    file is a directory





    -e file





    file exists





    -f file





    file is an ordinary file





    -g file





    file has its set group id (SGID) bit set





    -h file





    file is a symbolic link





    -k file





    file has its sticky bit set





    -L file





    file is a symbolic link





    -p file





    file is a named pipe





    -r file





    file is readable by the process





    -S file





    file is a socket





    -s file





    file has nonzero length





    -t fd





    fd is open file descriptor associated with a terminal (1 is default)





    -u file





    file has its set user id (SUID) bit set





    -w file





    file is writable by the process





    -x file





    file is executable





    String Operators





    string





    string is not null





    -n string





    string is not null (and string must be seen by test)





    -z string





    string is null (and string must be seen by test)





    string1 = string2





    string1 is identical to string2





    string1 != string2





    string1 is not identical to string2





    Integer Comparison Operators





    int1 -eq int2





    int1 is equal to int2





    int1 -ge int2





    int1 is greater than or equal to int2





    int1 -gt int2





    int1 is greater than int2





    int1 -le int2





    int1 is less than or equal to int2





    int1 -lt int2





    int1 is less than int2





    int1 -ne int2





    int1 is not equal to int2





    Boolean Operators





    ! expr





    expr is FALSE; otherwise, returns TRUE





    expr1 -a expr2





    expr1 is TRUE, and expr2 is TRUE





    expr1 -o expr2





    expr1 is TRUE, or expr2 is TRUE





    The times Command



    General Format: times



    Execution of this command causes the shell to write to standard output the total amount of time that has been used by the shell and by all its child processes. For each, two numbers are listed: first the accumulated user time and then the accumulated system time.



    Note that times does not report the time used by built-in commands.



    Example





    $ times Print time used by processes

    1m5s 2m9s 1 min., 5 secs. user time, 2 mins., 9 secs. system time

    8m22.23s 6m22.01s Time used by child processes

    $



    The trap Command



    General Format: trap commands signals



    This command tells the shell to execute commands whenever it receives one of the signals listed in signals. The listed signals can be specified by name or number.



    trap with no arguments prints a list of the current trap assignments.



    If the first argument is the null string, as in





    trap "" signals



    the signals in signals are ignored when received by the shell.



    If the format





    trap signals



    is used, processing of each signal listed in signals is reset to the default action.



    Examples





    trap "echo hangup >> $ERRFILE; exit" 2 Log message and exit on hangup



    trap "rm $TMPFILE; exit" 1 2 15 remove $TMPFILE on signals l, 2, or 15



    trap "" 2 Ignore interrupts



    trap 2 Reset default processing of interrupts



    Table A.12 lists values that can be specified in the signal list.







































































































    Table A.12. Signal Numbers and Names for trap


    Signal #





    Signal Name





    Generated for





    0





    EXIT





    Exit from the shell





    1





    HUP





    Hangup





    2





    INT





    Interrupt (for example, Delete key, Ctrl+c)





    3





    QUIT





    Quit





    6





    ABRT





    Abort





    9





    KILL





    Kill





    14





    ALRM





    Alarm timeout





    15





    TERM





    Software termination signal (sent by kill by default)





    The shell scans commands when the trap command is encountered and again when one of the listed signals is received. This means, for example, that when the shell encounters the command





    trap "echo $count lines processed >> $LOGFILE; exit" HUP INT TERM



    it substitutes the value of count at that point, and not when one of the signals is received. You can get the value of count substituted when one of the signals is received if you instead enclose the commands in single quotes:





    trap 'echo $count lines processed >> $LOGFILE; exit' HUP INT TERM



    The true Command



    General Format: true



    This command returns a zero exit status.



    The type Command



    General Format: type commands



    This command prints information about the indicated commands.



    Examples





    $ type troff echo

    troff is /usr/bin/troff

    echo is a shell builtin

    $



    The umask Command



    General Format: umask mask



    umask sets the default file creation mask to mask. Files that are subsequently created are ANDed with this mask to determine the mode of the file.



    umask with no arguments prints the current mask. The �S option says to produce symbolic output.



    Examples





    $ umask Print current mask

    0002 No write to others

    $ umask 022 No write to group either

    $



    The unalias Command



    General Format: unalias names



    The alias's names are removed from the alias list. The �a option says to remove all aliases.



    The unset Command



    General Format: unset names



    This causes the shell to erase definitions of the variables or functions listed in names. Read-only variables cannot be unset. The �v option to unset specifies that a variable name follows, whereas the �f option specifies a function name. If neither option is used, it is assumed that variable name(s) follow.



    Example





    unset dblist files Remove definitions of variables dblist and files



    The until Command



    General Format:





    until commandt

    do

    command

    command

    ...

    done



    commandt is executed and its exit status tested. If it is nonzero, the commands enclosed between the do and done are executed. Then commandt is executed again and its status tested. If it is nonzero, the commands between the do and done are once again executed. Execution of commandt and subsequent execution of the commands between the do and done continues until commandt returns a zero exit status, at which point the loop is terminated. Execution then continues with the command that follows the done.



    Note that because commandt gets evaluated immediately on entry into the loop, the commands between the do and done may never be executed if it returns a zero exit status the first time.



    Example





    # sleep for 60 seconds until jack logs on

    until who | grep jack > /dev/null

    do

    sleep 60

    done



    echo jack has logged on



    The preceding loop continues until the grep returns a zero exit status (that is, finds jack in who's output). At that point, the loop is terminated, and the echo command that follows is executed.



    The wait Command



    General Format: wait job



    This command causes the shell to suspend its execution until the process identified as job finishes executing. Job can be a process id number or a job_id. If job is not supplied, the shell waits for all child processes to finish executing. If more than one process id is listed, wait will wait for them all to complete.



    wait is useful for waiting for processes to finish that have been sent to the background for execution.



    Example





    sort large_file > sorted_file & sort in the background

    . . . Continue processing

    wait Now wait for sort to finish

    plotdata sorted_file



    The variable $! can be used to obtain the process id number of the last process sent to the background.



    The while Command



    General Format:





    while commandt

    do

    command

    command

    ...

    done



    commandt is executed and its exit status tested. If it is zero, the commands enclosed between the do and done are executed. Then commandt is executed again and its status tested. If it is zero, the commands between the do and done are once again executed. Execution of commandt and subsequent execution of the commands between the do and done continues until commandt returns a nonzero exit status, at which point the loop is terminated. Execution then continues with the command that follows the done.



    Note that because commandt gets evaluated immediately on entry into the loop, the commands between the do and done may never be executed if it returns a nonzero exit status the first time.



    Example





    # fill up the rest of the buffer with blank lines



    while [ $lines -le $maxlines ]

    do

    echo >> $BUFFER

    lines=$((lines + 1))

    done