Posts in Category: articles

How to apply for a programming job

Note that the opinions here are my own: they draw upon real world experience at my current employer, but they are not their views, I do not speak for them and I’m far from the only person there who reads CV’s, so my suggestions should not be assumed to offer a quick route to an interview.

I’ve been interviewing for over three years, and in the past year I’ve spent a lot of my working time looking for fresh Graduates to hire. I’ve now read many hundreds of CV’s and carried out telephone, video and face to face interviews, and I can confirm first hand what you’ve probably already realised, and that is simply having a degree related to Computing in any way at all is no guarantee of a job. It’s not even a certain that you’ll get an interview, and it’s down to the skill sets of the applicant not being focussed in the correct way for the needs of the employer.

Admittedly the company I work for is looking for an odd bunch of skills (if we followed the mainstream view, we wouldn’t have been in business for over 20 years), and is very picky about who they make on offer to, but it’s no less specialist than the oft-mentioned Games industry.

So what can be done ? Right now that is – not waiting for the years it will take to shake up ideas from Primary tuition to Degree level and then have the students follow that path. Well it depends how far through the educational pipeline you are: if you’re about to start applying for jobs there’s less you can do than if you are at least a year away from graduating.

Immediate fixes

For me, the first task is for the candidate to properly read the job advert: I know and decry the fact that failed applications aren’t given any feedback, and am fully aware that I am part of that self-perpetuating problem. At the height of the application process I am reading over 30 CV’s a day whilst still being expected to turn in my normal workload on time, and despite my best efforts at maintaining an impartial attitude, too many ‘junk mail’ style applications remove a lot of goodwill.

This means that if you fail to write a targeted cover letter, or simply have a stock one with a company name search-and-replace, then you won’t be doing your best to grab my attention. I do still read them all, but do not assume that letter+CV is some magical formula for an interview: your CV is a reference for me, enabling me to ask questions that probe the level of your knowledge, and to ensure that you have spent your time learning skills that are relevant. The covering letter is yours and your chance to shine: this is where you refer to aspects of your life, non-degree skills and knowledge as well as the job advert, to prove that not only have you paid attention to the job, but that you a more interesting and well qualified than the other applicants.

Refer to things you have done outside of your education: don’t simply give me a job title from part-time work, or rehash what’s in your CV, but explain why your time spent polishing widgets after school gives you more skills for the job than simply having a degree in widget analysis. Don’t automatically assume that I know the details of the schemes you’ve been involved in either: stating that you “learnt loads” or “grew as a person” due to your participation in a recognised scheme a) tells me nothing of the skills you learnt, and b) assumes that I somehow magically know the details of all youth programmes all across the country, despite having been out of education for over half my life. Yes, this means you need to spend time on your application, but trust me: the effort will be noticed, and your application will get more attention as a result.

It’s also worth taking time to explain (in a very small number of words) what your course modules have taught you: you may well know what “CS306 UI Basics” means, but you can be sure I’m not going to try and find a prospectus for your University from the year you joined the course in order to find out what you were supposed to have been taught. Sell yourself to me, and give a list of techniques or skills that the module gave you, or a sentence describing what you gained if that is more helpful to an outsider.

Longer term solutions

If you have a year or more before you’re going to start applying for jobs, then you have a wonderful opportunity: show me how much better you are than your course mates: having 20 applications from a single course does show itself in the fact that the CV’s will be almost identical, and you need to show that you are better than the other 19 who are also “Proficient in C, C++ and Java”.

How ? Simple: if you want a programming job, show me your programming. That isn’t an invitation to bring in a printout of your coursework or to send me tarballs of your latest masterpiece – give me URL’s to code that you’ve written or contributed to. Do you have your own website ? Great: give me a link. Got a blog ? Are you sure that it’s work-safe ? Really ? Then refer to that too.

Ok, but maybe you haven’t programmed at all before starting your degree, and you don’t feel confident enough or have any examples worth publishing. No problem. Find an Open Source project or any online community that you have an active presence in and tell me about it. Perhaps you have spent time coaching others in the basics of some skill or task and simply helping out newbies in forums. That’s great: I actively seek those who will ensure that learning is a constant activity and not something that is only done when a lecturer is in the room.

My one caveat for online references is that you can be 100% certain I will not be signing up with my email address or joining any website in order to view your work. Do not assume I have, or will create a Facebook account just to see your work, and I will not be clicking through any legal agreements (no matter how trivial) in order to read source.

Sounds harsh and restrictive ? Hardly: there are a myriad ways to shine, through well thought out discussions (or arguments) on a mailing list, to patches or diff’s submitted to a project (even if rejected), to well reasoned articles or example help on your own website or in an online community. Talking about the latest CSS developments, or musing about how to take better photographs – it all helps and is part of something larger that previous generations of applicants never had: an online legacy.

