Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e20f1fb
Fix env passthrough for DOS child tools and add toolchain guide
May 21, 2026
cd56b3a
Clarify README with compiler toolchain quick-start
May 21, 2026
e3dc9b2
Improve LINK.EXE compatibility and clean dead code
May 21, 2026
becb61b
Improve Borland BC5 startup compatibility in kvikdos
May 21, 2026
3365413
Add explicit DPMI runtime diagnostic for BC5/32RTM
May 21, 2026
dcae80d
Add structured CLI options with toolchain presets and defaults
May 21, 2026
717f9fe
Document structured CLI options, defaults, and examples
May 21, 2026
270b986
Make compat diagnostics quiet by default
May 21, 2026
aa7ed8e
Improve case fallback and batch cd/path behavior
May 21, 2026
1e59b5f
Expand batch command support for compiler toolchain scripts
May 21, 2026
50693f4
kvikdos: avoid hard aborts in permissive mode and fix path bounds check
May 21, 2026
6a8e53b
Update readme and makefile
May 22, 2026
bc3b0fb
kvikdos: add native/wine dispatch, harden permissive mode, and docume…
May 22, 2026
3b26596
kvikdos: refine Windows-exe dispatch heuristics and keep dual-mode NE…
May 22, 2026
b6706ca
Fix --prog DOS-path null dereference in filename resolution
May 25, 2026
c147f09
Run dos NE if possible
May 25, 2026
5a30561
run_dos_batch: preserve slash options when parsing commands
May 25, 2026
85a74ca
kvikdos: unify case-fallback path resolution and remove duplicate ope…
May 27, 2026
9716ca8
Fix DOS exec/path resolution and case-fallback file opens
May 28, 2026
26aca75
fix parse crash with --prog and add CLI regression test
May 29, 2026
3a80898
harden init/readability and enforce uninitialized warnings as errors
May 29, 2026
81b6059
Fix batch env/path handling and PE delegation
May 30, 2026
978150b
Add Linux-ready alink with OMF fixes
Jun 2, 2026
6f7a30d
Merge alink OMF Linux fixes
Jun 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.PHONY: all clean run
.PHONY: all clean run test test-batch test-mem test-cli test-cli-matrix test-static test-sanitizers test-valgrind test-tooling
.SUFFIXES:
MAKEFLAGS += -r

ALL = kvikdos guest.com slowp.com malloct.com mallocs.com printenv.com cat.com waitkey.com

# -Werror=int-conversion: GCC 4.8.4 fails.
CFLAGS = -ansi -pedantic -s -O2 -W -Wall -Wextra -Werror=implicit-function-declaration -fno-strict-aliasing -Wno-overlength-strings $(XCFLAGS)
CFLAGS = -ansi -pedantic -s -O2 -W -Wall -Wextra -Wuninitialized -Wmaybe-uninitialized -Werror -fno-strict-aliasing -Wno-overlength-strings $(XCFLAGS)
XCFLAGS = # To be overridden from the command-line.

SRCDEPS = kvikdos.c mini_kvm.h
Expand All @@ -18,6 +18,31 @@ clean:
run: kvikdos guest.com
./kvikdos guest.com hello world

test: test-batch test-mem test-cli test-cli-matrix

test-batch: kvikdos
./tests/test_batch.sh ./kvikdos

test-mem: kvikdos
./tests/test_mem_services.sh ./kvikdos

test-cli: kvikdos
./tests/test_cli_parse.sh ./kvikdos

test-cli-matrix: kvikdos
./tests/test_cli_matrix.sh ./kvikdos

test-static:
./tests/test_static.sh

test-sanitizers:
./tests/test_sanitizers.sh

test-valgrind: kvikdos
./tests/test_valgrind.sh ./kvikdos

test-tooling: test-static test-sanitizers test-valgrind

%.com: %.nasm
nasm -O0 -f bin -o $@ $<

Expand Down
150 changes: 147 additions & 3 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ Limitations:
(last 768 bytes), BIOS Data Area, helper code, the user code written for
Linux.

kvikdos doesn't support memory types UMB (up to 384 KiB more), HMA (63
KiB more), XMS (up to hundreds of megabytes more) or EMS (also up to
hundres of megabytes, overlapping with XMS).
kvikdos has partial compatibility support for UMB/XMS/EMS probes and
common allocator APIs used by DOS toolchains, but it is not a full
memory-manager implementation (no full DPMI/VCPI stack).

If your DOS programs need mre memory, use udosrun or DOSBox instead.

