.de XX .IP \ \ \ \- .. .TL APE \(em The ANSI/POSIX Environment .AU Howard Trickey .SH Introduction .PP When a large or frequently-updated program must be imported or exported to and from Plan 9, the ANSI/POSIX environment known as APE can be useful. APE combines the set of headers and object code libraries specified by the ANSI C standard (ANSI X3.159-1989) with the POSIX operating system interface standard (IEEE 1003.1-1990, ISO 9945-1). Using APE will cause slower compilation and marginally slower execution speeds, so if the importing or exporting happens only infrequently, due consideration should be given to using the usual Plan 9 compilation environment instead. Another factor to consider is that the Plan 9 header organization is much simpler to remember and use. .PP There are some aspectes of required POSIX behavior that are impossible or very hard to simulate in Plan 9. They are described below. Experience has shown, however, that the simulation is adequate for the vast majority of programs. The much more common problem is that many programs use functions or headers not defined by POSIX. APE has some extensions to POSIX to help in this regard. .SH Pcc .PP The .CW pcc command acts as a front end to the Plan 9 C compilers and loaders. It runs an ANSI C preprecessor over source files, using the APE headers to satisfy .CW "#include <\fIfile\fP>" directives; then it runs a Plan 9 C compiler; finally, it may load with APE libraries to produce an executable program. The document .I "How to Use the Plan 9 C Compiler" explains how environment variables are used by convention to handle compilation for differing architectures. The environment variable .CW $objtype controls which Plan 9 compiler and loader are used by .CW pcc , as well as the location of header and library files. For example, if .CW $objtype is .CW mips , then .CW pcc has .CW cpp look for headers in .CW /mips/include/ape followed by .CW /sys/include/ape ; then .CW pcc uses .CW vc to create .CW .v object files; finally, .CW vl is used to create an executable using libraries in .CW /mips/lib/ape . .SH Symbols .PP The C and POSIX standards require that certain symbols be defined in headers. They also require that certain other classes of symbols not be defined in the headers, and specify certain other symbols that may be defined in headers at the discretion of the implementation. POSIX defines .I "feature test macros" , which are preprocessor symbols beginning with an underscore and then a capital letter; if the program .CW #define s a feature test macro before the inclusion of any headers, then it is requesting that certain symbols be visible in the headers. The most important feature test macro is .CW _POSIX_SOURCE : when it is defined, exactly the symbols required by POSIX are visible in the appropriate headers. Consider .CW for example: ANSI defines some names that must be defined in .CW , but POSIX defines others, such as .CW sigset_t , which are not allowed according to ANSI. The solution is to make the additional symbols visible only when .CW _POSIX_SOURCE is defined. .PP When you export a program, it helps to know whether the program fits in one of the following categories: .IP 1. Strictly conforming ANSI C program. It only uses features of the language, libraries, and headers explicitly required by the C standard. It does not depend on unspecified, undefined, or implementation-dependent behavior, and does not exceed any minimum implementation limit. .IP 2. Strictly conforming POSIX program. Similar, but for the POSIX standard. .IP 3. Some superset of POSIX, with extensions. Each extension is selected by a feature test macro, so it is clear which extensions are being used. .PP With APE, if headers are always included to declare any library functions used, then the set of feature test macros defined by a program will show which of the above categories the program is in. To accomplish this, no symbol is defined in a header if it not required by the C or POSIX standard, and those required by the POSIX standard are protected by .CW "#ifdef _POSIX_SOURCE" . For example, .CW defines .CW EDOM , .CW ERANGE , and .CW errno , as required by the C standard. The C standard allows more names beginning with .CW E , but our header defines only those unless .CW _POSIX_SOURCE is defined, in which case the 35 more symbols required by POSIX are defined. This means that a program which uses .CW ENAMETOOLONG cannot masquerade as a strictly conforming ANSI C program. .PP .CW Pcc does not predefine any preprocessor symbols except those required by the ANSI C standard: .CW __STDC__ , .CW __LINE__ , .CW __FILE__ , .CW __DATE__ , and .CW __TIME__ . Any others must be defined in the program itself or using .CW -D on the command line. .SH Extensions .PP The pedagogy enforced by only putting required names in the headers is useful for exporting programs, but it gets in the way when importing programs. The compromise is to allow additional symbols in headers, additional headers, and additional library functions, but only under control of extension feature test macros. The following extensions are provided; unless otherwise specified, the additional library functions are in the default APE library. .XX .CW _LIBG_EXTENSION . This allows the use of the Plan 9 graphics library. The functions are as described in the Plan 9 manual (see .I graphics (2)) except that .CW div had to be renamed .CW ptdiv . Include the .CW header to declare the needed types and functions, and use .CW -lg on the .CW pcc command line to load the graphics functions. .XX .CW _LIMITS_EXTENSION . POSIX does not require that names such as .CW PATH_MAX and .CW OPEN_MAX be defined in .CW , but many programs assume they are defined there. If .CW _LIMITS_EXTENSION is defined, those names will all be defined when .CW is included. .XX .CW _BSDTIME_EXTENSION . The header .CW is not defined by POSIX. This extension allows the inclusion of that header, with its definitions of the .CW timeval and .CW timezone structures. .XX .CW _SELECT_EXTENSION . This extension allows the inclusion of the .CW header, which defines the Berkeley .CW select function and associated types and macros for dealing with multiple input sources. The .CW header must be included before .CW , so the .CW _BSDTIME_EXTENSION is needed too. .XX .CW _PCONS_EXTENSION . This defines a ``pseudo-tty'' capability. If .CW _PCONS_EXTENSION is defined, .CW may be included; it defines the functions .CW pcons(void) and .CW pushtty(void). .CW Pcons arranges for a Plan 9 file server to provide the .CW /dev/cons and .CW /dev/consctl files. It also provides .CW /dev/mcons , which is the ``master end'' of the pseudo-tty: characters written to .CW /dev/mcons can be read from .CW /dev/cons (or .CW /dev/tty , a synonym) and vice versa. POSIX tty line processing is supported: the contents of a .CW termios structure can be written to or read from the .CW /dev/pttyctl file in the format .P1 "stty %8ux %8ux %8ux %8ux " .P2 (the numbers are the .CW c_iflag , .CW c_oflag , .CW c_cflag , and .CW c_lflag ), followed by .CW NCCS bytes of .CW c_cc data. The .CW pushtty function uses .CW pcons to arrange that the standard input, output, and error files behave as ttys are supposed to according to POSIX. (This should not have to be done explicitly, but the cost of supporting .CW tcgetattr and .CW tcputattr is sufficiently high that it seemed better to not make it the default.) .XX .CW _NET_EXTENSION . This extension allows inclusion of .CW , which defines the networking functions described in the Plan 9 manual page .I dial (2). Programs using them must be loaded with .CW -lnet . .XX .CW _REGEXP_EXTENSION . This extension allows inclusion of .CW , which defines the regular expression matching functions described in the Plan 9 manual page .I regexp (2X). Programs using them must be loaded with .CW -lregexp . .XX .CW _RESEARCH_SOURCE . This extension enables a small library of functions from the Tenth Edition Unix Research System (V10). These functions and the types needed to use them are all defined in the .CW header, and programs using them must be loaded with .CW -lv . The provided functions are: .CW popen and .CW pclose (common extensions to ANSI C stdio; the .CW header must have been included); .CW telldir and .CW seekdir (common extensions to the ANSI C .CW readdir suite; .CW must have been included); .CW lstat , .CW symlink , and .CW readlink (dummy functions for Plan 9, since there are no symbolic links); .CW srand , .CW rand , .CW nrand , .CW lrand , and .CW frand (better random number generators); .CW getopt (program argument handler); .CW getpass , .CW tty_echoon , .CW tty_echooff (for dealing with the common needs for mucking with terminal characteristics); .CW min and .CW max ; .CW nap ; .CW setfields , .CW getfields , and .CW getmfields (for parsing a line into fields); and .CW ftw (for walking a file tree). See the Research Unix Programmer's Manual for a description of these functions. .SH Common Problems .PP Some large systems, including X11, have been ported successfully to Plan 9 using APE. The problems encountered fall into three categories: (1) non- ANSI C/POSIX features used; (2) inadequate simulation of POSIX functions; and (3) compiler/loader bugs. By far the majority of problems are in the first category. .PP POSIX is just starting to be a target for programmers. Most existing code is written to work with one or both of a BSD or a System V Unix. System V is fairly close to POSIX, but there are some differences. Also, many System V systems have imported some BSD features that are not part of POSIX. Here are some common non-POSIX things used in current programs, and what to do about them. .XX .CW sys_errlist and .CW sys_nerr globals. Use .CW strerror instead. .XX Third (environment) argument to .CW main . Use the .CW environ global instead. .XX .CW OPEN_MAX , .CW PATH_MAX , etc., assumed in .CW . Rewrite to call .CW sysconf or define .CW _LIMITS_EXTENSION . .XX .CW isascii assumed in .CW . Let the dead codeset go: leave the test out, or better still, convert to use multibyte characters (c.f. runes in Plan 9). Or define your own .CW isascii macro. .XX .CW , .CW index , and .CW rindex . Use .CW , .CW strchr , and .CW strrchr instead. .XX .CW mktemp . Rewrite to use ANSI C .CW tempnam or .CW tmpfile . .XX .CW . Rewrite to use .CW . .XX .CW popen assumed in .CW . Use .CW _RESEARCH_SOURCE extension, include .CW , and load with .CW -lv . Similarly for .CW telldir , .CW seekdir , .CW lstat , .CW srand , .CW rand , .CW nrand , .CW lrand , .CW frand , and .CW getopt . .XX .CW select . Define .CW _BSDTIME_EXTENSION and .CW _SELECT_EXTENSION and include .CW and .CW . .XX Socket or stream stuff. Rewrite to use the Plan 9 networking functions, define .CW _NET_EXTENSION , include .CW and load with .CW -lnet . .PP The second class of problems has to do with inadequacies in the Plan 9 simulation of POSIX functions. As long as this list is, these shortcomings have rarely gotten in the way (except, perhaps for the .CW link problem). .XX Functions for setting the userid, groupid, effective userid and effective groupid do not do anything useful. The concept is impossible to simulate in Plan 9. .CW Chown also does nothing. .XX .CW execlp and the related functions do not look at the .CW PATH environment variable. They just try the current directory and .CW /bin if the pathname is not absolute. .XX Advisory locking via .CW fcntl is not implemented. .XX .CW isatty is hard to do correctly. The approximation used is to see if the file is the same as .CW /dev/cons . Sometimes this cannot be determined, and sometimes this is not the right test. .XX With .CW kill , the behavior mandated for negative arguments (killing process groups) is not implemented. .XX .CW link always fails. .XX With .CW open , the .CW O_NOCTTY option has no effect. The concept of a ``controlling'' tty is foreign to Plan 9. .XX .CW setsid does a .CW forkpgrp , which is only approximately the right behavior. .XX The functions dealing with stacking signals, .CW sigpending , .CW sigprocmask and .CW sigsuspend , do not work. .XX .CW system uses .CW rc instead of .CW sh to interpret the argument. Use of .CW system is discouraged for security reasons anyway. .XX .CW tcgetattr and .CW tcsetattr only work if .CW pcons or .CW pushtty has been executed (see the discussion about the .CW _PCONS_EXTENSION , above ). .XX .CW umask has no effect, as there is no such concept in Plan 9. .XX .CW utime has no effect, because the time can't be changed in Plan 9.