Friday, May 8, 2015

Retrocomputing with UnixWare 7.0.1

This one's been a long time coming.


Months and months ago I acquired a scattered collection of old SCO software from a seller on eBay. It included a random hodgepodge of all kinds of stuff; a dozen manuals, dozens of CD's and floppies, packs and packs of licenses... It took a few hours just to sort out what went with what. Among the haul: a complete copy of OpenServer 5.0.0, two complete copies of OpenServer 5.0.2, and the license pack for UnixWare 7.0.1, but no UnixWare media. Seriously?! What happened to the media?

At the time I was a bit frustrated, but not terribly because I had plenty to play with. In fact, I still haven't gone through most of it. And, so I just sat on the licenses and waited.

Months later, someone was selling a copy of OpenServer 5.0.5 and the photos showed media for UnixWare 7.0.1 included in the pile. This wasn't too surprising though. SCO used to give away promotional copies of UW 7.0.0 and 7.0.1 with OSR 5.0.5. In fact, that's how I was first exposed to it, way back. They didn't give away licenses though. You could install everything, but you only had about 60 days to play with it before the demo timed out.

But, I had an actual license! And a few days later I had media to go with it!


Still, it was a few weeks later before I had enough time on my hands to start trying to get it to run. That turned into a bit of an adventure too.

Here's how it went.


Actually, first... What the heck is UnixWare?

I'm a little fuzzy on the history actually.

Novell and somebody else (AT&T?) got together at some point in the early 90's to put together a version of SVR4 Unix that could interoperate with Novell NetWare, for some reason. I'm not sure what the motivation was, actually. But they succeeded, released a few versions, and eventually got the attention of SCO. At the time, SCO had OpenServer, which was an SVR3 implementation. UnixWare had feature-parity with OpenServer, aside from the configuration interfaces and back-compatibility with older SCO platforms. I guess they figured it would be easier to buy an SVR4 platform and port their goodies to it than rework OpenServer.

Whatever the motivation, SCO bought UnixWare, or licensed it, or something, and made several 2.x releases. In the late 90's Sun released Solaris version 2.7 as "Solaris 7". SCO was coming out with another version of UnixWare around then, and rather than name it 3.0, they named it "UnixWare 7" as well.

SCO made a few more releases and tried to get everyone to migrate from OpenServer to UnixWare, but there weren't a lot of takers. SCO's users had legacy apps galore that still needed to run, like apps written in FoxPro for 3.2v4.2, and apps written in Microsoft Basic for Xenix, and instances of Oracle7. They could recompile their modern C/C++ apps, but FoxPro, MS Basic, and Oracle7 didn't even run on UnixWare. Those apps would have to be completely rewritten in different languages or migrated away from SCO platforms. No thanks.

SCO tried a few stunts. Unixware 7.1.2 was released as "OpenUnix 8", for example, but people stuck with OpenServer. Eventually, SCO released OpenServer 6, which piled everything that everybody liked from OpenServer (including back-compatibility) onto a UnixWare base. It looked and felt like OpenServer, ran all the legacy apps, but it was UnixWare underneath.

Technologically, they'd finally achieved what both they and their users wanted, but it might have been too late. When OSR 6 was released, SCO's courtroom shenanigans had turned the world against them. I wonder how many takers OSR6 actually has.

But I digress. My adventure begins about half of that story ago, with version 7.0.1, right about when SCO got serious about trying to get everyone to migrate off of OpenServer.

Here's how it went. (For real, this time)

VM Configuration

I'd had good success with various OpenServer's in VMware, but UnixWare is a totally different breed. Turns out it'll run too, but only if you're careful about how you do it.

In particular, UnixWare can't make heads or tails out of VMware's IDE emulation. SCSI's the way to go. And, in particular, BusLogic SCSI. Don't even fool around with LSI, it's not going to work. The hard drive has to be SCSI, and so does the CD ROM.

But, UnixWare 7.0.1 predates bootable CD's by a year or two, so you've got to come up with some boot floppies. None came with my CD, but it turns out there are floppy images on the CD. Not in an intuitive place, mind you, but they're on there. It took a little bit of digging, but I found them under INFO/IMAGES. The files are named BOOT.IMA.1 and BOOT.IMA.2. There are other disk images there too, but they're not necessary for VMware installation.

Installation basically involved adding a floppy, aiming it at BOOT.IMA.1 and powering on the VM.

Right away I was greeted with the familiar UnixWare splash screen.

unixware 7.0.1 - 1. splash

And the installation was kind-of straightforward.

I answered a few intuitive questions, swapped floppies when prompted, answered a few more intuitive questions, eventually answered some less-intuitive ones...

