mksh FAQ

Sponsored by
HostEurope Logo

mksh FAQ

MirBSD Korn Shell — frequently asked questions

This list is an (incomplete; feedback and patches welcome) attempt to answer questions that people often have about mksh, the MirBSD Korn Shell.

You might also wish to read the homepage of the #ksh IRC channel on Freenode which lists several resources for Korn or POSIX-compatible shells in general.

Table of contents

How do you spell mksh? How do you pronounce it?

The shell is spelt either “mksh” (with an initial lowercase letter, this is important) or “MirBSD Korn Shell”.

I usually pronounce it as “em-ka-es-ha”, that is, the letters individually in my native German, or say “MirBSD Korn Shell”, although it is manageable, mostly for Slavic speakers, to actually say “mksh” as if it were a word ☺

Oh… I’ve run into this one, didn’t I? “MirBSD” is pronounced “Mir-Be-Es-De” germanically, for anglophones “Mir-beas’tie” is fine.

I’m a $OS (Android, …) user, so what’s mksh?

mksh is a so-called (Unix) “shell” or “command interpreter”, similar to COMMAND.COM, CMD.EXE or PowerShell on other operating systems you might know. Basically, it runs in a terminal (“console” or “DOS box”) window, taking user input and running that as commands. It’s also used to write so-called (shell) “script”s, short programs made by putting several of those commands into a “batch file”.

On Android, mksh is used as the system shell — basically, the one running commands at system startup, in the background, and on user behalf (but never of its own). Any privilege pop-ups you might be encountering are therefore not caused by mksh but by some other code invoking mksh to do something on its behalf.

How does this relate to ksh or the Korn Shell?

The Korn Shell (AT&T ksh) was authored by David Korn; two major flavours exist (ksh88 and ksh93), the latter having been maintained until 2012 (last formal release) and 2014 (last beta snapshot), with development having been taken up by a third party around November 2017. A ksh86 did exist.

AT&T ksh88 is “the (original) Korn Shell”. Other implementations, of varying quality (MKS Toolkit’s MKS ksh being named as an example of the lower end, MirBSD’s mksh at the upper end). They are all not “Korn Shell” or “ksh”. However, mksh got blessed by David Korn, as long as it cannot be confused with the original Korn Shell.

The POSIX shell standard, while lacking most Korn Shell features, was largely based on AT&T ksh88, with some from the Bourne shell.

mksh is the currently active development of what started as the Public Domain Bourne Shell in the mid-1980s with ksh88-compatibl-ish extensions having been added later, making the Public Domain Korn Shell (pdksh), which, while never officially blessed, was the only way for most to get a Korn Shell-like command interpreter for AT&T’s was proprietary, closed-source code for a very long time. pdksh’s development ended in 1999, with some projects like Debian and NetBSD® creating small bug fixes (which often introduced new bugs) as part of maintenance. Around 2003, OpenBSD started cleaning up their shipped version of pdksh, removing old and compatibility code and modernising it. In 2002, development of what is now mksh started as the system shell of MirBSD, which took over almost all of OpenBSD’s cleanup, adding compatibility to other operating systems back on top of it, and after 2004, independent, massive development of bugfixes including a complete reorganisation of the way the parser works, and of new features both independent and compatible with other shells (ksh93, GNU bash, zsh, BSD csh) started and was followed by working with the group behind POSIX to fix issues both in the standard and in mksh. mksh became the system shell in several other operating systems and Linux distributions and Android and thus is likely the Korn shell, if not Unix shell, flavour with the largest user base. It has replaced pdksh in all contemporary systems except QNX, NetBSD® and OpenBSD (who continue to maintain their variant on “low flame”).

dtksh is the “Desktop Korn Shell”, a build of AT&T ksh93 with some additional built-in utilities for graphics programming (windows, menu bars, dialogue boxes, etc.) utilising Motif bindings.

MKS ksh is a proprietary reimplemention aiming for, but not quite getting close to, ksh88 compatibility.

SKsh is an AmigaOS-specific Korn Shell-lookalike by Steve Koren.

The Homepage of the #ksh channel on Freenode IRC contains more information about the Korn Shell in general and its flavours.

How should I package mksh? (common cases)

