Install Logical Journey of the Zoombinis (1996) on Linux


The game Logical Journey of the Zoombinis was an amazing game when I was young. It was fun, and apparently I learned a lot. I decided to try to install it on my Devuan ceres laptop. Here is the optimal route for making it work.

How to Install Zoombinis on Linux

The Zoombinis game was published in 1996, and it supports Windows 3.1 and Windows 95. We are going to install Windows 3.1 in DOSBox, install drivers, and then install the game.

Prepare Windows 3.1

Install DOSBox, which is probably in the main package manager on your GNU/Linux platform.

sudo dnf install dosbox
sudo apt-get install dosbox

Extract the Windows 3.1 VHD file (which I had from my old MSDN AA days). Also extract into sub-folders the Zoombinis disc contents, the sound drivers that DOSBox emulates, and the emulated video drivers.

mkdir -p ~/win31 ; cd ~/win31 ; 7z x ~/Downloads/Windows\ 3.1.vhd
mkdir -p ~/win31/zoominst ; cd ~/win31/zoominst && 7z x ~/Downloads/Logical\ Journey\ of\ the\ Zoombinis.iso
mkdir -p ~/win31/drivers/SB ; cd ~/win31/drivers/SB && 7z x ~/Downloads/
mkdir -p ~/win31/drivers/S3 ; cd ~/win31/drivers/S3 && 7z x ~/Downloads/

Prepare a batch file for mounting the right drives in the emulated environment.

cat <<'EOF' > win31.bat
REM for Zoombinis
MOUNT C ~/win31
MOUNT D ~/win31/zoominst


Run DOSBox:

dosbox win31.bat

Run Windows:


It might prompt you about deleting a corrupt swap file. You can select “Y” to do so, and then go into the Control Panel, “386 Enhanced,” Virtual Memory button, and save the information that is present. Then it shouldn’t prompt you anymore.

Install sound and video drivers

Zoombinis will warn you about sound and video settings, so the driver we loaded earlier should cover this. Now we have to install them. DOSBox emulates the SoundBlaster and S3 video hardware, so we just apply those drivers for Windows 3.1, and then audio will work and higher graphics settings too.
In DOSBox, cd to DRIVERS\SB and run the INSTALL utility.


Press enter to install the driver now.
Press enter to do a full installation.
Navigate with the arrow keys down to the Windows 3.1 path and enter in the “C:\Windows” value.

Change the Interrupt setting to the DOSBOX default of 7, as seen in this screenshot (unless you modified it in the dosbox.conf).

If it prompts you about replacing a file, feel free. It will not harm anything to replace it.
When that finishes, you can either reboot or stay on the current session.
Now it is time to install the video drivers. In DOSBox, run the Windows SETUP.EXE utility.


Select the DISPLAY option and press enter.

Scroll all the way to the bottom of the list and select “Other (requires disk…)”
Type in the directory where the video drivers are, e.g. “C:\DRIVERS\S3”
I am uncertain if Windows 3.1 has the ability to change the display resolution, so just pick your preferred screen resolution here.

I picked the 800×600 64K color with small fonts (as opposed to large-print fonts).
The SETUP utility will then return to the full list of system information, and you can select “Accept the configuration shown above.”
You might need to point it to the “C:\DRIVERS\S3” folder once more.
Now you can run Windows 3.1 with sound and an 800×600 display!


Install Zoombinis

Use File Manager to navigate to where we injected the install files.

Run the setup.exe!
Make sure you have enough disk space.

I installed QuickTime as well, although I don’t know what its omission would do.
Now you should have “Broderbund Software” group in Program Manager and the Zoombinis launcher inside it!


First of all, I had to find my old .VCD file (from my Virtual Drive Manager days on a non-free OS). I know those are basically ISO files and can just loop-mount them. Unfortunately, my .VCD file was corrupted. I then had to scrounge around for the old .FCD file and finally found it. But then, I had to try to get the contents out of it. I spent about 45 minutes researching online before I found IsoBuster. That software is shareware, but its free components worked enough to let me copy out the contents of the FCD file. On GNU/Linux these days, it’s all ISOs, and those are much easier to work with and find tutorials.

