Home
Main website
Display Sidebar
Hide Ads
Recent Changes
View Source:
PortabilityNotes
Edit
PageHistory
Diff
Info
LikePages
!!! [Shell] syntax 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. 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!). > ! 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 $? 0 </verbatim> Bash, more portable:: <verbatim> $ test -z "$NON_EXISTENT_VARIABLE" $ echo $? 0 </verbatim> Solaris sh:: <verbatim> $ test -z $NON_EXISTENT_VARIABLE test: argument expected $ echo $? 1 $ test -z "$NON_EXISTENT_VARIABLE" $ echo $? 0 </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> !! See also * [What to watch out for when writing portable shell scripts | http://programming.newsforge.com/article.pl?sid=04/03/01/1554205], a useful article on NewsForge ---- !!! [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 <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> ---- !!! [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> ! Avoid using other peoples types in your headers Other peoples types change in size, sometimes at the flick of a #define. One example is off_t changes if LARGEFILE64 is defined under Linux. Use the c99 <tt><stdint.h></tt> types (uint64_t) so that they don't vary. If you absolutely must reference someone elses type, do so via a pointer (eg FILE*) and treat it as opaque. !! 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]) ---- Part of CategoryProgramming
3 pages link to
PortabilityNotes
:
ApplicationErrorMessages
UserSubmittedNotes
BashNotes