Sunday, November 28, 2010

LPD Music Hack - How it's done

People have been asking how to achieve the lpd music hack, which was used at Friday night geekery #1.

First of all I would like to explain that the idea is not my own. OpenBSD developers have been using this technique at their hackathons for years now. I was first exposed to this hack at p2k9 when I was enrolled as an OpenBSD dev, then i asked for the configs at p2k10. So basically the message is "this was not my idea, but it's awesome".

Requirements



A single music server which maintains a playlist, playing tracks one at a time. Users should be able to queue their own music from their own machines without having to put anything into a database up-front (which is why mpd sucks for this). Users should be able to view the playlist.

Seems simple huh? Well no software I know does this.

Configure Server




  • Find a machine capable of playing audio and install OpenBSD on it. Do not enable aucat, or if you do, make sure the daemon user can use the aucat socket.

  • Set up a print spool that will use a shell script as it's filter. An /etc/printcap like this:

    mp3|lp:\
    :lp=/dev/null:mx#0:if=/opt/bin/mp3spool:sd=/var/spool/output


  • Permit remote printing

  • Set up an /etc/hosts.lpd and list hosts that should be able to play music. If you are in a trusted network, you can just stick in a '+', meaning "everyone with a reverse lookup name". If your hosts do not have reverse DNS records, then list them in /etc/hosts instead. Make sure that /etc/resolv.conf is configured correctly to do so.

  • Make the spooling script

  • Make the script that 'if' refers to in the print spooler, so in our case /opt/bin/mp3spool.


    /usr/local/bin/mplayer -vo null -af resample=48000 - || true > /dev/null 2>&1


    Make sure the script is executable.

  • Start lpd


  • Just type `lpd` as root. If you want lpd t start at boot, `echo 'lpd_flags=""' >> /etc/rc.conf.local`

  • Test the server

  • `lpq` should display 'no entries' and you should be able to queue songs using `lpr /some/song.mp3`, for example.


Configure Clients




  • Set up spooler

  • In /etc/printcap:

    lp:\
    :lp=:rm=servers_ip_here:rp=lp:sd=/var/spool/output:lf=/var/log/lpd-errs:


  • Start spooler in the same way as the server, `lpd`


  • Test clients

  • `lpq` and `lpr` should work in the same way as on the server.


That's it!

