438 lines
19 KiB
Plaintext
438 lines
19 KiB
Plaintext
|
README for ixemul.library and ixnet.library version 48.0
|
||
|
|
||
|
|
||
|
IMPORTANT
|
||
|
=========
|
||
|
|
||
|
Always read the NEWS file for information about new features! The NEWS file
|
||
|
is part of the ixemul source archive.
|
||
|
|
||
|
Also look at the ix.h header: ixemul-specific functions are documented in that
|
||
|
header.
|
||
|
|
||
|
Starting with ixemul.library version 42.0 the ssystem() function is no longer
|
||
|
supported. The only two applications use this function are (to my knowledge)
|
||
|
gcc and man. You should either upgrade to the latest gcc (2.7.2 or higher)
|
||
|
or replace gcc by gccv (which is part of older gcc distributions). You can
|
||
|
find a new 'man' version in Geek Gadgets.
|
||
|
|
||
|
Starting with ixemul.library version 43.1 various networking functions have
|
||
|
been moved to libc.a. See the NEWS file for details. It only concerns
|
||
|
certain somewhat specialized functions, so 'normal' clients and daemons
|
||
|
shouldn't be affected.
|
||
|
|
||
|
This library is part of Geek Gadgets. For more information see
|
||
|
ftp.ninemoons.com, /pub/geekgadgets.
|
||
|
|
||
|
|
||
|
|
||
|
INTRODUCTION
|
||
|
============
|
||
|
|
||
|
Originally created in 1991 or 1992 by Markus Wild, the ixemul.library has
|
||
|
become the driving force behind the Geek Gadgets project.
|
||
|
|
||
|
Essentially it is a BSD Unix kernel running under the Amiga OS. The
|
||
|
code for handling Unix signals is taken almost verbatim from the BSD kernel
|
||
|
sources, for example. Multitasking and file I/O is, of course, passed on
|
||
|
to the Amiga OS. Because the library resembles BSD Unix so closely, it has
|
||
|
made it possible to port almost all Unix programs.
|
||
|
|
||
|
However, because of the conformance to BSD, the library is not too
|
||
|
conservative with resources or overly concerned with Amiga standards. For
|
||
|
example, command line expansion uses Unix semantics and doesn't use
|
||
|
ReadArgs(). The purpose of ixemul.library is to emulate Unix as well as is
|
||
|
technically possible. So given a choice between Amiga behavior or Unix
|
||
|
behavior, the last one is chosen.
|
||
|
|
||
|
|
||
|
|
||
|
HISTORY
|
||
|
=======
|
||
|
|
||
|
As I mentioned, the library was originally created by Markus Wild. It
|
||
|
allowed him to port Unix programs, most notably gcc and a Unix shell
|
||
|
(pdksh), which in turn gave him the opportunity to start porting NetBSD
|
||
|
Unix. At some point he stopped working on ixemul.library and continued
|
||
|
with the real thing, NetBSD.
|
||
|
|
||
|
Although Markus made some snapshots of his library available on Internet,
|
||
|
he was about the only one who could actually compile it. The snapshots
|
||
|
where never complete and didn't use a standard Make tool.
|
||
|
|
||
|
Rafael W. Luebbert managed around June 1994 to actually compile the
|
||
|
library using bits and pieces from four different source releases. Even
|
||
|
then he had to write some missing code and had to debug a lot before he got
|
||
|
it working. Luebbert released versions 40.1 through 40.4. Since this was
|
||
|
the only version available that could actually be compiled, Fred Fish
|
||
|
switched to version 40.4 for his FreshFish CDROM series.
|
||
|
|
||
|
Leonard Norrgard also started working on 40.4, fixing a variety of
|
||
|
problems. So for a time there were two versions of the library, both
|
||
|
derived from 40.4. Around March 1995 I began contributing my own fixes for
|
||
|
the library to Fred, including a fix for a horrible memory trashing bug
|
||
|
which substantially improved the stability of the library. Starting with
|
||
|
version 42.0 I became the new maintainer of the library. I merged
|
||
|
Leonard's version of the library into 42.0, the whole source distribution
|
||
|
was cleaned up and reorganized and many bugs were fixed. Also new
|
||
|
functionality was added such as timezone support.
|
||
|
|
||
|
Thanks to Jeff Shepherd the support for network functions has been totally
|
||
|
reorganized for version 43.0. A new ixnet.library was introduced that
|
||
|
contains all the network handling. This new library supports both AS225
|
||
|
and AmiTCP. Furthermore, there is no longer any need to maintain two
|
||
|
versions of an Internet client or daemon as ixnet.library will do the
|
||
|
multiplexing for you. The program itself is completely shielded from the
|
||
|
actual networking package in use. Also, should a new networking package
|
||
|
appear for the Amiga, then it is relatively easy to add support for that
|
||
|
package to ixnet.library. All existing programs will automatically be able
|
||
|
to work with the new package too.
|
||
|
|
||
|
Version 43.0 also introduced support for automatic stack extension
|
||
|
(provided you compiled your program with the -mstackextend flag). This
|
||
|
support was done by Matthias Fleischer.
|
||
|
|
||
|
Last, but not least, I've added the ptrace() function, which was essential
|
||
|
for porting the GNU debugger, GDB. So it is now possible to use a decent
|
||
|
debugger with gcc (and with the GNU C++, fortran and ADA compilers).
|
||
|
|
||
|
Version 43.1 was a bug-fix release, which further improved stability.
|
||
|
|
||
|
Version 44.0 made the library much more (Net)BSD compatible, making it even
|
||
|
easier to port Unix programs. Also many bugs were fixed.
|
||
|
|
||
|
Version 45.0 fixed a few bugs, improved stack extension (see the new ixstack
|
||
|
utility) and further improved Ctrl-C handling by adding 'sessions', something
|
||
|
that was needed for the Geek Gadgets X port.
|
||
|
|
||
|
Version 45.1 was a bug-fix release, and also improved uid/gid handling.
|
||
|
|
||
|
Version 46.0 adds shared memory (shm*) and basic p.OS support.
|
||
|
|
||
|
Version 46.1 renames the __os variable to ix_os.
|
||
|
|
||
|
Version 47.0 completes the p.OS support and adds Unix semaphore and message
|
||
|
support. Also fixes several bugs.
|
||
|
|
||
|
Version 47.1 fixes a minor but very irritating bug in the ixstack utility.
|
||
|
|
||
|
Version 47.2 is a bug-fix release.
|
||
|
|
||
|
Version 47.3 is a bug-fix release.
|
||
|
|
||
|
Version 48.0 is a bug-fix release and removes the p.OS support. p.OS didn't
|
||
|
become a success, so ixemul no longer supports it.
|
||
|
|
||
|
|
||
|
USAGE
|
||
|
=====
|
||
|
|
||
|
The Aminet distribution of ixemul consists of several archives: one for
|
||
|
each flavor (CPU/FPU combination) of the library, one for the timezone
|
||
|
support, an archive for documentation, an archive for various utilities and
|
||
|
an SDK archive, containing headers, libraries and C-objects that provide
|
||
|
the startup code. There is also an ixemul source archive. If you don't
|
||
|
mind recompiling everything, and if you have a decent Geek Gadgets
|
||
|
environment, then all you have to do is retrieve this archive, as all the
|
||
|
other archives are generated from this source distribution.
|
||
|
|
||
|
Besides the library itself, there are also some utilities and other
|
||
|
goodies. First of all, there is a special trace version of the library.
|
||
|
Together with the ixtrace tool it allows you to see which library functions
|
||
|
are called by the program you want to debug. If you compile the library
|
||
|
yourself you will also get, as part of the compile process, a debug version
|
||
|
of the library. If you get an Enforcer hit in the library, and if you have
|
||
|
SegTracker installed, then you can track down in which source and at which
|
||
|
line the hit took place using the gccfindhit tool (available from Aminet
|
||
|
and Geek Gadgets) that is similar to the FindHit tool which is part of the
|
||
|
Enforcer package. I've used this with great success in the past.
|
||
|
|
||
|
Various settings that influence the behavior of the library can be set
|
||
|
using the ixprefs utility. A small tool ixrun allowing you to run AmigaOS
|
||
|
scripts from within the Unix shell is also provided. An ixemul-specific
|
||
|
pipe-handler allows you to set up a pipe between an AmigaOS utility and an
|
||
|
Unix program. A pipe between two Unix programs is handled by the
|
||
|
ixemul.library itself, but since AmigaOS programs are not under the
|
||
|
control of the library, this handler is used instead.
|
||
|
|
||
|
A recent addition is the ixstack tool, which can list and set the minimum
|
||
|
stack size an ixemul program needs. It can also show the actual stack
|
||
|
usage of ixemul programs if you start it with '-s'.
|
||
|
|
||
|
Finally, the tools zic (for manipulating the timezone databases) and
|
||
|
ixtimezone are also part of ixemul. The ixtimezone tool can be used to
|
||
|
automatically adjust the Amiga time based on the currently selected
|
||
|
timezone. The best way to use this tool is to install the timezone
|
||
|
databases (in etc:zoneinfo), set the TZ environment variable correctly (in
|
||
|
my case "Europe/Amsterdam"), add the line "ixtimezone -patch-resource
|
||
|
>nil:" to your user-startup and set the Amiga clock to Greenwich Mean Time
|
||
|
(or Universal Time, as it is now called). Now you will never have to worry
|
||
|
about things like Daylight Saving Time as each time ixtimezone is called,
|
||
|
this tool checks the current timezone and will patch the Amiga clock to the
|
||
|
right time. This tool is also very useful if you also run NetBSD or Linux,
|
||
|
as these OSes expect that the internal Amiga clock adheres to GMT.
|
||
|
|
||
|
I advise that you set the ixemul "Network support" to the correct method
|
||
|
using the ixprefs program. It will improve performance somewhat if ixemul
|
||
|
doesn't have to guess which network library is available, if any.
|
||
|
|
||
|
|
||
|
|
||
|
MEMORY REQUIREMENTS
|
||
|
===================
|
||
|
|
||
|
The library itself needs about 200 Kb, but if you want to do some useful
|
||
|
work, such as compiling programs, I advise at least 4 Mb. More importantly
|
||
|
is the stack size: set it to at least 50 Kb. If you have problems with
|
||
|
certain programs try to increase the stack size.
|
||
|
|
||
|
The reason for these large stacks is that the Unix operating system
|
||
|
automatically extends the stack if it is too small. Therefore some Unix
|
||
|
programs aren't exactly conservative with their stack space.
|
||
|
|
||
|
We can do the same on AmigaOS, however, by compiling programs with the
|
||
|
-mstackextend flag. Or you can set the minimum stack size of a program
|
||
|
using the ixstack tool. If the current stack is too small, the program will
|
||
|
automatically extend the stack on startup.
|
||
|
|
||
|
|
||
|
|
||
|
PROGRAMMING WITH IXEMUL
|
||
|
=======================
|
||
|
|
||
|
There is really very little to do. If you have a decent Geek Gadgets setup
|
||
|
with the necessary compilers and tools, and if you have installed the
|
||
|
ixemul SDK, then you are ready to go. There is no need to do anything
|
||
|
special, the communication between your program and ixemul.library is
|
||
|
handled by the startup code (the *crt0.o files in the /gg/lib directory)
|
||
|
and the standard C library (libc.a, also in /gg/lib) which are
|
||
|
automatically linked with your program. Note that ixemul.library together
|
||
|
with the compile tools also provides profiling support (compile and link
|
||
|
with -pg), and base-relative and resident support (compile with -fbaserel
|
||
|
or -resident). Compile and link with -g to add debug information so that
|
||
|
you can debug your program with gdb.
|
||
|
|
||
|
If you start gdb with the -enforcer option, then the program you are
|
||
|
debugging will automatically stop and drop into the debugger as soon as an
|
||
|
Enforcer hit occurs. This is obviously very useful.
|
||
|
|
||
|
The startup code will automatically expand the command-line for you (e.g.
|
||
|
'echo *' will expand to 'echo <filenames in current directory>'). If you
|
||
|
want to disable this in your program, then you should add the line:
|
||
|
|
||
|
int ix_expand_cmd_line = 0;
|
||
|
|
||
|
to your source. This global variable will tell the system not to expand the
|
||
|
command-line.
|
||
|
|
||
|
Code like you would on a Unix system, so DON'T USE any information
|
||
|
private to the library!
|
||
|
|
||
|
|
||
|
|
||
|
PORTING UNIX PROGRAMS
|
||
|
=====================
|
||
|
|
||
|
Most programs compile out-of-the-box. There are a few exceptions to this
|
||
|
rule. First of all, programs like linkers and the like that have to be
|
||
|
able to read or write the standard Amiga hunk format obviously need a lot
|
||
|
of work.
|
||
|
|
||
|
Secondly, there is no virtual memory support, and therefore no real fork()
|
||
|
function. In most cases the fork() function is only used to spawn a new
|
||
|
program, and in such cases it is possible to replace fork() by vfork(),
|
||
|
which is a light-weight fork() replacement that was originally created for
|
||
|
Unix to reduce the overhead a real fork() introduced.
|
||
|
|
||
|
A vfork() doesn't create a copy of itself as fork() does, but uses the
|
||
|
parent's code and data. Since the child will quickly call execve() to
|
||
|
spawn another program, this sharing of the code and data is no problem and
|
||
|
saves a lot of time.
|
||
|
|
||
|
There is one restriction, however: since the child process is running on
|
||
|
the stack of the parent until an exit() or execve() call the child must be
|
||
|
careful not to clobber the parent's stack. So this will fail:
|
||
|
|
||
|
main()
|
||
|
{
|
||
|
switch (vfork())
|
||
|
{
|
||
|
case -1: // Error
|
||
|
case 0: // Child
|
||
|
return 0; // Return from main()
|
||
|
|
||
|
default: // Parent
|
||
|
wait(0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
It fails because the child just returns, and this return will clobber the
|
||
|
stack for when the parent returns. But this is correct:
|
||
|
|
||
|
main()
|
||
|
{
|
||
|
switch (vfork())
|
||
|
{
|
||
|
case -1: // Error
|
||
|
case 0: // Child
|
||
|
exit(0); // Exit
|
||
|
break;
|
||
|
|
||
|
default: // Parent
|
||
|
wait(0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Here the child calls exit or execve and therefor leaves the underlying
|
||
|
stack intact for the parent. This restriction can cause very hard to find
|
||
|
bugs (I know, I spent quite a few hours researching this problem).
|
||
|
|
||
|
In some cases, such as a Unix shell (pdksh for example), you really want to
|
||
|
be able to port a program that uses a fork() that cannot be replaced with
|
||
|
vfork(). There is a way to do this, although it is a lot of work. First
|
||
|
of all, the program has to be compiled with -resident. Now you replace the
|
||
|
fork() by a ix_vfork() call, and in the child code you call vfork_setup_child()
|
||
|
(new for 44.0! Replaces the ix_resident()/ix_get_vars2() pair) to copy the
|
||
|
original data hunk to a new location. Next you have to copy all the
|
||
|
parent's data structures to the child. In other words, you have to copy
|
||
|
the complete state of the parent process to the child process. This can be
|
||
|
a lot of work. Finally, you call vfork_resume() which unblocks the parent
|
||
|
so that you now have two processes running separately from each other.
|
||
|
|
||
|
It is important to realize that you should never exit() from the parent
|
||
|
before all vfork()'ed children have died. Since exiting from the parent
|
||
|
causes the parents code and data segments to be deallocated, the child
|
||
|
would find itself without code space to run on, and would probably cause a
|
||
|
severe machine crash!
|
||
|
|
||
|
So always call at least `wait(0)' before returning from the parent.
|
||
|
|
||
|
For an example of how this works, see jobs.c from the pdksh source
|
||
|
distribution. It's a kind of poor-man's fork().
|
||
|
|
||
|
The third case I've come across that couldn't easily be ported were
|
||
|
programs that dump their state to a new file. Emacs does this, as does GNU
|
||
|
Common Lisp. The idea is that such a program will read lots of packages,
|
||
|
and then dump itself to a new file. That new file can in turn be executed,
|
||
|
and you will no longer have to load all those packages. All this assumes
|
||
|
that each time you load a program, all the code and data ends up at the same
|
||
|
memory addresses as before. Something that is true for Unix, but not for
|
||
|
the Amiga due to the lack of virtual memory.
|
||
|
|
||
|
However, if someone wants to do a port of such a program, please contact me
|
||
|
as I have developed a technique to implement this. At least, I've made
|
||
|
this work with a small test program. I've tried to use it with GNU Common
|
||
|
Lisp, but time constraints prevented me from developing this further.
|
||
|
|
||
|
The last problematic category I've seen is GNU Emacs. This program assumes
|
||
|
that all the data it allocates will always end up in a continuous memory
|
||
|
block, and that the upper 8 bits of each memory address are always the
|
||
|
same. The Amiga, however, can have multiple memory blocks positioned at
|
||
|
various places in memory. While there is a GNU Emacs port, this port does
|
||
|
assume this limitation and if you have an Amiga with many memory blocks (as
|
||
|
I had) GNU Emacs may easily crash. No easy solution exists.
|
||
|
|
||
|
|
||
|
|
||
|
AMIGA PROGRAMMING & IXEMUL
|
||
|
==========================
|
||
|
|
||
|
If you use Amiga specific resources like Windows and Screens from
|
||
|
Intuition, make sure to add an atexit() handler to close those resources,
|
||
|
if the user should decide to interrupt your program. Before the program is
|
||
|
left, the chain of registered atexit-handlers is called in exit(). So
|
||
|
PLEASE NEVER EVER call _exit() if you have registered any custom atexit()
|
||
|
handlers. It is a bad habit anyway, but normally you may call _exit()
|
||
|
without resource lossage (stdio won't flush its buffers, but that's about
|
||
|
all).
|
||
|
|
||
|
Ixemul provides a new unique Amiga specific signal called SIGMSG. If you
|
||
|
set up a handler for this signal, then the default mapping from
|
||
|
SIGBREAKB_CTRL_C into SIGINT will no longer occur, and your handler is
|
||
|
called with the following arguments:
|
||
|
|
||
|
signal_handler(SIGMSG, new_exec_signal_mask)
|
||
|
|
||
|
In this case, you have to deal with Exec signals yourself, so don't forget
|
||
|
to clear those signals that you want to receive notification about again
|
||
|
later. Thus if you'd want to handle SIGBREAKB_CTRL_C yourself, don't
|
||
|
forget to
|
||
|
|
||
|
SetSignal(0, SIGBREAKF_CTRL_C)
|
||
|
|
||
|
at the end of the handler, or you'll never get notification about that
|
||
|
signal again.
|
||
|
|
||
|
Most of the original BSD signals are implemented. SIGSTOP is currently not
|
||
|
implemented, although it would be relatively easy to add. The mechanisms
|
||
|
are already in place.
|
||
|
|
||
|
|
||
|
|
||
|
HANDLING OF UID/GID IN IXEMUL.LIBRARY
|
||
|
=====================================
|
||
|
|
||
|
The following information was provided by Norbert Pueschel:
|
||
|
|
||
|
Here is a list of functions that are concerned with uid/gid management
|
||
|
and access to user/group information:
|
||
|
|
||
|
a) uid/gid management:
|
||
|
get(e)uid, set((r)e)uid, get(e)gid, set((r)e)gid, (init|set|get)groups
|
||
|
|
||
|
b) access to user/group informations:
|
||
|
set(pass|group)ent, (set|get|end)pwent, get(pw|gr)nam, getpwuid, getgrgid,
|
||
|
(_)getlogin, setlogin
|
||
|
|
||
|
c) other functions:
|
||
|
setsid, crypt
|
||
|
|
||
|
|
||
|
Ixemul.library has several options how to implement these functions:
|
||
|
|
||
|
1) When MultiUser is installed, ixemul.library will use it to implement the
|
||
|
functions named above.
|
||
|
|
||
|
2) When MultiUser is _not_ installed, ixemul.library will use its own
|
||
|
uid/gid handling: uids and gids will be inherited by child processes
|
||
|
and files and directories created by ixemul using programs will have
|
||
|
the current user and group set as long as the filesystem supports that.
|
||
|
However, for file accesses only the setting of the flags for the file
|
||
|
owner is used (as for any other AmigaOS program).
|
||
|
|
||
|
Processes that are not started by other ixemul using programs use
|
||
|
environment variables to determine their (e)uid and (e)gid:
|
||
|
|
||
|
They will first check the variables LOGNAME and USER for a valid user
|
||
|
name. If they find this user in the passwd file, they will set up (e)uid
|
||
|
and (e)gid respectively. Then the environment variables UID, EUID, GID and
|
||
|
EGID will be queried, and, if present, their values will be used.
|
||
|
|
||
|
If none of the above variables is found, the process will be owned by
|
||
|
nobody/nogroup (uid/gid -2).
|
||
|
|
||
|
|
||
|
Ixemul.library has three different methods to get user/group
|
||
|
informations:
|
||
|
|
||
|
a) If networking software (AmiTCP or Inet) is installed, it will use their
|
||
|
user/group databases.
|
||
|
|
||
|
b) If no networking is available, it will try to read the files etc:passwd
|
||
|
and etc:group.
|
||
|
|
||
|
c) If both a) and b) fails, it will use a builtin user/group database.
|
||
|
This database only knows the nobody/nogroup (uid/gid -2), root/wheel
|
||
|
(uid/gid 0) and a user/group combination described by the environment
|
||
|
variables LOGNAME or USER, GROUP, UID and GID.
|
||
|
|
||
|
Hans Verkuil (hans@wyst.hobby.nl, July 14, 1998)
|
||
|
|
||
|
(Parts of this README are from the original README by Markus Wild).
|