Your online legacy

It’s brilliant. It’s scary. It’s here, and you have one: make the best use of it that you can. Googling (or Facebooking) the name of a prospective date has been a staple of comedy for a few years now, and you can be certain that any future employer will do the same. No, I won’t be looking at every applicant in this way, but if you have a well-written covering letter and interesting CV then I will want to know more about you.

Google has had an age based aspect to its weighting algorithm for long time: the longer a domain has been registered, the more likely it is that the content is useful and not part of some link farm. The same goes for you: yes, we all say things online that we later regret (no I’m not linking to them). I’m not looking for some artificial PR-generated online persona to be fed to me as part of the job application, but I would be expecting well thought out (even if incorrect) technical work. I’m not going to be a prudish censor or feel the need to report suspected illegalities, but bear in mind that the photos of you getting falling down drunk with your mates don’t need to be put on the top of the page with your latest code.

Equally, any future employer is not trying to be your friend: I want and demand your best work and attention in return for pay and a challenging and rewarding set of tasks. Don’t attempt to befriend me on a social network, or put your Twitter stream in your application (unless it’s a purely technical one) – keep your social and private life to yourself, and only show me the skills you have for the job. This doesn’t mean you have to live a Jekyll and Hyde online life, but simply keep one area of your online activities ready to be viewed by any employer at any time and do as you will elsewhere – remember that the length of time you stick at something is also relevant: showing that you have posted 50 helpful responses on a mailing list 3 weeks before a job application is not the same as having those 50 responses spread out over 12 months or more – the older the evidence of your involvement, the more compelling it is when supporting your application. It’s never too early to start.

revised ssh/ipf blocking on netbsd

Update 08jan06 @ 08:05: After sending this link to Hubert he came back with a change to get the sed lines inside the shell, so I’ve updated the post to reflect this as it’s a far neater solution.

Ok, I couldn’t resist the challenge after Hubert blogged about my pop-before-smtp script, so here’s my rather ugly shell version. Sadly, I’m lousy at sorting out shell escaping so as well as the shell script there is also a sed script that does the log file filtering: please feel free to alter things to work in one shell script – the code is mine, but do with it what you will, as it doesn’t really have much to it in the end (click on the filenames to get the source).

block.sh:

#!/bin/sh
  
# Block unauthorised login attempts using only system tools
# Inspired by Hubert Freyer's 'challenge' to write a script that just used
# tail to do the work
# (c) Ian Spray and Hubert Fyerer, 2006
  
# Use it for what you will: no restrictions, and no warranty
  
TAIL=/usr/bin/tail
SED=/usr/bin/sed
IPF=/sbin/ipf
CMD_PERM='/usr/bin/tee -a /etc/ipf.conf | '
LOG_FILE='/var/log/authlog'
SED_PAT=ip.sed
  
# uncomment the following line if you want bans to be temporary
# CMD_PERM=''
  
${TAIL} -F ${LOG_FILE} | while read LOG_LINE
do
	echo ${LOG_LINE} 
	| ${SED} 
		-e '/127\.0\.0\.1/d'  \
		-e '/192\.168\.0\./d' \
		-e '/Failed password .* from/!d' \
		-e 's/.*Failed password .* from \([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3}\).*/block in log quick from \1.\2.\3.\4 to any/' \
	| ${CMD_PERM} ${IPF} -A -f -
done 

Note the two main features are the -F in the tail to ensure that log rotations don’t kill the script (check your version if porting outside of NetBSD) and the while loop is to prevent sed from block buffering the log file data. The very long line that performs the actual cutting of the IP address doesn’t fit well on the web, so grab the source if you want to read it easily.

Note that you ought to replace your own LAN subnet (and trusted external site ?) at the start of the sed script to prevent unfortunate accidents, and that the text has been broken to try and fit it more cleanly on the web page: download the file for the correct source code.

If an annotated version of these is desired, then let me know and I’ll explain as much of it as I can remember 🙂

The original downloads are: old_block.sh and ip.sed

fun with pop-before-smtp and ipf on netbsd

I’ve not bothered with POP before SMTP authentication before but since v1.38 the script can take an optional config file that allows it to watch different log files in an easily customised fashion, which is great as I was wondering what the most efficient way of blocking automated ssh attempts was. I didn’t want to run a one minute cron job to parse the authlog file as it was clunky and most of the automated attacks I have seen are over in under two minutes or so. I did consider sticking a pipe in as the destination for the syslog data, but that would mean that if my code died then logging would be seriously compromised.

