Legends start at 1.0! – FreeBSD in 1993 (pt. 2)

[New to Gemini? Have a look at my Gemini FAQ.]

This article was bi-posted to Gemini and the Web; Gemini version is here: gemini://gemini.circumlunar.space/users/kraileth/neunix/2022/fbsd1_pt2.gmi

Happy FreeBSD day everyone! 🥳

In part one I covered a little bit of general information and preparation work before detailing the first part of the installation of FreeBSD 1.0 on real hardware. We stopped with having transferred a rump root filesystem and the kernel from two diskettes onto the hard drive.

Part two covers the rest of the installation. We’re going to continue right where we left off.

In case you want to play with FreeBSD 1.0 yourself – I’ve made an image of the drive and zstd-compressed it to make it as small as possible. It contains a bootable 1.0 system with bindist installed and both srcdist and xfree86 sources available, too. Download it here (60 MB compressed, 20 GB uncompressed) and play with it if you like.

Installation: Completing the mini system

I ended the previous part with the question: Will the new system boot from hard disk? Hell yeah, it does! (Ok, I’ll stop putting cheap DooM references in here now. 😈)

The system prints out the usual kernel boot info but then immediately runs another script. It’s pretty obvious that we’re not done with the installation, yet.

Insert cpio installation floppy in drive and
enter that drive's number (0 or 1): [0]

Verbose installation? [n]

Now I need to put the third floppy into the drive and the installation continues. Again, selecting verbose will print out a ton of info while extracting the cpio archive.

Please wait.  Copying to disk...
4483 blocks
183 blocks

Building /dev files...
mknod: zero: File exists
mknod: io: File exists

Install optional dos floppy? [n]

At this point we’ve made it from “can barely boot and continue the installation” to “it’s a minimal FreeBSD system with a much reduced set of tools”. We’re not over the finish line, yet, but certainly getting closer.