Do I want to enter the DCU? Maybe. What's a DCU? Ahh, "Driver Configuration Utility." I'm not sure. As it turns out, letting it auto-configure is the way to go.

The installer detects the emulated PCnet ethernet card but the driver has a lot of trouble with it. The "IBM PCI Ethernet" driver works well though.

Configuring TCP/IP is intuitive, except that you can select the ethernet frame format. The default of ETHERNET_II works well though.

Since this is UnixWare, it also supports IPX, and as it turns out, IPX can't not be installed. That's OK though, the defaults seem to work.

Unfortunately, NIS also can't not be installed. I gave my installation an NIS Type of "client" and NIS domain of "firstworks" and as I have no NIS servers anywhere, left the optional NIS servers blank.

Just about everything else was totally intuitive, and before too long, the installation proceeded unattended.

unixware 7.0.1 - 2. install

When the installation was complete, I had to disconnect the cdrom and floppy before reboot. Failing to do so resulted in several very insistent messages.

On reboot, I got a funny message about swap being smaller than memory. I'd given my VM a monstrous 256MB of RAM. In the late 90's, 32mb would have been a lot.

I also got some apparently-unimportant SCSI errors and a bunch of messages about configuring NetWare and other things. Eventually I had to configure the mouse and then it asked me to insert disc #2 to continue installing the system. I only had 1 system disc though. The other disc was the development system. I tried that disc, but apparently that's not what it was looking for. It also didn't like it when I gave it the first disc again. Oh, well. Eventually I just hit F8 to defer that step. It then prompted me for disc #3 and I just deferred it again. I might have chuckled a little too.

Fortunately it didn't ask me for disc #4, but instead started doing boot-type things and eventually presented me with a CDE login.

unixware 7.0.1 - 3. first boot

All right!

Post-Install Tweaks

Logging in got me to a familiar CDE desktop.

unixware 7.0.1 - 4. cde desktop

But, not a lot worked. I could poke around the system, but it was an island unto itself. I couldn't ping, ftp or telnet to anywhere.

This took days to figure out.

It turned out that there were two big problems. First, though above I say "the PCnet driver sucks, use the IBM PCI Ethernet driver", I hadn't done that at this point. I was still using the PCnet driver, which sucks. Tremendous packet loss.

After switching to the IBM PCI Ethernet driver, things were a lot better, but I couldn't yet tell that they were.

It eventually turned out that NIS was wreaking widespread havoc. I never figured out exactly what was going wrong, but my guess is that the /etc/hosts file is an NIS-able file, and since there were no NIS servers anywhere, all DNS lookups had to wait for an NIS timeout before proceeding past the /etc/hosts file. The effect was that if I tried to ftp or telnet to somewhere, it would hang for quite a while before actually trying the address. Telnetting or ftp'ing in from other hosts would hang too, during the reverse-lookup. If I waited, each these operations would eventually succeed, but in the beginning, I wasn't patient enough to realize this.

Once I did determine that NIS was the culprit, disabling it was still fairly tricky. I had to edit /etc/init.d/nis, set the domain to an empty string early in the file:


And then also comment out the setting of the variable "d" because the domainname program would somehow still return my domain, even though domain has been set to "".


But! After that, and a reboot, everything started working really well.

I was able to download a bunch of useful software from the SCO Skunkware FTP site, but unfortunately none of it worked without first installing a libc patch. Apparently the shared version of the libc that ships with 7.0.1 is missing some symbols. Weird. The patch fixed it though.

So I installed that patch, and several bits of software, like bash, sudo, gzip, etc., all using the standard SVR4 package management tools, which are worth discussing a bit.

Package management on UnixWare, while SVR4-compliant, is (not-unexpectedly) archaic. There's no dependency-resolving "yum install xxx" or "apt-get install yyy". You just download a .pkg file, hope it doesn't have any not-too-obvious dependencies, and install it in a completely unintuitive manner.

For example, if you download a file named xxx.pkg, then you'd install it using:

pkgadd -d `pwd`/xxx.pkg

The -d meaning "the packages are contained on this device or in this directory".

What? I'm trying to install the package xxx.pkg, why do I declare it to be the directory containing packages?

Well, the pkg file is actually a cpio archive.


In antiquity, packages weren't distributed individually. Dozens of expanded package trees were cpio'ed en-masse to a tape, and the tape was distributed. If you aimed pkgadd at the tape device, like pkgadd -d /dev/rmt0, or similar, it would tell you what packages are available and allow you to install one or more of them at a time. If you already knew which one(s) you wanted to install, you could supply the name(s) on the command line too.

As hard drives got bigger, someone got the idea to distribute packages as individual files, rather than collected up on tape. And, since on unix, everything is a file, pkgadd doesn't care whether the argument to -d is a file or a device, as long as it's a cpio archive.