Did you know that 7zip can extract files from ISO and VHD files? That was very neat to learn.
I tried installing the game in Wine, and after getting the cd check part to work (by modifying the ini file “INSTALLFROMDRIVE=D”), I ran into an error: “Cannot initialize graphics.” And it included some contents of a register, and I never solved it.

err:int21:INT21_Ioctl_Block int21: unknown/not implemented parameters:
int21: AX 440d, BX 0004, CX 0848, DX db46, SI 0000, DI 0000, DS 0000, ES 0000
fixme:reg:RegOpenUserClassesRoot (0x7c, 0x0, 0x2000000, 0xe2e6d8) semi-stub
err:int21:INT21_Ioctl_Block int21: unknown/not implemented parameters:
int21: AX 440d, BX 0004, CX 0848, DX dde2, SI 0000, DI 0000, DS 0000, ES 0000

I think that’s functionality that just hasn’t been added to Wine. I’m pretty sure the game does some early DirectX fullscreen mumbo-jumbo and this version of how it does that was not implemented in wine. Ah, well.
But, during all this work I had read the Zoombini readme and it indicates it can be installed in Windows 3.1, ergo the main part of this article.



General Win 3.1 howto
Another general Win.31 howto, with sound and video driver installations
Sound driver SB16W3X
Video driver S3


Logical or in package dependencies

Logical OR in rpm dependencies

Requires: (wine >= 1.3 or /usr/bin/wine)

Logical OR in dpkg dependencies

Depends: wine (>= 1.3) | wine-staging | winehq-staging | winehq



  2. rpm since 4.13.0

Delayed cleanup of temp files for shell script

If you want the temp files from your script to be left around for a few minutes, you can use a few shell tricks to remove a temp directory a few minutes later.

If the environment variable FETCH_NO_CLEAN has any content at all, the script will not clean up at all.
The script sends a heredoc to a separate, nohupped shell instance. The commands are to wait so many seconds (default of 300 seconds), and then remove the directory.

To ensure the cleanup function is called, set a trap on the most common exit codes (0 through 20) to call the function, unset the traps, and then exit.
Then you can define a tempdir, and use it to make some temp files.

Using the TMPDIR variable is safe on FreeBSD mktemp, but bash will be /usr/local/bin/bash.

Get SID from Linux ldapsearch in Active Directory

With the help of a fantastic post on ServerFault, here is a way to find a user’s SID in string format from an ldapsearch against Active Directory.

# Filename:
# Author: YasithaB
# Startdate: 2018-02-14 15:58
# Title: Script that Converts Sid from AD Ldap Hexadecimal into String
# Purpose: Help convert sid to usable value
# History:
#    2018-02-15 Modified to work with kornshell
# Usage:
#    ldapsearch -b 'dc=prod,dc=example,dc=com' -s 'sub' -x -D 'CN=My Username,OU=Domain Users,DC=prod,DC=example,DC=com' -W -H 'ldaps://' '(cn=Target Username)' objectSid | grep -E '^objectSid:' | awk '{print $2}' | ./ --stdin
# Reference:
# Improve:
# Document: Below this line

# Base-64 encoded objectSid
case "${1}" in
   "--stdin" ) read OBJECT_ID ;;
   "") : ;;
   *) OBJECT_ID="${1}" ;;

# Decode it, hex-dump it and store it in an array
H="$(echo -n $OBJECT_ID | base64 -d -i | hexdump -v -e '1/1 "%02X"')"

# SID Structure:
# LESA = Little Endian Sub Authority
# BESA = Big Endian Sub Authority
# LERID = Little Endian Relative ID
# BERID = Big Endian Relative ID



echo "${SID}"

getent passwd -s sss LOCALUSER shows local user


I want to easily and quickly tell if a user is local or domain (don’t care which domain).


  • freeipa-client-4.6.1-3.fc27.x86_64
  • sssd-1.16.0-4.fc27.x86_64

Full story

I am writing a script that will show if a user is local, sssd, can ssh, and is permitted by sssd.

Currently I am doing the check for if the user is from the domain with the getent passwd -s sss $USERNAME command. But I ran into an issue where checking the sssd database returns a local user!

