• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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 &lt;<i>some other shell</i>&gt; 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 &gt;/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&amp;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>&amp;&gt;</tt>” (and “|&amp;”) 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 |&amp; bar |&amp; baz &amp;&gt;log</tt>
483 </td></tr>
484 <tr><td>POSIX</td><td>
485  <tt>foo 2&gt;&amp;1 | bar 2&gt;&amp;1 | baz &gt;log 2&gt;&amp;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 |&amp;
508	while read -p foo; do ...; done
509	exec 3&gt;&amp;p; exec 3&gt;&amp;-
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 &lt;file</tt>);
517 the same applies for NUL-terminated lines:</p>
518<div class="boxtext">
519 <pre>
520	find . -type f -print0 |&amp; \
521	    while IFS= read -d '' -pr filename; do
522		print -r -- "found &lt;${filename#./}&gt;"
523	done
524 </pre>
525</div>
526----
527ToC: command-alias
528Title: “command” doesn’t expand aliases as in ksh93
529
530This is because AT&amp;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 = *+ ]] &amp;&amp; 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" &amp;&amp; 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" &amp;&amp; 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&amp;T ksh93
606 and mksh R51 and up have their own shell option scope, but while…</p>
607<pre>function istwo {
608        set +e
609610}</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 &amp;&amp; echo $x
626	done | cat
627 </pre>
628</div><p class="boxfoot">This is because, while the <tt>&amp;&amp;</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