summaryrefslogtreecommitdiff
path: root/doc/portability-book/files/utilities.xml
blob: f63819651ade2755012a7d314d2fa4b14f562ba5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
<!-- $NetBSD: utilities.xml,v 1.5 2006/11/05 07:24:04 rillig Exp $ -->

<chapter id="utilities">
<title>Command line utilities</title>

<para>This chapter collects the various bugs and peculiarities of the
<ulink url="http://www.opengroup.org/onlinepubs/000095399/idx/utilities.html">POSIX-like
utilities</ulink> on the platforms.</para>

<sect1 id="util.ls">
<title>ls</title>

<para>On MacOS&nbsp;X, <literal>ls</literal> does not return an error
code when the file to be listed does not exist. On some other platforms,
it does.</para>

</sect1>

<sect1 id="util.sh">
<title>sh</title>

<sect2 id="util.sh.ext">
<title>Non-standard extensions</title>

<para>The variable <varname>RANDOM</varname> is an addition of
<filename>ksh</filename>, and <filename>bash</filename> can do it as
well.</para>

<para>The command <command>[[</command> is an addition of
<filename>ksh</filename>, and <filename>bash</filename> can do it as
well.</para>

</sect2>

<sect2 id="util.sh.netbsd">
<title>NetBSD</title>

<para>On NetBSD, have a look at <ulink
url="http://www.netbsd.org/cgi-bin/query-pr-list.pl?state=open&amp;state=closed&amp;state=feedback&amp;text=/bin/sh&amp;category=bin">the
various PRs</ulink> to see what's wrong with the shell.</para>

</sect2>

<sect2 id="util.sh.solaris">
<title>Solaris</title>

<para>On Solaris, <filename>/bin/sh</filename> is missing some features
that POSIX <ulink
url="http://www.opengroup.org/onlinepubs/000095399/utilities/sh.html">requires</ulink>
for the sh utility:</para>

<programlisting>
    $ if ! false; then echo ok; fi
    !: not found

    $ echo ${PWD%/}
    bad substitution

    $ foo=$(true)
    syntax error: `foo=$' unexpected
</programlisting>

<para>There is another sh implementation in
<filename>/usr/xpg4/bin</filename>, which implements these features.
However, many shell scripts and other programs have /bin/sh
hard-coded.</para>

<para>Another incompatibility is this:</para>

<programlisting>
    $ set -- foo bar baz; echo "before: $#"; set --; echo "after: $#"
    before: 3
    after: 3
</programlisting>

<para>All(?) other shells, including <filename>/usr/xpg4/bin/sh</filename>,
reply with <quote>after: 0</quote>.</para>

<para>On Solaris, both <filename>/bin/sh</filename> and
<filename>/usr/xpg4/bin/sh</filename> cannot handle empty for loops.</para>

<programlisting>
    $ for i in ; do echo "i=$i"; done
    syntax error: `;' unexpected
</programlisting>

<para>The work-around is either to add some dummy arguments or to save
the list of things in a variable. Looping over empty lists is no
problem. But note that the various parameter expansions that are applied
here differ in this case.</para>

<programlisting>
    $ things=""; for i in $things; do echo "i=$i"; done
</programlisting>

<sect3 id="util.sh.solaris.glob">
<title>Globbing problems with quoting and hidden files</title>

<programlisting>
    rm -rf "testdir"
    mkdir "testdir"
    touch "testdir/.file"

    x="."
    y=".file"
    echo "=== x and y quoted"
    ls "$x"/*/"$y"
    echo "=== only x quoted"
    ls "$x"/*/$y
    echo "=== nothing quoted"
    ls $x/*/$y
</programlisting>

<para>The result of running this code with <filename>/bin/sh</filename>
is that in the first case, the result of the globbing expansion is
<quote><literal>./*/.file</literal></quote>, while in the two other
cases, it is the correct
<quote><literal>./testdir/.file</literal></quote>. This does only happen
when y starts with a dot, that is, for hidden files.</para>

</sect3>
</sect2>
</sect1>

<sect1 id="util.test">
<title>test</title>

<sect2 id="util.test.options">
<title>Supported options</title>

<para>It is expected that the <emphasis>test</emphasis> utility fully
supports the POSIX standard. Any deviations from it are recorded in the
<quote>Unsupported</quote> column.</para>

<table>
<title>Supported options of the <emphasis>test</emphasis> utility</title>
<tgroup cols="2">
<thead>
<row><entry>Platform</entry><entry>Unsupported</entry><entry>Supported</entry><entry>Extensions</entry></row>
</thead>
<tbody>
<row><entry>AIX-4.3-powerpc</entry><entry></entry><entry>bcdefghLnprstuwxz</entry><entry>k</entry></row>
<row><entry>IRIX-6.5-mipseb</entry><entry></entry><entry>bcdefghLnprstuwxz</entry><entry>k</entry></row>
<row><entry>Linux-2.6.*-*</entry><entry></entry><entry>bcdefgLnprSstuwxz</entry><entry>GkO nt ot ef</entry></row>
<row><entry>NetBSD-3.0-*</entry><entry></entry><entry>bcdefgLnprSstuwxz</entry><entry>GkO nt ot ef</entry></row>
<row><entry>SunOS-5.10-* /bin/sh</entry><entry>eS</entry><entry>bcdfghLnprstuwz</entry><entry>k</entry></row>
<row><entry>SunOS-5.10-* /bin/test</entry><entry></entry><entry>bcdefgLnprSstuwxz</entry><entry>aGkOo nt ot ef</entry></row>
</tbody>
</tgroup>
</table>

<para>Remarks:</para>

<itemizedlist>

<listitem><para>On Solaris-5.10-*, the behavior of the
<literal>-f</literal> operator depends on the value of the environment
variable <varname>PATH</varname>.</para></listitem>

<listitem><para>On Solaris-5.10-*, <filename>/usr/ucb/test</filename>
behaves like the builtin command in <filename>/bin/sh</filename>. On the
other hand, <filename>/usr/bin/test</filename> conforms to
POSIX.</para></listitem>

</itemizedlist>

</sect2>

<sect2 id="util.test.ext">
<title>Non-standard extensions</title>

<para>The Bourne Again Shell (bash) allows the binary operator
<literal>==</literal> to be used as an alias for <literal>=</literal>.
This leads to problems when programs using this feature are ported to
other platforms. By the way, not even the GNU coreutils have that
<quote>feature</quote>, it's really only Bash that does. After all,
there is no apparent benefit for having two names for the same
operator.</para>

</sect2>

<sect2 id="util.test.bugs">
<title>Bugs</title>

<para>On NetBSD upto X.Y (see <ulink url="&u.PR;34646">PR 34646</ulink>), the &man.test.1; utility cannot
handle the following:</para>

<programlisting>
    test ! = foo
</programlisting>

<para>POSIX <ulink
url="http://www.opengroup.org/onlinepubs/000095399/utilities/test.html">requires</ulink>
that when test is called with three arguments, the second operand is
checked first to see whether it is a binary operator. On NetBSD, the
unary <quote>!</quote> operator takes precedence.</para>

</sect2>
</sect1>
</chapter>