03 Feb 2020 [Permanent link]
(This isn't really anything too tricky, but since it took me a few
minutes to figure out and I had to do some grepping in the source code
I figured I should mention it.)
Quake (1996) is a great game. I know it, and if you didn't already, now you do, too. Better still, the engine source code is freely available under a nice license, so if you have an original CD you can port it to whatever machine you want and use the CD's assets to play the game on that system. I know there are nicer forks around, but I chose to build an engine as close as possible to the original source code as dropped by Id/John Carmack (I'm too young to remember the initial code drop, so I don't know how exactly that's attributed).
I got it to build with just a few minor tweaks (like having to force gcc to build it for i386 (32-bit) with `-m32`) after installing the 32 bit versions of the libraries it depends on) and changing a couple hardcoded paths in a makefile.
The problem is, though, that most (all?) modern-ish optical drives don't have an audio output that can be mixed into a sound card like old-school CD drives usually did. Quake would play music tracks off the disc just like an audio CD player (CDDA player) would, from 'red book' audio stored as tracks on the game disc. My laptop's most certainly doesn't, and neither do the drives in my desktop, which are both rather new since I lack IDE on my motherboard and my PCI IDE controller only supports hard disks.
It turns out that (for Linux kernels at least) CDemu is capable of handling cue/bin or toc/bin CD images as if they were physical discs in a virtual physical drive. That includes red book audio playback. So I ripped my Quake CD with `cdrdao` (since I use debian; other distros may use different tools) to make a .toc/.cue pair (TOC is cdrdao's preferred format, but it can be converted to .cue as needed).
After building and installing CDemu (it is not packaged in Debian, although they do provide .deb packages I could probably have used instead. Since I run a custom kernel I didn't want to have to deal with any incompatibilities, so I just did a source build), as well as GCDemu (a GUI for it), I was nearly there, but audio still wouldn't play.
I figured out after inspecting the man pages and source code that cdemu-daemon uses `libao` to play back audio, and that it defaulted to pulseaudio, which I do not use and never want to have to deal with ever again (long story for another time, it goes back nearly as far as my starting to use Linux distros when I was around 13… about ten years ago now). Turns out they let you change the audio driver being used with a configuration file at `~/.cdemu-daemon`. I just made the file and put the following line in it, and then restarted `cdemu-daemon`:
AUDIO_DRIVER=alsa
Since I already had a nicely configured ALSA setup (another story for another time) that allows more than one program to play sound at once, this was all it took. According to the man page, some other options are `oss`, `pulse`, and `null`. There may be more, but I don't know what all libao supports. The documentation also says it defaults to `null`, but never says where to change it; I figured out that the file is `~/.cdemu-daemon` while grepping through the sources to find out how the daemon started when `gcdemu` is run. Now however, I can play X11 Quake with music as it was intended!
14 July 2019 [Permanent link]
Hello. My first blog post is a bit of a rant, but hopefully you
feel like you learned something from it. I mainly write this for
my peers – CS students who possibly don't know much about the
history of Unix, or what a POSIX shell means. The kind of people
who have only surface level knowledge of Unix/Linux, but spend
most of their time in Windows.
So, first off. Your shell on your Ubuntu or other generic
GNU/Linux system is almost certainly bash. There's
absolutely nothing wrong with this in and of itself; bash is
great, and for interactive use, probably a good way to get used
to bourne-like shells. Maybe 'bourne shell' doesn't ring a bell
to some of you. I'll do my best to explain it.
TL;DR: Please use '#!/usr/bin/env
bash' if you want to write a bash script; bash is not always
the same as /bin/sh.
Caveat – I was born in 1996, after most of the dust from the
events I am about describe had already settled or was quickly
settling. By the time I was old enough to have any sort of
experience with these events, they were already very old. But I
love learning about history of basically everything, and
especially about fields that interest me.
–OK, now that that's out of the way…
Essentially, the earlier widely used versions of Unix were in
two camps: commercial Unix, such as System V
("System Five"), and research Unix, such as "Version 7".
Don't worry about the numbers in the names too much – if it
helps, know that the commercial unix releases made by AT&T
all used roman numerals, and were derived from research Unix
with some nice toys and tools added in. Most notably, for this
discussion, those tools included an early version of the Korn Shell
(or ksh, so named because of its initial author, David G. Korn).
None of these Unix systems were free of cost - AT&T
required a licensing payment, which gave the purchaser a copy of
the source code for the operating system to do whatever he or
she wanted with. AT&T was, if I understand correctly,
required in the late 70's and early 80's, required to license
its software like this because of the way it was regulated by
the government prior to the 1984 break-up of the Bell System,
which was up until that time a government regulated
(near-)monopoly. The UC
Berkeley Computer Systems Research Group was a licensee,
and some academics (students and faculty) began modifying and
adding to their installation, sharing their software with other
paid Unix licensees (other academic institutions, for instance).
By the early 90's, AT&T had raised licensing costs for
commercial unices to the extent that the CSRG decided to
re-write all of the remaining AT&T code in their version of
the OS. This became the source of modern FreeBSD, NetBSD,
OpenBSD, MirBSD, and others (to an extent, Mac OS X is also a
descendant of the last CSRG BSD release).
I bring all of this up because due to its ownership, the Korn
shell was not available to users that did not have a valid
license from AT&T. Korn shell was and is vastly powerful,
and also is compliant with a standard known as POSIX (or
Portable Operating System Interface). This is a standard that,
if followed, aimed to allow scripts and programs written for one
compliant operating system to run on any other compliant system.
POSIX is largely modelled on System V commercial Unix, with some
later additions and removals. Un-encumbered BSD's at first had
to use 'csh', a non-compatible alternative shell, and later on
largely or entirely POSIX compatible shells such as the Almquist
Shell. These are less powerful than modern ksh (ksh93) in
many respects, but performed their functions, especially the
almquist shell ([t]csh has lots of problems I won't get into
here). But Ksh's absence before it became 'free software' was
felt in the form of incompatible scripts.
In the world of shells, POSIX was originally important because
if a script was written for the theoretical "POSIX
Shell," using only software that follows the POSIX
standard, it should be able to run the same on an IBM AIX system
as it would on a Sun Solaris or SGI IRIX workstation.
Today, it is slightly less vitally important to follow it to the
letter, but I argue that it still should be a concern. The
reasons for this are varied:
So, if you want your script to run on a Mac at some point, it
makes sense to limit yourself to the features that are
guaranteed to be on the Mac (which is currently a certified
POSIX-compliant platform). The same goes for the other BSD's,
except that they aren't officially certified as
compliant (they are at least 99% compliant, though).
A benefit of following this approach was that I was able to
transfer nearly all of my shell-based tools in my ~/bin
directory (where I keep local programs I want to be able to
execute from anywhere at any time) directly to a mac and to a
FreeBSD installation, and have them work flawlessly. By
initially avoiding things like 'sed -i,' I was able to save
myself time later.
Now for the fun part, and where the title of this post came from:
'#! /bin/sh' is often found at the top of shell scripts. Any POSIX compliant shell will see this as a comment, but an extension that many follow, which comes from early versions of research Unix, is that if a file starts with '#!', the remainder of that line is to be seen as the program to pass the file as an argument to.
While a POSIX shell is not necessarily going to execute your file that has '#! /bin/env python' by running '/bin/sh /path/to/script.sh', it may do so, and otherwise will simply execute in the same type of shell as the one that called it.
'/bin/sh' usually refers to the Bourne shell – for all intents and purposes, the shell that the POSIX shell (and Korn Shell/Bash) grew out of and are based upon. By specifying it, you are saying that your program will run correctly in what is likely (but not guaranteed) to be the default shell of the entire system. This is almost always a POSIX shell.
FreeBSD does
not even include Bash in a default installation.
Even if it is installed, it will be in /usr/local/bin, if
installed via ports or the binary package manager, so your
#!/bin/bash shebang still won't do the job! By using
'#!/bin/sh', you are (in my mind) essentially saying one of
three things:
Basically, I'd urge you to look up the tools you see
recommended in Stack Overflow answers– Think to yourself,
"Huh, I wonder if this program has this flag in its POSIX
definition, or if this is an extension." Maybe your tool isn't
in POSIX at all! Then, I'd like you to decide – does that
matter, in this particular case? Are you trying to maximize the
utility of your script for others on multiple platforms? Do you
only have to worry about a single known target? Are you just
trying do something fast and get it over with so you can move on
with your life? I do all of these sometimes, but if your intent
is to share, please consider sticking to the basics!
I hope this didn't come across as too negative, and was
somewhat informative. Sorry it turned out so big. I'll probably
edit it over the next couple days for size and coherence, since
I am sure I lost my train of thought in a couple of places.
Thanks for reading.