Expand All @@ -72,6 +72,12 @@ Limitations:
already work, see the compatibility list below. To get good chances for
running any random DOS program, use udosrun or DOSBox instead.

* If the target file is Linux-native (ELF or shebang script), kvikdos
executes it natively with Linux `fork+execvp` instead of DOS emulation.

* If the target file is a Windows executable format (PE/NE/LE/LX), kvikdos
delegates execution to `wine` automatically.

Features and advantages:

* kvikdos is very fast, it runs CPU-intensive code at almost native speeds
Expand Down Expand Up @@ -146,6 +152,123 @@ How to install kvikdos:

If it displays the dot and the `Hello, World!' message, then it's OK.

Command-line options (structured):

General:

* `--kvm-check' checks KVM only.
* `--strict' enables strict unsupported-interrupt behavior.
* `--permissive' enables compatibility fallback behavior (default).

DOS runtime:

* `--toolchain=<name>' applies toolchain presets:
`msc4', `msc5', `msc6', `masm5', `bc2', `bcpp1', `bc5', `ic86'.
* `--env=<NAME>=<value>' adds one DOS environment variable.
* `--env-file=<file>' loads DOS environment variables from file
(`NAME=VALUE' lines).
* `--path-dos=<pathlist>' sets DOS PATH explicitly.
* `--prog=<dos-pathname>' sets DOS pathname of the running program.
* `--cwd-dos=<path>' sets initial DOS current directory.

Mounts:

* `--mount=<drive><case><dirname>/' mounts Linux directory to DOS drive.
* `--mount=<drive>0' hides DOS drive.
* `--drive=<drive>' sets initial DOS drive.

Compatibility:

* `--case-fallback=off|prog|all' controls case-insensitive executable
lookup fallback. Default: `all'.

Diagnostics:

* `--diag=compat|exec|int|fs|all|off' controls runtime diagnostics.
Default: `compat'.
* `--diag-file=<file>' writes diagnostics to a file.

I/O and memory:

* `--tty-in=<fd>' chooses input source (`-3', `-2', `-1', `>=0').
* `--mem-mb=<n>' DOS memory size in MiB (currently only `1').
* `--hlt-ok' and `--hlt-dump=<file>' are low-level debug options.

Best defaults:

* `--permissive'
* `--case-fallback=all'
* `--diag=compat'
* no toolchain preset unless requested

Examples:

* Microsoft C 5.1:

$ ./kvikdos --toolchain=msc5 /home/xor/inertia_player/dos_compilers/Microsoft\ C\ v5/CL.EXE HELLO.C

* Borland C 2 with explicit DOS PATH and cwd:

$ ./kvikdos --path-dos=C:\\ --cwd-dos=C:\\ /home/xor/inertia_player/dos_compilers/Borland\ Turbo\ C\ v2/TCC.EXE HELLO.C

* Diagnostics to file:

$ ./kvikdos --diag=all --diag-file=kvikdos.diag /home/xor/inertia_player/masm/BIN/LINK.EXE

Batch regression tests:

* Run all local tests:

$ make test

* Current batch suite (`tests/test_batch.sh`) covers commands/patterns used
by DOS compiler scripts: `set`, `%VAR%`, `%1..%9`, `shift`, `call`,
`if` (`==`, `not`, `errorlevel`, `exist`), `goto`, `mkdir`, `copy`, `del`.

Static analysis and runtime checks:

* cppcheck:

$ cppcheck --enable=warning,style,performance,portability --std=c89 --force kvikdos.c

* clang static analyzer:

$ clang --analyze -Xanalyzer -analyzer-output=text -std=c89 -Wall -Wextra kvikdos.c

* ASan+UBSan build and compiler smoke:

$ gcc -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer -fno-strict-aliasing -o kvikdos_asan kvikdos.c
$ /home/xor/kvikdos/kvikdos_asan /home/xor/inertia_player/dos_compilers/Microsoft\ C\ v5/CL.EXE /c HELLO0.C
$ /home/xor/kvikdos/kvikdos_asan /home/xor/inertia_player/dos_compilers/Microsoft\ MASM\ v5/BIN/MASM.EXE HELLO.ASM,HELLO.OBJ,NUL.LST,NUL.CRF

* Valgrind smoke:

$ valgrind --tool=memcheck --leak-check=full --error-exitcode=101 ./kvikdos /home/xor/inertia_player/dos_compilers/Microsoft\ C\ v5/CL.EXE /c HELLO0.C
$ valgrind --tool=memcheck --leak-check=full --error-exitcode=101 ./kvikdos /home/xor/inertia_player/dos_compilers/Microsoft\ MASM\ v5/BIN/MASM.EXE HELLO.ASM,HELLO.OBJ,NUL.LST,NUL.CRF

Readability and stability improvement roadmap (recommended):

* Priority 1 (safety):
* Initialize all state structs (`DirState`, `ParsedCmdArgs`, runtime locals)
before first use; avoid partial-init patterns.
* Keep parser regression tests for option combinations (`--prog`, mounts,
drive/cwd/path interactions) and assert "no crash" behavior.
* Prefer bounded copy helpers (`copy_cstr0`) over ad-hoc `strncpy` usage.

* Priority 2 (clarity):
* Split large functions (`parse_args`, `run_dos_prog`, `run_dos_batch`)
into smaller helpers by responsibility:
argument parsing, DOS path translation, int21 dispatch, batch command eval.
* Replace ambiguous locals (`p`, `q`, `r`) with intent names in new code
(`requested_drive`, `active_drive`, `resolved_prog`).
* Keep compatibility fallbacks local and commented at point of use.

* Priority 3 (analysis depth):
* Add a fast static target in CI: `cppcheck` + `clang --analyze`.
* Add sanitizer targets (ASan+UBSan) and valgrind jobs as separate steps.
* Add negative tests for malformed paths/env/flags to verify deterministic
error messages and exit codes.

About making Linux files available for DOS programs:

* kvikdos emulates DOS drives A: .. F: by exposing directories on the Linux
Expand Down Expand Up @@ -217,6 +340,27 @@ About uppercase and lowercase filenames:

Software compatibility, i.e. DOS programs known to work in kvikdos:

Quick start for DOS compilers and assemblers:

* For practical, copy-paste command lines, see TOOLCHAIN.md in this
repository.

* Recommended layout rules:
* Use 8.3 filenames for source/object/output files (e.g. HELLO.C).
* If a toolchain has BIN/LIB/INCLUDE directories, mount the toolchain
root as C: and run the executable from C:\BIN\...
* Set DOS environment explicitly with --env=LIB=... and
--env=INCLUDE=...

* Recently validated under kvikdos (compile, link, run of a tiny HELLO):
* Microsoft C 4.0
* Microsoft C 5.1
* Microsoft C 6ax (from toolchain root, C:\BIN\CL.EXE, LIB=C:\LIB)
* Intel iC-86 Compiler 4.5
* Borland Turbo C 2.0
* Borland Turbo C++ 1.01 (from toolchain root, C:\BIN\TCC.EXE, LIB=C:\LIB)
* Microsoft MASM 5.0 (MASM direct, LINK via prompt answers or stdin)

* Turbo Pascal 7.0 compiler tpc.exe. It produces .exe program files
directly.

Expand Down
102 changes: 102 additions & 0 deletions TOOLCHAIN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# kvikdos Toolchain Guide

This document shows known-good ways to run DOS C/ASM toolchains under `kvikdos`.

## Key rules

- Use DOS 8.3 names for source/object/output files when possible.
- Mount the correct directory as `C:` with `--mount=C:.` from that directory.
- For toolchains with separate `BIN`, `LIB`, `INCLUDE`, mount their parent root and call executables as `C:\BIN\...`.
- Set `LIB` and `INCLUDE` explicitly with `--env=...`.

## Minimal C source

Use this for widest compatibility:

```c
main(){return 0;}
```

## Microsoft C 4.0

```bash
cd '/home/xor/inertia_player/dos_compilers/Microsoft C v4'
printf 'main(){return 0;}\n' > HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. --env=LIB=lib --env=INCLUDE=inc C:\CL.EXE /c HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. --env=LIB=lib C:\LINK.EXE HELLO,,,SLIBFP
/home/xor/kvikdos/kvikdos --mount=C:. C:\HELLO.EXE
```

## Microsoft C 5.1

```bash
cd '/home/xor/inertia_player/dos_compilers/Microsoft C v5'
printf 'main(){return 0;}\n' > HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. --env=LIB=lib --env=INCLUDE=inc C:\CL.EXE /c HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. --env=LIB=lib C:\LINK.EXE HELLO,,,SLIBCE
/home/xor/kvikdos/kvikdos --mount=C:. C:\HELLO.EXE
```

## Microsoft C 6ax

```bash
cd '/home/xor/inertia_player/dos_compilers/Microsoft C v6ax'
printf 'main(){return 0;}\n' > HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. --env=LIB=C:\LIB --env=INCLUDE=C:\INCLUDE C:\BIN\CL.EXE /c /AS HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. --env=LIB=C:\LIB C:\BIN\LINK.EXE HELLO,,,SLIBCE
/home/xor/kvikdos/kvikdos --mount=C:. C:\HELLO.EXE
```

## Intel iC-86 Compiler v4.5

```bash
cd '/home/xor/inertia_player/dos_compilers/Intel iC-86 Compiler v4.5'
printf 'main(){return 0;}\n' > HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. C:\IC86.EXE HELLO.C small optimize\(3\) mod86 diagnostic\(2\) define\(INTELC\)
/home/xor/kvikdos/kvikdos --mount=C:. C:\LINK86.EXE libs\cstdoss.obj,HELLO.obj,c:\libs\cdoss.lib,u\cel87.lib,u\e8087.lib,u\de8087,libs\clib87.lib TO HELLO.EXE exe
/home/xor/kvikdos/kvikdos --mount=C:. C:\HELLO.EXE
```

## Borland Turbo C 2.0

```bash
cd '/home/xor/inertia_player/dos_compilers/Borland Turbo C v2'
printf 'main(){return 0;}\n' > HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. C:\TCC.EXE -ms -Z -O -G -Iinclude -Llib -eHELLO.EXE HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. C:\HELLO.EXE
```

## Borland Turbo C++ 1.01

```bash
cd '/home/xor/inertia_player/dos_compilers/Borland Turbo C++ v1'
printf 'main(){return 0;}\n' > HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. --env=LIB=C:\LIB --env=INCLUDE=C:\INCLUDE C:\BIN\TCC.EXE -ms -Z -O -G -IC:\INCLUDE -LC:\LIB -eHELLO.EXE HELLO.C
/home/xor/kvikdos/kvikdos --mount=C:. C:\HELLO.EXE
```

## Microsoft MASM 5.0

`MASM.EXE` works directly; `LINK.EXE` is easiest via stdin prompts.

```bash
cd '/home/xor/inertia_player/dos_compilers/Microsoft MASM v5/BIN'
cat > HELLO.ASM <<'EOA'
.MODEL SMALL
.STACK 100h
.CODE
start:
mov ax,4C00h
int 21h
END start
EOA
/home/xor/kvikdos/kvikdos --mount=C:. C:\MASM.EXE HELLO.ASM,HELLO.OBJ,NUL,NUL
printf 'HELLO.OBJ\nHELLO.EXE\nNUL\n\n\n' | /home/xor/kvikdos/kvikdos --mount=C:. C:\LINK.EXE
/home/xor/kvikdos/kvikdos --mount=C:. C:\HELLO.EXE
```

## Notes

- If compile succeeds but link cannot find CRT objects/libs, your `LIB` path is wrong for the mounted layout.
- If includes are missing, adjust `INCLUDE` to match the mounted layout.
- For old compilers, avoid modern signatures (`int main(void)`) and rely on K&R-style `main()` for compatibility.
12 changes: 12 additions & 0 deletions alink/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 8
UseTab: Always
BreakBeforeBraces: Allman
ColumnLimit: 100
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
PointerAlignment: Right
SortIncludes: false
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
4 changes: 4 additions & 0 deletions alink/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Checks: '-*,clang-analyzer-core.uninitialized.*'
WarningsAsErrors: '*'
HeaderFilterRegex: '.*ALINK\.H'
FormatStyle: file
10 changes: 10 additions & 0 deletions alink/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true

[*.{C,H}]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 8
tab_width = 8
trim_trailing_whitespace = true
17 changes: 17 additions & 0 deletions alink/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: ci

on:
push:
pull_request:

jobs:
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install toolchain
run: |
sudo apt-get update
sudo apt-get install -y build-essential clang clang-tidy clang-format clang-tools cppcheck valgrind
- name: Run CI checks
run: make ci
3 changes: 3 additions & 0 deletions alink/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.o
alink
alink.san
21 changes: 21 additions & 0 deletions alink/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Repository Notes

## Build

- `make` builds the Linux host binary `alink`
- `make sanitizers` builds `alink.san` with AddressSanitizer and UBSan

## Checks

- `make format-check`
- `make tidy`
- `make cppcheck`
- `make analyze`
- `make valgrind`
- `make ci`

## Conventions

- Source files use uppercase DOS-era filenames and must be compiled as C, not C++
- Linux path handling must continue to accept both `/` and `\`
- Compiler warnings are treated as errors in the maintained build targets
Loading