A few extra notes:


  • When you are using `lpq`, song names may be too long and truncated to '...', in which case, you would use `lpq -l`.


  • User's may de-queue their own tracks using `lprm jobnumber`, as long as the song is not already playing. The job number is found in the short `lpq` output.


  • Assign a "queue admin" who has root access on the server. If a crap song comes on and 3 people vote it off, the queue admin can kill the job using lprm as root.

  • If others don't use lpd or can't be arsed to set up cups (i don't blame you), then you can distribute a script to queue songs locally from the server. This is what we used:



    #!/bin/sh

    host="username@servername"
    path="/tmp/"

    if [ "$1" = "" ]; then
    echo " q.sh "
    echo " q.sh -l"
    exit 1
    elif [ "$1" = "-l" ]; then
    ssh ${host} lpq -l
    exit 0
    fi

    file="`basename \"$1\"`"
    scp "$1" "${host}:${path}\"${file}\""
    ssh ${host} "lpr ${path}\"${file}\""
    ssh ${host} "rm ${path}\"${file}\""


    If you do this you will either have to set up a user account for each user (if you want to see who queued what in the playlist), or if you are lazy, use a single user account on the server.


So, it's quite a hack and it amazes me that there is no better solution yet. Please someone write one.

Please leave know-it-all comments underneath, if you must.

Thursday, April 08, 2010

That Time When There Are No OpenBSD Snapshot Packages

Every six months there is a period of time when efforts of package building shift from building snapshot packages (for -current and snapshots) to building release packages; It is usually about a month or so. Also snapshots of base usually are not built either.

In the past I had just lived with it and not updated either my base or my packages, but recently I needed new packages. I would normally use `pkg_info -u`, but you can't if no packages are available. So you have to build them from source... But how do you build just the ones you have installed... A naive user will update their ports tree and go to /usr/ports and type "make update". This will work... If you don't mind building a package for everything in the ports tree and then updating only the ones you have installed.

I sure as hell don't have time to build all those packages, let alone disk space too! Here is a better way:


  • As usual, get a fresh base installed. As I said, around release time there are no binaries! I refer you to the FAQ. We want new packages, so why do we need a new base? Because you can't mix and old base with a new ports tree, it just won't work. Sorry.


  • Update your ports tree with `cvs up` (or if you have not checked it out yet, do that. All documented in the relevent FAQ sections).


  • I usually now "prune" my installed packages. By this I mean mean remove all the stuff that I don't really need to make the update faster. I have a hacky script to do this (and it is hacky):


    #!/bin/sh

    TMPOLD=/tmp/PKGPRUNE.old
    TMPNEW=/tmp/PKGPRUNE.new

    if [ "$EDITOR" = "" ]; then
    EDITOR=vi
    fi

    pkg_info -t > ${TMPOLD}
    cp ${TMPOLD} ${TMPNEW}
    ${EDITOR} ${TMPNEW}

    REMOVE=`diff -u ${TMPOLD} ${TMPNEW} | tail +4 | grep -e '^-'| \
    awk '{print $1}' | cut -b 2-`

    if [ "${REMOVE}" = "" ]; then
    echo "No packages selected. Abort."
    exit 0
    fi

    echo "Will remove:"
    echo $REMOVE
    echo

    echo "Enter to continue or ^C to exit"
    read edd

    sudo pkg_delete ${REMOVE}

    rm ${TMPOLD} ${TMPNEW}


    What this does is remove any packages whose line you delete from the editor session you are dropped into. It only shows packages that have no dependencies (thanks to pkg_info(1)'s -t). Basically go down the list and remove stuff you will not use. You might want to repeat this a few times, because as you remove packages, you will expose more packages that have no dependencies.


  • So now the only packages you have installed are the ones you want to upgrade. We are now able to make a list of sub-directories these packages are built in. I usually do:


    pkg_info -Pq > /tmp/LIST


    Examine the file we just made so you get an idea of what we just did.


  • Let's get to it:


    $ cd /usr/ports
    $ SUBDIRLIST=/tmp/LIST FORCE_UPDATE=Yes make update


    Make sure you understand what FORCE_UPDATE does, as it has security implications. See ports(7) for info.


  • Go and do something that takes while. Like buying Edd stuff.




That's it :)

Sunday, February 21, 2010

Wednesday, February 10, 2010

CodeByte: OpenBSD Linked Lists

If you are ever doing systems programming on OpenBSD, there are a number of linked list macros pre-defined, which you may find useful. See the manual page for QUEUE(3).

Here is a quick example I knocked up:



#include <stdio.h>
#include <sys/queue.h>
#include <stdlib.h>
#include <string.h>

#define SWM_MAX_ALT_WM_NAME 32

struct alt_wm {
SLIST_ENTRY(alt_wm) entries;
char wm[SWM_MAX_ALT_WM_NAME];
};

int
main(void)
{
struct alt_wm *n1, *n2, *n3, *node;

SLIST_HEAD(head, alt_wm) alt_wms_head;
SLIST_INIT(&alt_wms_head);

n1 = malloc(sizeof(struct alt_wm));
strlcpy(n1->wm, "cwm", SWM_MAX_ALT_WM_NAME);

n2 = malloc(sizeof(struct alt_wm));
strlcpy(n2->wm, "fvwm", SWM_MAX_ALT_WM_NAME);

n3 = malloc(sizeof(struct alt_wm));
strlcpy(n3->wm, "cde", SWM_MAX_ALT_WM_NAME); /* oldskool */

SLIST_INSERT_HEAD(&alt_wms_head, n1, entries);
SLIST_INSERT_HEAD(&alt_wms_head, n2, entries);
SLIST_INSERT_HEAD(&alt_wms_head, n3, entries);

SLIST_FOREACH(node, &alt_wms_head, entries) {
printf("%s\n", node->wm);
}

return(0);
}

Wednesday, February 03, 2010

Easter Egg in DDD

Everyone knows and loves ddd. I use this tool a whole lot for dynamic reverse engineering, but only today I found a cool easter egg.


  • Start DDD from a terminal

  • Press ^C on the terminal and a new menu appears in the GUI

  • On this menu is a tic-tac-toe game!



Wednesday, November 18, 2009

Setting up a printer on OpenBSD and CUPS for use at University of Kent Computing Lab

So I have wasted much time trying to figure this out on a couple of occasions now, so I am going to document how it is done:


  • Install cups - pkg_add -i cups

  • Install samba-cups - pkg_add -i samba

  • Do the stuff it says to do in the install message.

  • ln -s `which smbspool` /usr/local/libexec/cups/backend/smb

  • Start cupsd - /usr/local/sbin/cupsd

  • Goto localhost:631 in a browser

  • Add a samba printer with url similar to: smb://username:password@ukc/hostname/queue



If the www interface will not accept the root password, try adding a user 'cupsys'.

Sunday, November 01, 2009

Slacker Update

So I have fallen in to that cycle that we all do, the "Oh hai, I have not updated this in ages!" cycle.

So the two areas of my geek life that have changed are, a) a change of University, b) life as a new OpenBSD developer.

