Here’s for a small change of pace…

I’d like to talk about a tool I’ve all but forgotten I’m even using (and that’s a compliment to its stability and unobtrusiveness).

dzen is a great little application from the folks at suckless. It’s one of those do one thing and do it well types of tools. It’s probably not useful at all for anyone with a bloated –ahem, excuse me– featureful desktop environment or window manager (or both).

In my case, I’m using just XMonad with its beautiful simplicity. This means, of course, that there’s no out-of-the box… anything.

I’ve already covered some of this from an XMonad perspective, so this post is more about dzen’s general usefulness.


First up, a small visual notification when I adjust my volume:

ossvol screenshot 

It fades in (implicitly thanks to xcompmgr) for just a second when I adjust my volume and gives me that nice, unobtrusive indication of the volume level.

The actual volume adjustment can be done in many alsa or oss specific ways; for my implementation, just see the script as it is live. Completely separate of that, however, we can just use dzen to show the notification:


# we use a fifo to buffer the repeated commands that are common with 
# volume adjustment

# define some arguments passed to dzen to determine size and color.
dzen_args=( -tw 200 -h 25 -x 50 -y 50 -bg '#101010' )

# similarly for gdbar
gdbar_args=( -w 180 -h 7 -fg '#606060' -bg '#404040' )

# spawn dzen reading from the pipe (unless it's in mid-action already).
if [[ ! -e "$pipe" ]]; then
  mkfifo "$pipe"
  (dzen2 "${dzen_args[@]}" < "$pipe"; rm -f "$pipe") &

# send the text to the fifo (and eventually to dzen). oss reports 
# something like "15.5" on a scale from 0 to 25 so we strip the decimals 
# and send gdbar an optional "upper limit" argument
(echo ${level/.*/} 25 | gdbar "${gdbar_args[@]}"; sleep 1) >> "$pipe"

Pretty easy, and about as light-weight as you can get.

Status bar

Little known fact: you can use the ubiquitous conky to feed a simple statusbar via dzen. This means you can also use dzen escapes in your TEXT block to do cool things:

dzen screenshot 

My statusbar has the following “features”

  • Shows CPU/Mem/Network
  • The time, of course
  • Shows “Now playing” information from MPD
  • The music state (playing/paused) can be clicked to toggle it
  • The track title, when clicked, will advance

And here’s the conkyrc to achieve it:

background no
out_to_console yes
out_to_x no
override_utf8_locale yes
update_interval 1
total_run_times 0
mpd_port 6600

