The MirBSD Korn Shell

Sponsored by
HostEurope Logo

The MirBSD Korn Shell

mksh – old versions

This page lists information about versions of mksh(1) earlier than R40.

Old instructions


The build script also honours the following environment variables:

If CPPFLAGS contain any of the following definitions, the resulting binary will be compiled with a specific flavour:

You can override certain mirtoconf checks by setting environment variables like HAVE_REVOKE=0 (default for Linux) – if these are set to 0 or 1, the values are used; if unset, the values are probed (unless overridden by a different check, such as MKSH_SMALL), if set to ‘x’ the probe is forced.
Useful items to enable/disable are HAVE_MKNOD (set to x to re-enable), HAVE_SETLOCALE_CTYPE (set to 0 if you know that it won’t ever return UTF-8), HAVE_PERSISTENT_HISTORY (0 to not include this feature), HAVE_FLOCK_EX (if flock or mmap do not work on files).

Defining MKSH_SMALL will disable persistent history (to re-enable, env HAVE_PERSISTENT_HISTORY=x), try to compile with -fno-inline, disable the nice(3) extern; (not overridable) implies traditional/conservative filedescriptor usage, MKSH_NOPWNAM; omits shebang checking in scripts, the Vi command line editing mode (mksh R39b and up can re-enable it by defining -DMKSH_S_NOVI=0), certain verbose error messages, the entire ‘-T’ command line option; replaces inlines with separate functions for size over speed optimisation, etc. (In R39b and up, it disables a whole lot more things than in earlier versions.)

Accepted arguments to are:

These special values in CPPFLAGS are recognised:

The build script also honours the following environment variables:

Other Shells and more

mksh is a successor of pdksh but not affiliated with the pdksh developers or contributors. mksh is not affiliated with the AT&T Korn Shell, its past or present owners, other than that both attempt to implement the Korn Shell programming language.

mksh targets users who desire a compact, fast, reliable, secure shell not cut off modern extensions; a shell with Unicode support; an actively developed, current, and portable product; one with developers that listen to their users’ requests and implement them if they actually make sense.

mksh aims to replace pdksh in all but very rare use cases (such as support for checking the Unix mbox) and in all operating environments (thus including patches from pdksh on e.g. Debian).


mksh is a direct descendant from the OpenBSD /bin/ksh and contains all of its bug fixes and enhancements except the “GNU bash-like $PS1” and “POSIX character class support in globbing” changes and the incompatible “ulimit can handle multiple limits in one invocation” difference. Some of the more weird diffs in oksh have not been merged either. The DeliLinux developer who is responsible for packaging oksh for GNU/Linux should instead use mksh and port that diff over (be careful to not break the fixes to the command line editing modes, these are subtilely broken in OpenBSD). Even better, the OpenBSD people should not only commit a port of mksh but replace their ksh with it (optionally retaining that GNU bash-like $PS1 stuff). The set -o emacs-usemeta command is no longer needed because the emacs editing mode has been changed for Unicode/UTF-8 mode, which adds a new set -o utf8-mode flag. The set -o sh command has been completely removed, set -o posix merely turns off brace expansion as side effect. There is no limit (well, 2³² – for now…) on array sizes any more. Many bugs and security holes have been closed in mksh and are still in oksh and OpenBSD ksh. The user interface has much less bugs and surprises; emacs editing mode is enabled by default. In contrast to oksh, set -o arc4random can be used to control which generator for $RANDOM is used.

mksh is the heir of pdksh and contains all the latest fixes from upstream (so ca. 1995) and Debian. It is the only pdksh derivate currently being under active development. See above for other differences. The code really has been cleaned up and no longer contains any material under licences more restrictive than the BSD licence.

AT&T ksh88 and ksh93 compare to mksh substantially, but share no code; the user interface is slightly different especially for ksh88; many editing commands work (only slightly) differently as well. mksh implements many, but by far not all, ksh93 features, but most ksh88 features. No floating point. All commands of a pipeline are executed in a subshell.

