LDP/LDP/howto/linuxdoc/Software-Building-HOWTO.sgml

1660 lines
59 KiB
Plaintext

<!doctype linuxdoc system>
<article>
<!-- Title information -->
<title>Building and Installing Software Packages for Linux
<author>
<em><url url="mailto:thegrendel@theriver.com"
name="Mendel Cooper"></em>
---
<url url="http://personal.riverusers.com/~thegrendel/"
name="http://personal.riverusers.com/~thegrendel/">
<date>v1.91, 27 July 1999
<abstract>
This is a comprehensive guide to building and installing "generic" UNIX
software distributions under Linux. Additionally, there is some coverage
of "rpm" and "deb" pre-packaged binaries.
</abstract>
<!-- Table of contents -->
<toc>
<!-- Begin the document -->
<sect>Introduction
<p>
Many software packages for the various flavors of UNIX and Linux come as
compressed archives of source files. The same package may be "built"
to run on different target machines, and this saves the author of the
software from having to produce multiple versions. A single distribution
of a software package may thus end up running, in various incarnations,
on an Intel box, a DEC Alpha, a RISC workstation, or even a mainframe.
Unfortunately, this puts the responsibility of actually "building"
and installing the software on the end user, the de facto "system
administrator", the fellow sitting at the keyboard -- you. Take heart,
though, the process is not nearly as terrifying or mysterious as it seems,
as this guide will demonstrate.
<sect>Unpacking the Files
<p>
You have downloaded or otherwise acquired a software package. Most likely
it is archived (<em>tarred</em>) and compressed (<em>gzipped</em>),
in <tt>.tar.gz</tt> or <tt>.tgz</tt> form (familiarly known as a
"tarball"). First copy it to a working directory. Then <em>untar</em>
and <em>gunzip</em> it. The appropriate command for this is <bf>tar
xzvf <em>filename</em></bf>, where <em>filename</em> is the name of the
software file, of course. The de-archiving process will usually install
the appropriate files in subdirectories it will create. Note that if
the package name has a <em>.Z</em> suffix, then the above procedure will
serve just as well, though running <bf>uncompress</bf>, followed by a
<bf>tar xvf</bf> also works. You may preview this process by a <bf>tar
tzvf filename</bf>, which lists the files in the archive without actually
unpacking them.
The above method of unpacking "tarballs" is equivalent to either of the following:
<itemize>
<item>gzip -cd filename | tar xvf -
<item>gunzip -c filename | tar xvf -
</itemize>
(The '-' causes the <em>tar</em> command to take its input from
<tt>stdin</tt>.)
Source files in the new <em>bzip2</em> (<tt>.bz2</tt>) format
can be unarchived by a <bf>bzip2 -cd filename | tar xvf -</bf>,
or, more simply by a <bf>tar xyvf filename</bf>, assuming that
<tt>tar</tt> has been appropriately patched (refer to the <htmlurl
url="ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/mini/Bzip" name="Bzip2
HOWTO"> for details). Debian Linux uses a different patch for
<tt>tar</tt>, one written by Hiroshi Takekawa, so that the <em>-I,
--bzip2, --bunzip2</em> options work with that particular <tt>tar</tt>
version.
[Many thanks to R. Brock Lynn and Fabrizio Stefani for corrections and
updates on the above information.]
Sometimes the archived file must be untarred and installed from the
user's home directory, or perhaps in a certain other directory, such
as <tt>/</tt>, <tt>/usr/src</tt>, or <tt>/opt</tt>, as specified in
the package's config info. Should you get an error message attempting
to untar it, this may be the reason. Read the package docs, especially
the <tt>README</tt> and/or <tt>Install</tt> files, if present, and edit
the config files and/or <tt>Makefiles</tt> as necessary, consistent
with the installation instructions. Note that you would <bf>not</bf>
ordinarily alter the <tt>Imake</tt> file, since this could have unforseen
consequences. Most software packages permit automating this process by
running <bf>make install</bf> to emplace the binaries in the appropriate
system areas.
<itemize>
<item>You might encounter <tt>shar</tt> files, or <em>shell archives</em>,
especially in the source code newsgroups on the Internet. These remain
in use because they are readable to humans, and this permits newsgroup
moderators to sort through them and reject unsuitable ones. They may
be unpacked by the <bf>unshar filename.shar</bf> command. Otherwise the
procedure for dealing with them is the same as for "tarballs".
</itemize>
<itemize>
<item>Some source archives have been processed using nonstandard DOS,
Mac, or even Amiga compression utilities such <em>zip</em>, <em>arc</em>,
<em>lha</em>, <em>arj</em>, <em>zoo</em>, <em>rar</em>, and <em>shk</em>.
Fortunately, <url url="http://metalab.unc.edu" name="Sunsite"> and
other places have Linux uncompression utilities that can deal with most
or all of these.
</itemize>
Occasionally, you may need to update or incorporate bug fixes into the
unarchived source files using a <tt>patch</tt> or <tt>diff</tt> file
that lists the changes. The doc files and/or <tt>README</tt> file will
inform you should this be the case. The normal syntax for invoking Larry
Wall's powerful <em>patch</em> utility is <bf>patch < patchfile</bf>.
You may now proceed to the build stage of the process.
<sect>Using Make
<p>
The <tt>Makefile</tt> is the key to the build process. In its simplest
form, a Makefile is a script for compiling or building the "binaries",
the executable portions of a package. The Makefile can also provide a
means of updating a software package without having to recompile every
single source file in it, but that is a different story (or a different
article).
At some point, the Makefile launches <tt>cc</tt> or <tt>gcc</tt>. This
is actually a preprocessor, a C (or C++) compiler, and a linker, invoked
in that order. This process converts the source into the binaries, the
actual executables.
Invoking <em>make</em> usually involves just typing <bf>make</bf>. This
generally builds all the necessary executable files for the package in
question. However, make can also do other tasks, such as installing the
files in their proper directories (<bf>make install</bf>) and removing
stale object files (<bf>make clean</bf>). Running <bf>make -n</bf>
permits previewing the build process, as it prints out all the commands
that would be triggered by a make, without actually executing them.
Only the simplest software uses a generic Makefile. More complex
installations require tailoring the Makefile according to the location
of libraries, include files, and resources on your particular machine.
This is especially the case when the build needs the <tt>X11</tt>
libraries to install. <em>Imake</em> and <em>xmkmf</em> accomplish this
task.
An <tt>Imakefile</tt> is, to quote the man page, a "template"
Makefile. The imake utility constructs a Makefile appropriate for your
system from the Imakefile. In almost all cases, however, you would run
<bf>xmkmf</bf>, a shell script that invokes imake, a front end for it.
Check the README or INSTALL file included in the software archive for
specific instructions. (If, after dearchiving the source files, there
is an <tt>Imake</tt> file present in the base directory, this is a dead
giveaway that <bf>xmkmf</bf> should be run.) Read the <tt>Imake</tt> and
<tt>xmkmf</tt> man pages for a more detailed analysis of the procedure.
Be aware that <tt>xmkmf</tt> and <tt>make</tt> may need to be invoked as
root, especially when doing a <bf>make install</bf> to move the binaries
over to the <tt>/usr/bin</tt> or <tt>/usr/local/bin</tt> directories.
Using make as an ordinary user without root privileges will likely
result in <em>write access denied</em> error messages because you lack
write permission to system directories. Check also that the binaries
created have the proper execute permissions for you and any other
appropriate users.
Invoking <bf>xmkmf</bf> uses the <tt>Imake</tt> file to build a new
Makefile appropriate for your system. You would normally invoke
<bf>xmkmf</bf> with the <bf>-a</bf> argument, to automatically do a
<em>make Makefiles, make includes,</em> and <em>make depend</em>. This
sets the variables and defines the library locations for the compiler
and linker. Sometimes, there will be no <tt>Imake</tt> file, instead
there will be an <tt>INSTALL</tt> or <tt>configure</tt> script that will
accomplish this purpose. Note that if you run <tt>configure</tt>, it
should be invoked as <bf>./configure</bf> to ensure that the correct
<tt>configure</tt> script in the current directory is called. In most
cases, the <tt>README</tt> file included with the distribution will
explain the install procedure.
It is usually a good idea to visually inspect the <tt>Makefile</tt> that
<tt>xmkmf</tt> or one of the install scripts builds. The Makefile will
normally be correct for your system, but you may occasionally be
required to "tweak" it or correct errors manually.
Installing the freshly built binaries into the appropriate system directories
is usually a matter of running <bf>make install</bf> as root. The usual
directories for system-wide binaries on modern Linux distributions are
<tt>/usr/bin</tt>, <tt>/usr/X11R6/bin</tt>, and <tt>/usr/local/bin</tt>. The
preferred directory for new packages is <tt>/usr/local/bin</tt>, as this will
keep separate binaries not part of the original Linux installation.
Packages originally targeted for commercial versions of UNIX may attempt
to install in the <tt>/opt</tt> or other unfamiliar directory. This will,
of course, result in an installation error if the intended installation
directory does not exist. The simplest way to deal with this is to
create, as root, an <tt>/opt</tt> directory, let the package install
there, then add that directory to the <tt>PATH</tt> environmental
variable. Alternatively, you may create symbolic links to the
<tt>/usr/local/bin</tt> directory.
Your general installation procedure will therefore be:
<itemize>
<item>Read the <tt>README</tt> file and other applicable docs.
<item>Run <bf>xmkmf -a</bf>, or the <tt>INSTALL</tt> or <tt>configure</tt> script.
<item>Check the <tt>Makefile</tt>.
<item>If necessary, run <bf>make clean</bf>, <bf>make Makefiles</bf>,
<bf>make includes</bf>, and <bf>make depend</bf>.
<item>Run <bf>make</bf>.
<item>Check file permissions.
<item>If necessary, run <bf>make install</bf>.
</itemize>
<em>Notes:</em>
<itemize>
<item>You would not normally build a package as root. Doing an <bf>su</bf>
to root is only necessary for installing the compiled binaries into
system directories.
<item>After becoming familiar with <em>make</em> and its uses,
you may wish to add additional optimization options passed to
<tt>gcc</tt> in the standard <tt>Makefile</tt> included or created
in the package you are installing. Some of these common options are
<em>-O2</em>, <em>-fomit-frame-pointer</em>, <em>-funroll-loops</em>,
and <em>-mpentium</em> (if you are running a Pentium cpu). Use caution
and good sense when modifying a <tt>Makefile</tt>!
<item>After the <em>make</em> creates the binaries, you may wish to
<bf>strip</bf> them. The <bf>strip</bf> command removes the symbolic
debugging information from the binaries, and reduces their size, often
drastically. This also disables debugging, of course.
<item>The <url url="http://sunsite.auc.dk/pack/" name="Pack Distribution
Project"> offers a different approach to creating archived software
packages, based on a set of Python scripting tools for managing
symbolic links to files installed in separate <em>collection
directories</em>. These archives are ordinary <em>tarballs</em>, but
they install in <tt>/coll</tt> and <tt>/pack</tt> directories. You may
find it necessary to download the <em>Pack-Collection</em> from the
above site should you ever run across one of these distributions.
</itemize>
<sect>Prepackaged Binaries
<p>
<sect1> Whats wrong with rpms?
<p>
Manually building and installing packages from source is apparently so
daunting a task for some Linux users that they have embraced the popular
<em>rpm</em> and <em>deb</em> or the newer Stampede <em>slp</em> package
formats. While it may be the case that an <em>rpm</em> install normally
runs as smoothly and as fast as a software install in a certain other
notorious operating system, some thought should certainly be given to
the disadvantages of self-installing, prepackaged binaries.
First, be aware that software packages are normally released first as
"tarballs", and that prepackaged binaries follow days, weeks, even
months later. A current <em>rpm</em> package is typically at least a
couple of minor version behind the latest "tarball". So, if you wish
to keep up with all the 'bleeding edge' software, you might not wish to
wait for an <em>rpm</em> or <em>deb</em> to appear. Some less popular
packages may never be <em>rpm</em>'ed.
Second, the "tarball" package may well be more complete, have more
options, and lend itself better to customization and tweaking. The binary
rpm version may be missing some of the functionality of the full release.
Source <em>rpm</em>'s contain the full source code and are equivalent
to the corresponding "tarballs", and they likewise need to be built and
installed using either of the <bf>rpm --recompile packagename.rpm</bf>
or <bf>rpm --rebuild packagename.rpm</bf> options.
Third, some prepackaged binaries will not properly install, and even
if they do install, they could crash and core-dump. They may depend on
different library versions than are present in your system, or they may
be improperly prepared or just plain broken. In any case, when installing
an <em>rpm</em> or <em>deb</em> you necessarily trust the expertise of
the persons who have packaged it.
Finally, it helps to have the source code on hand, to be able to tinker
with and learn from it. It is much more straightforward to have the
source in the archive you are building the binaries from, and not in a
separate source <em>rpm</em>.
Installing an <em>rpm</em> package is not necessarily a no-brainer.
If there is a dependency conflict, an <em>rpm</em> install will
fail. Likewise, should the <em>rpm</em> require a different version of
libraries than the ones present on your system, the install may not work,
even if you create symbolic links to the missing libraries from the ones
in place. Despite their convenience, <em>rpm</em> installs often fail
for the same reasons "tarball" ones do.
You must install <em>rpm</em>'s and <em>deb</em>'s as root, in order
to have the necessary write permissions, and this opens a potentially
serious security hole, as you may inadvertently clobber system binaries
and libraries, or even install a <em>Trojan horse</em> that might wreak
havoc upon your system. It is therefore important to obtain <em>rpm</em>
and <em>deb</em> packages from a "trusted source". In any case, you should
run a 'signature check' (against the MD5 checksum) on the package, <bf>rpm
--checksig packagename.rpm</bf>, before installing. Likewise highly
recommended is running <bf>rpm -K --nopgp packagename.rpm</bf>. The
corresponding commands for <em>deb</em> packages are <bf>dpkg -I | --info
packagename.deb</bf> and <bf>dpkg -e | --control packagename.deb</bf>.
<itemize>
<item><tt>rpm --checksig gnucash-1.1.23-4.i386.rpm</tt>
<tscreen><verb>
</verb></tscreen>
<tt>gnucash-1.1.23-4.i386.rpm: size md5 OK</tt>
</itemize>
<itemize>
<item><tt>rpm -K --nopgp gnucash-1.1.23-4.i386.rpm</tt>
<tscreen><verb>
</verb></tscreen>
<tt>gnucash-1.1.23-4.i386.rpm: size md5 OK</tt>
</itemize>
For the truly paranoid (and, in this case there is much
to be said for paranoia), there are the <em>unrpm</em>
and <em>rpmunpack</em> utilities available from the <htmlurl
url="ftp://metalab.unc.edu/pub/Linux/utils/package" name="Sunsite
utils/package directory"> for unpacking and checking the individual
components of the packages.
<url url="mailto:klee@debian.org" name="Klee Diene"> has written an
experimental <em>dpkgcert</em> package for verifying the integrity of
installed <em>.deb</em> files against MD5 checksums. It is available from
the <url url="ftp://ftp.debian.org/pub/debian/project/experimental"
name="Debian ftp archive">. The current package name
/ version is <em>dpkgcert_0.2-4.1_all.deb</em>. The <url
url="http://dpkgcert.jimpick.com" name="Jim Pick Software"> site maintains
an experimental server database to provide <em>dpkgcert</em> certificates
for the packages in a typical Debian installation.
In their most simple form, the commands <bf>rpm -i packagename.rpm</bf>
and <bf>dpkg --install packagename.deb</bf> automatically unpack and
install the software. Exercise caution, though, since using these
commands blindly may be dangerous to your system's health!
Note that the above warnings also apply, though to a lesser extent,
to Slackware's <em>pkgtool</em> installation utility. All "automatic"
software installations require caution.
The <url
url="http://www.people.cornell.edu/pages/rc42/program/martian.html"
name="martian"> and <url url="http://kitenet.net/programs/alien/"
name ="alien"> programs allow conversion between the <em>rpm</em>,
<em>deb</em>, Stampede <em>slp</em>, and <em>tar.gz</em> package
formats. This makes these packages accessible to all Linux distributions.
Carefully read the man pages for the <em>rpm</em>
and <em>dpkg</em> commands, and refer to the <htmlurl
url="ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/RPM-HOWTO" name="RPM
HOWTO">, TFUG's <url url="http://www.tfug.org/helpdesk/linux/rpm.html"
name="Quick Guide to Red Hat's Package Manager">, and <url
url="http://www.debian.org/doc/FAQ/debian-faq-7.html" name="The Debian
Package Management Tools"> for more detailed information.
<sect1>Problems with rpms: an example
<p>
<url url="mailto:hubicka@paru.cas.cz" name="Jan Hubicka"> wrote
a very nice fractal package called <em>xaos</em>. At his <url
url="http://www.paru.cas.cz/~hubicka/XaoS" name="home page">, both
<tt>.tar.gz</tt> and <tt>rpm</tt> packages are available. For the sake
of convenience, let us try the rpm version, rather than the "tarball".
Unfortunately, the rpm of <em>xaos</em> fails to install. Two separate
rpm versions misbehave.
<bf>rpm -i --test XaoS-3.0-1.i386.rpm</bf>
<tscreen><verb>
error: failed dependencies:
libslang.so.0 is needed by XaoS-3.0-1
libpng.so.0 is needed by XaoS-3.0-1
libaa.so.1 is needed by XaoS-3.0-1
</verb></tscreen>
<bf>rpm -i --test xaos-3.0-8.i386.rpm</bf>
<tscreen><verb>
error: failed dependencies:
libaa.so.1 is needed by xaos-3.0-8
</verb></tscreen>
The strange thing is that <tt>libslang.so.0</tt>, <tt>libpng.so.0</tt>,
and <tt>libaa.so.1</tt> are all present in <tt>/usr/lib</tt> on the
system tested. The rpms of <em>xaos</em> must have been built with
slightly different versions of those libraries, even if the release
numbers are identical.
As a test, let us try installing <tt>xaos-3.0-8.i386.rpm</tt> with the
<em>--nodeps</em> option to force the install. A trial run of <em>xaos</em>
crashes.
<tscreen><verb>
xaos: error in loading shared libraries: xaos: undefined symbol: __fabsl
</verb></tscreen>
Let us stubbornly try to get to the bottom of this. Running <em>ldd</em>
on the <em>xaos</em> binary to find its library dependencies shows
all the necessary shared libraries present. Running <em>nm</em> on the
<tt>/usr/lib/libaa.so.1</tt> library to list its symbolic references
shows that it is indeed missing <em>__fabsl</em>. Of course, the absent
reference <em>could</em> be missing from one of the other libraries...
There is nothing to be done about that, short of replacing one or more
libraries.
Enough! Download the "tarball", <tt>XaoS-3.0.tar.gz</tt>, available from
the <url url="ftp://ftp.ta.jcu.cz/pub/linux/hubicka/XaoS/3.0" name="ftp
site">, as well as from the home page. Try building it. Running
<bf>./configure</bf>, <bf>make</bf>, and finally (as root) <bf>make
install</bf>, works flawlessly.
This is one of an number of examples of prepackaged binaries being more
trouble than they are worth.
<sect>Termcap and Terminfo Issues
<p>
According to its man page, <em>"terminfo is a data base describing
terminals, used by screen-oriented programs..."</em>. It defines a
generic set of control sequences (escape codes) used to display text on
terminals, and makes possible support for different terminal hardware
without the need for special drivers. The <em>terminfo</em> libraries
are located in <tt>/usr/share/terminfo</tt> on modern Linux distributions.
The <em>terminfo</em> database has largely supplanted the older
<em>termcap</em> and the totally obsolete <em>termlib</em> ones. This
is usually of no concern for program installation except when dealing
with a package that requires <em>termcap</em>.
Most Linux distributions now use <em>terminfo</em>, but still retain the
older termcap libraries for compatibility with legacy applications (see
<tt>/etc/termcap</tt>). Sometimes there is a special compatibility package
that needs to be installed to facilitate use of termcap linked binaries.
Very occasionally, an <em>#define termcap</em> statement might need to
be commented out of a source file. Check the appropriate doc files for
your particular distribution for definitive information on this.
<sect>Backward Compatibility With a.out Binaries
<p>
In a very few cases, it is necessary to use a.out binaries, either because
the source code is not available or because it is not possible to build
new ELF binaries from the source for some reason.
As it happens, ELF installations almost always have a complete set
of a.out libraries in the <tt>/usr/i486-linuxaout/lib</tt> directory.
The numbering scheme for a.out libraries differs from that of ELF ones,
cleverly avoiding conflicts that could cause confusion. The a.out
binaries should therefore be able to find the correct libraries at
runtime, but this might not always be the case.
Note that the kernel needs to have a.out support built into it, either
directly or as a loadable module. It may be necessary to rebuild the
kernel to enable this. Moreover, some Linux distributions require
installation of a special compatibility package, such as Debian's
<tt>xcompat</tt> for executing a.out X applications.
<sect1>An Example
<p>
Jerry Smith wrote a very handy <em>rolodex</em> program some years
back. It uses the Motif libraries, but fortunately is available
as a statically linked binary in a.out format. Unfortunately, the
source requires numerous tweaks to rebuild using the <em>lesstif</em>
libraries. Even more unfortunately, the a.out binary bombs on an ELF
system with the following error message.
<tscreen><verb>
xrolodex: can't load library '//lib/libX11.so.3'
No such library
</verb></tscreen>
As it happens, there is such a library, in
<tt>/usr/i486-linuxaout/lib</tt>, but xrolodex is unable to locate it
at run time. The simple solution is to provide a symbolic link in the
<tt>/lib</tt> directory:
<tt>ln -s /usr/i486-linuxaout/lib/X11.so.3.1.0 libX11.so.3</tt>
It turns out to be necessary to provide similar links for the libXt.so.3
and libc.so.4 libraries. This needs to be done as root, of course. Note
that you should make absolutely certain you will not overwrite or cause
version number conflicts with pre-existing libraries. Fortunately, the
new ELF libraries have higher version numbers than the older a.out ones,
to anticipate and forestall just such problems.
After creating the three links, <em>xrolodex</em> runs fine.
The <em>xrolodex</em> package was originally posted on <url
url="http://www.spectro.com/" name="Spectro">, but seems to
vanished from there. It may currently be downloaded from <url
url="http://metalab.unc.edu/pub/Linux/apps/reminder/xrolodex.tar.z"
name="Sunsite"> as a <em>tar.Z</em> format source file [512k].
<sect>Troubleshooting
<p>
If <em>xmkmf</em> and/or <em>make</em> succeeded without errors,
you may proceed to the <ref id="finalsteps" name="next section">.
However, in "real life", few things work right the first time.
This is when your resourcefulness is put to the test.
<sect1>Link Errors
<p>
<itemize>
<item>Suppose <em>make</em> fails with a <tt>Link error: -lX11: No such
file or directory</tt>, even after xmkmf has been invoked. This may mean
that the <em>Imake</em> file was not set up properly. Check the first
part of the <em>Makefile</em> for lines such as:
<tscreen><verb>
LIB= -L/usr/X11/lib
INCLUDE= -I/usr/X11/include/X11
LIBS= -lX11 -lc -lm
</verb></tscreen>
The <tt>-L</tt> and <tt>-I</tt> switches tell the compiler and linker
where to look for the <em>library</em> and <em>include</em> files,
respectively. In this example, the <em>X11 libraries</em> should be in
the <tt>/usr/X11/lib</tt> directory, and the <em>X11 include files</em>
should be in the <tt>/usr/X11/include/X11</tt> directory. If this is
incorrect for your machine, make the necessary changes to the
<em>Makefile</em> and try the <em>make</em> again.
</itemize>
<itemize>
<item>Undefined references to math library functions, such as the following:
<tscreen><verb>
/tmp/cca011551.o(.text+0x11): undefined reference to `cos'
</verb></tscreen>
The fix for this is to explicitly link in the <tt>math library</tt>,
by adding an <bf>-lm</bf> to the <em>LIB</em> or <em>LIBS</em> flags in
the <tt>Makefile</tt> (see previous example).
</itemize>
<itemize>
<item>Yet another thing to try if <em>xmkmf</em> fails is the following script:
<tscreen><verb>
make -DUseInstalled -I/usr/X386/lib/X11/config
</verb></tscreen>
This is a sort of bare bones equivalent of <em>xmkmf</em>.
</itemize>
<itemize>
<item>In a very few cases, running <em>ldconfig</em> as <em>root</em>
may be the solution:
<tscreen><verb>
</verb></tscreen>
<bf># ldconfig</bf> updates the shared library symbolic links. <em>This
may not be necessary .</em>
</itemize>
<itemize>
<item>Some <tt>Makefiles</tt> use unrecognized aliases for libraries
present in your system. For example, the build may require
<tt>libX11.so.6</tt>, but there exists no such file or link in
<tt>/usr/X11R6/lib</tt>. Yet, there is a <tt>libX11.so.6.1</tt>. The
solution is to do a <bf>ln -s /usr/X11R6/lib/libX11.so.6.1
/usr/X11R6/lib/libX11.so.6</bf>, as root. This may need to be followed
by a <bf>ldconfig</bf>.
</itemize>
<itemize>
<item>Sometimes the source needs the older release X11R5 libraries to
build. If you have the R5 libs in /usr/X11R6/lib (you were given the
option of having them when first installing Linux), then you need only
ensure that you have the links that the software needs to build. The
<tt>R5 libs</tt> are named <tt>libX11.so.3.1.0</tt>,
<tt>libXaw.so.3.1.0</tt>, and <tt>libXt.so.3.1.0</tt>. You generally
need links, such as <em>libX11.so.3 -> libX11.so.3.1.0</em>. Possibly
the software will also need a link of the form <em>libX11.so ->
libX11.so.3.1.0</em>. Of course, to create a "missing" link, use the
command <bf>ln -s libX11.so.3.1.0 libX11.so</bf>, <em>as root</em>.
</itemize>
<itemize>
<item>
Some packages will require you to install updated versions of one or
more libraries. For example, the 4.x versions of the <em>StarOffice</em>
suite from StarDivision GmbH were notorious for needing a <tt>libc</tt>
version 5.4.4 or greater. Even the more recent <em>StarOffice</em> 5.0
will not run after installation with the new <tt>glibc 2.1</tt> libs.
Fortunately, the newer <em>StarOffice</em> 5.1 solves these problems.
If running an older version of <em>StarOffice</em> you would, as
<em>root</em>, need to copy one or more libraries to the appropriate
directories, remove the old libraries, then reset the symbolic links
(check the latest version of the <tt>StarOffice miniHOWTO</tt> for more
information on this).
<bf>Caution: Exercise extreme care in this, as you can render your
system nonfunctional if you screw up.</bf>
You can usually find the latest updated libraries at <htmlurl
url="ftp://metalab.unc.edu/pub/Linux/libs" name="Sunsite">.
</itemize>
<sect1>Other Problems
<p>
<itemize>
<item>An installed <em>Perl</em> or shell script gives you a <tt>No such
file or directory</tt> error message. In this case, check the file
permissions to make sure the file is executable and check the file
header to ascertain whether the shell or program invoked by the script
is in the place specified.
For example, the scrip may begin with:
<tscreen><verb>
#!/usr/local/bin/perl
</verb></tscreen>
If <em>Perl</em> is in fact installed in your <tt>/usr/bin</tt>
directory instead of the <tt>/usr/local/bin</tt> one, then the script
will not run. There are two methods of correcting this. The
script file header may be changed to <tt>#!/usr/bin/perl</tt>, or
a symbolic link to the correct directory may be added, <bf>ln -s
/usr/bin/perl /usr/local/bin/perl</bf>.
</itemize>
<itemize>
<item>Some X11 software requires the Motif libraries to build.
The standard Linux distributions do not have the Motif libraries
installed, and at present Motif costs an extra $100-$200 (though the
freeware <url url="http://www.lesstif.org/" name="Lesstif"> also works
in many cases). If you need Motif to build a certain package, but lack
the Motif libraries, it may be possible to obtain <em>statically linked
binaries</em>. Static linking incorporates the library routines in the
binaries themselves. This results in much larger binary files, but the
code will run on systems lacking the libraries.
<tscreen><verb>
</verb></tscreen>
When a package requires libraries not present on your system for the
build, it will result in link errors (<tt>undefined reference</tt>
errors). The libraries may be expensive proprietary ones or difficult
to find for sone other reason. In that case, obtaining a <em>statically
linked</em> binary either from the author of the package or from a Linux
user group may be the easiest to implement fix.
</itemize>
<itemize>
Running a <em>configure</em> script creates a strange Makefile, one
seemingly unrelated to the package you are attempting to build. This
means the wrong <em>configure</em> ran, one found somewhere else in your
path. Always invoke <em>configure</em> as <bf>./configure</bf> to
prevent this.
</itemize>
<itemize>
Most Linux distributions have changed over to the <tt>libc 6 / glibc
2</tt> libraries from the older <tt>libc 5</tt>. Precompiled binaries
that worked with the older library may bomb if you have upgraded your
library. The solution is to either recompile the applications from the
source or to obtain newer precompiled binaries. If you are in the process
of upgrading your system to <tt>libc 6</tt> and are experiencing problems,
refer to Eric Green's <em>Glibc 2 HOWTO</em>.
<tscreen><verb>
</verb></tscreen>
Note that there are some minor incompatibilities between <tt>glibc</tt>
versions, so a binary built with <tt>glibc 2.1</tt> may not work with
<tt>glibc 2.0</tt>, and vice versa.
</itemize>
<itemize>
Sometimes it is necessary to remove the <em>-ansi</em> option from the
compile flags in the <tt>Makefile</tt>. This enables gcc's extra, non-ANSI features,
and allows building packages that require these extensions. (Thanks to Sebastien
Blondeel for pointing this out.)
</itemize>
<itemize>
<item>Some programs require having <em>setuid root</em>, in order to run
with <em>root privileges</em>. The command to implement this is
<bf>chmod u+s filename</bf>, <em>as root</em> (note that the program
must already be owned by root). This has the effect of setting
the <em>setuid</em> bit in the file permissions. This issue comes up
when the program accesses the system hardware, such as a modem or CD ROM
drive, or when the SVGA libs are invoked from console mode, as in one
particularly notorious emulation package. If a program works when run by
root, but gives <em>access denied</em> error messages to an ordinary
user, suspect this as the cause.
<P>
<bf>Warning:</bf>
A program with <em>setuid</em> as root may pose a security risk to your
system. The program runs with root privileges and thus has the potential
for doing significant damage. Make certain that you know what the
program does, by looking at the source if possible, before setting the
<em>setuid</em> bit.
</itemize>
<sect1>Tweaking and fine tuning
<p>
You may wish to examine the <tt>Makefile</tt> to make certain that
the best compilation options for your system are invoked. For example,
setting the <em>-O2</em> flag chooses the highest level of optimization
and the <em>-fomit-frame-pointer</em> flag results in a smaller binary
(though debugging will then be disabled). <bf>Do not play around with
this unless you know what you are doing, and in any case, not until
after a trial <em>build</em> works.</bf>
<sect1>Where to go for more help
<p>
In my experience, perhaps 25% of applications build "right out
of the box". Another 50% or so can be "persuaded" to build with
an effort ranging from trivial to herculean. That still means a
significant number of packages will not build no matter what. Even
then, the Intel <tt>ELF</tt> and/or <tt>a.out</tt> binaries for
these might possibly be found at <htmlurl url="ftp://metalab.unc.edu"
name="Sunsite"> or the <htmlurl url="ftp://tsx-11.mit.edu" name = "TSX-11
archive">. <url url="http://redhat.com" name="Red Hat"> and <url
url="http://www.debian.org" name="Debian"> have extensive archives of
prepackaged binaries of most of the popular Linux software. Perhaps
the author of the software can supply the binaries compiled for your
particular flavor of machine.
<tt>Note that if you obtain precompiled binaries, you will need to check
for compatibility with your system:</tt>
<itemize>
<item><tt>The binaries must run on your hardware (i.e., Intel
x86).</tt>
<item><tt>The binaries must be compatible with your kernel (i.e., a.out or
ELF).</tt>
<item><tt>Your libraries must be up to date.</tt>
<item><tt>Your system must have the appropriate installation utility (rpm or
deb)</tt>.
</itemize>
If all else fails, you may find help in the appropriate
newsgroups, such as <htmlurl url="news://comp.os.linux.x"
name="comp.os.linux.x"> or <htmlurl url="news://comp.os.linux.development"
name="comp.os.linux.development">.
If nothing at all works, at least you gave it your best effort, and you
learned a lot.
<sect>Final Steps<label id="finalsteps">
<p>
Read the software package documentation to determine whether certain
environmental variables need setting (in <tt>.bashrc</tt>
or <tt>.cshrc</tt>) and
if the <tt>.Xdefaults</tt> and <tt>.Xresources</tt> files need customizing.
There may be an applications default file, usually named <tt>Xfoo.ad</tt>
in the original Xfoo distribution. If so, edit the Xfoo.ad file to
customize it for your machine, then rename (<bf>mv</bf>) it Xfoo
and install it in the <tt>/usr/lib/X11/app-defaults</tt> directory,
<em>as root</em>. Failure to do this may cause the software to behave
strangely or even refuse to run.
Most software packages come with one or more preformatted man
pages. <em>As root</em>, copy the Xfoo.man file to the appropriate
<tt>/usr/man</tt>, <tt>/usr/local/man</tt>, or <tt>/usr/X11R6/man</tt>
directory (<tt>man1</tt> - <tt>man9</tt>), and rename it accordingly.
For example, if Xfoo.man ends up in /usr/man/man4, it should be
renamed Xfoo.4 (mv Xfoo.man Xfoo.4). By convention, user commands go
in <tt>man1</tt>, games in <tt>man6</tt>, and administration packages in
<tt>man8</tt> (see the <em>man docs</em> for more details). Of course,
you may deviate from this on your own system, if you like.
A few packages will not install the binaries in the appropriate system
directories, that is, they are missing the <em>install</em> option in the
<tt>Makefile</tt>. Should this be the case, you can install the binaries
manually by copying the binaries to the appropriate system directory,
<tt>/usr/bin</tt>, <tt>/usr/local/bin</tt> or <tt>/usr/X11R6/bin</tt>,
<em>as root</em>, of course. Note that <tt>/usr/local/bin</tt> is
the preferred directory for binaries that are not part of the Linux
distribution's base install.
Some or all of the above procedures should, in most cases, be handled
automatically by a <bf>make install</bf>, and possibly a <bf>make
install.man</bf> or <bf>make install_man</bf>. If so, the <tt>README</tt>
or <tt>INSTALL</tt> doc file will specify this.
<sect>First Example: Xscrabble
<p>
Matt Chapman's <tt>Xscrabble</tt> seemed like a program that would be
interesting to have, since I happen to be an avid Scrabble<tt>TM</tt>
player. I downloaded it, uncompressed it, and built it following the
procedure in the README file:
<tscreen><verb>
xmkmf
make Makefiles
make includes
make
</verb></tscreen>
<em>Of course it did not work...</em>
<tscreen><verb>
gcc -o xscrab -O2 -O -L/usr/X11R6/lib
init.o xinit.o misc.o moves.o cmove.o main.o xutils.o mess.o popup.o
widgets.o display.o user.o CircPerc.o
-lXaw -lXmu -lXExExt -lXext -lX11 -lXt -lSM -lICE -lXExExt -lXext -lX11
-lXpm -L../Xc -lXc
BarGraf.o(.text+0xe7): undefined reference to `XtAddConverter'
BarGraf.o(.text+0x29a): undefined reference to `XSetClipMask'
BarGraf.o(.text+0x2ff): undefined reference to `XSetClipRectangles'
BarGraf.o(.text+0x375): undefined reference to `XDrawString'
BarGraf.o(.text+0x3e7): undefined reference to `XDrawLine'
etc.
etc.
etc...
</verb></tscreen>
I enquired about this in the <htmlurl url="news://comp.os.linux.x"
name="comp.os.linux.x"> newsgroup, and someone kindly pointed out that
apparently the Xt, Xaw, Xmu, and X11 libs were not being found at the
link stage. Hmmm...
There were two main Makefiles, and the one in the <tt>src</tt> directory
caught my interest. One line in the Makefile defined LOCAL_LIBS as:
LOCAL_LIBS = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB) Here were
references to the libs not being found by the linker.
Looking for the next reference to LOCAL_LIBS, I saw on line 495 of that
Makefile:
<tscreen><verb>
$(CCLINK) -o $@ $(LDOPTIONS) $(OBJS) $(LOCAL_LIBS) $(LDLIBS)
$(EXTRA_LOAD_FLAGS)
</verb></tscreen>
Now what were these LDLIBS?
<tscreen><verb>
LDLIBS = $(LDPOSTLIB) $(THREADS_LIBS) $(SYS_LIBRARIES)
$(EXTRA_LIBRARIES)
</verb></tscreen>
The SYS_LIBRARIES were:
<tscreen><verb>
SYS_LIBRARIES = -lXpm -L../Xc -lXc
</verb></tscreen>
Yes! Here were the missing libraries.
Possibly the linker needed to see the LDLIBS before the LOCAL_LIBS...
So, the first thing to try was to modify the Makefile by transposing the
$(LOCAL_LIBS) and $(LDLIBS) on line 495, so it would now read:
<tscreen><verb>
$(CCLINK) -o $@ $(LDOPTIONS) $(OBJS) $(LDLIBS) $(LOCAL_LIBS)
$(EXTRA_LOAD_FLAGS) ^^^^^^^^^^^^^^^^^^^^^^^
</verb></tscreen>
I tried running <em>make</em> again with the above change, and lo and
behold, it worked this time. Of course, Xscrabble still needed some
fine tuning and twiddling, such as renaming the dictionary and
commenting out some assert statements in one of the source files, but
since then it has provided me with many hours of pleasure.
[Note that a newer version of Xscrabble is now available in rpm format, and
this installs without problems.]
You may e-mail <url url="mailto:matt@belgarath.demon.co.uk" name="Matt
Chapman">, and download <em>Xscrabble</em> from his <url
url="http://www.belgarath.demon.co.uk/programs/index.html" name="home
page">.
<tscreen><verb>
Scrabble is a registered trademark of the Milton Bradley Co., Inc.
</verb></tscreen>
<sect>Second Example: Xloadimage
<p>
This example poses an easier problem. The <em>xloadimage</em> program
seemed a useful addition to my set of graphic tools. I copied the
<tt>xloadi41.gz</tt> file directly from the source directory on the CD
included with the excellent <ref id="refs" name="X User Tools"> book, by
Mui and Quercia. As expected, <em>tar xzvf</em> unarchives the files.
The <em>make</em>, however, produces a nasty-looking error and
terminates.
<tscreen><verb>
gcc -c -O -fstrength-reduce -finline-functions -fforce-mem
-fforce-addr -DSYSV -I/usr/X11R6/include
-DSYSPATHFILE=\"/usr/lib/X11/Xloadimage\" mcidas.c
In file included from /usr/include/stdlib.h:32,
from image.h:23,
from xloadimage.h:15,
from mcidas.c:7:
/usr/lib/gcc-lib/i486-linux/2.6.3/include/stddef.h:215:
conflicting types for `wchar_t'
/usr/X11R6/include/X11/Xlib.h:74: previous declaration of
`wchar_t'
make[1]: *** [mcidas.o] Error 1
make[1]: Leaving directory
`/home/thegrendel/tst/xloadimage.4.1'
make: *** [default] Error 2
</verb></tscreen>
The error message contains the essential clue.
Looking at the file <tt>image.h</tt>, line 23...
<tscreen><verb>
#include <stdlib.h>
</verb></tscreen>
Aha, somewhere in the source for <em>xloadimage</em>, <em>wchar_t</em>
has been redefined from what was specified in the standard include file,
<tt>stdlib.h</tt>. Let us first try commenting out line 23 in
<tt>image.h</tt>, as perhaps the <em>stdlib.h include</em> is
not, after all, necessary.
At this point, the build proceeds without any fatal errors. The
<em>xloadimage</em> package functions correctly now.
<sect>Third Example: Fortune
<p>
This example requires some knowledge of C programming. The majority
of UNIX/Linux software is written in C, and learning at least a little
bit of C would certainly be an asset for anyone serious about software
installation.
The notorious <em>fortune</em> program displays up a humorous saying, a
"fortune cookie", every time Linux boots up. Unfortunately (pun intended),
attempting to build fortune on a Red Hat distribution with a 2.0.30
kernel generates fatal errors.
<tscreen><verb>
~/fortune# make all
gcc -O2 -Wall -fomit-frame-pointer -pipe -c fortune.c -o
fortune.o
fortune.c: In function `add_dir':
fortune.c:551: structure has no member named `d_namlen'
fortune.c:553: structure has no member named `d_namlen'
make[1]: *** [fortune.o] Error 1
make[1]: Leaving directory `/home/thegrendel/for/fortune/fortune'
make: *** [fortune-bin] Error 2
</verb></tscreen>
Looking at <tt>fortune.c</tt>, the pertinent lines are these.
<tscreen><verb>
if (dirent->d_namlen == 0)
continue;
name = copy(dirent->d_name, dirent->d_namlen);
</verb></tscreen>
We need to find the structure <tt>dirent</tt>, but it is not declared in
the <em>fortune.c</em> file, nor does a <bf>grep dirent</bf> show it in
any of the other source files. However, at the top of
<em>fortune.c</em>, there is the following line.
<tscreen><verb>
#include <dirent.h>
</verb></tscreen>
This appears to be a system library include file, therefore, the logical
place to look for <em>dirent.h</em> is in <em>/usr/include</em>.
Indeed, there does exist a <em>dirent.h</em> file in
<em>/usr/include</em>, but that file does not contain the declaration of
the <tt>dirent</tt> structure. There is, however, a reference to
another <em>dirent.h</em> file.
<tscreen><verb>
#include <linux/dirent.h>
</verb></tscreen>
At last, going to <em>/usr/include/linux/dirent.h</em>, we find the
structure declaration we need.
<tscreen><verb>
struct dirent {
long d_ino;
__kernel_off_t d_off;
unsigned short d_reclen;
char d_name[256]; /* We must not include
limits.h! */
};
</verb></tscreen>
Sure enough, the structure declaration contains no <em>d_namelen</em>,
but there are a couple of "candidates" for its equivalent. The most
likely of these is <em>d_reclen</em>, since this structure member
probably represents the length of something and it is a short integer.
The other possibility, <em>d_ino</em>, could be an inode number, judging
by its name and type. As a matter of fact, we are probably dealing with
a "directory entry" structure, and these elements represent attributes
of a file, its name, inode, and length (in blocks). This would seem to
validate our guess.
Let us edit the file <tt>fortune.c</tt>, and change the two
<em>d_namelen</em> references in lines 551 and 553 to <em>d_reclen</em>.
Try a <em>make all</em> again. <bf>Success.</bf> It builds without
errors. We can now get our "cheap thrills" from fortune.
<sect>Fourth Example: Hearts
<p>
Here is the hoary old game of Hearts, written for UNIX systems by Bob
Ankeney sometime in the '80's, revised in 1992 by Mike Yang, and currently
maintained by <url url="mailto:badger@phylo.life.uiuc.edu" name="Jonathan
Badger">. Its predecessor was an even older Pascal program by Don
Backus of Oregon Software, later updated by Jeff Hemmerling. Originally
intended as a multiplayer client, it also works well in single-player
mode against computer opponents. The graphics are nice, though the game
lacks sophisticated features and the computer players are not particularly
strong. All the same, it seems to be the only decent Hearts game available
for UNIX and Linux machines even at this late date.
Due to its age and lineage, this package is particularly difficult to
build on a Linux system. It requires solving a long and perplexing series
of puzzles. It is an exercise in patience and determination.
<em>Before beginning, make certain that you have either the <tt>motif</tt> or
<tt>lesstif</tt> libraries installed.</em>
<itemize>
<item><bf></bf>
</itemize>
<bf>xmkmf</bf>
<bf>make</bf>
<tscreen><verb>
client.c: In function `read_card':
client.c:430: `_tty' undeclared (first use in this function)
client.c:430: (Each undeclared identifier is reported only once
client.c:430: for each function it appears in.)
client.c: In function `scan':
client.c:685: `_tty' undeclared (first use in this function)
make: *** [client.o] Error 1
</verb></tscreen>
These are the culprits in the file <tt>client.c</tt>:
<tscreen><verb>
#ifndef SYSV
(buf[2] != _tty.sg_erase) && (buf[2] != _tty.sg_kill)) {
#else
(buf[2] != CERASE) && (buf[2] != CKILL)) {
#endif
</verb></tscreen>
<itemize>
<item><bf></bf>
</itemize>
In <tt>client.c</tt>, add
<tscreen><verb>
#define SYSV
</verb></tscreen>
at line 39. This will bypass the reference to <em>_tty</em>.
<bf>make</bf>
<tscreen><verb>
client.c:41: sys/termio.h: No such file or directory
make: *** [client.o] Error 1
</verb></tscreen>
<itemize>
<item><bf></bf>
</itemize>
The include file <tt>termio.h</tt> is in the <tt>/usr/include</tt>
directory on a Linux system, rather than the <tt>/usr/include/sys</tt>
one, as was the case on older UNIX machines. Therefore, change line 41
of <tt>client.c</tt> from
<tscreen><verb>
#include <sys/termio.h>
</verb></tscreen>
to
<tscreen><verb>
#include <termio.h>
</verb></tscreen>
<bf>make</bf>
<tscreen><verb>
gcc -o hearts -g -L/usr/X11R6/lib client.o hearts.o select.o connect.o
sockio.o start_dist.o -lcurses -ltermlib
/usr/bin/ld: cannot open -ltermlib: No such file or directory
collect2: ld returned 1 exit status
make: *** [hearts] Error 1
</verb></tscreen>
<itemize>
<item><bf></bf>
</itemize>
Modern Linux distributions use the <em>terminfo</em> and/or
<em>termcap</em> database, rather than the obsolete <em>termlib</em> one.
Edit the <tt>Makefile</tt>.
Line 655:
<tscreen><verb>
CURSES_LIBRARIES = -lcurses -ltermlib
</verb></tscreen>
changes to:
<tscreen><verb>
CURSES_LIBRARIES = -lcurses -ltermcap
</verb></tscreen>
<bf>make</bf>
<tscreen><verb>
gcc -o xmhearts -g -L/usr/X11R6/lib xmclient.o hearts.o select.o
connect.o sockio.o start_dist.o gfx.o -lXm_s -lXt -lSM -lICE -lXext -lX11
-lPW
/usr/bin/ld: cannot open -lXm_s: No such file or directory
collect2: ld returned 1 exit status
</verb></tscreen>
<itemize>
<item><bf></bf>
</itemize>
The main <em>lesstif</em> library is <tt>libXm</tt>, rather than
<tt>libXm_s</tt>. Therefore, edit the <tt>Makefile</tt>.
In line 653:
<tscreen><verb>
XMLIB = -lXm_s $(XTOOLLIB) $(XLIB) -lPW
</verb></tscreen>
changes to:
<tscreen><verb>
XMLIB = -lXm $(XTOOLLIB) $(XLIB) -lPW
</verb></tscreen>
<bf>make</bf>
<tscreen><verb>
gcc -o xmhearts -g -L/usr/X11R6/lib xmclient.o hearts.o select.o
connect.o sockio.o start_dist.o gfx.o -lXm -lXt -lSM -lICE -lXext -lX11 -lPW
/usr/bin/ld: cannot open -lPW: No such file or directory
collect2: ld returned 1 exit status
make: *** [xmhearts] Error 1
</verb></tscreen>
<itemize>
<item><bf></bf>
</itemize>
Round up the usual suspects.
There is no <tt>PW</tt> library. Edit the <tt>Makefile</tt>.
Line 653:
<tscreen><verb>
XMLIB = -lXm $(XTOOLLIB) $(XLIB) -lPW
</verb></tscreen>
changes to:
<tscreen><verb>
XMLIB = -lXm $(XTOOLLIB) $(XLIB) -lPEX5
</verb></tscreen>
(The <tt>PEX5</tt> lib comes closest to <tt>PW</tt>.)
<bf>make</bf>
<tscreen><verb>
rm -f xmhearts
gcc -o xmhearts -g -L/usr/X11R6/lib xmclient.o hearts.o select.o
connect.o sockio.o start_dist.o gfx.o -lXm -lXt -lSM -lICE -lXext -lX11 -lPEX5
</verb></tscreen>
The <tt>make</tt> finally works (hurray!).
<itemize>
<item><bf></bf>
</itemize>
<em>Installation:</em>
As root,
<tscreen><verb>
[root@localhost hearts]# make install
install -c -s hearts /usr/X11R6/bin/hearts
install -c -s xmhearts /usr/X11R6/bin/xmhearts
install -c -s xawhearts /usr/X11R6/bin/xawhearts
install in . done
</verb></tscreen>
<itemize>
<item><bf></bf>
</itemize>
<em>Test run:</em>
<bf>rehash</bf>
(We're running the <tt>tcsh</tt> shell.)
<bf>xmhearts</bf>
<tscreen><verb>
localhost:~/% xmhearts
Can't invoke distributor!
</verb></tscreen>
<itemize>
<item><bf></bf>
</itemize>
From <tt>README</tt> file in the <tt>hearts</tt> package:
<tscreen><verb>
Put heartsd, hearts_dist, and hearts.instr in the HEARTSLIB
directory defined in local.h and make them world-accessible.
</verb></tscreen>
From the file <tt>local.h</tt>:
<tscreen><verb>
/* where the distributor, dealer and instructions live */
#define HEARTSLIB "/usr/local/lib/hearts"
</verb></tscreen>
This is a classic case of RTFM.
As <em>root</em>,
<bf>cd /usr/local/lib</bf>
<bf>mkdir hearts</bf>
<bf>cd !$</bf>
Copy the <tt>distributor</tt> files to this directory.
<bf>cp /home/username/hearts/heartsd .</bf>
<bf>cp /home/username/hearts/hearts_dist .</bf>
<bf>cp /home/username/hearts/hearts.instr .</bf>
<itemize>
<item><bf></bf>
</itemize>
<em>Try another test run.</em>
<bf>xmhearts</bf>
It works some of the time, but more often than not crashes with a
<tt>dealer died!</tt> message.
<itemize>
<item><bf></bf>
</itemize>
The "distributor" and "dealer" scan the hardware ports. We should thus
suspect that those programs need root user privileges.
Try, as <em>root</em>,
<bf>chmod u+s /usr/local/lib/heartsd</bf>
<bf>chmod u+s /usr/local/lib/hearts_dist</bf>
(Note that, as previously discussed, <em>suid</em> binaries may create
security holes.)
<bf>xmhearts</bf>
<em>It finally works!</em>
<tt><em>Hearts</em> is available from <htmlurl
url="ftp://metalab.unc.edu/pub/Linux/games/multiplayer/hearts.tgz"
name="Sunsite">.</tt>
<sect>Fifth Example: XmDipmon
<p>
<tscreen><verb>
Bullwinkle: Hey Rocky, watch me pull a rabbit out of my hat.
Rocky: But that trick never works.
Bullwinkle: This time for sure.
Presto!
Well, I'm gettin' close.
Rocky: And now it's time for another special feature.
--- "Rocky and His Friends"
</verb></tscreen>
XmDipmon is a nifty little application that displays a button showing the
status of an Internet connection. It flashes and beeps when the connection
is broken, as is all too often the case in on rural telephone systems.
Unfortunately, XmDipmon works only with <em>dip</em>, making it useless
for those people, the majority, who use <em>chat</em> to connect.
Building XmDipmon is not a problem. XmDipmon links to the <em>Motif</em>
libraries, but it builds and works fine with <em>Lesstif</em>. The
challenge is to alter the package to work when using <em>chat</em>. This
involves actually tinkering with the source code, and necessarily requires
some programming knowledge.
<tscreen><verb>
"When xmdipmon starts up, it checks for a file called /etc/dip.pid
(you can let it look at another file by using the -pidfile
command line option). This file contains the PID of the dip
deamon (dip switches itself into deamon mode once it has
established a connection)."
--- from the XmDipmon README file
</verb></tscreen>
Using the <em>-pidfile</em> option, the program can be directed to
check for a different file upon startup, one that exists only during
a successful <em>chat</em> login. The obvious candidate is the modem
lock file. We could therefore try invoking the program with <bf>xmdipmon
-pidfile /var/lock/LCK..ttyS3</bf> (this assumes that the modem is on
com port #4, ttyS3). This only solves part of the problem, however. The
program continually monitors the <em>dip daemon</em>, and we need to
change this so it instead polls a process associated with <em>chat</em>
or <em>ppp</em>.
There is only a single source file, and fortunately it is
well-commented. Scanning the <tt>xmdipmon.c</tt> file, we find the
<em>getProcFile</em> function, whose header description reads as follows.
<tscreen><verb>
/*****
* Name: getProcFile
* Return Type: Boolean
* Description: tries to open the /proc entry as read from the dip pid file.
<snip>
*****/
</verb></tscreen>
We are hot on the trail now. Tracing into the body of the function...
<tscreen><verb>
/* we watch the status of the real dip deamon */
sprintf(buf, "/proc/%i/status", pid);
procfile = (String)XtMalloc(strlen(buf)*sizeof(char)+1);
strcpy(procfile, buf);
procfile[strlen(buf)] = '\0';
</verb></tscreen>
The culprit is line 2383:
<tscreen><verb>
sprintf(buf, "/proc/%i/status", pid);
^^^^^^^^^^^^^^^^^^^^^
</verb></tscreen>
This checks whether the dip daemon process is running . So, how can we
change this to monitor the pppd daemon instead?
Looking at the <em>pppd</em> manpage:
<tscreen><verb>
FILES
/var/run/pppn.pid (BSD or Linux), /etc/ppp/pppn.pid (others)
Process-ID for pppd process on ppp interface unit n.
</verb></tscreen>
Change line 2383 in <tt>xmdipmon.c</tt> to:
<tscreen><verb>
sprintf(buf, "/var/run/ppp0.pid" );
</verb></tscreen>
Rebuild the revised package. No problems with the build. Now test it
with the new command line argument. It works like a charm. The little
blue button indicates when a <tt>ppp</tt> connection to the ISP has
been established, and flashes and beeps when the connection is broken.
Now we have a fully functional <em>chat</em> monitor.
XmDipmon can be downloaded from <htmlurl
url="http://www.xs4all.nl/~ripley/RSD/linux.html" name="Ripley Linux Tools">.
<sect>Where to Find Source Archives
<p>
Now that you are eager to use your newly acquired
knowledge to add utilities and other goodies to
your system, you may find them online at the <url
url="http://www.redhat.com/linux-info/linux-app-list/linapps.html"
name="Linux Applications and Utilities Page">, or on one of the very
reasonably priced CD ROM archives by <url url="http://www.redhat.com/"
name="Red Hat">, <url url="http://www.infomagic.com" name="InfoMagic">,
<url url="http://www.lsl.com" name="Linux Systems Labs">, <url
url="http://www.cheapbytes.com" name="Cheap Bytes">, and others.
A comprehensive repository of source code is the <htmlurl
url="ftp://ftp.vix.com/pub/usenet/comp.sources.unix/" name="comp sources
UNIX archive">.
Much UNIX source code is posted on the <htmlurl url="news://alt.sources"
name="alt.sources"> newsgroup. If you are looking for particular source
code packages, you may post on the related <htmlurl
url="news://alt.sources.wanted" name="alt.sources.wanted"> newsgroup.
Another good place to check is the <htmlurl
url="news://comp.os.linux.announce"
name="comp.os.linux.announce"> newsgroup. To get on the <htmlurl
url="mailto:unix-sources@pa.dec.com" name="Unix sources"> mailing list,
send a <em>subscribe</em> message there.
Archives for the <htmlurl url="news://alt.sources" name="alt.sources">
newsgroup are at the following ftp sites:
<itemize>
<item><htmlurl url="ftp://ftp.sterling.com/usenet/alt.sources/"
name="ftp.sterling.com/usenet/alt.sources/">
<item><htmlurl
url="ftp://wuarchive.wustl.edu/usenet/alt.sources/articles"
name="wuarchive.wustl.edu/usenet/alt.sources/articles">
<item><htmlurl
url="ftp://src.doc.ic.ac.uk/usenet/alt.sources/articles"
name="src.doc.ic.ac.uk/usenet/alt.sources/articles">
</itemize>
<sect>Final Words
<p>
To sum up, persistence makes all the difference (and a high frustration
threshold certainly helps). As in all endeavors, learning from mistakes
is critically important. Each misstep, every failure contributes to the
body of knowledge that will lead to mastery of <bf>the art of building
software</bf>.
<sect>References and Further Reading<label id="refs">
<p>
<tscreen><verb>
BORLAND C++ TOOLS AND UTILITIES GUIDE, Borland International, 1992,
pp. 9-42.
[One of the manuals distributed with Borland C++, ver. 3.1. Gives
a fairly good intro to make syntax and concepts, using Borland's
crippled implementation for DOS.]
DuBois, Paul: SOFTWARE PORTABILITY WITH IMAKE, O'Reilly and Associates,
1996, ISBN 1-56592-226-3.
[This is reputed to be the definitive imake reference, though I did not
have it available when writing this article.]
Frisch, Aeleen: ESSENTIAL SYSTEM ADMINISTRATION (2nd ed.), O'Reilly and
Associates, 1995, ISBN 1-56592-127-5.
[This otherwise excellent sys admin handbook has only sketchy coverage
of software building.]
Hekman, Jessica: LINUX IN A NUTSHELL, O'Reilly and Associates, 1997, ISBN
1-56592-167-4.
[Good all-around reference to Linux commands.]
Lehey, Greg: PORTING UNIX SOFTWARE, O'Reilly and Associates, 1995, ISBN
1-56592-126-7.
Mayer, Herbert G.: ADVANCED C PROGRAMMING ON THE IBM PC, Windcrest Books,
1989, ISBN 0-8306-9363-7.
[An idea-filled book for the intermediate to advanced C programmer.
Superb coverage of algorithms, quirks of the language, and even
amusements. Unfortunately, out of print.]
Mui, Linda and Valerie Quercia: X USER TOOLS, O'Reilly and Associates,
1994, ISBN 1-56592-019-8, pp. 734-760.
Oram, Andrew and Steve Talbott: MANAGING PROJECTS WITH MAKE, O'Reilly
and Associates, 1991, ISBN 0-937175-90-0.
Peek, Jerry and Tim O'Reilly and Mike Loukides: UNIX POWER TOOLS,
O'Reilly and Associates / Random House, 1997, ISBN 1-56592-260-3.
[A wonderful source of ideas, and tons of utilities you may end up
building from the source code, using the methods discussed in
this article.]
Stallman, Richard M. and Roland McGrath: GNU MAKE, Free Software
Foundation, 1995, ISBN 1-882114-78-7.
[Required reading.]
Waite, Mitchell, Stephen Prata, and Donald Martin: C PRIMER PLUS, Waite Group
Press, ISBN 0-672-22090-3,.
[Probably the best of the introductions to C programming. Extensive
coverage for a primer. Newer editions now available.]
Welsh, Matt and Lar Kaufman: RUNNING LINUX, O'Reilly and Associates,
1996, ISBN 1-56592-151-8.
[Still the best overall Linux reference, though lacking in depth
in some areas.]
The man pages for dpkg, gcc, gzip, imake, ldconfig, ldd, make, nm, patch,
rpm, shar, strip, tar, termcap, terminfo, and xmkmf.
The BZIP2 HOWTO, by David Fetter.
The Glibc2 HOWTO, by Eric Green
The LINUX ELF HOWTO, by Daniel Barlow.
The RPM HOWTO, by Donnie Barnes.
The StarOffice miniHOWTO, by Matthew Borowski.
</verb></tscreen>
[These HOWTOs should be in the <tt>/usr/doc/HOWTO</tt> or
<tt>/usr/doc/HOWTO/mini</tt> directory on your system. Updated
versions are available in text, HTML, and SGML format from the <url
url="http://metalab.unc.edu/LDP/HOWTO" name="LDP site">, and usually
from the respective authors' home sites.]
<sect>Credits
<p>
The author of this HOWTO would like to thank the following persons for their
helpful suggestions, corrections, and encouragement.
<itemize>
<item>R. Brock Lynn
<item>Michael Jenner
<item>Fabrizio Stefani
</itemize>
Kudos also go to the fine people who have translated this HOWTO into Italian
and Japanese.
And, of course, thanks, praise, benedictions and hosannahs to Greg
Hankins and Tim Bynum of the <url url="http://metalab.unc.edu/LDP/"
name="Linux Documentation Project">, which has made all this possible.
</article>