Export a few environment variables, namely CC (the C compiler), CPPFLAGS (all C præprocessor definitions), CFLAGS (only compiler flags, no -Dfoo or anything!), LDFLAGS (for anything to pass to the C compiler while linking) and LIBS (appended to the linking command line after everything else. You might wish to export LDSTATIC=-static for a static build as well.

When cross-compiling, CC is the cross compiler (mksh currently does not require a compiler targetting the build system), but you must also export TARGET_OS to whatever system you are compiling for, e.g. “Linux”. For most operating systems, that’s just the uname(1) output. Some very rare systems also need TARGET_OSREV; consult the source code of for details.

Create two subdirectories, say build-mksh and build-lksh. In each of them, start a compilation by issuing sh ../ -r followed by running the testsuite¹ via ./ For lksh(1) add -DMKSH_BINSHPOSIX to CPPFLAGS and use sh ../ -r -L to compile.

See below if the testsuite fails.

Install build-mksh/mksh as /bin/mksh (or similar), build-lksh/lksh as /bin/lksh with a symlink(7) to it from /bin/sh (if desred), and mksh.1 and lksh.1 as manpages (mdoc macropackage required). Install dot.mkshrc either as /etc/skel/.mkshrc (meaning your users will have to manually resynchronise their home directories’ copies after every package upgrade) or as /etc/mkshrc, in which case you install a redirection script like Debian’s into /etc/skel/.mkshrc. If you need a summary of the licence information, take it.

At runtime, the presence of /bin/ed as default history editor is recommended, as well as a manpage formatter; you can also install preformatted manpages from build-*ksh/*ksh.cat1 if nroff(1) (or $NROFF) is available at build time by removing the -r flag from either invocation.

Some shell features require the ability to create temporary files and FIFOS (cf. mkfifo(2))/pipes at runtime. Set TMPDIR to a suitable location if /tmp isn’t it; if this is known ahead of time, you can add -DMKSH_DEFAULT_TMPDIR=\"/path/to/tmp\" to CPPFLAGS. We currently are unable to determine one on Android because its bionic libc does not expose any method suitable to do so in the generic case.

① To run the testsuite, ed(1) must be available as /bin/ed, and perl(1) is needed. When cross-compiling, the version of the first ed binary on the PATH must be the same as that in the target system on which the tests are to be run, in order to be able to detect which flavour of ed to adjust the tests for. Busybox ed is broken beyond repair, and all three ed-related tests will always fail with it.

The testsuite fails!

The mksh testsuite has uncovered numerous bugs in operating systems (kernels, libraries), compilers and toolchains. It is likely that you just ran into one. If you’re using LTO (the option -c lto) try to disable it first — especially GCC is a repeat offender breaking LTO and its antecessor -fwhole-program --combine and tends to do wrong code generation quite a bit. Otherwise, try lowering the optimisation levels, bisecting, etc.

Why doesn’t this use a Makefile to build?

Not all supported target operating environments have a make utility available, and shell was required for “mirtoconf” (like autoconf) already anyway, so it was chosen to run the make part as well.

You can, however, add the -M flag to your invocations to let it produce a file tailored for this specific build which you can then include in a Makefile, such as with the BSD make(1) “.include” command or GNU make equivalent. It even contains, for the user to start out with, a commented-out example of how to do that in the most basic manner.

Why do other BSDs and QNX still use pdksh instead of mksh?

Some systems are resistent to change, mostly due to bikeshedding (some people would, for example, rather see all shells banned to ports/pkgsrc®) and hysterial raisins (historical reasons ☻). Most BSDs have mksh packages available, and it works on all of them and QNX just fine.

In fact, on all of these systems, you can replace their 1999-era /bin/ksh (which is a pdksh) with mksh. On at least NetBSD® 1.6 and up (not 1.5) and OpenBSD, even /bin/sh is fair game.

MidnightBSD notably has adopted mksh as system shell (thanks laffer1).

Why is there no mksh in OpenBSD’s ports tree?

OpenBSD don’t like people who fork off their project at all; heck, they don’t even like the people they themselves forked off (NetBSD®). Several people tried over the years to get one committed, but nobody dared so as to not lose their commit bit. If you try, succeed, and survive Theo, however, kudos to you! See also the “other BSDs” FAQ entry.

I’m an OS/2 user, what do I need to know?

This issue is discussed at more length in the FAQ section in the manpage. You can install plain mksh (usually by compiling it yourself) which behaves like one expects from a Unix shell in a Unix environment (LF line endings, binary mode file I/O, etc.) or “mksh-os2” from komh (binaries on Hobbes), which are built from the same source with the -T flag, enabling “textmode” to behave more similar to native applications (CR+LF line endings, text mode file I/O, etc).

I’d like an introduction.

Unfortunately, nobody has written a book about mksh yet, although other shells have received (sometimes decent) attention from authors and publishers. This FAQ lists a subset of things packagers and generic people ask, and the mksh(1) manpage is more of a reference, so you are probably best off starting with a shell-agnostic, POSIX or ksh88 reference such as the first edition (the second one deals with ksh93 which differs far more from mksh than ksh88, as ancient as it is, does) of the O’Reilly book (⚠ disclaimer: only an example, not a recommendation) and going forward by reading scripts (the “shellsnippets” repository referenced in the #ksh channel homepage (see the top of this document) has many examples) and trying to understand them and the mksh specifics from the manpage.

My prompt from <some other shell> does not work!

Contact us on the mailing list or on IRC, we'll convert it for you. Also have a look at the PS1 section in the mksh(1) manpage (search for “otherwise unused char”, e.g. with / in less(1), to spot it quickly).

Can mksh set the title of the window according to the command running?

There’s no such thing as “the command currently running”; consider pipelines and delays (cmd1 | (cmd2; sleep 3; cmd3) | cmd4). There is, however, a way to make the shell display the command line during the time it is executed; for testing, you will need to download this script and source it. For merging into your ~/.mkshrc you should first understand how it works: lines 4–18 set a PS1 (prompt) equivalent to lines 84–96 of the stock dot.mkshrc, with one change: line 15 (print >/dev/tty …) is new, inserted just before the return command of the function substitution in the default prompt; this is what you’ll need to merge into your own, custom, prompt (if you have one; otherwise pull this adaption to the default one). Line 19 is the only other thing in this script rebinding the Ctrl-M key (which is normally produced by the Enter/Return key) to code that… does something crazy. This trick however does funny things with multiline commands, so if you type something out in multiple lines, for example here documents or loops press Ctrl-J instead of Enter/Return after each line including the first (at PS1) and final (at PS2) one.

What about programmable tab completion?

The shell itself provides static deterministic tab completion. However, you can use hooks like reprogramming the Tab key to a command line editor macro, and using the evaluate-region editor command (modulo a bugfix and possibly adding another, convenience, editor command) together with shell functions to implement a programmable completion engine. Multiple people have been considering doing so in our IRC channel; we’ll hyperlink to these engines when they are available.

My question is not answered here!

Check out the FAQ section at the end of the mksh(1) manual page which contains questions that are in user scope; this webpage collects those about mksh in general, by packagers, etc.

How do I contact you (to say thanks)?

You can say hi in the #!/bin/mksh channel on Freenode IRC, although a donation wouldn’t be amiss ☺ The mailing list can also be used.

MirBSD Logo