The best solution is to watch the file for modifications and then parse only the newest data, storing the matches in a database so that I don’t get multiple entries, which is pretty much what pop-before-smtp does, and it ships with an example non-POP3 config file ip-blocking-conf.pl which just needs some tweaks to fit in nicely with ipfilter on NetBSD. In my case, I’m not too bothered about removing the block: if someone tries non-existant usernames via ssh then they can vanish forever – a luxury of a home system that not many people visit 🙂 To that end, I not only want to implement the ban but also record the ban so that the blocking continues over a reboot: this is obviously dangerous and not recommended so I’ll show both the temporary and permanent versions.

File location (for stock NetBSD 3.0):

$dbfile = '/var/db/ip-blocking';
$file_tail{'name'} = '/var/log/authlog';

For testing, dump all activity to the terminal:

$debug = 1;
$logto = '-';

IPFilter differs from ipchains, so change the add and remove subroutines to pass the correct flags and change the order of the arguments:

sub add_ipblock
{
    my($ip) = @_;
    $db{$ip} = $dbvalue;
    system(sprintf($cmdformat, $ip, '-A'));
}
 
sub del_ipblock
{
    my($ip) = @_;
    system(sprintf($cmdformat, $ip, '-A -r'));
    delete $db{$ip};
} 

Now change the command to be executed when a match is found, first for a temporary solution:

$cmdformat = 'echo "block in log quick from %s to any" | /sbin/ipf %s -f -';                       

A more permanent record:

$cmdformat = 'echo "block in log quick from %s to any" | /usr/bin/tee -a /etc/ipf.conf | /sbin/ipf %s -f -';                       

Note that when blocking permanently, it doesn’t make sense to have the rule removed after a timeout, so simply comment out the content of the del_ipblock like so:

sub del_ipblock
{
#    my($ip) = @_;
#    system(sprintf($cmdformat, $ip, '-A -r'));
#    delete $db{$ip};
} 

To start the system off, simply run the script with the correct privilege level to access the database directory and log file:

sudo ./pop-before-smtp --config=./ipf-blocking.pl

I also have a problem with WordPress spam attacks, and have solved it for the most part by deleting the wp-trackback.php file from my site, but that doesn’t stop bots, obviously. What I also want to do is consign these machines to the bitbucket, as they are simply annoying and are often open relays, which will mean SMTP traffic is also likely to originate there. The drawback is that whilst the pattern match is configurable via the $pat variable, the main pop-before-smtp makes a fairly valid assumption that all log lines start with a syslog-style timestamp, which Apache doesn’t do. Without that extra match, the software would have a hard time just tracking new additions, so rather than change the source I decided to log some extra data from Apache, and then strip it out when I do my monthly log rotations. Note that I also log the virtual host in my Apache access_log file, so this strings might have an extra %v in it compared to normal:

LogFormat "%{%b %e %T}t %v %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" syslogcvh
CustomLog /var/log/httpd/access_log syslogcvh

This simply duplicates data (in a lossy fashion), and can be trimmed via a regexp or simple cut -b 17- command during normal log rotation/processing. The changes to the ip-blocking-conf.pl are pretty much as before, but if you want to run both at once it’s advisable to change the DB used to store the matched IP’s:

$dbfile = '/var/db/wp-ip-blocking';
$file_tail{'name'} = '/var/log/httpd/access_log';
$pat = '^(... .. ..:..:..)\s+(?:virtual.hostname.1|virtual.hostname.2)\s+(\d+\.\d+\.\d+\.\d+).+(POST )';

Note that the $pat above is very aggressive (and not WordPress specific): I have it set so that virtual.hostname.1 is the catch-all which is hit when a numeric IP is used to access my site, and virtual.hostanme.2 no-longer runs WordPress so any POST is invalid. Do NOT apply this to a live site, or no-one will be able to post a comment ! Extending the regexp to trap POST requests for WordPress files that arrive from an invalid Referer is left as an exercise for the reader[1]

One final warning, you must, must, MUST set your local subnet correctly in the mynet_ipblock or you will come unstuck. I have also added in an extra item or two for external systems that I trust so that I always have a route back in again should the worst happen:

sub mynet_ipblock
{   
    # You'll probably want to edit this (it specifies IP ranges to ignore).
    '127.0.0.0/8 192.168.0.1/24';
} 

Note that running two such scanners does raise the chance that one IP will get blocked twice (most likely when the program is first started and old lines are being processed), in which case an error like 1:ioctl(add/insert rule): File exists may well be shown. This is a non-fatal error, and for tidiness the duplicate IP should be removed from /etc/ipf.conf if permanent logging has been chosen. If the block is temporary then the message can be safely ignored.

[1] Heh, memories of Dave Smallwood lectures still linger, although I think I need ‘trivial‘ in there somewhere…

making an unabridged audio album from a dvd in mac os x

I’m pretty sure this is covered by most ‘fair use’ clauses (do check your own laws: IANAL) but is intended for people with a DVD and a DVD-ROM drive who want the soundtrack to the film but don’t feel the need to pay twice for the same material on different media…