mksh can do many things GNU bash can’t, for example better arrays, the ksh Co-processes, etc. but is much faster and smaller. In contrast to bash, mksh is still being actively developed (bash almost only receives small changes or weird stuff like programmable tab completion). GNU bash’s array initialiser syntax is not yet supported. We don’t aim at being fully bash compatible, but some of the surprises for converts will be removed. Funnily, bash4 now contains some things first introduced in mksh.

The Z shell (zsh) isn’t even remotely ksh compatible in its “emulate ksh” operation mode, and we don’t compare to it.

mksh is mostly bourne shell compatible (but ^ as alias for | is not supported, like most modern shells). mksh is also POSIX sh compatible. Some constructs are not supported, for example
((foo; bar) 2>&1 || baz)
which has to be rewritten as
( (foo; bar) 2>&1 || baz)
because ((…)) is shell arithmetics; brace expansion is turned on by default; etc.

mksh R33 supports more (later versions even more) bash/ksh93/zsh constructs than its predecessors; sometimes, not all cases (e.g. applying string trimming on arrays) are supported, but you probably will not notice that.

Hints and other useful stuff

mksh does not write a history file by default any longer; set the environent variable HISTFILE in ~/.mkshrc (or the profile) if you want this. The history file format of mksh (and oksh and pdksh) differs from that of other shells, so you might want to use a construct like
case $KSH_VERSION in
*MIRBSD\ KSH*) export HISTFILE=~/.mksh-history ;;
*PD\ KSH*MirOS*) export HISTFILE=~/.oldmksh-history ;;
*PD\ KSH*) export HISTFILE=~/.pdoroksh-history ;;
?*) export HISTFILE=~/.ksh-history ;;
*) export HISTFILE=~/.nonksh-history ;;

to avoid them overwriting each others' history file.

Very old sample: this

OS inclusion:

For packagers: Upgrades

mksh R39c should fix a bug that could have led to accidental removal of the manpage when building in the source directory. AIX builds no longer uselessly pull in libcrypt.

mksh R39b now has a separate caveat section listing the most relevant user-visible changes, split off this packagers' list. The optional, undesirable, unsupported printf(1) builtin is now documented in the manpage. The chdir builtin is an alias for cd. The realpath builtin is now always provided. MKSH_SMALL removes much more functionality than it used to. MKSH_NOVI=1 is now MKSH_S_NOVI=[0|1]. $RANDOM handling is greatly simplified. There's now both “±o sh” and “±o posix”, and they differ; MKSH_MIDNIGHTBSD01ASH_COMPAT needs the former. New build flags -M, -valgrind. The default on HP-UX on IA64 is no longer to default to building with -mlp64 (gcc) or +DD64 (HP aCC). SUNWcc tries -xipo (but requires the packager to use -xO4 or up manually).

mksh R39 has user-visible changes regarding “set -u” (“set -o nounset”) and alias/function name conflicts regarding whitespace before parenthesēs, as well as a much enhanced dot.mkshrc sample file I urge to install. People using a Makefile to build it may need to regenerate their set of CPPFLAGS used; CPPFLAGS handling in general has improved. There is now a defined but unsupported way to make printf(1) a builtin; this is not tested and adds a huge SLOB of foreign code to the build, lets the shell use stdio and floating point, making it bloated and fragile; if you still want it (hi Md), set USE_PRINTF_BUILTIN=1 and add printf.c from mircvs://src/usr.bin/printf/ to the build.

mksh R38c adds QNX fixes, build system fixes, and the (not recommended) ability to use -DMKSH_ASSUME_UTF8=0 to skip the environment checks for locale (leading to one (supposedly un-)expected regression test failure). Use -DMKSH_NO_LIMITS to skip the ulimit builtin (klibc).

mksh R38b works on QNX 6.4 out of the box.

mksh R38 offers -DMKSH_MIDNIGHTBSD01ASH_COMPAT and users should be warned about the “!string” line and UTF-8 mode changes.

mksh R37c now honours -DMKSH_CONSERVATIVE_FDS and ACK. The regression test suite keeps LOCPATH around.

mksh R37b now honours -DMKSH_UNEMPLOYED for the jobless mode required on, at least, Minix 3.

