It ends with my friends receiving an email like this:

It begins with me connecting to my mail server with telnet or netcat. After connecting, I have an SMTP session with it like this:

susam@nifty:~$ telnet mail.susam.in 25
Trying 67.43.13.244...
Connected to susam.in.
Escape character is '^]'.
220-krishna.ewebguru.net ESMTP Exim 4.69 #1 Mon, 15 Feb 2010 02:10:18
+0530
220-We do not authorize the use of this system to transport unsolicited,
220 and/or bulk e-mail.
EHLO
250-krishna.ewebguru.net Hello  [122.167.69.67]
250-SIZE 52428800
250-PIPELINING
250-AUTH PLAIN LOGIN
250-STARTTLS
250 HELP
AUTH PLAIN ××××××××××××
235 Authentication succeeded
MAIL FROM:<prun××××××@gmail.com>
250 OK
RCPT TO:<prun××××××@gmail.com>
250 Accepted
RCPT TO:<wes×××××××@gmail.com>
250 Accepted
RCPT TO:<sus××××××@gmail.com>
250 Accepted
RCPT
TO:<ind××××××××××@gmail.com>
250 Accepted
RCPT TO:<kart×××××××@gmail.com>
250 Accepted
DATA
354 Enter message, ending with "." on a line by itself
Date: Mon, 21 Dec 2012 10:28:00 +0530
From: "Prunthaban Kanthakumar" <prun××××××@gmail.com>
To: "Prunthaban Kanthakumar" <prun××××××@gmail.com>
Cc: "Susam Pal" <sus××××××@gmail.com>, "John Wesley"
<wes×××××××@gmail.com>,
 "Indhu Bharathi" <ind××××××××××@gmail.com>, "Karthik"
<kart×××××××@gmail.com>
Subject: Experiment Successful

I was working today (21 Dec, 2012) on an experiment to send messages to
a space-time co-ordinate in the past. If this experiment is successful I
should receive this mail on 15 Feb, 2010, a date in the past.

It is quite funny that we can remember the past but not the future.  So,
when I receive this message on (15 Feb, 2010), I wouldn't remember that
this is the result of a successful revolutionary experiment to be
performed in future. I should have got this message time stamped by a
trusted time stamping authority in order to prove that this message is
indeed from the future but that has its own problems. Why would I, in
the past, believe that such a trusted time stamping authority would
exist in the future?  Moreover, I don't have time to get all this done
as the world is coming to an end today.
.
250 OK id=1NglGq-0008JC-RK
QUIT
221 krishna.ewebguru.net closing connection
Connection closed by foreign host.

An internet message or email consists of two sections: header and body. The header usually consists of fields like 'From', 'To', 'Cc', 'Subject', etc. which are usually displayed to the user. It may have more fields like 'Message-ID', 'Return-Path', 'Content-Type', etc. which are usually not displayed to the user. But many email programs provide some mechanism to view them as well. For instance, in GMail, one can click the little arrow near the 'Reply' button and select the 'Show original' option to view the message with all the message headers. In Microsoft Office Outlook, selecting 'Options' from the 'View' menu in the message window shows all the message headers.

These headers, which are usually not displayed by the email program, are used by the email client and the various programs running on various mail servers to deliver the email to the recipient's inbox. For example, if the delivery of the email fails for some reason, a message describing the failure would be sent to the email address found in the 'Return-Path' field. This is usually the email address of the sender. This field is automatically added by the mail server before sending the email.

The actual message meant to be read by the recipient is contained in the message body. The message body begins after the message headers. The message header and the message body are separated by an empty line. These things can be seen in the above example.

When we compose an email using web based emails like GMail, Hotmail, etc. or email clients such as Microsoft Outlook, Thunderbird, etc. the client automatically enters the sender's email address in the 'From' field before sending the email. Similarly, it automatically uses the email addresses mentioned in the 'To' and 'Cc' fields as recipients of the email. The email client connects to the SMTP server and executes the necessary commands to send the email.

