Solaris sans-seq

Solaris, while a fairly decent OS, can be a bit of a pain if you try and write some cross-Unix compatible scripts.

One of the functions I tend to use quite a bit is ‘seq’, a sequence generator:

~$ seq 1 10
1
2
3
4
5
6
7
8
9
10
~$

I use it in a couple of my scripts where I need to chunk, or ‘split’ some files without ending with cruft:

~$ cat /tmp/mylongfile| sed "$( seq -f 'n;' 2 5| tr -d '\n' )G;"
line 1
line 2
line 3
line 4
line 5

line 6
line 7
line 8
line 9
line 10

line 11
~$

All fair and well, but, as mentioned at the top of this post; Solaris is sometimes a bit of a pain. In this case, in particular, since Solaris is sans-‘seq’.

This is my version of ‘seq.sh’ for Solaris, especially when you don’t feel the need of dragging your C compiler closer and re-implementing it in binary; or you feel that using Perl or Python is simply overdoing matters:

#!/usr/bin/env ksh

seq() {
    __seq_PARM="";

    if [ "$1" = "-f" -o "${1##-f}" != "$1" ]; then
        if [ "$1" = "-f" ]; then
            __seq_PARM=$2;
            shift;
        else
            __seq_PARM="${1##-f}";
        fi
        shift;
    fi

    typeset -i __seq_START;
    typeset -i __seq_END;

    if [ $# -eq 1 ]; then
        __seq_START=0;
        __seq_END=$1;
    elif [ $# -eq 2 ]; then
        __seq_START=$1;
        __seq_END=$2;
    else
        echo "seq [-f format] [first] last" >&2;
        return;
    fi

    [ "${__seq_PARM}" = "" ] && __seq_PARM="%d";

    for (( __seq_i=${__seq_START}; __seq_i<=${__seq_END}; __seq_i++ )); do
        printf "${__seq_PARM}\n" $__seq_i;
    done
    unset __seq_PARM __seq_START __seq_END __seq_i;
}

__seq_CURR=$( echo $_| sed 's/.*\*//' );
if [[ $__seq_CURR = $0 ]]; then
    if [ "$1" = "-?" -o "$1" = "-h" -o "$1" = "--help" -o $# -eq 0 ]; then
        __seq_HELP="[-f format] [first] last"
        __seq_SNAME=$(basename $0);
        __seq_HELPTXT="${__seq_SNAME} usage:\n\nRun ${__seq_SNAME} directly:\n    $0 [-h|--help] ${__seq_HELP}\n\n";
        __seq_HELPTXT=${__seq_HELPTXT}"Source ${__seq_SNAME}:\n    . $0;\n    seq ${__seq_HELP}\n\n";

        printf "${__seq_HELPTXT}" >&2;
        unset __seq_HELPTXT __seq_HELP __seq_SNAME;
    else
        seq $@;
    fi
fi
unset __seq_CURR;

One of the (kinda) cool things this does is check whether you’re sourcing the file (inside your own script so you can run the seq function from there afterwards) or whether you’re running it directly (from the command-line, for example). Running it with a ‘-h‘ will attempt to explain… :-)

~$ /usr/local/bin/seq.sh -h
seq.sh usage:

Run seq.sh directly:
    /usr/local/bin/seq.sh [-h|--help] [-f format] [first] last

Source seq.sh:
    . /usr/local/bin/seq.sh;
    seq [-f format] [first] last

~$

As always, do with this as you will: you break it, you get to keep both pieces.

Update: 2015-10-15

A mere couple of hours after publishing the previous I realised that Solaris’ KSH (88) does not support for (( )) constructs. Of course not.

This means I had to replace the for (( )) loop with a while [[ ]] loop:

__seq_i=${__seq_START}
while [[ ${__seq_i} -le ${__seq_END} ]]; do
     printf "${__seq_PARM}\n" "${__seq_i}";
     let __seq_i=${__seq_i}+1
done

This should run nearly as fast as the previous loop, but will run on KSH-88, KSH-93 and Bash as well.

The updated seq.sh script now looks like this:

#!/usr/bin/env ksh

seq()
{
    __seq_PARM="";

    if [ "$1" = "-f" -o "${1##-f}" != "$1" ]; then
        if [ "$1" = "-f" ]; then
            __seq_PARM=$2;
            shift;
        else
            __seq_PARM="${1##-f}";
        fi
        shift;
    fi

    typeset -i __seq_START;
    typeset -i __seq_END;

    if [ $# -eq 1 ]; then
        __seq_START=0;
        __seq_END=$1;
    elif [ $# -eq 2 ]; then
        __seq_START=$1;
        __seq_END=$2;
    else
        echo "seq [-f format] [first] last" >&2;
        return;
    fi

    [ "${__seq_PARM}" = "" ] && __seq_PARM="%d";

    __seq_i=${__seq_START}
    while [[ ${__seq_i} -le ${__seq_END} ]]; do
        printf "${__seq_PARM}\n" "${__seq_i}";
        let __seq_i=${__seq_i}+1
    done
    unset __seq_PARM __seq_START __seq_END __seq_i;

}

__seq_CURR=$( echo $_| sed 's/.*\*//' );
if [[ $__seq_CURR = $0 ]]; then
    if [ "$1" = "-?" -o "$1" = "-h" -o "$1" = "--help" -o $# -eq 0 ]; then
        __seq_HELP="[-f format] [first] last"
        __seq_SNAME=$(basename $0);
        __seq_HELPTXT="${__seq_SNAME} usage:\n\nRun ${__seq_SNAME} directly:\n    $0 [-h|--help] ${__seq_HELP}\n\n";
        __seq_HELPTXT=${__seq_HELPTXT}"Source ${__seq_SNAME}:\n    . $0;\n    seq ${__seq_HELP}\n\n";

        printf "${__seq_HELPTXT}" >&2;
        unset __seq_HELPTXT __seq_HELP __seq_SNAME;
    else
        seq $@;
    fi
fi
unset __seq_CURR;

Wallpaper Mavericks…

I have finally had enough of Mavericks’ shenanigans when it comes to Desktop Wallpapers…

For those not in the know, in OS X Mavericks, Apple has changed the mechanism for configuring Desktop Wallpaper from the venerable .plist to using a Sqlite3 database.

While using the database is probably more robust and easier to integrate, it is not as easy to change the desktop or, even more important from my perspective, to change all your desktops to the same wallpaper.

After some Googling and digging, I finally came up with the following little Python script which I called, reasonably enough, changewall:

#!/usr/bin/python

from __future__ import print_function

import os, sys, subprocess
import sqlite3

if len( sys.argv ) < 2:
    sys.exit( 'Usage: "%s" file-name' % sys.argv[ 0 ] )

if not os.path.exists( sys.argv[1] ):
    sys.exit( 'ERROR: File "%s" was not found!' % sys.argv[ 1 ] )

desktop_picture_path = sys.argv[ 1 ]
database_location = os.path.expanduser( '~/Library/Application Support/Dock/desktoppicture.db' )

conn = sqlite3.connect( database_location )
print( 'Opened database', end=", " )

cur = conn.cursor()
cur.execute( 'SELECT count( DISTINCT display_id ) + 1 FROM pictures;' )
displays = cur.fetchone()[0]

cur.execute( 'SELECT count( DISTINCT space_id ) + 1 FROM pictures;' )
spaces = cur.fetchone()[0]

conn.execute( 'DELETE FROM preferences' )

conn.execute( 'DELETE FROM data' )
conn.execute( 'INSERT INTO data VALUES (?)', ( desktop_picture_path, ))
conn.execute( 'VACUUM data' )

screens = spaces * displays
for screen in range( screens ):
    conn.execute( 'INSERT INTO preferences VALUES (1,1,?)', ( screen + 1, ))
    conn.execute( 'VACUUM preferences' )

conn.commit()

print( 'Records created successfully', end=", " )
conn.close()
print( 'Closed database' )

subprocess.check_call( ['/usr/bin/killall', 'Dock'] )

Not all that impressive, I’m fully aware, but it does seem to do the job. Using it is simplicity itself: changewall ~/Wallpaper/funky_wallpaper.jpg

As usual, do with it what you will…

New Year Blues

It’s getting to that time of year again we we have to pause and reflect on our accomplishments (or lack thereof) during the year. Again.

A time to compare where we are, to where we should be, to where would like to be…

And as is usual for most of humanity, we will all most likely decide: Screw that, we’ll try again next year.

Merry Christmas to all of you, and a very Happy New Year.

Geektool is even cooler than I thought…

Hacking away at Geektool I decided to try something else: sending raw terminal escape-codes at it and see how it handled it… In short: even better than I thought. So here is an update to my earlier Geeklet to display a calendar:

ESC="\\\033["; \
printf "\n$( cal| \
    sed "\
        s/^/ /; s/$/ /;\
        /^ Su.*/d;\
        /.*$( date +'%B %Y' ).*/d;\
        /^$/d;\
        s/$( date +%e ) /${ESC}1;37m$( date +%e )${ESC}0m /g;\
    "\
)\n"

I will admit to still using the previous version, though, since I prefer the font bolding in that one.

Of fortunes and Macs and (Xscreen) savers…

Every so often I have the urge to do something quite unnatural; something like, for instance, actually updating the software on my Macbook…

Rather subversive, I know, but we all have our weaknesses.

One go the packages I make a habit of installing, and updating, is JWZ’s Mac build of Xscreensaver. The biggest down-side of doing that, though, is that, unlike in Linux, it doesn’t by default display quotes from the fortune files.

The ability do so is, of course, still very much there, but the Mac build does not have an easy way of enabling it.

Herewith, then, my workflow to get things back to “sanity” once I’ve upgraded.

Firstly, make sure that you have installed fortune from the ports (or any other way that takes your fancy):

eroux@smaug:~$ sudo port install fortune
--->  Fetching archive for fortune
--->  Fetching fortune
--->  Verifying checksum(s) for fortune
--->  Extracting fortune
--->  Applying patches to fortune
--->  Configuring fortune
--->  Building fortune
--->  Staging fortune into destroot
--->  Installing fortune @6.2.0-RELEASE_0+universal
--->  Activating fortune @6.2.0-RELEASE_0+universal
--->  Cleaning fortune
eroux@smaug:~$ 

Once you can run fortune and get a result, you are ready to continue:

eroux@smaug:~$ fortune
I always had a repulsive need to be something more than human.
                                                -- David Bowie
eroux@smaug:~$ type fortune
fortune is hashed (/opt/local/bin/fortune)
eroux@smaug:~$

Now you need the following patch, which we’ll use to convince Xscreensaver that we know what we’re doing:

--- xscreensaver-text.pre   2011-03-01 18:06:46.000000000 +0200
+++ xscreensaver-text       2011-03-01 18:07:05.000000000 +0200
@@ -247,6 +247,7 @@
   elsif ($text_mode eq '1') { $text_mode = 'literal'; }
   elsif ($text_mode eq '2') { $text_mode = 'file';    }
   elsif ($text_mode eq '3') { $text_mode = 'url';     }
+  elsif ($text_mode eq '4') { $text_mode = 'program'; }

   $v = get_cocoa_pref_1 ($id, "textLiteral");
   $text_literal = $v if defined ($v);

All we’re doing here is adding a program text mode to Xscreensaver, which we will then use via defaults to get fortune to run under its auspices.

Now we need to update all the files that actually could use some fortune:

for I in Apple2 FlipText FontGlide NoseGuy Phosphor StarWars XMatrix; do
    cd "/Library/Screen Savers/${I}.saver/Contents/Resources/" && 
        patch -p0 < ~/xscreensaver-text.patch && cd;
done

Now we get to test one of the screen savers. My favourite is one called Phosphor, so lets start with that:

defaults -currentHost write \
  org.jwz.xscreensaver.Phosphor \
  textProgram "/opt/local/bin/fortune";

This tells Phosphor which program to run, but not yet that it should actually use it. Let’s do that now, why don’t we?

defaults -currentHost write \
  org.jwz.xscreensaver.Phosphor \
  textMode 4;

Here you see us actually using the mode we defined in the patch, earlier. I had to change the scale of the fonts to get the display to fit on my screen, so if it’s too big or too small, you can change that from within the screensaver configuration window.

eroux@smaug:~$ defaults -currentHost read org.jwz.xscreensaver.Phosphor
{
    scale = 3;
    textMode = 4;
    textProgram = "/opt/local/bin/fortune";
}
eroux@smaug:~$

All done… Now you just need to sit back and wait for your screen to lock… Or just press Ctrl-Shift-Eject if you’re too impatient, of course.

Some alternatives to consider: Since the fortune you run is the same program you would find on any Linux machine, you could use “/opt/local/bin/fortune -s” to get only the short quotes, if you wish, or even “/opt/local/bin/fortune -o” for some… other quotes.

Of Geeky Mac Users and their Tools…

One of the toys I’ve come to appreciate running on my Mac, is a little utility called GeekTool

What makes GeekTool cool, is that it allows you to embed different items into your Mac desktop, so it is quite easy to use it to display a text file, for instance (like your system log) or to scrape a ticker-tape from the web and use that to keep track of your favourite Stock Price, but it is also possible to do much cooler stuff…

A quick example of what is possible was featured on LifeHacker, where they embed the venerable Unix “cal” command in the desktop, and using some “sed” slight-of-hand they even mark the current day on the calendar.

“Very Cool”, I thought, “except…”

Well, yes, except. I would have preferred not losing the day, but rather marking it in some way.

But before I get to that, I need to digress a bit first, though.

There are some thinks I would really like in this world. Peace. Children being able to play together for more than a few minutes without fighting. Winning a big one on the Euro Lottery. GeekTool being able to display HTML. But alas…

And since GeekTool would not allow me to embed HTML (or any other markup I could tell: I would have settled for Markdown or even RTF) I tried to work around the problem…

After a couple of iterations (and careful selection of the font GeekTool used to display my resultant calendar) I finally settled on the following:

cal| sed "s/^/ /;s/$/ /;s/.*date +'%B %Y'.*//;/^$/d; \
    s/ date +%e /(date +%e)/g;"

This got me a nice-looking calendar with the day-of-week marked by some parentheses:

 Su Mo Tu We Th Fr Sa  
                 1  2  
  3  4  5  6  7  8  9  
 10 11 12 13 14 15 16  
 17 18 19 20 21 22 23  
(24)25 26 27 28 29 30  
 31

In doing this, I also got rid of the Month and Year since I already have another Geeklet that displays that on my Desktop:

That displayed okay, I guess, but I was still (slightly) disappointed. Then it struck me: I was being an utter dunce. I had already been overlaying the other script Geeklets to get the Date/Time display I had wanted; there was nothing stopping me from generating two calendars, one on top of the other, one with the current day edited out, and the other only containing the current day, in the correct spot. That way the second could be displayed in another colour and give me the result I had sought.

So, without further ado, I cooked up the following. First, the easy one. Here is the script for displaying the calendar with the current day masked out:

cal| sed "s/^/ /;s/$/ /;s/^ Su.*//;s/.*date +'%B %Y'.*//; 
/^$/d; s/date +%e /   /g;"

The second stumped me for a bit, till I realised I was doing my usual: over-thinking the problem. This is the script I used in the end:

cal| sed "s/^/ /;s/$/ /;s/^ Su.*//;s/.*date +'%B %Y'.*//; 
/^$/d; s/ date +%e / ## /g; s/[0-9]/ /g; s/ ## / date +%e /"

In these I also deleted the Day strip at the top and added a Geeklet containing the days of the week in the more traditional three-letter format. By dropping the font of that to 18 points as opposed to the other two’s 24 points, I managed to for it all in perfectly:

Now all of them fit together rather nicely, and I’m a happy(er) person.

For anyone curious enough to know how I had all of these placed to get them to work together (both of you), here it is:

For everyone else… I apologise?

Oh, and if you’re wondering about my Desktop Wallpaper, it’s Vlad Gerasimov’s Mac OS-X Lion wallpaper

Okay… Colour me impressed by Apple!

From TUAW via Cult of Mac comes the following:

Apple is offering free repairs to those with Macs and iOS devices who had their equipment damaged in the earthquake and tsunami that struck Japan back in March.

A guide[Link content now changed] on Apple’s Japanese website states the company is offering free repairs to Macs, Cinema Displays, iPhones, iPads, and iPod touches for people who live in the municipalities covered be the Disaster Relief Act of 2011.

For those affected, Apple will pick up and repair your equipment at no charge, then deliver it back to you once the repairs are complete. The company is also offering free access to the AppleCare Service & Support Line for those who can solve issues over the telephone.
Apple has been keen to help those in Japan who have been affected by the recent disasters: It has opened up its stores as ‘communication centers’ and allowed people to access the Internet to contact their loved ones through email, FaceTime and Skype. It has also offered donations from app proceeds and allowed customers to donate to the Red Cross through iTunes.

Maybe some lessons to be taken here by the rest of Tech…

When Lions Roared…

If you ever have the urge to reformat John Lions’ “A commentary on the Sixth Edition UNIX Operating System”, this patch might help you:

--- Lions.old/lionc.tex 1994-05-19 04:40:49.000000000 +0200
+++ Lions.new/lionc.tex 2011-04-07 15:38:14.000000000 +0200
@@ -1,7 +1,16 @@
 %
 % The Lion's Commentary, file lionc.tex, version 1.3, 18 May 1994
+% Updated 07 April 2011 to generate PDF Bookmarks
+% and to fit LaTeX2e slightly better
 %
-documentstyle[twoside,fancyheadings]{article}
+documentclass[twoside,a4paper]{article}
+usepackage{fancyhdr}
+usepackage[plainpages=false]{hyperref}
+hypersetup{%
+ pdfborder = {0 0 0},
+ pdftitle = {Commentary on 6ed UNIX OS},
+ pdfauthor = {John Lions}
+}
 fonttwlrm = cmr10 scaled magstep1

% Set the page dimensions
@@ -38,7 +47,7 @@

% Set up the headings for the document

-setlength{headrulewidth}{0cm}
+renewcommand{headrulewidth}{0pt}
 renewcommand{sectionmark}[1]{markboth{#1}{}}
 renewcommand{subsectionmark}[1]{markright{#1}}
 rhead[{it UNIX 6th Edition Commentary}]{it leftmark}

If you have no idea what I’m talking about… Well, then, erm… Never mind… :-)

The wheel turns…

It’s with distress that I’ve witnessed soldiers using live ammo on protesters in Libya and Iran this week, and the brutality of the soldiers against the paramedics in Egypt last week.

As someone who spent more than just a few years in the military and who had been involved in a few riots, and you have to have been in a riot in South Africa in the mid to late eighties to really understand the significance of that statement, I do know the fear and uncertainty involved in standing in a line; just a few soldiers against thousands of rioters. I can still remember the anxiety and can still actually remember “tasting” the fear.

What I can also remember is standing there with rifle uncocked and pointing down. We were warned that there would be actual hell to pay, court-martial style, if we ever shot a civilian; no matter the reason. The rioters were of course not aware of it, or if they were, were not always believing it, but that was immaterial; our job was not to quell the riot but to marginally control it; it was to keep people not involved as safe as we could. The rioters would only very rarely attempt to break through the lines and make our job impossible. Even in those bad old days, the military was respected by the civilians; the police… not as much.

It was during those times that I had learnt to equate the tasks of the soldiers and the police to those in certain medieval city-states: the difference between the Watch and the Guard.

In those cities who might actually have had both, the guard’s primary task was to defend the gates and wall of the city, the watch was to police the city and the wards… Well as much policing as happened in those times. Point being, while these groups would support each other in crises, these groups had their own expertise and zones of authority: the guard would watch for external threat and the watch would police the city.

It is just wrong then, that a “weapon” (there is no other way of really describing the military machine) would be used by their own government on their own citizens. The very existence of military forces is to protect the people, not to oppress them.

A note to the soldiers involved in this: these actions will come back to haunt you, and when it does please remember your beating up the poor paramedics while you lie there bleeding after it has done so…

The wheel turns. It always does…

An erstwhile buddy of mine, the joker of the platoon, would always claim you can smell fear… It smells like shi… Ah. Never-mind…