1RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.10 2020/10/01 22:59:12 tg Exp $ 2ToC: spelling 3Title: How do you spell <tt>mksh</tt>? How do you pronounce it? 4 5<p>This <a href="@@RELPATH@@mksh.htm">shell</a> is spelt either 6 “<tt>mksh</tt>” (with, even at the beginning of a sentence, <a 7 href="https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Capital_letters#Items_that_require_initial_lower_case">an 8 initial lowercase letter</a>; this is important) or “MirBSD Korn Shell”, 9 possibly with “the”.</p> 10<p>I usually pronounce it as “<span xml:lang="de-DE-1901">em-ka-es-ha</span>”, 11 that is, the letters individually in my native German, or say “MirBSD Korn 12 Shell”, although it is manageable, mostly for Slavic speakers, to actually 13 say “mksh” as if it were a word ☺</p> 14<p>Oh… I’ve run into this one, didn’t I? “MirBSD” is pronounced “<span 15 xml:lang="de-DE-1901">Mir-Be-Es-De</span>” germanically, for anglophones 16 “Mir-beas’tie” is fine.</p> 17---- 18ToC: sowhatismksh 19Title: I’m a $OS (<i>Android, OS/2, …</i>) user, so what’s mksh? 20 21<p>mksh is a so-called (Unix) “shell” or “command interpreter”, similar to 22 <tt>COMMAND.COM</tt>, <tt>CMD.EXE</tt> or PowerShell on other operating 23 systems you might know. Basically, it runs in a terminal (“console” or 24 “DOS box”) window, taking user input and running that as commands. It’s 25 also used to write so-called (shell) “script”s, short programs made by 26 putting several of those commands into a “batch file”.</p> 27<p>On Android, mksh is used as the system shell — basically, the one 28 running commands at system startup, in the background, and on user 29 behalf (but never of its own). Any privilege pop-ups you might <a 30 href="https://forum.xda-developers.com/showthread.php?t=1963976">be 31 encountering</a> are therefore <a 32 href="https://forum.xda-developers.com/showpost.php?p=33550523&postcount=1553">not 33 caused by mksh</a> but by some other code invoking mksh to do something 34 on its behalf.</p> 35---- 36ToC: os2 37Title: I’m an OS/2 user, what else do I need to know? 38 39<p>Unlike the native command prompt, the current working directory is, 40 for security reasons common on Unix systems which the shell is designed 41 for, not in the search path at all; if you really need this, run the 42 command <tt>PATH=.$PATHSEP$PATH</tt> or add that to a suitable 43 initialisation file (<tt>~/.mkshrc</tt>).</p> 44<p>There are two different newline modes for mksh-os2: standard (Unix) 45 mode, in which only LF (0A hex) is supported as line separator, and 46 “textmode”, which also accepts ASCII newlines (CR+LF), like most other 47 tools on OS/2, but creating an incompatibility with standard mksh. If 48 you compiled mksh from source, you will get the standard Unix mode unless 49 <tt>-T</tt> is added during compilation; however, you will most likely 50 have gotten this shell through komh’s port on Hobbes, or from his OS/2 51 Factory on eComStation Korea, which uses “textmode”, though. Most OS/2 52 users will want to use “textmode” unless they need absolute compatibility 53 with Unix mksh and other Unix shells and tools.</p> 54---- 55ToC: kornshell 56Title: How does this relate to ksh or the Korn Shell? 57 58<p>The Korn Shell (AT&T ksh) was authored by David Korn; two major 59 flavours exist (ksh88 and ksh93), the latter having been maintained 60 until 2012 (last formal release) and 2014 (last beta snapshot, buggy). 61 A ksh86 did exist.</p> 62<p>There’s now <tt>ksh2020</tt>, a project having restarted development 63 around November 2017 forking the last <tt>ksh93 v-</tt> (beta) snapshot 64 and continuing to develop it, presented at FOSDEM.</p> 65<p>AT&T ksh88 is “the (original) Korn Shell”. Other implementations, 66 of varying quality (MKS Toolkit’s MKS ksh being named as an example of 67 the lower end, MirBSD’s mksh at the upper end). They are all <em>not</em> 68 “Korn Shell” or “ksh”. However, mksh got blessed by David Korn, as long 69 as it cannot be confused with the original Korn Shell.</p> 70<p>The POSIX shell standard, while lacking most Korn Shell features, was 71 largely based on AT&T ksh88, with some from the Bourne shell.</p> 72<p>mksh is the currently active development of what started as the Public 73 Domain Bourne Shell in the mid-1980s with ksh88-compatibl-ish extensions 74 having been added later, making the Public Domain Korn Shell (pdksh), 75 which, while never officially blessed, was the only way for most to get 76 a Korn Shell-like command interpreter for AT&T’s was proprietary, 77 closed-source code for a very long time. pdksh’s development ended in 78 1999, with some projects like Debian and NetBSD® creating small bug fixes 79 (which often introduced new bugs) as part of maintenance. Around 2003, 80 OpenBSD started cleaning up their shipped version of pdksh, removing old 81 and compatibility code and modernising it. In 2002, development of what 82 is now mksh started as the system shell of MirBSD, which took over almost 83 all of OpenBSD’s cleanup, adding compatibility to other operating systems 84 back on top of it, and after 2004, independent, massive development of 85 bugfixes including a complete reorganisation of the way the parser works, 86 and of new features both independent and compatible with other shells 87 (ksh93, GNU bash, zsh, BSD csh) started and was followed by working with 88 the group behind POSIX to fix issues both in the standard and in mksh. 89 mksh became the system shell in several other operating systems and Linux 90 distributions and Android and thus is likely the Korn shell, if not Unix 91 shell, flavour with the largest user base. It has replaced pdksh in all 92 contemporary systems except QNX, NetBSD® and OpenBSD (who continue to 93 maintain their variant on “low flame”).</p> 94<p>dtksh is the “Desktop Korn Shell”, a build of AT&T ksh93 with some 95 additional built-in utilities for graphics programming (windows, menu 96 bars, dialogue boxes, etc.) utilising Motif bindings.</p> 97<p>MKS ksh is a proprietary reimplemention aiming for, but not quite 98 getting close to, ksh88 compatibility.</p> 99<p>SKsh is an AmigaOS-specific Korn Shell-lookalike by Steve Koren.</p> 100<p>The <a href="@@RELPATH@@ksh-chan.htm">Homepage of the <tt>#ksh</tt> 101 channel on Freenode IRC</a> contains more information about the Korn 102 Shell in general and its flavours.</p> 103---- 104ToC: packaging 105Title: How should I package mksh? (common cases) 106 107<p>Export a few environment variables, namely <tt>CC</tt> (the C compiler), 108 <tt>CPPFLAGS</tt> (all C præprocessor definitions), <tt>CFLAGS</tt> (only 109 compiler flags, <em>no</em> <tt>-Dfoo</tt> or anything!), <tt>LDFLAGS</tt> 110 (for anything to pass to the C compiler while linking) and <tt>LIBS</tt> 111 (appended to the linking command line after everything else. You might 112 wish to <tt>export LDSTATIC=-static</tt> for a static build as well.</p> 113<p>When cross-compiling, <tt>CC</tt> is the <em>cross</em> compiler (mksh 114 currently does not require a compiler targetting the build system), but 115 you <em>must</em> also export <tt>TARGET_OS</tt> to whatever system you 116 are compiling for, e.g. “Linux”. For most operating systems, that’s just 117 the uname(1) output. Some very rare systems also need <tt>TARGET_OSREV</tt>; 118 consult the source code of <tt>Build.sh</tt> for details.</p> 119<p>Create two subdirectories, say <tt>build-mksh</tt> and <tt>build-lksh</tt>. 120 In each of them, start a compilation by issuing <tt>sh ../Build.sh -r</tt> 121 followed by running the testsuite<a href="#packaging-fn1">¹</a> via 122 <tt>./test.sh</tt>. For lksh(1) add <tt>-DMKSH_BINSHPOSIX</tt> to 123 <tt>CPPFLAGS</tt> and use <tt>sh ../Build.sh -r -L</tt> to compile.</p> 124<p>See <a href="#testsuite-fails">below</a> if the testsuite fails.</p> 125<p>Install <tt>build-mksh/mksh</tt> as <tt>/bin/mksh</tt> (or similar), 126 <tt>build-lksh/lksh</tt> as <tt>/bin/lksh</tt> with a symlink(7) to it 127 from <tt>/bin/sh</tt> (if desred), and <tt>mksh.1</tt> and <tt>lksh.1</tt> 128 as manpages (mdoc macropackage required). Install <tt>dot.mkshrc</tt> 129 either as <tt>/etc/skel/.mkshrc</tt> (meaning your users will have to 130 manually resynchronise their home directories’ copies after every package 131 upgrade) or as <tt>/etc/mkshrc</tt>, in which case you install a <a 132 href="https://evolvis.org/plugins/scmgit/cgi-bin/gitweb.cgi?p=alioth/mksh.git;a=blob;f=debian/.mkshrc;hb=HEAD">redirection 133 script like Debian’s</a> into <tt>/etc/skel/.mkshrc</tt>. You may need a <a 134 href="@@RELPATH@@TaC-mksh.txt">summary of the licence information</a>.</p> 135<p>At runtime, the presence of <tt>/bin/ed</tt> as default history editor 136 is recommended, as well as a manpage formatter; you can also install 137 preformatted manpages from <tt>build-*ksh/*ksh.cat1</tt> if nroff(1) (or 138 <tt>$NROFF</tt>) is available at build time by removing the <tt>-r</tt> 139 flag from either <tt>Build.sh</tt> invocation.</p> 140<p>Some shell features require the ability to create temporary files and 141 FIFOS (cf. mkfifo(2))/pipes at runtime. Set <tt>TMPDIR</tt> to a suitable 142 location if <tt>/tmp</tt> isn’t it; if this is known ahead of time, you 143 can add <tt>-DMKSH_DEFAULT_TMPDIR=\"/path/to/tmp\"</tt> to CPPFLAGS. We 144 currently are unable to determine one on Android because its bionic libc 145 does not expose any method suitable to do so in the generic case.</p> 146<p id="packaging-fn1">① To run the testsuite, ed(1) must be available as 147 <tt>/bin/ed</tt>, and perl(1) is needed. When cross-compiling, the version 148 of the first <tt>ed</tt> binary on the <tt>PATH</tt> <em>must</em> be the 149 same as that in the target system on which the tests are to be run, in 150 order to be able to detect which flavour of ed to adjust the tests for. 151 Busybox ed is broken beyond repair, and all three ed-related tests will 152 always fail with it.</p> 153---- 154ToC: mkshrc 155Title: How does mksh load configuration files? 156 157<p>The shell loads first <tt>/etc/profile</tt> then <tt>~/.profile</tt> 158 if called as login shell or with the <tt>-l</tt> flag, then loads the file 159 <tt>$ENV</tt> points to (defaulting to <tt>~/.mkshrc</tt>) for interactive 160 shells (that includes login shells).</p> 161<p>Distributors should take care to either install the <tt>dot.mkshrc</tt> 162 example provided into <tt>/etc/skel/.mkshrc</tt> (so that it’s available 163 for newly created user accounts) and ensure it can propagate to existing 164 accounts or, if upgrading these is difficult, install the shipped file 165 as, for example, <tt>/etc/mkshrc</tt> and install a skeleton file, such 166 as the one in Debian, that sources the file in <tt>/etc</tt>.</p> 167<p>It’s vital that users can change the configuration, so do not force a 168 root-provided config file onto them; the shipped file, after all, is just 169 an example.</p> 170<p>If you need central user and configuration management and cannot use 171 something that installs skeleton files upon home directory creation 172 (like pam_mkhomedir), you can <tt>export ENV</tt> in <tt>/etc/profile</tt> 173 to a file (say <tt>/etc/shellrc</tt>) that sources the per-shell file. 174 Users can, this way, still override it by setting a different <tt>$ENV</tt> 175 in their <tt>~/.profile</tt>.</p> 176---- 177ToC: testsuite-fails 178Title: The testsuite fails! 179 180<p>The mksh testsuite has uncovered numerous bugs in operating systems 181 (kernels, libraries), compilers and toolchains. It is likely that you 182 just ran into one. If you’re using LTO (the <tt>Build.sh</tt> option 183 <tt>-c lto</tt>) try to disable it first — especially GCC is a repeat 184 offender breaking LTO and its antecessor <tt>-fwhole-program --combine</tt> 185 and tends to do wrong code generation quite a bit. Otherwise, try 186 lowering the optimisation levels, bisecting, etc.</p> 187---- 188ToC: selinux-androidiocy 189Title: I forbid stat(2) in my SELinux policy, and some things do not work! 190 191Don’t break Unix. Read up on the GIGO principle. Duh. 192---- 193ToC: makefile 194Title: Why doesn’t this use a Makefile to build? 195 196<p>Not all supported target operating environments have a make utility 197 available, and shell was required for “mirtoconf” (like autoconf) 198 already anyway, so it was chosen to run the make part as well.</p> 199<p>You can, however, add the <tt>-M</tt> flag to your <tt>Build.sh</tt> 200 invocations to let it produce a <tt>Makefrag.inc</tt> file <em>tailored 201 for this specific build</em> which you can then include in a Makefile, 202 such as with the BSD make(1) “.include” command or <a 203 href="https://www.gnu.org/software/make/manual/make.html#Include">GNU 204 make</a> equivalent. It even contains, for the user to start out with, 205 a commented-out example of how to do that in the most basic manner.</p> 206---- 207ToC: oldbsd 208Title: Why do other BSDs and QNX still use pdksh instead of mksh? 209 210<p>Some systems are resistant to change, mostly due to bikeshedding 211 (some people would, for example, rather see all shells banned to 212 ports/pkgsrc®) and hysterial raisins (historical reasons ☻). Most 213 BSDs have mksh packages available, and it works on all of them and 214 QNX just fine.</p> 215<p>In fact, on all of these systems, you can replace their 1999-era 216 <tt>/bin/ksh</tt> (which is a pdksh) with mksh. On at least NetBSD® 217 1.6 and up (not 1.5) and OpenBSD, even <tt>/bin/sh</tt> is fair game.</p> 218<p>MidnightBSD notably has adopted mksh as system shell (thanks laffer1).</p> 219---- 220ToC: openbsd 221Title: Why is there no mksh in OpenBSD’s ports tree? 222 223OpenBSD don’t like people who fork off their project at all; heck, 224they don’t even like the people they themselves forked off (NetBSD®). 225Several people tried over the years to get one committed, but nobody 226dared so as to not lose their commit bit. If you try, succeed, and 227survive Theo, however, kudos to you! See also <a href="#oldbsd">the 228“other BSDs” FAQ entry</a>. 229---- 230ToC: book 231Title: I’d like an introduction. 232 233Unfortunately, nobody has written a book about mksh yet, although 234other shells have received (sometimes decent) attention from authors 235and publishers. This FAQ lists a subset of things packagers and 236generic people ask, and the mksh(1) manpage is more of a reference, 237so you are probably best off starting with a shell-agnostic, POSIX 238or ksh88 reference such as the first edition (the second one deals 239with ksh93 which differs far more from mksh than ksh88, as ancient 240as it is, does) of the O’Reilly book (⚠ disclaimer: only an example, 241not a recommendation) and going forward by reading scripts (the 242“shellsnippets” repository referenced in the <tt>#ksh</tt> channel 243homepage (see the top of this document) has many examples) and 244trying to understand them and the mksh specifics from the manpage. 245---- 246ToC: ps1conv 247Title: My prompt from <<i>some other shell</i>> does not work! 248 249<a href="#contact">Contact</a> us on the mailing list or on IRC, 250we’ll convert it for you. Also have a look at the PS1 section in 251the mksh(1) manpage (search for “otherwise unused char”, e.g. with 252<tt>/</tt> in less(1), to spot it quickly). 253---- 254ToC: ps1weird 255Title: My prompt is weird! 256 257<p>There are several reasons why your <tt>PS1</tt> might be not 258 what you’d expect:</p><ul> 259<li><tt>$PS1</tt> is <tt>export</tt>ed. <strong>Do not export PS1!</strong> 260 (This was agreed upon as suggestion in a discussion between bash, zsh and 261 Korn shell developers.) The feature set of different shells vastly differs 262 and each shell should use its default PS1 or from its startup files.</li> 263<li><tt>$ENV</tt> <a href="#env">is set and/or <tt>export</tt>ed</a>.</li> 264<li>Your prompt is just “<tt># </tt>”: you’re entering a root shell, and 265 <tt>$PS1</tt> does not contain the ‘#’ character, in which case the shell 266 forces this prompt, making extra privileges obvious.</li> 267<li>Your prompt is just “<tt>$ </tt>”: perhaps your system administrator 268 did not install the shipped <tt>dot.mkshrc</tt> file, or you did not copy 269 <tt>/etc/skel/.mkshrc</tt> into your home directory (perhaps it was created 270 before <tt>mksh</tt> was installed?). Without another idea for a fix, get <a 271 href="http://www.mirbsd.org/cvs.cgi/~checkout~/src/bin/mksh/dot.mkshrc?rev=HEAD;content-type=text%2Fplain">this 272 file</a> and store it as <tt>~/.mkshrc</tt> then run <tt>mksh</tt>; this 273 will at the very least install our sample (“user@host:path $ ”) prompt.</li> 274<li>Your prompt contains things like “\u” or “\w”: it is for another shell 275 and <a href="#ps1conv">needs converting</a>.</li> 276<li>Your prompt contains colours, and when the command line is long the 277 cursor position or screen contents, especially using the history, is off: 278 terminal escapes must be escaped from the shell; check the PS1 section in 279 the manpage: search for “otherwise unused char” (see above).</li> 280<li>If the prompt doesn’t leave enough space on the right, the shell inserts 281 a line break after it when rendering.</li> 282</ul> 283---- 284ToC: env 285Title: On startup files and <tt>$ENV</tt> across and detecting various shells 286 287Interactive shells look at <tt>~/.mkshrc</tt> (or <tt>/system/etc/mkshrc</tt> 288on Android and <tt>/etc/mkshrc</tt> on FreeWRT and OpenWrt) by default. This 289location can, however, be overridden by setting the <tt>ENV</tt> environment 290variable. (FreeBSD is rumoured to set it in their system profile.) It’s better 291to not set <tt>$ENV</tt> if possible and let every shell user their native 292startup files; otherwise, you must ensure that it runs under all shells. Check 293<tt>$BASH_VERSION</tt> (GNU bash), <tt>$KSH_VERSION</tt> (contains “LEGACY KSH” 294or “MIRBSD KSH” for mksh, “PD KSH” for ancient mirbsdksh/oksh/pdksh, “Version” 295for ksh93); <tt>$NETBSD_SHELL</tt> (NetBSD ash); <tt>POSH_VERSION</tt> (posh, a 296pdksh derivative); <tt>$SH_VERSION</tt> (“PD KSH” as sh), <tt>$YASH_VERSION</tt> 297(yash), <tt>$ZSH_VERSION</tt> (or if <tt>$VERSION</tt> begins with “zsh”); a <a 298href="@@RELPATH@@ksh-chan.htm#which-shell">list of more approaches</a> exists. 299---- 300ToC: ctrl-x-e 301Title: Multiline command editing 302 303<p>mksh is very independent of the terminal and external libraries and 304 databases, such as termcap, and therefore is conservative in which ANSI 305 control codes are sent to the terminal.</p> 306<p>For this reason, mksh’s input line editing uses a “windowed one-line” 307 concept: the line the cursor is on is a “window” into the whole input, 308 horizontally scrolled. Some other shells (that are much larger and have 309 more dependencies on external tooling) use a “multi-line” editing mode, 310 and users occasionally wish for this. It is on the long-term TODO, but 311 (due to the aforementioned implications) this is not trivial.</p> 312<p>One way to achieve multi-line editing is to <em>dis</em>able input 313 line editing: <tt>set +o emacs +o vi</tt><br />This will, however, lose 314 you all editing features: tab completion, cursor keys, history, etc.</p> 315<p>Another way, if you don’t need it all the time, is to use a function 316 that spawns your editor on the input line: press <tt>^Xe</tt> in the 317 default emacs mode or <tt>Esc + v</tt> in vi mode. Once you exit the 318 editor, whatever was written there is run; this includes the original 319 command line if you quit without saving, so request the editor to exit 320 nōn-zero (e.g. using jupp’s “abendjoe” command) to prevent execution. 321 This is <em>really</em> useful to write ad-hōc scripts as well.</p> 322---- 323ToC: ctrl-l-cls 324Title: ^L (Ctrl-L) does not clear the screen 325 326Use ^[^L (Escape+Ctrl-L) or rebind it:<br /> 327<tt>bind '^L=clear-screen'</tt> 328---- 329ToC: ctrl-u-pico 330Title: ^U (Ctrl-U) clears the entire line 331 332If it should only delete the line up to the cursor, use:<br /> 333<tt>bind -m ^U='^[0^K'</tt> 334---- 335ToC: cur-up-zsh 336Title: Cursor Up behaves differently from zsh 337 338Some shells make Cursor Up search in the history only for commands 339starting with what was already entered. mksh separates the shortcuts: 340Cursor Up goes up one command and PgUp searches the history as described 341above. You can, of course, rebind:<br /> 342<tt>bind '^XA=search-history-up'</tt> 343---- 344ToC: current 345Title: Can mksh set the title of the window according to the command running? 346 347There’s no such thing as “the command currently running”; consider 348pipelines and delays (<tt>cmd1 | (cmd2; sleep 3; cmd3) | cmd4</tt>). 349There is, however, a way to make the shell display the command <em>line</em> 350during the time it is executed; for testing, you will need to download <a 351href="https://evolvis.org/plugins/scmgit/cgi-bin/gitweb.cgi?p=shellsnippets/shellsnippets.git;a=blob;f=mksh/terminal-title;hb=HEAD">this 352script</a> and <tt>source</tt> it. For merging into your <tt>~/.mkshrc</tt> 353you should first understand how it works: lines 4–18 set a <tt>PS1</tt> 354(prompt) equivalent to lines 84–96 of the stock <tt>dot.mkshrc</tt>, with 355one change: line 15 (<tt>print >/dev/tty …</tt>) is new, inserted just 356before the <tt>return</tt> command of the function substitution in the 357default prompt; this is what you’ll need to merge into your own, custom, 358prompt (if you have one; otherwise pull this adaption to the default 359one). Line 19 is the only other thing in this script rebinding the Ctrl-M 360key (which is normally produced by the Enter/Return key) to code that… 361does <em>something crazy</em>. This trick however <em>does funny things with 362multiline commands</em>, so if you type something out in multiple lines, 363for example <strong>here documents</strong> or <strong>loops</strong> press 364<strong>Ctrl-J instead of Enter/Return</strong> after <em>each</em> line 365including the first (at PS1) and final (at PS2) one. 366---- 367ToC: other-tty 368Title: How do I start mksh on a specific terminal? 369 370<p>Normally: <tt>mksh -T<i>/dev/tty2</i></tt></p> 371<p>However, if you want for it to return (e.g. for an embedded system rescue 372 shell), use this on your real console device instead: 373 <tt>mksh -T!<i>/dev/ttyACM0</i></tt></p> 374<p>mksh can also daemonise (send to the background): 375 <tt>mksh -T- -c 'exec cdio lock'</tt></p> 376---- 377ToC: completion 378Title: What about programmable tab completion? 379 380The shell itself provides static deterministic tab completion. 381However, you can use hooks like reprogramming the Tab key to a 382command line editor macro, and using the <tt>evaluate-region</tt> 383editor command (modulo a bugfix) together with <tt>quote-region</tt> and shell functions to 384implement a programmable completion engine. Multiple people have 385been considering doing so in our IRC channel; we’ll hyperlink to 386these engines when they are available. 387---- 388ToC: posix-mode 389Title: How POSIX compliant is mksh? Also, UTF-8 vs. locales? 390 391<p>You’ll need to use the <tt>lksh</tt> binary, unless your C <tt>long</tt> 392 type is 32 bits wide, for POSIX-compliant arithmetic in the shell. This is 393 because <tt>mksh</tt> provides consistent, wraparound-defined, 32-bit 394 arithmetics on all platforms normally. You’ll also need to enable POSIX mode 395 (<tt>set -o posix</tt>) explicitly, which also disables brace expansion upon 396 being enabled (use <tt>set -o braceexpand</tt> to reenable if needed).</p> 397<p>For the purpose of POSIX, mksh supports only the <tt>C</tt> locale. mksh’s 398 <tt>utf8-mode</tt> (which only supports the BMP (Basic Multilingual Plane) of 399 UCS and maps raw octets into the U+EF80‥U+EFFF wide character range; see 400 <tt>Arithmetic expressions</tt> in mksh(1) for details) <em>must</em> stay 401 disabled in POSIX mode (it is disabled upon enabling POSIX mode in R56+).</p> 402<p class="boxhead">The following POSIX sh-compatible code toggles the 403 <tt>utf8-mode</tt> option dependent on the current POSIX locale, for mksh 404 to allow using the UTF-8 mode, within the constraints outlined above, in 405 code portable across various shell implementations:</p> 406<div class="boxtext"> 407 <pre> 408 case ${KSH_VERSION:-} in 409 *MIRBSD KSH*|*LEGACY KSH*) 410 case ${LC_ALL:-${LC_CTYPE:-${LANG:-}}} in 411 *[Uu][Tt][Ff]8*|*[Uu][Tt][Ff]-8*) set -U ;; 412 *) set +U ;; 413 esac ;; 414 esac 415 </pre> 416</div><p class="boxfoot">In near future, (UTF-8) locale tracking will 417 be implemented, though.</p> 418<p>The shell is pretty close to POSIX, when run as <tt>lksh -o posix</tt> 419 under the "C" locale it is intended to match. It does not do everything 420 like other POSIX-compatible or ‑compliant shells, though.</p> 421---- 422ToC: function-local-scopes 423Title: What differences in function-local scopes are there? 424 425<p><tt>mksh</tt> has a different scope model from AT&T <tt>ksh</tt>, 426 which leads to subtle differences in semantics for identical builtins. 427 This can cause issues with a <tt>nameref</tt> to suddenly point to a 428 local variable by accident. (Other common shells share mksh’s scoping 429 model.)</p> 430<p class="boxhead">GNU <tt>bash</tt> allows unsetting local variables; in 431 <tt>mksh</tt>, doing so in a function allows back access to the global 432 variable (actually the one in the next scope up) with the same name. The 433 following code, when run before function definitions, changes the behaviour 434 of <tt>unset</tt> to behave like other shells (the alias can be removed 435 after the definitions):</p> 436<div class="boxtext"> 437 <pre> 438 case ${KSH_VERSION:-} in 439 *MIRBSD KSH*|*LEGACY KSH*) 440 function unset_compat { 441 \\builtin typeset unset_compat_x 442 443 for unset_compat_x in "$@"; do 444 eval "\\\\builtin unset $unset_compat_x[*]" 445 done 446 } 447 \\builtin alias unset=unset_compat 448 ;; 449 esac 450 </pre> 451</div><p class="boxfoot">When a local variable is created (e.g. using 452 <tt>local</tt>, <tt>typeset</tt>, <tt>integer</tt> or 453 <tt>\\builtin typeset</tt>) it does not, like in other shells, inherit 454 the value from the global (next scope up) variable with the same name; 455 it is rather created without any value (unset but defined).</p> 456---- 457ToC: regex-comparison 458Title: I get an error in this regex comparison 459 460<p>Use extglobs instead of regexes:<br /> 461 <tt>[[ foo =~ (foo|bar).*baz ]]</tt><br /> 462 … becomes…<br /> 463 <tt>[[ foo = *@(foo|bar)*baz* ]]</tt></p> 464---- 465ToC: trim-vector 466Title: ${@?}: bad substitution 467 468<p>In mksh, you cannot assign to or trim a vector (yet). For most 469 cases it is possible to write the affected code in a way avoiding 470 this extension; for example, trimming <tt>${@#foo}</tt> could be 471 applied to <tt>$1</tt> only and <tt>${@?}</tt> can be replaced 472 with a test whether <tt>$# -eq 0</tt>.</p> 473---- 474ToC: extensions-to-avoid 475Title: Are there any extensions to avoid? 476 477<p>GNU <tt>bash</tt> supports “<tt>&></tt>” (and “|&”) to redirect 478 both stdout and stderr in one go, but this breaks POSIX and Korn Shell syntax; 479 use POSIX redirections instead:</p> 480<table border="1" cellpadding="3"> 481 <tr><td>GNU bash</td><td> 482 <tt>foo |& bar |& baz &>log</tt> 483 </td></tr> 484 <tr><td>POSIX</td><td> 485 <tt>foo 2>&1 | bar 2>&1 | baz >log 2>&1</tt> 486 </td></tr> 487</table> 488---- 489ToC: while-read-pipe 490Title: Something is going wrong with my while...read loop 491 492<p class="boxhead">Most likely, you’ve encountered the problem in which 493 the shell runs all parts of a pipeline as subshell. The inner loop will 494 be executed in a subshell and variable changes cannot be propagated if 495 run in a pipeline:</p> 496<div class="boxtext"> 497 <pre> 498 bar | baz | while read foo; do ...; done 499 </pre> 500</div><p class="boxfoot">Note that <tt>exit</tt> in the inner loop will 501 also only exit the subshell and not the original shell. Likewise, if the 502 code is inside a function, <tt>return</tt> in the inner loop will only 503 exit the subshell and won’t terminate the function.</p> 504<p class="boxhead">Use co-processes instead:</p> 505<div class="boxtext"> 506 <pre> 507 bar | baz |& 508 while read -p foo; do ...; done 509 exec 3>&p; exec 3>&- 510 </pre> 511</div><p class="boxfoot">If <tt>read</tt> is run in a way such as 512 <tt>while read foo; do ...; done</tt> then leading whitespace will be 513 removed (IFS) and backslashes processed. You might want to use 514 <tt>while IFS= read -r foo; do ...; done</tt> for pristine I/O.</p> 515<p class="boxhead">Similarly, when using the <tt>-a</tt> option, use of the 516 <tt>-r</tt> option might be prudent (<tt>read -raN-1 arr <file</tt>); 517 the same applies for NUL-terminated lines:</p> 518<div class="boxtext"> 519 <pre> 520 find . -type f -print0 |& \ 521 while IFS= read -d '' -pr filename; do 522 print -r -- "found <${filename#./}>" 523 done 524 </pre> 525</div> 526---- 527ToC: command-alias 528Title: “command” doesn’t expand aliases as in ksh93 529 530This is because AT&T ksh93 ships a predefined alias enabling this:<br /> 531<tt>alias command='command '</tt><br /> 532put this into your <tt>~/.mkshrc</tt> 533(note the space before the closing single quote) 534---- 535ToC: builtin-rename 536Title: “rename” doesn’t work as expected! 537 538<p>There’s a <tt>rename</tt> built-in utility in mksh, which is a very 539 thin wrapper around the rename(2) syscall. It receives two pathnames, 540 source and destination where the first is then atomically renamed to 541 the latter. It does not move, i.e. fails for different filesystems.</p> 542<p>The GNU package <tt>util-linux</tt> has a different <tt>rename</tt> 543 command. If you wish to invoke an external utility (in favour over a 544 builtin), you can use <tt>dot.mkshrc</tt>’s function <tt>enable</tt> 545 or put the following into your <tt>~/.mkshrc</tt>:</p> 546<pre>alias rename="$(whence -p rename)"</pre> 547---- 548ToC: builtin-sleep 549Title: “sleep” does not accept ‘m’ for minutes! 550 551<p>mksh contains a <tt>sleep</tt> built-in utility, in order to be 552 able to offer sub-second sleep to shell scripts for most platforms. 553 (It does not exist if the platform lacks select(2) — which should 554 be rare.)</p> 555<p>GNU coreutils contains a sleep implementation accepting suffixed 556 numbers. If you wish to invoke an external utility (in favour over a 557 builtin), you can use <tt>dot.mkshrc</tt>’s function <tt>enable</tt> 558 or put something along the following lines into <tt>~/.mkshrc</tt>:</p> 559<pre>alias sleep="$(whence -p sleep)"</pre> 560<pre>timer() { sleep $(($1*60${2:++$2})); } # timer mins [secs]</pre> 561<pre>timer() { 562 local arg=${1/m/'*60+'} 563 [[ $arg = *+ ]] && arg+=0 564 sleep $(($arg) 565}</pre> 566---- 567ToC: string-concat 568Title: “+=” behaves differently from other shells 569 570<p>In POSIX shell, “=” in code like <tt>var=content</tt> is a string 571 assignment, always. You can use <tt>var=$((content))</tt> for an 572 arithmetic assignment that mostly uses C language rules.</p> 573<p>It stands to consider that the common shell extension “+=” as in 574 <tt>var+=content</tt> would always do string concatenation; it does 575 in mksh, but not in some other shells, in which, when <tt>var</tt> has 576 been declared integer, addition is done instead.</p> 577<p>You can make the code portable by using “((…))” (a.k.a. <tt>let</tt>) 578 instead: <tt>(( var += content ))</tt> does arithmetic addition in 579 all shells involved.</p> 580---- 581ToC: set-e 582Title: I use “set -e” and my code unexpectedly errors out 583 584<p>I personally recommend people to not use “<tt>set -e</tt>”, as it 585makes error handling more difficult. However, some insist. There have 586been bugfixes (relative to e.g. oksh/loksh and posh) in this aspect, 587and the user has to make sure <tt>$?</tt> is always 0 ASAP even after 588a command that doesn’t check it.</p> 589<pre>istwo() { 590 for i in "$@"; do 591 test x"$i" = x"2" && echo two 592 done 593} 594set -e 595istwo 1 596echo END</pre> 597<p>This can be fixed by either adding an explicit “<tt>:</tt>” (or 598“<tt>true</tt>”) after the comparison, or even…</p> 599<pre>test x"$i" = x"2" && echo two || :</pre> 600<p>… or right after the <tt>done</tt> inside the function, but…</p> 601<pre>test x"$i" != x"2" || echo two</pre> 602<p>… negating the condition and using “<tt>||</tt>” is preferable.</p> 603 604<p>Remember that Korn shell-style functions (with <tt>function</tt> 605 keyword and <strong>without</strong> parenthesēs) in AT&T ksh93 606 and mksh R51 and up have their own shell option scope, but while…</p> 607<pre>function istwo { 608 set +e 609 … 610}</pre> 611<p>… might help in error handling, the return status of a function is 612 still the last errorlevel inside, so an explicit true (“<tt>:</tt>”) 613 or, more explicitly, “<tt>return 0</tt>” at its end is still needed 614 if the <em>caller</em> runs under <tt>set -e</tt>.</p> 615---- 616ToC: set-eo-pipefail 617Title: I use “set -eo pipefail” and my code unexpectedly errors out 618 619<p class="boxhead">Related to the above FAQ entry, using 620 <tt>set -o pipefail</tt> makes the following construct error out:</p> 621<div class="boxtext"> 622 <pre> 623 set -e 624 for x in 1 2; do 625 false && echo $x 626 done | cat 627 </pre> 628</div><p class="boxfoot">This is because, while the <tt>&&</tt> 629 ensures that the inner command’s failure is not taken, it sets the entire 630 <tt>for</tt>‥<tt>done</tt> loop’s errorlevel, which is passed on by 631 <tt>-o pipefail</tt>.</p> 632<p>Invert the inner command:<br /> 633 <tt>true || echo $x</tt></p> 634---- 635ToC: faq 636Title: My question is not answered here! 637 638Do read the mksh(1) manual page. You might also wish to read the <a 639 href="@@RELPATH@@ksh-chan.htm">homepage of the <tt>#ksh</tt> IRC channel 640on Freenode</a> which lists several resources for Korn or POSIX-compatible 641shells in general. Or, <a href="#contact">contact</a> us (developer and 642users), for example via IRC. 643---- 644ToC: contact 645Title: How do I contact you (to say thanks)? 646 647You can say hi in the <tt>#!/bin/mksh</tt> channel on Freenode <a 648 href="@@RELPATH@@irc.htm">IRC</a>, although a <a 649 href="@@RELPATH@@danke.htm">donation</a> wouldn’t be amiss ☺ The <a 650 href="http://www.mail-archive.com/miros-mksh@mirbsd.org/">mailing 651list</a> can also be used. 652---- 653