# getent passwd -s sss 'bgstack15-local'

Checking the contents of the database (cache) for sss shows sssd apparently caches all sorts of information about the local user.

# sudo su root -c 'strings /var/lib/sss/db/* | grep bgstack15-local' | sort | uniq
[...output truncated]

I tried clearing the sssd cache overall, and just for the user. Neither made a difference.

# sss_cache -U
# sss_cache -u bgstack15-local

The user does show up as a local user, and I promise it is only a local user!

getent passwd -s files 'bgstack15-local'

The man pages for getent(1) and getpwent(3) don’t help me understand what could be going on. sssd(8) shows me that sssd can cache local users, which actually goes against what I want! The nss section of sssd.conf(5) doesn’t help, but maybe I didn’t take enough time to read it. I’m a little stuck.

My sssd.conf

id_provider = ipa
ipa_server = _srv_,
ipa_domain =
ipa_hostname =
auth_provider = ipa
chpass_provider = ipa
access_provider = ipa
cache_credentials = True
ldap_tls_cacert = /etc/ipa/ca.crt
krb5_store_password_if_offline = True
services = nss, pam, ssh, sudo
domains =
homedir_substring = /home

Last resort

I can try doing my checks against ${USERNAME}@${DOMAIN} when doing the -s sss check, but that means I then have to iterate over all domains in sssd.conf and that would slow the process down.


The option that controls this behavior is buried in sssd.conf(5) on CentOS 7 and Fedora, but not in the online man page.


enable_files_domain = false

Reference 3 shows that sssd makes a “fast cache for local users.”

From man sssd.conf(5) on my Fedora system:

   enable_files_domain (boolean)
       When this option is enabled, SSSD prepends an implicit domain with
       “id_provider=files” before any explicitly configured domains.

       Default: true

Disabling this behavior lets me make a simple check to see if it is a local user or domain user.


  1. ddg: sssd disable caching local users
  4. Fedora 27 sssd.conf(5)

Ldapsearch notes

This post will be updated over time.

List all members of an AD group, including following the nested group membership

ldapsearch -b 'dc=dc=example,dc=com' -s 'sub' -x -D 'CN=B Stack,OU=Domain Users,DC=example,DC=com' -W -H 'ldaps://' '(&(objectClass=user)(memberof:1.2.840.113556.1.4.1941:=CN=complex_sample_group,OU=Linux,OU=Security Groups,DC=example,DC=com))' samaccountname | awk '/^samaccountname/{print $2;}'



Compiling Pale Moon web browser on Fedora 27



I like the traditional model of Firefox. This is easily represented in the current project Pale Moon. The upstream project does not currently provide instructions for compiling on Fedora 27. All the options they have documented are on their developer site:

You might think it is no big deal to download and compile an application. But when the application is still targeted for gcc4.9, it’s a little tricky to compile on the current Fedora which uses gcc7.

After consulting the Internet, I have assembled my instructions for compiling Palemoon on Fedora.

Compile palemoon on Fedora 27

# Install the whole set of packages listed on (primary ref 1) for CentOS7
sudo dnf -y install gtk2-devel dbus-glib-devel autoconf213 yasm mesa-libGL-devel alsa-lib-devel libXt-devel zlib-devel openssl-devel sqlite-devel bzip2-devel pulseaudio-libs-devel
sudo dnf -y groupinstall 'Development Tools'

# Install additional dependencies I found
sudo dnf -y install nspr-devel

# Use autoconf 2.13
autoconfver="$( autoconf --version 2>/dev/null | awk 'NR==1 {print $NF*100;} END {print "0";}' | head -n1 )"
test ${autoconfver} -ne 213 && test ${autoconfver} > 0 && sudo mv /usr/bin/autoconf /usr/bin/autoconf-${autoconver} 2>/dev/null ; sudo ln -sf autoconf-2.13 /usr/bin/autoconf

