OS X 10.6.3 broke ncurses

As I was working on my Seitunes project, I noticed something strange: the arrows didn’t quite work any more. Instead of their proper action (up & down to change volume, right & left to change song), they all quit the program and printed -respectively- “OA”, “OB”, “OC” and “OD” on the stdout.

I tried to go back to a working state by progressively deleting new features I was implementing, until I had exactly the same code as the (known working!) 0.5 version, but it was still quitting. gdb told me it wasn’t a crash (“Program exited normally”).

After some testing, I noticed Seitunes worked on my laptop, but not on my MacBook Pro. The only difference between them being that my laptop was still in OS X 10.6.2, while my mbp has upgraded to 10.6.3.

After a bit of digging into curses functions, I started to suspect keypad(WINDOW *, BOOL) to not work properly after the update. keypad() is supposed to dictate whether getch() should interpret an arrow as one non-ASCII value (with the boolean argument set to TRUE) or a set of ASCII values beginning by the escape char, a.k.a. 27 (FALSE). I explicitly call keypad(stdscr, TRUE) in Seitunes, but the FALSE state would perfectly explain the quit-then-print-two-chars behaviour I had was having: I use the escape character to quit Seitunes.

I wrote two very simple pieces of code -one for keypad true, one for keypad false- that plainly outputs the value returned by getch(). They look like:

#include <curses.h>

int main( int argc, char** argv )
{
	int key;
	initscr();
	cbreak();
	noecho();
	nonl();
	intrflush(stdscr, FALSE);
	keypad(stdscr, TRUE);
	printw("getch() should produce only one value when hitting an arrow.\n");
	while ( (key = getch() ) != 'q' ) {
		printw("You entered key %d\n", key);	
	}
	endwin();
	return 0;
}

Code and makefile available here (testCurses.zip) if you want to give it a try.

Under both OS X 10.6.2 and Linux Mint 6 “Felicia” (based on Ubuntu 8.10), these programs behave as they’re supposed to: when keypad is TRUE, an arrow is shown as a single value; when FALSE, an arrow becomes a set of values.

Under OS X 10.6.3, these two programs behave the same way. Both output several values for an arrow.

I filed a bug report to Apple (vintage interface by the way!).

While this bug is present, we’ll have to manually parse the ASCII values for the arrows, which are mapped as follows:

Up	27 79 65	('escape' 'O' 'A')
Down	27 79 66	('escape' 'O' 'B')
Right	27 79 67	('escape' 'O' 'C')
Left	27 79 68	('escape' 'O' 'D')

Edit: these values assume OS X 10.6.3 and keypad(stdscr, TRUE), a.k.a. when the bug is present.

If you want to use keypad(stdscr, FALSE) in 10.6.3, the arrows are mapped as:

Up	27 91 65	('escape' '[' 'A')
Down	27 91 66	('escape' '[' 'B')
Right	27 91 67	('escape' '[' 'C')
Left	27 91 68	('escape' '[' 'D')

