This commit is contained in:
gferg 2004-11-15 13:35:56 +00:00
parent 5998209da2
commit d904bba749
21 changed files with 793 additions and 182 deletions

View File

@ -6,6 +6,89 @@
http://personal.riverusers.com/~thegrendel/Change.log
------------------------------------------------------------------------
Version 3.1
Bayberry release, 11/14/04
1) In "Subshells" chapter:
Removed superfluous close-parenthesis from in-line example comments.
Removed doubled line in "lock file" in-line example.
(Thanks, bojster.)
Added example of the $BASH_SUBSHELL variable (new to Bash 3).
2) In "Complex Functions and Function Complexities" chapter:
Fixed typos in "realname.sh" example script.
(Thanks, bojster.)
3) In "Unofficial Shell Scripting Stylesheet" section of
Scripting With Style" chapter:
Fixed a couple of typos involving extra space and quote.
(Thanks, bojster.)
Added Ender's suggestion to use exit codes in /usr/include/sysexits.h.
Added Ender's list of suggested script invocation flags.
4) In "Colorizing Scripts" section of "Miscellany" chapter:
Added example of using bold foreground text, with note to that effect.
Updated link for Moshe Jacobson's project.
(Thanks, bojster.)
5) In "Assorted Tips" section of "Miscellany" chapter:
At "whatis" entry, added safer alternative to using that.
(Thanks, bojster.)
Added discussion of the use of the "rcs" package in script revisions.
6) In "System and Administrative Commands" chapter:
At "fuser" entry, added usage example.
7) Assorted other typos pointed out by bojster fixed.
8) In "$RANDOM" section of "Variables Revisited" chapter:
Removed an unnecessary variable from "ex21.sh" example.
(Thanks, jaka kranjc.)
9) In "Internal Variables" section of "Variables Revisited" chapter:
Fixed prefatory comment in "timed-input.sh" example.
Added $BASH_SUBSHELL variable (Bash 3 or later).
10) In "File and Archiving Commands" section of "External Commands" Chapter:
At "split" entry, added "csplit."
11) In "Gotchas" chapter:
Added "echo $BASH_SUBSHELL" command to Richardson/Berendsen example.
12) In "Debugging" chapter:
Added Kernighan quote at beginning.
Added list of debugging variables new to version 3 of Bash.
13) In "Bibliography" section:
Updated William Parks' bio and added his Nov. '04 "Linux Gazette"
article.
14) In "To Do List" appendix.
Added Michael Zick's "test-cgi.sh" script as a starter example.
15) In "Writing Scripts" section of "Exercises" appendix:
In "Difficult" section, added "Creating man pages" exercise .
16) In "Contributed Scripts" appendix:
Applied Daniel Albers' patch to "life.sh" to enable use of non-square
grids.
Added two additional reader exercises to "life.sh" script.
17) In "Localization" appendix:
Fixed quoting bug in "localized.sh" in-line example.
Numerous other changes and bugfixes.
(Thanks, Alfredo Pironti.)
18) In "History Commands" appendix:
Added $HISTTIMEFORMAT variable (new to Bash, ver. 3.0 or later).
Added link to "Advancing in the Bash Shell" site.
19) Added "Mirror Site" appendix.
20) Minor cleanups on various example scripts.
Version 3.0
Loganberry release, 10/03/04
@ -438,7 +521,7 @@ Version 2.5
8) In "Complex Commands" section of "External Commands" Chapter:
At "xargs" entry, added "kill-byname.sh" example script.
9) In "Complex Functions and Function Complexities"
9) In "Complex Functions and Function Complexities" chapter:
section of "Functions" chapter:
In discussion of capturing output of a function, corrected reference
of "parameter substitution" to "command substitution."

View File

@ -1,10 +1,29 @@
SOME SCRIPTS WILL NOT RUN AS IS
Note that the source code for some of the example shell scripts,
Note that the source code for certain of the example shell scripts
have the "&lt;" and "&gt;" in place of angle brackets (< and >), or &amp; in
place of the ampersand (&). This is necessary for the Docbook SGML
conversion. If you plan to run these scripts from the enclosed source
files, then it will, of course, be necessary to restore the angle
brackets or ampersand.
&lt; becomes <
&gt; becomes >
&lt;&lt; becomes <<
&lt;&lt; becomes <<<
&gt;&gt; becomes >>
&amp; becomes &
In some of the below cases, only the comments are affected, and these scripts
require no fixups to execute as expected.
Scripts needing to be altered:
-----------------------------
Du.sh
encryptedpw.sh
encryptedpw.sh (lines 27 and 35)
ex57.sh
ex70.sh
ex71.sh
@ -27,15 +46,3 @@ directory-info.sh (lines 273 and 353)
is-spammer.sh (comments on lines 4, 35, and 51)
bashrc (comments on lines 596 and 618)
is_spammer.bash (comments on various lines)
have the "&lt;" and "&gt;" in place of angle brackets (< and >), or &amp; in
place of the ampersand (&). This is necessary for the Docbook SGML
conversion. If you plan to run these scripts from the enclosed source
files, then it will, of course, be necessary to restore the angle
brackets or ampersand.
&lt; becomes <
&gt; becomes >
&lt;&lt; becomes <<
&gt;&gt; becomes >>
&amp; becomes &

View File