Freshmeat announcements have ceased because the site switched to a very user-unfriendly HTML (especially Lynx). Use the RSS feed instead.

mksh R37 has a new ‘-combine’ option. The -DMKSH_AFREE_DEBUG flag is gone due to a new allocator, which however honours -DUSE_REALLOC_MALLOC=0.

At Freshmeat you can subscribe to get automatically notified (with a summary of changes, not the complete changelog, see below) whenever new releases are put out.

Note: This is not the ChangeLog, these are the packager-visible upgrade notes regarding changes in the build system ( and friends, compiler support, packaging conventions, bad examples, etc).

mksh R36b stays compatible, no surprises there. The ‘-llvm’ option to, however, is new.

mksh R36’s script ‘-q’ option is gone. Furthermore, you must add -DMKSH_BINSHREDUCED to your CPPFLAGS now if you want mksh to behave more POSIXish if called as sh.
OSF/1 V2.0 is now supported using the native DEC C compiler.

mksh R35b builds on some more platforms and throws less warnings, but the build system is almost unchanged; now shows the Perl binary used (honours $PERL) and its version.

In mksh R35, setlocale/nl_langinfo have been disabled by default for some platforms. If we do not assume UTF-8, disabling lets mksh employ the LANG and LC_* environment variables for codeset determination. Also, a new builtin is included depending on existence of the readlink(3) function, disabled by default if MKSH_SMALL. The “pdksh” check category is no longer persistent. The licence has changed (the advertising clause was removed). The dot.mkshrc sample was changed to improve re-use.
There was no R34.

No changes in mksh R33c except for Ultrix support. None in R33d.

In mksh R33b, much more compilers are detected, even if not all of them are supported. The OE (OS and CC/LD) versions are now dumped too. Instead of #error, forced link failures are now used as the mechanism to auto-detect some things in the target environment. Features are now much better detected, and some annoying warnings don’t show up any longer due to this. Less tools are required to build.

Please be reminded that you should run ./ -v inside an environment with /dev/tty available (as device node) and usable (e.g. use script(1) or GNU screen if you’re doing auto-builds detached from controlling terminal). Use -v to see failures.

No surprises in mksh R33 either, but the build system now gives more detailed output on the version actually built, to aid tracking down FTBFSen (build errors) with access to only the build logs. Regression tests now work with Intel’s compiler on SLES too, which requires a custom LD_LIBRARY_PATH formerly stripped by the script.

No surprises in mksh R32, but some ancient systems (AIX, Solaris 11, OSF/1, UWIN) are now better supported.

In mksh R31d, parallel make with ‘-j’ was added (no limitation on number of childs though), this even works with Solaris 8 /bin/sh. The MKSH_NEED_MKNOD define is no longer honoured.

From mksh R31 to R31b, arc4random.c has been upgraded.

From mksh R30 to R31, there are no surprises. The “arc4random.c” file is available from mircvs://contrib/code/Snippets/arc4random.c now, and the new “source” command is not available in posix mode either.

From mksh R29 to R30, the following things should be kept in mind:

The syntax of has changed: $CC now defaults to “cc” instead of “gcc”, and the ‘-d’ and ‘-nd’ arguments are gone – if you want to build a statically linked mksh, pass LDSTATIC=-static (gcc+GNU ld, adjust for other OEs) to it. An “arc4random.c” is now automatically included into the build if found in the source directory. The $CPP variable is ignored, $CC -E is used instead, except for tcc, which uses “cpp -D__TINYC__” because “tcc -E” doesn’t work.

As a tribute to better POSIX compatibility, certain aliases (like “stop”) are no longer predefined in “set -o posix” mode, which is invoked automatically if the shell is run as -sh, /bin/sh or similar, so that they can be used as function names.

If defining MKSH_SMALL, the ‘vi’ editing mode is omitted, which may surprise your users.

Many compilers other than gcc are now supported as well as AIX.

Users' Upgrade Caveat

R39c: Evaluation of things like ${foo:-bar} and "${foo+bar}" now behave standards-compliant (SUSv4) and more like all other shells, sans bugs. In particular, if a ${} expression is double-quoted, the apostrophe/single quote loses its special meaning within, whereas it still acts as quote character if the expression is not double quoted. Other special characters' meanings have been updated to match standardised/expected behaviour.

