Penguin
Blame: PortabilityNotes
EditPageHistoryDiffInfoLikePages
Annotated edit history of PortabilityNotes version 4, including all changes. View license author blame.
Rev Author # Line
2 AristotlePagaltzis 1 !!! [Shell] syntax
1 AristotlePagaltzis 2
2 AristotlePagaltzis 3 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.
1 AristotlePagaltzis 4
2 AristotlePagaltzis 5 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!).
1 AristotlePagaltzis 6
2 AristotlePagaltzis 7 > ! Portable Shell Programming
8 >
9 > When writing your own checks, there are some shell-script programming
10 > techniques you should avoid in order to make your code portable. The Bourne
11 > shell and upward-compatible shells like the Korn shell and Bash have evolved
12 > over the years, but to prevent trouble, do not take advantage of features
13 > that were added after UNIX version 7, circa 1977 .
14 >
15 > You should not use shell functions, aliases, negated character classes, or
16 > other features that are not found in all Bourne-compatible shells; restrict
17 > yourself to the lowest common denominator. Even <tt>unset</tt> is not supported
18 > by all shells! Also, include a space after the exclamation point in interpreter
19 > specifications, like this:
20 >
21 > <verbatim>
22 > #! /usr/bin/perl
23 > </verbatim>
24 >
25 > If you omit the space before the path, then 4.2BSD based systems (such as
26 > DYNIX) will ignore the line, because they interpret "<tt>#! /</tt>" as a
27 > 4-byte magic number. Some old systems have quite small limits on the length
28 > of the <tt>#!</tt> line too, for instance 32 bytes (not including the
29 > newline) on SunOS 4.
30
31 !! The test(1) command
32
33 Note that test(1) is a built-in function in many shells.
34
35 ! <i><tt>-z</tt>: tests if the length of STRING is zero</i>
36
37 In bash, a non-existent variable is treated like "", but on some other shells it is treated like nothing.
38
39 Bash, non-portable::
40
41 <verbatim>
42 $ test -z $NON_EXISTENT_VARIABLE
43 $ echo $?
44 0
45 </verbatim>
46
47 Bash, more portable::
48
49 <verbatim>
50 $ test -z "$NON_EXISTENT_VARIABLE"
51 $ echo $?
52 0
53 </verbatim>
54
55 Solaris sh::
56
57 <verbatim>
58 $ test -z $NON_EXISTENT_VARIABLE
59 test: argument expected
60 $ echo $?
61 1
62 $ test -z "$NON_EXISTENT_VARIABLE"
63 $ echo $?
64 0
65 </verbatim>
66
67 ! <i><tt>-e</tt>: FILE exists</i>
68
69 This seems to be a [GNU] extension – some shells don't allow <tt>-e</tt> as an option to test.
70
71 Solaris sh::
72
73 <verbatim>
74 $ test -e filename
75 test: argument expected
76 </verbatim>
77
78 In most cases, you can use <tt>-r</tt> (for file is readable) instead.
79
80 !! Variables
81
82 Bash, non-portable:
83
84 <verbatim>
85 $ export VAR1=foo
86 $ echo $VAR1
87 foo
88 </verbatim>
89
90 Bash, more portable:
91
92 <verbatim>
93 $ VAR2=bar; export VAR2
94 $ echo $VAR2
95 bar
96 </verbatim>
97
98 Solaris sh:
99
100 <verbatim>
101 $ export VAR1=foo
102 VAR1=foo is not an indentifier
103 $ echo $VAR1
104 $ VAR2=bar; export VAR2
105 $ echo $VAR2
106 bar
107 </verbatim>
4 AristotlePagaltzis 108
109 !! See also
110
111 * [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
2 AristotlePagaltzis 112
113 ----
114
115 !!! [Shell] tools
116
117 !! tar(1)
118
119 tar(1) on [BSD] systems (including [MacOSX]) need an explicit dash (-) before the options, whereas [GNU] tar doesn't. Eg.:
120
121 <verbatim>
1 AristotlePagaltzis 122 $ tar xf file.tar (gnu)
123 $ tar -xf file.tar (bsd)
2 AristotlePagaltzis 124 </verbatim>
1 AristotlePagaltzis 125
2 AristotlePagaltzis 126 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.)
127
128 <verbatim>
1 AristotlePagaltzis 129 $ tar -zxf file.tar.gz # not portable
130 $ gzip -d -c file.tar.gz | tar -xf -
2 AristotlePagaltzis 131 </verbatim>
132
133 ----
134
135 !!! [C]
136
137 !! File locking
138
139 [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.
140
141 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)).
142
143 !! printf(3) types
144
145 ! 64-bit-isms and fixed sized types
146
147 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.:
148
149 <verbatim>
150 uint64_t x;
151 printf("%llu",x);
152 </verbatim>
153
154 This however will fail on 64bit machines as <tt>uint64_t</tt> is <tt>long</tt> not <tt>long long</tt>.
155
156 [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.:
157
158 <verbatim>
159 uint64_t x;
160 printf("%"PRIu64,x);
161 </verbatim>
3 PerryLorier 162
163 ! Avoid using other peoples types in your headers
164 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.
2 AristotlePagaltzis 165
166 !! See also
167
168 * [HP] has [a set of C portability notes | http://docs.hp.com/en/5074/portability.html], although it targets HP-UX.
169 * [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])
1 AristotlePagaltzis 170
171 ----
172 Part of CategoryProgramming

PHP Warning

lib/blame.php:177: Warning: Invalid argument supplied for foreach()