@ -308,6 +308,7 @@ Uncomment line below to generate index.
<!ENTITY avoidsubshell SYSTEM "avoid-subshell.sh">
<!ENTITY drawbox SYSTEM "Draw-box.sh">
<!ENTITY evalex SYSTEM "eval.example">
<!ENTITY testcgi SYSTEM "test-cgi.sh">
<!ENTITY namesdata SYSTEM "names.data">
<!ENTITY gen0data SYSTEM "gen0">
<!ENTITY bashrc SYSTEM "bashrc">
@ -328,19 +329,12 @@ Uncomment line below to generate index.
</affiliation>
</author>
<releaseinfo>3.0</releaseinfo>
<pubdate>03 October 2004</pubdate>
<releaseinfo>3.1</releaseinfo>
<pubdate>14 November 2004</pubdate>
<revhistory>
<revision>
<revnumber>2.7</revnumber>
<date>18 April 2004</date>
<authorinitials>mc</authorinitials>
<revremark>'MULBERRY' release: Minor update.</revremark>
</revision>
<revision>
<revnumber>2.8</revnumber>
<date>11 July 2004</date>
@ -355,6 +349,13 @@ Uncomment line below to generate index.
<revremark>'LOGANBERRY' release: Major update.</revremark>
</revision>
<revision>
<revnumber>3.1</revnumber>
<date>14 Nov 2004</date>
<authorinitials>mc</authorinitials>
<revremark>'BAYBERRY' release: Bugfix update.</revremark>
</revision>
</revhistory>
@ -375,7 +376,7 @@ Uncomment line below to generate index.
introduction to programming concepts.</para>
<para><ulink
url="http://personal.riverusers.com/~thegrendel/abs-guide-3.0.tar.bz2">
url="http://personal.riverusers.com/~thegrendel/abs-guide-3.1.tar.bz2">
The latest update of this document</ulink>, as an archived, <link
linkend="bzipref">bzip2-ed</link> <quote>tarball</quote>
including both the SGML source and rendered HTML, may
@ -5550,6 +5551,23 @@ echo "t2 = $t2 a = $a" # t2 = 5 a = 9</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term><anchor id="bashsubshellref"><varname>$BASH_SUBSHELL</varname></term>
<indexterm>
<primary>$BASH_SUBSHELL</primary>
</indexterm>
<indexterm>
<primary>variable</primary>
<secondary>subshell</secondary>
</indexterm>
<listitem>
<para>a variable indicating the <link
linkend="subshellsref">subshell</link> level. This is a
new addition to <link linkend="bash3ref">Bash, version 3</link>.</para>
<para>See <xref linkend="subshell"> for usage.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$BASH_VERSINFO[n]</varname></term>
<indexterm>
@ -12797,7 +12815,7 @@ tr -d 0-9 &lt;filename
</varlistentry>
<varlistentry>
<term><command>groff</command></term>
<term><anchor id="groffref"><command>groff</command></term>
<term><command>tbl</command></term>
<term><command>eqn</command></term>
<indexterm>
@ -13825,6 +13843,7 @@ gzip -cd patchXX.gz | patch -p0
<varlistentry>
<term><command>split</command></term>
<term><command>csplit</command></term>
<indexterm>
<primary>split</primary>
</indexterm>
@ -13832,10 +13851,23 @@ gzip -cd patchXX.gz | patch -p0
<primary>command</primary>
<secondary>split</secondary>
</indexterm>
<indexterm>
<primary>csplit</primary>
</indexterm>
<indexterm>
<primary>command</primary>
<secondary>csplit</secondary>
</indexterm>
<listitem>
<para>Utility for splitting a file into smaller chunks. Usually used
for splitting up large files in order to back them up on floppies or
preparatory to e-mailing or uploading them.</para>
<para>These are utilities for splitting a file into smaller
chunks. They are usually used for splitting up large files
in order to back them up on floppies or preparatory to
e-mailing or uploading them.</para>
<para>The <command>csplit</command> command splits a file
according to <emphasis>context</emphasis>, the split occuring
where patterns are matched.</para>
</listitem>
</varlistentry>
@ -13874,8 +13906,8 @@ gzip -cd patchXX.gz | patch -p0
the contents of key system files have not been altered
or corrupted. For security applications, use the 128-bit
<command>md5sum</command> (<command>m</command>essage
<command>d</command>igest check<command>sum</command>)
command.</para>
<command>d</command>igest <command>5</command>
check<command>sum</command>) command.</para>
<para>
@ -17461,6 +17493,31 @@ Average: all 6.33 1.70 14.71 0.00 77.26</compute
those processes. This has interesting implications for
system security, especially in scripts preventing
unauthorized users from accessing system services.</para>
<para>One important application for <command>fuser</command> is
when physically inserting or removing storage media, such
as CD ROM disks or USB flash drives. Sometimes trying
a <link linkend="umountref">umount</link> fails with a
<errorname>device is busy</errorname> error message. This
means that some user(s) and/or process(es) are accessing
the device. An <command>fuser -um /device_name</command>
will clear up the mystery, so you can kill any relevant
processes.</para>
<para>
<screen><prompt>bash$ </prompt><userinput>umount /mnt/usbdrive</userinput>
<computeroutput>umount: /mnt/usbdrive: device is busy</computeroutput>
<prompt>bash$ </prompt><userinput>fuser -um /dev/usbdrive</userinput>
<computeroutput>/mnt/usbdrive: 1772c(bozo)</computeroutput>
<prompt>bash$ </prompt><userinput>kill -9 1772</userinput>
<prompt>bash$ </prompt><userinput>umount /mnt/usbdrive</userinput>
</screen>
</para>
</listitem>
</varlistentry>
@ -17821,7 +17878,7 @@ ls -alR # List the files in the directory tree there.
</varlistentry>
<varlistentry>
<term><command>umount</command></term>
<term><anchor id="umountref"><command>umount</command></term>
<indexterm>
<primary>umount</primary>
</indexterm>
@ -20769,12 +20826,11 @@ fi # Variable has been set in current script,
# Could also be written [[ ${variable-x} != x || ${variable-y} != y ]]
# or [[ ${variable-x} != x$variable ]]
# or [[ ${variable+x} = x ]])
# or [[ ${variable-x} != x ]])</programlisting>
# or [[ ${variable+x} = x ]]
# or [[ ${variable-x} != x ]]</programlisting>
Another application is checking for a lock file:
<programlisting>if (set -C; : &gt; lock_file) 2&gt; /dev/null
if (set -C; : > lock_file) 2> /dev/null
then
: # lock_file didn't exist: no user running the script
else
@ -22342,7 +22398,7 @@ exit 0</programlisting></para>
</para>
<para>Getting the time from from <filename>nist.gov</filename>:</para>
<para>Getting the time from <filename>nist.gov</filename>:</para>
<screen><prompt>bash$ </prompt><userinput>cat &lt;/dev/tcp/time.nist.gov/13</userinput>
<computeroutput>53082 04-03-18 04:26:54 68 0 0 502.3 UTC(NIST) *</computeroutput>
</screen>
@ -22633,6 +22689,13 @@ ln -s /dev/null ~/.netscape/cookies
<chapter id="debugging">
<title>Debugging</title>
<epigraph>
<attribution>Brian Kernighan</attribution>
<para>Debugging is twice as hard as writing the code in the first
place. Therefore, if you write the code as cleverly as possible,
you are, by definition, not smart enough to debug it.</para>
</epigraph>
<para>The Bash shell contains no debugger, nor even any
debugging-specific commands or constructs.
@ -22871,6 +22934,21 @@ trap 'echo "Control-C disabled."' 2
trap 2 # Reenables Control-C
</programlisting></para>
<sidebar>
<para><link linkend="bash3ref">Version 3</link> of Bash adds the
following special variables for use by the debugger.
<orderedlist>
<listitem><para>$BASH_ARGC</para></listitem>
<listitem><para>$BASH_ARGV</para></listitem>
<listitem><para>$BASH_COMMAND</para></listitem>
<listitem><para>$BASH_EXECUTION_STRING</para></listitem>
<listitem><para>$BASH_LINENO</para></listitem>
<listitem><para>$BASH_SOURCE</para></listitem>
<listitem><para><link linkend="bashsubshellref">$BASH_SUBSHELL</link></para></listitem>
</orderedlist></para>
</sidebar>
</chapter> <!-- Debugging -->
@ -23321,7 +23399,8 @@ exit 0</programlisting>
Sure enough, back at the command prompt, $WHATEVER remains unset.
</para>
<para>Setting and manipulating variables in a subshell, then attempting
<para>Setting and manipulating variables in a <link
linkend="subshellsref">subshell</link>, then attempting
to use those same variables outside the scope of the subshell will
result an unpleasant surprise.</para>
@ -23361,6 +23440,11 @@ do
echo "$f is over 100KB and has not been accessed in over 30 days"
echo "Consider moving the file to archives."
foundone=true
# ------------------------------------
echo "Subshell level = $BASH_SUBSHELL"
# Subshell level = 1
# Yes, we're inside a subshell.
# ------------------------------------
done
# foundone will always be false here since it is
@ -23491,21 +23575,21 @@ find $HOME -type f -atime +30 -size 100k | {
# Clean up project files. #
#************************************************#
BADDIR=65 # No such directory.
projectdir=/home/bozo/projects # Directory to clean up.
E_BADDIR=65 # No such directory.
projectdir=/home/bozo/projects # Directory to clean up.
# ------------------------------------------------------- #
# cleanup_pfiles () #
# Removes all files in designated directory. #
# Parameter: $target_directory #
# Returns: 0 on success, $BADDIR if something went wrong. #
# ------------------------------------------------------- #
# --------------------------------------------------------- #
# cleanup_pfiles () #
# Removes all files in designated directory. #
# Parameter: $target_directory #
# Returns: 0 on success, $E_BADDIR if something went wrong. #
# --------------------------------------------------------- #
cleanup_pfiles ()
{
if [ ! -d "$1" ] # Test if target directory exists.
then
echo "$1 is not a directory."
return $BADDIR
return $E_BADDIR
fi
rm -f "$1"/*
@ -23523,9 +23607,9 @@ exit 0</programlisting>
</listitem>
<listitem>
<para>Avoid using <quote>magic numbers</quote>,
<para>Avoid using <quote>magic numbers,</quote>
<footnote><para>In this context, <quote> magic
<footnote><para>In this context, <quote>magic
numbers</quote> have an entirely different meaning than
the <link linkend="magnumref">magic numbers</link> used
to designate file types.</para></footnote>
@ -23608,8 +23692,48 @@ _uservariable=23 # Permissable, but not recommended.
...
exit $E_WRONG_ARGS</programlisting>
See also <xref linkend="exitcodes">.</para>
<para><emphasis>Ender</emphasis> suggests using the exit codes
in <filename>/usr/include/sysexits.h</filename> in shell
scripts, though these are primarily intended for C and C++
programming.</para>
</listitem>
<listitem>
<para>Use standardized parameter flags for script invocation.
<emphasis>Ender</emphasis> proposes the following set
of flags.</para>
<para>
<programlisting>-a All: Return all information (including hidden file info).
-b Brief: Short version, usually for other scripts.
-c Copy, concatenate, etc.
-d Daily: Use information from the whole day, and not merely
information for a specific instance/user.
-e Extended/Elaborate: (often does not include hidden file info).
-h Help: Verbose usage w/descs, aux info, discussion, help.
See also -V.
-l Log output of script.
-m Manual: Launch man-page for base command.
-n Numbers: Numerical data only.
-r Recursive: All files in a directory (and/or all sub-dirs).
-s Setup & File Maintenance: Config files for this script.
-u Usage: List of invocation flags for the script.
-v Verbose: Human readable output, more or less formatted.
-V Version / License / Copy(right|left) / Contribs (email too).</programlisting>
</para>
<para>See also <xref linkend="standard-options">.</para>
</listitem>
<listitem>
<para>Break complex scripts into simpler modules. Use functions
where appropriate. See <xref linkend="ex79">.</para>
@ -23939,7 +24063,7 @@ test "$city" \< Paris && echo "Yes, Paris is greater than $city" # Greater ASCI
</para>
<para>A similar escape sequence switches on the underline
attribute (on an <emphasis>rxvt</emphasis> and and an
attribute (on an <emphasis>rxvt</emphasis> and an
<emphasis>aterm</emphasis>).
<screen>
<prompt>bash$ </prompt><userinput>echo -e "\033[4mThis is underlined text.\033[0m"</userinput>
@ -23959,9 +24083,16 @@ test "$city" \< Paris && echo "Yes, Paris is greater than $city" # Greater ASCI
<prompt>bash$ </prompt><userinput>echo -e '\E[33;44m'"yellow text on blue background"; tput sgr0</userinput>
<prompt>bash$ </prompt><userinput>echo -e '\E[1;33;44m'"BOLD yellow text on blue background"; tput sgr0</userinput>
</screen>
</para>
<note><para>It's usually advisable to set the
<emphasis>bold</emphasis> attribute for light-colored foreground
text.</para></note>
<para>The <command>tput sgr0</command> restores the
terminal settings to normal. Omitting this lets all
subsequent output from that particular terminal remain
@ -24071,7 +24202,7 @@ test "$city" \< Paris && echo "Yes, Paris is greater than $city" # Greater ASCI
<para>Moshe Jacobson's <command>color</command> utility
(<ulink
url="http://runslinux.net/projects/color">http://runslinux.net/projects/color</ulink>)
url="http://runslinux.net/projects.html#color">http://runslinux.net/projects.html#color</ulink>)
considerably simplifies using ANSI escape sequences. It
substitutes a clean and logical syntax for the clumsy constructs
just discussed.</para>
@ -24144,7 +24275,7 @@ grep "$word" "$file"
<listitem>
<para>To keep a record of which user scripts have run
during a particular sesssion or over a number of sessions,
during a particular session or over a number of sessions,
add the following lines to each script you want to keep track
of. This will keep a continuing file record of the script
names and invocation times. </para>
@ -24152,12 +24283,13 @@ grep "$word" "$file"
<para>
<programlisting># Append (>>) following to end of each script tracked.
date>> $SAVE_FILE #Date and time.
echo $0>> $SAVE_FILE #Script name.
echo>> $SAVE_FILE #Blank line as separator.
whoami>> $SAVE_FILE # User invoking the script.
echo $0>> $SAVE_FILE # Script name.
date>> $SAVE_FILE # Date and time.
echo>> $SAVE_FILE # Blank line as separator.
# Of course, SAVE_FILE defined and exported as environmental variable in ~/.bashrc
# (something like ~/.scripts-run)</programlisting>
# Of course, SAVE_FILE defined and exported as environmental variable in ~/.bashrc
#+ (something like ~/.scripts-run)</programlisting>
</para>
</listitem>
@ -24342,7 +24474,7 @@ while [ "$var1" != "end" ] #> while test "$var1" != "end"</programlisting></p
<programlisting>#!/bin/bash
COMMENT_BLOCK=
# Try setting the above variable to something or other
# Try setting the above variable to some value
#+ for an unpleasant surprise.
if [ $COMMENT_BLOCK ]; then
@ -24545,6 +24677,13 @@ PlanB=command2 # Fallback option.
command_test=$(whatis "$CMD" | grep 'nothing appropriate')
# If 'command1' not found on system , 'whatis' will return
#+ "command1: nothing appropriate."
#
# A safer alternative is:
# command_test=$(whereis "$CMD" | grep \/)
# But then the sense of the following test would have to be reversed,
#+ since the $command_test variable holds content only if
#+ the $CMD exists on the system.
# (Thanks, bojster.)
if [[ -z "$command_test" ]] # Check whether command present.
@ -24631,7 +24770,23 @@ fi
extensions), or <emphasis>PyQt</emphasis> (Python with
Qt extensions).</para>
</listitem>
</listitem>
<listitem>
<para>For doing multiple revisions on a complex script, use the
<emphasis>rcs</emphasis> Revision Control System package.</para>
<para> Among
other benefits of this is automatically updated ID
header tags. The <command>co</command> command in
<emphasis>rcs</emphasis> does a parameter replacement of
certain reserved key words, for example, replacing
<parameter>#$Id$</parameter> in a script with something like:
<programlisting>#$Id$</programlisting></para>
</listitem>
</itemizedlist>
@ -24754,6 +24909,10 @@ fi
Mortice Kern Associates add shell scripting capabilities to
Windows.</para>
<para>There have been intimations that a future release of Windows
will contain Bash-like command line scripting capabilities,
but that remains to be seen.</para>
</sect1> <!-- Shell Scripting Under Windows -->
</chapter> <!-- Miscellany -->
@ -25153,16 +25312,18 @@ fi</programlisting>
Baris Cicek, Greg Keraunen, Keith Matthews, Sandro Magi, Albert
Reiner, Dim Segebart, Rory Winston, Lee Bigelow, Wayne Pollock,
<quote>jipe,</quote> <quote>Mark,</quote> <quote>bojster,</quote>
Emilio Conti, Ian. D. Allen, Arun Giridhar, Dennis Leeuw, Dan
Jacobson, Aurelio Marinho Jargas, Edward Scholtz, Jean Helou,
Chris Martin, Lee Maschmeyer, Bruno Haible, Wilbert Berendsen,
Sebastien Godard, Bj&ouml;n Eriksson, <quote>nyal,</quote> John
MacDonald, Joshua Tschida, Troy Engel, Manfred Schwarb, Amit
Singh, Bill Gradwohl, David Lombard, Jason Parker, Steve Parker,
Bruce W. Clare, William Park, Vernia Damiano, Mihai Maties, Jeremy
Impson, Ken Fuchs, Frank Wang, Sylvain Fourmanoit, Matthew Walker,
Kenny Stauffer, Filip Moritz, Andrzej Stefanski, Stefano Palmeri,
and David Lawyer (himself an author of four HOWTOs).</para>
<quote>Ender</quote>, Emilio Conti, Ian. D. Allen, Arun
Giridhar, Dennis Leeuw, Dan Jacobson, Aurelio Marinho Jargas,
Edward Scholtz, Jean Helou, Chris Martin, Lee Maschmeyer,
Bruno Haible, Wilbert Berendsen, Sebastien Godard, Bj&ouml;n
Eriksson, <quote>nyal,</quote> John MacDonald, Joshua Tschida,
Troy Engel, Manfred Schwarb, Amit Singh, Bill Gradwohl, David
Lombard, Jason Parker, Steve Parker, Bruce W. Clare, William
Park, Vernia Damiano, Mihai Maties, Jeremy Impson, Ken Fuchs,
Frank Wang, Sylvain Fourmanoit, Matthew Walker, Kenny Stauffer,
Filip Moritz, Andrzej Stefanski, Daniel Albers, Stefano Palmeri,
Alfredo Pironti, and David Lawyer (himself an author of four
HOWTOs).</para>
<para>My gratitude to <ulink url="mailto:chet@po.cwru.edu">Chet
Ramey</ulink> and Brian Fox for writing <command>Bash</command>,
@ -25814,11 +25975,20 @@ fi</programlisting>
<biblioentry>
<abstract>
<para><ulink url="mailto:opengeometry@yahoo.ca">William Park</ulink>
is working on a <ulink
url="http://home.eol.ca/~parkw/index.html">project</ulink> to
incorporate certain Awk and Python features into Bash. Among
these is a <emphasis>gdbm</emphasis> interface.</para>
has been working on a <ulink
url="http://home.eol.ca/~parkw/index.html">project</ulink>
to incorporate certain Awk and Python
features into Bash. Among these is a
<emphasis>gdbm</emphasis> interface. He has released <ulink
url="http://freshmeat.net/projects/bashdiff/">bashdiff</ulink>
on <ulink url="http://freshmeat.net">Freshmeat.net</ulink>. He
has an <ulink
url="http://linuxgazette.net/108/park.html">article</ulink>
in the November, 2004 issue of the <ulink
url="http://www.linuxgazette.net">Linux Gazette</ulink> on
adding string functions to Bash.</para>
</abstract>
</biblioentry>
<biblioentry>
@ -27662,7 +27832,8 @@ exit 0</programlisting>
<para>
<programlisting>#!/bin/bash
# localized.sh
# Script by Stephane Chazelas, modified by Bruno Haible
# Script by Stephane Chazelas,
#+ modified by Bruno Haible, bugfixed by Alfredo Pironti.
. gettext.sh
@ -27674,9 +27845,73 @@ error()
exit $E_CDERROR
}
cd $var || error "`eval_gettext \"Can't cd to \$var.\"`"
cd $var || error "`eval_gettext \"Can\'t cd to \$var.\"`"
read -p "`gettext \"Enter the value: \"`" var
# ...</programlisting>
# ...
# ------------------------------------------------------------------
# Alfredo Pironti comments:
# This script has been modified to not use the $"..." syntax in
#+ favor of the "`gettext \"...\"`" syntax.
# This is ok, but with the new localized.sh program, the commands
#+ "bash -D filename" and "bash --dump-po-string filename"
#+ will produce no output
#+ (because those command are only searching for the $"..." strings)!
# The ONLY way to extract strings from the new file is to use the
# 'xgettext' program. However, the xgettext program is buggy.
# Note that 'xgettext' has another bug.
#
# The shell fragment:
# gettext -s "I like Bash"
# will be correctly extracted, but . . .
# xgettext -s "I like Bash"
# . . . fails!
# 'xgettext' will extract "-s" because
#+ the command only extracts the
#+ very first argument after the 'gettext' word.
# Escape characters:
#
# To localize a sentence like
# echo -e "Hello\tworld!"
#+ you must use
# echo -e "`gettext \"Hello\\tworld\"`"
# The "double escape character" before the `t' is needed because
#+ 'gettext' will search for a string like: 'Hello\tworld'
# This is because gettext will read one literal `\')
#+ and will output a string like "Bonjour\tmonde",
#+ so the 'echo' command will display the message correctly.
#
# You may not use
# echo "`gettext -e \"Hello\tworld\"`"
#+ due to the xgettext bug explained above.
# Let's localize the following shell fragment:
# echo "-h display help and exit"
#
# First, one could do this:
# echo "`gettext \"-h display help and exit\"`"
# This way 'xgettext' will work ok,
#+ but the 'gettext' program will read "-h" as an option!
#
# One solution could be
# echo "`gettext -- \"-h display help and exit\"`"
# This way 'gettext' will work,
#+ but 'xgettext' will extract "--", as referred to above.
#
# The workaround you may use to get this string localized is
# echo -e "`gettext \"\\0-h display help and exit\"`"
# We have added a \0 (NULL) at the beginning of the sentence.
# This way 'gettext' works correctly, as does 'xgettext.'
# Moreover, the NULL character won't change the behavior
#+ of the 'echo' command.
# ------------------------------------------------------------------</programlisting>
</para>
@ -27726,17 +27961,22 @@ read -p "`gettext \"Enter the value: \"`" var
<para>Now, build a <filename>language.po</filename>
file for each language that the script will be translated
into, specifying the <replaceable>msgstr</replaceable>. As an
example:</para>
into, specifying the <replaceable>msgstr</replaceable>. Alfredo
Pironti gives the following example:</para>
<para>fr.po:
<programlisting>#: a:6
msgid "Can't cd to %s."
msgstr "Impossible de se positionner dans le répertoire %s."
msgid "Can't cd to $var."
msgstr "Impossible de se positionner dans le repertoire $var."
#: a:7
msgid "Enter the value: "
msgstr "Entrez la valeur : "</programlisting>
msgstr "Entrez la valeur : "
# The string are dumped with the variable names, not with the %s syntax,
#+ similar to C programs.
#+ This is a very cool feature if the programmer uses
#+ variable names that make sense!</programlisting>
</para>
<para>Then, run <link linkend="msgfmtref">msgfmt</link>.</para>
@ -27777,14 +28017,15 @@ read -p "$(gettext -s "Enter the value: ")" var
</note>
<para>The <varname>TEXTDOMAIN</varname> and
<varname>TEXTDOMAINDIR</varname> variables need to be exported
to the environment.</para>
<varname>TEXTDOMAINDIR</varname> variables need to be set and
exported to the environment. This should be done within the
script itself.</para>
<para>---</para>
<para>This appendix written by Stephane Chazelas, with modifications
suggested by Bruno Haible, maintainer of GNU
<link linkend="gettextref">gettext</link>.</para>
suggested by Alfredo Pironti, and by Bruno Haible, maintainer
of GNU <link linkend="gettextref">gettext</link>.</para>
</appendix>
<!-- Localization -->
@ -27822,6 +28063,7 @@ read -p "$(gettext -s "Enter the value: ")" var
<listitem><para>$HISTFILE</para></listitem>
<listitem><para>$HISTFILESIZE</para></listitem>
<listitem><para>$HISTSIZE</para></listitem>
<listitem><para>$HISTTIMEFORMAT (Bash, ver. 3.0 or later)</para></listitem>
<listitem><para>!!</para></listitem>
<listitem><para>!$</para></listitem>
<listitem><para>!#</para></listitem>
@ -27848,7 +28090,11 @@ history
<screen><prompt>bash$ </prompt><userinput>./history.sh</userinput>
<computeroutput>(no output)</computeroutput>
</screen>
</para>
</para>
<para>The <ulink url="http://www.deadman.org/bash.html">Advancing in the
Bash Shell</ulink> site gives a good introduction to the use of
history commands in Bash.</para>
@ -28815,6 +29061,32 @@ Smith,Tom,404 Polk Ave.,Los Angeles,CA,90003,(213) 879-5612
<para>As necessary, use the appropriate <link
linkend="communinfo1">network analysis commands</link>.</para>
<para>For some ideas, see <xref linkend="isspammer"> and <xref
linkend="isspammer2">.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>Creating man pages</command></term>
<listitem>
<para>Write a script that automates the process of creating
<emphasis>man pages</emphasis>.</para>
<para>Given a text file which contains information to be
formatted into a <emphasis>man page</emphasis>, the
script will read the file, then invoke the appropriate
<link linkend="groffref">groff</link> commands to
output the corresponding <emphasis>man page</emphasis>
to <filename>stdout</filename>. The text file contains
blocks of information under the standard <emphasis>man
page</emphasis> headings, i.e., <quote>NAME,</quote>
<quote>SYNOPSIS,</quote> <quote>DESCRIPTION,</quote>
etc.</para>
<para>See <xref linkend="manview">.</para>
</listitem>
</varlistentry>
@ -29272,6 +29544,11 @@ fairly detailed rundown on the Playfair Cipher and its solution methods.</progra
<entry>03 Oct 2004</entry>
<entry>LOGANBERRY release: Major update.</entry>
</row>
<row>
<entry><option>3.1</option></entry>
<entry>14 Nov 2004</entry>
<entry>BAYBERRY release: Bugfix update.</entry>
</row>
</tbody>
</tgroup>
</table>
@ -29279,6 +29556,31 @@ fairly detailed rundown on the Playfair Cipher and its solution methods.</progra
</appendix> <!-- End Revision History appendix -->
<appendix id="mirrorsites">
<title>Mirror Sites</title>
<para><ulink
url="http://personal.riverusers.com/~thegrendel/abs-guide-3.0.tar.bz2">
The latest update of this document</ulink>, as an archived
<quote>tarball</quote>
including both the SGML source and rendered HTML, may
be downloaded from the author's home site.</para>
<para>The main mirror site for this document is the <ulink
url="http://www.tldp.org/LDP/abs/">Linux Documentation Project</ulink>,
which maintains many other Guides and HOWTOs as well.</para>
<para><ulink
url="http://www.ibiblio.org/pub/Linux/docs/linux-doc-project/abs-guide/">Sunsite/Metalab/ibiblio.org</ulink>
also mirrors the <emphasis>ABS Guide</emphasis>.</para>
<para>Yet another mirror site for this document is
<ulink url="ftp://ftp.morethan.org">the morethan.org ftp site</ulink>.</para>
</appendix> <!-- Mirror Sites appendix -->
<appendix id="todolist">
<title>To Do List</title>
@ -29293,7 +29595,16 @@ fairly detailed rundown on the Playfair Cipher and its solution methods.</progra
</listitem>
<listitem>
<para>A primer on CGI programming, using Bash.</para>
<para>Here's a simple CGI script to get you started.</para>
<example id="testcgi">
<title>Print the server environment</title>
<programlisting>&testcgi;</programlisting>
</example>
</listitem>
</itemizedlist>
@ -29408,10 +29719,10 @@ B. Distribution of the work or derivative of the work in any standard
url="http://it.tldp.org/guide/abs/index.html">Italian</ulink>,
<ulink
url="http://gazette.linux.ru.net/rus/articles/index-abs-guide.html">Russian</ulink>,
and Chinese translations are also available or in progress. If
you wish to translate this document into another language, please
feel free to do so, subject to the terms stated above. The author
wishes to be notified of such efforts.</para>
Chinese, and Dutch translations are also available or in
progress. If you wish to translate this document into another
language, please feel free to do so, subject to the terms stated
above. The author wishes to be notified of such efforts.</para>
</appendix> <!-- End Copyright appendix -->

View File

@ -13,7 +13,8 @@ grep -v 'ed$' # no past tense verbs
# Uses "anagram" utility
#+ that is part of the author's "yawl" word list package.
# http://ibiblio.org/pub/Linux/libs/yawl-0.3.tar.gz
# http://ibiblio.org/pub/Linux/libs/yawl-0.3.2.tar.gz
# http://personal.riverusers.com/~thegrendel/yawl-0.3.2.tar.gz
exit 0 # End of code.

View File

@ -1,10 +1,11 @@
:
#!/bin/bash
##########################################################################
# Shellscript: base.sh - print number to different bases (Bourne Shell)
# Author : Heiner Steven (heiner.steven@odn.de)
# Date : 07-03-95
# Category : Desktop
# $Id$
# ==> Above line is RCS ID info.
##########################################################################
# Description
#

View File

@ -36,3 +36,8 @@ cat "$@" | tr "a-z" "A-Z" | tr "A-Z" "$key"
#+ using only pencil and paper.
exit 0
# Exercise:
# --------
# Modify the script so that it will either encrypt or decrypt,
#+ depending on command-line argument(s).

View File

@ -18,7 +18,7 @@ Username=bozo # Change to suit.
pword=/home/bozo/secret/password_encrypted.file
# File containing encrypted password.
Filename=`basename $1` # Strips pathname out of file name
Filename=`basename $1` # Strips pathname out of file name.
Server="XXX"
Directory="YYY" # Change above to actual server name & directory.
@ -41,6 +41,6 @@ put $Filename
bye
End-Of-Session
# -n option to "ftp" disables auto-logon.
# "bell" rings 'bell' after each file transfer.
# Note that "bell" rings 'bell' after each file transfer.
exit 0

View File

@ -77,7 +77,6 @@ echo
SPOTS=6 # Modulo 6 gives range 0 - 5.
# Incrementing by 1 gives desired range of 1 - 6.
# Thanks, Paulo Marcel Coelho Aragao, for the simplification.
ZERO=0
die1=0
die2=0

View File

@ -1,8 +1,9 @@
#!/bin/bash
# Uudecodes all uuencoded files in current working directory.
lines=35 # Allow 35 lines for the header (very generous).
for File in * # Test all the files in the current working directory...
for File in * # Test all the files in $PWD.
do
search1=`head -$lines $File | grep begin | wc -w`
search2=`tail -$lines $File | grep end | wc -w`
@ -22,7 +23,9 @@ done
#+ into thinking it is a uuencoded file,
#+ because it contains both "begin" and "end".
# Exercise:
# Modify this script to check for a newsgroup header.
# Exercise:
# --------
# Modify this script to check each file for a newsgroup header,
#+ and skip to next if not found.
exit 0

View File

@ -9,6 +9,6 @@ zzz23EndOfMessagezzz23
# Could have been done more efficiently by
# wall &lt;message-file
# However, saving a message template in a script saves work.
# However, embedding the message template in a script saves work.
exit 0

View File

@ -5,6 +5,7 @@
#+ to incoming directory at Sunsite/UNC (ibiblio.org).
# Filename.tar.gz is the tarball itself.
# Filename.lsm is the descriptor file.
# Sunsite requires "lsm" file, otherwise will bounce contributions.
E_ARGERROR=65
@ -30,7 +31,7 @@ ftp -n $Server &lt;&lt;End-Of-Session
user anonymous "$Password"
binary
bell # Ring 'bell' after each file transfer
bell # Ring 'bell' after each file transfer.
cd $Directory
put "$Filename.lsm"
put "$Filename.tar.gz"

View File

@ -1,11 +1,13 @@
#! /bin/bash
# is-spammer.sh: Identifying spam domains
# $Id$
# Above line is RCS ID info.
#
# This is a simplified version of the "is_spammer.bash
#+ script in the Contributed Scripts appendix.
# is-spammer &lt;domain.name&gt;
# $Id$
# Uses an external program: 'dig'
# Tested with version: 9.2.4rc5

View File

@ -1,5 +1,8 @@
#!/bin/bash
# $Id$
# Above line is RCS info.
# The latest version of this script is available from ftp://ftp.morethan.org.
#
# Spammer-identification

View File

@ -1,5 +1,7 @@
#!/bin/bash
# life.sh: "Life in the Slow Lane"
# Version 2: Patched by Daniel Albers
#+ to allow non-square grids as input.
# ##################################################################### #
# This is the Bash script version of John Conway's "Game of Life". #
@ -20,7 +22,7 @@
# 3) A dead cell with 3 living neighbors becomes alive (a "birth"). #
SURVIVE=2 #
BIRTH=3 #
# 4) All other cases result in dead cells. #
# 4) All other cases result in a dead cell for the next generation. #
# ##################################################################### #
@ -40,10 +42,13 @@ ALIVE1=.
DEAD1=_
# Represent living and "dead" cells in the start-up file.
# ---------------------------------------------------------- #
# This script uses a 10 x 10 grid (may be increased,
#+ but a large grid will will cause very slow execution).
ROWS=10
COLS=10
# Change above two variables to match grid size, if necessary.
# ---------------------------------------------------------- #
GENERATIONS=10 # How many generations to cycle through.
# Adjust this upwards,
@ -71,7 +76,7 @@ declare -a current
display ()
{
alive=0 # How many cells "alive".
alive=0 # How many cells "alive" at any given time.
# Initially zero.
declare -a arr
@ -86,7 +91,7 @@ for ((i=0; i<$element_count; i++))
do
# Insert newline at end of each row.
let "rowcheck = $i % ROWS"
let "rowcheck = $i % COLS"
if [ "$rowcheck" -eq 0 ]
then
echo # Newline.
@ -131,7 +136,7 @@ then
fi
row=$2
let "left = $row * $ROWS" # Left limit.
let "left = $row * $COLS" # Left limit.
let "right = $left + $COLS - 1" # Right limit.
if [ "$1" -lt "$left" -o "$1" -gt "$right" ]
@ -190,7 +195,7 @@ GetCount () # Count live cells in passed cell's neighborhood.
let "top = $cell_number - $COLS - 1" # Set up cell neighborhood.
let "center = $cell_number - 1"
let "bottom = $cell_number + $COLS - 1"
let "r = $cell_number / $ROWS"
let "r = $cell_number / $COLS"
for ((i=0; i<$ROW_NHBD; i++)) # Traverse from left to right.
do
@ -264,6 +269,8 @@ done
# let "generation += 1" # Increment generation count.
# Why was the above line commented out?
# Set variable to pass as parameter to "display" function.
avar=`echo ${array[@]}` # Convert array back to string variable.
@ -333,8 +340,20 @@ echo
exit 0
# --------------------------------------------------------------
# The grid in this script has a "boundary problem".
# The grid in this script has a "boundary problem."
# The the top, bottom, and sides border on a void of dead cells.
# Exercise: Change the script to have the grid wrap around,
# + so that the left and right sides will "touch",
# + so that the left and right sides will "touch,"
# + as will the top and bottom.
#
# Exercise: Create a new "gen0" file to seed this script.
# Use a 12 x 16 grid, instead of the original 10 x 10 one.
# Make the necessary changes to the script,
#+ so it will run with the altered file.
#
# Exercise: Modify this script so that it can determine the grid size
#+ from the "gen0" file, and set any variables necessary
#+ for the script to run.
# This would make unnecessary any changes to variables
#+ in the script for an altered grid size.

View File

@ -1,8 +1,10 @@
#!/bin/bash
# realname.sh
#
# From username, gets "real name" from /etc/passwd.
ARGCOUNT=1 # Expect one arg.
ARGCOUNT=1 # Expect one arg.
E_WRONGARGS=65
file=/etc/passwd
@ -14,9 +16,9 @@ then
exit $E_WRONGARGS
fi
file_excerpt () # Scan file for pattern, the print relevant portion of line.
file_excerpt () # Scan file for pattern, then print relevant portion of line.
{
while read line # while does not necessarily need "[ condition]"
while read line # "while" does not necessarily need "[ condition ]"
do
echo "$line" | grep $1 | awk -F":" '{ print $5 }' # Have awk use ":" delimiter.
done

View File

@ -3,14 +3,21 @@
echo
echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
# Bash, version 3, adds the new $BASH_SUBSELL variable.
echo
outer_variable=Outer
(
echo "Subshell level INSIDE subshell = $BASH_SUBSHELL"
inner_variable=Inner
echo "From subshell, \"inner_variable\" = $inner_variable"
echo "From subshell, \"outer\" = $outer_variable"
)
echo
echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
echo
if [ -z "$inner_variable" ]

View File

@ -1,9 +1,10 @@
#!/bin/bash
# timed-input.sh
# TMOUT=3 useless in a script
# TMOUT=3 Also works, as of newer versions of Bash.
TIMELIMIT=3 # Three seconds in this instance, may be set to different value.
TIMELIMIT=3 # Three seconds in this instance. May be set to different value.
PrintAnswer()
{

View File

@ -1,8 +1,8 @@
#!/bin/bash
# timeout.sh
# Written by Stephane Chazelas,
# and modified by the document author.
# Written by Stephane Chazelas,
#+ and modified by the document author.
INTERVAL=5 # timeout interval
@ -11,7 +11,7 @@ timedout_read() {
varname=$2
old_tty_settings=`stty -g`
stty -icanon min 0 time ${timeout}0
eval read $varname # or just read $varname
eval read $varname # or just read $varname
stty "$old_tty_settings"
# See man page for "stty".
}
@ -19,9 +19,9 @@ timedout_read() {
echo; echo -n "What's your name? Quick! "
timedout_read $INTERVAL your_name
# This may not work on every terminal type.
# The maximum timeout depends on the terminal.
# (it is often 25.5 seconds).
# This may not work on every terminal type.
# The maximum timeout depends on the terminal.
#+ (it is often 25.5 seconds).
echo

View File

@ -198,7 +198,7 @@ Describes the basics of IRC and respective applications for Linux. </Para>
Linux-Gamers-HOWTO</ULink>,
<CiteTitle>The Linux Gamers' HOWTO</CiteTitle>
</Para><Para>
<CiteTitle>Updated: Jul 2004</CiteTitle>.
<CiteTitle>Updated: Nov 2004</CiteTitle>.
A stepping stone to get the most common problems
resolved and to give people the knowledge to begin thinking
intelligently about what is going on with their games. </Para>

View File

@ -2453,7 +2453,7 @@ guide. </emphasis></Para>
Linux-Gamers-HOWTO</ULink>,
<CiteTitle>The Linux Gamers' HOWTO</CiteTitle>
</Para><Para>
<CiteTitle>Updated: Jul 2004</CiteTitle>.
<CiteTitle>Updated: Nov 2004</CiteTitle>.
A stepping stone to get the most common problems
resolved and to give people the knowledge to begin thinking
intelligently about what is going on with their games. </Para>

View File

@ -49,7 +49,7 @@
</personname>
</author>
<!-- year-month-day -->
<pubdate>2004-07-30 v.1.0.2</pubdate>
<pubdate>2004-11-13 v.1.0.6</pubdate>
<copyright>
<year>2001</year>
@ -135,23 +135,18 @@
<sect2 id="acknowledgements"><title>Acknowledgements</title>
<para>Thanks to Mike Phillips who commented extensively on the howto. Thanks to Dmitry
Samoyloff, <email>dsamoyloff(at)yandex(dot)ru</email>, for translating this document into
Russian. It blew my mind when he told me that he was translating my words to Russian.
Further thanks goes to:</para>
<para>Thanks goes out to these people for extensive comments, corrections, and diffs. Their
effort is above and beyond the call of duty:</para>
<orderedlist>
<para>Fr&eacute;d&eacute;ric Delanoy, Moritz Muehlenhoff
<email>jmm(at)Informatik(dot)uni-bremen(dot)de</email>, Mike Phillips, Ioan Rogers
<email>buck(at)aiur(dot)co(dot)uk</email></para>
<listitem><para>Moritz Muehlenhoff <email>jmm(at)Informatik(dot)uni-bremen(dot)de</email>
for sending me updates (even if I'm eternally behind on them...)</para></listitem>
<listitem><para>Fr&eacute;d&eacute;ric Delanoy for extensive diffs or correcting typos and docbook
mistakes</para></listitem>
</orderedlist>
<para>I would also like to thank Michael Mc Donnell for sending in comments and
corrections.</para>
<para>I would also like to thank the following people for sending in comments and corrections.
Without their help, there would be more typos and mistakes than you could shake a stick
at:</para>
<para>Michael McDonnell</para>
</sect2>
@ -169,9 +164,25 @@
<para>The most recent stable version can be found at <ulink
url="http://www.tldp.org"></ulink>.</para>
<para>Dmitry Samoyloff <email>dsamoyloff(at)yandex(dot)ru</email> is the maintainer of the
Russian translation. The most recent version can be found at <ulink
url="http://www.dirac.org/linux/writing"></ulink>.</para>
<sect3><title>Russian</title>
<para>Dmitry Samoyloff <email>dsamoyloff(at)yandex(dot)ru</email> is the maintainer of the
Russian translation. The most recent version can be found at <ulink
url="http://www.dirac.org/linux/writing"></ulink>.</para>
</sect3>
<sect3><title>Hungarian</title>
<para>László Daczi <email>dacas(at)korhaz(dot)rethy(dot)hu</email>, the Hungarian LDP
coordinator, announced that a Hungarian translation was produced by Szilard Ivan, and is
available at <ulink url="http://tldp.fsf.hu/HOWTO/Linux-Gamers-HOWTO-hu"
>http://tldp.fsf.hu/HOWTO/Linux-Gamers-HOWTO-hu</ulink>.
</sect3>
</sect2>
@ -227,12 +238,12 @@
<screen>
You are in a room. It is pitch dark and you're likely to be eaten by a grue.
> Light lantern with match.
You light the lantern. This room appears to be a kitchen. There's a table with a book in
the center. You also see an oven, refrigerator and a door leading east.
You light the lantern. This room appears to be a kitchen. There's a table with a
book in the center. You also see an oven, refrigerator and a door leading east.
> Open the oven.
In the oven you see a brown paper bag.
> Take the bag. Open the bag. Close the oven.
Inside the bag is a clove of garlic and a cheese sandwich. The oven door is now closed.
Inside the bag is a some garlic and a cheese sandwich. The oven door is now closed.
</screen>
<para>Back then, text adventures were self contained executables on a disk or casette. These
@ -248,7 +259,7 @@
with Infocom (<xref linkend="infocom">) which are also playable under Linux.</para>
<para>As computer graphics became easier and more powerful, text adventures gave rise to
graphic adventures. The death of interactive fiction more or less coincided with the
graphic adventures. The death of commercial interactive fiction more or less coincided with the
bankruptcy of Infocom.</para>
</sect2>
@ -694,23 +705,33 @@
<sect2 id="openal"><title>What is OpenAL?</title>
<para>OpenAL &lt;<ulink url="http://www.openal.org"></ulink>&gt; aims to be for sound what
OpenGL is for graphics. Jointly developed by Loki Software and Creative Labs, it sets out to
be a vendor neutral and cross platform API for audio. It is licensed LGPL and the specs can
be had for free from the OpenAL website. OpenAL is fully functional, but now that Loki
Software is no more its future development is questionable.</para>
OpenGL is for graphics. It started as a joint project between Loki Software and Creative
Labs, setting out to be a vendor neutral and cross platform API for audio - the audio
equivalent of OpenGL (<xref linkend="opengl">). Loki is no longer in business, but Creative
and the Open Source community have kept the project alive. It is licensed LGPL and the specs
can be obtained for free from the OpenAL website. It has support from nVidia (nForce2/3 based
motherboards come with OpenAL MS Windows libraries for the on-board audio), Apple has added
OpenAL to their audio framework for OSX and it can also be found powering the Epic Games
Unreal Engine</para>
<para>Currently, it's not all cross-platform goodness. There is almost no support for
enhancements like EAX or any hardware acceleration on Linux, though it does it exist in the
Windows implementation. However, if you have a Creative SoundBlaster or Audigy sound card
(with an emu10x chip), and you use ALSA sound drivers, you can get OpenAL libraries from
<ulink url="http://www.lost.org.uk"></ulink> that provide hardware acceleration and decent
surround support.</para>
</sect2>
<sect2 id="directx"><title>What is DirectX?</title>
<para>DirectX is a collection of proprietary multimedia API's, first developed by Microsoft in
1995, for its various Windows OS's. It's a mistake to say something like "DirectX is like
OpenGL" or "DirectX is like SDL", as is commonly said in DirectX tutorials. Multimedia API's
are more centralized on Windows than they are on Linux. A more accurate statement would be
something like "DirectX is like DRI, OpenGL and SDL combined". As of June 2003, the most
recent version of DirectX is 9.0. The components of DirectX are:</para>
something like "DirectX is like DRI, OpenGL and SDL combined". As of October 2004, the most
recent version of DirectX is 9c. The components of DirectX are:</para>
<variablelist>
@ -727,8 +748,8 @@
higher level and only compiles on Windows. D3D first appeared in DirectX 2, released in
1996.</para></listitem></varlistentry>
<varlistentry><term>DirectXAudio</term>
<listitem><para>Direct Audio is a combination of 2 audio API's, DirectSound and DirectMusic,
<varlistentry><term>DirectAudio</term>
<listitem><para>DirectAudio is a combination of 2 audio API's, DirectSound and DirectMusic,
which allows direct access to the sound card for sound and music
playback.</para></listitem></varlistentry>
@ -751,11 +772,12 @@
</variablelist>
<para>DirectX is "kind of" supported by winex (<xref linkend="winex">), poorly supported by
wine (<xref linkend="wine">), barely supported by vmware (<xref linkend="vmware">) and
unsupported by Win4Lin (<xref linkend="win4lin">).</para>
<para>Depending on the version of DirectX you're talking about, DirectX support in winex
(<xref linkend="winex">) ranges from well supported to "kind of" supported. It's poorly
supported by wine (<xref linkend="wine">), barely supported by vmware (<xref
linkend="vmware">) and unsupported by Win4Lin (<xref linkend="win4lin">).</para>
<para>One comment about portability. Each component of DirectX has multiple corresponding
<para>One comment about portability: Each component of DirectX has multiple corresponding
library on Linux. Moreover, a game writer who uses libraries like OpenGL, GGI or SDL will
write a game which will trivially compile on Windows, Linux and a multitude of other OS's.
Yet game companies persist using DirectX and therefore limit their audience to Windows users
@ -911,11 +933,14 @@
<sect2 id="nowm"><title>Playing Games In X Without a Window Manager</title>
<para>When playing a game under X, you should consider starting X without a window manager
(wm). Heavy weight wm's, like Enlightenment, may produce a noticeable slow down. Even light
weight wm's, like twm, rob your CPU of clock cycles (and in twm's case, even full screen games
will have a frame around the window). To run a game without a wm, modify
<filename>.xinitrc</filename>, which tells X what to run upon starting, in your home
directory. Here is what my .xinitrc looks like:</para>
(WM). Heavyweight WMs, like Enlightenment, or full-blown desktop environments like GNOME or
KDE, may produce a noticeable slow down. Even lightweight WMs, like twm, rob your CPU of
clock cycles (and in twm's case, even full screen games will have a frame around the window).
Running a game without a WM or DE depends on how you access X. If you usually log in to a
Virtual Console and start X with &quot;startx&quot; try the following: </para>
<para>Modify <filename>~/.xinitrc</filename>, which tells X what to run upon starting. Here
is what my .xinitrc looks like:</para>
<screen>
#quake3 +set r_gldriver libGR.so.1
@ -926,28 +951,52 @@
</screen>
<para>You'll usually see a window or desktop manager being executed from this file (GNOME or
KDE). Comment out the lines containing the wm or desktop manager with a pound sign (#) and
KDE). Comment out the lines containing the WM or desktop manager with a pound sign (#) and
place your game on a new line with any command line arguments you want to pass. If the game
is not located in your $PATH, give its full path name. Note that this is for people who use
`startx' to start X.</para>
is not located in your $PATH, give its full path name.</para>
<para>If you log directly into X using gdm, then things are a little different. These
instructions are for gdm 2.4 or greater. They *may* work with kde, but I cannot say for
certain.</para>
<para>First, check your <filename>gdm.conf</filename> (usually in <filename
role="directory">/etc/X11/gdm</filename> or <filename role="directory">/etc/gdm</filename>)
file for a line that says begins "<literal>SessionDesktopDir=blah</literal>". One of the
directories listed as options should be "<filename
role="directory">/usr/share/xsessions</filename>", and is the directory which will be used in
this example. As root, change to the "<filename
role="directory">/usr/share/xsessions</filename>" directory and take a look at its contents.
It should contain some <filename>.desktop</filename> files, each corresponding to an entry
you'll see in gdm's Session menu, e.g <filename>gnome.desktop</filename>,
<filename>enlightenment.destop</filename>. This example will show you how to log in to Doom3.
Copy any of the desktop files to "<filename>doom3.desktop</filename>" and open the new file in
your favourite text editor. The file will be full of alternative languages, so cut out
everything you don't want and make the file look like this:</para>
<para>I never use things like gdm or run-level 5 (so I'm not positive here), but I suspect
that if you do, you'll need to do things a bit differently. My best guess is to go to single
user mode (run-level 1) by:</para>
<screen>
# telinit 1
[Desktop Entry]
Encoding=UTF-8
Name=DOOM III
Comment=iD's Doom III
#if game is not in path, remember to put the full path here
Exec=/usr/games/doom3/doom3
# no icon yet, only the top three are currently used
Icon=
Type=Application
</screen>
<para>then edit .xinitrc, then go back to run-level 5 by</para>
<screen>
# telinit 5
</screen>
<para>Save the file and log out of your window manager. At the gdm login screen, you should
now see "<literal>DOOM III</literal>" as an option in "Sessions". Naturally you can add a
.desktop file for each game you have installed</para>
<para>Then when you stop playing, go to run-level 1, modify .xinitrc then go back to run-level
5. I don't use this stuff, so I'm not sure, but you may need to kill gdm. I'd appreciate
some feedback on this.</para>
<!--
Add some stuff about adding scripts to launch games so that you can change env vars, use
nVidia-settings, etc.
-->
</sect2>
@ -1119,7 +1168,124 @@
directory.</para>
<para>Also, even if you just add extra libraries to your system, you must update
<filename>ld.so.cache</filename> to reflect the presense of the new libraries.</para>
<filename>ld.so.cache</filename> to reflect the presence of the new libraries.</para>
</sect3>
<sect3><title>Finding Out What Libraries a Game Depends On</title>
<para>Most commercial Linux games will be dynamically linked against various LGPL libraries,
such as OpenAL or SDL. For these examples, Bioware's NeverWinter Nights &lt;<ulink
url="http://nwn.bioware.com"></ulink>&gt; will be used.</para>
<para>To find out what libraries a game uses, we can use the "<filename>ldd</filename>"
command. Cd to <filename role="directory">/usr/games/nwn</filename>, or wherever you
installed it and take a look at the files. You should see a file called
<filename>nwmain</filename>; this is the actual game binary. Type "<literal>ldd
nwmain</literal>" and you'll see:</para>
<screen>
$ ldd nwmain
linux-gate.so.1 => (0xffffe000)
libm.so.6 => /lib/libm.so.6 (0x40027000)
libpthread.so.0 => /lib/libpthread.so.0 (0x40049000)
libGL.so.1 => /usr/lib/libGL.so.1 (0x4009b000)
libGLU.so.1 => /usr/X11R6/lib/libGLU.so.1 (0x40103000)
libmss.so.6 => not found
libSDL-1.2.so.0 => /usr/lib/libSDL-1.2.so.0 (0x40178000)
libc.so.6 => /lib/libc.so.6 (0x401ff000)
/lib/ld-linux.so.2 (0x40000000)
libGLcore.so.1 => /usr/lib/libGLcore.so.1 (0x40319000)
libnvidia-tls.so.1 => /usr/lib/libnvidia-tls.so.1 (0x409f1000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x409f3000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x40a01000)
libdl.so.2 => /lib/libdl.so.2 (0x40acd000)
libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x40ad1000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x40b88000)
libasound.so.2 => /usr/lib/./libasound.so.2 (0x40b90000)
</screen>
<para>ldd shows all the libraries a dynamic executable relies on, and shows you where they
are. It also "pulls in" the dependencies of the dependencies. For instance, while NWN does
not itself depend on <filename role="library">libnvidia-tls.so</filename>, the Nvidia supplied
libGL on my system does.</para>
<para>Missing libraries?</para>
<para>In the example above, we can see that <filename>nwmain</filename> wants <filename
role="library">libmss.so.6</filename>, and the linker cannot find it. Usually, a missing
library is a crash waiting to happen. There is one other thing to consider though: The
majority of games are actually launched by a "wrapper", a shell script that performs some
magic prior to launching the game. In the case of NWN, the wrapper is called
<filename>nwn</filename>. Let's take a look at that now:</para>
<screen>
$ less nwn
#!/bin/sh
# This script runs Neverwinter Nights from the current directory
export SDL_MOUSE_RELATIVE=0
export SDL_VIDEO_X11_DGAMOUSE=0
# If you do not wish to use the SDL library included in the package, remove
# ./lib from LD_LIBRARY_PATH
export LD_LIBRARY_PATH=./lib:./miles:$LD_LIBRARY_PATH
./nwmain $@
</screen>
<para>This script sets up some environment variables, then launches the game binary with
whatever command line options we added. The relevant part here is the environment variable
called "LD_LIBRARY_PATH". This is a way of adding to the linkers search path. Try copying the
line to your shell and seeing what happens when you re-run ldd.</para>
<screen>
$ export LD_LIBRARY_PATH=./lib:./miles:$LD_LIBRARY_PATH
$ ldd nwmain
linux-gate.so.1 => (0xffffe000)
libm.so.6 => /lib/libm.so.6 (0x40027000)
libpthread.so.0 => /lib/libpthread.so.0 (0x40049000)
libGL.so.1 => /usr/lib/libGL.so.1 (0x4009b000)
libGLU.so.1 => /usr/X11R6/lib/libGLU.so.1 (0x40103000)
libmss.so.6 => ./miles/libmss.so.6 (0x40178000)
libSDL-1.2.so.0 => ./lib/libSDL-1.2.so.0 (0x401ec000)
libc.so.6 => /lib/libc.so.6 (0x4025e000)
/lib/ld-linux.so.2 (0x40000000)
libGLcore.so.1 => /usr/lib/libGLcore.so.1 (0x40378000)
libnvidia-tls.so.1 => /usr/lib/libnvidia-tls.so.1 (0x40a50000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x40a52000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x40a60000)
libdl.so.2 => /lib/libdl.so.2 (0x40b2c000)
libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x40b30000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x40be7000)
</screen>
<para>As you can see, this gives us slighly different results. The NWN library directories
have been prepended to the search path, so now the linker can find <filename
role="library">libmss.so.6</filename> in the "<filename role="directory">./miles</filename>"
directory, and also finds the local copy of libSDL first, no longer using the system
copy.</para>
<para>There's another benefit of these scripts: they are easily edited to allow you to provide
your own copy of a library. Any game-supplied copy of a library such as OpenAL or SDL is
likely to be compiled for the lowest common denominator, probably i486 or i686. If you have a
Pentium4 or an AthlonXP, you could compile you own version specifically for your processor.
The compiler will try to optimise the resulting binary, giving some increase in performance.
See the homepage for GCC for more information this at <ulink url="http://gcc.gnu.org"> the GCC
site.</ulink></para>
<para>Making NWN use your system copy is easy. It says so in the wrapper script! Remove
"./lib:" from the <literal>LD_LIBRARY_PATH</literal> line, and you're good to go.</para>
<para>Another nice little trick is for games that use OpenAL for their sound output (e.g.
Unreal based games: UT, Postal, Rune, etc.). Since the Open Sound System's (OSS) deprecation
in favour of ALSA, all Linux distributions I've seen now ship with ALSA support as default,
with OSS support actually being supplied via ALSA's compatability modules. The copies of
<filename role="library">openal.so</filename> distributed with games often do NOT support
ALSA, so making the game use a copy compiled yourself will allow you to use ALSA
natively.</para>
</sect3>
@ -1319,17 +1485,17 @@
be a library:</para>
<screen>
% ./exult
./exult: error while loading shared libraries: libSDL-1.2.so.0: cannot load shared object
file: No such file or directory
% ./exult
./exult: error while loading shared library: libSDL-1.2.so.0: cannot load shared object
file: No such file or directory
</screen>
<para>or it could be some kind of data file, like a <filename class="extension">wad</filename>
or <filename class="extension">map</filename> file:</para>
<screen>
% qf-client-sdl
IP address 192.168.0.2:27001 UDP Initialized Error: W_LoadWadFile: couldn't load gfx.wad
% qf-client-sdl
IP address 192.168.0.2:27001 UDP Initialize Error: W_LoadWadFile: couldn't load gfx.wad
</screen>
<para>Suppose <filename>gfx.wad</filename> is already on my system, but couldn't be found