gcc
or write simple Makefiles
you have to learn your lessons first!
This FAQ is not a "Beginners Guide to un*x/programming", though
I address several topics from such an introduction.
Since it may be rather hard to actually detect something helpful in this document, so you should remember that the FIND function of your browser/viewer is your friend: Since quite a lot interfaces and packages are covered here, just look for a keyword and hope there's already a helpful comment on it! Some parts have meanwhile been put in external documents with "local linkage"; official "compiled" versions (PDF currently) may include those for your convenience.
In case you may want to correct an error, contribute another entry or "just" correct spelling/grammar, please check first the primary location of this FAQ for the latest revision. You may send me emails with corrections, enhancements and criticism!
Note that usage of the tips & procedures described here is totally on your own risk, there is no warranty that they do what one might expect without any (unwanted) side effects!
Work is ongoing to get many of the hints and workarounds mentioned here into a real powerful extension library for EMX. Take a look and see what's already done! Especially try to look up whether symbols missing in this FAQ are already included in libExt.
There is a PDF version of this document available. From the PDF format you can easily get a fine printout. Using appropriate tools you can also search in it and extract a plain text version. (Check out pdftotext, which is part of the xpdf distribution for that purpose!)
0
or the appropriate return code upon error
relies on the concept that the source was written properly and to some
extent handles failures of these APIs properly.
#define chdir _chdir2 /* see below */ #define chown(x,y,z) (0) #define endgrent() /* is type void */ #define FNDELAY O_NONBLOCK #define getcwd _getcwd2 /* see below */ #define getdtablesize () (1024) #define getgrent() ((group*)NULL) #define link(x, y) (-1) /* no hard links */ #define lstat stat /* no soft links */ #define major(dev) (0) /* doesn't make sense on OS/2 */ #define makedev(dev,minr) (0) /* doesn't make sense on OS/2 */ #define minor(dev) (0) /* doesn't make sense on OS/2 */ #define mkfifo(p,m) (0) /* see below for mkfifo() */ #define mknod(p,m,d) (0) #define mlock (-1) /* see below */ #define munlock (-1) /* see below */ #define munlockall (-1) /* see below */ #define readlink(x,y,z) (0) /* or a negative value and use errno? */ #define readlink(s,t,l) (strcpy(t,s),strlen(t)) #define setgrent() /* is type void */ #define setpgrp() (0) /* ? */ #define sigset(x,y) signal(x,y) /* well, almost ... */ #define strcasecmp stricmp /* see libExt */ #define strncasecmp strnicmp /* see libExt */ #define symlink(x,y) (-1) #define sync() /* check out fsync(), etc. */ #define S_ISLNK(x) (0) #define S_IFLNK (0) #define S_ISBLK(x) (0) #define S_IFBLK (0) #define S_ISVTX (0) #define usleep(t) _sleep2(((t)+500)/ 1000) /* see below */
ecvt()
, fcvt()
, gcvt()
*printf()
or even attempt writing your
own version. Shouldn't be too hard ...
errno
errno
is nothing un*x-specific, but an integral
part of ANSI/ISO C's error handling. The catch here is that
some programmers erroneously #define errno
to
something like int
or abuse it as a name for
an identifier.
errno
is an important thumb-rule:
always compile and link your EMX apps as multi-threaded
applications (gcc flag -Zmt
). This will avoid
much trouble.
exec*()
fork()
and the section about process handling.
exec*()
with spawn*()
and exit()
if the parent process waits for the termination of the new process
(by calling wait()
or by waiting for SIGCLD
).
This is required to keep the process ID of the child process.
In a forked process, however, you don't have to do this because emx.dll
does it for you.
fchmod()
fcntl()
F_SETLK
is not supported.
fcntl()
or add code which makes use of an existing
flock*()
implementation. Or watch
libext.
flock()
DosSetFileLocks()
.
Also see libext.
fork()
exec*()
and the section about
process handling.
fork()
and
exec*()
with spawn*()
.
Under OS/2, fork()
is inefficient. You may not care if it's
rarely being called, but read the docs for any specific
information about the fork()
implementation.
getenv()
getrlimit()
ulimit(3)
, sysconf(3)
,
emxdev: chapter "7 Customizing"
mlock()
, munlock()
, munlockall()
DevHlp()
interfaces (API for device drivers)
provide such calls, to mark memory pages as non-swappable.
However this is no trivial replacement which could be implemented
by inserting a few lines of code.
poll()
select()
.
Check out
libExt for an emulation using this relationship.
popen()
system()
rename()
rename()
doesn't replace existing targets.
remove()
)
remove()
remove()
fails on open files.
select()
select()
is a common source of portability problems.
These may involve: the necessary header files, argument types
or some "EMXisms", like the following:
select()
will report that stdin
is
"ready", i.e. will return immediately. If you want to trigger on
any new input, i.e. keystrokes, you have to change the terminal
settings. A small snippet should give you the idea:
#include <sys/types.h> #include <stdio.h> #include <termio.h> #include <termios.h> #include <sys/time.h> #include <sys/select.h> ... fd_set rfds; struct timeval tv; int retval; struct termios tio; ... /* Watch stdin to see when it has input. */ FD_ZERO(&rfds); FD_SET(fileno(stdin), &rfds); /* Now change EMX' default settings */ tcgetattr(fileno(stdin), &tio); tio.c_lflag &= ~IDEFAULT; tcsetattr(fileno(stdin), TCSANOW, &tio); /* Wait up to five seconds. */ tv.tv_sec = 5; tv.tv_usec = 0; retval = select(1, &rfds, NULL, NULL, &tv); if (retval > 0) { /* FD_ISSET(0, &rfds) will be true here */ printf("Data is available now.\n"); }
sigaction()
signal()
).
Especially check if you need to link with
-Zbsd-signals
while XFree86 OS/2 (imake; perhaps
the docs mention it as well) tends
to use -Zsysv-signals
!
sigaction()
and
signal()
are used together.
signal()
signal()
:
SIG_ACK
should be used instead of the
signal handler address to re-enable a signal by calling
signal()
when the signal handler has been called.
This behaviour can be changed with the -Zbsd-signals
and -Zsysv-signals
options of gcc.
If you use POSIX.1 functions for signal handling, SIG_ACK
is not required.
SIGNAL name | Short Explanation | Reference | Comments |
---|---|---|---|
SIGABRT | Process abort signal | B |
e.g. by abort()
|
SIGALRM | Alarm clock | E | |
SIGBREAK | CTRL-BREAK by user | B | OS/2 only |
SIGBUS | Bus error | E | |
SIGCHLD (SIGCLD) | Child process stopped/terminated | E | |
SIGCONT | Continue if stopped | - | |
SIGDANGER | Danger signal | - | |
SIGEMT | ? | E | |
SIGFPE | Floating point exception | B | |
SIGHUP | Hangup | E | |
SIGILL | Illegal instruction | B | |
SIGINFO | Information request | - | |
SIGINT | Interrupt from terminal | B | |
SIGIO | IO now possible | - | (4.2 BSD) |
SIGIOT | IOT trap | - | |
SIGRANT | Monitor mode granted | - | |
SIGKILL | Kill process | E | cannot be be caught or ignored |
SIGLOST | Resource lost | - | |
SIGLWP | ? | - | |
SIGMSG | Monitor mode data available | - | |
SIGNOFP | Floating point co-processor not available | - | |
SIGPHONE | ? | - | |
SIGPIPE | Broken pipe | E | write to pipe w/o reading process |
SIGPOLL | I/O possible | - | |
SIGPROF | Profiling timer expired | - | |
SIGPWR | Power failure | - | |
SIGQUIT | Quit from terminal | E | |
SIGRETRACT | Need to relinguish monitor mode | - | |
SIGSEGV | Segmentation fault | B | |
SIGSOUND | Sound completed | - | |
SIGSTKFLTT | Stack fault on coprocessor | - | (linux) |
SIGSTOP | Stop process | - | |
SIGSYS | Illegal system call | E | |
SIGTERM | Termination | B | |
SIGTRAP | Breakpoint/tracepoint trap | E | (see "hardcoded breakpoint") |
SIGTSTP | Stop typed at tty | - | |
SIGTTIN | tty input for background process | - | |
SIGTTOU | tty output for background process | - | |
SIGUNUSED | Unused signal | - | a very important one ;-) |
SIGURG | Urgent I/O condition | - | |
SIGUSR1 | User defined signal #1 | B | |
SIGUSR2 | User defined signal #2 | B | |
SIGUSR3 | User defined signal #3 | I | EMX seems to miss this!? |
SIGVTALRM | Virtual timer expired | - | |
SIGWINCH | Window resize | E | see termsize lib |
SIGWIND | ? | - | |
SIGXCPU | CPU time limit exceeded | - | |
SIGXFSZ | File size limit exceeded | - |
system()
system()
may be
passed to cmd.exe
which might not be able to handle them!
system()
and
popen()
do not expand wildcards unless COMSPEC
/EMXSHELL
points to a shell which expands wildcards (of course on un*x those calls
wouldn't do either - but the shell being called).
Check out the EMX docs to learn which shell is called by these
routines! One may run across code like
system("foo&");
which would try to launch
a job in the background with an un*x shell but this
won't work with cmd.exe
!
unlink()
remove()
instead.
usleep()
_sleep2()
) doesn't feature
a microsecond resolution; but contrary to its name many implementations on un*x
won't do either. More info on timers on OS/2 is available on
EDM/2.
Also see info about g/setitimer().
select()
(see according entry in this FAQ). You have to specify no descriptors to
monitor but only a timeout. Check out the docs which resolution
actually is provided here and about properties of this call
in general (e.g. the effect of signals beign raised).
#include <sys/types.h> #include <sys/time.h> #include <sys/select.h> struct timeval tv; long secs, microsecs; /* set secondss and microseconds of the interval */ tv.tv_sec = secs; tv.tv_usec = microsecs; /* tell select() to monitor no file descriptors */ select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, &tv);
#define foo bar
dlopen()
/dlfcn()
(access to dynamic link libraries)
drand48()
, srand48()
(random numbers)
gettext()
(National Language Support library from GNU)
mmap()
, munmap()
, etc. (mapping files into memory)
mkfifo(3)
(a named-pipe mechanism using the file system)
Octave
(on Hobbes, LEO)
pthreads
(POSIX threads)
(on Hobbes, LEO)
readline
(provides simple editing features in an input line on terminals)
regex
(regular expressions)
(on Hobbes, LEO;
also part of
libext)
rpc
(Remote Procedure Call) interfaces are supplied
with libExt.
scandir()
Part of libExt
setitimer()
/getitimer()
(timer functions)
open()
/read()
interface should
make timing easy and enable writing an itimer compatible interface.
Also you may read this
EDM/2 article.
setpriority()
,
getpriority()
shm
(shared memory between different processes):
shmat()
, shmctl()
,shmdt()
,
shmget()
syslog()
(send messages to system logger)
system()
,
exec*()
,
etc. which are available on OS/2 EMX (also see
fork()
).
The term threads has no unique meaning in the un*x world as opposed
to OS/2. Those un*x systems which had already offered something similar
to the OS/2 threads concept often developed their own standard for this.
pthreads (POSIX threads) is now a kind of standard. A wrapper from this API
set to OS/2 exists
(see Hobbes).
For the purposes similar to those of multi-threading often processes
started via
fork()
are being used.
When
fork()
/
exec*()
is used to start a subprocess
often communication between the parent and child process is done.
The most simple way is to redirect stdin/stdout/stderr using
pipes (created by pipe()
). If you migrate the code from
fork()
/
exec*()
to spawn*()
you have to change this code slightly as well: in the former case pipes are
created, then the child process switches it's std* to the according
ends of the previously created pipes before calling
exec*()
.
The parent just closes the unused ends of the pipes and
keeps those required to communicate with the child.
Using spawn*()
you don't have explicit access to the child,
but it inherits the pipes/handles given from it's parent.
So you have to redirect std* of the whole process to the
pipes, start the child and fixup std* again:
dup()
)
dup2()
)
spawn*()
)
dup2()
) and close()
unused file handles
Watch out for open file (socket, ...) handles being passed to
subprocesses: e.g. open file handles passed to a spawned child
may prevent the parent from removing that file later in the
future. See fcloseall()
and
fcntl()
(-> FD_CLOEXEC
flag)
DosQuery*Info
will succeed on calls for files
in a case-insensitive matching! More useful is DosFindFirst
and it's friends (see Toolkit docs for sample code)
man hier
on your favourite un*x system
to get a description of the file system hierarchy being used.
In the following overview I may also mention some which are not mandatory,
while trying to have all the canonical ones included.
foo.2
)
ln
is sometimes required by
scripts. Using a replacement which does actually copy
and also echoes a warning might be a good, but sometimes
"dangerous" idea.
cmd.exe
and most apps do not.
_fullpath()
and _abspath()
)
#define getcwd _getcwd2 #define chdir _chdir2may help to support drive letters.
///abc
is a valid un*x filename.
It's equivalent to /abc
. In general multiple
'/' slash characters won't hurt, unlike the situation on
OS/2.
chdir ("..")
is a no-op under un*x
if the current working directory is the root directory.
Under EMX it fails in the root directory.
lib
prefix, like
libfoo.a
. If you want to link against it however,
the right command is -lfoo
.
On EMX unfortunately this prefix has been dropped,
i.e. -lfoo
links against foo.a
instead.
.so
on most
un*x systems (alternatives include .sl
).
There's no need for an import library usually.
On un*x/ELF systems shared/dynamic libraries may contain unresolved references,
on OS/2 they at least carry a 'link' to the DLL which contains those. This has
both advantages and disadvantages. A nice example for an advantage is
if you want to access symbols from a dynamic library (using
dlopen()):
on OS/2 you will be able to call such a routine in any case,
on un*x/ELF you might end up with unresolved symbols!
cmd.exe
, i.e. you can only
execute files with the endings
.com
, .exe
, .cmd
, .bat
(this is the exact search order!).
Note that most of this trouble is bound to cmd.exe
and all APIs which may (or may not, see docs) interface with it
(including popen() and system())
stdin
/stdout
.
_fsetmode()
, fopen()
, ... in the
EMX docs
Operating systems | line delimiters (hex) | |
---|---|---|
DOS, OS/2 |
0D 0A
| |
un*x, VMS(?) |
0A
| |
Macintosh |
0D
|
*
?
cmd.exe
won't do it for you. However be aware that even people
on OS/2 may use shells which already expand (4os2? or an un*xish shell).
Note that this shouldn't hurt at first glance, but may end up with a
substantial number of commandline arguments passed to your application!
#include <stdlib.h> int main (int argc, char *argv[]) { _wildcard (&argc, &argv); /* ... the program ... */ }See EMX docs for details on
_wildcard()
and
_response()
getenv()
calls always to return a non-NULL result.
Changing this is a valuable bugfix, not a porting related change!
:q!
/tmp
. On OS/2 unfortunately one sometimes
runs across TEMP
, TEMPDIR
and other garbage.
test
!
test
is a standard program on un*x,
which does apparently nothing - at least if you don't have a closer look
at it ...
cmd.exe
) commands
find
, install
, more
,
patch
, sort
, unpack
cmd.exe
) commands
cd
, date
, dir
, echo
,
mkdir
, rmdir
ld -X -r -o darin.o foo1.o foo2.o ...
lpr
and lpd
tools
(shipped with Warp 4) to access the Postscript printer queues from the
commandline.
/dev/audio
emulation available from
Hobbes and LEO (devaudio*.zip).
Given this version one might imagine to have the current implementation
enhanced by additional features.
from 5.1 Porting Unix applications
exec*()
and
spawn*()
.
(Note that a process created by
fork()
inherits the socket handles of its parent process.) Inheriting socket
handles is planned for a future release of emx.
setmode()
to switch to text mode.
Text mode applies to read()
and write()
,
only. recv()
and send()
always use binary mode.
recvmsg()
, sendmsg()
, and
socketpair()
are not implemented.
from 5 Hints for porting Unix programs to emx
open()
, fopen()
, fdopen()
and freopen()
calls to use O_BINARY
or
"b"
, respectively, for binary files.
If a file contains both binary and textual data, read the file in binary mode
and do the conversion yourself.
fseek()
and ftell()
now work on text files,
the offsets are different from what Unix programs expect. You may have to
open the files in binary mode and ignore carriage returns (this has been done
in GDB
).
_seek_hdr()
or _fseek_hdr()
before reading the
header to support .exe files. More changes are usually required.
/dev/null
under Unix.
The __open()
system call translates the filenames
/dev/null
and /dev/tty
(lower case, with slashes) to nul
and con
,
respectively. However,
system ("whatever >/dev/null");won't work as the standard OS/2 interpreter (
cmd.exe
)
doesn't recognize "/dev/null
"
(see system()
)
PTRACE_TRACEME
request of ptrace()
:
use P_DEBUG
instead when starting the process with
spawn*()
.
/bin/sh
.
Use system()
.
setvbuf (stdout, NULL, _IOLBF, BUFSIZ);and to use
fflush(stdout);
if you need the output immediately
(flushing is required only after displaying prompting texts before
reading input or displaying progress reports that don't end with a
newline character). GDB
output has been made much faster
by using line buffering.
VEOF
!= VMIN
and
VEOL
!= VTIME
.
Programs which use VEOF
and VEOL
to access
VMIN
and VTIME
, respectively, should be changed
to use VMIN
and VTIME
.
emx uses separate fields for VEOF
, VEOL
,
VMIN
and VTIME
.
IDEFAULT
bit of
c_lflag
. This does not apply to termios.
termios
in new code!
_read_kbd()
if you don't want to get input line by line.
_read_kbd()
! This breaks your code in
xterms and in addition it is non-portable!
#define
s are in effect
you can use the example batch script below.
Note that it requires 2 un*x utils (touch
, rm
),
but you may easily replace them by OS/2 native calls. Advantage of the
given version is obviously that you can use it almost literally on many
un*x systems! (and it can handle a big number of additional commandline
arguments like compiler flags: "-ansi" is a candidate here)
touch __shd.c gcc -dM -E %1 %2 %3 %4 %5 %6 %7 %8 %9 __shd.c rm __shd.c
libm
) is often specified in
Makefiles among the linker flags. On EMX you don't need this (the functions
are already among the standard C libs). But to keep the linker
happy with those Makefiles a dummy math library exists,
which is linked if -lm
is used. The enhanced math library
from libext is available in a stand-alone library.
ranlib
(a tool to prepare static libraries for usage by linker)
ranlib
is not available and not necessary with EMX anyway.
Use the s command of ar instead, like ar s foo.a
(or better forget about it completly ...)
make.cmd
in your path which is helpful to some extent and a problem
in some other cases. You can call the underlying binary executable
by x11make.exe
. This batch file defines
SHELL=""
and may do other things
(currently it doesn't ...)
make
on un*x. However since GNUMake is very portable and widely available
you may try to use them anyway.
(cd foo; $(MAKE) bar)to
(cd foo && $(MAKE) -f Makefile.os2 bar & cd ..)and
for i in $(subdirs); do (cd $i; $(MAKE) bar); doneto
for %i in ($(subdirs)) do (cd %i && $(MAKE) -f Makefile.os2 bar & cd ..)
SHELL
variable is set explicitly!
x11make
does not properly work with things like
VERSION := $(shell grep -e "^VERSION=" $(VERSIONFILE) | sed -e "s/VERSION=//")while some gnumake 3.76 from Hobbes, LEO does work.
ash
, bash
,
ksh
, tcsh
, zsh
, ...
set -x
configure.in
file available
you should try to use the existing
autoconf port (as of version 2.13 at least).
After getting the installation done, ensure that the supplied
configure.in
is compatible to the current autoconf port and no
fancy libtool stuff is used (especially dynamic/shared libs are used).
Then using it should be as trivial as
autoconf && configure && makeDefault autoconf/2 lacks a "-Zexe" for EMX and such things, but that shouldn't be real problems.
xmkmf
(mxmkmf
exists for LessTif systems;
the OS/2 port lacks this so far).
Unfortunately it may also contain non-portable shell commands.
CFLAGS
, CXXFLAGS
, ...
emxexp
.
PATH
before any other
incompatible versions.
ln
, install, ls, mkdir, mv, rm, mv)
sh.exe
into the
/bin
subdirectory on your working drive
to keep many scripts/Makefiles running without changes.
(this holds for other standard tools as well, like rm
,
cp
, ...)
sed
, awk
, etc.) are no longer sufficient or the
suitable commands become too awful.
The OS/2 command shell cmd.exe
can't execute such
things directly, so you either have to explicitly
call the interpreter (like foo bar.foo
) or
rename it to foo.cmd
and add
a suitable first line containing
extproc foo
like e.g. for perl scripts:
extproc perl -SxNote that this kind of perl scripts have to be in your
PATH
The following table lists several language interpreters which have already being ported to OS/2. Those may not necessarily be the latest version, but you will find out yourself.
Language | OS/2 port |
---|---|
awk (e.g. GNU awk="gawk") | Hobbes, LEO |
m4 | Hobbes, LEO |
perl | ftp.math.ohio-state.edu or the old distribution from Hobbes, LEO |
python | www.python.org and another page |
Tcl | www.vaeshiep.demon.nl |
Tk | www.vaeshiep.demon.nl |
hello.tar.gz
refers to a file hello
which was produced by tar
and finally packed
by gzip
.
extension | related tool |
---|---|
.cpio | cpio |
.deb | Package for Debian linux |
.bz2 | bzip2 |
.gz |
(GNU) gzip (gzip -d , gunzip )
|
.rpm | RPM; OS/2 port of this tool |
.shar |
sh (shell archive) (sh foo.shar )
|
.tar | (GNU) tar |
.uue | uudecode/uudeview |
.Z | decompress/gunzip |
.z | pack/unpack |
.zip | Info-(un)zip |
dos2unix/unix2dos
, recode
, tr
,
trans
, ...
chk4dlls
somewhere. It lists all DLLs required
by an executable/DLL and is an equivalent to the ldd
utility available on many un*x systems.
DosLoadModule()
and similar)
main()
routine (except for the beginning
or end, perhaps), but most of the time it stays in a loop which waits for
events like keyboard or mouse actions. Then it calls the appropriate routines
(callbacks) which have been installed to react upon them.
foo
is linked against Xt.dll run foo -sync
inside a debugger and set a breakpoint on exit()
(see below).
There are usually static X11 libs available. Linking against these
might help in debugging (no, it does not really help, it just makes life
easier, since all symbols are now within the executable which
is handy when using a debugger).
Xm
.
The leading underscore _
which gets added to all symbols
(at least using EMX/gcc) is omitted here for brevity.
In the following I list some prefixes and the linker command to select the appropriate library. The "Origin" entry tells you which package supplies the appropriate library.
Prefix | Library | Origin |
---|---|---|
X | -lX11 | XFree86 OS/2 |
Xt | -lXt | XFree86 OS/2 |
Xmu, XEditRes | -lXmu | XFree86 OS/2 |
Smc, Sms | -lSM | XFree86 OS/2 |
Ice | -lICE | XFree86 OS/2 |
Xdbe, Xext, XShape | -lXext | XFree86 OS/2 |
Xie | -lXie | XFree86 OS/2 |
Xp | -lXp | XFree86 OS/2 |
XScreenSaver | -lXss | XFree86 OS/2 |
XTest, XRecord | -lXtst | XFree86 OS/2 |
Xaw | -lXaw | XFree86 OS/2 (?) (also check OS/2 ports) |
Xm | -lXm | M*tif (LessTif) |
Mrm | -lMrm | M*tif (LessTif) |
Uil | -lUil | M*tif (LessTif) |
Xbae | -lXbae | Xbae (matrix widgets) (LessTif) |
Xpm, xpm | -lXpm | XFree86 OS/2, ports |
fl_ | -lforms | xforms (OS/2 ports) |
fltk | -lfltk | fltk (OS/2 port) |
gl_ | -lMesaGL | MesaGL (OS/2 ports) |
? | -lgtk | ? |
shm | -lshm | various sources |
? | -lqt | ? |
You can locate symbols not listed here by running
emxexp
on the libraries in %X11ROOT%/XFree86/lib.
Obviously the library name tends to be the same cryptic
letter combination as the prefix you are looking for ...
The order in which you have to link these libs is partially fixed:
-lUil -lMrm -lXm -lXt -lXmu -lXp -lXext -lXpm -lSM -lICE -lX11Of course not all of these libraries are always necessary, but in some cases even more libraries may be required. The socket library (
-lsocket
) is another candidate here.
It provides e.g. gethostname()
or connect()
.
-lsocket
(see
"What if an (X11) app fails to link due to unresolved symbols?").
A sample commandline would be
gcc -Zmtd -Zbsd-signals -o bar.exe bar.o -lXt_s -lSM -lICE -lX11_s -lsocket