Introduction
Conformance and Legacy Behavior
Types of Compatibility Issues
Compile/Link Issues
Command usage issues
Execution issues
In an effort to increase compatibility with other UNIX operating systems, Apple has made a significant effort in Mac OS X v.10.5 to support the Single UNIX Specification Version 3 (SUSv3). Although Apple has attempted to minimize the impact of the changes involved, some of them will affect developers who work with UNIX APIs and commands.
The Mac OS X kernel, libraries, and utilities are drawn from a number of Open Source projects, including FreeBSD, GNU, NetBSD, and OpenBSD. Although these projects make an effort to follow industry standards, none of them have the resources to engage in a formal certification process.
By performing this work for Mac OS X, Apple benefits both its developers (who can now rely on well-defined interfaces and behavior) and the contributing Open Source projects (whose code and documentation can be updated to include Apple's changes).
Although Apple has attempted to make the process as seamless as possible, some conformance changes are simply incompatible with commands and APIs found on earlier versions of Mac OS X. This document provides an overview of these incompatibilities, along with information on specific changes that are likely to be problematic.
In most cases, the conformance tests can be passed by adding functionality, such as functions and command-line options, to the operating system. As this does not change existing behavior or interfaces, it will not affect current applications (and will not be addressed in this document). For portability, however, new or changed code should use conformant interfaces.
In some cases, the standard defines behavior that was left unspecified by existing documentation, such as manual pages). The tests look for this behavior. In most cases, the changes needed to pass the tests will not affect current applications. In cases where specific problems have been observed, this document discusses them.
In a relatively small number of cases, conformant interfaces or behavior actually conflict with that found in previous (legacy) versions of Mac OS X. As discussed in the compat(5)
manual page, Mac OS X v.10.5 provides ways to approximate legacy behavior. Although this does not guarantee that current programs will "Just Work", it should minimize the number of coding changes.
Existing compiled applications should not encounter problems in moving to Mac OS X v.10.5. If a system call or library function is known to have new behavior, the new version will only be used with programs that have been compiled for use on Mac OS X v.10.5. An existing executable will not "see" these versions and thus will not be affected by the changes.
If an application is recompiled for use on Mac OS X v.10.5, it will get the new versions of libraries and system calls, unless a legacy target is specified (See Execution issues, below) .Some scripts, such as bash and perl scripts, may also encounter problems with commands whose options and/or behavior has changed. It is possible to request legacy behavior by setting the environment variable COMMAND_MODE
to the value "legacy
".
The include files and/or prototypes for a number of library functions and system calls have changed. If a change seems likely to cause problems, the previous version or versions have been documented in the LEGACY SYNOPSIS
section of the relevant manual page.
Although you should use conformant include files and prototypes where possible, the following macro:
#define _NONSTD_SOURCE |
will frequently allow the legacy versions to be used. Again, see the compat(5)
manual page for details.
The following manual pages currently have LEGACY SYNOPSIS
sections:
System Calls:
Library functions:
If the options and/or behavior of a command have changed significantly, one or more LEGACY
sections should document this fact. However, these sections are still very much "in progress" at this time.
The following commands respond to the COMMAND_MODE environment variable, as discussed in compat(5)
:
awk
The awk(1)
command honors several forms of extended regular expressions (i.e., {n,m}
, [[==]]
, and [[..]]
). Legacy operation disables this behavior.
bash, sh
"echo -n
" works in bash(1)
, but not in sh(1)
. In legacy operation, the echo(1)
builtin also supports the option in sh
. However, this requires that sh
itself be run in legacy mode.
bash-3.1$ echo === |
=== |
bash-3.1$ echo -n === |
===bash-3.1$ COMMAND_MODE=legacy sh |
sh-3.1$ echo -n === |
===sh-3.1$ exit |
exit |
bash-3.1$ sh |
sh-3.1$ echo -n === |
-n === |
sh-3.1$ COMMAND_MODE=legacy sh -c 'echo -n ===' |
===sh-3.1$ |
Similar issues apply to the way echo
treats "\r
". The printf(1)
command is the recommended way to handle newline and escape sequences.
Existing scripts can be run in legacy mode, as:
COMMAND_MODE=legacy old_script arg ... |
However, this will cause the entire script (and any commands it runs) to operate in legacy mode (generally, like Mac OS X v.10.4 would).
chown
If the chown(8)
command when invoked as "chown -RP ..." encounters a symbolic link, the user ID of the symlink itself is modified. Legacy operation disables this behavior.
cp
The -i
option to cp(1)
disables -f
. In legacy operation, the -f
and -i
options cannot be used together.
The -f
option specifies new access rights for any target file. Legacy operation disables this behavior, retaining the original access rights of any preexisting target file.
With the -R
option, a copying error for an individual file will cause the entire copy to terminate. In legacy operation, copying will continue despite errors..
crontab
If given no arguments, this command reads from stdin. In legacy operation, this command format is not allowed.
date
In legacy operation, the following exit values are returned:
0
—The date was written successfully
1
—Unable to set the date
2
—Able to set the local date, but unable to set it globally
df
The -t
option is normally a no-op (the total allocated-space figures are printed, by default). However, if used with an argument (e.g., "-t hfs
", it acts like -T
, but this usage is deprecated and should not be relied upon. In legacy operation, -t
acts like -T
.
The "capacity" percentage is rounded up to the next higher integer. In legacy operation, it is rounded down to the next lower integer.
The default block size is 512 bytes. This may be overridden by the BLOCKSIZE
environment variable. The -b
, -g
, -k
, -m
, and -P
options will override both the default and any BLOCKSIZE
specification. In legacy operation, the default block size is 1024 bytes. So (unless BLOCKSIZE
is specified), the -k
option is a no-op and the -b
and -P
options actually force the use of 512-byte blocks.
du
Any combination of -[LHP]
options can be specified. The last one encountered determines the command's behavior. In legacy operation, only one of these options may be specified.
The command will detect and report a SYMLOOP
error (loop involving symbolic links). In legacy operation, this is not the case.
ex, vi, view, vim
The -w option sets the default window size value for scrolling. In legacy operation, it defines a "scriptout" file.
A number of the internal commands change (mostly in minor ways) when the commands are used in legacy operation.
file
The -i
option means "if the file is a regular file, do not classify its contents. In legacy operation, -i
and --mime
cause the file command to output mime type strings, rather than the more traditional human readable ones.
The -r
and --raw
options are no-ops. In legacy operation, these prevent the file command from translating unprintable characters to their octal representations.
grep
The caret (beginning of line) meta-character can never be matched in any location other than the beginning of the line. In -E
mode, grep will print an error message and abort on certain cases of this usage (e.g., "^^*
", "^^+
", "^^?
"). In legacy operation, the nonsense usage is allowed to fail (i.e., match nothing) silently.
join
The -e
option causes a specified string to be substituted into empty fields, even if they are in the middle of a line. In legacy operation, the substitution only takes place at the end of a line.
Only documented options are allowed. In legacy operation, some obsolete options are re-written into current options.
less, more
In the more(1)
command, the -n
option specifies the number of lines per screenful. In legacy operation, or when the command is invoked as less(1)
, -n
is used to suppress line numbering.
In the more
command, the -p
option is used to specify commands (e.g., :p
) for each new screenful of text. In legacy operation, or when invoked as less
, the -p
flag specifies a search pattern.
ls
When -H
is specified (and not overridden by -L
or -P
) and a file argument is a symlink that resolves to a non-directory file, the output will reflect the nature of the link, rather than that of the file. In legacy operation, the output will describe the file.
The -f
option turns on the -a
option (show files whose names have a period (.
) as the first character). In legacy operation, it does not.
The -o
option causes the listing to be in long format, but to omit the group id. In legacy operation, the -o
option modifies the -l
option, causing file flags to be listed.
The -g
, -n
, and -o
options turn on the -l
option (causing the listing to be in long format). In legacy operation, they do not.
mkfifo
The -m
option sets the created FIFO to the specified mode. In legacy operation, the specified mode is masked with 0666
.
mv
The command "mv dir/afile dir
" will abort with an error message. In legacy operation, it will fail silently with an exit code of 0
.
pr
The last space before the tab stop is replaced with a tab character. In legacy operation, it is not.
ps
The biggest change is in the interpretation of the -u
option, which now displays processes belonging to the specified username(s). Thus, "ps -aux
" will fail (unless you want to know about user "x
"). As a convenience, however, "ps aux
" still works as it did in Mac OS X v.10.4.
In legacy operation, ps has the following differences:
-e
Display the environment as well. Same as -E
.
-g
Ignored for compatibility. Takes no argument.
-l
Display information associated with the following keywords: uid
, pid
, ppid
, cpu
, pri
, nice
, vsz
, rss
, wchan
, state
, tt
, time
, and command
.
-u
Display information associated with the following keywords: user
, pid
, %cpu
, %mem
, vsz
, rss
, tt
, state
, start
, time
, and command
.
The -u
option implies the -r
option.
sed
Warnings are not generated for unused labels. In legacy operation, they are.
When the y
function is specified (for example, sed y/string1/string2/
), doubled backslashes are not converted to single ones. In legacy operation, they are. To avoid this issue, use the s
function instead.
sort
The form sort +POS1 -POS2 ...
is no longer supported. For example:
bash-3.1$ cat data |
b a |
a b |
bash-3.1$ sort data |
a b |
b a |
bash-3.1$ sort +1 -2 data |
sort: invalid option -- 2 |
Try `sort --help' for more information. |
The form sort -k POS1,POS2
can be used to achieve the same effect, but note that the field and character positions are numbered starting with 1 (rather than 0). For example:
bash-3.1$ sort -k 2,3 data |
b a |
a b |
The options are not supported even in legacy operation, but they can be used by means of the following workaround:
bash-3.1$ _POSIX2_VERSION=200111 sort +1 -2 data |
b a |
a b |
stty
The bs[01]
, cr[0-3]
, ff[01]
, nl[01]
, tab[0-3]
, and vt[01]
control modes are accepted, as well as ocrnl
, ofdel
, ofill
, onlret
, and onocr
(along with their inverses, such as -ocrnl
). In legacy operation, these modes are not accepted.
uudecode, uuencode
In legacy operation, uudecode(1)
masks file modes with 0666
, preventing the creation of executable files.
uudecode
cannot change the mode of a created file which is not owned by the current user (unless that user is root
). In legacy operation, fchmod(2)
allows the mode to be changed.
who
The -u
option causes the who(1)
command to display the process id (pid). In legacy operation, it does not.
xargs
In legacy operation, the -L
option treats all newlines as end-of-line, regardless of whether the line is empty or ends with a space. In addition, the -L
and -n
options are not mutually-exclusive.
SUSv3 requires a number of error checks that the Mac OS X kernel has not made in the past. As a result, unexpected errno values may be encountered. Because specific reason(s) for most of these values have not yet been documented in the relevant manual pages, your best resource is the intro(2)
manual page, which supplies general explanations for errno values.
Although some C-language calls now check for error conditions that they didn't under Mac OS X v.10.4, commands and applications compiled for earlier releases of Mac OS X (e.g., Mac OS X v.10.4, Mac OS X v.10.3) will not be affected. The changes take effect only if the programs are recompiled on Mac OS X 10.5 (or greater) with a deployment target of Mac OS X 10.5 (or greater).
The deployment target can be set in at least two ways. One way is to set an environment variable. For example, in bash(1)
, this would look like this:
export MACOSX_DEPLOYMENT_TARGET=10.5 # Build for use on Mac OS X v.10.5 |
export MACOSX_DEPLOYMENT_TARGET=10.4 # Build for use on Mac OS X v.10.4 |
export MACOSX_DEPLOYMENT_TARGET=10.3 # Build for use on Mac OS X v.10.3 |
Alternatively, the target can be passed to the compiler as a command-line option, as shown here:
gcc -mmin-macosx-version=10.5 ... # Build for use on Mac OS X v.10.5 |
gcc -mmin-macosx-version=10.4 ... # Build for use on Mac OS X v.10.4 |
gcc -mmin-macosx-version=10.3 ... # Build for use on Mac OS X v.10.3 |
© 2006 Apple Computer, Inc. All Rights Reserved. (Last updated: 2006-10-06)
|