However, when we have a session with the SMTP server, we need to execute those commands ourselves. For example, each recipient is specified with the RCPT TO command. The actual email message that is displayed to the user by the various email clients begins after the DATA command. The message headers such as 'From', 'Date', etc. have to be composed manually.

This gives us more freedom while composing the message. We can specify a future date in the 'Date' field. We can specify a false email address in the 'From' field. There need not be any relation between the recipients specified with the RCPT TO command and the email addresses specified in 'To' and 'Cc' fields. So, it is possible to send an email to one person with the 'To' or 'Cc' field displaying the email address of another person. Similarly, the 'From' field need not contain the email address of the actual sender. SMTP is not concerned with the correctness of these fields.

In the above example, I have composed an email with the email address of a friend in the 'From' as well as 'To' headers. Similarly, I have specified a future date in the 'Date' field. I have specified a false email address in the MAIL FROM command as well because the email address specified there appears in the 'Return-Path' field in the message header.

In the examples above, I have smudged or hidden parts of the authentication response and the email addresses with crosses for privacy reasons. The authentication response contains the credentials I use to log into my email server. For more on how to form an authentication response, see: AUTH CRAM-MD5.

Here are a couple of hyperlinks for further reading.

  1. RFC 5321 : Simpe Mail Transfer Protocol
  2. RFC 5322 : Internet Message Format

A networking teacher once told us, "Computer networking is not a game of gentlemen".

In one of the corporate trainings, there was an excellent C instructor. He typed complete programs on his terminal which was live on the projector and explained the concepts very nicely. Something else caught my attention. He was using a 7-character password (yes, I counted the keystrokes) to login to the remote Linux machine and the default password given to us for our Linux accounts also had 7-characters. I tried to login with the default password into the instructor's account and I succeeded. So, I got this funny idea. I don't remember what his ID was, but let us assume it was his_id.

I ran who | grep his_id and found that there were two terminals for his_id: pts/7 and pts/40. I ran tty and found that mine was /dev/pts/40. So, the other one must be the instructor's.

I ran echo -n " " > /dev/pts/7 and I found that the cursor blinking on the screen moved ahead. I had successfully redirected a space to his terminal when the instructor was looking at us. Before, he turned back. I ran echo -ne "\b" > /dev/pts/7. That was a backspace which brought the cursor back to its original place.

Then I wrote a small script to automate this process and I redirected all sorts of funny messages on the screen when the instructor looked at us. I remember some of them.

  • When will this session be over? Are you guys hungry?
  • Do you know who is doing this?
  • FATAL: Disk has crashed.
  • Hey instructor! Don't turn back.
  • Twinkle twinkle little star.
  • Laugh!
I also included a 'dance' command to my script that would make some random characters dance from left to right and right to left in a single line.

It took some time for my batchmates to figure out who was doing this. Most of them were hiding their faces and giggling. A couple of times, the instructor became suspicious about why the class was acting funny all of a sudden. He looked back. The lady beside me was so scared that she almost held my hand to pull it away from the keyboard. That could have been a disaster but I redirected the backspaces just in time and I escaped narrowly.

I deleted most of them with backspaces before the instructor turned back. However, I did not delete the FATAL warning. I wanted to see how he would react. When he looked back, he stared at the message, thought for a while and pressed the ENTER key a few times and carried on with the training.

I uploaded this video on Youtube last night: Nightly Experiments – A few notes 2.0. The music was recorded as an MP3 file with Audacity after connecting the musical keyboard's output jack to the laptop's line-in jack using a cable with 3.5 mm stereo plug at both ends. A 3.5 mm stereo jack to 6.35 mm stereo adapter was used to connect the 3.5 mm (approx. ⅛") stereo plug to the keyboard's 6.35 mm (¼") stereo jack.