R39b: Due to a lot of bugfixes and some enhancements, take care when upgrading. The realpath builtin is now always available. There are now both “±o sh” and “±o posix”, and they differ (scroll down to almost the end of the R39b changelog). In numeric expressions, “'a'” is an alternative to “1#a” like in ksh93; “$'…'” expanded strings are now also supported. Some constructs parse more loosely, and things like “function stop () {” work now. MKSH_SMALL removes much more functionality than it used to. set +o arc4random is no longer possible (either it's there and used, or it's not). "mksh /tmp/horsies" now exits 127 ipv 1 (ENOENT). 「((foo) || bar)」 and 「((foo) | (bar))」 work now. Lazy evaluation of ternary operations is fixed. In '-o sh' mode, echo does not expand backslashes any more. In '+o sh' mode, “set -- $(false)” POSIXly correctly returns 0 (and breaks getopt(1) in traditional usage mode). Changes of variables inside Bourne style functions affect the caller's environment. “eval $(false)” also returns 0. “±U” is now honoured on an interactive shell's command line. Finally, the getopts builtin now behaves standards-compliant: even on an unknown option, OPTIND is incremented (think “getopts "ab:c" ch” and “script -a -I foo bar” in contrast to “script -a -- -I foo bar” – mkdep(1) was affected, as will be every script that does not abort in the (\?) or (*) case).

mksh R39 has user-visible changes regarding “set -u” (“set -o nounset”) and alias/function name conflicts regarding whitespace before parenthesēs.

Recent Changes

mksh R39c is an important minor bugfix release:

mksh R39b is a major stability and bugfix update:

mksh R39 evolved into these through various means:

mksh R38c contains the following fixes:

mksh R38b fixes the following problems:

mksh R38 comes with these changes and fixes applied:

mksh R37c provides these follow-up fixes:

mksh R37b comes with the following fixes on top:

mksh R37 has major standards compliance improvements:

mksh R36b is a compatible, major bug-fix update:

mksh R36 features the following changes:

mksh R35b comes with the following bug fixes:

mksh R35 comes with helluva changes:

mksh R33d is a quick security-update with these changes:

mksh R33c issues fixes for the following issues:

mksh R33b comes with the following minor fixes:

A release with many new features is mksh R33, look yourself:

Sported by mksh R32 are these changes:

Everyone should upgrade to mksh R31d with fixes for…

The mksh R31c (Solaris-only) upgrade for cnuke@ was caused by:

A quick upgrade, mksh R31b with major bug fixes:

mksh R31 was released as part of MirOS #10 with these news:

A milestone in development: mksh R30 can do this:

In mksh R29g we MFCd the following changes:

Please use mksh R29f because of below modifications:

Dedicated to David Ramsey and Coverity, mksh R29e unveils:

Portability improvements in mksh R29d contain:

Minor bugfixes in mksh R29c – you might want it:

Immediately upgrade to mksh R29b please:

Please upgrade to mksh R29 due to the following changes:

Upgrading to mksh R28 with these changes is highly recommended:

We recommended mksh R27e to be used:

What became of mksh R27d in the meanwhile?

Featuring mksh R27c with these changes:

Changes in the minor version R26c, relative to R26b:

Changes in the minor version R26b, relative to R26:

New major version R26 changed this, relative to R25b:

New minor version R25b contains these changes:

New major version R25 contains these changes:

R24c is another clean-up release, with no change to KSH_VERSION.

R24b is a minor clean-up relase, recommended especially on Darwin.

R24 is an important bug fix release and the new required minimum version to be installed for MirMake. Changes are:

R23 comes with an overhauled build system providing more flags for easier configuration, a bug-fix if the relative path to $0 contained a space, and does not need h2ph(1) to build some headers any more. Also, the code has cleaned up a bit and some manual page glitches were corrected. Some of these changes originated by Han Boetes, a few came via the OpenBSD project.

R22d is the first version which works if source or build directory contain spaces in the pathname. It also allows building without bothering to pre-format the manual page.

