1*10224b2fSjca$OpenBSD: NOTES,v 1.16 2018/01/12 14:20:57 jca Exp $ 27cb960a2Sdownsj 33b015934SmillertGeneral features of at&t ksh88 that are not (yet) in pdksh: 43b015934Smillert - exported aliases and functions (not in ksh93). 57cb960a2Sdownsj - set -t. 67cb960a2Sdownsj - signals/traps not cleared during functions. 77cb960a2Sdownsj - trap DEBUG, local ERR and EXIT traps in functions. 8f00c5086Smillert - ERRNO parameter. 9b9f1c854Sdavid - read/select aren't hooked in to the command line editor 10dcacb757Sdownsj - the last command of a pipeline is not run in the parent shell 117cb960a2Sdownsj 12*10224b2fSjcaKnown bugs (see also PROJECTS files): 137cb960a2Sdownsj Variable parsing, Expansion: 147cb960a2Sdownsj - some specials behave differently when unset (eg, IFS behaves like 157055cce3Sdownsj " \t\n") others lose their special meaning. IFS/PATH taken care of, 167cb960a2Sdownsj still need to sort out some others (eg, TMOUT). 177cb960a2Sdownsj Parsing,Lexing: 18f00c5086Smillert - line numbers in errors are wrong for nested constructs. Need to 197cb960a2Sdownsj keep track of the line a command started on (can use for LINENO 207cb960a2Sdownsj parameter as well). 217cb960a2Sdownsj - a $(..) expression nested inside double quotes inside another $(..) 227cb960a2Sdownsj isn't parsed correctly (eg, $(echo "foo$(echo ")")") ) 237cb960a2Sdownsj Commands,Execution: 247055cce3Sdownsj - setting special parameters that have side effects when 257055cce3Sdownsj changed/restored (ie, HISTFILE, OPTIND, RANDOM) in front 26*10224b2fSjca of a command (eg, HISTFILE=/foo/bar echo hi) affects the parent 277055cce3Sdownsj shell. Note that setting other (not so special) parameters 28*10224b2fSjca does not affect the parent shell. 297cb960a2Sdownsj - `echo hi | exec cat -n' causes at&t to exit, `exec echo hi | cat -n' 307cb960a2Sdownsj does not. pdksh exits for neither. Don't think POSIX requires 317cb960a2Sdownsj an exit, but not sure. 327cb960a2Sdownsj - `echo foo | read bar; echo $bar' prints foo in at&t ksh, nothing 33040161f7Smillert in pdksh (ie, the read is done in a separate process in pdksh). 347cb960a2Sdownsj 35945abdecSmillertKnown problems not caused by ksh: 36945abdecSmillert - after stoping a job, emacs/vi is not re-entered. Hitting return 37945abdecSmillert prints the prompt and everything is fine again. Problem (often 38945abdecSmillert involving a pager like less) is related to order of process 39945abdecSmillert scheduling (shell runs before `stop'ed (sub) processes have had a chance 40945abdecSmillert to clean up the screen/terminal). 41945abdecSmillert 427cb960a2SdownsjKnown differences between pdksh & at&t ksh (that may change) 437cb960a2Sdownsj - vi: 447cb960a2Sdownsj - `^U': at&t: kills only what has been inserted, pdksh: kills to 457cb960a2Sdownsj start of line 467cb960a2Sdownsj - at&t ksh login shells say "Warning: you have running jobs" if you 477cb960a2Sdownsj try to exit when there are running jobs. An immediate second attempt 487cb960a2Sdownsj to exit will kill the jobs and exit. pdksh does not print a warning, 497cb960a2Sdownsj nor does it kill running jobs when it exits (it does warn/kill for 507cb960a2Sdownsj stopped jobs). 517cb960a2Sdownsj - TMOUT: at&t prints warning, then waits another 60 seconds. If on screwed 527cb960a2Sdownsj up serial line, the output could cause more input, so pdksh just 537cb960a2Sdownsj prints a message and exits. (Also, in at&t ksh, setting TMOUT has no 547cb960a2Sdownsj effect after the sequence "TMOUT=60; unset TMOUT", which could be 557cb960a2Sdownsj useful - pdksh may do this in the future). 567cb960a2Sdownsj - in pdksh, if the last command of a pipeline is a shell builtin, it is 577cb960a2Sdownsj not executed in the parent shell, so "echo a b | read foo bar" does not 587cb960a2Sdownsj set foo and bar in the parent shell (at&t ksh will). 597cb960a2Sdownsj This may get fixed in the future, but it may take a while. 607cb960a2Sdownsj - in pdksh, set +o lists the options that are currently set, in at&t ksh 617cb960a2Sdownsj it is the same as set -o. 627cb960a2Sdownsj - in pdksh emacs mode, ^T does what gnu emacs does, not what at&t ksh 637cb960a2Sdownsj does. 64dcacb757Sdownsj - in ksh93, `. name' calls a function (defined with function) with POSIX 65dcacb757Sdownsj semantics (instead of ksh semantics). in pdksh, . does not call 66dcacb757Sdownsj functions. 677055cce3Sdownsj - test: "test -f foo bar blah" is the same as "test -f foo" (the extra 687055cce3Sdownsj arguments, of which there must be at least 2, are ignored) - pdksh 697055cce3Sdownsj generates an error message (unexpected operator/operand "bar") as it 707055cce3Sdownsj should. Sometimes used to test file globs (e.g., if test -f *.o; ...). 717055cce3Sdownsj - if the command 'sleep 5 && /bin/echo blah' is run interactively and 727055cce3Sdownsj is the sleep is stopped (^Z), the echo is run immediately in pdksh. 737055cce3Sdownsj In at&t ksh, the whole thing is stopped. 74f00c5086Smillert - LINENO: 75f00c5086Smillert - in ksh88 variable is always 1 (can't be changed) in interac mode; 76f00c5086Smillert in pdksh it changes. 77f00c5086Smillert - Value of LINENO after it has been set by the script in one file 78f00c5086Smillert is bizarre when used in another file. 797cb960a2Sdownsj 807cb960a2SdownsjKnown differences between pdksh & at&t ksh (that are not likely to change) 817cb960a2Sdownsj - at&t ksh seems to catch or ignore SIGALRM - pdksh dies upon receipt 827cb960a2Sdownsj (unless it's traped of course) 837cb960a2Sdownsj - typeset: 847cb960a2Sdownsj - at&t ksh overloads -u/-l options: for integers, means unsigned/long, 857cb960a2Sdownsj for strings means uppercase/lowercase; pdksh just has the 867cb960a2Sdownsj upper/lower case (which can be useful for integers when base > 10). 877cb960a2Sdownsj unsigned/long really should have their own options. 887cb960a2Sdownsj - at&t ksh can't have justified integer variables 897cb960a2Sdownsj (eg, typeset -iR5 j=10), pdksh can. 907cb960a2Sdownsj - in pdksh, number arguments for -L/-R/-Z/-i must follow the option 917cb960a2Sdownsj character, at&t allows it at the end of the option group (eg, 927cb960a2Sdownsj at&t ksh likes "typeset -iu5 j", pdksh wants "typeset -i5 -u j" 937cb960a2Sdownsj or "typeset -ui5 j"). Also, pdksh allows "typeset -i 5 j" (same 947cb960a2Sdownsj as "typeset -i5 j"), at&t ksh does not allow this. 957cb960a2Sdownsj - typeset -R: pdksh strips trailing space type characters (ie, 967cb960a2Sdownsj uses isspace()), at&t ksh only skips blanks. 977cb960a2Sdownsj - at&t ksh allows attributes of read-only variables to be changed, 987cb960a2Sdownsj pdksh allows only the export attribute to be set. 99dcacb757Sdownsj - (some) at&t ksh allows set -A of readonly variables, pdksh does not. 1007cb960a2Sdownsj - at&t ksh allows command assignments of readonly variables (eg, YY=2 cat), 1017cb960a2Sdownsj pdksh does not. 1027cb960a2Sdownsj - at&t ksh does not exit scripts when an implicit assignment to an integer 1037cb960a2Sdownsj variable fails due to an expression error: eg, 1047cb960a2Sdownsj echo 2+ > /tmp/x 1057cb960a2Sdownsj unset x; typeset -i x 1067cb960a2Sdownsj read x < /tmp/x 1077cb960a2Sdownsj echo still here 1087cb960a2Sdownsj prints an error and then prints "still here", similarly for 1097cb960a2Sdownsj unset x; typeset -i x 1107cb960a2Sdownsj set +A x 1 2+ 3 1117cb960a2Sdownsj echo still here 1127cb960a2Sdownsj and 1137cb960a2Sdownsj unset x y; typeset -i x y; set +A y 10 20 30 1147cb960a2Sdownsj set +A x 1 1+y[2+] 3 1157cb960a2Sdownsj echo still here 1167cb960a2Sdownsj pdksh exits a script in all the above cases. (note that both shells 1177cb960a2Sdownsj exit for: 1187cb960a2Sdownsj unset x; typeset -i x 1197cb960a2Sdownsj for x in 1 2+ 3; do echo x=$x; done 1207cb960a2Sdownsj echo still here 1217cb960a2Sdownsj ). 1227cb960a2Sdownsj - at&t ksh seems to allow function calls inside expressions 1237cb960a2Sdownsj (eg, typeset -i x='y(2)') but they do not seem to be regular functions 1247cb960a2Sdownsj nor math functions (eg, pow, exp) - anyone known anything about this? 1257cb960a2Sdownsj - `set -o nounset; unset foo; echo ${#foo}`: at&t ksh prints 0; pdksh 1267cb960a2Sdownsj generates error. Same for ${#foo[*]} and ${#foo[@]}. 1277cb960a2Sdownsj - . file: at&t ksh parses the whole file before executing anything, 1287cb960a2Sdownsj pdksh executes as it parses. This means aliases defined in the file 1297cb960a2Sdownsj will affect how pdksh parses the file, but won't affect how at&t ksh 130fe2ad28bSjmc parses the file. Also means pdksh will not parse statements occurring 1317cb960a2Sdownsj after a (executed) return statement. 1327cb960a2Sdownsj - a return in $ENV in at&t ksh will cause the shell to exit, while in 1337cb960a2Sdownsj pdksh it will stop executing the script (this is consistent with 1347cb960a2Sdownsj what a return in .profile does in both shells). 1357cb960a2Sdownsj - at&t ksh does file globbing for `echo "${foo:-"*"}"`, pdksh does not 1367cb960a2Sdownsj (POSIX would seem to indicate pdksh is right). 1377cb960a2Sdownsj - at&t ksh thinks ${a:##foo} is ok, pdksh doesn't. 1387cb960a2Sdownsj - at&t does tilde expansion on here-document delimiters, pdksh does 1397cb960a2Sdownsj not. eg. 1407cb960a2Sdownsj $ cat << ~michael 1417cb960a2Sdownsj ~michael 1427cb960a2Sdownsj $ 1437cb960a2Sdownsj works for pdksh, not for at&t ksh (POSIX seems to agree with pdksh). 1447cb960a2Sdownsj - in at&t ksh, tracked aliases have the export flag implicitly set 1457cb960a2Sdownsj and tracked aliases and normal aliases live in the same name space 1467cb960a2Sdownsj (eg, "alias" will list both tracked and normal aliases). 1477cb960a2Sdownsj in pdksh, -t does not imply -x (since -x doesn't do anything yet), and 148040161f7Smillert tracked/normal aliases live in separate name spaces. 1497cb960a2Sdownsj in at&t ksh, alias accepts + options (eg, +x, +t) - pdksh does not. 1507cb960a2Sdownsj in pdksh, alias has a -d option to allow examination/changing of 1517cb960a2Sdownsj cached ~ entries, also unalias has -d and -t options (unalias -d 1527cb960a2Sdownsj is useful if the ~ cache gets out of date - not sure how at&t deals 1537cb960a2Sdownsj with this problem (it does cache ~ entries)). 1547cb960a2Sdownsj - at&t ksh will stop a recursive function after about 60 calls; pdksh 1557cb960a2Sdownsj will not since the limit is arbitrary and can't be controlled 1567cb960a2Sdownsj by the user (hit ^C if you get in trouble). 1577cb960a2Sdownsj - the wait command (with and without arguments) in at&t ksh will wait for 1587cb960a2Sdownsj stopped jobs when job control is enabled. pdksh doesn't. 1597cb960a2Sdownsj - at&t ksh automatically sets the bgnice option for interactive shells; 1607cb960a2Sdownsj pdksh does not. 1617cb960a2Sdownsj - in at&t ksh, "eval `false`; echo $?" prints 1, pdksh prints 0 (which 1627cb960a2Sdownsj is what POSIX says it should). Same goes for "wait `false`; echo $?". 1637cb960a2Sdownsj (same goes for "set `false`; echo $?" if posix option is set - some 1647cb960a2Sdownsj scripts that use the old getopt depend on this, so be careful about 1657cb960a2Sdownsj setting the posix option). 1667cb960a2Sdownsj - in at&t ksh, print -uX and read -uX are interrperted as -u with no 1677cb960a2Sdownsj argument (defaults to 1 and 0 respectively) and -X (which may or 1687cb960a2Sdownsj may not be a valid flag). In pdksh, -uX is interpreted as file 1697cb960a2Sdownsj descriptor X. 1707cb960a2Sdownsj - in at&t ksh, some signals (HUP, INT, QUIT) cause the read to exit, others 1717cb960a2Sdownsj (ie, everything else) do not. When it does cause exiting, anything read 1727cb960a2Sdownsj to that point is used (usually an empty line) and read returns with 0 1737cb960a2Sdownsj status. pdksh currently does similar things, but for TERM as well and 1747cb960a2Sdownsj the exit status is 128+<signal-number> - in future, pdksh's read will 1757cb960a2Sdownsj do this for all signals that are normally fatal as required by POSIX. 1767cb960a2Sdownsj (POSIX does not require the setting of variables to null so applications 1777cb960a2Sdownsj shouldn't rely on this). 1787cb960a2Sdownsj - in pdksh, ! substitution done before variable substitution; in at&t ksh 1797a3af63bStb it is done after substitution (and therefore may do ! substitutions on 1807cb960a2Sdownsj the result of variable substitutions). POSIX doesn't say which is to be 1817cb960a2Sdownsj done. 1827cb960a2Sdownsj - pwd: in at&t ksh, it ignores arguments; in pdksh, it complains when given 1837cb960a2Sdownsj arguments. 1847cb960a2Sdownsj - the at&t ksh does not do command substition on PS1, pdksh does. 185dcacb757Sdownsj - ksh93 allows ". foo" to run the function foo if there is no file 186dcacb757Sdownsj called foo (go figure). 187dcacb757Sdownsj - field splitting (IFS): ksh88/ksh93 strip leading non-white space IFS 188dcacb757Sdownsj chars, pdksh (and POSIX, I think) leave them intact. e.g. 189dcacb757Sdownsj $ IFS="$IFS:"; read x; echo "<$x>" 190dcacb757Sdownsj :: 191dcacb757Sdownsj prints "<>" in at&t ksh, "<::>" in pdksh. 192dcacb757Sdownsj - command completion: at&t ksh will do completion on a blank line (matching 193dcacb757Sdownsj all commands), pdksh does not (as this isn't very useful - use * if 194dcacb757Sdownsj you really want the list). 195dcacb757Sdownsj - co-processes: if ksh93, the write portion of the co-process output is 196dcacb757Sdownsj closed when the most recently started co-process exits. pdksh closes 197dcacb757Sdownsj it when all the co-processes using it have exited. 198040161f7Smillert - pdksh accepts empty command lists for while and for statements, while 199040161f7Smillert at&t ksh (and sh) don't. Eg., pdksh likes 200040161f7Smillert while false ; do done 201040161f7Smillert but ksh88 doesn't like it. 202945abdecSmillert - pdksh bumps RANDOM in parent after a fork, at&t ksh bumps it in both 203945abdecSmillert parent and child: 204945abdecSmillert RANDOM=1 205945abdecSmillert echo child: `echo $RANDOM` 206945abdecSmillert echo parent: $RANDOM 207945abdecSmillert will produce "child: 16838 parent: 5758" in pdksh, while at&t ksh 208945abdecSmillert will produce "child: 5758 parent: 5758". 2097cb960a2Sdownsj 2107cb960a2SdownsjOddities in ksh (pd & at&t): 2117cb960a2Sdownsj - array references inside (())/$(()) are strange: 2127cb960a2Sdownsj $(( x[2] )) does the expected, $(( $x[2] )) doesn't. 2137cb960a2Sdownsj - `typeset -R3 X='x '; echo "($X)"` produces ( x) - trailing 2147cb960a2Sdownsj spaces are stripped. 2157cb960a2Sdownsj - typeset -R turns off Z flag. 2167cb960a2Sdownsj - both shells have the following mis-feature: 2177cb960a2Sdownsj $ x='function xx { 2187cb960a2Sdownsj cat -n <<- EOF 2197cb960a2Sdownsj here we are in xx 2207cb960a2Sdownsj EOF 2217cb960a2Sdownsj }' 2227cb960a2Sdownsj $ (eval "$x"; (sleep 2; xx) & echo bye) 2237cb960a2Sdownsj [1] 1234 2247cb960a2Sdownsj bye 2257cb960a2Sdownsj $ xx: /tmp/sh1234.1: cannot open 2267cb960a2Sdownsj - bizarre special handling of alias/export/readonly/typeset arguments 2277cb960a2Sdownsj $ touch a=a; typeset a=[ab]; echo "$a" 2287cb960a2Sdownsj a=[ab] 2297cb960a2Sdownsj $ x=typeset; $x a=[ab]; echo "$a" 2307cb960a2Sdownsj a=a 2317cb960a2Sdownsj $ 2327cb960a2Sdownsj - both ignore SIGTSTP,SIGTTIN,SIGTTOU in exec'd processes when talking 2337cb960a2Sdownsj and not monitoring (at&t ksh kind of does this). Doesn't really make 2347cb960a2Sdownsj sense. 2357cb960a2Sdownsj (Note that ksh.att -ic 'set +m; check-sigs' shows TSTP et al aren't 2367cb960a2Sdownsj ignored, while ksh.att -ic 'set +m^J check-sigs' does... very strange) 2377cb960a2Sdownsj - when tracing (set -x), and a command's stderr is redirected, the trace 2387cb960a2Sdownsj output is also redirected. so "set -x; echo foo 2> /tmp/O > /dev/null" 2397cb960a2Sdownsj will create /tmp/foo with the lines "+ > /dev/null" and "+ echo foo". 240*10224b2fSjca - undocumented at&t ksh88, documented in ksh93: FPATH is searched 241*10224b2fSjca after PATH if no executable is found, even if typeset -uf wasn't used. 2427cb960a2Sdownsj 2437cb960a2SdownsjPOSIX sh questions (references are to POSIX 1003.2-1992) 2447cb960a2Sdownsj - arithmetic expressions: how are empty expressions treated? 2457cb960a2Sdownsj (eg, echo $(( ))). at&t ksh (and now pdksh) echo 0. 2467cb960a2Sdownsj Same question goes for `test "" -eq 0' - does this generate an error 2477cb960a2Sdownsj or, if not, what is the exit code? 2487cb960a2Sdownsj - if a signal is received during the execution of a built-in, 2497cb960a2Sdownsj does the builtin command exit or the whole shell? 2507cb960a2Sdownsj - is it legal to execute last command of pipeline in current 2517cb960a2Sdownsj execution environment (eg, can "echo foo | read bar" set 2527cb960a2Sdownsj bar?) 2537cb960a2Sdownsj - what action should be taken if there is an error doing a dup due 25400c69fa2Sjca to system limits (eg, not enough file destriptors): is this 25596315c49Sfgsch a "redirection error" (in which case a script will exit iff the 2567cb960a2Sdownsj error occured while executing a special built-in)? 2577cb960a2Sdownsj IMHO, shell should exit script. Couldn't find a blanket statement 2587cb960a2Sdownsj like "if shell encounters an unexpected system error, it shall 2597cb960a2Sdownsj exit non-interactive scripts"... 2607cb960a2Sdownsj 2617cb960a2SdownsjPOSIX sh bugs (references are to POSIX 1003.2-1992) 2627cb960a2Sdownsj - in vi insert mode, ^W deletes to beginning of line or to the first 2637cb960a2Sdownsj blank/punct character (para at line 9124, section 3). This means 2647cb960a2Sdownsj "foo ^W" will do nothing. This is inconsistent with the vi 2657cb960a2Sdownsj spec, which says delete preceding word including and interceding 2667cb960a2Sdownsj blanks (para at line 5189, section 5). 2677cb960a2Sdownsj - parameter expansion, section 3.6.2, line 391: `in each case that a 2687cb960a2Sdownsj value of word is needed (..), word shall be subjected to tilde 2697cb960a2Sdownsj expansion, parameter expansion, ...'. Various expansions should not 2707cb960a2Sdownsj be performed if parameter is in double quotes. 2717cb960a2Sdownsj - the getopts description says assigning OPTIND a value other than 1 2727cb960a2Sdownsj produces undefined results, while the rationale for getopts suggests 2737cb960a2Sdownsj saving/restoring the OPTIND value inside functions (since POSIX 2747cb960a2Sdownsj functions don't do the save/restore automatically). Restoring 2757cb960a2Sdownsj OPTIND is kind of dumb since getopts may have been in the middle 2767cb960a2Sdownsj of parsing a group of flags (eg, -abc). 2777cb960a2Sdownsj - `...` definition (3.6.3) says nothing about backslash followed by 2787cb960a2Sdownsj a newline, which sh and at&t ksh strip out completely. e.g., 2797cb960a2Sdownsj $ show-args `echo 'X 2807cb960a2Sdownsj Y'` 2817cb960a2Sdownsj Number of args: 1 2827cb960a2Sdownsj 1: <XY> 2837cb960a2Sdownsj $ 2847cb960a2Sdownsj POSIX would indicate the backslash-newline would be preserved. 2857cb960a2Sdownsj - does not say how "cat << ''" is to be treated (illegal, read 'til 2867cb960a2Sdownsj blank line, or read 'til eof). at&t ksh reads til eof, bourne shell 2877cb960a2Sdownsj reads 'til blank line. pdksh reads 'til blank line. 288