Differences between version 2 and previous revision of PortabilityNotes.
Other diffs: Previous Major Revision, Previous Author, or view the Annotated Edit History
Newer page: | version 2 | Last edited on Friday, July 7, 2006 9:44:30 am | by AristotlePagaltzis | Revert |
Older page: | version 1 | Last edited on Friday, July 7, 2006 9:16:45 am | by AristotlePagaltzis | Revert |
@@ -1,21 +1,165 @@
-!!! Shell Syntax
-See ShellPortabilityNotes for bash(1)/sh(1) portability notes.
+!!! [
Shell] syntax
-!!! Miscellaneous
+Since the default [Shell] on almost all LinuxDistribution~s is bash(1), this page lists some common bash-isms that might fail on other sh-type shells on other [Unix](-like) OperatingSystem~s. If there is even the remote possibility that your script might be used by someone other than you, it's worth putting in a small bit of effort to use more portable constructs.
-! tar
+This little section is quoted from the documentation for autoconf(1) (do <tt>info autoconf</tt>, although personally I hate info pages). This demonstrates how stable the [Unix] programming environment is (don't use "new" features added since 1977
!).
-tar(1) on [BSD] systems (including [MacOSX]) need an explicit dash (-) before the options. (
[GNU] tar doesn't)
. Eg
+> ! Portable Shell Programming
+>
+> When writing your own checks, there are some shell-script programming
+> techniques you should avoid in order to make your code portable. The Bourne
+> shell and upward-compatible shells like the Korn shell and Bash have evolved
+> over the years, but to prevent trouble, do not take advantage of features
+> that were added after UNIX version 7, circa 1977 .
+>
+> You should not use shell functions, aliases, negated character classes, or
+> other features that are not found in all Bourne-compatible shells; restrict
+> yourself to the lowest common denominator. Even <tt>unset</tt> is not supported
+> by all shells! Also, include a space after the exclamation point in interpreter
+> specifications, like this:
+>
+> <verbatim>
+> #! /usr/bin/perl
+> </verbatim>
+>
+> If you omit the space before the path, then 4.2BSD based systems (such as
+> DYNIX) will ignore the line, because they interpret "<tt>#! /</tt>" as a
+> 4-byte magic number. Some old systems have quite small limits on the length
+> of the <tt>#!</tt> line too, for instance 32 bytes (not including the
+> newline) on SunOS 4.
+
+!! The test(1) command
+
+Note that test(1) is a built-in function in many shells.
+
+! <i><tt>-z</tt>: tests if the length of STRING is zero</i>
+
+In bash, a non-existent variable is treated like "", but on some other shells it is treated like nothing.
+
+Bash, non-portable::
+
+ <verbatim>
+ $ test -z $NON_EXISTENT_VARIABLE
+ $ echo $?
+
+ </verbatim>
+
+Bash, more portable::
+
+ <verbatim>
+ $ test -z "$NON_EXISTENT_VARIABLE"
+ $ echo $?
+
+ </verbatim>
+
+Solaris sh::
+
+ <verbatim>
+ $ test -z $NON_EXISTENT_VARIABLE
+ test: argument expected
+ $ echo $?
+ 1
+ $ test -z "$NON_EXISTENT_VARIABLE"
+ $ echo $?
+
+ </verbatim>
+
+! <i><tt>-e</tt>: FILE exists</i>
+
+This seems to be a [GNU] extension – some shells don't allow <tt>-e</tt> as an option to test.
+
+Solaris sh::
+
+ <verbatim>
+ $ test -e filename
+ test: argument expected
+ </verbatim>
+
+In most cases, you can use <tt>-r</tt> (for file is readable) instead.
+
+!! Variables
+
+Bash, non-portable:
+
+ <verbatim>
+ $ export VAR1=foo
+ $ echo $VAR1
+ foo
+ </verbatim>
+
+Bash, more portable:
+
+ <verbatim>
+ $ VAR2=bar; export VAR2
+ $ echo $VAR2
+ bar
+ </verbatim>
+
+Solaris sh:
+
+ <verbatim>
+ $ export VAR1=foo
+ VAR1=foo is not an indentifier
+ $ echo $VAR1
+ $ VAR2=bar; export VAR2
+ $ echo $VAR2
+ bar
+ </verbatim>
+
+----
+
+!!! [Shell] tools
+
+!! tar(1)
+
+
tar(1) on [BSD] systems (including [MacOSX]) need an explicit dash (-) before the options, whereas
[GNU] tar doesn't. Eg.:
+
+ <verbatim>
$ tar xf file.tar (gnu)
$ tar -xf file.tar (bsd)
+ </verbatim>
-Not all tars support the -z option for gzip(1) '
ped tar files
. Pipe it instead. (Not all environments have the zcat(1) alias either)
-<verbatim>
+Not all tars support the <tt>
-z</tt>
option for [
gzip(1)]
ped TarBall~s
. Pipe it instead. (Not all environments have the zcat(1) alias either.
)
+
+ <verbatim>
$ tar -zxf file.tar.gz # not portable
$ gzip -d -c file.tar.gz | tar -xf -
-</verbatim>
+
</verbatim>
+
+----
+
+!!! [C]
+
+!! File locking
+
+[BSD]-style unixes uses flock(2), which uses "advisory" locks. Ie, a process with sufficient read or write permission can ignore the lock and read/write a file. [SysV]-style unixes use either advisory locks or "mandatory" locks (if enabled in the FileSystem), and access them by the fcntl(2) command and a <tt>struct flock</tt> object.
+
+A more portable way ([POSIX] 1003.1-2001) is to use the lockf(3) function from unistd.h, which will do the correct type of locking for the unix it is compiled on. (In [Linux]/[GNU] libc, this function is a wrapper around fcntl(2)).
+
+!! printf(3) types
+
+! 64-bit-isms and fixed sized types
+
+If you have a fixed sized type (eg, uint64_t) and you want to use printf(3) to display it, you need to know the real type of the integer. Eg.:
+
+ <verbatim>
+ uint64_t x;
+ printf("%llu",x);
+ </verbatim>
+
+This however will fail on 64bit machines as <tt>uint64_t</tt> is <tt>long</tt> not <tt>long long</tt>.
+
+[POSIX] defines some macros to use in this case, normally found in <tt>inttypes.h</tt>. Eg., for an unsigned 64 bit value, use the macro <tt>PRIu64</tt>. This will be substituted for whatever is appropriate on your host – either <tt>lu</tt> or <tt>llu</tt>, depending on if you are on a 32bit or 64bit host. Eg.:
+
+ <verbatim>
+ uint64_t x;
+ printf("%"PRIu64,x);
+ </verbatim>
+
+!! See also
+
+* [HP] has [a set of C portability notes | http://docs.hp.com/en/5074/portability.html], although it targets HP-UX.
+* [Intel] has [a similar set of notes | http://www.intel.com/cd/ids/developer/asmo-na/eng/technologies/64bit/200519.htm?page=1] (for porting to [ia64] and [amd64])
-!!!Programming
-[C] - see [CPortabilityNotes]
----
Part of CategoryProgramming