University of Kent



Having finished my undergraduate degree at Bouremouth University, I have moved on to the University of Kent to do a PhD in reverse engineering of executable code. The uni is very green indeed, its like a large field scattered with a few buildings. Amusingly some of the building are mirror images of each other, making them most confusing. There is a rumour that these buildings were designed as prisons because they didn't think a University would succeed?! Come to think of it, those buildings are very prison-feeling.

The infrastructure here is great. I was most impressed. Some of the highlights:


  • Several outward facing UNIX boxes for students to SSH into (or use via sunrays in a room called "rox")

  • Option to have your @kent.ac.uk mail delivered to one of these machines for retrieval using mutt, pine or mail, or even via IMAP/POP.

  • VPN - Will be useful if I move off-campus

  • Subversion and trac hosting for all students

  • University hosted IRC server, which we mostly use for arranging lunch and pub meets.

  • Dedicated sysadmins, ones who have heard of UNIX. Ones who run it on their desktop. Ones who hang on IRC and help people out. Very refreshing.

  • MirrorService - A large opensource mirror, including sourceforge, many linux distros, BSD distros, firefox etc...



So thatsa all useful stuff. I am settling in well, getting on well with my supervisor and office-mates.

P2K9



I was invited to the OpenBSD ports hackathon this year, where I became an OpenBSD developer. I amanged to get a fair amount done that week, including:


  • The much needed MPlayer update.

  • TeX Live 2009.

  • TeX Works update (to a release).

  • Xpdf security fix.

  • Javascript support for elinks.

  • OpenTTD update.

  • Ziproxy.

  • Pms update.

  • Qt-creator.

  • Flickcurl update.

  • Orbital Eunuchs Sniper (games/snipe2d).

  • A brief look at mixxx, cmake and ncmpc.



Amongst the hacking, beer, spa, feasting etc :)

p2k9

p2k9

Tuesday, June 16, 2009

Mastering Audio on OpenBSD

As you probably know, hacking is more fun with music. Perhaps some Megadeth or some Genghis Tron? My point is; I can't hack with no music. I don't know if this is just me, but if my music skips when I change virtual desktop or build some code, my mind also skips. It distracts me and annoys me.

Ever since I started running Gnome on my desktop, (which sometimes I do), this was the behavior I got. Various attempts to renice the music player (MPD in this case) made no difference. This led to a look at aucat.

When run in daemon mode, aucat behaves like one of these userland audio daemons, like artsd or esd. OpenBSD has it's own sound backend called 'sndio', which uses the sun driver underneath. Any application using sndio will attempt to connect to an aucat daemon and use it. If the app can not find a daemon, it will address the device node directly. Sounds great, but then comes the problem of the permissions of the socket the aucat daemon will use.

When 'aucat -l' starts, it will make a socket in /tmp/aucat-[id], where [id] is the user id of the user which started aucat. This means that if a different user trys to run sndio apps, they will look in a different place for the aucat daemon, not find the other user's instance, attempt to use the device node directly, only to find the node locked by the other user's aucat daemon. Oh dear. Classic example: mpd runs as '_mpd' and the user 'edd' also wishes to share the aucat daemon.

I have come up with a somewhat clunky solution:


