Intro
In Part 1, we got OpenStep 4.2 installed, patched, and running cleanly on modern hardware.
In this sequel, we’ll finish the job — replicating the complete OVA Appliance build published on Archive.org. This guide assumes that you are building your own VM and have completed Part1. If you downloaded the OVA Appliance, these steps are already complete.
By the end, you’ll have a full OpenStep workstation: compiler toolchain, X11, shells, text utilities, and even a few Easter eggs.
Let’s Unix!
Developer Tools
We’ll start by installing the Developer Tools.
You can download the iso from here or from archive.org.
Steps
-
Log in as root after setting a password (see Set Password).
-
Attach or insert the Developer CD ISO.
-
Navigate to:
/NextCD/Packages/ -
Install the following packages in order:
DeveloperTools.pkg DeveloperLibs.pkg GNUSource.pkg ProfileLibs.pkg DeveloperDoc.pkgWhen logged in as root you merely double-click on each pkg file to run the installer.
You could also launch the installer from the terminal with
/NextAdmin/Installer.app/Installer /DeveloperCDname/NextCD/DevloperTools.pkg -
Reboot or log out/in once finished.
Verify Developer Tools Installation
After rebooting or logging back in, confirm the compiler toolchain is working:
# Check that the C compiler (cc) is available and functioning
cc -v
# Expected output (varies slightly by build)
# Reading specs from /lib/i386/specs
# NeXT Software, Inc. version cc-744.13, gcc version 2.7.2.1
perl -v
# Expected output
#
# This is perl, version 5.001
#
# Unofficial patchlevel 1m.
#
# Copyright 1987-1994, Larry Wall
#
# Perl may be copied only under the terms of either the Artistic License or the
# GNU General Public License, which may be found in the Perl 5.0 source kit.
# Confirm other key tools exist
which cc
which ld
which make
which ar
# Check library and include directories
ls /NextDeveloper/Headers
ls /NextDeveloper/Lib
After installing the Developer Tools, verify that Compile and run it to confirm your toolchain is functioning: You should see system info, the current date, and your user details — proof your NeXT compiler and environment are alive and kicking.Example: Build and run a NeXT-friendly Hello World test
cc is working with this simple C program:/*
* hello.c — NeXT-friendly Hello World demo
* Compatible with OPENSTEP/NeXTSTEP cc
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/param.h>
/* Try to include uname if it exists */
#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
#endif
int main()
{
time_t now;
char *timestr;
FILE *fp;
char buf[256];
#ifdef HAVE_SYS_UTSNAME_H
struct utsname sys;
#endif
now = time((time_t *)0);
timestr = ctime(&now);
if (timestr && timestr[strlen(timestr) - 1] == '\n')
timestr[strlen(timestr) - 1] = '\0';
printf("=====================================\n");
printf(" Hello from NeXT/OpenStep Unix!\n");
printf("=====================================\n\n");
#ifdef HAVE_SYS_UTSNAME_H
if (uname(&sys) == 0)
printf("System: %s %s (%s)\nNode: %s\n",
sys.sysname, sys.release, sys.machine, sys.nodename);
else
printf("System information unavailable.\n");
#else
printf("System information unavailable (no uname support).\n");
#endif
printf("Date: %s\n\n", timestr ? timestr : "(unknown)");
printf("Running 'whoami' and 'uptime'...\n\n");
fp = popen("whoami", "r");
if (fp) {
if (fgets(buf, sizeof(buf), fp) != NULL) {
buf[strcspn(buf, "\n")] = '\0';
printf("User: %s\n", buf);
}
pclose(fp);
}
fp = popen("uptime", "r");
if (fp) {
if (fgets(buf, sizeof(buf), fp) != NULL)
printf("Uptime: %s", buf);
pclose(fp);
}
printf("\nAll systems nominal.\n");
printf("=====================================\n");
return 0;
}cc hello.c -o hello
./hello
=====================================
Hello from NeXT/OpenStep Unix!
=====================================
System information unavailable (no uname support).
Date: Tue Nov 4 19:32:19 2025
Running 'whoami' and 'uptime'...
User: me
Uptime: 7:32pm up 9:31, 3 users, load average: 2.99, 2.33, 1.73
All systems nominal.
=====================================
Bash shell
Install a better shell and set your account to use it.
You can download a working pkg to install bash2 from bash.2.0.NIHS.b.tar.gz. This contemporary version supports tab completion and many other niceties over csh.
You can also grab a copy of tcsh if you prefer from tcsh.6.06.NIHS.b.gz
TIP When browsing archives of NeXT software, you are looking for NIHS or NI or I versions where the I stands for Intel and b denotes that the tarball contains a binary or pkg installer or bs meaning it contains binaries and source.
To Install
- use FileZilla to ftp to the IP or hostname of the VM using your me credentials and transfer the shell tarballs to
/me/src/ - on NeXT, login as root and run the
bash.pkgin/me/src
This will install bash to /usr/gnu/bin/bash
Bash Startup Dotfiles
You’ll also need a good .bashrc and .bash_profile
TIP before building vim and termcap, :set paste will not be available in vi and pasting into your editor from telnet will mess up the formatting. It might be easiest to create the following file and ftp it to /me. Just remember to use ASCII and do it on Linux or run dos2unix on it before ftp’ing.
If you don’t have a working editor yet, you can create the Alternative: Create .bashrc via heredoc in telnet (before vim is installed)
.bashrc file directly from the shell using a heredoc:cat > ~/.bashrc << 'EOF'
# ~/.bashrc OPENSTEP BASH2 QOL
export HISTFILE=~/.bash_history
export HISTSIZE=5000
export EDITOR=vim
export VISUAL=vim
export PAGER=less
export TERMCAP=/etc/termcap
export TERM=openstep-safe
export PATH="/usr/local/bin:/usr/etc:/usr/ucb:/usr/gnu/bin:/usr/local/games:/usr/bin:/bin:$PATH"
export MANPATH=/usr/local/man:/usr/man
# Prompt
#PS1='\[\033[1;36m\]\u@\h:\w\$ \[\033[0m\]'
# ANSI-safe color codes
USER_COLOR='\[\033[1;36m\]' # Cyan
AT_COLOR='\[\033[1;34m\]' # Blue
HOST_COLOR='\[\033[1;36m\]' # Cyan again
FRAME_COLOR='\[\033[1;33m\]' # Yellow brackets
PATH_COLOR='\[\033[0;37m\]' # Normal white path
RESET='\[\033[0m\]'
# Final PS1
#PS1="${FRAME_COLOR}[ ${USER_COLOR}\u${AT_COLOR}@${HOST_COLOR}\h${FRAME_COLOR} ]${PATH_COLOR}:\w ${RESET}\\$ "
PS1="${FRAME_COLOR}[ ${USER_COLOR}\u${AT_COLOR}@${HOST_COLOR}\h${FRAME_COLOR} ]${PATH_COLOR}:\w ${RESET}\\$ ${RESET} "
stty erase '^?'
eval `dircolors`
# Aliases
alias ls='ls --color=auto -F'
alias ll='ls -lagF'
alias la='ls -aF'
alias cls='clear'
alias termcheck='od -c' # Inspect key sequences
alias vtest='TERM=openstep-safe vim -u NONE -N' # Launch Vim with minimal config
# Enable some shell options
set -o emacs # emacs-style command line (default)
shopt -s histappend # preserve history between sessions
shopt -s checkwinsize # auto resize terminal columns
# Functions (yes, bash 2 has these!)
extract() {
if [ -f "$1" ]; then
case "$1" in
*.tar.bz2) bzip2 -dc "$1" | tar xf - ;;
*.tar.gz) gzip -dc "$1" | tar xf - ;;
*.bz2) bunzip2 "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.tar.Z) uncompress -c "$1" | tar xf - ;;
*) echo "Unknown archive format." ;;
esac
else
echo "'$1' is not a valid file"
fi
}
if [ -x /usr/local/games/fortune ]; then
echo
/usr/local/games/fortune
echo
fi
EOF
# Also create .bash_profile
cat > ~/.bash_profile << 'EOF'
[ -f "$HOME/.bashrc" ] && source "$HOME/.bashrc"
EOF
# Source it to apply changes
source ~/.bashrc
.bashrc
# ~/.bashrc OPENSTEP BASH2 QOL
export HISTFILE=~/.bash_history
export HISTSIZE=5000
export EDITOR=vim
export VISUAL=vim
export PAGER=less
export TERMCAP=/etc/termcap
export TERM=openstep-safe
export PATH="/usr/local/bin:/usr/etc:/usr/ucb:/usr/gnu/bin:/usr/local/games:/usr/bin:/bin:$PATH"
export MANPATH=/usr/local/man:/usr/man
# Prompt
#PS1='\[\033[1;36m\]\u@\h:\w\$ \[\033[0m\]'
# ANSI-safe color codes
USER_COLOR='\[\033[1;36m\]' # Cyan
AT_COLOR='\[\033[1;34m\]' # Blue
HOST_COLOR='\[\033[1;36m\]' # Cyan again
FRAME_COLOR='\[\033[1;33m\]' # Yellow brackets
PATH_COLOR='\[\033[0;37m\]' # Normal white path
RESET='\[\033[0m\]'
# Final PS1
#PS1="${FRAME_COLOR}[ ${USER_COLOR}\u${AT_COLOR}@${HOST_COLOR}\h${FRAME_COLOR} ]${PATH_COLOR}:\w ${RESET}\\$ "
PS1="${FRAME_COLOR}[ ${USER_COLOR}\u${AT_COLOR}@${HOST_COLOR}\h${FRAME_COLOR} ]${PATH_COLOR}:\w ${RESET}\\$ ${RESET} "
stty erase '^?'
eval `dircolors`
# Aliases
alias ls='ls --color=auto -F'
alias ll='ls -lagF'
alias la='ls -aF'
alias cls='clear'
alias termcheck='od -c' # Inspect key sequences
alias vtest='TERM=openstep-safe vim -u NONE -N' # Launch Vim with minimal config
# Enable some shell options
set -o emacs # emacs-style command line (default)
shopt -s histappend # preserve history between sessions
shopt -s checkwinsize # auto resize terminal columns
# Functions (yes, bash 2 has these!)
extract() {
if [ -f "$1" ]; then
case "$1" in
*.tar.bz2) bzip2 -dc "$1" | tar xf - ;;
*.tar.gz) gzip -dc "$1" | tar xf - ;;
*.bz2) bunzip2 "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.tar.Z) uncompress -c "$1" | tar xf - ;;
*) echo "Unknown archive format." ;;
esac
else
echo "'$1' is not a valid file"
fi
}
if [ -x /usr/local/games/fortune ]; then
echo
/usr/local/games/fortune
echo
fi
.bash_profile
[ -f "$HOME/.bashrc" ] && source "$HOME/.bashrc"
You should now have bash available which is much nicer to use than csh.
NOTEIf you get a message about with the prompt TERM= in your shell, just type vt100. We’ll fix that in the next section with a new termcap and TERM setting.
Setting Shell for Your User Account
After installing Bash, you can set it as your login shell using UserManager.app.
-
Open /NextAdmin/UserManager.app as
root. -
From the menu, choose
User ▸ Open, then double-click your account (me). -
In the User Information window, locate the Login shell field and replace the existing entry with
/usr/gnu/bin/bash -
Choose User ▸ Save, confirm in the pop-up dialog, and click OK.
-
Repeat the process for the
rootaccount if desired. -
Edit
/etc/shellsand append/usr/gnu/bin/bashThis ensures Bash is recognized as a valid shell. -
Log out and log back in to start a new Bash session.
Editor – Vim 5.3 & Termcap Fixes
“Real editors never die; they just :q!”
— NeXT OpenStep Restoration Project, 2025
Overview
This guide explains how to install a fully working Vim 5.3 on NeXTSTEP / OpenStep 4.2 (Intel) using a prebuilt GNU Termcap bundle. It replaces NeXT’s broken libtermlib with a proper libtermcap.a and eliminates arrow-key and Delete/Backspace issues.
This was relatively difficult to port but it makes the system so much nicer to use that it was well worth it. If you want to see what I did you can download an unmodified copy of vim 5.3 and diff with mine. There are numerous edits and shims to get it to work. Running vim --version will show the compile options. I wouldn’t recommend it as a good time.
The result: Vim is a useful editor and a huge upgrade over the built-in, barebones vi
Required Sources
Before beginning, grab the two prepared packages from the restoration project:
📦 GNU Termcap 1.3.1 (for OpenStep)
termcap131_openstep_bundle — Archive.org
Includes libtermcap.a, headers, and man pages rebuilt for OpenStep 4.2 (Intel).
This replaces NeXT’s broken libtermlib.a and restores full key-sequence support.
🧰 Vim 5.3 (native OpenStep build)
vim-5.3-openstep-intel — Archive.org
Contains a fully compiled Vim 5.3 binary, runtime tree, and manual page — ready to install.
These contain the standard source file plus my modifications to get them to build and binaries ready to copy into place.
Install the GNU Termcap Bundle
Download from Archive.org, ftp to /me/src on the VM and extract:
su
cd /me/src
gunzip termcap_openstep_bundle.tar.gz
tar -xvf termcap_openstep_bundle.tar
mkdir /usr/local
mkdir /usr/local/lib
mkdir /usr/local/include
cp /me/src/termcap_openstep_bundle/termcap-1.3.1/libtermcap.a /usr/local/lib/
cp /me/src/termcap_openstep_bundle/termcap-1.3.1/termcap.h /usr/local/include/
cat /me/src/termcap_openstep_bundle/etc_termcap.openstep-safe >> /etc/termcap
Setting the Environment Variables
echo 'export TERMCAP=/etc/termcap' >> ~/.bashrc
echo 'export TERM=openstep-safe' >> ~/.bashrc
. ~/.bashrc
(If mkdir reports “File exists,” you can safely ignore it.)
Install Vim 5.3
Download from archive.org, ftp the tarball to /me/src on the VM and extract:
su
cd /me/src
# Extract
gunzip vim5.3-OpenStep-Intel.tar.gz
tar -xvf vim5.3-OpenStep-Intel.tar
cd vim5.3-OpenStep/
# Create destination paths (no -p on NeXT)
mkdir /usr/local
mkdir /usr/local/bin
mkdir /usr/local/share
mkdir /usr/local/share/vim
mkdir /usr/local/man
mkdir /usr/local/man/man1
# Copy the compiled Vim binary into place
cp src/vim /usr/local/bin/vim
chmod 755 /usr/local/bin/vim
# Copy runtime and support files
cp menu.vim bugreport.vim vimrc_example gvimrc_example /usr/local/share/vim/
cp -R macros syntax termcap tutor /usr/local/share/vim/
# Copy documentation and manpage
cp -R doc /usr/local/share/vim/
cp doc/vim.1 /usr/local/man/man1/
chmod 644 /usr/local/man/man1/vim.1
# Verify the installation
/usr/local/bin/vim --version
Ensure /etc/termcap includes the openstep-safe entry
(from the termcap_openstep_bundle.tar.gz package).
NOTE Make sure to set your ftp transfer mode correctly during these steps. If you set ASCII and then transfer binary content it will be corrupt. If you set binary when tranferring things like .bashrc or .vimrc, you will see artifacts like ^M and oddly rendered invalid characters. check that if a file doesn’t work at first and try again
Configure the Terminal Environment
Update .bashrc
Your .bashrc should already exist from earlier steps Part 1, but confirm that it includes the following lines:
export TERMCAP=/etc/termcap
export TERM=openstep-safe
export PATH="/usr/local/bin:/usr/etc:/usr/ucb:/usr/gnu/bin:/usr/local/games:/usr/local/bin:/usr/bin:/bin:$PATH"
stty erase '^?'
If these are missing, add them manually with vi or cat >> ~/.bashrc.
Add man page path
You should already have this in your .bashrc but if you didn’t use the one in Part 1 then make sure to add the following to yours
echo 'export MANPATH=/usr/local/man:/usr/man' >> ~/.bashrc
Reload your configuration:
. ~/.bashrc
(Remember that stty erase '^?' ensures the Delete key behaves properly when editing.)
Configure Vim Key Behavior
Now that we have a better termcap and the openstep-safe profile to use as our $TERM, we can add a .vimrc to establish some decent settings and most importantly to fix some problem behaviors involving how the cursor, backspace, and delete keys are handled and to suppress some ugly ACS artifacts when displaying line numbers with :set numbers
If you don’t yet have Vim running or prefer to create the configuration non-interactively, you can generate your Alternative: Create .vimrc via heredoc (no editor required)
.vimrc using a heredoc:cat > ~/.vimrc << 'EOF'
" ======================================================================
" ~/.vimrc -- Vim 5.3 on OPENSTEP 4.2
" forfaxx@adminjitsu.com
" ======================================================================
" ----- Core behavior -----
set nocompatible
set autoindent
set smartindent
set showmode
set ruler
set number
set nowrap
set noerrorbells
set visualbell
set laststatus=2
set incsearch
set ignorecase
set smartcase
set hlsearch
set tabstop=4
set shiftwidth=4
set expandtab
set modeline
set showcmd
set backspace=2
" ----- Terminal & key behavior -----
" Backspace/Delete fix
execute "map! " . nr2char(127) . " <BS>"
execute "nmap " . nr2char(127) . " X"
inoremap <BS> <Del>
" ----- Paste mode toggle -----
" Vim 5.3 lacks 'pastetoggle', emulate manually
nmap <C-P> :set invpaste paste?<CR>
imap <C-P> <C-O>:set invpaste paste?<CR>
set paste
" ----- Visual tweaks -----
if has("syntax")
syntax on
endif
set background=dark
set t_Co=8
" Disable ACS line-drawing artifacts (no fillchars in 5.3)
"if &term == "openstep-safe"
" set vt100
"endif
" ----- File handling -----
set nobackup
set nowritebackup
set noswapfile
set hidden
" ----- Convenience mappings -----
nmap <F2> :w<CR>
nmap <F3> :q<CR>
nmap <F4> :wq<CR>
nmap <F12> :e $HOME/.vimrc<CR>
EOF
.vimrc
" ======================================================================
" ~/.vimrc -- Vim 5.3 on OPENSTEP 4.2
" forfaxx@adminjitsu.com
" ======================================================================
" ----- Core behavior -----
set nocompatible
set autoindent
set smartindent
set showmode
set ruler
set number
set nowrap
set noerrorbells
set visualbell
set laststatus=2
set incsearch
set ignorecase
set smartcase
set hlsearch
set tabstop=4
set shiftwidth=4
set expandtab
set modeline
set showcmd
set backspace=2
" ----- Terminal & key behavior -----
" Backspace/Delete fix
"map! ^? <BS> " make DEL behave like Backspace
"map ^? X " delete left in normal mode
"map! <BS> <Del> " optional: swap behavior if needed
execute "map! " . nr2char(127) . " <BS>"
execute "nmap " . nr2char(127) . " X"
inoremap <BS> <Del>
" ----- Paste mode toggle -----
" Vim 5.3 lacks 'pastetoggle', emulate it manually
nmap <C-P> :set invpaste paste?<CR>
imap <C-P> <C-O>:set invpaste paste?<CR>
set paste
" ----- Visual tweaks -----
if has("syntax")
syntax on
endif
set background=dark
set t_Co=8
" Disable ACS line-drawing artifacts (no fillchars in 5.3)
"if &term == "openstep-safe"
" set vt100
"endif
" ----- File handling -----
set nobackup
set nowritebackup
set noswapfile
set hidden
" ----- Convenience mappings -----
nmap <F2> :w<CR>
nmap <F3> :q<CR>
nmap <F4> :wq<CR>
nmap <F12> :e $HOME/.vimrc<CR>
At this point you should have a working vim with good termcap behaviors just like in the VirtualBox ova appliance. One thing that really helps when trying to copy and paste through vim over telnet is to hit escape to enter command mode then the colon and the command :set paste. You can then paste in long text passages like the .vimrc and .bashrc without vim mangling the indentation. When you’re done you can save with :wq or :w and enter :set nopaste to disable.
In the .vimrc above, I have mapped Ctrl-P to toggle between paste modes (which disables auto-indent and line wrapping and other insert mode features that get in the way)
TIP Before experimenting further, make a snapshot of your VM. OpenStep’s filesystems can be delicate — you’ll thank yourself later.
Adding Fileutils and Textutils
To complete the core UNIX userland on OPENSTEP 4.2, you’ll want modern implementations of the GNU Fileutils and Textutils packages. These provide many of the essential commands expected on a contemporary UNIX system — including ls, cp, mv, sort, uniq, and more — all built natively for the NeXT environment.
Required Sources
Both archives are available from GNU mirrors or preservation repositories (such as ftp.gnu.org mirrors or Archive.org).
Building and Installing
fileutils
su
gunzip fileutils-3.16.tar.gz
tar xvf fileutils-3.16.tar
cd fileutils-3.16
sh ./configure --prefix=/usr/local
make
make install
cd ..
textutils
gunzip textutils-1.19.tar.gz
tar xvf textutils-1.19.tar
cd textutils-1.19
sh ./configure --prefix=/usr/local
make
make install
exit
Installed Tools
After installation, /usr/local/bin should contain a full suite of GNU utilities, including:
cat comm df fmt ln mknod pr strfile touch vdir
chgrp cp dir fold ls mv rm sum tr vim
chmod csplit dircolors head md5sum nl rmdir sync unexpand wc
chown cut du install mkdir od sort tac uniq
cksum dd expand join mkfifo paste split tail unstr
With these installed, OPENSTEP behaves much more like a late-90s GNU environment, allowing most shell scripts and build tools to run without modification.
TIP
If you’ve followed this tutorial in order, /usr/local/bin should appear at the beginning of your $PATH.
On NeXT, the which command uses hard-coded search paths — instead, run:
echo $PATH
dos2unix and unix2dos
Before beginning, grab the prepared package from the restoration project:
🧩 dos2unix 5.2 (OPENSTEP Port)
dos2unix-5.2-openstep — Archive.org
Includes fully working dos2unix and unix2dos binaries, source code, and corrected Makefile for OPENSTEP 4.2 (Intel).
This port fixes missing libgen.h and mode_t definitions, adds compatibility stubs for querycp, and ensures clean builds using NeXT’s native cc and /usr/bin/install.
# Clean any previous object files or binaries
make clean
# Build both dos2unix and unix2dos
make
# Install the binaries and man pages as root
su
make install
exit
The updated Makefile for OPENSTEP automatically handles:
- Ensuring
/usr/local/binand/usr/local/man/man1exist before installation - Installing the binaries:
/usr/local/bin/dos2unix/usr/local/bin/unix2dos
- Installing the manpage (if present):
/usr/local/man/man1/dos2unix.1- (Unix2dos uses the same manpage; it’s symlinked internally)
You can verify both tools work:
# Create a DOS-style test file
echo -e "Hello world.\r\nThis is a DOS line.\r\nAnd another.\r\n" > test_dos.txt
# Convert it to Unix format
/usr/local/bin/dos2unix test_dos.txt
# Inspect it
od -c test_dos.txt
# Convert it back to DOS
/usr/local/bin/unix2dos test_dos.txt
# Inspect it again
od -c test_dos.txt
✅ Notes
- Both programs are fully self-contained and compile cleanly under the OPENSTEP developer tools.
- The Makefile uses
/usr/bin/installfor compatibility with NeXT’s environment (no-pflag). - NeXT lacks pod2man so I bundled the resulting manpage from linux.
- This version replaces the missing
libgen.h,mode_t, andquerycpfunctions with portable local definitions. - You can safely re-run
make install; it will overwrite binaries but not break the environment.
Replacing the Broken grep with GNU grep 2.2
The stock grep shipped with OpenStep 4.2 is badly broken — -q, -v, and long options fail outright.
We can replace it with a working GNU grep 2.2 built natively using the NeXT toolchain.
Download the verified working build from Archive.org:
📦 Download grep-2.2-openstep-intel
Upload the tarball to /me/src on your VM using binary mode FTP
Steps
cd ~/src
gunzip grep-2.2.tar.gz
tar -xvf grep-2.2.tar
cd grep-2.2
# fix timestamps and permissions
find . -exec touch {} \;
chmod u+x configure
# configure and build
./configure --prefix=/usr/local --disable-nls
make CC="/bin/cc" LD="/bin/ld" \
CFLAGS="-O2 -arch i486 -traditional-cpp" \
LDFLAGS="-lSystem -lc"
# test the result
cd src
./grep --version
echo foo | ./grep -q foo && echo "grep works"
# install
su
make install
exit
This installs the new binaries and manpages to:
/usr/local/bin/grep
/usr/local/bin/egrep
/usr/local/bin/fgrep
/usr/local/man/man1/grep.1
NOTE
No need to replace the system binary — as long as /usr/local/bin appears before /bin in your $PATH, your shell will automatically prefer the new version. If you’ve followed the earlier bash configuration, you’re already covered.
Verification
grep --version
grep -q foo <<< foo && echo OK
echo -e "foo\nbar" | grep -v foo
Expected output:
grep (GNU grep) 2.2
OK
bar
✅ Your OpenStep environment now has a fully functional grep with standard GNU options, completing the core text-processing toolchain alongside textutils and fileutils.
top
Now we’ll add top to make it easier to keep an eye on resource usage and processes.
You can grab a prebuilt binary from 🔗 fsck.technology
Transfer it to /me/src on your VM and unpack:
su
cd /me/src
gunzip top.0.5.NI.b.tar.gz
tar -xvf top.0.5.NI.b.tar
cd top-v0.5
Copy the binary and set the proper ownership and permissions so it can read kernel memory:
NOTE You don’t see this much on modern systems — with sudo, privilege separation, and ACLs doing the heavy lifting — but setuid binaries were once a common (and slightly terrifying) way to let normal users perform privileged actions safely.
cp top /usr/local/bin/top
chmod 4755 /usr/local/bin/top
chown root.kmem /usr/local/bin/top
ls -al /usr/local/bin/top
There’s also a man page included — install it to /usr/local/man/man1:
mkdir /usr/local/man/man1 2>/dev/null
cp top.1 /usr/local/man/man1/
chmod 644 /usr/local/man/man1/top.1
Test it:
man top
top
If everything’s right, you’ll see a live process list with CPU and memory stats.
Press q to exit.
CUBX X11R6
This was easy to set up. Just grab the iso and serial number from archive.org or from the NeXT archive here
Steps
- login as root
- attach the iso to Virtualbox
- when it appears in the file viewer, click on the cd and double-click on
ISInstaller.appThis will prompt for the serial number - You probably want to choose Client when prompted.
- The installer will then install and configure the system
NOTE When installing CUB’X Windows 5, you can choose Server (to receive remote X11 apps drawn on your OpenStep desktop) or Client (to send X apps from OpenStep to another display).
Use the server mode if you want to integrate modern Unix apps into your NeXT workspace; use the client mode if you prefer to open OpenStep X programs on another host’s screen.See X11 display forwarding explained for a solid overview of how exported displays work.
This gives you xterm which is much nicer to use than the built in Terminal as well as a host of standard x11 apps and the ability to build more (you’ll want to look for releases from 1994-1999 typically that would have been contemporaneous )
Try running xeyes & and enjoy having xterm available.
TIP Before experimenting further, make a snapshot of your VM. This is a good place to save.
w3c-httpd
This is version 3.0A of the original CERN httpd web server — the first web server developed by Tim Berners-Lee on NeXTSTEP.
This port has been rebuilt and tested natively under OPENSTEP 4.2 Intel, using the original toolchain (cc = gcc 2.7.2.1) with no GNU dependencies.
Required Sources
Download the verified working build from Archive.org:
📦 Download w3c-httpd-3.0A.next.i486.tar.gz
https://archive.org/download/w3c-httpd-3.0A.next.i486/w3c-httpd-3.0A.next.i486.tar.gz
Upload the tarball to /me/src on your VM using binary mode (FTP or NFS).
Installing CERN httpd 3.0A
# Navigate to your source directory
cd /me/src
# Extract the source archive
gunzip cern-httpd-3.0A-openstep-bin.tar.gz
tar -xvf cern-httpd-3.0A-openstep-bin.tar
cd w3c-httpd-3.0A
# Become root
su
Create the target install layout:
mkdir -p /usr/local/httpd/bin
mkdir -p /usr/local/httpd/lib
mkdir -p /usr/local/httpd/conf
mkdir -p /usr/local/httpd/logs
mkdir -p /usr/local/httpd/html
NOTE If you haven’t followed the previous steps in this tutorial and installed fileutils, you will need to run mkdir without -p and create both /usr, /usr/local and /usr/local/httpd manually before creating the subdirs in the steps above.
Install the compiled binaries and library:
install -m 0755 Daemon/next/httpd /usr/local/httpd/bin/httpd
install -m 0755 Daemon/next/htadm /usr/local/httpd/bin/htadm
install -m 0755 Daemon/next/htimage /usr/local/httpd/bin/htimage
install -m 0755 Daemon/next/cgiparse /usr/local/httpd/bin/cgiparse
install -m 0755 Daemon/next/cgiutils /usr/local/httpd/bin/cgiutils
install -m 0644 Library/next/libwww.a /usr/local/httpd/lib/libwww.a
Create a working configuration file for port 80 and user pages:
WARNING About Port 80 and the nobody user:
Binding to port 80 requires root privileges, but the daemon drops to the nobody user after startup for security. The HostName directive should match your VM’s actual IP address — adjust 192.168.1.50 to your network configuration. If you prefer to avoid running as root, change Port 80 to Port 8080 (or any port above 1024) and start the daemon as a regular user.
cat >/usr/local/httpd/conf/httpd.conf <<'EOF'
ServerRoot /usr/local/httpd
Port 80
User nobody
Group nobody
HostName 192.168.1.50
DocumentRoot /usr/local/httpd/html
LogFile /usr/local/httpd/logs/access_log
ErrorLog /usr/local/httpd/logs/error_log
Protect / none
Pass / /usr/local/httpd/html/*
Pass /~me* /me/public_html/*
Protect /~me* none
EOF
And a test HTML document:
mkdir -p /me/public_html
chmod 755 /me /me/public_html
cat >/usr/local/httpd/html/index.html <<'EOF'
<!DOCTYPE html>
<html><body><h1>Welcome to CERN httpd 3.0A on OpenStep!</h1></body></html>
EOF
cat >/me/public_html/index.html <<'EOF'
<!DOCTYPE html>
<html><body><h1>Hello from ~me on OpenStep!</h1></body></html>
EOF
Running the Server
Start the daemon manually:
/usr/local/httpd/bin/httpd &
You should see output similar to:
............ This is CERN-HTTPD, version 3.0A, using libwww version 2.17
ServerType.. standalone
Reading..... /usr/local/httpd/conf/httpd.conf
Verify the process:
ps aux | grep httpd
Check logs:
tail -n 5 /usr/local/httpd/logs/error_log
Testing
From your host or another VM:
curl http://192.168.1.50/
curl http://192.168.1.50/~me/
Expected result:
<h1>Welcome to CERN httpd 3.0A on OpenStep!</h1>
<h1>Hello from ~me on OpenStep!</h1>
If you’re using OmniWeb, Mosaic, or an early Netscape build, both pages should render correctly.
Auto-start at Boot
Add CERN httpd to /etc/rc.local so it launches automatically after networking:
WARNING Security consideration:
This configuration runs httpd as root initially to bind port 80, then drops to nobody. On a private network VM this is acceptable, but never expose this server to the public internet — it lacks modern security features and uses unencrypted HTTP only. Consider using port 8080 or adding this VM to an isolated network segment.
cat >>/etc/rc.local <<'EOF'
# Start CERN httpd 3.0A
if [ -x /usr/local/httpd/bin/httpd ]; then
echo "Starting CERN httpd 3.0A..." >/dev/console
/usr/local/httpd/bin/httpd &
fi
EOF
chmod +x /etc/rc.local
You can test immediately without rebooting:
/etc/rc.local
Confirm it’s running:
ps aux | grep httpd
At the next reboot, the daemon will start automatically and serve your pages from
http://192.168.1.50/ and http://192.168.1.50/~me/.
Notes
- This build uses native OpenStep tools only — no GNU Make, no bash, no BSD ports.
- Configuration format matches CERN httpd 3.x syntax exactly.
- Runs safely in standalone mode on port 80.
- Logs and HTML documents live under
/usr/local/httpd/for simplicity.
You now have a fully installed and operational CERN httpd 3.0A daemon, serving web content from OpenStep just like the first webserver.
TIP This is another friendly reminder to save a snapshot in VirtualBox!
fortune-mod 9708 & Custom Sets
A UNIX system without fortune is a sterile, joyless place. I even wrote an entire post celebrating its shenanigans —
Fortune Favors the Sysadmin.
So naturally, we’re going to need a working copy on OPENSTEP.
Neat but we'll be installing fortune-mod with everything included
Required Sources
Start by grabbing my fortune-mod-9708 port from archive.org
📦 Download fortune-mod-9708 for OPENSTEP 4.2
Building and Installing fortune-mod-9708 port
Set FTP transfer mode to binary and upload fortune-mod-9708-openstep.tar.gz to /me/src on the VM.
# Navigate to your source directory
cd /me/src
# Extract the source archive
gunzip fortune-mod-9708-openstep.tar.gz
tar -xvf fortune-mod-9708-openstep.tar
cd fortune-mod-9708-openstep
# Clean any previous builds
make clean
# Build the binaries and cookie databases
make
# Install everything as root (fortune, utilities, manpages, and data)
su
make install
exit
The install target now handles everything automatically:
-
Creates required directories if they don’t exist:
/usr/local/games/usr/local/share/games/fortunes/usr/local/bin/usr/local/man/man6/usr/local/man/man1
-
Installs the compiled binaries:
/usr/local/games/fortune/usr/local/bin/strfile/usr/local/bin/unstr
-
Generates and installs the manpages:
/usr/local/man/man6/fortune.6/usr/local/man/man1/strfile.1(withunstr.1symlink)
-
Copies all fortune cookie databases (
*.datand subdirs) into/usr/local/share/games/fortunes/.
Verify it works as expected
You can verify it works:
/usr/local/games/fortune
/usr/local/games/fortune startrek
/usr/local/games/fortune zippy
If you want to add your own fortune sets, place them in
datfiles/, then rebuild the indexes:
cd datfiles
/usr/local/bin/strfile myfortunes
Your new set appears automatically under
/usr/local/share/games/fortunes/myfortunes.
✅ Notes
- This Makefile is OPENSTEP-compatible and idempotent: re-running
make installwon’t break existing installs. - You no longer need to manually copy files or run
strfile— the build handles everything. - Manpages and directories are generated cleanly with the correct permissions.
“Absolutum obsoletum. (If it works, it’s out of date.)” – Stafford Beer
Installing GUI Apps & Packages
There are a ton of downloads available on archive.org and fsck.technology. They tend to come in a few flavors:
-
tarballs (file.tar.gz)
- you want ones with NIHS, NI and/or b or bs in the title
- These will contain a README or INSTALL with instructions
- typically you’ll use something like make install as directed by the documentation in the archive.
-
tarballs containing source only, not ported to NeXT. You’ll have to figure these out. Some are easy, some aren’t. Try to find releases from around 1995-1998
-
.pkgfiles. Login as root and double-click the .pkg file to run the installer alternatively you can launch with /NextAdmin/Installer.app/Installer packagename.pkg -
.appbundles As long as it contains an Intel Mach binary, these can be run from anywhere. You probably want to copy these to either /me/Apps or /LocalApps or even /NextApps
Running nmap Against nextcube
When you scan nextcube from a modern host:
nmap -A -p- -T4 -v nextcube
It lights up like a slot machine of open ports — Telnet, FTP, Finger, rlogin, exec, SMTP, and friends.
A living exhibit of 90s networking.
Show full Nmap scan output for nextcube.darkstar.home
┌──[ grumble@shinobi ]:~/codelab/adminjitsu (main)
└─$ nmap -A -p- -T4 -v nextcube.darkstar.home
Starting Nmap 7.80 ( https://nmap.org ) at 2025-11-03 17:14 CST
NSE: Loaded 151 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 17:14
Completed NSE at 17:14, 0.00s elapsed
Initiating Ping Scan at 17:14
Scanning nextcube.darkstar.home (192.168.1.50) [2 ports]
Completed Ping Scan at 17:14, 0.20s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 17:14
Completed Parallel DNS resolution of 1 host. at 17:14, 0.01s elapsed
Initiating Connect Scan at 17:14
Scanning nextcube.darkstar.home (192.168.1.50) [65535 ports]
Discovered open port 23/tcp on 192.168.1.50
Discovered open port 111/tcp on 192.168.1.50
Discovered open port 25/tcp on 192.168.1.50
Discovered open port 21/tcp on 192.168.1.50
Discovered open port 19/tcp on 192.168.1.50
Discovered open port 7/tcp on 192.168.1.50
Discovered open port 79/tcp on 192.168.1.50
Discovered open port 2453/tcp on 192.168.1.50
Discovered open port 706/tcp on 192.168.1.50
Discovered open port 13/tcp on 192.168.1.50
Discovered open port 513/tcp on 192.168.1.50
Discovered open port 515/tcp on 192.168.1.50
Discovered open port 514/tcp on 192.168.1.50
Discovered open port 37/tcp on 192.168.1.50
Discovered open port 512/tcp on 192.168.1.50
Discovered open port 9/tcp on 192.168.1.50
Discovered open port 709/tcp on 192.168.1.50
Discovered open port 178/tcp on 192.168.1.50
Completed Connect Scan at 17:25, 677.52s elapsed (65535 total ports)
Initiating Service scan at 17:25
Scanning 18 services on nextcube.darkstar.home (192.168.1.50)
Completed Service scan at 17:28, 163.85s elapsed (18 services on 1 host)
NSE: Script scanning 192.168.1.50.
Initiating NSE at 17:28
Completed NSE at 17:28, 29.77s elapsed
Nmap scan report for nextcube.darkstar.home (192.168.1.50)
Host is up (0.0054s latency).
Not shown: 65497 closed ports
PORT STATE SERVICE VERSION
7/tcp open echo
9/tcp open discard?
13/tcp open daytime Sun Solaris daytime
19/tcp open chargen
21/tcp open ftp
| fingerprint-strings:
| GenericLines:
| 220 nextcube FTP server (Version 5.1 (NeXT 1.0) Tue Jan 26, 1999) ready.
| command not understood.
| command not understood.
| NULL, SMBProgNeg:
| 220 nextcube FTP server (Version 5.1 (NeXT 1.0) Tue Jan 26, 1999) ready.
| SSLSessionReq:
| 220 nextcube FTP server (Version 5.1 (NeXT 1.0) Tue Jan 26, 1999) ready.
|_ command not understood.
| ftp-syst:
| SYST: Version: BSD-43
| STAT:
| nextcube FTP server status:
| Version 5.1 (NeXT 1.0) Tue Jan 26, 1999
| Connected to 192.168.1.51 (192.168.1.51)
| Waiting for user name
| TYPE: ASCII, FORM: Nonprint; STRUcture: File; transfer MODE: Stream
| No data connection
|_End of status
23/tcp open telnet IRIX telnetd 6.X
25/tcp open smtp Sendmail NX5.67g/NX3.0S
|_smtp-commands: SMTP: EHLO 500 Command unrecognized\x0D
37/tcp open time (32 bits)
|_rfc868-time: 2025-11-03T17:28:07
79/tcp open finger SGI IRIX or NeXTSTEP fingerd
| finger: Login Name TTY Idle When Office\x0D
|_me My Account co 1d Mon 00:48 \x0D
111/tcp open rpcbind 2 (RPC #100000)
178/tcp open nextstep?
512/tcp open exec?
| fingerprint-strings:
| Kerberos, SMBProgNeg, afp, oracle-tns:
|_ Login incorrect.
513/tcp open login OpenBSD or Solaris rlogind
514/tcp open tcpwrapped
515/tcp open printer lpd (path: /usr/lib/lpd; error: ....: Malformed from address)
706/tcp open rpcbind
709/tcp open rpcbind
2453/tcp open madge-ltd?
2968/tcp filtered enpp
8649/tcp filtered unknown
10553/tcp filtered unknown
12263/tcp filtered unknown
12651/tcp filtered unknown
13523/tcp filtered unknown
27087/tcp filtered unknown
27860/tcp filtered unknown
30923/tcp filtered unknown
32979/tcp filtered unknown
34521/tcp filtered unknown
35920/tcp filtered unknown
46067/tcp filtered unknown
46934/tcp filtered unknown
47204/tcp filtered unknown
52006/tcp filtered unknown
56233/tcp filtered unknown
62708/tcp filtered unknown
64492/tcp filtered unknown
64498/tcp filtered unknown
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port21-TCP:V=7.80%I=7%D=11/3%Time=690939E9%P=x86_64-pc-linux-gnu%r(NULL
SF:,4A,"220\x20nextcube\x20FTP\x20server\x20\(Version\x205\.1\x20\(NeXT\x2
SF:01\.0\)\x20Tue\x20Jan\x2026,\x201999\)\x20ready\.\r\n")%r(GenericLines,
SF:8C,"220\x20nextcube\x20FTP\x20server\x20\(Version\x205\.1\x20\(NeXT\x20
SF:1\.0\)\x20Tue\x20Jan\x2026,\x201999\)\x20ready\.\r\n500\x20'':\x20comma
SF:nd\x20not\x20understood\.\r\n500\x20'':\x20command\x20not\x20understood
SF:\.\r\n")%r(SSLSessionReq,6D,"220\x20nextcube\x20FTP\x20server\x20\(Vers
SF:ion\x205\.1\x20\(NeXT\x201\.0\)\x20Tue\x20Jan\x2026,\x201999\)\x20ready
SF:\.\r\n500\x20'\x16\x03':\x20command\x20not\x20understood\.\r\n")%r(SMBP
SF:rogNeg,4A,"220\x20nextcube\x20FTP\x20server\x20\(Version\x205\.1\x20\(N
SF:eXT\x201\.0\)\x20Tue\x20Jan\x2026,\x201999\)\x20ready\.\r\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port512-TCP:V=7.80%I=7%D=11/3%Time=69093A18%P=x86_64-pc-linux-gnu%r(Ker
SF:beros,12,"\x01Login\x20incorrect\.\n")%r(SMBProgNeg,12,"\x01Login\x20in
SF:correct\.\n")%r(oracle-tns,12,"\x01Login\x20incorrect\.\n")%r(afp,12,"\
SF:x01Login\x20incorrect\.\n");
Service Info: OSs: Solaris, IRIX, Unix; CPE: cpe:/o:sun:sunos, cpe:/o:sgi:irix
Host script results:
|_clock-skew: -6h00m02s
NSE: Script Post-scanning.
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 876.65 seconds
WARNING
Keep nextcube off the public internet. It’s historically authentic and hilariously insecure by design.
Links and Stuff
These install correctly without modification:
Prepared packages and binaries with required modifications:
- grep-2.2-openstep-intel (Archive.org)
- termcap131_openstep_bundle (Archive.org)
- vim-5.3-openstep-intel (Archive.org)
- fortune-mod-9708.OPENSTEP4.2.i486 (Archive.org)
- w3c-httpd-3.0A.next.i486 (Archive.org)
- dos2unix-5.2-openstep
Software highlights in the collection:
Conclusion
At this point, you have a pretty complete OpenStep 4.2 workstation — developer tools, X11, shells, GNU utilities, and the full retro Unix experience.
In the next installment, we’ll publish a short User Guide for the Appliance:
filesystem map, compile examples, file sharing tips, and snapshot management.
It’s been nice having the nextcube VM now that I’ve gotten it to this point. I’d love to hear any feedback if this guide helped you or if I missed something feedback@adminjitsu.com