[ ^ca(1, mpc toggle)${mpd_status}^ca()

  ${if_mpd_playing}- ${mpd_elapsed}/${mpd_length}$endif ]

  ^fg(\#909090)^ca(1, mpc next)${mpd_title}^ca()^fg() by

  ^fg(\#909090)${mpd_artist}^fg() from


  Cpu: ^fg(\#909090)${cpu}%^fg()

  Mem: ^fg(\#909090)${memperc}%^fg()

  Net: ^fg(\#909090)${downspeedf eth0} / ${upspeedf eth0}^fg()

  ${time %a %b %d %H:%M}

Line breaks added for clarity.

The most interesting part is the clickable areas: ^ca( ... )some text^ca() defines an area of “some text” that can be clicked. The two arguments inside the first parens are are “which mouse button” and “what command to run”. Pretty simple and damn convenient.

Then all you’ve got to do is call this from your startup script:

$ conky -c ~/path/to/that | dzen2 -p -other -args

The -p option just means “persist” so the dzen will never close.


This was just two examples of some uses for a simple “pipe some text in and see it” GUI toolkit – there are plenty others.

This echoes one of the great things about open-source: something like this is so small, so simple, it could never have survived marketing meetings, planning sessions or cost-benefit analyses – but here it is, and I find it oh-so-very-useful.

29 Apr 2012, tagged with linux

Forks and Children

While writing a small learning exercise in C, I came across a nifty little concept. The task itself was a common one: I wanted to spawn a subprocess to the background while letting the main process continue to loop.

Many thanks go to falconindy who spoon fed me quite a bit as I was wrapping my head around all of this knowledge I’m now shamelessly presenting as my own.

In most languages you have some facility to group code into a logical unit (a haskell function or a bash subshell) then pass that unit to a command which forks it off into the background for you (haskell’s forkProcess or bash’s simple &).

Forking C

C takes a far different, but I’d say more elegant, approach. C provides a function, fork() which returns a pid_t.

The beauty of fork() is in its simplicity. All it does is create an exact copy of your program in its current state in memory. That’s it.

int main() {
    pid_t pid;

    pid = fork();

    // ...

Guess what, now you’ve got two copies of your running program, both sitting at the exact spot where pid is being assigned the output of fork().

In the copy that was the original (the parent), pid will be the process id of the other copy (the child). And in that child copy, pid will be assigned 0. That’s it; the full extent of fork().

So how do we use this?

Well, let’s say you’ve got a program (as I did) which should sit and loop forever. When some event happens, we want to take some asynchronous action (in my case throw up a dzen notification).

This is the perfect time to use fork(). We’ll let the main thread run continuously, and fork off a child to do its thing when the triggering event occurs.

Here’s a simplified version:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>

int main() {
    int ret;
    pid_t pid;

    while (1) {
       /* wait for the "event" */
       ret = some_blocking_process();

       if (ret) {
           /* fork it! */
           pid = fork();

           if (pid == 0) {
               /* we are the child, take action! */

           /* and the parent loops forever... */

So as you can see, the main program waits until some_blocking_process returns an int. If that int is nonzero, we consider that “the event” so we fork to create a copy of ourselves. If pid is zero, we know we are the child process so we take some_action and then simply exit. The parent process will skip that if statement, loop again and wait for some_blocking_process to signal the next event.

Zombie kids

So I may have lied to you slightly about the simplicity of this approach. The above is all well and good – it is simple – but I ran into a small snag while working with my little learner’s app…


Turns out, when a child process exits, it reports its return value to its parent; like any good child should. The child does this by sending a SIGCHLD signal.

The parent then knows if all or some of its spawned children finished successfully or not. This is important if you’ve got some dependant logic or simply want to log that fact.

In my case, I couldn’t care less. Succeed fail, whatever. I’m done with you kid – go away.

Double turns out, if the parent neglects to act on the signal sent from the dying child, it can remain a zombie.

I think this is poor form. I mean, come on, a negligent parent is no reason to make a process wander around aimlessly as a zombie until the next reboot.

Ok, ok, enough with the metaphor. Bottom line – all you need to do to prevent this is install a simple signal handler which will read (and ignore) the status of the child process in response to said signal.

Here’s our same example, but this time with a simple handler added:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>

static void sigchld_handler(int signum) {
    /* this just silences a compiler warning you might get since we 
     * discard the signum parameter that is passed in */
    (void) signum;

    /* the actual handling of the signal... */
    while (waitpid(-1, NULL, WNOHANG) > 0);

int main() {
    int ret;
    pid_t pid;

    struct sigaction sig_child;

    sig_child.sa_handler = &sigchld_handler;
    sig_child.sa_flags = 0;
    sigaction(SIGCHLD, &sig_child, NULL);

    while (1) {
       ret = some_blocking_process();

       if (ret) {
           pid = fork();

           if (pid == 0) {

That’s it, no more zombies.

I noticed in the source for dzen2 that they use a double-fork approach which also prevents zombies – with no need for signal handlers (yay KISS!):

if (fork() == 0) {
    if (fork() == 0) {
        // child logic...




// continue parent logic...

I like this approach better.

02 Jun 2011, tagged with linux


For me, any sort of general purpose note taking and/or keeping solution needs to meet only a few requirements:

  1. Noting something has to be quick and easy (in a terminal and scriptable)
  2. Notes should be available from anywhere… tothecloud!
  3. Notes should be searchable

Now, just to clarify – I’m not talking about classroom notes, those things go in note-books. I’m talking about short little blurbs of information I would like to keep and reference at a later time.

Though, I suppose this could work for classroom notes too…

I’m also not talking about reminders, those are the stuff of calendars, not note-keeping apps.

So what’s my solution? What else, Gmail!


Setting up gmail as a note keeper/searcher is simple. A note is an email from me with the prefix “Note -” in the subject line. Therefore, it’s easy to setup a label and a filter to funnel note-mails into a defined folder:

From:    me@whatever.com
Subject: ^Note - 

I also add “Skip inbox” and “Mark as read” as part of the rule.

I know the gmail filters support some level of regex and/or globbing, but I don’t know where it ends. I’m hoping that the ^ anchor is supported but I’m not positive.

Requirements 2 and 3 done.


So if taking a note is done by just sending an email of a particular consistent format, then it’s easy for me to achieve requirement 1 since I use that awesome terminal mail client mutt.

A short bash function gives us uber-simple note taking abilities by handling the boilerplate of a note-mail:

noteit() {
  _have mutt || return 1 # see my dotfiles re: _have

  local subject="$*" message

  [[ -z "$subject" ]] && { echo 'no subject.'; return 1; }

  echo -e "^D to save, ^C to cancel\nNote:\n"


  [[ -z "$message" ]] && { echo 'no message.'; return 1; }

  # send message
  echo "$message" | mutt -s "Note - $subject" -- pbrisbin@gmail.com

  echo -e "\nnoted.\n"

You could probably also streamline note taking by leveraging mutt’s -H option. I’ll leave reading that man page snippet as an exercise to the reader.

And here’s how that might work out in the day-to-day:

//blue/0/~/ noteit test note
^D to save, ^C to cancel

This is a test note.

< I pressed ^D here >


You could also use sendmail, mailx, msmtp or whatever other CLI mail solution you want for this.

And there it is, ready to be indexed by the almighty google:

Mutt notes shot 

With a few mutt macros, I think this could get pretty featureful without a lot of code.

Let me know in the comments if there are any other simple or out-of-the-box note-keeping solutions you know of.

Oh, and before anyone mentions it – no, you can’t take notes without internet when you’re using this approach. I’m ok with that, I understand if you’re not.

26 Mar 2011, tagged with linux

Android Receiver

Android notifier is a great little app I just recently found on the marketplace. What it does is use your wifi network or a bluetooth connection to send out a broadcast when certain events happen on your phone.

The idea is to have a companion application running on your computer to listen for the event and pass along the message via some notification system: Growl on Windows/Mac and (I think) gnome-dbus on Linux.

This means your phone can be charging in the other room while you’re at your computer and you’ll get a nice notification on your desktop when someone’s calling you or you get a text.

This is great and all but totally not worth the Gnome or bluetooth library dependencies to get going on Linux. After a brief look at the project’s wiki however I knew I could do something simpler.

I was able to put together two scripts I had already in place to achieve a dead-simple android-receiver on my desktop. The first was a script call ncom which used netcat to send commands across a network and execute them on another machine. The second, bashnotify, was something I was playing around with to get pop-up notifications on track changes in mpd.


From the project wiki, I found out that the application will send a broadcast packet on port 10600 in a specific format. After some playing around with test messages I was able to put together the following which successfully echod back the message text in a terminal.

while read -d $'\0'; do
  echo $REPLY
done < <(netcat -z -u -l -p 10600 localhost)

The incoming message doesn’t end with a newline but rather a null character. That’s why using read -d $'\0' and netcats -z option is required. I also found out that I wasn’t getting anything from TCP even though the android app should be broadcasting with both protocols. Using UDP via the -u option seems stable so far.


I took the dzen code present in bashnotify and tweaked it a little bit so that the notification temporarily covers my entire status bar and shows the message text:

handle_dzen() {
  local message="$*"

  # dzen settings
  local pipe='/tmp/android-receiver.fifo'
  local delay=4
  local x_offset=0
  local y_offset=0
  local height=17
  local font='Verdana-8'
  local foreground='#ffffba'
  local background='#303030'

  if [[ ! -e "$pipe" ]]; then
    mkfifo "$pipe"
    (dzen2 -ta l -h $height -x $x_offset -y $y_offset \
        -fn "$font" -bg $background -fg $foreground < "$pipe"; rm -f "$pipe") &

  # todo: make this prettier
  (echo "$message"; sleep $delay) >> "$pipe"

And there you go.

The end product is no longer moving my charger away from its normal spot because I’m expecting a call. Instead, I’ll see this:

Android Receiver Screenshot 

The source for this script can be found in my github.

In my continued attempts to learn some C, I decided to combine the netcat and message parsing functions of the above into a small C app.

The end result is a nice little program that you can find here. It handles binding to the port, parsing and formatting the message, then handing it off as the first argument to a handler script which is in charge of actually displaying the notification to the user.

To match this functionality, I’ve culled the original script down to only the handle_dzen() function and renamed it to dzen-handler such that it can be used by any application that wants to toss up a brief notification. This script is also available in that android-receiver repo.

11 Dec 2010, tagged with android, linux

Web Preview

Recently, I made the switch (again) away from Uzbl as my main browser. Jumanji is a really nice browser in that it’s as light as Uzbl but feels more polished. It provides almost all of the features I had to build into Uzbl myself right out of the box. The tab-completion on the commands and urls is incredibly useful and negates the need for all the external history and bookmark scripts that I was using with Uzbl. The only part I really miss is (obviously) the controllability and configurability.

I only ever used this controllability for one thing: previewing web pages as I write them. I had a nice little script that would go out and ask each Uzbl instance what its URI was, and if it matched the URI version of the filename I was currently editing it would send the reload command to this browser.

You just cannot do something like this in any other browser.

So I figured, if I relegate Uzbl to this one single simple use, it’s configurability could be leveraged such that I could strip out anything that didn’t serve this one purpose and the browser would be incredibly responsive.

In the end, I’m actually amazed at how well this worked out. During my testing, I actually spent a good ten minutes troubleshooting a nonexistent bug because the page was reloading so fast that I thought nothing was happening.

This works nicely for me because my desktop is my web server. All I have to do is vim /srv/http/pages/foo.html and I’m editing http://localhost/pages/foo.html directly.

I’m not saying it’s impossible to pull this off with a remote server, this just makes things easier. It’s up to you to port my script for use in a remote server setting.

First thing you’ll need is my script, download the raw version into your $PATH.

Adjust the in-script variables srv_dir and srv_url to match your environment. These variables are used to turn a filename like /srv/http/pages/foo.html into a url like http://localhost/pages/foo.html.

Recently the script has changed slightly to work with my new framework; I now just define file_url as a direct modification of $2.

Make sure you’ve got uzbl installed and uzbl-core is also in your $PATH.

Add the following uber simplistic configuration file for uzbl at ~/.config/uzbl/config:

set socket_dir         = /tmp
set status_background  = #303030
set uri_section        = \@[\@uri]\@
set status_format      = <span font_family="Verdana" foreground="#909090">@uri_section</span>
set title_format_short = Uzbl - \@TITLE
set title_format_long  = @title_format_short

This just makes sure a socket is placed in /tmp and makes the status bar a little more pleasing on the eyes.

Only the socket_dir declaration is actually needed for the script to function.

Finally, add the following to your ~/.vimrc:

command! Open :! webpreview --open %
command! Reload :! webpreview --reload %

au BufWritePost /srv/http/pages/* silent Reload

This defines an Open and Reload command to be used directly within vim and also sets up an auto command to fire whenever I hit :w on a page I’m editing.

In your ~/.vimrc you could make these conditional for html and php filetypes and, as you can see, the auto-refresh only happens if I’m editing a file under my server’s pages directory. You’ll want to do something similar so that the script doesn’t run for all files all the time.

That’s all that’s needed. Fire up your favorite text editor and give it a try.

26 Jul 2010, tagged with linux


I’ve recently finished work on an HTPC. The goal was to run a media center WM on a box that looked appropriate in my cabinet by my TV using a remote. That much I’ve done; all that’s left is tweaking the remote functions and adding to the collection.


The first thing I got was the case; I wanted one with a built in remote and a low enough profile to fit in my TV cabinet and not look out of place.

Enter Lian Li’s PC-C39. Let me say, it’s a great case. It’s small, quiet, and looks great. One problem, the remote is garbage.

It doesn’t work more than 2 feet away from the sensor. The remote is RF (another flaw IMO) and the sensor is actually over-shielded by the case itself. Solution? Slide open the top of the case (even just an inch), your range will increase tenfold. I did this for a while but wanted something better – more on that later; anyone reading this should buy the PC-C37B which is the same case but sans the trash remote (and $50 bucks).

Next, I stopped in at MicroCenter to pick up the internal components. I knew I wanted to spend five to six hundred bucks and get a decently powered machine; one that could keep up with whatever HD content I wanted to run without getting too hot.

Here’s what I ended up with:

  • Intel DP55WB mATX 129.99
  • ASUS GF210 47.99
  • Intel Core i5 650 139.99
  • OCZ 4GB DDR3 1600 CL8 119.99
  • OCZ 600W Stealth 69.99
  • WD 1TB SATA 99.99
  • LG 22x Burner 29.99
  • Total 639.93

After the usual mail-in-rebates, It’ll be just over $550. You could definitely achieve a great system for less, but I wanted something more high-end (and I had just gotten my tax return), so I probably spent a little more than I had to.

So now that I’ve got a fully functioning box, it’s time to fix my remote situation.

Enter Logitech’s Harmony 300. I originally bought this thinking it was primarily a PC Media Center remote and would come with its own USB IR receiver. It did not. I was pissed.

In the end, I’m really glad I made that mistake because the remote’s awesome. You configure it by plugging it into a computer and using an in-browser control panel (luckily it’s mac+firefox compatible), just add devices by Manufacturer number, and that’s it.

To get it working with the computer was a bit more involved, but not much.

First, I had to get my own USB IR Receiver. Luckily, amazon had a Dell RC6 receiver for like $18 bucks, sold. Then it was just a matter of adding its MFR# to the harmony setup and starting lirc.

If you’re on Arch, it’s like this:

pacman -S lirc
cp /usr/share/lirc/remotes/mceusb/lircd.conf.mceusb /etc/lirc/lircd.conf
/etc/rc.d/lircd start

You can test it by typing irw and pressing some buttons.

You’ll want to add lirc_mceusb2 to MODULES and lircd to DAEMONS in /etc/rc.conf.

If you find on reboot that your remote’s not working, check if /dev/lirc0 exists (it needs to); if this happens, try a different USB port, that solved it for me

Now I’ve got just one remote that runs my whole living room. The girlfriend was pleased. There was much rejoicing.


I went with XBMC. Once installed, I set up an autologin by editing /etc/inittab (assuming xbmc is your default username):

## Only one of the following two lines can be uncommented!
# Boot to console
# Boot to X11

# snip...

x:5:respawn:/bin/su xbmc -l -c "/bin/bash --login -c startx >/dev/null 2>&1"

And then adding the following to that user’s ~/.xinitrc:

exec /usr/bin/ck-launch-session /usr/bin/dbus-launch --exit-with-session /usr/bin/xbmc --standalone -fs

Most of the above is out of date now. I defer to the Arch wiki for details on setting up XBMC.

I share my media from the main desktop PC using samba, so I just added the shares in XBMC.

Once added, XBMC scans your sources using some filename regexps that caught pretty much everything I threw at it. It downloaded plot summaries and fanart for all my movies and TV shows, and it of course uses your music collection’s tags (which I’m a bit OCD about anyway).

The result is an instantly full and beautiful library. Here are some screenshots:

HTPC Shot  HTPC Shot  HTPC Shot  HTPC Shot 

Remote configuration

XBMC found and used a hotplugged keyboard, the case’s built-in RF remote, and my lirc controlled mceusb remote all without issue right out of the box using default button mappings. I was impressed.

If you’d like to customize your remote behavior, there are two files involved: ~/.xbmc/userdata/Lircmap.xml and ~/.xbmc/userdata/keymaps/remote.xml. Defaults can be found in /opt/xbmc/system on an Arch install; just copy them and start editing.

Lircmap.xml will translate the device/button (as reported by irw) to an XBMC button string. Through this file, you can make it so that ... OK mceusb will register as “select”. Then, in remote.xml you can actually map select to an XBMC action, like “Select”.

It’s all explained here and here.

The last little issue I noticed was that after playing a DVD, I couldn’t eject. This was fixed by adding the following line to the file /etc/sysctrl.conf:

sys.dev.cdrom.lock = 0

A reboot is required for the change to take effect.

With the update to the 2.6.34 kernel, alsa now has support for audio over hdmi with my chipset (Asus/Nvidia GF210).

It wasn’t exactly trivial to get it working though. Basically it took some trial and error to figure out that the audio out I needed was card 1 device 7, so plughw:1,7.

Sadly, specifying this plughw as a custom output device in XBMC’s audio setup meant no dmix, which meant no crossfading (two sounds at once).

Thanks to Themaister on the arch forums though, I actually got around this quite quickly.

Save the following as /etc/asound.conf:

pcm.dmixer {
  type dmix
  ipc_key 2048
  slave {
    pcm "hw:1,7"
    period_size 512
    buffer_size 4096
    rate 48000
    format S16_LE
  bindings {
    0 0
    1 1

pcm.!default {
  type plug
  slave.pcm dmixer

pcm:iec958 {
  type plug
  slave.pcm dmixer


In the XBMC audio setup, specify default as the output device and iec958 as the passthrough device.

That’s it!

01 May 2010, tagged with linux

Controlling MPlayer


MPlayer is an extremely versatile media player, I’ve begun to use it for absolutely any media that I’m not already piping through mpd. One day while going through my XMonad config, I decided it’d be convenient to bind my media keys to control MPlayer. I already had them bound to control volume/mpd, but I figured Meta + key combinations could be the MPlayer equivalents.

A bit of googling later and I had the solution: a fifo!


Fifos (for file in file out) are two way files on your system that can be used for communication; kind of a poor man’s socket. You can play with them like this to get the idea:

# in one terminal:
mkfifo ./fifo
tail -f ./fifo

# and in some other terminal:
echo some text > ./fifo

MPlayer setup

The MPlayer manpage states that it can read commands out of a fifo by using the input flag. Combine that with the fact that MPlayer will read any flags from ~/.mplayer/config and we’re 90% there.

mkfifo ~/.mplayer_fifo
vim ~/.mplayer/config

Add the following in that file:

input = file=/home/username/.mplayer_fifo

Now fire up a movie. Go to some other terminal and do the following:

echo pause > ~/.mplayer_fifo

If MPlayer didn’t pause, double check the above. It works for me.


Now it’s really up to you if you want to run these via a wrapper script, or send the commands directly from your keybind configuration. Here’s an example wrapper script if you decide to go this way:



echo $command > "$fifo" &>/dev/null

Place it in your $PATH, chmod +x it, and bind some keys to script 'play', script 'pause', etc.

Personally, I put a simple function (of basically the above) in my xmonad.hs, then call that from the keybinds. Here’s the relevant section of my config:

myKeys = [ ...

         -- Mod+ to control MPlayer
         , ("M-<XF86AudioPlay>", mPlay "pause"   ) -- play/pause mplayer
         , ("M-<XF86AudioStop>", mPlay "stop"    ) -- stop mplayer
         , ("M-<XF86AudioPrev>", mPlay "seek -10") -- seek back 10 seconds
         , ("M-<XF86AudioNext>", mPlay "seek 10" ) -- seek forward 10 seconds

         , ...


           mPlay s = spawn $ "echo " ++ s ++ " > $HOME/.mplayer_fifo"

I’m using EZConfig notation in my keybindings.

I’ll leave it up to you to figure out your WM’s keybind configuration or use some generic tool like xbindkeys.

08 Apr 2010, tagged with linux


Irssi is an IRC client. If that sentence made no sense, then read no further. This post outlines my current irssi setup as I think it’s quite nice and others may wish to copy it.

Note: I’ve since moved to weechat. If anyone’s interested, that config can be found here.


Irssi Screenshot 


For the longest time I didn’t really touch ~/.irssi/config except to set up auto connections etc. Then I started using awl.pl (which I’ll describe in the scripts section). This meant I no longer had a use for one of the statusbars. So for the sake of completeness, here is the change I made to get the statusbar look you see in the screenshot:

statusbar = {

    # <snip>

    default = {
      window = {

        # disable the default bar containing window list
        disabled = "yes";

        # window, root
        type = "window";
        # top, bottom
        placement = "bottom";
        # number
        position = "0";
        # active, inactive, always
        visible = "active";

        # list of items in statusbar in the display order
        items = {
          barstart = { priority = "100"; };
          time = { };
          user = { };
          window = { };
          window_empty = { };
          lag = { priority = "-1"; };
          more = { priority = "-1"; alignment = "right"; };
          barend = { priority = "100"; alignment = "right"; };
          active = { };
          act = { };

      # <snip>

      prompt = {
        type = "root";
        placement = "bottom";
        # we want to be at the bottom always
        position = "100";
        visible = "always";
        items = {
          barstart = { priority = "100"; };
          time = { };

          user = { }; # added my current nick here b/c it was the only useful
                      # item in the disabled bar

          prompt = { priority = "-1"; };
          prompt_empty = { priority = "-1"; };
          # treated specially, this is the real input line.
          input = { priority = "10"; };


      # <snip>


My full config (sans passwords) can be downloaded here.


The theme I currently use was originally generane.theme; I’ve gradually hacked away at it until, at this point, it’s entirely unlike that theme. I just call it pbrisbin.theme and it can be found with the above dotfiles. It’s a really grey theme to go with my overall desktop. Messages from me are a bright-ish grey, with messages to me as bright yellow. Actions (/me stuff) are magenta and offset to the left which I really like.


Bitlbee is a killer app. It sets up a small-footprint IRC server on your local machine, hooks into your various chat protocols (gchat, aim, facebook, twitter), and let’s you /join or /query them as if they were any other #channel.

This is great for someone like me who’s gotten used to /exec -o foo and other tricks that aren’t possible in a normal chat client.

There are a lot of guides online for setting this up so I’m just going to list out a few facts that it took me a minute to figure out or get used to:

  • In the &bitlbee channel, any text not prefixed with a buddy’s nick is interpreted as a command to bitlebee itself.

  • If you decide to chat with buddies by sending nick-prefixed messages within the main &bitlbee channel, it’s not a chatroom and they can’t see things you send to other nicks.

  • Whether you decide to talk to a buddy via a nick-prefixed message or a query, bitlbee remembers this and any future conversations initiated by them will come in the same way by default.


And the best part, the scripts. All of these can be easily googled for so I won’t provide links; the versions on my box could even be out of date anyway.

cap_sasl.pl - in an effort to streamline my dotfiles management, I was looking for ways to get plaintext passwords out of dotfiles. One such way is to use SASL for authentication to freenode. After getting the script, setup can be done via in-irssi commands as many existing how-tos outline. I got gummed up however because I fudged up the server name (freenode vs Freenode) when setting up sasl compared to when I had initially setup the connection…

This is why I prefer to do direct, in-file configuration. So, here are the portions of .irssi/config to support this:

servers = (
    address = "irc.freenode.net";
    chatnet = "freenode";
    port = "6697";
    use_ssl = "yes";
    ssl_verify = "yes";
    ssl_capath = "/etc/ssl/certs/";
    autoconnect = "yes";


And place a file as ~/.irssi/sasl.auth with the following contents:

freenode	<primary nick>	<password>	DH-BLOWFISH

It’s important that you use your primary nick or it won’t work. For instance, I always talk as brisbin but that’s just a secondary nick associated with my primary brisbin33, so I had to use brisbin33 in the sasl setup.

nm.pl - this handles random/unique nick coloring and nick alignment. Personally, I /set neat_maxlength 13.

awl.pl - the advanced window list (sometimes called adv_windowlist.pl). This gives that nice statusbar with the channel names and numbers. Channels turn bright white when active and magenta if I’m highlighted. Personally, I use /set awl_display_key "%w$N.$H$C$S" and awl_maxlines 1.

trackbar.pl - this puts a dashed mark in the buffer at the last point you viewed the conversation. I really like this script, it’s simple but affective. If you hop around between windows this is a great little addition to your .irssi/scripts/autorun.

screen_away.pl - thank you rson for turning me onto this. Once I started using irssi exclusively in screen (as outlined here) this script really started coming in handy. It just auto-sets you as away when you detach your screen session and brings you back when you reattach. This means Ctrl-a d logs me off, and when I do reattach I’ve got all my messages waiting for me right there in window 1.

queryresume.pl - now that I’m using bitlbee as my main IM client, I’m spending a lot of time in queries. This script gives you a little bit of context by printing the last few lines of your most recent query with this person that you’ve just started a new query with.

hilightwin.pl - this script captures any text that matches your /hilight rules, whether it’s nick or keyword-based. Anything you’ve set up as a hilight will be captured in a dedicated window. Couple this with a smart layout where your hilightwin is dedicated to the top 8 lines of your client, and you can always see who’s talking at you, no matter what you’re doing. Any google search for this script will not only give you the source, but also the commands required to setup the smart layout to go along with it.

link_titles.pl - this is a script that I recently wrote as a learning exercise in perl. It watches the conversation for urls. When it finds one, it visits that page and prints the title element back to the window where the link was sent. Most actual channels I’m in will have a bot that does this, but I wanted to print titles for links sent to me in a query via gchat or aim. The source for this is on my github, hopefully more scripts will show up there soon.

20 Mar 2010, tagged with linux


It seems as users (myself inclusive) progress through the stages of using a distribution like Arch linux, they reach certain stages. Like when you realize how amazing find -exec is. Or crossing over from god, vim is a pain in the ass! to jesus, why doesn’t everyone use this?

I find one well-known stage is how can I automount my USB drives? This usually comes early on as a new Arch user ditches GNOME or KDE in favor of something lighter, something more minimalistic, something they can actually be proud to show off in the screenshot thread. Well, ditch the DE and you lose all those nifty little automagical tools, like gnome-volume-manager and the like.

So what do you do? hal should take care of it. Some ck-launch-session black magic might do the trick. Edit some *.fdi file to get it going?

No. Udev does just fine.


Udev has a little folder called /etc/udev/rules.d. In this folder, are ‘rules files’ each named 10-some-crap.rules. They are processed one by one each time some udev ‘event’ occurs, like, say, plugging in a flashdrive.

Go google udev rules, there’s a lot out there for all sorts of nifty things.

Someone smarter than I added a handful of useful rules to the Arch udev wiki page. The one I use is as follows:

# adjust this line to skip any persistent drives
# i.e. KERNEL!="sd[d-z][0-9]", ...
KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"

# Global mount options
ACTION=="add", ENV{mount_options}="relatime,users"

# Filesystem specific options
ACTION=="add", PROGRAM=="/lib/initcpio/udev/vol_id -t %N", RESULT=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002"
ACTION=="add", PROGRAM=="/lib/initcpio/udev/vol_id --label %N", ENV{dir_name}="%c"
ACTION=="add", PROGRAM!="/lib/initcpio/udev/vol_id --label %N", ENV{dir_name}="usbhd-%k"
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}"
ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"

This file defines how udev reacts to usb drives (/dev/sda1, etc) being added and removed. You plug in a flashdrive, if it has a label, it’s mounted at /media/<label>; if not, it’s mounted at /media/usbhd_sda1 (for example). umount and remove the drive, and that directory under /media is removed. It’s a beautiful thing.


One problem I found with this is that it works really well. When a device is added it is mounted, period. So whenever I tried to partition a drive, as soon as the partition was initialized it would get mounted, and the partitioning tool would fail with drive is mounted.

For this reason, I had to write a script. I always have to write a script.

What this does is simply write the above rules file or remove it. This effectively turns automounting on or off. So there you go, simple handling of usb flash drive with nothing but udev required.

DVDs and CDs

Just a bit about optical media. The above won’t solve any issues related to that. I’ll just say this though, if I need to do anything related to CDs or DVDs, I can just reference /dev/sr0 directly. Burning images, playing DVDs, it all works just fine using /dev directly. And when I need to mount it, I’ll do it manually. I think a line in fstab will get /dev/sr0 to mount to /media/dvd if that’s what your after.

12 Jan 2010, tagged with linux


This post is very out of date. The scripts which are its subject no longer exist as I now use two much simpler scripts which can be found in my scripts repo.

Backups are extremely important. In linux, with a little effort and hardrive space, one can easily come up with a fully automated backup solution to suit any needs. Here, I’d like to outline my setup. Feel free to take it and adapt to your needs.

I’ll go through what’s required, how and why I do it the way I do, as well as the shortcomings of how I’m doing it.


My main box runs on one 500G hardrive. So far, this has suited me well even with my extensive movies and music collection. I decided I wanted to have a daily backup and a monthly backup and only one copy of each, so I went out and got a 1TB hardrive, split it, and now use that for both.

All you need is space, so whether you use an internal drive like me, an external USB, or some off-site scp/rsync situation is up to you; you’ll just have to modify my below script(s) to suit your setup.

How I do it

The first is a backup script that runs via cron daily and monthly. It can be downloaded from my git repo.

The script defines an array of files to include and another to exclude:

includes=( /srv/http /home/patrick /etc /usr /var /boot )
excludes=( Downloads lost+found )

It takes those directories and just rsyncs them with the backup location:

|-- boot
|-- etc
|-- http
|-- patrick
|-- usr
`-- var

|-- boot
|-- etc
|-- http
|-- patrick
|-- usr
`-- var

It also creates two text files: one that lists all your installed packages less those that are foreign (from the AUR) and another that lists those foreign packages.

These lists can be used to quickly reinstall everything you had installed at the time of the backup.

pacman -Qqe | grep -Fvx "$(pacman -Qqm)" > "$backup_dir/paclog"
pacman -Qqm > "$backup_dir/aurlog"

Another script I use constantly is retrieve which will take the filenames passed on the commandline and look for them in your backups. If found, the files are retrieved and re-inserted into you live system.

This is great if you’ve seriously screwed up your xorg.conf (something not in git) and you want to just roll back to what you had yesterday.

The only trick to it is that it has to handle the fact that my backup stores patrick/ at top level even though it’s /home/patrick/ on the live system.

retrieve is also no longer available in my git repo.

The last script that I have, I haven’t had to use –knocks on wood–. This restore script is intended to be used after a crash and clean re install to restore your system back from the directories made by my backup script.

You guessed it, restore is also no longer in the repo.

Why mine sucks

This solution works for me, but it has its shortcomings. Here are a few things to be aware of if you decided to implement something like what I have.

Not off-site, or even out-of-box.

If my apartment burns down, my backups are useless. To mitigate this, I’ve started taking manual copies of my monthly backup and storing them on a separate drive in a fireproof box.

Backups are not rolling

This isn’t so bad for the dailies, but my monthly backup occurs every month on the first; this means if you have an issue that’s more then two days old, and you happen to notice on the 2nd, you don’t have a backup old enough to fix it.


I’ve never had to use restore, though I do use retrieve all the time. Anyone will tell you, an untested backup solution is no solution at all. Guess I’m just too lazy to hose my install to test it. Worse comes to worst, I know the backed up data is good; if my restore script fails I can always manually copy everything over. I pretty much did this last time I installed a new Arch box; as I tend to reuse configs, just grabbing them off of my main box’s backups really sped up the process.

03 Jan 2010, tagged with linux

Wifi Pipe

So the other day when I was using wifi-select (awesome tool) to connect to a friends hot-spot, I realized, “hey! This would be great as an openbox pipe menu!”

I’m fairly decent in bash and I knew both netcfg and wifi-select were in bash so why not rewrite it that way?


A simplified version of wifi-select which will scan for networks and populate an openbox right-click menu item with available networks. Displays security type and signal strength. Click on a network to connect via netcfg the same way wifi-select does it.

Zenity is used to ask for a password and notify of a bad connection. One can optionally remove the netcfg profile if the connection fails.


  • netcfg
  • zenity
  • A NOPASSWD entry in sudoers for this script
  • An entry in your menu.xml

The script now has its own github repo so it doesn’t fall victim to bitrot. Please head there for more installation details and a copy of the source.

05 Dec 2009, tagged with linux

Using Two IMAP Accounts in Mutt

Mutt can be really great with multiple accounts, but it’s not exactly intuitive to setup. Here I’ll document how I access two Gmail accounts together in one mutt instance.

If you haven’t yet seen my previous mutt post, please go read that now. I recommend using that post to get a single account setup first before coming back here. Even if you plan to jump right into a multi-account setup, this post assumes you’ve at least read the other one and will focus on the differences and required changes to get from there to here.


To get Offlineimap syncing multiple accounts, we simply need to add additional configuration blocks to sync the second account with another local Maildir.


ui = ttyui
accounts = Personal,Work

[Account Personal]
localrepository = Personal-Local
remoterepository = Personal-Remote

[Account Work]
localrepository = Work-Local
remoterepository = Work-Remote

[Repository Personal-Local]
type = Maildir
localfolders = ~/Mail/Personal

[Repository Work-Local]
type = Maildir
localfolders = ~/Mail/Work

[Repository Personal-Remote]
type = Gmail
remoteuser = username@gmail.com
remotepass = secret
realdelete = no
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

[Repository Work-Remote]
type = Gmail
remoteuser = work-username@gmail.com
remotepass = secret
realdelete = no
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

Obviously, if either of these accounts weren’t a Gmail server, the configuration blocks would be different.

You can test your setup by running offlineimap -o to sync things once. It could take a while, but once done, you should have a nice folder structure like this:

|-- Personal
|   |-- INBOX
|   `-- ...
`-- Work
    |-- INBOX
    `-- ...


Msmtp also handles multiple accounts very elegantly, we just add another account block for the second account.


# shared defaults since both are gmail accounts
host smtp.gmail.com
port 587
protocol smtp
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt

account personal
from username@gmail.com
user username@gmail.com
password secret

account work
from work-username@gmail.com
user work-username@gmail.com
password secret

account default : personal

Now we can simply call msmtp -a personal or msmtp -a work to use whichever account we want. Omitting the -a option will use the default account which we’ve set as personal.


The goal with mutt is to have certain settings change when we enter certain folders. For example, when we’re viewing +Personal/INBOX we want our from setting to be our personal From address and the sendmail setting should be msmtp -a personal. To provide this functionality, we’re going to do the following:

  1. Place any account-specific settings in separate files
  2. Use mutt’s folder-hook facility to source the proper file and set the proper settings upon entering a folder for a given account.

Here are the two account-specific files:


set from      = "username@gmail.com"
set sendmail  = "/usr/bin/msmtp -a personal"
set mbox      = "+Personal/archive"
set postponed = "+Personal/drafts"

color status green default

macro index D \
    "<save-message>+Personal/Trash<enter>" \
    "move message to the trash"

macro index S \
    "<save-message>+Personal/Spam<enter>"  \
        "mark message as spam"


set from      = "work-username@gmail.com"
set sendmail  = "/usr/bin/msmtp -a work"
set mbox      = "+Work/archive"
set postponed = "+Work/drafts"

color status cyan default

macro index D \
    "<save-message>+Work/Trash<enter>" \
    "move message to the trash"

macro index S \
    "<save-message>+Work/Spam<enter>"  \
        "mark message as spam"

Notice the color line which changes the status bar depending on what account I’m “in” at any given moment.

The following settings will tell mutt to source one of these files upon entering a folder matching the given pattern, this will setup all the correct settings when entering a folder for a given account:


set spoolfile = "+Personal/INBOX"

source ~/.mutt/personal

folder-hook Personal/* source ~/.mutt/accounts/personal
folder-hook Work/*     source ~/.mutt/accounts/work

The first two lines effectively set Personal as the default account when we open mutt.

Well, that should do it. Open up mutt, change folders, send some mails, and make sure everything’s working as you’d expect.

For reference, my complete and current setup can be found with my dotfiles.

05 Dec 2009, tagged with linux, mutt

Text From CLI

This is a short but extensible script to allow text messaging (to verizon customers) straight from the commandline.

Setup requires simply a means to send email from the commandline along with a small script to pass the message off to <number>@vtext.com.

If you already have a CLI mailing solution you can just copy the script and go ahead and change the mail command to mutt, ssmtp, mailx, or whatever you’re using.

Email from CLI

I use msmtp to send mails in mutt so it was easy for me to adapt that into a CLI mailing solution.

Here’s a ~/.msmtprc for gmail:

# msmtp config file

# gmail
account gmail
host smtp.gmail.com
port 587
protocol smtp
auth on
from username@gmail.com
user username@gmail.com
password gmail_password
tls on

account default : gmail

Right now, as-is, it’s possible for you to echo "Some text" | msmtp someone@somewhere.com and it’ll email just fine. I’d like to make things a little more flexible.

By dropping a file in ~/.mailrc we can change the mail command to use whatever binary we want instead of the default /usr/bin/sendmail. It should have the following contents:

set sendmail=/usr/bin/msmtp

Now, anytime your system mails anything on your behalf, it’ll use msmtp.

The Script

The script started out very simply, here it is in its original form:


if [[ $# -lt 2 ]]; then
  echo "usage: $0 [number] [some message]"
  exit 1

number="$1"; shift

echo "$*" | mail "$number@vtext.com"

With this little sendtext.sh script in your back pocket, you can send yourself texts from remind, cron, rtorrent, or any other script to notify you (or other people) of whatever you want.

sendtext.sh 1234567890 'This is a test text, did it work?'

Sure did.

Now, at some point, Ghost1227 got bored again.

He took my sendtext script and ran with it. Added loads of carriers and some new option handling.

I took his update of my script and re-updated it myself. Mainly syntactical changes and minor options handling, just to tailor it to my needs.

The new version with my and ghost’s changes can be downloaded from my git repo.

I also added simple phone book support. When sending a message to someone, pass -s <number> <name> and the contact will be saved to a text file. After that, you can just sendtext <name> and the most recent match out of this text file will be used. The service is saved as well (either the default or the one passed as an argument at the time of -s).

05 Dec 2009, tagged with linux

Screen Tricks

Hopefully, if you’re a CLI junky, you’ve heard of GNU/screen. And if you’ve heard of it, chances are you’re using it.

Screen is a terminal multiplexer. This means that you can start screen in one terminal (say, your SSH connection) and open any number of terminals inside that terminal. This lets me have mutt, ncmpcpp, and a couple of spare shells all open inside my single PuTTY window at work.

This is a great use of screen, but the benefits don’t have to end there. When I’m not at work but at home, I can use screen to run applications which I don’t want to end if I want to change terminals, log in and out, or even if all of X comes crashing down around me.

See, screen can detach (default binding: C-a d). Better still, It will auto-detach if the terminal it’s in crashes or you logout. You can then re-attach it later, from any other ssh session, tty, or X terminal.

This is great for apps like rtorrent and irssi, it’s also great for not losing any work if your ssh connection gets flaky. Just re-connect and re-attach.

So now I have a dilemma. When I’m at work, I want to start screen and get a few fresh tabs set up as I’ve defined in ~/.screenrc: mutt, ncmpcpp, and three shells. But at home I don’t want those things to load, I instead want only rtorrent or only irssi to load up in the new screen window.

Furthermore, if rtorrent or irssi are already running in some detached screen somewhere, I don’t want to create an entirely new session, I’d rather grab that one and re-attach it here.

The goal was to achieve this without changing the commands I run day to day, affecting any current keybinds, or using any overly complicated scripts.

So, how do I do this as simply and easily as possible? Environment variables.

How to do it

First we set up one main ~/.screenrc which is always called. Then we set up a series of “screenrc extensions” which only load the apps in the screen session via a stanza of screen -t <name> <command> lines.

Next, we dynamically choose which “screenrc extension” to source from the main ~/.screenrc via two environment variables which are either exported from ~/.bashrc (the default) or explicitly set when running the command (the specialized cases).

So, set up a ~/.screenrc like this:

# screen config file; ~/.screenrc

# put all our main screen settings like
# term, shell, vbell, hardstatus whatever
# then add this:

# sources environment-specific apps

# you can even add some tabs you'll always
# open no matter what

# then always open some terms
screen -t bash $SHELL
screen -t bash $SHELL
screen -t bash $SHELL

Now, how does screen know what “screenrc extension” to source? By setting those variables up in ~/.bashrc:

# dynamically choose which tabs load in screen
export SCREEN_CONF_DIR="$HOME/.screen/configs"
export SCREEN_CONF="main"

In a clean environment, screen will source that default ~/.screen/configs/main, which will:

# example: screen -t [name] [command]
screen -t mail mutt
screen -t music ncmpcpp

Why is this useful? Because, now I can do something like this:

SCREEN_CONF=rtorrent screen

And screen will instead source that explicitly set ~/.screen/configs/rtorrent which yields:

# example: screen -t [name] [command]
screen -t torrents rtorrent 

Et viola, no mutt or ncmpcpp, but rtorrent instead (same thing happens with irssi).

Oh, but it gets better! Now we’ll add some aliases to ~/.bashrc to complete the whole thing:

alias irssi='SCREEN_CONF=irssi screen -S irssi -D -R irssi'
alias rtorrent='SCREEN_CONF=rtorrent screen -S rtorrent -D -R rtorrent'

Oh how beautiful, how simple, how easy. I type rtorrent, what happens?

Screen checks for any running screens with session-name “rtorrent” and re-attaches here and now. If none are found, screen opens a new screen (using the rtorrent file) and names the session “rtorrent” so we can -D -R it explicitly thereafter.

All of this happens for irssi too, and can be used for any app (or multi-app setup) you want.

Pretty KISS if I do say so.

05 Dec 2009, tagged with linux

Mutt + Gmail + Offlineimap

Most people use Gmail. Some people like CLI mail clients. This post describes how I use Gmail in the best CLI mail client, mutt. Many people will back me up when I say it’s a very good setup.

For reference, my complete and current setup can be found with my dotfiles.


Step one is to setup Offlineimap to keep ~/Mail in sync with Gmail. This is a two way sync so anything moved, deleted, or sent from any IMAP-connected device or our local mutt interface will act exactly the same. This also has the benefit of storing offline, local copies of all your mails.

First, install Offlineimap and fill in an ~/.offlineimaprc like so:

ui = ttyui
accounts = Gmail

[Account Gmail]
localrepository = Gmail-Local
remoterepository = Gmail-Remote

[Repository Gmail-Local]
type = Maildir
localfolders = ~/Mail/Gmail

[Repository Gmail-Remote]
type = Gmail
remoteuser = you@gmail.com
remotepass = secret
realdelete = no
maxconnections = 3
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

Test that this works by running offlineimap -o. Your first sync could take some time, but once done, you should see the folders under ~/Mail/Gmail with the proper structure.

Once you’re satisfied syncing is working, we’ll schedule a periodic sync via cron.

There are some tempting options offlineimap has for daemonizing itself to handle periodic syncing for you – in my experience these don’t work. Scheduling a full offlineimap run via cron is the only working setup I’ve been able to find.

To work around a thread-joining bug, I’ve landed on a wrapper script that spawns offlineimap to the background then babysits the process for up to 60 seconds. If it appears to be hung, it’s killed.

#!/usr/bin/env bash

# Check every ten seconds if the process identified as $1 is still 
# running. After 5 checks (~60 seconds), kill it. Return non-zero to 
# indicate something was killed.
monitor() {
  local pid=$1 i=0

  while ps $pid &>/dev/null; do
    if (( i++ > 5 )); then
      echo "Max checks reached. Sending SIGKILL to ${pid}..." >&2
      kill -9 $pid; return 1

    sleep 10

  return 0

read -r pid < ~/.offlineimap/pid

if ps $pid &>/dev/null; then
  echo "Process $pid already running. Exiting..." >&2
  exit 1

offlineimap -o -u quiet & monitor $!

Set this script to run as frequently as you want, by adding something like the following to your crontab – I chose to sync once every 3 minutes:

*/3 * * * * /path/to/mailrun.sh


Now we need a way to send mails. I like msmtp, you can also use other smtp clients. If you choose to install msmtp, the config file is at ~/.msmtprc and should look like this:

account default 
host smtp.gmail.com
port 587
protocol smtp
auth on
from user@gmail.com
user user@gmail.com
password secret
tls on

You can test this by executing echo "a test message" | msmtp you@gmail.com.


Now the fun part! I don’t know how many hours I’ve spent in the past year fine tuning my muttrc, but it’ll never be done. Here are the parts required to get this setup working.

set mbox_type   = Maildir
set sendmail    = /usr/bin/msmtp

set folder      = ~/Mail
set spoolfile   = "+INBOX"
set mbox        = "+[Gmail]/All Mail"
set postponed   = "+[Gmail]/Drafts"
unset record

mailboxes +INBOX

macro index D \
    "<save-message>+[Gmail]/Trash<enter>" \
    "move message to the trash"

macro index S \
    "<save-message>+[Gmail]/Spam<enter>" \
    "mark message as spam"

The above should be enough to get a connection and start sending/receiving mail, but here are some other must-have options that make it feel a bit more like gmail:

# main options
set realname   = "Real Name"
set from       = "user@gmail.com"
set mail_check = 0
set envelope_from

unset move           # gmail does that
set delete           # don't ask, just do
unset confirmappend  # don't ask, just do!
set quit             # don't ask, just do!!
unset mark_old       # read/new is good enough for me

# sort/threading
set sort     = threads
set sort_aux = reverse-last-date-received
set sort_re

# look and feel
set pager_index_lines = 8
set pager_context     = 5
set pager_stop
set menu_scroll
set smart_wrap
set tilde
unset markers

# composing 
set fcc_attach
unset mime_forward
set forward_format = "Fwd: %s"
set include
set forward_quote

ignore *                               # first, ignore all headers
unignore from: to: cc: date: subject:  # then, show only these
hdr_order from: to: cc: date: subject: # and in this order

I’ve left out quite a few tweaks in the above so that those who are happy with mutt’s very sane defaults aren’t overwhelmed. Keep in mind, man muttrc is a great command for when you’re bored.

That should do it. Hopefully this info will get you going in the right direction.

05 Dec 2009, tagged with linux, mutt

Display Manager

GDM, KDM, SLiM; they all serve one purpose: accept a username/password and start X. The below accomplishes the same in the cleanest, simplest, most transparent way I know.

# Note: a $SHELL of either bash or zsh is assumed

if [[ $TTY == /dev/tty1 ]] && [[ -z $DISPLAY ]]; then
  exec startx

These are the last lines of my ~/.zprofile, but they would work as well in ~/.bashrc if that’s your preferred shell.

One added benefit here is that if X dies for any reason, you aren’t left logged in on tty1 like you might be using some other display managers. This is since the built-in exec replaces the current process with the one specified.

05 Dec 2009, tagged with linux