Pretty much all you need to know can be found at Shepmaster’s site, but there are only two pages that matter: how to turn the DVD into AAC files and then how to turn AAC files into stereo audio files.

Do Google for the most current sites, but at the time of writing you can find the 0SEx program here, and the mAC3dec project here. Download and expand both those binary files, shove in a DVD (in my case Koyaanisqatsi), quit any auto-launched DVD player app and start up 0SEx.

The only tricky part is figuring out which Title has the film – each Title can contain many Chapters, so choose the Title that has the same number of Chapter entries as the film inlay says it has scenes. Titles are used to contain menu items as well as the main feature, but in my case the film has 16 Chapters as so is easy to spot. Click on Ti and choose the correct title. If you don’t want all of the film chapters, click on Ch and choose the ones you want. Next, turn off the video decode (click on the Vid button, and click to turn off the tick mark), and then turn off the subtitle extraction (click on the Sub button, and click on each tick). There are menu items under Control that do this for you, if you are feeling more adventurous.

Change the format of the extracted files by clicking on Fmt and choosing Elementary Streams so that the audio comes out in it’s own file (and not in a VOB with no image data), and then click on Seg and choose Chapter, so that each scene is split into a separate file. Then click on BEGIN and choose a destination directory.

Wait a while and you should have a collection of .ac3 files in their own directory – the most useful thing to do is to convert them to .wav or .aiff files whilst downmixing from 5.1 to 2.0 and applying a global volume normalisation. Eh ? Ok: the AC3 files can have a much greater dynamic range than ‘normal’ 16-bit 44.1kHz WAV files, so the Normalising process means that the maximum and minimum volume of each track is noted and used to scale the final WAV/AIFF files so that the audio for the entire album fits comfortably into the range available. Still sounds odd ? Then trust me: without Normalising you will most likely find that the quiet bits are too quiet, and the loud bits too loud for comfortable music listening.

Start up mAC3dec. I’m aiming to playback the final result via iTunes, so choose AIFF from the Format menu, then 44.1kHz from the Sample rate options, tick Normalize and tick Globally, and check that Split Channels is left unticked. Now go to File->Add AC3 and select all of the files that make up your DVD audio. Once they’re loaded, click Start and wait: if you like to see graphical progress bars then make sure you’ve visited the mAC3dec->Preferences menu and unticked the Disable Progress Bar option.

The program will scan through all of the files once to record the volume highs and lows for each track, and then setabout converting them to plain 2.0 (stereo) AIFF files. Once this is complete, do with them what you will ! I opened up iTunes, added the AIFF files to the Library and then selected all of them and used Advanced->Convert Selection to MP3. After all had been converted I deleted the AIFF originals from the Library and added ID3 tags to taste.

Yes, you can skip a step and get mAC3dec to convert from AC3 directly to MP3, but I haven’t had chance to mess with the MP3 encoder in mAC3dec so I can’t vouch for what differences (if any) there are from the iTunes encoder. I quite liked the idea of having the AIFF files around for a while in case I wanted to burn a pure Audio CD from them, but so far haven’t taken that step.

typo in the WinCVS/ssh guide

Thanks go to Skip Coombe for finding two very long standing errors in the WinCVS/ssh guide – I can’t prove one of them as my setup works fine as detailed, but it’s been added as a footnote for those that might be having problems.

messin’ with google.com

Cool – giving Google the search phrase ‘wincvs ssh‘ means that the guide on this site is the 7th hit !

applescript, itunes and speech

I like iTunes on my iBook, but I often forget the name of a track (I just listen to the album[s] whilst programming) so thanks to the hotkey ability of Keyboard Maestro, I’ve got an AppleScript solution (my first !) that takes up no screen space at all. I also threw in a pause and play pair of scripts too, so other people can interrupt me and I don’t need to hunt for the right app and button.

I bind these to F9 (speak), F10 (pause) and F11 (play) because it suits me although I’m not brave enough to take a magic marker to my iBook’s keyboard. Yet.Pause:

tell application "iTunes"
 if player state is playing then
  pause
  say "Paused"
 else
  say "Not playing"
 end if
end tell

Play:

tell application "iTunes"
 say "Play"
 play
end tell

Current tune:

tell application "iTunes"
  if player state is playing then
    say artist of current track as string
    say name of current track as string
  else
    say "Not playing"
  end if
end tell

Enjoy !

neoprene case

I’ve also started planning a neoprene case for an iBook. No, I don’t have one (yet), but that doesn’t stand in the way of a good idea… Unfortunately, just after I got the rubber delivered, I found that the idea is already a product, but I reckon mine will be nicer 🙂

Ok, it’ll be cheaper.