R22c contains some compile time warning fixes on non-MirOS platforms.

R22b contains an important fix regarding the srand(3) initialisation logic and a portability fix for NetBSD.

R22 is the result of three different kinds of work: integrating diffs from Debian's pdksh package, as needed, including fixing bugs and of course testing and fixing docs; fixing the dreaded emacs-mode filename with brackets (hello AONE); much cleanup and polishing. Also, the new codebase has been tested on a fair number of systems now, with more to follow (maybe even new, currently unsupported, platforms).

R20b contains some minor arc4random and build fixes against R20.

R21 has been a three-way integration work from OpenBSD-current's ksh, MirOS-current's ksh and portable mksh R20. This is the first release to come without autoconf'd script; it is much smaller and installs both faster and easier. Several bugs have been fixed, the testsuite has been enhanced and the code was cleaned up largely. pdksh lookalikeness was largely dropped, and support for octal and sedecimal (hexadecadic) numbers via prefixing with 0 or 0x has been added. This is an experimental release; it is not yet supported e.g. by MirMake – make(1) – or other tools but this will follow soon. MirbsdKsh R21 is to be the only shell available on MirOS #9.

R20 integrated an experimental bugfix from millert@openbsd and shuffled some code around. OS/2 support vanished, and the rest of the code shrank and was optimised. This is the first version since v1.11 to work on SFU (Interix) 3.5 as-is. The upgrade to R20 is highly recommended. Note: the mksh R20 distfile has changed from before Dec 14, 16:00.

R19 changes back a bugfix from R18 which caused a regression (from OpenBSD) and changed behaviour to match ksh88 on Solaris (from OpenBSD).

v1.18 (R18) fixes some core dump bugs and is a recommended update.

v1.17 comes out with the final MirOS licence template applied, but not yet OSI approved (it's not our fault though). There are regression fixes and bug fixes; IFS field splitting now works as documented. This version is a major improvement both over v1.16 and OpenBSD /bin/ksh, so please use it and report possible bugs.

v1.16 IS A BETA VERSION, use at your own risk. This version comes with a code cleanup session (for compilation with -Wall -Werror -W -pedantic and in preparation for doing an indent(1) whack over the source; any volunteers?) and some new features (with -T it spawns on a different tty than you're on - cool for single user mode) and code removed (the mailbox checking functionality, since everyone sane uses UW-IMAPD to access his MBX format folder using IMAPS, port 993, even to localhost). The code is also ANSIfied and protoised, in preparation for style(9) aka KNF.

There were no v1.13, v1.14, and v1.15 was never released as portable version. MirbsdKsh version numbers were pretty much RCS IDs at the time of writing this paragraph.

v1.12 fixes the manpages and minor stuff, as well as a signalling bug and the inability to build without gcc installed as gcc. It also adds installation hints for various operating systems.

v1.11 is a minor update to v1.10 with a few build and style fixes only.

Recommendations on version numbering

mksh by default uses a version numbering scheme that uses full integers, prefixed by a capital letter R significing “Release”. If minor updates are required or requested, a lower-case letter from the standard latin alphabet will be appended, starting at ‘b’ and ending at ‘z’ (but usually way before or at ‘i’). If a packaging system cannot handle version numbers such as mksh-R29b (source) → mksh-R29b-1, mksh-R29bp1 (binary), packagers OUGHT TO map this to a numerical system as follows: mksh-29.2-1, mksh-29.2.1, mksh-29.2nb0, depending on the packaging-system local policy for build numbers / patchlevels.

Schemes to AVOID are mirbsdksh-1.29b, mksh-2.9.2, or worse. Please adhere to our recommendations so that users are able to locate mksh in their operation environment of choice.


While we’re at it – recommendations for packagers – there is another set of do’s and dont’s: location of the UNIX® standard text editor. As outlined in traditional unixoid operating system standards, manifested into POSIX, and – for these three-letter words that aren’t Unix, no matter which of the kernels they use in their variety of so-called distributions – the FHS (FSSTND): ed lives in /bin/ed, period.

Patching mksh’s code to look for ed in ANY other location is a MUST NOT.

Future Plans

MirOS Logo