#!/bin/sh
# Edd Barrett
# start aucat and provide access to all users in the aucat group

me=`whoami`
if [ "${me}" != "root" ]; then
echo "link_aucat is for charlie root only!"
exit 1
fi

aucat_users=`(groupinfo aucat | grep -e '^members' | cut -f 2-) || echo ""`

if [ "${aucat_users}" = "" ]; then
echo "do you have an aucat group configured?"
exit 1
fi

pkill aucat
rm -Rf /tmp/aucat-*
nice -n -20 aucat -l -b 7000
chgrp -R aucat /tmp/aucat-0
chmod -R 770 /tmp/aucat-0

for user in ${aucat_users}; do
id=`userinfo ${user} | grep uid | awk '{print $2}'`
ln -sf /tmp/aucat-0 /tmp/aucat-${id}
done


This starts aucat with a buffer of 7000 frames (enough to shield against Gnome), with a top priority (nice of -20, you will need this). It then allows the aucat group to use the socket and makes symlinks for the users in the group, therefore allowing aucat to be shared and for multiple streams to be mixed (which the pure sun driver is incapable of).

I wish such a script existed in base.

Monday, May 18, 2009

Configuring X11 with SSH Keys without Gnome-keyring

Hello,

As requested by Didi, an example of how to configure X11 with SSH keys without gnome-keyring. I pulled parts of this from the default xdm Xsession of OpenBSD. Wack this is your .xsession or .xinitrc. You could do what I do and symlink them to the same file. I am lazy.


ssh_keys() {
id1=$HOME/.ssh/identity
id2=$HOME/.ssh/id_dsa
id3=$HOME/.ssh/id_rsa
if [ -x /usr/bin/ssh-agent ] && [ -f $id1 -o -f $id2 -o -f $id3 ];
then
eval `ssh-agent -s`
ssh-add < /dev/null
fi
}

do_exit() {
if [ "$SSH_AGENT_PID" ]; then
ssh-add -D < /dev/null
eval `ssh-agent -s -k`
fi
exit
}

ssh_keys
exec xrandr --output VGA --mode 1680x1024 &
exec xterm -e sh /home/edd/eck/trunk/bin/iftool ral0 &
exec feh --bg-scale ~/.bg &
#exec xclock -digital -geometry +0-0 &
exec sudo pkill xconsole &
exec tint &
exec rox -p default &
exec openbox
do_exit

Wednesday, May 13, 2009

More LaTeX Gems from Dissertation Land

Hello,

Another quick post I am afraid. Here are two recent discoveries, which I think you will like and a web-link you may find useful:

Dot TeX



With this package you may embed directly graphviz "dot" pictures into your LaTeX, for example:


\usepackage[shell,pdf]{dottex}

...

\begin{dotpic}
/* Styles */
size = "3,4"

"Parser Grammar + Actions" [shape=box, width=1.9];
"Parser C Code" [shape=box];
"Tokeniser C Code" [shape=box];
"Compiler Executable" [shape=box];
"Tokenisation Rules" [shape=box, width=1.9];

subgraph cluster1 {
label = "Parser";
labeljust = "l"
color = blue;
"Parser Grammar + Actions" -> "Yacc / Bison" -> "Parser C Code";
};

subgraph cluster2 {
label = "Tokeniser";
labeljust = "r"
color = red;
"Tokenisation Rules" -> "Lex / Flex" -> "Tokeniser C Code";
};

"Parser C Code" ->"C Compiler";
"Tokeniser C Code" ->"C Compiler";
"C Compiler" -> "Compiler Executable";
\end{dotpic}




Those Pesky Underscores



I find it really annoying that the underscore character in LaTeX causes an error if not escaped eg. '\_' (or if you are sick '\textunderscore'). So just type \usepackage{underscore}. Done.

I would recommend you do not do this in class and style files, as people will have the tenancy to pull bits from those and wonder why the macros no longer work in the absence of \usepackage{underscore}.

My TeX Resources Page



As a lot of my fellow students are also doing dissertations, I thought I would point out my TeX resources page, which is a big old list of TeX/LaTeX related stuff which may help. I have been building this list over the last 3 years. I hope you find it useful and please let me know if you think I have missed something.



Thanks