Archive for the ‘tinkering’ Category

Python, Telnet and GUI-fying Legacy Apps

Wednesday, November 12th, 2008

Today I want to talk about telnet. Yes, telnet is stupid and you should use ssh. Sometimes you can’t though. For example if there is some old legacy app that is sitting on some remote server that is not even yours and the only way to interact with it is via telnet session. We have one of these things at work – it is a little app running on a mail server that allows people to set up an auto-reply message when they go on vacation.

In theory this is something that every user should be able to do themselves. The instructions are simple enough. Go to Start, Run, paste this telnet command into the box, hit enter, follow prompts on the screen. The interface is easy to use, if a little clunky. I never had any issues with it. And yet, no one ever wants to deal with. That black window with the dreaded blinking cursor is incredibly scary it seems. Most people call the help desk and request a message to be set up for them instead. This is not the end of the world, but it’s backwards. This system does not have a main administration panel where we could set these things up from above. So when someone calls in with a request, the helpdesk must actually telnet to the system and use their username and password.

So I started thinking if we could dumb-down this process enough to make it accessible to our average luser. The idea was to have a GUI layer shielding the user from the scary telnet stuff. I hacked up a tiny little prototype app in Python and it looked a bit like this:

auto_reply.JPG

It is very simplistic – kinda ugly actually. It’s Python using the Tkinter widgets for GUI-fication. It is less than 30 lines of code once again demonstrating that Python can be very terse and concise language despite it’s strict whitespace regime – even when coding GUI apps. Observe:

from Tkinter import *
class AutoReply:
   def __init__(self):
      self.root = Tk()
      self.root.title("DG Auto Reply Tool")
      self.root.resizable(0,0)
 
      self.text = ""
      self.email = StringVar()
      self.onoff = StringVar()
 
      self.reply = Text(self.root)
      self.reply.grid(row=0, column=0, columnspan=5)
 
      eml = Entry(self.root, textvariable=self.email)
      eml.grid(row=1, column=0)
 
      status = Label(self.root, textvariable=self.onoff)
      status.grid(row=1, column=3)
 
      button = Button(self.root, text="Update", command=self.update)
      button.grid(row=1, column=1)
 
      toggle = Button(self.root, text="Auto Reply:", command=self.toggle)
      toggle.grid(row=1, column=2)
 
      self.root.mainloop()
 
   def update(self):
      pass
 
   def toggle(self):
      pass
 
if __name__ == "__main__":
   app = AutoReply()

This is what Python is good at – creating usable software really fast. Next step was to figure out how this GUI layer would communicate with the telnet application. I started thinking about sockets and streams and all that fun stuff. That was my first instinct – just open a socket and dump messages to it and try to see if I can get anything back. I did something like this before, and it was a lot of tedious coding just to get the communication between the client and server. Of course I was using Java to do it, which means there was a lot of tedious coding there in general.

Python on the other hand ships with a built in telnet library (aptly named telnetlib) and all you really need to do to connect to a server and start sending messages is this:

I didn’t want to do all of that.

import telnetlib
 
HOST = "my.remote.host"
PORT = 1337
user = "my-username"
password = "my-password"
 
tn = telnetlib.Telnet(HOST, PORT)
 
tn.read_until("login: ")
tn.write(user + "\n")
tn.read_until("Password: ")
tn.write(password + "\n")

You just follow this pattern for all your other interactions with the server. You read_until and then you write and etc. I abstracted this into a tiny self contained class, and made my GUI initialize it in the constructor and then call it every time it needed to send or receive data. I kept it simple – each transaction was self contained, connecting to the server, logging in, interfacing with the app and then disconnecting. This way I didn’t have to worry about keeping the connection alive, timeouts, disconnects and could pretty much rely that the app running on the server will be in predictable state when I connect to it.

The rest was just a bit of creative screen scraping. The read_until method returns a string, which I could break into lines, and then parse each line to extract the information I needed. It was pretty easy to isolate the important data and discard everything else. I’m not going to post the code here because it is really customized to the particular application, and thus probably useless to most people.

The GUI works pretty well, but it is synchronous – it will block until the read/write transactions are accomplished which is probably not the worst thing that could happen. I’m pretty sure I could do it asynchronously but it would take more effort and make no huge impact on usability. The blocking as it is right now actually works like a feedback mechanism that shows the user when sending and receiving is taking place.

My app is actually more user friendly because it allows you to edit the message as a whole in a familiar editor window. The telnet app forces you to type the message line by line. The only way to change a line already in place is to delete it, append new line to the end of the message and then move it up one line at a time until it is in the right place. Oh, and pressing backspace inserts the lovely ^H instead of actually deleting the character. So the GUI is much friendlier and I deal with the craziness by simply nuking the message and then re-inserting it every time the user clicks on update.

I haven’t unleashed it on unsuspecting users yet – it’s still buggy and unfinished. I’m just throwing it out here to show how easy it is to hack things like that together with just a little bit of Python. The complete app is tiny (only slightly over 100 lines of code – including white space). The only problem is that most of my users are not running Python. This of course could be solved by using py2exe but then I’m basically converting 3KB of python into 30 MB of crap. Not a perfect solution there. I could either deploy python, ship the app as a huge native package, or rewrite it in C#. What would you do?