In this blog post, I'll explain how I converted the MPEG audio (a .mp3 file) to an MPEG video (a .mpg file) with my Debian GNU/Linux system so that I could upload the video to Youtube. My requirements were simple. I needed one still image displaying some text while the music plays. I wrote this Python script to generate a JPEG image that displays the album name and the title at the center and my name at the bottom right corner.

import Image, ImageDraw, ImageFont

ALBUM = 'Nightly Experiments'
TITLE = 'A few notes 2.0'
ARTIST = 'Susam Pal'
FILE = 'a_few_notes_2.jpg'

WIDTH = 640
HEIGHT = 480
GAP = 10
MARGIN = 10

FONT = '/usr/share/fonts/truetype/freefont/FreeSans.ttf'

image = Image.new('RGB', (WIDTH, HEIGHT))
writer = ImageDraw.Draw(image)
largeFont = ImageFont.truetype(FONT, 36)
smallFont = ImageFont.truetype(FONT, 20)

albumWidth, albumHeight = writer.textsize(ALBUM, font=largeFont)
titleWidth, titleHeight = writer.textsize(TITLE, font=largeFont)
artistWidth, artistHeight = writer.textsize(ARTIST, font=smallFont)

albumX = (WIDTH - albumWidth) / 2
albumY = (HEIGHT - albumHeight - titleHeight -
GAP - 2 * MARGIN - artistHeight) / 2
titleX = (WIDTH - titleWidth) / 2
titleY = albumY + albumHeight + GAP
artistX = WIDTH - artistWidth - MARGIN
artistY = HEIGHT - artistHeight - MARGIN

writer.text((albumX, albumY), ALBUM, font=largeFont)
writer.text((titleX, titleY), TITLE, font=largeFont)
writer.text((artistX, artistY), ARTIST, font=smallFont)

image.save(FILE)

Python Imaging Library (PIL) is used in this script. It can be installed on Debian GNU/Linux by running: aptitude install python-imaging.

After generating the JPEG image by running the above script, the JPEG image and the MPEG audio was converted into an MPEG video by running this command:

ffmpeg -ab 256k -loop_input -shortest -i a_few_notes_2.jpg -i a_few_notes_2.mp3 a_few_notes_2.mpg
FFmpeg video converter can be installed by running: aptitude install ffmpeg.

When we are kids, our mothers tell us bedtime stories and sing us lullabies before we go to sleep. But what when we are grown up and living alone? I love music a lot and I listen to music almost all the time: at work, at home, when I am traveling and even when I am about to fall asleep. When I go to bed, I play music on my computer. I use Debian GNU/Linux at home and I play music using Rhythmbox with 'Repeat' enabled for the album or artist I am listening to on the day.

When I am falling asleep with the music playing on my computer, gradually the music becomes disturbing and prevents me from going into deep sleep. Decreasing the volume helps but it helps only for the next ten minutes or so and then it feels too loud again. So, after sometime I need to stop playing the music and go to sleep peacefully without any music to disturb me. Decreasing the volume every five minutes or so and finally taking care to stop the player before sleeping is not a nice way to fall asleep.

I thought of writing a shell script to automate this so that I do not have to worry about the volume and the player. It occurred to me that I can make the computer tell me bedtime stories too. I needed two things to do it: a way to pause Rhythmbox from the shell and a way to decrease the volume as the night progresses. I found rhythmbox-client command to control Rhythmbox from the shell and aumix command to adjust the volume of the audio mixer. I used espeak command to read text files aloud.

So far, so good. How about asking the computer to wake me up in the morning? If the script can start the music player in the morning and increase the volume gradually, I'll have a morning alarm too.

Here is the script:

#!/bin/bash

# Bedtime story and lullaby cum morning alarm script.
# Susam Pal

# Falling asleep (0.5 hour)
espeak -a 100 -s 150 -f story.txt &
for volume in {80..51} 
do
    aumix -v $volume
    echo Reduced volume to $volume. 
    sleep 1m 
done