Clever. Agreed. But completely unintuitive.

In fact, the man page for pkgin doesn't help much either. It goes on and on about how -d can refer to a directory, or a pipe, or a device (like a tape), and about the default locations, and other stuff, and unless one notices that -d can refer to a "directory, file, or named pipe", and it occurs to one that file might mean .pkg file, and that .pkg files might simulate tapes, then one might overlook that option altogether.

That's what I did, way back, when I first encountered UnixWare, and it drove me nuts. Even after I figured out the whole file=tape thing, I still couldn't get it to work because the fact that the argument to -d has to be the full pathname to the .pkg file is not mentioned ANYWHERE, AT ALL!

Somewhere I found an example though, and had to laugh, in hindsight, at how obvious it should have been.

Remote Access

It was fun using the CDE desktop and all, but not practical in the long run. Telnet worked, but it's difficult to automate.

OpenSSH packages were available, but they were apparently built for a later version of UnixWare. sshd kept complaining about libc missing the strlcmp function.

No problem though, I've built OpenSSH for a bunch of old Linux and Solaris platforms. Maybe I could get it to work on UnixWare too.

I had to install a few packages first though. OpenSSL for starters, and it required prngd and zlib. Also, I didn't have a lot of faith in the native development system, so I installed gcc-2.95.2pl1 too.

And, it turned out, building OpenSSH-3.4p1 from source was quick and easy.

./configure --prefix=/usr/local/openssh-3.4p1
sudo make install

Configuring it was familiar from OSR5 too.


X11Forwarding yes
UsePrivilegeSeparation no

And I created an init script at /etc/init.d/sshd...


case "$1" in
kill `ps -efa | grep sshd | grep -v grep | cut -c10-15`
echo $"Usage: $0 {start|stop}"
exit 1

exit 0

...made it executable, and set it up to run at boot:

chmod 755 /etc/init.d/sshd
cd /etc/rc2.d
ln -s ../init.d/sshd S98sshd

The last step was to uninstall OpenSSL. Oddly, for both UnixWare and OpenServer, the OpenSSL packages only contain static libraries. This creates problems for my software, and since once OpenSSL is compiled it no longer needs the OpenSSL libraries, it's safe to remove the packages.


unixware 7.0.1 - 5. ssh

Remote access!

But, it wasn't perfect. ksh on UnixWare is all but unusable over SSH. Neither backspace nor delete work. Bash worked though, so it was easy enough to work around.

I could ssh out too.

Looking good.

File Transfer

As mentioned earlier, ftp worked pretty well. OpenSSH came with scp and sftp. I'd installed gzip earlier. UnixWare comes with tar and cpio, though neither can gunzip on the fly. Packages for GNU tar, as well as zip, unzip and bzip were all available from skunkware.

After installing a few more packages, I was well equipped to transfer files.

The Web

No system is complete without being able to get on the web, right?


UnixWare 7.0.1 came with Netscape Navigator 3.0.4. Cutting edge for 1999, but it struggled pretty badly with today's web.

I installed wget and lynx packages from skunkware though. Good old lynx.

On the server side, things were slightly better.

UnixWare comes with the Netscape FastTrack web server. To turn it on, you have to log into a CDE desktop, run SCOAdmin and select Netscape Server Admin. This launches Netscape and aims it at FastTrack's web-based configuration interface.

After logging in as admin and using the password for the root user, you get this snazzy UI.

unixware 7.0.1 - 6. netscape fasttrack web server

The toggle switch on the left is for the web server on port 80. Switching it to the "ON" position started up the web server, and it was immediately accessible from my local browser.

unixware 7.0.1 - 7. default web page

Oh yeah!

It took a bit of digging around in the interface, but I figured out how to enable CGI's and a quick "print out the environment variables" script worked.

Skunkware packages for Apache were also available, but I didn't try them. Maybe later.


The CDE login and desktop was enabled by default.

It can be disabled using:

scologin stop

And re-enabled using:

scologin start

When disabled, running startx from the command line, surprisingly, didn't start a CDE session though.

unixware 7.0.1 - 8. non-cde desktop

Weird. I'd apparently never done that before because I didn't recognize the desktop from OpenServer, UnixWare, or anywhere else.

It turns out that it is possible to get a CDE session with startx though, if you first create a .xinitrc file containing:


There were Skunkware packages for GNU make and CVS. What about the compiler though?

Well, I'd intalled gcc earlier to build OpenSSH, but I had 2 CD's. One with the OS, and the other with the development system. And, I had actual licenses for it in the same pack as the OS licenses.

The OpenServer development system isn't super mature, at least as of OSR 5.0.5. There's no support for 64-bit integers, and the C++ compiler is just a c-front and both quirky and not terribly capable with templates, even simple ones. I wasn't sure about the UnixWare development system though. Back in the late 90's, I never got around to playing with it.

