command-com

module
v0.0.0-...-f4e3d25 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2026 License: GPL-3.0

README

COMMAND.COM

A COMMAND.COM for Unix - because some of us never got over losing that C:\> prompt, and now we can impose it on perfectly innocent Linux systems.

Module: codeberg.org/lyda/command-com Binary: COMMAND.COM

The shell provides a DOS 3.3 style command interface over a normal Unix host. It is not a DOS emulator - there is no FAT filesystem, no .EXE/.COM execution, no BIOS. What you get is a familiar-feeling interactive shell with DOS-style path notation, .BAT file execution, and even EDLIN and TURGO (a Turbo Pascal-style IDE for Go) for that real 1986 development experience.

Installation

Pre-built binaries for Linux, FreeBSD, NetBSD, OpenBSD, DragonFly BSD, Solaris, illumos, AIX, and macOS are available on the releases page. Linux builds cover amd64, arm64, 386, arm, and riscv64. Other platforms cover amd64 and/or arm64 where supported by Go.

Or install from source with Go:

go install codeberg.org/lyda/command-com/cmd/command.com@latest

The binary is called COMMAND.COM. To use it as a login shell:

# copy to a location in /etc/shells
sudo cp $(go env GOPATH)/bin/COMMAND.COM /bin/COMMAND.COM
echo /bin/COMMAND.COM | sudo tee -a /etc/shells
chsh -s /bin/COMMAND.COM

Quick start

A:\>ver
Go COMMAND.COM version 0.1

A:\>prompt $p$g
A:\>cd \projects
A:\projects>dir

A:\projects>type build.bat
@echo off
echo Hello from COMMAND.COM

A:\projects>edlin notes.txt
New file
*I
      1: Hello, world
.
*E
notes.txt written

Drive mapping

The shell maps DOS drive letters to Unix directory trees.

Drive Default mapping
C: / (filesystem root)
A: ~ (your home directory)

Additional mappings may be configured in ~/config.sys (see Configuration). Switch drives with a bare A: or C:.

Paths may use \ or / as separators. Output always uses \.

Interactive features

  • Line editing - cursor movement, history recall (up/down arrows), home/end
  • Command history - persisted to ~/.command_history across sessions
  • Tab completion - built-in command names, executables in PATH, DOS-style paths
  • Ctrl-C - cancels the current input line; does not exit the shell
  • Configurable prompt - see Prompt sequences
  • Startup scripts - /etc/autoexec.bat and ~/autoexec.bat run at login

Invocation modes

COMMAND.COM                        # interactive shell
COMMAND.COM /C "DIR A:\tmp"        # run one command and exit
COMMAND.COM /K "CD A:\work"        # run one command, then stay interactive
COMMAND.COM script.bat [args]      # run a batch file and exit

Built-in commands

Navigation
Command Effect
A:, C:, ... Switch to drive
CD [path] / CHDIR [path] Print or change current directory
MD path / MKDIR path Create directory
RD path / RMDIR path [/S] Remove directory (/S = recursive)
Files
Command Effect
DIR [path] List directory
TYPE file Print file contents
COPY src dest Copy file (NUL accepted as destination)
DEL file / ERASE file Delete file (glob patterns accepted)
REN old new / RENAME old new Rename file
ATTRIB [file] Show synthetic file attributes (R=read-only, H=hidden)
Environment
Command Effect
SET [name[=value]] List, get, or set environment variables
PATH [value] Print or set PATH
PROMPT [template] Set prompt; no argument resets to default
Shell
Command Effect
VER Print version
CLS Clear screen
ECHO [text] / ECHO ON / ECHO OFF Print text or control command echoing
PAUSE Wait for any key
REM text Comment (no-op)
DATE Print current date
TIME Print current time
EXIT [n] Exit shell with optional exit code
Batch / control flow
Command Effect
GOTO label Jump to :label in current batch file
CALL file [args] Run nested batch file and return
SHIFT Shift positional parameters (%2->%1, %3->%2, ... - first arg discarded)
IF ... Conditional - see IF forms
Editor
Command Effect
EDLIN file Open file in the line-oriented EDLIN editor

IF forms

IF ERRORLEVEL n command
IF NOT ERRORLEVEL n command
IF EXIST file command
IF NOT EXIST file command
IF string==string command
IF NOT string==string command

IF ERRORLEVEL n is true when the current ERRORLEVEL is >= n (DOS semantics).


Redirection and pipes

command > file          redirect stdout
command >> file         append stdout
command < file          redirect stdin
command 2> file         redirect stderr
command 2>> file        append stderr
command 2>&1            merge stderr into stdout
command | command       pipe
command && command      run second only if first succeeds
command || command      run second only if first fails

The 2>, 2>>, 2>&1, &&, and || operators are extensions beyond classic DOS; they are available in the default (practical) mode.

Prompt sequences

Sequence Output
$P Current path (e.g. A:\work)
$G >
$M Machine name (extension)
$N Current drive letter
$Q =
$S Space
$T Current time
$U User name (extension)
$D Current date
$$ Literal $

Default prompt: $P$G -> A:\work>

Batch scripting

.BAT files are plain text scripts, executed line by line.

@ECHO OFF
REM This is a comment
SET GREETING=Hello

IF NOT EXIST output.txt GOTO build
ECHO Already built.
GOTO end

:build
ECHO %GREETING%, world > output.txt
ECHO Built.