# Deep sleep (5 hours)
pkill espeak
rhythmbox-client --pause
echo Sleeping at `date`
sleep 5h

# Morning alarm (1 hour)
echo Waking up at `date`
rhythmbox-client --play
for volume in {41..100}
do
    aumix -v $volume
    echo Increased volume to $volume. 
    sleep 1m 
done

If you find espeak too electronic and monotonous, you can go for the festival command which can be configured to sound more human. To do this, you can just replace the line containing the espeak command with

festival --tts story.txt &

Of course, you need to replace pkill espeak with pkill festival as well.

I add the following code to my /etc/festival.scm file to set a good voice and a higher volume.

(set! voice_default 'voice_en1_mbrola)
(set! default_after_synth_hooks
    (list (lambda (utt) (utt.wave.rescale utt 1.0 t))))

The first line of code sets the voice to one that I like. The next two lines sets the volume I want. To see the list of voices available, run festival in interactive mode and run the (voice.list) command.

I bought a Seagate External Portable Drive a few days back as I have a lot of movie and music files now that require hundreds of gigabytes of disk space. When I connected it to my laptop running Debian GNU/Linux, I found that Debian was unable to mount it automatically as the file system was NTFS. I wanted to convert it to FAT32 so that I could use it across various operating systems without any hassles. I thought that I would do it next day at office where I had a laptop running Windows XP. But next day, at office, I found that Windows XP wouldn't give me an option to format the 320 GB portable drive as FAT32. The only option that appeared was NTFS. On searching the web, it seemed that I needed to use some third party tool to format a volume greater than 32 GB using the FAT32 file system on Windows. There are plenty of them available on the web. However, I decided to avoid the hassle of finding an appropriate tool (I was later told by a friend that 'fat32format' is a good tool for Windows). So, I decided to do the formatting using Linux. I am documenting the commands I had to run to do it in this blog post.

I ran the fdisk command to list the partition table and selected the relevant lines by piping the output through grep.

nifty:/home/susam# fdisk -l | grep ^Disk
Disk /dev/sda: 160.0 GB, 160041885696 bytes
Disk identifier: 0x0002ade8
Disk /dev/sdb: 320.1 GB, 320072933376 bytes
Disk identifier: 0x00225e47
nifty:/home/susam# fdisk -l | grep ^/dev/sdb
/dev/sdb1               1       38913   312568641    7  HPFS/NTFS

So, the output showed that /dev/sdb represents the 320 GB portable drive, /dev/sdb1 represents the file system on it and the file system is NTFS. So, I changed the file system to FAT32 using the fdisk command again.

nifty:/home/susam# fdisk /dev/sdb

The number of cylinders for this disk is set to 38913.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
(e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): b
Changed system type of partition 1 to b (W95 FAT32)

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.

Note that this time fdisk was invoked with the device file representing the portable drive as an argument. The t command at the fdisk prompt is used to change a partition's system ID. The system ID was entered as b which is the code for FAT32 file system. The w command is used to write the partition table to disk and exit.

Next, the disk was formatted with the FAT32 file system.

nifty:/home/susam# mkdosfs -v -F 32 -n Susam320GB /dev/sdb1
mkdosfs 3.0.5 (27 Jul 2009)
/dev/sdb1 has 255 heads and 63 sectors per track,
logical sector size is 512,
using 0xf8 media descriptor, with 625137282 sectors;
file system has 2 32-bit FATs and 32 sectors per cluster.
FAT size is 152547 sectors, and provides 19526004 clusters.
Volume ID is aa58f967, volume label Susam320GB.

The string following the -n option is the volume label for the volume. The volume label can of course be changed later using the mlabel command. This command comes with the 'mtools' package. The command can be used as shown below.

nifty:/home/susam# mlabel -i /dev/sdb1 -s ::
Volume label is Susam320GB
nifty:/home/susam# mlabel -i /dev/sdb1 ::Foo
The first command prints the existing volume label. The second one, changes the volume label to 'Foo'.

RSS