Merge commit 'db1c88f6dab43484b6c33636600ac4596ff4c354'
[unleashed.git] / bin / ksh / NOTES
blob5bda635249d75ba17737e5454c9fe429221a66cc
1 $OpenBSD: NOTES,v 1.16 2018/01/12 14:20:57 jca Exp $
3 General features of at&t ksh88 that are not (yet) in pdksh:
4     - exported aliases and functions (not in ksh93).
5     - set -t.
6     - signals/traps not cleared during functions.
7     - trap DEBUG, local ERR and EXIT traps in functions.
8     - ERRNO parameter.
9     - read/select aren't hooked in to the command line editor
10     - the last command of a pipeline is not run in the parent shell
12 Known bugs (see also PROJECTS files):
13     Variable parsing, Expansion:
14         - some specials behave differently when unset (eg, IFS behaves like
15           " \t\n") others lose their special meaning.  IFS/PATH taken care of,
16           still need to sort out some others (eg, TMOUT).
17     Parsing,Lexing:
18         - line numbers in errors are wrong for nested constructs.  Need to
19           keep track of the line a command started on (can use for LINENO
20           parameter as well).
21         - a $(..) expression nested inside double quotes inside another $(..)
22           isn't parsed correctly (eg, $(echo "foo$(echo ")")") )
23     Commands,Execution:
24         - setting special parameters that have side effects when
25           changed/restored (ie, HISTFILE, OPTIND, RANDOM) in front
26           of a command (eg, HISTFILE=/foo/bar echo hi) affects the parent
27           shell.  Note that setting other (not so special) parameters
28           does not affect the parent shell.
29         - `echo hi | exec cat -n' causes at&t to exit, `exec echo hi | cat -n'
30           does not.  pdksh exits for neither.  Don't think POSIX requires
31           an exit, but not sure.
32         - `echo foo | read bar; echo $bar' prints foo in at&t ksh, nothing
33           in pdksh (ie, the read is done in a separate process in pdksh).
35 Known problems not caused by ksh:
36     - after stoping a job, emacs/vi is not re-entered.  Hitting return
37       prints the prompt and everything is fine again.  Problem (often
38       involving a pager like less) is related to order of process
39       scheduling (shell runs before `stop'ed (sub) processes have had a chance
40       to clean up the screen/terminal).
42 Known differences between pdksh & at&t ksh (that may change)
43     - vi:
44         - `^U': at&t: kills only what has been inserted, pdksh: kills to
45           start of line
46     - at&t ksh login shells say "Warning: you have running jobs" if you
47       try to exit when there are running jobs.  An immediate second attempt
48       to exit will kill the jobs and exit.  pdksh does not print a warning,
49       nor does it kill running jobs when it exits (it does warn/kill for
50       stopped jobs).
51     - TMOUT: at&t prints warning, then waits another 60 seconds.  If on screwed
52       up serial line, the output could cause more input, so pdksh just
53       prints a message and exits.  (Also, in at&t ksh, setting TMOUT has no
54       effect after the sequence "TMOUT=60; unset TMOUT", which could be
55       useful - pdksh may do this in the future).
56     - in pdksh, if the last command of a pipeline is a shell builtin, it is
57       not executed in the parent shell, so "echo a b | read foo bar" does not
58       set foo and bar in the parent shell (at&t ksh will).
59       This may get fixed in the future, but it may take a while.
60     - in pdksh, set +o lists the options that are currently set, in at&t ksh
61       it is the same as set -o.
62     - in pdksh emacs mode, ^T does what gnu emacs does, not what at&t ksh
63       does.
64     - in ksh93, `. name' calls a function (defined with function) with POSIX
65       semantics (instead of ksh semantics).  in pdksh, . does not call
66       functions.
67     - test: "test -f foo bar blah" is the same as "test -f foo" (the extra
68       arguments, of which there must be at least 2, are ignored) - pdksh
69       generates an error message (unexpected operator/operand "bar") as it
70       should.  Sometimes used to test file globs (e.g., if test -f *.o; ...).
71     - if the command 'sleep 5 && /bin/echo blah' is run interactively and
72       is the sleep is stopped (^Z), the echo is run immediately in pdksh.
73       In at&t ksh, the whole thing is stopped.
74     - LINENO:
75         - in ksh88 variable is always 1 (can't be changed) in interac mode;
76           in pdksh it changes.
77         - Value of LINENO after it has been set by the script in one file
78           is bizarre when used in another file.
80 Known differences between pdksh & at&t ksh (that are not likely to change)
81     - at&t ksh seems to catch or ignore SIGALRM - pdksh dies upon receipt
82       (unless it's traped of course)
83     - typeset:
84         - at&t ksh overloads -u/-l options: for integers, means unsigned/long,
85           for strings means uppercase/lowercase; pdksh just has the
86           upper/lower case (which can be useful for integers when base > 10).
87           unsigned/long really should have their own options.
88         - at&t ksh can't have justified integer variables
89           (eg, typeset -iR5 j=10), pdksh can.
90         - in pdksh, number arguments for -L/-R/-Z/-i must follow the option
91           character, at&t allows it at the end of the option group (eg,
92           at&t ksh likes "typeset -iu5 j", pdksh wants "typeset -i5 -u j"
93           or "typeset -ui5 j").  Also, pdksh allows "typeset -i 5 j" (same
94           as "typeset -i5 j"), at&t ksh does not allow this.
95         - typeset -R: pdksh strips trailing space type characters (ie,
96           uses isspace()), at&t ksh only skips blanks.
97         - at&t ksh allows attributes of read-only variables to be changed,
98           pdksh allows only the export attribute to be set.
99     - (some) at&t ksh allows set -A of readonly variables, pdksh does not.
100     - at&t ksh allows command assignments of readonly variables (eg, YY=2 cat),
101       pdksh does not.
102     - at&t ksh does not exit scripts when an implicit assignment to an integer
103       variable fails due to an expression error: eg,
104                 echo 2+ > /tmp/x
105                 unset x; typeset -i x
106                 read x < /tmp/x
107                 echo still here
108       prints an error and then prints "still here", similarly for
109                 unset x; typeset -i x
110                 set +A x 1 2+ 3
111                 echo still here
112       and
113                 unset x y; typeset -i x y; set +A y 10 20 30
114                 set +A x 1 1+y[2+] 3
115                 echo still here
116       pdksh exits a script in all the above cases. (note that both shells
117       exit for:
118                 unset x; typeset -i x
119                 for x in 1 2+ 3; do echo x=$x; done
120                 echo still here
121       ).
122     - at&t ksh seems to allow function calls inside expressions
123       (eg, typeset -i x='y(2)') but they do not seem to be regular functions
124       nor math functions (eg, pow, exp) - anyone known anything about this?
125     - `set -o nounset; unset foo; echo ${#foo}`: at&t ksh prints 0; pdksh
126       generates error.  Same for ${#foo[*]} and ${#foo[@]}.
127     - . file: at&t ksh parses the whole file before executing anything,
128       pdksh executes as it parses.  This means aliases defined in the file
129       will affect how pdksh parses the file, but won't affect how at&t ksh
130       parses the file.  Also means pdksh will not parse statements occurring
131       after a (executed) return statement.
132     - a return in $ENV in at&t ksh will cause the shell to exit, while in
133       pdksh it will stop executing the script (this is consistent with
134       what a return in .profile does in both shells).
135     - at&t ksh does file globbing for `echo "${foo:-"*"}"`, pdksh does not
136       (POSIX would seem to indicate pdksh is right).
137     - at&t ksh thinks ${a:##foo} is ok, pdksh doesn't.
138     - at&t does tilde expansion on here-document delimiters, pdksh does
139       not.  eg.
140         $ cat << ~michael
141         ~michael
142         $
143       works for pdksh, not for at&t ksh (POSIX seems to agree with pdksh).
144     - in at&t ksh, tracked aliases have the export flag implicitly set
145       and tracked aliases and normal aliases live in the same name space
146       (eg, "alias" will list both tracked and normal aliases).
147       in pdksh, -t does not imply -x (since -x doesn't do anything yet), and
148       tracked/normal aliases live in separate name spaces.
149       in at&t ksh, alias accepts + options (eg, +x, +t) - pdksh does not.
150       in pdksh, alias has a -d option to allow examination/changing of
151       cached ~ entries, also unalias has -d and -t options (unalias -d
152       is useful if the ~ cache gets out of date - not sure how at&t deals
153       with this problem (it does cache ~ entries)).
154     - at&t ksh will stop a recursive function after about 60 calls; pdksh
155       will not since the limit is arbitrary and can't be controlled
156       by the user (hit ^C if you get in trouble).
157     - the wait command (with and without arguments) in at&t ksh will wait for
158       stopped jobs when job control is enabled.  pdksh doesn't.
159     - at&t ksh automatically sets the bgnice option for interactive shells;
160       pdksh does not.
161     - in at&t ksh, "eval `false`; echo $?" prints 1, pdksh prints 0 (which
162       is what POSIX says it should).  Same goes for "wait `false`; echo $?".
163       (same goes for "set `false`; echo $?" if posix option is set - some
164       scripts that use the old getopt depend on this, so be careful about
165       setting the posix option).
166     - in at&t ksh, print -uX and read -uX are interrperted as -u with no
167       argument (defaults to 1 and 0 respectively) and -X (which may or
168       may not be a valid flag).  In pdksh, -uX is interpreted as file
169       descriptor X.
170     - in at&t ksh, some signals (HUP, INT, QUIT) cause the read to exit, others
171       (ie, everything else) do not.  When it does cause exiting, anything read
172       to that point is used (usually an empty line) and read returns with 0
173       status.  pdksh currently does similar things, but for TERM as well and
174       the exit status is 128+<signal-number> - in future, pdksh's read will
175       do this for all signals that are normally fatal as required by POSIX.
176       (POSIX does not require the setting of variables to null so applications
177       shouldn't rely on this).
178     - in pdksh, ! substitution done before variable substitution; in at&t ksh
179       it is done after substitution (and therefore may do ! substitutions on
180       the result of variable substitutions).  POSIX doesn't say which is to be
181       done.
182     - pwd: in at&t ksh, it ignores arguments; in pdksh, it complains when given
183       arguments.
184     - the at&t ksh does not do command substition on PS1, pdksh does.
185     - ksh93 allows ". foo" to run the function foo if there is no file
186       called foo (go figure).
187     - field splitting (IFS): ksh88/ksh93 strip leading non-white space IFS
188       chars, pdksh (and POSIX, I think) leave them intact. e.g.
189         $ IFS="$IFS:"; read x; echo "<$x>"
190         ::
191       prints "<>" in at&t ksh, "<::>" in pdksh.
192     - command completion: at&t ksh will do completion on a blank line (matching
193       all commands), pdksh does not (as this isn't very useful - use * if
194       you really want the list).
195     - co-processes: if ksh93, the write portion of the co-process output is
196       closed when the most recently started co-process exits. pdksh closes
197       it when all the co-processes using it have exited.
198     - pdksh accepts empty command lists for while and for statements, while
199       at&t ksh (and sh) don't.  Eg., pdksh likes
200         while false ; do done
201       but ksh88 doesn't like it.
202     - pdksh bumps RANDOM in parent after a fork, at&t ksh bumps it in both
203       parent and child:
204         RANDOM=1
205         echo child: `echo $RANDOM`
206         echo parent: $RANDOM
207       will produce "child: 16838 parent: 5758" in pdksh, while at&t ksh
208       will produce "child: 5758 parent: 5758".
210 Oddities in ksh (pd & at&t):
211     - array references inside (())/$(()) are strange:
212           $(( x[2] )) does the expected, $(( $x[2] )) doesn't.
213     - `typeset -R3 X='x '; echo "($X)"` produces (  x) - trailing
214       spaces are stripped.
215     - typeset -R turns off Z flag.
216     - both shells have the following mis-feature:
217         $ x='function xx {
218                 cat -n <<- EOF
219                 here we are in xx
220                 EOF
221                 }'
222         $ (eval "$x"; (sleep 2; xx) & echo bye)
223         [1] 1234
224         bye
225         $ xx: /tmp/sh1234.1: cannot open
226     - bizarre special handling of alias/export/readonly/typeset arguments
227         $ touch a=a; typeset a=[ab]; echo "$a"
228         a=[ab]
229         $ x=typeset; $x a=[ab]; echo "$a"
230         a=a
231         $
232     - both ignore SIGTSTP,SIGTTIN,SIGTTOU in exec'd processes when talking
233       and not monitoring (at&t ksh kind of does this).  Doesn't really make
234       sense.
235       (Note that ksh.att -ic 'set +m; check-sigs' shows TSTP et al aren't
236        ignored, while ksh.att -ic 'set +m^J check-sigs' does... very strange)
237     - when tracing (set -x), and a command's stderr is redirected, the trace
238       output is also redirected. so "set -x; echo foo 2> /tmp/O > /dev/null"
239       will create /tmp/foo with the lines "+ > /dev/null" and "+ echo foo".
240     - undocumented at&t ksh88, documented in ksh93: FPATH is searched
241       after PATH if no executable is found, even if typeset -uf wasn't used.
243 POSIX sh questions (references are to POSIX 1003.2-1992)
244         - arithmetic expressions: how are empty expressions treated?
245           (eg, echo $((  ))).  at&t ksh (and now pdksh) echo 0.
246           Same question goes for `test "" -eq 0' - does this generate an error
247           or, if not, what is the exit code?
248         - if a signal is received during the execution of a built-in,
249           does the builtin command exit or the whole shell?
250         - is it legal to execute last command of pipeline in current
251           execution environment (eg, can "echo foo | read bar" set
252           bar?)
253         - what action should be taken if there is an error doing a dup due
254           to system limits (eg, not enough file destriptors): is this
255           a "redirection error" (in which case a script will exit iff the
256           error occured while executing a special built-in)?
257           IMHO, shell should exit script.  Couldn't find a blanket statement
258           like "if shell encounters an unexpected system error, it shall
259           exit non-interactive scripts"...
261 POSIX sh bugs (references are to POSIX 1003.2-1992)
262         - in vi insert mode, ^W deletes to beginning of line or to the first
263           blank/punct character (para at line 9124, section 3).  This means
264           "foo     ^W" will do nothing.  This is inconsistent with the vi
265           spec, which says delete preceding word including and interceding
266           blanks (para at line 5189, section 5).
267         - parameter expansion, section 3.6.2, line 391: `in each case that a
268           value of word is needed (..), word shall be subjected to tilde
269           expansion, parameter expansion, ...'.  Various expansions should not
270           be performed if parameter is in double quotes.
271         - the getopts description says assigning OPTIND a value other than 1
272           produces undefined results, while the rationale for getopts suggests
273           saving/restoring the OPTIND value inside functions (since POSIX
274           functions don't do the save/restore automatically).  Restoring
275           OPTIND is kind of dumb since getopts may have been in the middle
276           of parsing a group of flags (eg, -abc).
277         - `...` definition (3.6.3) says nothing about backslash followed by
278           a newline, which sh and at&t ksh strip out completely.  e.g.,
279                 $ show-args `echo 'X
280                 Y'`
281                 Number of args: 1
282                         1: <XY>
283                 $
284           POSIX would indicate the backslash-newline would be preserved.
285         - does not say how "cat << ''" is to be treated (illegal, read 'til
286           blank line, or read 'til eof).  at&t ksh reads til eof, bourne shell
287           reads 'til blank line.  pdksh reads 'til blank line.