home *** CD-ROM | disk | FTP | other *** search
- Unix compatibility library for SAS/C 6.55+
- ------------------------------------------
-
- Note: this is an edited version of the original doc written by David Gay
- to reflect the changes I introduced.
-
- Introduction
- ------------
-
- This library provides 110+ odd functions which are useful for porting
- Unix programs to the Amiga running AmigaDOS 2.04 or higher. It is thus
- similar to ixemul.library, but has more restricted aims:
-
- a) It is written specifically for SAS/C 6.55+.
-
- b) It isn't a complete C library, it requires the SAS/C library to function.
- It adds some routines, and replaces others that were deficient, out of date,
- or that didn't provide adequate functionality.
-
- c) It isn't a complete Unix emulation library, it only contains those functions
- that I needed while porting various utilities (mainly from GNU) to the Amiga.
-
- d) It is a traditional C link library, not an Amiga library. This produces
- bigger executables.
-
- Considering the above points, you might ask why David wrote it ...
- There are several good answers:
-
- a) He started it before he was aware of ixemul.library.
-
- b) ixemul.library didn't provide the features he needed for Emacs (support for
- select).
-
- c) It was easier for him to maintain when he found the need to support another
- Unix feature (eg deleting open files).
-
- As regard me, I updated it to SAS/C 6.55+ and added other improvements to
- be able to port X11 programs to AmiWin.
-
- Copying
- -------
-
- The library includes code that David (and I) have written, which he (and I)
- place in the public domain. This is found in all the files that don't have a
- Copyright notice.
-
- It also includes code which is (inclusive of my modifications)
-
- Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
- All rights reserved.
-
- This code is freely redistributable (see the copyright notices in the source
- and include files).
-
- Finally it includes Stefan Proels's public domain alloca implementation
- specifically written for SAS/C 6.55+.
-
- Installation & Use
- ------------------
-
- To use this library, you must compile with the include directory in your
- include search path, and link with the unix.lib library (which must be
- specified before sc.lib). For example, if you extract this archive in a
- directory called src: and assign uinclude: to src:unix/include and
- ulib: to src:unix, you could compile the following program:
-
- echo.c:
-
- #include <string.h>
- #include <unistd.h>
-
- int main(int argc, char **argv)
- {
- int i;
-
- for (i = 1; i < argc; i++) {
- if (i != 1) write(1, " ", 1);
- write(1, argv[i], strlen(argv[i]));
- }
- write(1, "\n", 1);
- return 0;
- }
-
- with the command
-
- sc link idir=uinclude: lib=ulib:unix.lib echo.c
-
- to produce a simple unix-like echo command.
-
- Among other improvements, I added support for sockets code, relying for this
- on AmiTCP's bsdsocket.library. If you need compiling code containing socket
- calls, than you should have AmiTCP, its include files in netinclude: and
-
- 1) compile with AMITCP defined (DEF=AMITCP)
- 2) add netinclude: AFTER uinclude: in the include search path
- 3) have an #include <proto/socket.h> in your code
-
- So the command to compile prog.c (containing socket calls) should be like
-
- sc link DEF=AMITCP idir=uinclude: idir=netinclude: lib=ulib:unix.lib prog.c
-
- Of course, for compiling code containing socket calls, you could instead use
- net.lib, the link library distributed with AmiTCP, but it lacks support for
- pipes, i.e. the pipe() call. This unix.lib does not have the complete
- functionality of net.lib as regard socket code support but I think it is
- sufficient for compiling the vast majority of programs using network sockets.
-
- You should define the following environment variables:
-
- USER - A user name for the sole Amiga user (default "user").
- USERNAME - The full name of the sole Amiga user (default $USER).
- HOME - A "home" directory (default "s:") for programs that want one.
- Configuration files will probably end up here ...
- SHELL - A program which behaves reasonably like a Unix shell
- (default "bin:sh"). You should copy the sh executable there if
- you don't have a Unix-like shell.
- HOSTNAME - The name of your machine (default "amiga").
-
- If you are going to be using pipes, you will require Matt Dillon's fifo.library
- and fifo: device. This can be found on the Fish disks, with his UUCP
- distribution and on any Aminet site.
-
- If you use the popen() and pclose() calls you also need the APipe-Handler.
- Again you can find it on any Aminet site.
-
- If you want to install the timezone information (see the discussion below on
- Unix vs Amiga time), do the following:
-
- a) change to the zoneinfo directory
- b) compile the zic program by running smake.
- c) change to the datfiles directory.
- d) edit smakefile and choose your timezone (you can look at the data files
- to see the ones available). If you get this wrong, you can always change
- it later with the zic program.
- e) type 'smake install'. This will compile the timezones, and setup the one
- you chose as the default. The default can be changed with
- zic -l <timezone name>
-
- or by defining the environment variable TZ.
-
- Functionality
- -------------
-
- While this library aims to hide the differences between AmigaDOS & Unix,
- it also aims to provide support for Amiga specific features. This sometimes
- produces strange compromises.
-
- This library provides two things to programs linked with it:
-
- a) A Unix-like environment:
-
- This includes:
-
- - Unix-like command line parsing, with wildcard expansion. These
- wildcards are however specified with the Amiga syntax.
-
- Arguments which are unquoted or surround with single quotes are
- handled like Unix shells. Those surrounded with double quotes are
- handled in the Amiga fashion, but with wildcard expansion (this is
- done to avoid problems with the way the exec function works).
-
- Here is a summary of argument splitting:
-
- Arguments can be enclosed in single quotes, (') double quotes ("), or
- separated by spaces.
-
- Arguments enclosed by single quotes never suffer wildcard expansion, and
- no character is significant inside them (not even \). Given the echo program
- given above,
-
- echo 'f*un\'
-
- simply displays
-
- f*un\
-
- Within double quotes, * is the standard Amiga escape character. \ is
- handled just like any other character. Wildcards are expanded. So,
- assuming the current directory contains only echo.c and echo,
-
- echo "#?.c" "*.c" "\mad"
-
- displays
-
- echo.c .c \mad
-
- (* escapes the following character, except that *N is newline and *E is
- escape. Wildcard characters still behave as usual (' is the standard
- Amiga wildcard escape character)).
-
- If an argument is unquoted, \ acts as an escape character (removing
- special significance from the next character, be it a wildcard, a space,
- a \, ...). So
-
- echo \*.c \\ \n
-
- displays
-
- *.c \ n
-
- - When a program is run from the Workbench, stdin, stdout & stderr are
- opened on NIL:, and the icons selected are converted to file names and
- passed as the argc,argv to main.
-
- - The standard variable environ is defined and contains all the local
- environment variables. This is passed as the envp parameter to main.
-
- - The program is led to believe that all files belong to $USER (uid 1),
- group wheel (gid 0).
-
- - Amiga protection flags are mapped onto the standard 12 Unix protection
- bits (and back when necessary). This can be overridden (dynamically) by
- changing the value of use_amiga_flags. Eg:
-
- extern int use_amiga_flags;
-
- ...
-
-
- main()
- {
- use_amiga_flags = 1;
-
- ... some code using stat or chmod or ...
- }
-
- In this case, the Amiga protection bits are left untouched. Otherwise the
- mapping is as follows (note that the archive bit is lost):
-
- Unix -> Amiga
-
- Amiga read: if user, group or world read.
- Amiga write: if user or group write.
- Amiga delete: if user or world write.
- Amiga execute: if group execute or only user execute.
- Amiga script: if world execute or only user execute.
- Amiga pure: if sticky.
-
- Amiga -> Unix
-
- user, group, world read: if amiga read.
- user write: if amiga write and delete.
- group write: if amiga write.
- world write: if amiga delete.
- user execute: if amiga execute or amiga script.
- group execute: if amiga execute.
- world execute: if amiga script.
- sticky: if amiga pure.
-
- - Unix-like time. time is expressed in seconds since 1-Jan-1970 00:00 GMT.
- This is the format used by the time(), stat() and utime() functions. The
- library uses the BSD time functions which properly handle timezones,
- daylight savings time, etc.
-
- On Unix systems, time is generally stored as GMT, while the Amiga stores
- local time. These times are visible in two places: the time stored in the
- system clock and the creation, modification or access dates for files
- (only the modification date is available on the Amiga). There are 3 ways
- to resolve this conflict:
-
- 1) Ignore timezones (you can choose this option by not installing the
- timezone information). The library will then assume that system time
- and file times are expressed in GMT and will never apply any
- corrections. All will work well (except maybe on a global network).
- This is the simplest solution.
-
- 2) System & file time are assumed to be local times. The time() & stat()
- functions convert local time to GMT, the utime() call converts GMT to
- local time. This allows you to keep the system clock on local time,
- which is compatible with most (all?) Amiga applications. However,
- nearly every program will be bigger because they will need the timezone
- information and timezone conversion code (approximately 7k). The
- library can be recompiled if you prefer to have things this way by
- adding `DEF USE_LOCAL=1' to the DEFS variable in smakefile.
-
- 3) System & file time are stored in GMT. Times are converted to local time
- only when they are displayed to the user, who must of course choose the
- correct timezone. This entails changing your system clock to GMT, which
- means that most programs will display an incorrect time. However, you
- won't have to change your system clock when daylight savings time ends.
- The library comes compiled this way (But you can still choose option 1,
- no timezone information, and avoid the potential confusion).
-
- - BSD-like signals. Signal handlers stay enabled after a signal occurs
- (that particular signal is simply masked for the duration of the handler).
- setjmp & longjmp preserve the signal mask (the functions _setjmp & _longjmp
- don't). You may receive any signal with kill(getpid(), sig). Otherwise only
- the following occur:
-
- SIGINT: user typed ctrl-c
- SIGQUIT: user typed ctrl-d
- SIGALRM: alarm() expired
- SIGCHLD: a child process died
- SIGIO: asynhronous I/O is pending | these can be triggered only by
- SIGURG: urgent data is pending | bsdsocket.library
-
- When using kill to signal another process, only SIGHUP, SIGINT, SIGQUIT &
- SIGKILL do anything. They all send SIGBREAKF_CTRL_C | D to the process (and
- hopefully its children). See the discussion under the exec function.
-
-
- b) A large number of unix C library calls:
-
-
- _exit, _setjmp, _longjmp, abort, alarm, access, alloca, bcmp, bcopy, bzero,
- chmod, chown, fchown, close, creat, dup, dup2, fnmatch, getopt, tzset,
- tzsetwall, gettimeofday, ftime, localtime, gmtime, asctime, ctime, mktime,
- endgrent, endpwent, getgrent, setgid, setegid, setgroupent, setgrent,
- setuid, seteuid, opendir, closedir, readdir, telldir, seekdir, fchmod,
- fcntl, fstat, ftruncate, getenv, setenv, gethostname, getpid, getwd, getgid,
- getegid, getgrgid, getgrnam, hypot, index, ioctl, isatty, kill, link, lseek,
- lstat, mkdir, mkfifo, mknod, mktemp, open, perror, pipe, socketpair,
- getpwuid, getpwnam, getlogin, popen, pclose, read, readlink, regerror,
- regcomp, regexec, regsub, remove, rename, rindex, rmdir, select, setjmp,
- longjmp, signal, sigpause, sigprocmask, sigsetmask, sleep, stat, strcasecmp,
- strncasecmp, strerror, strftime, symlink, tempnam, time, truncate, getuid,
- geteuid, umask, unlink, utime, wait, waitpid, wait3, wait4, write
-
- These functions aim to be BSD compatible, however I based myself on
- descriptions in the SunOS 4 man pages. Their behaviour is sometimes strange
- or incomplete.
-
- Here is a summary of the differences with the standard Unix functions:
-
- alloca - This is Stefan Proels's alloca for SAS/C. It is implemented taking
- advantage of the compiler's PROFILEing facility. If you compile
- with the PROFILE switch turned on the compiler calls _PROLOG()
- whenever a function is entered and _EPILOG() when the function
- returns respectively. Refer to your SAS/C manuals for details.
- This alloca() implementation uses those hooks to track alloca()ted
- memory. Whenever a function returns all memory alloca()ted by that
- function will be freed. Remember to compile with the PROFILE switch
- the modules using alloca() if you want a working alloca(). If you
- include alloca.h (which you have to do if you want its prototype)
- you will be remembered of this ...
-
- gettimeofday - The dst field of the timezone is a (not very good) guess. It
- shouldn't be used anyway.
-
- chown, fchown - These are do-nothing routines.
-
- opendir, closedir, ... - These interact with stat to avoid having to read
- each directory entry twice when doing a readdir + stat loop.
-
- fchmod - The protection is only set when the file is closed. See also the
- discussion of protection modes above.
-
- fcntl - Only the F_GETFL & F_SETFL operations are supported.
-
- truncate, ftruncate - These will not necessarily work with all filing
- systems. See the discussion of the AmigaDOS SetFileSize function.
-
- getenv - This checks local environment variables and then global ones. It
- allocates memory for the variables value each time. This memory is
- never freed (till the program exits).
-
- gethostname - This is obtained from the HOSTNAME environment variable at
- startup.
-
- getuid, geteuid, getgid, getegid, getpwuid, getpwnam, getgrgid, getgrnam,
- getlogin - These function only know about one user. He/She is:
-
- name: $USER (default "user")
- home directory: $HOME (default "s:")
- shell: $SHELL (default "bin:sh")
- uid: 1, gid: 0
-
- ioctl - Only FIONBIO & TIOCGWINSZ are known (for sockets all those
- recognized by AmiTCP), plus a number of amiga specific ioctls
- (for internal use). These are documented in include/amiga/ioctl.h.
-
- lseek - Seeks beyond the end of a file are not implemented.
-
- mkfifo, mknod - These are 'do-nothing' routines.
-
- select - This implementation cannot detect 'exceptional' conditions
- with pipes & sktpairs. By default FD_SETSIZE is 64. If you need
- a large value you must #define FD_SETSIZE before including
- <sys/types.h> and, if you use sockets, also set the external
- variable _fd_setsize to the same value, e.g.:
- #define FD_SETSIZE 128
- #include <sys/types.h>
- long _fd_setsize = FD_SETSIZE; /* only needed for sockets */
-
- umask - This is a 'do-nothing' routine.
-
- unlink - You can unlink a file that your program has opened before you close
- it. At that point, the AmigaDOS file is closed & deleted, though it
- still appears open to read (it returns EOF), write, close, etc.
- Also you can unlink a file even if it is protected from deletion
- (the protection mode is changed first ...).
-
- utime - Only the modification time can be changed (the others don't exist).
-
- wait3, wait4 - Resource usage is never returned.
-
- Recompiling
- -----------
-
- To recompile, simply run smake in the src directory. You can add DEF=USE_LOCAL
- to DEFS in smakefile if you want the system clock to store local time
- instead of GMT.
-
-