Update, March 1st: Apple answered to my bugreport (ID #7812788). They told me it was a known issue (duplicate of bug #7812932) currently being investigated by engineering.

Insecure startup item disabled

As a follow-up to my post about startup items, I want to point out that a Startup Item must have proper permissions or it will be disabled at startup with the following message:

The error message saying a startup item has been disabled

In my case, the files under /Library/StartupItems/MyApache still belonged to me instead of root:wheel.

Fixed with a simple:

mbp:StartupItems florent$ sudo chown -Rv root:wheel /Library/StartupItems/MyApache/

It also appears that StartupItems permissions need to be set to 755 (executable/script file) and 644 (plist file) respectively.

Put OS X to sleep via command-line

When connecting to an OS X box via SSH, you may want to put it to sleep after you’re done.

This is no system call to put the computer to sleep that I know of. However, Applescript can do it, and it is trivial to call the OSAScript interpreter in bash.

The following script puts the computer to sleep:

#!/bin/bash

osascript -e 'tell application "System Events" to sleep'

Edit: found a better way!

I don’t know if this is specific to Snow Leopard, but the following command will work as well without having to use Applescript or administrator rights:

pmset sleepnow

Seitunes, an iTunes command-line interface

My home main computer is a MacBook Pro, on which I frequently play music with iTunes. However, I’m often on my laptop, without direct access to the MBP’s screen or keyboard/mouse to pause, change song, change volume, etc. I can connect to the MBP using VNC, but I was looking for something more lightweight.

I therefore decided to design a command-line interface for iTunes, that I would run via SSH. I called it Seitunes for reasons I can’t really remember right now, but there it is!

Seitunes is

– written in C and interfaces with iTunes through AppleScript
– designed for OS X – should be compatible with quite old versions actually, because it doesn’t rely on a lot of cutting edge features
– built upon the curses library
– very very small
– still under development
– Free software (GPLv3)
– available here

Features

> Display iTunes playing track and status

Seitunes main screen

> Control iTunes playback (play/pause, volume, next song/previous song)

Seitunes, main screen, playing, with help

> If iTunes is stopped when Seitunes starts, it starts iTunes and starts a song from the Library.

To do

> Add more tests to better check iTunes state and not trigger Applescript errors
> Add info about playlists in order to be able to play a specific playlist instead of the whole library
> Add an option to toggle shuffle
> Implement the “quit iTunes” function and check that it doesn’t cause more Applescript problems

Known bugs

> An error message flickers when an Applescript error is triggered (often when iTunes quit while Seitunes is opened)

Startup Items: launch services at boot

This post is a follow-up on the setup of your own Apache web server (although the technique can be used to start about anything of course).

Unlike classical Linuces that stock programs to launch at boot in a /etc/init.d folder for example; OS X uses a mechanism called Startup Items. These items can be found in /Library/StartupItems/, ~/Library/StartupItems and /System/Library/StartupItems.

One particular strength of the Startup Items is that you can specify in which order to launch them.

Let’s say I’ll make a startup item called MyApache. I’ll start by create the folder:

mbp:~ florent$ sudo mkdir /Library/StartupItems/MyApache

This folder will contain at least two files: an executable script called MyApache, and a file called StartupParameters.plist.

The script will be called at startup and shutdown, and will look like this:

#!/bin/sh

## Apache Web Server ; custom install ##

. /etc/rc.common
StartService (){
    ConsoleMessage "Starting Apache"
    /usr/local/apache2/bin/launchctl start
}

StopService (){
    ConsoleMessage "Stopping Apache"
    /usr/local/apache2/bin/launchctl stop
}

RestartService (){
    ConsoleMessage "Restarting Apache"
    /usr/local/apache2/bin/launchctl restart
}

RunService "$1"

The StartupParameters.plist file will contain data about the information to launch. It’s an XML file that will look like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Description</key>
    <string>My own Apache webserver</string>
    <key>Messages</key>
    <dict>
        <key>start</key>
        <string>Starting my Apache</string>
        <key>stop</key>
        <string>Stopping my Apache</string>
    </dict>
    <key>Preference</key>
    <string>Late</string>
    <key>Provides</key>
    <array>
        <string>MyApache</string>
    </array>
    <key>Requires</key>
    <array>
        <string>Network</string>
    </array>
    <key>Uses</key>
    <array>
        <string>Disks</string>
    </array>
</dict>
</plist>

We can see that Apache Requires the networks to be up, and will use Disks.

Let’s imagine I want to launch my Apache after my Jabber server for some reason. I’ll just create a StartupItem called “Jabber”, the same way as we just did, then add the following line to MyApache’s StartupParameters.plist “Requires” section:

                <string>Jabber</string>

Now at startup, OS X will launch Jabber and wait until it’s up and running before launching Apache.