:end
What works
  • Line-by-line execution
  • @ echo-suppression prefix
  • ECHO ON / ECHO OFF
  • Labels (:label) and GOTO
  • CALL file [args] for nested batch files, CALL :label for local subroutines
  • SHIFT for positional parameter handling
  • FOR %V IN (list) DO cmd - literal list iteration
  • FOR /L %V IN (start,step,end) DO cmd - numeric range iteration
  • %0..%9 positional parameters
  • %VARNAME% variable expansion
  • %% for a literal % in batch context
  • IF in all four forms with optional NOT
  • ERRORLEVEL set by built-ins and external commands
  • All redirection and pipe operators
  • REM and :: comments
  • Any form of arithmetic except shift operators (SET /A)
  • String manipulation (%VAR:old=new%, substrings)
  • SETLOCAL / ENDLOCAL variable scope - SETLOCAL ENABLEDELAYEDEXPANSION enables !VAR!
What does not work
  • Parenthesized multi-line blocks (IF (...) ELSE (...))

EDLIN

EDLIN is a line-oriented text editor. All commands are case-insensitive. Addresses: an integer, . (current line), or $ (last line).

A:\>edlin notes.txt
Editing 3 lines
*1,3L          list lines 1 through 3
*2I            insert before line 2 (end input with a line containing only .)
*A             append after current line
*3D            delete line 3
*1,3D          delete lines 1 through 3
*Sfoo          search for "foo"
*1,$Sfoo       search entire file for "foo"
*R             replace (prompts for search/replace strings)
*U             undo last change
*W             write file without exiting
*E             write file and exit
*Q             quit without saving (confirms if there are unsaved changes)
*H             help

Pressing Enter on a blank line advances to the next line and displays it.


Turbo Go 3.0

TURGO opens an interactive IDE inspired by Turbo Pascal 3.0. It runs entirely in the terminal using ANSI escape sequences - no TUI library.

A:\projects>turgo main.go
Turbo Go system     Version 0.1

Logged drive: A

Work file: main.go

Edit     Build   Run    Save
Dir      Quit    Options

Text:  1234 bytes

Last result: Build OK

>
Key Action
E Open work file in $EDITOR (default: vi); jumps to error line for joe/jed/vim/nano
B go build ./...; error shown in Last result
R go run <workfile>; output fills screen; any key to return
S Set work file name
D Directory listing of current drive
O Options sub-menu (work file, build flags)
Q Return to COMMAND.COM prompt

Set EDITOR=edlin to use the built-in editor (invoked via COMMAND.COM /C EDLIN). Set EDITOR=joe (or jed, nano, vim, nvim, etc.) to jump directly to the error line.

For the most authentic Turbo Pascal experience, use joe or jed.

Configuration

~/config.sys (INI format with sections):

[drives]
D = /mnt/data
E = /media/usb

[shell]
; Prompt default (used when PROMPT env var is unset)
prompt = $P$G
; Set to false to skip /etc/autoexec.bat and ~/autoexec.bat at login
startup = true

[history]
file = ~/.command_history

Deliberately not supported

The following are intentional non-goals, not gaps:

  • Execution of DOS .COM or .EXE binaries
  • FAT or NTFS filesystem semantics
  • 8.3 filename enforcement
  • Full compatibility with arbitrary real-world DOS batch files
  • DOS device names (CON, PRN, AUX) - NUL maps to /dev/null
  • Hardware commands: FORMAT, FDISK, DISKCOPY, SYS, DEBUG, MODE, MEM, CTTY, LABEL (these are registered as stubs that print an error)
  • Case-sensitive path comparison (paths are matched case-insensitively by default)

Architecture

cmd/command.com/       main entry point, flag dispatch, interactive loop
internal/
  builtins/            built-in command implementations and registry
  exec/                command dispatcher, pipeline, redirection, IF handling
  batch/               batch execution engine: labels, GOTO, CALL, ERRORLEVEL
  parser/              tokenizer and command-line parser
  fsmap/               DOS path <-> Unix path mapping, per-drive CWD
  env/                 case-insensitive environment and variable expansion
  prompt/              prompt string rendering
  edlin/               EDLIN line editor
  term/                readline wrapper (history, completion, Ctrl-C handling)
  config/              ~/config.sys loader

All packages are internal; the only public API surface is the command.com binary.

External runtime dependency: github.com/peterh/liner for line editing.

License

See the LICENSE file.

Directories

Path Synopsis
cmd
command.com command
internal
batch
Package batch implements the DOS batch file execution engine.
Package batch implements the DOS batch file execution engine.
builtins
Package builtins implements the DOS built-in command registry.
Package builtins implements the DOS built-in command registry.
config
Package config loads and holds shell configuration.
Package config loads and holds shell configuration.
edlin
Package edlin implements the EDLIN line-oriented text editor.
Package edlin implements the EDLIN line-oriented text editor.
env
Package env implements a case-insensitive shell environment with DOS-style variable expansion.
Package env implements a case-insensitive shell environment with DOS-style variable expansion.
exec
Package exec wires together the parser, environment, filesystem map, builtins, and external command execution into a running shell.
Package exec wires together the parser, environment, filesystem map, builtins, and external command execution into a running shell.
fsmap
Package fsmap implements DOS-style drive mappings over a Unix filesystem.
Package fsmap implements DOS-style drive mappings over a Unix filesystem.
parser
Package parser tokenizes and parses DOS-style command lines and batch constructs.
Package parser tokenizes and parses DOS-style command lines and batch constructs.
prompt
Package prompt renders DOS-style prompt strings.
Package prompt renders DOS-style prompt strings.
term
Package term provides line editing, history, and tab completion for the interactive shell.
Package term provides line editing, history, and tab completion for the interactive shell.
turbogo
Package turbogo implements the Turbo Go 3.0 interactive IDE.
Package turbogo implements the Turbo Go 3.0 interactive IDE.
utils
release command
release extracts a version's changelog section and prints it as a JSON-encoded string, ready for use in a Forgejo/GitHub API body field.
release extracts a version's changelog section and prints it as a JSON-encoded string, ready for use in a Forgejo/GitHub API body field.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL