July 27, 2010

Escape from the shell

Perl's exec, system, and fork functions all let one execute system commands, and they all do it by driving a POSIX exec system call so they don't invoke a shell. But Perl's backtick operator (aka the qx quotelike operator), the easiest way to capture output from a command, invokes a shell, so the arguments to the command need to be shell-escaped.

Sysadm::Install has quote and qquote functions that do a good job of this, but it's easy enough to avoid needing shell escaping.

sub command {
  my ($command, $dontchomp) = @_;
  $dontchomp //= 0;
  open(my $ph, qq{$command|}) or die "Can't fork $command: $!";
  my $raw = do { local $/ = <$ph> };
  close($ph) or die "$command returned error: $! $?";
  chomp $raw unless $dontchomp;
  return wantarray ? split "\n", $raw : $raw;
}

Note that you pass the whole command line as one string, arguments and all. The default behavior is to chomp the command output, which differs from the native backtick behavior; you can pass a true value for the second arg, $dontchomp, if you don't want it.

Reading all the output into a scalar is suitable for things with modest amounts of output (like the situtations in which you would have been using a backtick.) If you were processing a lot of output, you'd want to open the pipehandle and iterate on <$ph> yourself.

The reason I went down this rabbit-hole is wanting to get info from ratpoison so I could write some window management scripts. When you pass ratpoison a command with its -c option, it expects the whole command as one string. So we do have to worry about quote-escaping that string, like so:

sub rp {
  local $_ = "@_";
  s/"/\\"/g;
  return command(qq{ratpoison -c "$_"});
}

The way this is written, you can pass your arguments as a string or as a list, to taste.

rp("windows %c %t %n");
rp("windows", "%c", "%t", "%n");

Ratpoison lets you pass it multiple commands at once, and this rp routine doesn't, but that's usually what you want when you're getting info out of it.

June 21, 2010

CPAN handling

Later the same week I was having problems building a Python package, I rounded out my fun by having problems building a Perl package.

I learned that <prefix>/perl/<version>/Config.pm includes the various flags and settings that your perl was built with, and can be your guide to how to build things to play nice with your Perl instance. (Module::Build tries to do this automagically, but it wasn't working with the idiosyncrasies of the environment I was working with.)

June 9, 2010

Not an ez_setup

I was trying to build a Python module yesterday, but

python setup.py build

insisted on including several compiler options that the compiler immediately balked at, returning an error. This is despite that the instance of Python I was using was freshly compiled with the same environment, so shouldn't have any mistaken notions of how things should be built.

setup.py went:

if os.name == "posix":
    from setup_posix import get_config
else: # assume windows
    from setup_windows import get_config

metadata, options = get_config()
# other assignments to metadata
setup(**metadata)

so I just used pprint to look at options:

import pprint
pp = pprint.PrettyPrinter(indent=2)
metadata, options = get_config()
pp.pprint(options)

I saw that the unwanted compiler options were coming from options['extra_compile_args'] so I set that to the null list, and now I could build it.

Also, I got to find out that the 3 year old release version of mod_python 3.3.1 has a bug that causes compilation errors on some platforms (including mine, Solaris 2.10.)

May 19, 2010

Ratpoison titlechanged hook

A tiny patch I wrote was just committed to the ratpoison git repository. It adds a hook called "titlechanged" that allows you to configure actions to be taken when the current window's title is changed.

My patch included a one-line description of the hook in the manual. It's accurate enough, but by itself it remains one of those things that would leave you thinking "OK, so I can do this, but why would I want to?"

So this entry is my explanation of why you might want to.

One of the points of ratpoison is that it just draws windows, with no titlebar or other window decoration (save for an optional border.) Most of the time, I find this to be a feature -- the titlebar rarely adds anything useful, so it's usually wasted space. But I sometimes found it to be a bug when using a web browser, when the window title is whatever's the contents of the current tab's title tag, info that isn't necessarily duplicated elsewhere and occasionally has value.

At some point, I toyed with a greasemonkey script that would reproduce the title in the body of the html in some distinctive style, but it was a pain. It took a while, but eventually I struck upon my current course and realized just how easy it would be to add the necessary support to ratpoison. (I programmed in C for five years in my first job out of college, but that was a long time ago, and I wouldn't claim to be a C programmer today. But the ratpoison source is so clean and clear, the patch was straightforward.) And it's a relief to know I'll never want to cobble together an application-specific workaround again.

How I'm using it relies on inotail and dzen (compiled from source for xft support, which the Ubuntu Lucid package doesn't have.)

In my .xsession, I have:


[ -f /tmp/left ] && rm /tmp/left
[ -f /tmp/right ] && rm /tmp/right
touch /tmp/left
touch /tmp/right
killall dzen2
inotail -f /tmp/left|dzen2 -x 0 -w 400 -ta l -fg "#1F1F1F" -bg "#CFCFD7" -fn "Consolas-11" &
inotail -f /tmp/right|dzen2 -x 400 -w 1280 -ta r -fg "#1F1F1F" -bg "#CFCFD7" -fn "Consolas-11" &
/usr/local/bin/status.pl &
ratpoison

In my .ratpoisonrc, I have:


set padding 0 16 0 0
addhook switchwin exec ratpoison -c "info %t" > /tmp/right
addhook switchframe exec ratpoison -c "info %t" > /tmp/right
addhook deletewindow exec ratpoison -c "info %t" > /tmp/right
addhook titlechanged exec ratpoison -c "info %t" > /tmp/right

"set padding" leaves 16 pixels at the top of the screen for the dzen2 bar, suitable for 1 line of Consolas-11. The hooks update /tmp/right whenever a potentially title-changing event occurs. (I was tempted to fire the titlechanged hooks in ratpoison as a side effect of the other hooks, but no other hook in ratpoison chains in that fashion, and I chose not to.)

Meanwhile, /usr/local/bin/status.pl writes to /tmp/left to update the left 400 pixels with the time and current CPU temp.


#!/usr/bin/perl
my $font="Consolas-11";
my $fg="#1F1F1F";
my $bg="#CFCFD7";

while (1) {
open(KID_TO_WRITE, ">/tmp/left") or die "couldn't open /tmp/left: $!";
my ($sec, $min, $hour) = localtime(time);
my $time = sprintf "%02d:%02d", $hour, $min;

my @sensors = split "\n", `sensors`;
my ($systemp, $core0, $core1);
for (@sensors) {
/^Core 0/ && do { /(\d+\.\d+)/; $core0 = sprintf "%2.0f", $1; };
/^Core 1/ && do { /(\d+\.\d+)/; $core1 = sprintf "%2.0f", $1; };
}
print KID_TO_WRITE "$time ", (join "/", $core0, $core1), "\n";
sleep 15;
close KID_TO_WRITE;
}

I'm not using dual monitors at the moment. This setup would need some revision for that case; I'd probably want different dzen bars per screen (and I'd assign something to a switchscreen hook in ratpoison.) And the static width of the dzen bars wouldn't do the right thing with screen rotation, something I'll address at some point.

May 17, 2010

What I tell you three times is true

Two science fiction novels I love pay tribute to The Hunting of the Snark with turning points in which computers allow otherwise unauthorized behavior when the user tells it something three times. (I'm not mentioning which novels, because it's a major spoiler for one of them.)

They have inspired this utterly brilliant idea:

Set up some pre- and post-processing of command lines in your shell so that it has a history of return codes as well as a history of the command lines themselves.

If a given command is identical to the two previous commands entered, and the two previous commands exited with identical non-zero return codes, automatically escalate privilege to root.

What could go wrong?

May 5, 2010

Why I almost left Ubuntu

It's hard to believe, but I've been using Ubuntu for about 6 years now. I'd been using Gentoo beforehand; I've come to like the Debian packaging system, repositories whose intra-operability had been extensively tested (at least after release...), but with the regular release schedule putting a reasonable bound on getting recent versions of apps. And Pocahontas is happy with her Ubuntu (Gnome) desktop, and it's convenient to have all the machines in the house on the same OS.

But I don't have any use for Gnome, or KDE, or desktop environments in general. I start with a command-line system, install X, build ratpoison from source (with a patch of my own), build rxvt-unicode from source (because even Lucid's package is one release behind, missing the crucial letterspace adjustment feature), build dzen2 from source (for xft support)... in short, I was acting more like an Arch Linux user. And I was often finding the Arch wiki and forums more helpful than Ubuntu's, given how often the latter's advice was desktop environment-centric. I figured why fight it? I'd give a distro more or less aimed at compulsive customizers a go.

So I did. I have a draft blog entry lying around talking about it, which was mostly positive. But I gave up due to a fatal flaw that I suspected (and am now confident) wasn't Arch's fault. This bug in which mode_switch is intermittently locked may be common to all instances of Xorg's Xserver >= 1.7. Harmless for the majority who've never Xmodmapped a mode_switch key into existence or mapped a keyboard layout that relied on it. But if you have, it makes your system unusable. At first I'd thought my keyboard was dirty and sticking, but it persisted with a new keyboard.

I wasn't willing to unlearn my custom keyboard layout, and didn't want to learn how to do it in XKB having found that a frustrating exercise when I'd looked into it before, so I thought I'd install the Ubuntu Lucid pre-release (I think it was the last Alpha.) My latest machine didn't have a CD drive, so I was installing with a USB CD drive. And after starting, the installer complained it couldn't find the CD drive, would I like to provide a driver on floppy? This was when I remembered I'd had the same problem with Karmic. So, like I did then, I started with Jaunty, planning to dist-upgrade for there. Which I did. But whether it was due to my manually configured LVM/crypto configuration or an Alpha bug, the two dist-upgrades left me with a system that froze on the Ubuntu boot screen.

Screw it, thought I, and I downloaded and burned a Debian Squeeze installer. There wasn't a heck of a lot of distance between Ubuntu and Debian the way I did it, anyway.

That was when I found out that whatever the problem was with the USB CD driver, it was something Ubuntu inherited from Debian.

Screw it, thought I, and ripped the one SATA DVD drive in the house out of its machine and installed it in mine (my current machine has a Zotac Ion mini-ITX motherboard with no IDE headers.) I started over with Lucid.

Shortly thereafter, I encountered the same X issue. So I had to break down and learn how to map my keyboard in XKB. If mode_switch and xmodmap are so marginal that a problem of those magnitude can stand, it's probably time to throw in the towel and get with the modern technique.

So after all of that, I'm back on Ubuntu, with no reason I couldn't switch back to Arch, except that all my tolerance for installing OSes has been used up for some months to come.

April 13, 2010

Adventures in Ubuntu Lucid, Mythtv, and the Hauppauge HVR-2250

saa7164-stable won't compile with Lucid's kernel due to some name changes in recent kernels. One needs to use saa7164-dev.

Compiling saa7164-dev errors out at first, too. But after make creates v4l/.config, you can change CONFIG_DVB_FIREDTV=m to CONFIG_DVB_FIREDTV=n

The instructions to extract and install the firmware are outdated with little attention being called to the fact. Follow the directions to get dvb-fe-tda10048-1.0.fw in the right place, but then download v4l-saa7164-1.0.2-3.fw and v4l-saa7164-1.0.3-3.fw directly and save them to /lib/firmware/`uname -r` (or /lib/firmware/2.6.32-20-generic at the moment for an up to date Ubuntu Lucid.) (I've also put all 3 directly in /lib/firmware, but that's probably redundant.)

Once you've gone through all of this, and done a make install, modprobe saa7164 should make your system recognize the card. But the devices are owned by group video, and ordinary users aren't a member of it to start with. so adduser yourusernamehere video. (Remember that it won't take effect in existing logins.)

Lucid's mythtv is reasonably up-to-date and I've found no reason so far to seek out a more recent one.

I followed these instructions to migrate my old mythtv recordings to the new server (I followed the advice in a comment there to use --complete-insert, though it may not have been necessary.)

After installing mythtv, I found that its channel scan was having some trouble finding everything. So I did a wajig install w-scan dvb-apps, did a service mythtv-backend stop to make sure there was no competition for the card, and:

w_scan -x -f a -c us > w_scan.out
scan w_scan.out > w_scan_channels.conf
scan /usr/share/dvb/atsc/us-CA-SF-Bay-Area > scan_channels.conf
cat w_scan_channels.conf scan_channels.conf|sort|uniq > channels.conf

Then in mythv-setup I pointed it at channels.conf to do its scan.

mythtv-backend was being started before the devices for the video card had been created, which resulted in errors in the log, though I'm not sure whether the situation was causing any real harm. At any rate, inspired by this comment I put this in /etc/init/mythtv-backend.conf:

# MythTV Backend service

description "MythTV Backend"
author "Mario Limonciello "
# modified per http://swiss.ubuntuforums.org/showthread.php?t=1345079&page=2 to wait for devices
start on (local-filesystems and net-device-up IFACE=lo and started mysql)
stop on starting shutdown

#expect fork
respawn

pre-start script
LOG_FILE=/var/log/mythtv/mythbackend-init.log
. /etc/mythtv/mysql.txt
#get the tuner card paths
TUNERS=`mysql --user=${DBUserName} --password=${DBPassword} --database=${DBName} --skip-column-names --execute='SELECT DISTINCT videodevice FROM capturecard;'`
echo "`date`: Mythtv-backend Upstart; tuners found in database: ${TUNERS}" >> $LOG_FILE
for t in $TUNERS
do
while [ -c !$t ]; do
echo "`date`: Mythtv-backend Upstart; tuner device ${t} is not ready. Waiting 1 second..." >> $LOG_FILE
sleep 1s
done
echo "`date`: Mythtv-backend Upstart; tuner device ${t} is now ready" >> $LOG_FILE
done
echo "`date`: Mythtv-backend Upstart: tuner devices are now registered. Starting mythbackend" >> $LOG_FILE

end script

script
test -f /etc/default/mythtv-backend && . /etc/default/mythtv-backend || true
/usr/bin/mythbackend $ARGS
end script

Now all I have to do is find out why there's no sound (probably something independent of mythtv), why, even after all that scanning, it's not finding KQED (almost certainly having to do with the antenna), and why playing videos in mythfrontend causes the system to reboot after a few seconds (!)

March 16, 2010

I ♥ Perl, the command line, and Infocom text adventures

I decided to dust off (literally, it turned out) my Classic Text Adventure Masterpieces CD and install the games. I installed Malyon, the zcode interpreter for Emacs. But it checks to see that the files end .z3, .z5, or .z8, indicating its zcode version, and all the zcode files from the CD ended .dat. And some of them were version 4, so it would be useful to have them marked correctly so I know which ones Malyon won't handle. The second byte of the file is the version number (and the first byte is guaranteed to be 0), and I wanted to skip the .dat files in 'save' directories, so:

find . -name '*.dat'|fgrep -v '/save/'|xargs perl -e 'for (@ARGV) { $old=$_; read(FH, $buf, 2); $z=unpack "c", $buf; s/dat$/z$z/; rename $old, $_}'

Next thing you know, I'm west of a white house.

Short shameful confession: the first Zork is the only Infocom game I ever finished (though I came really close with Hitchhiker's.) So I figure I have my next several years of gaming lined up.

March 11, 2010

All Emacs (almost) all the time

(For those not so familar with Emacs vs Vi, let's just say this is like the social situation between Republicans and the Democrats or the Roman Catholics and Southern Baptists: You live next door to them, but you know they're going to hell.)

Emacs can run in the background as a daemon, so it starts lickety-split when you need to spawn an editor. But what if it's not running yet? I needed a convoluted method for the Emacs 23.0.60 I was running in Ubuntu Intrepid; the Emacs 23.1.1 in Ubuntu Karmic's emacs23 package includes an improved emacsclient that'll launch an emacs daemon for you if you pass it an empty string for the alternative editor (-a parameter).

That's why this goes in /usr/local/bin/editor:

#!/bin/sh
exec emacsclient -c -a "" "$@"

You're going to want to use this as your editor alternative and use that as your EDITOR environment variable, but there's a problem -- now if you sudo visudo, you're launching emacs and you're left with an emacs daemon running as root. Oops.

So you

sudo visudo

and add !env_editor,editor=/usr/bin/zile to the end of your Defaults line.

Now:

sudo update-alternatives --install /usr/bin/editor editor /usr/local/bin/editor 99
cat >> ~/.bashrc
export EDITOR="/usr/bin/editor"
export VISUAL="/usr/bin/editor"
export SUDO_EDITOR="/usr/bin/zile"

You'll want to be able to kill the emacs daemon, so this goes in /usr/local/bin/killemacs

#!/bin/bash
emacsclient -e "(progn (setq kill-emacs-hook 'nil) (kill-emacs))" && rm -rf "/tmp/emacs`id -u`"

And you'll want to automatically kill them on shutdown, so here's /etc/init.d/killemacsdaemons:

#!/bin/sh
exec find /tmp -maxdepth 1 -type d -name 'emacs*' -exec find {} -type s -name server \;|perl -ne 's/[^\d]//g; print scalar getpwuid($_), "\n"'|xargs -n 1 su -c /usr/local/bin/killemacs -

Then:

sudo update-rc.d killemacsdaemons stop 1 0 1 6 .

March 7, 2010

The first n things to do after installing an Ubuntu command-line system, where n is large

This is my guide to how to install Ubuntu. There aren't many like it, because this one is mine. This is using Karmic and for a single-user computer.

I start with the alternate install CD, and install a command-line system. There's a lot of talk about how Ubuntu is bloated, which is a little silly, as Ubuntu is not the same thing as the ubuntu-desktop metapackage. The command-line system will leave you with a few things you won't need -- it includes the tools for several filesystems, including NTFS, and support for various hardware, some of which you won't have. I don't doubt that there are leaner minimalist distributions, but it's a stretch to call this bloated.

Toward keeping it unbloated, the first step is turning off the automatic installation of recommended packages:

echo 'APT::Install-Recommends "false";' | sudo tee > /etc/apt/apt.conf.d/02notrecommended

Then I install the first tools I want:

sudo apt-get install wajig zile

That's the last we'll see of apt-get, as wajig is my preferred front end to the Debian package manager. zile is a small Emacs-workalike. Next, I make sure it gets used whenever anything needs an editor (and that I never, ever get dumped into vi):

sudo update-alternatives --install /usr/bin/vi vi /usr/bin/zile 99
sudo update-alternatives --config editor

The latter will prompt me to choose among installed editors; I pick zile.

Now I'm ready to configure sudo.

sudo visudo

I add to the line beginning Defaults env_reset, making it:

Defaults env_reset,insults,!tty_tickets

!tty_tickets makes the sudo timeout global, instead of on a per-session basis, so that if I sudo in one window, and, soon after, sudo in another, I won't have to type my password again. This is very useful. insults means sudo will insult me if I type my password wrong. This isn't useful except inasmuch as it amuses the 12-year-old in me.

Next is configuring my repository sources:

sudo -e /etc/apt/sources.list

This boils down to these four lines, with my closest mirror substituted for "us.archive.ubuntu.com"

deb http://us.archive.ubuntu.com/ubuntu/ karmic main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ karmic main restricted universe
deb http://us.archive.ubuntu.com/ubuntu/ karmic-updates main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ karmic-backports main restricted universe multiverse

plus I keep the default last few lines:

deb http://security.ubuntu.com/ubuntu karmic-security main restricted
deb-src http://security.ubuntu.com/ubuntu karmic-security main restricted
deb http://security.ubuntu.com/ubuntu karmic-security universe
deb-src http://security.ubuntu.com/ubuntu karmic-security universe
deb http://security.ubuntu.com/ubuntu karmic-security multiverse
deb-src http://security.ubuntu.com/ubuntu karmic-security multiverse

I make sure I'm up-to-date:

sudo wajig update
sudo wajig upgrade
sudo wajig dist-upgrade

Now it's time to install everything related to one of my most important tools, ssh:

sudo wajig install ssh denyhosts molly-guard sshfs yafc keychain
sudo -e /etc/ssh/sshd_config

I modify /etc/hosts to assign shortcuts to several of my most-used machines.

I set "PermitRootLogin no" (even though I don't have a root password, so no one could login as root anyway), and "PasswordAuthentication no" to disable login by password altogether -- it'll require public key authentication.

sudo adduser zed fuse

sshfs is an amazingly useful tool that lets you mount remote filesystems over ssh so they're transparently accessibly as if they were local. But you have to add yourself to the fuse group (and it won't take until you logout and log back in.) I like to drop this in /usr/local/bin/mkmnt as a convenience to make the mount points I'll use with it:

#!/bin/bash
for i in $@
do
mkdir /mnt/$i
chown root:fuse /mnt/$i
chmod 775 /mnt/$i
done

Finally:

sudo chown root:fuse /mnt
sudo chmod 775 /mnt

I used to configure denyhosts to make it more restrictive and quicker to ban, but I don't bother anymore. The defaults are reasonable. molly-guard is there to prevent accidentally shutting down or rebooting my machine when I'm logged in remotely. yafc is a much-improved sftp, with tab-completion. And keychain lets me type my ssh private key password just once. I just add this to my .bashrc:

eval `keychain --eval --nogui -Q -q id_rsa`

And I install my private and public keys in my .ssh directory.

Now we're ready to install X.

sudo wajig install hal xorg nvidia-glx-185 nvidia-settings xdm msttcorefonts ttf-liberation ttf-droid xscreensaver

This gets you a whole raft of video and input packages, most of which you don't need, but is a lot faster and easier than picking out the ones you do.

Now it's time to start building packages from source.

sudo wajig install build-essential automake m4 subversion git-core fakeroot checkinstall libtool texinfo texinfo-doc-nonfree manpages-dev
sudo wajig build-depend ratpoison
sudo wajig build-depend rxvt-unicode-ml

I like to do my building from source under /usr/local/src, so I'll make that a little easier:

chmod -R root:admin /usr/local
chown -R 775 /usr/local

First, ratpoison:

cd /usr/local/src
git clone git://git.savannah.nongnu.org/ratpoison.git
cd ratpoison
autoreconf
automake --add-missing
autoreconf

I put a patch of my own into title_changed.patch, and apply it, then build the Debian package:

patch -p1 < title_changed.patch
fakeroot debian/rules binary

This drops a .deb into /usr/local/src, and I install it:

cd /usr/local/src
sudo wajig install ratpoison_1.4.6~git-0_i386.deb

Next comes rxvt-unicode. I'm still in /usr/local/src...

wget http://dist.schmorp.de/rxvt-unicode/rxvt-unicode-9.07.tar.bz2
tar xjf rxvt-unicode-9.07.tar.bz2
cd rxvt-unicode-9.07
./configure --prefix=/usr
make
sudo checkinstall --fstrans=no

I use the name 'rxvt-unicode-ml', the same as Ubuntu normally uses for the full rxvt-unicode, the description 'rxvt-unicode-ml', and the version '9.07-1source'. Per the contents of urxvtc's man page, I put this in /usr/local/bin/urxvt:

#!/bin/sh
urxvtc "$@"
if [ $? -eq 2 ]; then
urxvtd -q -o -f
urxvtc "$@"
fi

And that's what I define as my x-terminal-emulator:

sudo update-alternatives --install /usr/bin/x-terminal-emulator x-terminal-emulator /usr/local/bin/urxvt 99

Now I can remove xterm. This'll take the xorg metapackage with it, but that's fine -- it's just a metapackage and all the stuff it installed will still be there.

sudo wajig remove xterm

Oh, so close. Now, per the xsession man page, I put this in /etc/X11/Xsession.d/35×11-custom_xmodmap --

SYSMODMAP="/etc/X11/Xmodmap"
USRMODMAP="$HOME/.xmodmap"

if [ -x /usr/bin/X11/xmodmap ]; then
if [ -f "$SYSMODMAP" ]; then
xmodmap "$SYSMODMAP"
fi
if [ -f "$USRMODMAP" ]; then
xmodmap "$USRMODMAP"
fi
fi

Then I populate /etc/X11/Xmodmap, ~/.Xresources, .ratpoisonrc, and put this in .xsession:

xscreensaver-command -exit
xscreensaver &
x-window-manager

And now we're ready to run X. It's that easy.

sudo invoke-rc.d xdm start

I edit .xscreensaver to set 'splash: False', and run

xscreensaver-demo

so I can set the Mode to 'Blank Screen Only', turn on Display Power Management, and turn off 'Fade to Black when Blanking'. There are many beautiful xscreensaver hacks, but some of them create appreciable system load. I'm running it for security.

OK, now for some miscellany. apt-file can do some tricks wajig can't.

sudo wajig install apt-file
sudo apt-file update

most is my preferred pager.

sudo wajig install most
sudo update-alternatives --config pager

Really, the whole point of the exercise is Emacs.

sudo wajig install emacs23 emacs-goodies-el python-mode yaml-mode

I like Ruby, Perl, and Nethack. Someday I will ascend.

sudo wajig install ruby-full ruby-elisp rubygems perl-doc nethack-el

Some other important command-line tools:

sudo wajig install screen ack-grep

ack-grep's intended name is ack, but that's taken in the Debian world, so I uncomment this in the default .bashrc:

if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi

And into .bash_aliases goes:

alias ack="ack-grep"

Being able to unpack things is good:

sudo wajig install atool unrar unzip

Put this in ~/.atoolrc:

use_rar_for_unpack 0

The web is pretty important:

sudo wajig install firefox epdfview privoxy

Privoxy is a filtering web proxy.

cd /tmp
wget http://neilvandyke.org/privoxy-rules/neilvandyke.action
sudo mv /tmp/neilvandyke.action /etc/privoxy
sudo -e /etc/privoxy/config

Between actionsfile default.action and actionsfile user.action, I add:

actionsfile neilvandyke.action

In user.action, I add some more sites, as well as define some sites on which to not block ads.

I get the Flash 10.1 beta:

cd /tmp
wget http://download.macromedia.com/pub/labs/flashplayer10/flashplayer10_1_p3_linux_022310.tar.gz
tar xzf flashplayer10_1_p3_linux_022310.tar.gz
mkdir ~/.mozilla/plugins
mv libflashplayer.so ~/.mozilla/plugins

Sound starts out set to zero, so I need alsamixer to turn it up:

sudo wajig install alsa-utils
alsamixer

Get and install the forbidden packages:


cd /tmp
wget http://packages.medibuntu.org/pool/non-free/w/w32codecs/w32codecs_20071007-0medibuntu5_i386.deb
wget http://packages.medibuntu.org/pool/free/libd/libdvdcss/libdvdcss2_1.2.10-0.3medibuntu1_i386.deb
sudo wajig install w32codecs_20071007-0medibuntu5_i386.deb
sudo wajig install libdvdcss2_1.2.10-0.3medibuntu1_i386.deb

Install the fonts from Powerpoint.

Monitoring is good. This includes:

sudo wajig install lm-sensors htop iftop iotop hddtemp smartmontools

Virtual machines are fun.

sudo wajig install qemu kvm

Downloader helpers.

sudo wajig install transmission-cli axel

Multimedia.

sudo wajig install mplayer-nogui flac vorbis-tools vorbisgain feh

Into every life some Microsoft Word docs must fall.

sudo wajig install antiword

Keep the computer time synced with atomic clocks:

sudo wajig install ntp
sudo -e /etc/ntp.conf

I remove the 'server ntp.ubuntu.com' line and replace it with:

server 0.north-america.pool.ntp.org
server 1.north-america.pool.ntp.org
server 2.north-america.pool.ntp.org
server 3.north-america.pool.ntp.org

I like TeX, and LaTeX, and ConTeXt and printing things.

sudo wajig install context texlive-latex-extra gv texlive-latex-extra-doc texlive-latex-base-doc cups-client texlive-latex-recommended texlive-latex-recommended-doc

That may seem like a lot, and it is, but it's still not much compared to texlive-full.

I just need a client to a Cups server running elsewhere on my local network, so I just need to populate /etc/cups/client.conf:

ServerName hostname_of_cups_server

I want to access a Samba server on my local network, so:

sudo wajig install smbfs
mkmnt smbmountpoint

I add this to /etc/fstab:

//smbhostname/Volume_1 /mnt/smbmountpoint cifs credentials=/etc/smbcredentials,iocharset=utf8,file_mode=0777,dir_mode=0777,noperm 0 0

/etc/smbcredentials is of the form:

username=smbusername
password=smbpassword

Then I just:

sudo mount -a

I've skimped on configuring Firefox, Emacs, urxvt, and on talking about the contents of my .Xresources, .Xmodmap, and .ratpoisonrc, as well as the other little scripts I put in /usr/local/bin. Maybe next time.

February 27, 2010

Manually mounting whole disk encryted drive

The Debian installer (which I've been using with the Ubuntu Alternate Install CD for years) makes it easy to set up whole disk crypto with cryptsetup, LUKS, and LVM. So easy that it's easy to forget how to get to the info when you're not longer booting the disk, but are accessing it in an external drive. So here's a reminder of how to do it when it's LVM over a LUKS encrypted partition. ls dev or dmesg to get the device name of the encrypted partition. Let's say it was /dev/sdb1.

sudo cryptsetup luksOpen /dev/sdb1 arbitraryname

sudo lvscan

This'll give you the name of the logical volumes as they were originally set up. Let's say the one you're interested in was /dev/myvolumegroup/root.

You're almost there; all you have to do is make a mount point, e.g., /mnt/lvroot and:

sudo mount /dev/myvolumegroup/root /mnt/lvroot

Ta da.

Updated: One may have to load some kernel modules before the luksOpen, e.g.,

modprobe dm_mod
modprobe dm_crypt
modprobe aes

And mark the logical volume and/or volume group active:

lvchange -ay logical_volume_name
vgchange -ay volume_group_name

January 2, 2010

Chromium: useless (to me, for now)

I've been frustrated with Firefox grinding to a halt over time, and needing restarting. I've heard tell that Google's Chromium browser is much faster on Linux, so I thought I'd try it.

It took as long as the first time I tried to type something in a text field to be bit by this bug. The X Window System supports essentially a second shift key, called mode_switch. The other keys can have different definitions for all four of their unmodified, shifted, mode_switched, and shifted and mode_switched meanings.

So far as I know, most distributions don't do anything with them by default, but I use them extensively to provide, among other things, a set of cursor keys under my fingertips, without requiring moving my hands.

In Chromium, it's as if mode_switch is being held down all the time, so those keys can only produce the cursor movement, and not their normal text values, leaving me with half my keyboard missing.

A developer has marked it WontFix, saying it was a gtk problem that's been fixed in more recent versions. It's a problem that doesn't occur in any other gtk app; the gtk bug the developer cited as responsible is clearly unrelated; and I tried updating my gtk with no effect.

I'll try delving into the code myself, but this is the extent of my gtk experience.

June 14, 2009

Civilization in Wine on Linux. How civilized.

I have the Civilization IV: the Complete Edition DVD sans DRM. It works pretty well under Wine. But this is what it took (Ubuntu 8.10, aka Intrepid):

I find it makes life easier to segregate my Wine apps, so first steps were:

export WINEPREFIX=/usr/local/civ
winecfg

There, I set Wine to also consider /usr/local/civ to be where my My Documents folder was, so the game would create its "My Games" folder there instead of under my real Linux home directory.

Wine 1.1.22. It failed with Wine 1.1.23, the current development release.
Used winetricks to install d3dx9 and msxml3
Needed this to get around a stupid sound bug:

mkdir -pv $HOME/.kde/socket-$HOSTNAME

Then just running

wine setup.exe

on the file at the top level of the DVD did the rest. I selected "custom install" so I could set a less long, obnoxious installation path than the default. I installed the just-released Beyond the Sword 3.19 patch.

I put Blue Marble on top of that, and ran vanilla Civ, Warlords, Beyond the Sword, and Colonization once each to create the appropriate folders under My Games, and to set the graphics and audio options to my preferences.

I edited each of the CivilizationIV.ini files in their respective directories under the installation directories to set NoIntroMovie = 1 and EnableVoice = 0. (The first is just by preference; the intro movies worked fine. The default EnableVoice = 1 resulted in a warning under Warlords, but not the others. Strange.) It didn't work to set these just in the CivilizationIV.ini files under My Games, which I would have thought was the point.

Finally, I backed up the results so I won't have to do all that again when I inevitably screw something up while playing with mods.

The startup scripts are simply like this:

#!/bin/bash
WINEPREFIX=/usr/local/civ 
/usr/bin/wine /usr/local/civ/drive_c/Program\ Files/civ4complete/Civilization4.exe $@

Everything but a few cosmetic details works. Unit health bars don't, city progress bars on the main map don't (this can be ameliorated by requesting detailed city info in the options), the cursor animation doesn't work, so it doesn't turn into a little spinning globe when you're waiting. So far as I can tell, everything else works. (And my words are backed by a Holy Roman spaceship at Alpha Centauri.)

June 12, 2009

Ruby string escaping weirdness

Well, that's odd... (ruby 1.8.7)

irb(main):021:0> '\\' + 'x'
=> "\\x"
irb(main):022:0> "x".gsub("x",'\\' + 'x')
=> "\\x"
irb(main):023:0> '\\' + '&'
=> "\\&"
irb(main):024:0> "&".gsub("&",'\\' + '&')
=> "&"

March 3, 2009

Recycling Palms as secondary LCD displays

Recently, I’ve had a crush on the computer lcd front panel displays you can find here or here. But they’re either tiny or expensive.

I remembered a project to let you use a Palm in its cradle as an LCD display. PalmOrb has been orphaned since 2005, and, as of the last version, indicates you’re on your own with USB Palms (which are the only ones I have left.) It actually worked decently with LCD4Linux. But it only left you with a tiny block of text, and it was harder than I’d like to customize the output.

So I tried simply running ptelnet, a Palm telnet app, to make a serial connection, and running a script that wrote to /dev/pilot (I had the visor module loaded), clearing the screen every minute (with VT100 escape codes) and sending status info.

It works pretty well, but the text is tiny, with no way to change the size. Anyone know of an alternative to ptelnet to just receive data from the serial connection and display it, that allows you to change fonts?

February 13, 2009

New and improved emacs launcher

I'm much happier with this combination. /usr/local/bin/editor is:

#!/bin/bash ALTERNATE_EDITOR=/usr/local/bin/editor2 emacsclient -c "$*"

/usr/local/bin/editor2 is:
#!/bin/bash
EMACS=/usr/bin/emacs
EMACSCLIENT=/usr/bin/emacsclient
SOCKET=/tmp/emacs`id -u`/server

$EMACS --daemon

count=25

while [ $[ count-- ] -gt 0 ]; do
if [ -e $SOCKET ] && [ ! (lsof $SOCKET &> /dev/null) ]; then
$EMACSCLIENT -c "$*"
break
fi
sleep .2
done

Among the advantages here over the old one:

emacs --daemon is only run if emacsclient can't find a socket, as opposed to emacsclient encountering any error

The old one slept for 1 second after launching the daemon. This was occasionally too short, but usually too long. This one checks for the socket five times a second, and gives up after five seconds. (There are imaginable race conditions that could give undesirable results, but I don't expect to ever actually encounter them.)

February 3, 2009

Daemon Emacs

A nifty feature in the current development version of Emacs (now available in a pretest release candidate) is that you can start it as a daemon, to which graphical and terminal clients alike can attach. A not so nifty lack of feature is there being no easy standard way to do the obvious: launch a client if the daemon's running; if it's not, start the daemon, and then launch the client. So everyone cobbles together their own. Here's mine, which cribs from here.

#!/bin/bash
if [ -z $DISPLAY ] ; then
OPT="-t"
else
OPT="-c"
fi

if [ -z "$*" ]; then
OPT="$OPT -e (raise-frame)"
else
OPT="$OPT $@"
fi
emacsclient $OPT 2>/dev/null || (
(emacs --daemon)
sleep 1
emacsclient $OPT)

I have that as /usr/local/bin/editor. To stop emacs nicely, and get prompted to save unfinished business, I have another script with:

/usr/local/bin/editor -e '(save-buffers-kill-emacs)'

October 13, 2008

My own virtual Ubuntu Intrepid

  1. Make sure your CPU supports virtualization (you may have to turn it on in the BIOS)

    cat /proc/cpuinfo |egrep '(svm|vmx)'

    If you get no response, it doesn't. A response means you're good to go.

  2. Download the Ubuntu Intrepid Beta alternate install CD

  3. install qemu and kvm

    sudo apt-get install qemu kvm

  4. create the disk image that will serve as the virtualized intrepid's hard drive

    qemu-img create -f qcow2 intrepid.img 6G

  5. start the vm, booting the Intrepid CD

    sudo kvm -cdrom ubuntu-8.10-beta-alternate-i386.iso -hda intrepid.img -boot d -m 256M

  6. Hit F4 to choose a command-line install; go through the installation.

  7. When the installation finishes and reboots, kill the VM. Restart it with:

    sudo kvm -hda qemu/intrepid.img -boot c -m 256M -redir tcp:2222::22 &

  8. In the VM, turn off apt-get automatically installing recommended packages

    echo 'APT::Install-Recommends "false";'|sudo tee /etc/apt/apt.conf

  9. In the VM, Edit /etc/apt/sources.list to point to the closest mirror

  10. In the VM, Bring yourself up-to-date and install openssh-server

    sudo apt-get update sudo apt-get upgrade sudo apt-get install openssh-server

  11. On your real machine, ssh into the VM.

    ssh -p 2222 username@localhost

  12. Have fun with your new virtual Intrepid.

September 22, 2008

xterm made easy

I’m a fan of the rxvt-unicode terminal emulator, but it has one problem: it sometimes spaces xft fonts badly, with conspicuous gaps between the characters, making for fewer characters per line.

Looking into alternatives, I found that the GTK library includes vte, a terminal emulator widget that a bunch of terminal emulators use. And they all look good, but had a drawback I couldn’t live with: none of the ones I tried recognized my Meta-keys, which I’ve grown used to using for command-line editing in my shell.

vte, along with the Ruby GTK bindings, makes life so easy, I just rolled my own. This is just the Ruby vte demo program that comes with the bindings with a couple of lines added to handle Meta-keys.

require "vte"

window = Gtk::Window.new("Terminal sample")
window.signal_connect("destroy"){Gtk.main_quit}

vte = Vte::Terminal.new
vte.set_font("DejaVu Sans Mono 16", Vte::TerminalAntiAlias::FORCE_ENABLE)

Gtk.key_snooper_install {|t, e| 
  vte.feed_child("\e")  if e.state.meta_mask? and e.event_type == Gdk::Event::KEY_PRESS
}

vte.signal_connect("child-exited") do |widget|
  Gtk.main_quit
end
vte.signal_connect("window-title-changed") do |widget|
  window.title = vte.window_title
end
vte.fork_command
window.add(vte)
window.show_all

Gtk.main

September 16, 2008

Fastest Ubuntu mirror for you

I recently learned about netselect-apt, a Debian package to find the fastest Debian mirror. Ubuntu Hardy includes it, but it's worse than useless -- it's still hard-coded to work with Debian. But it's easy enough to reproduce its essential functionality.

sudo apt-get install netselect
wget --no-check-certificate -O mirrors https://launchpad.net/ubuntu/+archivemirrors
sudo netselect -v -s 5 $(perl -F'"' -ane 'print "$F[1] " if (/United States/ .. /highlighted/) && /http/' mirrors)

That gives the top 5 (from fastest to slowest) in the US using http. It should be reasonably clear how to adjust the number returned, the country, or the protocol (which could be 'ftp' or 'rsync'.) It erroneously considers canonical.com a mirror in Viet Nam (it fails to find the end correctly for the last country in the list), but there's only one mirror in Viet Nam, and this is a quick hack, so I can live with that.

June 18, 2008

PDF Viewer

I don't use a desktop environment; I use an antidesktop environment featuring the ultra-minimalist ratpoison window manager and the ultra-maximalist Emacs.

It makes me grumpy when applications depend on installing huge portions of Gnome or KDE. So I was never thrilled with the PDF viewer choices.

ghostview and xpdf are good tools, but ugly, and they don't natively talk to CUPS print servers. evince and kpdf want to install huge portions of Gnome and KDE, respectively. I haven't tried acroread, but I scramble for alternative's to Adobe's bloated reader in Windows, so I thought I'd spare myself.

So I was happy to find epdfview, which shares some of evince's dependencies on graphics libraries without the gratuitous dependencies.

But there was a catch: Ubuntu 8.04's binary package doesn't include CUPS support, for no apparent reason (there's already a bug filed.) The good news is that you can build it yourself.

So I'm now a happy viewer and printer of PDFs while still avoiding having dbus, gamin, bonobo, etc., installed.

October 4, 2007

First look at Ubuntu Gutsy Beta

The forthcoming Ubuntu release, 7.10, the Gutsy Gibbon, is scheduled for release next month, 10/18. I recently tried installing it, and quickly encountered this bug, reported as fixed yesterday.

Ubuntu had inherited from Debian a problem whereby network interfaces' names can be inconsistent from one reboot to the next. The installer identified my mobo's wired network interface as eth1. On rebooting, the OS decided it was eth2, but /etc/network/interfaces had been configured to use the (now non-existent) eth1, hence no network.

In days' past, I've used /etc/iftab to ensure it didn't recur, but, apparently, as of Gutsy, this approach is deprecated, and the shiny new method is to use udev.

I then spent much time bashing my head against trying to arrange to boot into an encrypted root filesystem within an LVM2 logical volume on an encrypted LUKS partition, similar to this but using yaird to create the boot image. This is something I've done in the current Ubuntu release, Feisty. But I ran into a couple of bugs in Gutsy's yaird package. (The trivial one also existed in Feisty, but I didn't report it then.)

It'd be nice if Ubuntu offered an encrypted root installation option like Debian Etch, but I'd probably want enough things different from any set of options offered to end up doing it manually anyway.

I'm pretty sure I know how to fix the problem now. But I haven't had the time to take another crack at it, so my first look has been stalled here.

Maybe when I'm done, I'll write yet another encrypted root howto.

July 3, 2007

Seeking Random Numbers. Must pass Chi-Square test. No freaks.

Pocahontas had some little webcam she'd gotten a while ago as a promo item for signing up with an ISP. For a while, I've had in the back of my mind to use it to build a LavaCan. Because, you know, every home needs a cryptographically secure source of random numbers in hardware. Well, it seems like people were lucky to get this camera working with an allegedly supported OS. This guy heroically analyzed the signal between the PC and the webcam and came up with some sort of picture, but his write-up falls short of providing code.

Oh well. The Weecam's off to the Alameda County Computer Resource Center, and I'll give iwrandom a try. (But a webcam in the dark is so much cooler, drat it.)