The install script asks whether to install the “optional DOS floppy”. This was a means of transferring files over from DOS which was usually used to create the installation floppies (we used dd(1) since we already had a Unix-like system available, but the CDROM also shipped rawrite.exe, a DOS program for creating the installation diskettes from the image files. It also came with two boot managers and those were meant to be copied over using DOS-formatted floppy disk if people needed one.

However in my case, I don’t (even though I admit having been tempted to go with a FreeDOS + FreeBSD dual-boot system just for fun. Since the difference is only one letter, if names mean anything they should be fairly close, shouldn’t they? 😉).

OK. All of the base files are installed.

The next step: reboot from the hard disk.  Further
instructions are presented upon rebooting.

Enter 'halt' now at the prompt to halt the machine.
After the machine has halted, remove the floppy from the disk
drive, and hit any key to reboot from the hard disk.
# halt
syncing disks... done

The operating system has halted.
Please press any key to reboot.

Alright, time to reboot and see what’s different! Indeed fsck fixes a couple of errors and the following message is printed:


NOTE: The above errors are expected if this is the
first time you have booted from the hard disk after
completing the floppy install

Automatic file system check changed the root file system
The system must halt for these corrections to take effect

Ok, good to know. A couple of seconds later, the system reboots again.

Completing the installation: Binary distribution

When it has finished, there’s a new instruction text after the kernel messages:

FreeBSD Base System Release 1.0

Congratulations, you've got FreeBSD on the hard disk!

Press the return key for more installation instructions

To finish installation:
Pick a temporary directory by running set_tmp_dir. Make sure it's
in a place with lots of space, probably under /usr.
Then, load the remaining distribution files into that temporary
directory by issuing one of the following commands:

        load_fd         load_qic_tape   load_scsi_tape

or by fetching the files with ftp (see the installation notes for
information on how to do that).

Once this is complete, extract the distribution files by issuing the
command 'extract <distribution>' where <distribution> is the base name
of the distribution files, e.g. 'base10'.

Once all of the filesets you wish to install have been extracted,
enter the command 'configure' to finish setting up the system

If you should wish to uninstall FreeBSD, delete the partition by using the
DOS 5 FDISK program. If installed on the entire drive, use FDISK/MBR
to remove the FreeBSD bootstrap from the drive.
erase ^?, werase ^H, kill ^L, intr ^C

Oh wow! Here’s the obligatory “congratulations”, but in this case I’ve almost got the feeling that I actually kind of deserve it (they do come really, really cheap today after all). 🙃

We’re going to use load_fd and extract. I suspect that these are helper scripts, but since the system doesn’t have which(1), yet, I didn’t go looking for them and left that for later. At that point I did not yet know that they are gone once the installation completes!

The first one is a handy script that asks for the drive with the medium that holds tha data and the destination directory (default: /user/distrib) once. It then mounts the FAT filesystem on it on a /floppy if I remember correctly, and transfers all the files over. When that’s done, it unmounts the FS and prompts the user to either insert the next floppy or type ‘q’ to quit.

5 of my floppies turned out to have read errors that they didn’t have when I checked before, so I had to replace that and try again. A little bit frustrating, but at that point I was getting used to how it had been back in the day (you put your cool new program / save file / map / whatever on a floppy and when you went to a friend after school, you found out that the darn thing was bad!).

And worse: When I finally had everything copied off without any read errors, I still had a bad feeling. Why? Because on two of my 5 replacement disks I didn’t like the sound that the drive made while copying the data. And indeed: Running the extract command lead to gzip(1) complaining about invalid stream data!

It’s probably a good thing that I still have pretty sharp memories of dealing with floppies. I can imagine how somebody of a later generation, being blissfully ignorant to this kind of trouble, would have lost his temper and went off to do something else at that point! 😣

My suspicion was that floppy disks 5 and 13 were the culprits that had silently provided garbage data. So I replaced them again and tried once more. Instead of using the extract command directly, I did:

cat bin_tgz.* | gunzip -t -v

Right! That “OK” was just what I needed. Now I let extract do its thing again:

extract bin_tgz
Would you like to be verbose about this? [n]

Nah, I know the score by now and there’s no reason for spamming me with all the file names that the base system consists of!

I wanted to install some of the other sets, too, but due to a shortage of good floppies, I needed to re-use those after finally getting bindist installed. So I powered down the system.

Creating a backup image of the system

What if something would go wrong for some reason? You never know. Better back things up. But how?

I ended up booting a FreeBSD 13.1 live CD, bring up the network, mount an NFS share and dding the drive contents into an image file there:

dhclient rl0
mount /mnt
dd if=/dev/ada0 bs=1m status=progress | gzip -c > /mnt/fbsd1_0_bindist.img.gz

The receiving end is of course using ZFS for its storage, so even a 20GB image consisting mostly of zeros would have worked well enough. But the low compression levels of gzip are fine even on an old machine like my Acer laptop and so I don’t need to send gigabytes of data across the wire.

Dding the thing back onto the local drive would be done with this command line:

cat /mnt/fbsd1_0_bindist.img.gz.img.gz | gunzip | dd of=/dev/ada0 bs=1m status=progress

All simple enough. Since the drive is not the fastest by today’s standards, this process took 25 minutes or so. But hey, it would have been much worse in 1993!

Installation: Optional components

Now that I have a complete FreeBSD 1.0 installation on my drive, I went for populating it with additional things. I decided to copy over at least the source distribution and the x11 source. And of course I was very interested in giving ports a try!

The source distribution is a little smaller than the binary distribution, so I can re-use my good floppies and don’t need all of them. I hadn’t been looking forward to copying so much data on floppies again, but eventually I had what looked like a good set.

Then I booted up my new FreeBSD system – and was in for a surprise: The installation helpers were gone! And so I still have no clue what the “configure” command would have done (it’s gone, too). 😥

So this means that I also had to either do file copying by and or to write my own little script. But yeah, fair enough.

It took me another night to get the other two distribution sets copied over and I didn’t feel like doing the same for the binary Xfree86 distribution. Maybe I could give building X a try, maybe not, I’ve been more interested in other things. I found it nice to learn, though, that FreeBSD originally had included X as a distribution set! I haven’t checked, but I assume that they stopped when Xfree86’s successor, X.org, at some point came up with the “modular X.org” structure. I like what OpenBSD does with Xenocara, though (if anybody agrees, please let me know! I’d love to see Xenocara – which has even been ported to Linux – brought to FreeBSD as well.).

Keyboard fun

Alright! Time to finally explore the system. Here’s the userland part of the boot messages as the system comes up and I log in:

Automatic reboot in progress...
/dev/rwd0a: 455 files, 5986 used, 25229 free (173 frags, 3132 blocks, 0.6% fragmentation)
/dev/rwd0e: 21560 files, 273250 used, 588380 free (8780 frags, 72450 blocks, 1.0% fragmentation)
starting network
starting system logger.
checking for core dump...
preserving editor files
clearing /tmp
standard daemons: update crond.
starting network daemons: routed printer sendmail inetd.
starting local daemons:.
Wed Jun 15 17:30:51 PDT 2022

   FreeBSD (myname.my.domain) (console)

login: root
Last login: Wed Jun 15 16:50:28 on console
Copyright (c) 1980,1983,1986,1988,1990,1991 The Regents of the University of California. All rights reserved.

FreeBSD myname.my.domain 1.0.2 GENERICAH#0 i386

Welcome to FreeBSD!

Terminal type? [pc3]
Don't login as root, use su

There we are on my new old system with the source distribution and xf86 source extracted as well as some ports copied over (more about this later).

I’ve done all the copying files over using the default US keymap but if I were to actually use this machine, it makes sense to switch over to the keymap that’s actually printed on the keys, right?

# kbdmap
kbdmap: Command not found.
# kbdcontrol
kbdcontrol: Command not found.

Hm… Looks like both commands were not yet available in 1.0. But do we have keymaps at all?

# ls /usr/share/syscons/keymaps
danish.cp865.map       german.iso.map       uk.iso.map
danish.iso.map         swedish.cp850.map    us.iso.map
fff.map                swedish.iso.map
german.cp850.map       uk.cp850.map

Yes, we have! So the question is: How to make syscons actually use them?

# apropos syscons
syscons (1) - a utility for manipulating the syscons VTY driver.

Well, I know and expected syscons(4), but have never heard of syscons(1). So what is this? According to the man page, it’s “a utility for manipulating the syscons VTY driver” and it has the “-k” switch which reads “Install keyboard map from mapfile”. Excellent! That wasn’t too hard, was it?

# syscons -k /usr/share/syscons/keymaps/german.iso.map
You must be running this from a syscons vty for it to work.

If you are currently using pccons (default) and wish to have virtual
consoles, then rebuild your kernel after replacing the line:

        device pc0 at isa? port "IO_KBD" tty irq 1 vector pcrint


        device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr

(Then install the new kernel and reboot your system)

Uh-oh. Probably it is a little bit harder actually. I’ve already noticed that I could not switch between VTYs using CTRL + ALT + Fx and thought that the system wasn’t configured to support more than one by default. Turns out that FreeBSD’s switch to vt(4) was not the first one and even though syscons(4) was part of version 1.0 of the OS, it was not yet the default.

Building FreeBSD

I’ve wanted to mess with building the system from source, anyway. So here we go.

# less /usr/src/Makefile
less: Command not found

Arrg, I’m sure that one is going to kill me, unless I alias less(1) to more(1):

# alias less=more
# less /usr/src/Makefile

Turns out that there are the following targets:

  • world
  • directories
  • cleandist
  • mk
  • includes
  • libraries
  • tools
  • mdec

The “world” target depends on all of those so that’s what I’ll be using. Thanks to the description lines in the Makefile I get what all of those are. The “mdec” target is one that I could not guess from the name: It’s the bootcode. Alright, will I be able to rebuild FreeBSD 1.0 from source? Let’s try.

# make world

The machine starts building away but at some point it errors out:

xditview.c:34: X11/Xatom.h: No such file or directory
xditview.c:35: X11/Xlib.h: No such file or directory

Looks like groff is expecting various X11 headers to be present (it had to be a GNU component that was bound to annoy me, right?). I’ve installed the xfree86 sources, but maybe they are not in the right place? I’m not interested in X right now, anyway, so I decide to just not build the offending graphical component of groff:

# vi /usr/src/gnu/groff/Makefile

Let’s remove “xditview” from the “SUBDIR=” definition and try again.

This time it all works well. But I make an important discovery: “world” does indeed not include the kernel! I’ve just built (and re-installed) the userland part of the OS. There’s no target for building the kernel. So how to do it?

Custom kernel

Ok, maybe the structure of the source tree hasn’t changed much and back then everything was already in the place where I’d expect it to be in? Let’s see:

# ls /usr/src/sys/i386/conf
GENERICAH      LINT            SYSCONS      files.i386
GENERICBT      Makefile.i386   devices.i386

Indeed! There are the kernel config files. Looks like there’s even one pre-made that uses syscons instead of pccons. If I remember correctly, one can use the config(8) utility on those. Modern FreeBSD versions do this automatically when KERNCONF is supplied when running the buildkernel target. But we don’t have that here.

# man config

Alright, the man page covered everything I needed to know, including the path where the actual configuration and Makefile is generated. Let’s do it!

# cd /usr/src/sys/i386/conf
# config SYSCONS
# cd /usr/src/sys/compile/SYSCONS
# make depend
# make

Success! FreeBSD has not yet renamed the kernel which still goes by the name “386bsd”. Let’s copy it over, do the mystic triple sync dance (there was a bug in early systems and people used to work around it by syncing three times) and halt the system:

# cp 386bsd /
# sync ; sync ; sync
# halt

After rebooting, the system should now be using shiny new syscons! But what is this? The shell doesn’t accept backspace anymore which is rather annoying. Can I fix it with stty(1)?

I can. Good! Time to try again to set the keymap:

# syscons -k /usr/share/syscons/keymaps/german.cp850.map

Nice, I’ve got my local keymap working. Definitely making progress. What’s next? Taking a look at how system startup works with monolithic rc, I suppose.

System startup

Ok, /etc/rc and /etc/rc.local are not that bad: They are ugly (it’s shell code after all), but readable. Most of the non-obvious stuff has comments which helps understanding what happens there.

/etc/rc is 170 lines and /etc/rc.local is another 23 lines. One interesting thing I noticed here is that on FreeBSD 1.x, vi is actually elvis. For FreeBSD 2.0 they switched to nvi.

Adding the syscons command above to /etc/rc.local is all that is required to set my keymap automatically during boot. Adding the stty command as well does not work for some reason and I stopped investigating at some point. I don’t expect to reboot the machine that often and typing in one short command is not that bad. Later when exploring more of the system, I found out that the .profile file for the shell also calls stty. Changing the default of ^? for erase to ^H however doesn’t seem to do the trick, either. Whatever.

It’s time to examine /etc/netstart now. This system is not currently networked (FreeBSD 1.0 doesn’t have a driver for my NIC), but that file is still important. It’s also only 29 lines long, so no excuse to not look at it.

There I learn how to change the hostname; the script takes it directly from /etc/myname. After the next reboot, my system will come up with its own hostname.

The FreeBSD Ports Collection

Now for something that I really looked forward to: Exploring ports. The official CD comes with several packages – both binary packages and source packages, curiously. The actual ports tree is present twice on the CD. One time as a directory that holds all the subdirectories for the ports and one time in form of all ports as individually gzipped tarballs. It’s also flat; there are no categories, yet, every port is directly in the main ports directory.

But none of that was nowhere close to the biggest surprise for me! The ports tree is not what I expected it to be. It’s not so much today’s framework for building software. It’s the actual software source code of all ported programs, slightly modified to work well on FreeBSD! So it’s closer to being a second source tree with third party software.

I’ve put some ports that I’m interested in into /usr/ports and extracted the gzipped tarballs. First thing to look at is pkg_install, which contains an early version of the package tools pkg_* that FreeBSD used up to version 8.x. Or as the description puts it: ‘This is the pkg_install suite of tools for doing maintenance of software “packages”.’ Let’s build and install it:

# cd /usr/ports/pkg_install
# make
# make install
install: /usr/local/man/man1: No such file or directory
*** Error code 1

Well, looks like I have to first create that directory manually. Indeed /usr/local is empty by default.

# mkdir -p /usr/local/man/man1
# make install

That looks better. Now pkg_info should be available:

# pkg_info
pkg_info: Command not found.

Alright, alright:

# rehash
# pkg_info
pkg_info: Command not found.
# which pkg_info
no pkg_info in /sbin /usr/sbin /bin /usr/bin /usr/local/bin .

Huh? What happened here? Oh, I see: There has been no /usr/local/bin directory, either, and the port tried to copy each binary there! So it made /usr/local/bin a file and overwrote it multiple times with each binary!

# rm /usr/local/bin
# mkdir /usr/local/bin
# make install
# make clean
# rehash

There we go! Now the package tools are available on this system. They consist of pkg_add, pkg_create, pkg_delete and pkg_info.

Next is installing zsh – the ports works like a breeze and this one is a real treat! Imagine if you will: Shell history! Tab completion! It’s so much better for an interactive shell…

For some reason I cannot get screen or perl to build. Those ports don’t include a Makefile. I honestly don’t know how these are supposed to work (what am I missing here?). The other one I copied over, gopher seems to require gmake to build which I did not bring along.

One thing to note is that programs installed from ports are not recorded as installed packages! I also managed to destroy the right shift key of my laptop (the left one broke back in the day) while messing with perl. Oh well, nothing is forever. 😢

Exploring packages

I’ve seen enough of building from source right now, time to explore packages. I decided to wipe /usr/local and start over. So I first need pkg_install. How does creating packages work? There are the make targets src_dist and bin_dist. I’m going to try out the latter:

# cd /usr/ports/pkg_install
# make bin_dist

This built the port, installed the software (directly into the system, no fake directory!) and then packaged it up. So in addition to the software already installed, I also have /usr/ports/pkg_install/pkg_install.tar.gz now. What can we do with it? Maybe the pkg tools can help.

# pkg_info
pkg_info: Missing package name(s)

Usage: pkg_info [args] pkg [ .. pkg ]
Where args are one or more of:

-a         show all installed packages (if any)
-I         print 'index' of packages
-c         print `one line comment'
-d         print description
-f         show packing list
-i         show install script
-k         show deinstall script
-r         show requirements script
-p         show prefix
-l <str>   Prefix each info category with <str>
-v         show all information
-t temp    use temp as template for mktemp()

[no args = -c -d]

Interesting. So this utility does two things: It’s used to list packages installed on the system and to get information about packages not yet installed as contained in the actual package files. Let’s try it out, shall we?

Back to transferring files over via diskette as I had planned to only work with ports. I settle on just zsh and gopher. While I’m here, I notice that there is no binary package for either screen or perl. Maybe they were WIP at that time and it’s no wonder I could not build them?

Another little fun piece of info: There’s a package for gcc1 available and it’s described as “A less memory intensive C compiler written by the GNU folks”. I also noticed sblaster_kern.tgz: “SoundBlaster driver for FreeBSD, vers 1.5 (kernel)” – nice! Maybe one great day on FreeBSD we can play… Right, right, I didn’t want to bring that ID game we all were obsessed with up again!

# pkg_info -c /usr/packages/zsh_bin.tgz
Information for zsh_bin.tgz:

ZSH 2.3.1 zsh shell

That does the trick, I suppose. Like one would expect, the package contains the Z Shell and it’s version 2.3.1.

# pkg_info -i /usr/packages/zsh_bin.tgz
Information for zsh_bin.tgz:

Install script:
#! /bin/csh -f
# Update /etc/shells on post install

Ah, so this package has an install script and it is what takes care of registering zsh with /etc/shells. Makes a lot of sense. But I definitely want my zsh back that I deleted when I removed /usr/local, so that’s got to happen next.

pkg_add: Missing package name(s)

Usage: pkg_add [args] pkg [ .. pkg ]
Where args are one or more of:

-v         verbose
-p arg     override prefix with arg
-I         don't execute pkg install script, if any
-R         don't record installation (can't delete!)
-n         don't actually install, just show steps
-t temp    use temp as template for mktemp()
-S         run in SLAVE mode
-M         run in MASTER mode

Got it (of course I looked up master and slave mode – but as the manpage mentions, this is rather special and not too useful if you’re not messing with packages at a much lower level). Let’s see what installing the zsh package would do:

# pkg_add -n /usr/packages/zsh_bin.tgz
Running install with PRE-INSTALL for zsh_bin..
extract: CWD to /root
extract: Package name is zsh_bin
extract: CWD to /usr/local
extract: /usr/local/bin/zsh
extract: /usr/local/man/man1/zsh.1
extract: CWD to .
Running install with POST-INSTALL for zsh_bin..

That’s pretty nice actually. Now for the real thing:

# pkg_add /usr/packages/zsh_bin.tgz
updating /etc/shells

# rehash
# zsh

Ah, so much better! Now there should be one installed package, right?

# pkg_info -I -a
> zsh_bin ZSH 2.3.1 zsh shell

Indeed! This is pretty simple to grasp and – considering the time we’re talking about – very well thought-out. It’s extremely easy to use, too. Not half bad, Mr. Hubbard!

User management

Whenever I login as root, the system reminds me not to do that and to use su(1) instead. To be able to do so, I need an unprivileged user, though. I remember reading somewhere (in the FAQ, I think) that adding users is not completely trivial. But I’m not that green, am I? How hard can it be to add a user?!

There’s the adduser(8) manpage, but curious enough, there’s no adduser command. The manpage explains how to do it, though: By editing the /etc/master.passwd file and rebuilding the password db! Ok, I can see why this might be slightly intimidating to newbies, but it’s not so bad really, is it?

In a surprisingly large number of cases, when I think that something is not that hard actually, I stand corrected. This time however, it really is simple. In case you don’t remember what all the fields mean, you can look it up quickly:

# man 5 passwd

On second thought, let’s do this properly and add a group for the new user first:

# echo 'kraileth:*:1000:kraileth' >> /etc/group

Now for the user:

# vipw

The vipw(8) command automatically invoked pwd_mkdb(8) after checking that the file looked ok. So my user is now present on the system. However I could not log in, yet, as the home directory is missing. I also want to give the new user a password and copy over some dot files from the skeleton directory.

# mkdir -p /usr/home/kraileth
# chown kraileth:kraileth /usr/home/kraileth
# passwd kraileth
# cp /usr/share/skel/dot.login /usr/home/kraileth/.login
# cp /usr/share/skel/dot.profile /usr/home/kraileth/.zshrc
# chown kraileth:kraileth /usr/home/kraileth/.*

Logging out root and logging in with my user works as expected. I also assume that I need to be part of the wheel group to be able to su(1) to root and that this is not some newer convention. Let’s just try it out and see:

% su -l
su: you are not in the correct group to su root.

Not much happened here and still this was a real wow!! moment for me. Why? Today’s su(1) is very much newcomer-unfriendly. You’re not in group wheel and try to su? This is what you get instead:

su: Sorry

I’ve told many people that this rather… unhelpful message was due to Unix originally using hard-copy terminals (with line printers) and that to save paper and ink the responses were most often extremely brief and expected you to know what they mean (see ed(1) as a classical example!). Turns out that I’ve been very wrong. And to be perfectly honest, I have no freaking idea how that regression happened. If it had never been better than what we have today, I could live with it. But this? It has had a useful error message and that was removed later? It does annoy me somewhat.

Ok, it doesn’t tell you which group, but still that’s at least a pointer in the right direction. Anyway: We all know. It’s make the new user part of wheel by replacing the respective line:

# vi /etc/group

Let’s try again:

% su

Now it works: It asks for the password and then grants me access to root.

System services

I’ll best be looking at the deamons next. First: What is the “update” deamon? Do I really want that?

# man update
update - flush internal filesystem caches to disk frequently

Err… ok, maybe I do want to actually keep that one! But since this box is not networked, I certainly don’t need routed, so I can edit /etc/netstart and change routedflags to NO. I don’t need the printer deamon, either, so that one goes off, too. There’s no variable for it which means that I simply comment its line out in /etc/rc.

And I certainly don’t need inetd. Especially since we’re talking a more… naive time and age and the default inetd configuration has 20 (!!) services activated, including spiked pits like rsh, rlogind and rexecd and so on. It’s also not meant to be turned of using a variable, so again I comment out the line that starts it. I’m going to tolerate sendmail here because it does have some local use, too.

After making those configuration changes and rebooting we’re now down to three deamons:

# ps ax
    0 ??  DLs    0:00.01  (swapper)
    1 ??  Ss     0:00.00 init -
    2 ??  DL     0:00.00  (pagedaemon)
   25 ??  Ss     0:00.04 syslogd
   38 ??  Ss     0:00.00 update
   40 ??  S      0:00.01 /usr/libexec/crond
   47 ??  Ss     0:00.01 sendmail: accepting connections
   49 vg  Ss     0:00.04 -csh (csh)
   63 vg  R+     0:00.00 ps ax

Not too shabby at all!


FreeBSD 1.0 is a very old operating system now – a few months short of being 29 years old. Almost three decades is a respectable part of a man’s life. In the IT business it’s close to being an eternity. New technology came into being and went away again. You don’t really talk about floppy disks at all anymore. Heck, there are machines that don’t even have an optical drive anymore! Try to ask the younger folks about the ISA bus or hard disk jumpers…

Those things are gone. And if we’re honest: Rightfully so. But they were necessary steps in the development and evolution of the IT as they enabled us to build what we have today. They became invisible to most eyes, but if you look carefully, you can see that they left their legacy. Think about UFS for example. It’s still a capable filesystem that does meet the requirements of many modern workloads well. But that “cylinder boundary” stuff that was a necessity at the time of its design and creation, is basically carved in stone for more decades to come.

FreeBSD 1.0 is pioneer’s work and in some regards that shows. There are many things that feel rather odd today (the PATH variable that is set in the skel profile dotfiles includes “/usr/new” and “/usr/local” – but not “/usr/local/bin”, what the heck!). The very simple default shell is a true pain to work with as it lacks each and every convenience feature that we’ve grown used to for interactive shell use. But that was what we had back in the day. I still remember that it was a revelation for me when I got the first advanced shell that supported tab-completion (I do not remember though if this was the Windows 2000 CMD or an advanced FreeDOS COMMAND.COM that I was playing with back in the day). Luckily this can be fixed by installing a better one such as zsh. And then it’s pretty much ok.

Many commands that I’m used to are missing (no sockstat till 3.2!) or have seen renaming over time (what is mount_msdosfs(8) used to be called mount_msdos before and here on 1.0 it’s in fact called mount_pcfs). From the couple of hours that I’ve spend with it, I’d say that it has been a satisfying journey. Would I want to seriously work with it? Not really. But I could – within the limits that it has of course (can you say TLS?).

It’s shortcomings which are to be expected due to its age aside, I’ve found out something more important: Despite being different in many details, the system feels familiar. I’ve had to look at older Linux systems, constantly thinking “good lord, why??” and sometimes even having trouble finding my way around. Solving those problems without asking duckduckgo even once is completely out of the question. Not so much here: It’s all there in the manual pages and often enough it’s at least kind of what I’d expect it to be. And it’s not just an “old” system; it’s an ancient one. This shows just how much there is a consistent philosophy and careful design behind FreeBSD. The character and the spirit of the project that the founders formed proved strong enough to be perfectly recognizable three decades later. Now if that doesn’t mean that their ideals and ideas stood the test of time, I don’t know.

This has been a very worthwhile little project for me and I intend to follow this path further along. Maybe taking a look at X11, maybe looking at a newer version. There is one thing that I’m currently struggling with, though. How do you update version 1.0 to 1.1 by source? Is this even possible? There seems to not be much info on this existing anymore – if it ever did. I’ll continue looking for it, but if you happen to know, please get in contact! Any piece of info would be greatly appreciated.

Thanks for reading and I hope you had a good time!


Here’s FreeBSD 1.0’s dmesg of the same laptop to compare it against the one from FreeBSD 13.1 in the previous post:

FreeBSD 1.0.2 (SYSCONS) #0: Wed Jun 15 17:43:50 PDT 2022
CPU: i486DX (486-class CPU)
real mem  = 67104768
avail mem = 64495616
using 819 buffers containing 6709248 bytes of memory
Probing for devices on the ISA bus:
sc0 at 0x60-0x6f irq 1 on motherboard
VGA color <8 virtual consoles>
sio0 not found at 0x3f8
sio1 not found at 0x2f8
sio2 not found at 0x3e8
sio3 not found at 0x2e8
lpt0 not found at 0x3bc
lpa0 at 0x378-0x37f on isa
lpa1 not found at 0x278
fd0 at 0x3f0-0x3f7 irq 6 drq 2 on isa
fd0: unit 0 type 1.44MB 3.5in
wd0 at 0x1f0-0x1f7 irq 14 on isa
wd0: unit 0 type TOSHIBA MK2018GAP
ahb0 not found
aha0 not found at 0x330
wt0 not found at 0x300
ed0 not found at 0x280
ed1 not found at 0x300
ie0 not found at 0x360
is0 not found at 0x280
npx0 on motherboard
biomask 4040 ttymask 2 netmask 2

4 thoughts on “Legends start at 1.0! – FreeBSD in 1993 (pt. 2)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.