# Use the copr davidva/gcc49
sudo dnf -y copr enable davidva/gcc49
# fix the $releasever variable in the repo
sudo sed -i -r -e 's/-\$releasever-/-23-/;' /etc/yum.repos.d/_copr_davidva-gcc49.repo
sudo dnf -y install gcc49
# fix a minor library problem (primary ref 2)
pushd /opt/gcc-4.9.3/lib64/gcc/x86_64-fedoraunited-linux-gnu/4.9.3
sudo cp -p ../lib64/ .
sudo ln -s

# Fetch palemoon source
mkdir ~/pmsrc ~/pmbuild
cd ~/pmsrc
git clone .

# Prepare to compile
# use .mozconfig from (primary ref 1)
touch "${tf}"
cat <<EOFMOZCONFIG > "${tf}"
# Please see for restrictions when using the official branding.
ac_add_options --enable-official-branding

mk_add_options MOZ_CO_PROJECT=browser
ac_add_options --enable-application=browser

mk_add_options MOZ_OBJDIR=/home/$USER/pmbuild/

ac_add_options --enable-optimize="-O2 -msse2 -mfpmath=sse"
ac_add_options --with-pthreads

ac_add_options --disable-installer
ac_add_options --disable-updater

ac_add_options --enable-release
ac_add_options --enable-devtools
ac_add_options --enable-jemalloc
ac_add_options --enable-shared-js

ac_add_options --enable-strip

ac_add_options --x-libraries=/usr/lib

# Compile:
mkdir ~/log
cd ~/pmsrc
source /usr/bin/gcc49
{ time ./mach build ; } | tee -a ~/log/pmsrc.$( date "+%Y-%m-%d-%H%M%S" ).log
echo done

Future steps

Post these instructions on the fedora and palemoon fora.
Ask Pale Moon devs if these can be adapted and shared on Reference 1.




  2. ensure lib files are in right dir:


  1. A great example and future reference

gcc 4.9 for Fedora 27

If you want gcc 4.9 (the GNU Compiler Collection) on the current version of Fedora, which is Fedora 27, there is an easy option for you!

You can use the Cool Other Packages Repo, or copr, written by the user davidva.
The easiest way to use his gcc49 copr is this:

sudo dnf -y copr enable davidva/gcc49
sudo sed -i -r -e 's/-\$releasever-/-23-/;' /etc/yum.repos.d/_copr_davidva-gcc49.repo
sudo dnf -y install gcc49

There is a weakness in the repo file delivered by the copr, where it uses the $releasever instead of a static number 23 used by the repo. Davidva compiled the package without a specific fedora version number tied to it, so it will install on any version of Fedora, as long as you can get to the rpm package.
There is also a weakness with a particular library. It’s in the wrong directory, so it cannot be found. You might find an error when trying to compile a project:

/usr/bin/ld: cannot find -lgcc_s

Use these steps to fix it (Weblink 2).

pushd /opt/gcc-4.9.3/lib64/gcc/x86_64-fedoraunited-linux-gnu/4.9.3
sudo cp -p ../lib64/ .
sudo ln -s

As the copr page (Weblink 1) indicates, this installation of gcc 4.9 can be present concurrently with the main gcc installation. To use version 4.9, you need to run:

source /usr/bin/gcc49

Which sets a few variables, notably $CC and $CXX to be the specific binaries from this package.


  2. ensure lib files are in right dir:

Shell functions for testing other functions

When I am updating or adding to my scripts package, I like to find out the fastest way to execute a task.

This involves using the time command and a few wrapper functions.

Here’s an example. I was updating my lsd (list directories) function, and I wanted to see how fast it is compared to a variant I was considering.

func() { pushd "${1}" 1>/dev/null 2>&1 ; find $( find . -maxdepth 1 -type d -printf '%p\n' | sed -r -e 's/^\.\/?//;' | sed -r -e '/^\s*$/d' ) -maxdepth 0 -exec ls -ldF --color=always {} + ; popd 1>/dev/null 2>&1 ;  } ;

func_wrapper() { __x=0 ; while test ${__x} -lt ${1} ; do __x=$(( __x + 1 )) ; __func "${2}" "{$3}" ; done ; }

So now you can run the wrapper and tell it how many times to loop:

time func_wrapper 1000 . 1>/dev/null

real    0m6.081s
user    0m2.103s
sys     0m5.157s