Using Spare Laptop LCD as a VGA Monitor

Monday, March 31st, 2008

We have bunch of old broken laptops lying around at work. Most of them are unusable, but I don’t like to throw them out because they are a great resource of spare parts. Sometimes I’m able to dig in that pile and use stuff like display hinges, bezels, arm rests, touch pads and etc to quickly fix some of the older machines that are still floating around. Naturally all these machines have been stripped out of memory, hard drives and CPU’s long time ago. One thing that doesn’t get replaced that often are LCD’s. There is probably 6 or 7 displays like the one below in that pile.

Spare Laptop LCD

They are just sitting there and not doing anything constructive, so I started thinking about putting them to a good use. There is another problem I often face – lack of spare monitors. Every time someone brings in a desktop for service we have to go an pull a monitor from one of the currently unused machines available in the office. Which is not the end of the world, since I usually have some flat surface available to set it all up.

Sometimes however a friend or relative brings their machine to my house asking for help. This is where the fun begins. I do have a spare CRT up in the attic that I keep for just hat occasion. What I don’t have is space. When I’m fixing someone’s computer you will usually see a scene of pure mayhem on the floor of my room:

Family Tech Support

I’m usually forced to squeeze the old CRT, the desktop, the keyboard and mouse in the tiny little amount of free space between the bed and the TV, and essentially sit with my back wedged against my desk, occasionally turning around to Google something on my desktop in the back. I could buy a LCD screen, but even a tiny 15″ cheepo sells for almost $200 at neweg – which seems a bit high for something that I would use twice a year, and then stash in the attic or at the bottom of some closet.

This is where the two needs begin to merge: my need to do something useful with the spare laptop LCD’s and my need for ultra-small portable LCD screen. I figured that if I could find an Laptop LCD to VGA adapter I would be all set. Or not…

It turns out that I’m not the only person who had this brilliant idea. Unfortunately, it turns out that it is not as easy as one might think. The laptop LCD has a digital output that is designed to pin into a controller circuit which in turn talks to the video card. These things are mostly proprietary, not standardized and not widely available. The difficult part is figuring out exactly what kind of controller circuit do you need, then locating and ordering one. It’s definitely possible though.

For example, I have found this blog describing the process. Unfortunately it is very light on technical details to the point of being relatively useless. It’s more or less photographic proof that it is possible, but not much more:

dyilcd.jpg

