doc/en/handbook/linuxemu/chapter.sgml
Bill Fumerola 05d191f662 freebsd.org -> FreeBSD.org, which seems to be the domain name of choice.
FreeBSD, Inc. now owes me a new keyboard as I've seemed to have worn out
my "shift" and "`" key from sending vi so many "~"s. :->
1999-06-20 21:19:40 +00:00

947 lines
39 KiB
Text

<!--
The FreeBSD Documentation Project
$Id: chapter.sgml,v 1.15 1999-06-20 21:19:13 billf Exp $
-->
<chapter id="linuxemu">
<title>Linux Emulation</title>
<para><emphasis>Contributed by &a.handy; and &a.rich;</emphasis></para>
<sect1>
<title>How to Install the Linux Emulator</title>
<para>Linux emulation in FreeBSD has reached a point where it is possible
to run a large fraction of Linux binaries in both a.out and ELF format.
The linux emulation in the 2.1-STABLE branch is capable of running Linux
DOOM and Mathematica; the version present in &rel.current;-RELEASE is
vastly more capable and runs all these as well as Quake, Abuse, IDL,
netrek for Linux and a whole host of other programs.</para>
<para>There are some Linux-specific operating system features that are not
supported on FreeBSD. Linux binaries will not work on FreeBSD if they
use the Linux <filename>/proc</filename> filesystem (which is different
from the optional FreeBSD <filename>/proc</filename> filesystem) or
i386-specific calls, such as enabling virtual 8086 mode.</para>
<para>Depending on which version of FreeBSD you are running, how you get
Linux-emulation up will vary slightly:</para>
<sect2>
<title>Installing Linux Emulation in 2.1-STABLE</title>
<para>The <filename>GENERIC</filename> kernel in 2.1-STABLE is not
configured for linux compatibility so you must reconfigure your kernel
for it. There are two ways to do this: 1. linking the emulator
statically in the kernel itself and 2. configuring your kernel to
dynamically load the linux loadable kernel module (LKM).</para>
<para>To enable the emulator, add the following to your configuration
file (c.f. <filename>/sys/i386/conf/LINT</filename>):</para>
<programlisting>
options COMPAT_LINUX</programlisting>
<para>If you want to run doom or other applications that need shared
memory, also add the following.</para>
<programlisting>
options SYSVSHM</programlisting>
<para>The linux system calls require 4.3BSD system call compatibility.
So make sure you have the following.</para>
<programlisting>
options "COMPAT_43"</programlisting>
<para>If you prefer to statically link the emulator in the kernel rather
than use the loadable kernel module (LKM), then add</para>
<programlisting>
options LINUX</programlisting>
<para>Then run config and install the new kernel as described in the
<link linkend="kernelconfig">kernel configuration</link>
section.</para>
<para>If you decide to use the LKM you must also install the loadable
module. A mismatch of versions between the kernel and loadable module
can cause the kernel to crash, so the safest thing to do is to
reinstall the LKM when you install the kernel.</para>
<screen>&prompt.root; <userinput>cd /usr/src/lkm/linux</userinput>
&prompt.root; <userinput>make all install</userinput></screen>
<para>Once you have installed the kernel and the LKM, you can invoke
`linux' as root to load the LKM.</para>
<screen>&prompt.root; <userinput>linux</userinput>
Linux emulator installed
Module loaded as ID 0</screen>
<para>To see whether the LKM is loaded, run
<command>modstat</command>.</para>
<screen>&prompt.user; modstat
Type Id Off Loadaddr Size Info Rev
Module Name EXEC 0 3 f0baf000 0018 f0bb4000 1 linux_emulator</screen>
<para>You can cause the LKM to be loaded when the system boots in either
of two ways. In FreeBSD 2.2.1-RELEASE and 2.1-STABLE enable it in
<filename>/etc/sysconfig</filename>
<programlisting>
linux=YES</programlisting>
by changing it from NO to YES. FreeBSD 2.1 RELEASE and earlier do not
have such a line and on those you will need to edit
<filename>/etc/rc.local</filename> to add the following line.</para>
<programlisting>
linux</programlisting>
</sect2>
<sect2>
<title>Installing Linux Emulation in 2.2.2-RELEASE and later</title>
<para>It is no longer necessary to specify <literal>options
LINUX</literal> or <literal>options COMPAT_LINUX</literal>. Linux
emulation is done with an LKM (&ldquo;Loadable Kernel Module&rdquo;)
so it can be installed on the fly without having to reboot. You will
need the following things in your startup files, however:</para>
<orderedlist>
<listitem>
<para>In <filename>/etc/rc.conf</filename>, you need the following
line:</para>
<programlisting>
linux_enable=YES</programlisting>
</listitem>
<listitem>
<para>This, in turn, triggers the following action in
<filename>/etc/rc.i386</filename>:</para>
<programlisting>
# Start the Linux binary emulation if requested.
if [ "X${linux_enable}" = X"YES" ]; then echo -n '
linux'; linux &gt; /dev/null 2&gt;&amp;1
fi</programlisting>
</listitem>
</orderedlist>
<para>If you want to verify it is running, modstat will do that:</para>
<screen>&prompt.user; modstat
Type Id Off Loadaddr Size Info Rev Module Name
EXEC 0 4 f09e6000 001c f09ec010 1 linux_mod</screen>
<para>However, there have been reports that this fails on some
2.2-RELEASE and later systems. If for some reason you cannot load the
linux LKM, then statically link the emulator in the kernel by
adding
<programlisting>
options LINUX</programlisting>
to your kernel config file. Then run config and install the new
kernel as described in the <link linkend="kernelconfig">kernel
configuration</link> section.</para>
</sect2>
<sect2>
<title>Installing Linux Runtime Libraries</title>
<sect3>
<title>Installing using the linux_lib port</title>
<para>Most linux applications use shared libraries, so you are still
not done until you install the shared libraries. It is possible to
do this by hand, however, it is vastly simpler to just grab the
linux_lib port:</para>
<screen>&prompt.root; <userinput>cd /usr/ports/emulators/linux_lib</userinput>
&prompt.root; <userinput>make all install</userinput></screen>
<para>and you should have a working linux emulator. Legend (and the
mail archives <!-- smiley -->:-) seems to hold that Linux emulation
works best with linux binaries linked against the ZMAGIC libraries;
QMAGIC libraries (such as those used in Slackware V2.0) may tend to
give the Linuxulator heartburn. Also, expect some programs to
complain about incorrect minor versions of the system libraries. In
general, however, this does not seem to be a problem.</para>
</sect3>
<sect3>
<title>Installing libraries manually</title>
<para>If you do not have the &ldquo;ports&rdquo; distribution, you can
install the libraries by hand instead. You will need the Linux
shared libraries that the program depends on and the runtime linker.
Also, you will need to create a "shadow root" directory,
<filename>/compat/linux</filename>, for Linux libraries on your
FreeBSD system. Any shared libraries opened by Linux programs run
under FreeBSD will look in this tree first. So, if a Linux program
loads, for example, <filename>/lib/libc.so</filename>, FreeBSD will
first try to open <filename>/compat/linux/lib/libc.so</filename>,
and if that does not exist then it will try
<filename>/lib/libc.so</filename>. Shared libraries should be
installed in the shadow tree <filename>/compat/linux/lib</filename>
rather than the paths that the Linux <command>ld.so</command>
reports.</para>
<para>FreeBSD-2.2-RELEASE and later works slightly differently with
respect to <filename>/compat/linux</filename>: all files, not just
libraries, are searched for from the &ldquo;shadow root&rdquo;
<filename>/compat/linux</filename>.</para>
<para>Generally, you will need to look for the shared libraries that
Linux binaries depend on only the first few times that you install
a Linux program on your FreeBSD system. After a while, you will
have a sufficient set of Linux shared libraries on your system to be
able to run newly imported Linux binaries without any extra
work.</para>
</sect3>
<sect3>
<title>How to install additional shared libraries</title>
<para>What if you install the <filename>linux_lib</filename> port and
your application still complains about missing shared libraries? How
do you know which shared libraries Linux binaries need, and where to
get them? Basically, there are 2 possibilities (when following these
instructions: you will need to be root on your FreeBSD system to do
the necessary installation steps).</para>
<para>If you have access to a Linux system, see what shared libraries
the application needs, and copy them to your FreeBSD system.
Example: you have just ftp'ed the Linux binary of Doom. Put it on
the Linux system you have access to, and check which shared
libraries it needs by running <command>ldd
linuxxdoom</command>:</para>
<screen>&prompt.user; <userinput>ldd linuxxdoom</userinput>
libXt.so.3 (DLL Jump 3.1) =&gt; /usr/X11/lib/libXt.so.3.1.0
libX11.so.3 (DLL Jump 3.1) =&gt; /usr/X11/lib/libX11.so.3.1.0
libc.so.4 (DLL Jump 4.5pl26) =&gt; /lib/libc.so.4.6.29</screen>
<para>You would need to get all the files from the last column, and
put them under <filename>/compat/linux</filename>, with the names in
the first column as symbolic links pointing to them. This means you
eventually have these files on your FreeBSD system:</para>
<screen>/compat/linux/usr/X11/lib/libXt.so.3.1.0
/compat/linux/usr/X11/lib/libXt.so.3 -&gt; libXt.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3 -&gt; libX11.so.3.1.0
/compat/linux/lib/libc.so.4.6.29 /compat/linux/lib/libc.so.4 -&gt; libc.so.4.6.29</screen>
<note>
<para>Note that if you already have a Linux shared library with a
matching major revision number to the first column of the
<command>ldd</command> output, you will not need to copy the file
named in the last column to your system, the one you already have
should work. It is advisable to copy the shared library anyway if
it is a newer version, though. You can remove the old one, as
long as you make the symbolic link point to the new one. So, if
you have these libraries on your system:</para>
<screen>/compat/linux/lib/libc.so.4.6.27
/compat/linux/lib/libc.so.4 -&gt; libc.so.4.6.27</screen>
<para>and you find a new binary that claims to require a later
version according to the output of <command>ldd</command>:</para>
<screen>libc.so.4 (DLL Jump 4.5pl26) -&gt; libc.so.4.6.29</screen>
<para>If it is only one or two versions out of date in the in the
trailing digit then do not worry about copying
<filename>/lib/libc.so.4.6.29</filename> too, because the program
should work fine with the slightly older version. However, if you
like you can decide to replace the <filename>libc.so</filename>
anyway, and that should leave you with:</para>
<screen>/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -&gt; libc.so.4.6.29</screen>
</note>
<note>
<para>The symbolic link mechanism is <emphasis>only</emphasis>
needed for Linux binaries. The FreeBSD runtime linker takes care
of looking for matching major revision numbers itself and you do
not need to worry about it.</para>
</note>
</sect3>
<sect3>
<title>Configuring the <filename>ld.so</filename> &mdash; for FreeBSD
2.2-RELEASE and later</title>
<para>This section applies only to FreeBSD 2.2-RELEASE and later.
Those running 2.1-STABLE should skip this section.</para>
<para>Finally, if you run FreeBSD 2.2-RELEASE you must make sure that
you have the Linux runtime linker and its config files on your
system. You should copy these files from the Linux system to their
appropriate place on your FreeBSD system (to the
<filename>/compat/linux</filename> tree):</para>
<screen>/compat/linux/lib/ld.so
/compat/linux/etc/ld.so.config</screen>
<para>If you do not have access to a Linux system, you should get the
extra files you need from various ftp sites. Information on where
to look for the various files is appended below. For now, let us
assume you know where to get the files.</para>
<para>Retrieve the following files (all from the same ftp site to
avoid any version mismatches), and install them under
<filename>/compat/linux</filename> (i.e.
<filename>/foo/bar</filename> is installed as
<filename>/compat/linux/foo/bar</filename>):</para>
<screen>/sbin/ldconfig
/usr/bin/ldd
/lib/libc.so.x.y.z
/lib/ld.so</screen>
<para><command>ldconfig</command> and <command>ldd</command> do not
necessarily need to be under <filename>/compat/linux</filename>; you
can install them elsewhere in the system too. Just make sure they
do not conflict with their FreeBSD counterparts. A good idea would
be to install them in <filename>/usr/local/bin</filename> as
<command>ldconfig-linux</command> and
<command>ldd-linux</command>.</para>
<para>Create the file
<filename>/compat/linux/etc/ld.so.conf</filename>, containing the
directories in which the Linux runtime linker should look for shared
libs. It is a plain text file, containing a directory name on each
line. <filename>/lib</filename> and <filename>/usr/lib</filename>
are standard, you could add the following:</para>
<programlisting>
/usr/X11/lib
/usr/local/lib</programlisting>
<para>When a linux binary opens a library such as
<filename>/lib/libc.so</filename> the emulator maps the name to
<filename>/compat/linux/lib/libc.so</filename> internally. All
linux libraries should be installed under /compat/linux (e.g.
<filename>/compat/linux/lib/libc.so</filename>,
<filename>/compat/linux/usr/X11/lib/libX11.so</filename>, etc.) in
order for the emulator to find them.</para>
<para>Those running FreeBSD 2.2-RELEASE should run the Linux ldconfig
program.</para>
<screen>&prompt.root <userinput>cd /compat/linux/lib</userinput>
&prompt.root; <userinput>/compat/linux/sbin/ldconfig</userinput></screen>
<para><command>ldconfig</command> is statically linked, so it does not
need any shared libraries to run. It creates the file
<filename>/compat/linux/etc/ld.so.cache</filename> which contains
the names of all the shared libraries and should be rerun to
recreate this file whenever you install additional shared
libraries.</para>
<para>On 2.1-STABLE do not install
<filename>/compat/linux/etc/ld.so.cache</filename> or run
<command>ldconfig</command>; in 2.1-STABLE the syscalls are
implemented differently and <command>ldconfig</command> is not
needed or used.</para>
<para>You should now be set up for Linux binaries which only need a
shared libc. You can test this by running the Linux
<command>ldd</command> on itself. Supposing that you have it
installed as <command>ldd-linux</command>, it should produce
something like:</para>
<screen>&prompt.root; <userinput>ldd-linux `which ldd-linux`</userinput>
libc.so.4 (DLL Jump 4.5pl26) =&gt; /lib/libc.so.4.6.29</screen>
<para>This being done, you are ready to install new Linux binaries.
Whenever you install a new Linux program, you should check if it
needs shared libraries, and if so, whether you have them installed
in the <filename>/compat/linux</filename> tree. To do this, you run
the Linux version <command>ldd</command> on the new program, and
watch its output. <command>ldd</command> (see also the manual page
for &man.ldd.1;) will print a list of shared libraries
that the program depends on, in the form
<literal><replaceable>majorname</replaceable>
(<replaceable>jumpversion</replaceable>) =&gt;
<replaceable>fullname</replaceable></literal>.</para>
<para>If it prints <literal>not found</literal> instead of
<replaceable>fullname</replaceable> it means that you need an extra
library. The library needed is shown in majorname and will be of
the form
<literal>lib<replaceable>XXXX</replaceable>.so.<replaceable>N</replaceable></literal>.
You will need to find a
<filename>lib<replaceable>XXXX</replaceable>.so.N.mm</filename> on a
Linux ftp site, and install it on your system. The
<replaceable>XXXX</replaceable> (name) and
<replaceable>N</replaceable> (major revision number) should match;
the minor number(s) <replaceable>mm</replaceable> are less
important, though it is advised to take the most recent
version.</para>
</sect3>
</sect2>
<sect2>
<title>Installing Linux ELF binaries</title>
<para>ELF binaries sometimes require an extra step of
&ldquo;branding&rdquo;. If you attempt to run an unbranded ELF
binary, you will get an error message like the following;</para>
<screen>&prompt.user; <userinput>./my-linux-elf-binary</userinput>
ELF binary type not known
Abort</screen>
<para>To help the FreeBSD kernel distinguish between a FreeBSD ELF
binary from a Linux binary, use the &man.brandelf.1; utility.</para>
<screen>&prompt.user; <userinput>brandelf -t Linux my-linux-elf-binary</userinput></screen>
<para>The GNU toolchain now places the appropriate branding information
into ELF binaries automatically, so you should be needing to do this
step increasingly rarely in future.</para>
</sect2>
<sect2>
<title>Configuring the host name resolver</title>
<para>If DNS does not work or you get the messages
<screen>resolv+: "bind" is an invalid keyword resolv+:
"hosts" is an invalid keyword</screen>
then you need to configure a
<filename>/compat/linux/etc/host.conf</filename> file containing:
<programlisting>
order hosts, bind
multi on</programlisting>
where the order here specifies that <filename>/etc/hosts</filename> is
searched first and DNS is searched second. When
<filename>/compat/linux/etc/host.conf</filename> is not installed
linux applications find FreeBSD's <filename>/etc/host.conf</filename>
and complain about the incompatible FreeBSD syntax. You should remove
<literal>bind</literal> if you have not configured a name-server using
the <filename>/etc/resolv.conf</filename> file.</para>
<para>Lastly, those who run 2.1-STABLE need to set an the
<envar>RESOLV_HOST_CONF</envar> environment variable so that
applications will know how to search the host tables. If you run
FreeBSD 2.2-RELEASE or later, you can skip this. For the
<filename>/bin/csh</filename> shell use:</para>
<screen>&prompt.user; <userinput>setenv RESOLV_HOST_CONF /compat/linux/etc/host.conf</userinput></screen>
<para>For <filename>/bin/sh</filename> use:</para>
<screen>&prompt.user; <userinput>RESOLV_HOST_CONF=/compat/linux/etc/host.conf; export RESOLV_HOST_CONF</userinput></screen>
</sect2>
<sect2>
<title>Finding the necessary files</title>
<note>
<para>The information below is valid as of the time this document was
written, but certain details such as names of ftp sites, directories
and distribution names may have changed by the time you read
this.</para>
</note>
<para>Linux is distributed by several groups that make their own set of
binaries that they distribute. Each distribution has its own name,
like &ldquo;Slackware&rdquo; or &ldquo;Yggdrasil&rdquo;. The
distributions are available on a lot of ftp sites. Sometimes the
files are unpacked, and you can get the individual files you need, but
mostly they are stored in distribution sets, usually consisting of
subdirectories with gzipped tar files in them. The primary ftp sites
for the distributions are:</para>
<orderedlist>
<listitem>
<para>sunsite.unc.edu:/pub/Linux/distributions</para>
</listitem>
<listitem>
<para>tsx-11.mit.edu:/pub/linux/distributions</para>
</listitem>
</orderedlist>
<para>Some European mirrors:</para>
<orderedlist>
<listitem>
<para>ftp.luth.se:/pub/linux/distributions</para>
</listitem>
<listitem>
<para>ftp.demon.co.uk:/pub/unix/linux</para>
</listitem>
<listitem>
<para>src.doc.ic.ac.uk:/packages/linux/distributions</para>
</listitem>
</orderedlist>
<para>For simplicity, let us concentrate on Slackware here. This
distribution consists of a number of subdirectories, containing
separate packages. Normally, they are controlled by an install
program, but you can retrieve files &ldquo;by hand&rdquo; too. First
of all, you will need to look in the <filename>contents</filename>
subdir of the distribution. You will find a lot of small text files
here describing the contents of the separate packages. The fastest
way to look something up is to retrieve all the files in the contents
subdirectory, and grep through them for the file you need. Here is an
example of a list of files that you might need, and in which
contents-file you will find it by grepping through them:</para>
<informaltable frame="none">
<tgroup cols="2">
<thead>
<row>
<entry>Library</entry>
<entry>Package</entry>
</row>
</thead>
<tbody>
<row>
<entry><filename>ld.so</filename></entry>
<entry>ldso</entry>
</row>
<row>
<entry><filename>ldconfig</filename></entry>
<entry>ldso</entry>
</row>
<row>
<entry><filename>ldd</filename></entry>
<entry>ldso</entry>
</row>
<row>
<entry><filename>libc.so.4</filename></entry>
<entry>shlibs</entry>
</row>
<row>
<entry><filename>libX11.so.6.0</filename></entry>
<entry>xf_lib</entry>
</row>
<row>
<entry><filename>libXt.so.6.0</filename></entry>
<entry>xf_lib</entry>
</row>
<row>
<entry><filename>libX11.so.3</filename></entry>
<entry>oldlibs</entry>
</row>
<row>
<entry><filename>libXt.so.3</filename></entry>
<entry>oldlibs</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>So, in this case, you will need the packages ldso, shlibs, xf_lib
and oldlibs. In each of the contents-files for these packages, look
for a line saying <literal>PACKAGE LOCATION</literal>, it will tell
you on which &ldquo;disk&rdquo; the package is, in our case it will
tell us in which subdirectory we need to look. For our example, we
would find the following locations:</para>
<informaltable frame="none">
<tgroup cols="2">
<thead
<row>
<entry>Package</entry>
<entry>Location</entry>
</row>
</thead>
<tbody>
<row>
<entry>ldso</entry>
<entry>diska2</entry>
</row>
<row>
<entry>shlibs</entry>
<entry>diska2</entry>
</row>
<row>
<entry>oldlibs</entry>
<entry>diskx6</entry>
</row>
<row>
<entry>xf_lib</entry>
<entry>diskx9</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>The locations called
&ldquo;disk<replaceable>XX</replaceable>&rdquo; refer to the
<filename>slakware/<replaceable>XX</replaceable></filename>
subdirectories of the distribution, others may be found in the
<filename>contrib</filename> subdirectory. In this case, we could now
retrieve the packages we need by retrieving the following files
(relative to the root of the Slackware distribution tree):</para>
<itemizedlist>
<listitem>
<para><filename>slakware/a2/ldso.tgz</filename></para>
</listitem>
<listitem>
<para><filename>slakware/a2/shlibs.tgz</filename></para>
</listitem>
<listitem>
<para><filename>slakware/x6/oldlibs.tgz</filename></para>
</listitem>
<listitem>
<para><filename>slakware/x9/xf_lib.tgz</filename></para>
</listitem>
</itemizedlist>
<para>Extract the files from these gzipped tarfiles in your
<filename>/compat/linux</filename> directory (possibly omitting or
afterwards removing files you do not need), and you are done.</para>
<para><emphasis>See also:</emphasis>
<filename>ftp://ftp.FreeBSD.org/pub/FreeBSD/2.0.5-RELEASE/xperimnt/linux-emu/README</filename> and <filename>/usr/src/sys/i386/ibcs2/README.iBCS2</filename></para>
</sect2>
</sect1>
<sect1 id="mathematica">
<title>How to Install Mathematica on FreeBSD</title>
<para><emphasis>Contributed by &a.rich; and &a.chuck;</emphasis></para>
<para>This document shows how to install the Linux binary distribution of
Mathematica 2.2 on FreeBSD 2.1.</para>
<para>Mathematica supports Linux but not FreeBSD as it stands. So once
you have configured your system for Linux compatibility you have most of
what you need to run Mathematica.</para>
<para>For those who already have the student edition of Mathematica for
DOS the cost of upgrading to the Linux version at the time this was
written, March 1996, was &#36;45.00. It can be ordered directly from
Wolfram at (217) 398-6500 and paid for by credit card.</para>
<sect2>
<title>Unpacking the Mathematica distribution</title>
<para>The binaries are currently distributed by Wolfram on CDROM. The
CDROM has about a dozen tar files, each of which is a binary
distribution for one of the supported architectures. The one for
Linux is named <filename>LINUX.TAR</filename>. You can, for example,
unpack this into <filename>/usr/local/Mathematica</filename>:</para>
<screen>&prompt.root; <userinput>cd /usr/local</userinput>
&prompt.root; <userinput>mkdir Mathematica</userinput>
&prompt.root; <userinput>cd Mathematica</userinput>
&prompt.root; <userinput>tar -xvf /cdrom/LINUX.TAR</userinput></screen>
</sect2>
<sect2>
<title>Obtaining your Mathematica Password</title>
<para>Before you can run Mathematica you will have to obtain a password
from Wolfram that corresponds to your &ldquo;machine ID&rdquo;.</para>
<para>Once you have installed the linux compatibility runtime libraries
and unpacked the mathematica you can obtain the &ldquo;machine
ID&rdquo; by running the program <command>mathinfo</command> in the
Install directory.</para>
<screen>&prompt.root; <userinput>cd /usr/local/Mathematica/Install</userinput>
&prompt.root; <userinput>mathinfo</userinput>
LINUX: 'ioctl' fd=5, typ=0x89(), num=0x27 not implemented
richc.isdn.bcm.tmc.edu 9845-03452-90255</screen>
<para>So, for example, the &ldquo;machine ID&rdquo; of
<hostid>richc</hostid> is <literal>9845-03452-90255</literal>. You
can ignore the message about the ioctl that is not implemented. It
will not prevent Mathematica from running in any way and you can
safely ignore it, though you will see the message every time you run
Mathematica.</para>
<para>When you register with Wolfram, either by email, phone or fax, you
will give them the &ldquo;machine ID&rdquo; and they will respond with
a corresponding password consisting of groups of numbers. You need to
add them both along with the machine name and license number in your
mathpass file.</para>
<para>You can do this by invoking:</para>
<screen>&prompt.root; <userinput>cd /usr/local/Mathematica/Install</userinput>
&prompt.root; <userinput>math.install</userinput></screen>
<para>It will ask you to enter your license number and the Wolfram
supplied password. If you get them mixed up or for some reason the
math.install fails, that is OK; you can simply edit the file
<filename>mathpass</filename> in this same directory to correct the
info manually.</para>
<para>After getting past the password, math.install will ask you if you
accept the install defaults provided, or if you want to use your own.
If you are like us and distrust all install programs, you probably
want to specify the actual directories. Beware. Although the
math.install program asks you to specify directories, it will not
create them for you, so you should perhaps have a second window open
with another shell so that you can create them before you give them to
the install program. Or, if it fails, you can create the directories
and then restart the <command>math.install</command> program. The
directories we chose to create beforehand and specify to
<command>math.install</command> were:</para>
<informaltable frame="none">
<tgroup cols="2">
<tbody>
<row>
<entry><filename>/usr/local/Mathematica/bin</filename></entry>
<entry>for binaries</entry>
</row>
<row>
<entry><filename>/usr/local/Mathematica/man/man1</filename></entry>
<entry>for man pages</entry>
</row>
<row>
<entry>/usr/local/Mathematica/lib/X11</entry>
<entry>for the XKeysymb file</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>You can also tell it to use <filename>/tmp/math.record</filename>
for the system record file, where it puts logs of sessions. After
this <command>math.install</command> will continue on to unpacking
things and placing everything where it should go.</para>
<para>The Mathematica Notebook feature is included separately, as the X
Front End, and you have to install it separately. To get the X Front
End stuff correctly installed, cd into the
<filename>/usr/local/Mathematica/FrontEnd</filename> directory and
execute the <command>xfe.install</command> shell script. You will
have to tell it where to put things, but you do not have to create any
directories because it will use the same directories that had been
created for math.install. When it finishes, there should be a new
shell script in <filename>/usr/local/Mathematica/bin</filename> called
<filename>mathematica</filename>.</para>
<para>Lastly, you need to modify each of the shell scripts that
Mathematica has installed. At the beginning of every shell script in
<filename>/usr/local/Mathematica/bin</filename> add the following
line:</para>
<screen>&prompt.user; <userinput>XKEYSYMDB=/usr/local/Mathematica/lib/X11/XKeysymDB; export XKEYSYMDB</userinput></screen>
<para>This tells Mathematica were to find its own
version of the key mapping file <filename>XKeysymDB</filename>.
Without this you will get pages of error messages about missing
key mappings.</para>
<para>On 2.1-STABLE you need to add the following as well:</para>
<screen>&prompt.user; <userinput>RESOLV_HOST_CONF=/compat/linux/etc/host.conf; export RESOLV_HOST_CONF</userinput></screen>
<para>This tells Mathematica to use the linux version of host.conf.
This file has a different syntax from FreeBSD's host.conf, so you will
get an error message about <filename>/etc/host.conf</filename> if you
leave this out.</para>
<para>You might also want to modify your
<filename>/etc/manpath.config</filename> file to read the new man
directory, and you may need to edit your <filename>~/.cshrc</filename>
file to add <filename>/usr/local/Mathematica/bin</filename> to your
path.</para>
<para>That is about all it takes. With this you should be able to type
<command>mathematica</command> and get a really slick looking
Mathematica Notebook screen up. Mathematica has included the Motif
user interfaces, but it is compiled in statically, so you do not need
the Motif libraries. Good luck doing this yourself!</para>
</sect2>
<sect2>
<title>Bugs</title>
<para>The Notebook front end is known to hang sometimes when reading
notebook files with an error messages similar to:</para>
<screen><errorname>File .../Untitled-1.mb appears to be broken for OMPR.257.0</errorname></screen>
<para>We have not found the cause for this, but it only affects the
Notebook's X Window front end, not the mathematica engine itself. So
the command line interface invoked by 'math' is unaffected by this
bug.</para>
</sect2>
<sect2>
<title>Acknowledgments</title>
<para>A well-deserved thanks should go to &a.sos; and &a.peter; who made
linux emulation what it is today, and Michael Smith who drove these
two guys like dogs to get it to the point where it runs Linux binaries
better than linux! <!-- smiley -->:-)</para>
</sect2>
</sect1>
<sect1>
<title>How does the emulation work?</title>
<para>This section is based heavily on an e-mail written to the
<email>chat@FreeBSD.org</email> mailing list, written by Terry Lambert
<email>tlambert@primenet.com</email> (Message ID:
<literal>&lt;199906020108.SAA07001@usr09.primenet.com&gt;</literal>).</para>
<para>FreeBSD has an abstraction called an &ldquo;execution class
loader&rdquo;. This is a wedge into the &man.execve.2; system
call.</para>
<para>What happens is that FreeBSD has a list of loaders, instead of a
single loader with a failback to the <literal>#!</literal> loader for
running any shell interpreters or shell scripts.</para>
<para>Historically, the only loader on the UNIX platform examined the
magic number (generally the first 4 or 8 bytes of the file) to see if it
was a binary known to the system, and if so, invoked the binary
loader.</para>
<para>If it was not the binary type for the system, the &man.execve.2;
call returned a failure, and the shell attempted to start executing it
as shell commands.</para>
<para>The assumption was a default of &ldquo;whatever the current shell
is&rdquo;.</para>
<para>Later, a hack was made for &man.sh.1; to examine the first two
characters, and if they were <literal>:\n</literal>, then it invoked the
&man.csh.1; shell instead (I believe SCO first made this hack, but am
willing to be corrected).</para>
<para>What FreeBSD does now is go through a list of loaders, with a
generic <literal>#!</literal> loader that knows about interpreters as
the characters which follow to the next whitespace next to last,
followed by a fallback to <filename>/bin/sh</filename>.</para>
<para>For the Linux binary emulation, FreeBSD sees the magic number as an
ELF binary (it makes no distinction between FreeBSD, Solaris, Linux, or
any other OS which has an ELF image tpye, at this point).</para>
<para>The ELF loader looks for a specialized <emphasis>brand</emphasis>,
which is a comment section in the ELF image, and which is not present on
SVR4/Solaris ELF binaries.</para>
<para>For Linux binaries to function, they must be
<emphasis>branded</emphasis> as type <literal>Linux</literal>; from
&man.brandelf.1;:</para>
<screen>&prompt.root; <userinput>brandelf -t Linux file</userinput></screen>
<para>When this is done, the ELF loader will see the
<literal>Linux</literal> brand on the file.</para>
<para>When the ELF loader sees the <literal>Linux</literal> brand, the
loader replaces a pointer in the <literal>proc</literal>
structure. All system calls are indexed through this pointer (in a
traditional UNIX system, this would be the <literal>sysent[]</literal> structure array, containing the system
calls). In addition, the process is flagged for special handling of the
trap vector for the signal trampoline code, and sever other (minor)
fixups that are handled by the Linux kernel module.</para>
<para>The Linux system call vector contains, among other things, a list of
<literal>sysent[]</literal> entries whose addresses reside in the kernel
module.</para>
<para>When a system call is called by the Linux binary, the trap code
dereferences the system call function pointer off the
<literal>proc</literal> structure, and gets the Linux, not the FreeBSD,
system call entry points.</para>
<para>In addition, the Linux emulation dynamically
<emphasis>reroots</emphasis> lookups; this is, in effect, what the
<literal>union</literal> option to FS mounts ( <emphasis>not</emphasis>
the unionfs!) does. First, an attempt is made to lookup the file in the
<filename>/compat/linux/<replaceable>original-path</replaceable></filename>
directory, <emphasis>then</emphasis> only if that fails, the lookup is
done in the
<filename>/<replaceable>original-path</replaceable></filename>
directory. This makes sure that binaries that require other binaries
can run (e.g., the Linux toolchain can all run under emulation). It
also means that the Linux binaries can load and exec FreeBSD binaries,
if there are no corresponding Linux binaries present, and that you could
place a &man.uname.1; command in the <filename>/compat/linux</filename>
directory tree to ensure that the Linux binaries could not tell they
were not running on Linux.</para>
<para>In effect, there is a Linux kernel in the FreeBSD kernel; the
various underlying functions that implement all of the services provided
by the kernel are identical to both the FreeBSD system call table
entries, and the Linux system call table entries: file system
operations, virtual memory operations, signal delivery, System V IPC,
etc&hellip; The only difference is that FreeBSD binaries get the FreeBSD
<emphasis>glue</emphasis> functions, and Linux binaries get the Linux
<emphasis>glue</emphasis> functions (most older OS's only had their own
<emphasis>glue</emphasis> functions: addresses of functions in a static
global <literal>sysent[]</literal> structure array, instead of addresses
of functions dereferenced off a dynamically initialized pointer in the
<literal>proc</literal> structure of the process making the
call).</para>
<para>Which one is the native FreeBSD ABI? It does not matter. Basically
the only difference is that (currently; this could easily be changed in
a future release, and probably will be after this) the FreeBSD
<emphasis>glue</emphasis> functions are statically linked into the
kernel, and the Linux glue functions can be statically linked, or they
can be accessed via a kernel module.</para>
<para>Yeah, but is this really emulation? No. It is an ABI
implementation, not an emulation. There is no emulator (or simulator,
to cut off the next question) involved.</para>
<para>So why is it called &ldquo;Linux emulation&rdquo;? To make it hard
to sell FreeBSD! <!-- smiley -->8-). Really, it is because the
historical implementation was done at a time when there was really no
word other than that to describe what was going on; saying that FreeBSD
ran Linux binaries was not true, if you did not compile the code in or
load a module, and there needed to be a word to describe what was being
loaded&mdash;hence &ldquo;the Linux emulator&rdquo;.</para>
</sect1>
</chapter>
<!--
Local Variables:
mode: sgml
sgml-declaration: "../chapter.decl"
sgml-indent-data: t
sgml-omittag: nil
sgml-always-quote-attributes: t
sgml-parent-document: ("../handbook.sgml" "part" "chapter")
End:
-->