1$OpenBSD: NOTES,v 1.16 2018/01/12 14:20:57 jca Exp $ 2 3General 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 11 12Known 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). 34 35Known 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). 41 42Known 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. 79 80Known 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". 209 210Oddities 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. 242 243POSIX 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"... 260 261POSIX 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. 288