The last entry is particularly discouraging – apparently the merchant who was supplying the circuits used in the example no longer produces them, and is currently out of stock. :(

A slightly more informative but less complete post can be found on the mp3car forum. They actually post a link to a vendor who seems to have quite a few different models for sale. There are two caveats though – the vendor seems to be located in Europe, and they only sell in bulk (100 units of more) which makes them useless as a resource. I found few others but none of them was really selling anything online.

Then I remembered a piece of old internet wisdom – if it exist, someone is probably selling it on ebay. Believe it or not, I found some interesting looking kits for sale. Here is a closeup pic of one of them:

tft_lcd_panel__back_light_1.JPG

It is a TFT LCD controller with a back light inverter, which seems to be exactly what I would need. It also looks astonishingly simillar to what the dude in the first blog I linked to was using. Good news is they seem to be selling for $35 + shipping and handling (which will probably be another $30 or more knowing these types of ebay stores). So I’m tempted. It could work, provided that my LCD is one of the models supported by this device and that there are no funky drivers required to actually run this thing.

Anyone ever did something like that? Should I do it? It could make for a nice, space saving, ultra portable monitor, provided that I could find a semi-decent frame to mount the circuit and LCD…

Ubuntulite: Problems Running Feisty on Old Hardware

Thursday, September 20th, 2007

While I was moderately happy with Fluxbuntu, I decided to give Ubuntulite a shot. It sounded like a great idea – the most basic of basic systems, with minimal Openbox setup on top of it. Fluxbuntu still seemed to exhibit some strange bloat here and there, and a very stripped down system seemed exactly what my old junky Presario 1240 needed.

Ubuntulite Logo

So I followed the Ubuntulite instructions to the iota and got the system on my machine. It’s very spartan, and rough around the edges, but hey – that’s what I wanted, wasn’t it?

But I run into a heap of issues with this installation. And I’m not really blaming Ubuntulite team for this. I think this is sum of unfortunate software choices, and inherit Feisty issues. My biggest issue was the strange shit that was happening on boot time. Every time I would power up this machine, I would get the following lovely message:

[ 0.000000] ACPI: Unable to locate RSDP
Loading, please wait...
kinit: name_to_dev_t(dev/disk/by/uuid/the-long-uuid-goes-here) = hda5(3,5)
kinit: trying to resume from /dev/disk/by/the-long-uuid-goes-here
kinit: No resume image, doing normal boot...

The machine would actually hang and wait about a minute on the Loading prompt before displaying the kinit messages and resuming boot sequence. Apparently, this issue has not one but at least two bug reports on launchpad already #103148 and #105316 and neither one has been resolved. There is also this thread in the Ubuntu forums about it. I followed all the proposed fixes and nothing worked. This was not a show stopper, but an annoyance.

I finally resolved it by following the instructions here, but instead of using the UUID’s I actually modified my fstab to use standard notation like /dev/hda5. If you are to lazy to follow the link and try to figure it out on your own, here is what you do. In your /etc/fstab you will see the following line for swap:

#/dev/hda5
UUID=the-swap-partition-uuid-number-here	swap	sw	0	0

Delete the UUID bullshit and change it to:

/dev/hda5	swap	sw	0	0

Now open your /etc/initramfs-tools/conf.d/resume. It will have a long UUID listed there. Get rid of it, and replace it by simple:

RESUME=/dev/hda5

Once that is done, do:

sudo update-initramfs -u

Note that this will take around 17 million hours when you are on slow hardware, so just be patient. Once it is done, sudo reboot now. Problem solved – at least for me. Your millage may vary.

To get rid of the ACPI error I just modified my GRUB entry to add acpi=off noacpi at the end of the kernel string. Go to your /boot/grub/menu.list and find the part where it lists all the bootable entries. Find the line that specifies the kernel – it will look something like this:

kernel	/boot/vmlinuz-version.number root=/dev/hda2 ro quiet splash elevator=cfq

Slap the aforementioned string at the end like so:

kernel	/boot/vmlinuz-version.number root=/dev/hda2 ro quiet splash elevator=cfq acpi=off noacpi

This is an old POS laptop, and none of the distros I tried could figure out the ACPI stuff for it. I kinda gave up on that stuff. I mean, there is no point in loading it if it won’t work on this machine anyway, no?

The rest of the boot was working ok, but I noticed bunch of things there that I can probably shave off to save time – like fetchmail, CUPS and etc.

Openbox configured itself pretty well, but with two odd quirks. First one would only show up when you switched to a TTY using the Alt+Function Key shortcut and then go back to X. The display would become inexplicably dim and dark. Almost as if someone turned down the brightness on your monitor down to the lowest setting – but only when displaying X. All the other terminal screens looked fine. Killing X and restarting it solves the problem. I’m suspecting this is some oddball vesa quirk. Fluxbuntu did not seem to have this issue. :(

Any idea why this happens and how to fix it? Once again, this is not a show stopper – just annoying as hell.

The most bizzare quirk however was the odd Openbox numlock behavior. The Presario 1240 is a laptop, and as many mobile machines it as one of those Fn keys and no numeric keypad. In a half assed attempt to provide customers with one, Compaq decided to use combos like Fn+J through L to mean 1-3 thereby re-using the whole right side of the keyboard as the numpad.

When logged into Openbox, it forces NumLock to the on state and so my keyboard would actually use these alternate values for all the “fake-numpad” keys. So pressing K would actually type 2, pressing P would trigger a minus sign and etc. I could still get the “normal” letters by holding down the Fn key as I press them but that was just plain stupid. External keyboard would work normally, and pressing NumLock on it would “fix” this issue on the built in keyboard as well.

Quickly swiching to a TTY and back would do the same. But then I’d have to deal with that dark-vision effect so that was not a good solution either. Why wouldn’t I just hit NumLock on the laptop keyboard? Oh, probably because I fucking couldn’t. You see – NumLock on that keyboard is one of these special keys that can only be accessed while holding Fn key. And for some reason, it would just not work. Whooptie do!

Fortunately, it seems that I’m not the only person experiencing this issue, and there is a quick software fix for this behavior called numlockx:

numlockx off

The downside of this is that you have to run this command every time you boot into X. I’ll have to figure how to plug this command into the openbox boot sequence, along with commands to start the fbpanel and xsetroot into something not ugly. Care to point me in the right direction? I still haven’t gotten around to customizing my environment this way.

Its strange, but none of the other distros I used really touched NumLock. Go figure.

Btw, I’m not saying Ubuntulite is bad I actually I kinda like it. Being rough around the edges is kinda their aim, so I can’t complain about that. And the fact it doesn’t pus any given setup GUI setup on you let’s me experiment with different lightweight components and create an environment I’m happy with. Most of my problems seem to be Feisty related – rather than Ubuntulite specific. Dapper was rock solid on this machine. Feisty is a tad flaky as you can see from the issues above. I will play around some more with this system. I think I solved most of the jarring issues, and the rest will probably just fall into places soon. If it continues being flaky, and pisses me off I will probably scrap this installation and try Vector or Wolvix at some point. We’ll see.

Update 09/23/2007 11:44:03 AM

Just to clarify – Ubuntulite is still in a very early beta stage. It’s in no way a finished product. I’m not really bashing the distro – just pointing out minor issues I encountered with the early version. If you download it now, it will be more polished and usable than when I got it because they just released a new version. :) I think this will be a really good distro for old hardware once it matures a bit and reaches a stable state.