Now would be a good time, I figured.

The CD had a README on it, so I followed its instructions to run the Development System's installer.

unixware 7.0.1 - 9. dev system

Turns out, it installed the C and C++ compilers, a ton of libraries and headers, and Java version 1.1.3. Whooo! 1.1.3. That's a blast from the past.

The UnixWare C++ compiler was a lot more capable than it's OSR cousin. In fact, calling them cousins isn't even inaccurate. It didn't appear to be a c-front, and compiled my Rudiments library with only a few tweaks.

But, when I got around to running the tests, I discovered one of its deficiencies. Like earlier versions of gcc, it didn't handle nested template invocations correctly. Darnit.

There were issues with variadic macros too, but I could just comment those out. The template thing was a show-stopper.

That's OK, there's always gcc, right?

Not exactly.

I'd installed gcc-2.95.2p1 earlier, and it was able to compile all of my software quite easily, but when I tried to run just about anything, I'd get a segfault, almost immediately.

I tracked it down to a dynamic linker error of some sort. Basically, my charstring class had an overloaded compare() function with two different signatures, and attempts to call the one with 3 arguments would crash.

I'd actually seen this same error on OpenServer 6 years ago, and eventually fixed it by compiling gcc-2.95.3, with some SCO patches from source, using the native compiler.

No such luck though. Same error.

I tried other versions of gcc-2.95.x, both packages and builds from source. Nothing worked. At best I'd get the same error. At worst, the compiler would segfault. Eventually I gave up.

And that's where it sat, for months. Sometimes you've got to get away from a problem for a while though. This afternoon I took another look at it. I noticed that there were Skunkware packages for older versions of gcc, like 2.8.0 and the egcs compilers. I couldn't remember if I'd tried them before or not.

I must not have because the compiler from the egcs-1.1.1 package ran without segfaulting, and produced working code.

The rudiments tests mostly ran fine. SQL Relay built and the command line client ran.

unixware 7.0.1 - 10. sqlrsh

SQL Relay supports lots of languages and database backends, but unfortunately not many of them are well supported on UnixWare 7.0.1.

I couldn't get it working with Perl, Python, PHP, TCL, Ruby or Java. In some cases, even the oldest language package was clearly meant for a newer version of UnixWare. In other cases, there were odd header quirks that prevented them from compiling cleanly. I'm not sure what the issue is with Java yet. By rights, it ought to work but I get weird errors at runtime.

Things weren't any better on the database front. PostgreSQL was the only database available, and the only package that would install was for version 6.5.3 - older than the oldest version I've ever tried before. UnixODBC was available, but the package was for a newer version of UnixWare.

SQL Relay builds against that old PostgreSQL, but there's some shared-memory-related issue that keeps it from running.

Ehh, who knows. There's always some quirky thing with every platform.

That's where I left it.

Quirks and Endearing Features

So, what's weird about UnixWare 7.0.1?

Not all that much, actually, especially given it's age.

The most significant thing is an issue with the filesystem. It's very easy to run out of inodes, waaaaay before you run out of space:

bash-2.05a$ df -v /
Mount Dir Filesystem blocks used avail %used
/ /dev/root 16000740 1538304 14462436 10%
bash-2.05a$ df -i /
Mount Dir Filesystem iused ifree itotal %iused
/ /dev/root 55862 9674 65536 85%

Multiple times I had to tar and zip stuff up and delete directory trees to free up enough space to untar something else. It looks like they're using a 16-bit number for the number of inodes. I guess back in the day, when a 1.6G hard drive was gigantic, file systems would have been smaller, there would have been more of them, and that was enough. But I'd swear that one of the selling points of UnixWare was support for petabyte and exabyte sized volumes. Maybe the filesystem does support more inodes, but there's no option for it at install time, and 65536 is a small default.

Other quirks...

The ksh shell has trouble over ssh, neither backspace nor delete work.

The halt and reboot commands are in /usr/ucb, which isn't in the default PATH.

Adding directories to the PATH is remarkably difficult. /etc/profile exports PATH before setting it. Lord knows where it's getting the default PATH from. Also, CDE sessions don't appear to source /etc/profile at all. Again, it's unclear where their PATH is set.

socklen_t is defined but a lot of network functions use size_t instead.

The chmod command accepts a shorter argument list than commands like cp. I had to update several Makefiles to work around this.

If you make a change that requires a kernel relink, the relink is done during the reboot, not before. As such, there's no unix.old to boot to until after the boot fails. Actually, for that matter, it's not clear how to get to a bootloader prompt.


Strange, old unix.

Gotta love it.