Mini-HOWTO: Linux-Windows serial file transfer


First, some background: I have an old Toshiba T4600 (the link points to a PDF) laptop: it has a 33 MHz 486DX processor, 4 MB of RAM and a 200 MB hard drive. It currently runs Windows 95, which was recently installed using a Gericom 5xC laptop: this one has a 500MHz Celeron, 64 MB of RAM and a CD drive. I usually run Puppy Linux on it, but I used it a couple of times to install FreeDOS and Windows 95 on the T4600’s hard drive.
The problem that I encountered was that Windows 95 simply refused to connect to the Gericom machine (running Puppy Linux 4.1.2 from a CD, with storage on a USB drive). I followed a HOWTO detailing how to trick Windows 95 into thinking the Linux machine is a modem and another one detailing how to set up a “Direct Cable Connection” between the machines. Neither yielded any result, so I started experimenting.

This HOWTO will detail what I found out: how to create a serial port connection between the two machines and how to transfer files using the Zmodem protocol.


Except the computers, you’ll need a serial (DB-9) null modem cable or adaptor. Find one at your local electronics store or make one yourself.

The server should run Linux (any distribution should work), although you can probably adapt the instructions, one way or another, for *BSDs.
The client should run Windows 95, 98, Me, 2000 or XP and have a copy of HyperTerminal (I think it’s bundled with those). Vista and above might work too (using Le Putty instead of HyperTerminal). I’ve only tested this on Windows 95 though, so no guarantees.
Oh, and the two machines should have serial ports, if, by any chance, you haven’t read the title.

Also, learn the Linux command line basics before attempting this HOWTO, or you’ll probably screw your system up.

Setting up the server, the hard way

EDIT (28/1/11): scroll down for an unbelievably easy alternative to this step.

Step zero: install Linux. I recommend Puppy Linux: it’s light, fast and can boot from a USB pendrive. If you’ll use Puppy, don’t forget to create a save file; you’ll have to restart to apply the init configuration, and you need a save file to keep your changes.
Note to Ubuntu users: Ubuntu uses Upstart instead of a traditional init, so these instructions won’t work. The same can be said for Ubuntu derivatives (Linux Mint, Pinguy OS etc.). To make a generalization: if /etc/inittab is empty, you can’t do this. Run Puppy from a persistent save instead.

Step one: become superuser. You usually do that with the su or sudo -i command. Note that you don’t need to do this with Puppy; you’re already logged in as root.

Step two: back up your inittab. cp /etc/inittab /etc/inittab.backup

Step three: open /etc/inittab using your favorite text editor. I typically use nano or gedit on Debian systems and geany on Puppy Linux.

Your inittab should contain lines similar to this:
tty0:2345:respawn:/sbin/getty tty0
After the last one that looks like that, add:
S0:2345:respawn:/sbin/getty ttyS0 38400
The line above basically says that for runlevels 2, 3, 4 and 5, init should invoke getty and tell it to open up terminal access on ttyS0, which is the equivalent of COM1 in Windows, running at baud rate 38400 (Zmodem seems to dislike anything higher). You might need to replace ttyS0 with whatever your serial port is called in Linux (e.g. ttyS1). Determining how your ports are labelled is beyond the scope of this tutorial. Oh, that’s an upper-case S; if you write a lower-case s it won’t work.

Beware that the line above might look different. On Puppy Linux, for example, you’d use this:
S0::respawn:/sbin/getty ttyS0 38400
Just follow the general layout of the inittab file and you should be fine.
After making the changes, use telinit q, init -q or just restart to apply the changes. In Puppy, restarting is your best bet.

Now that you’re done configuring your inittab, you’ll need to install lrzsz. For Debian/apt-based systems: apt-get install lrzsz. For Fedora/yum-based systems: yum install lrzsz. There’s a PUP package for Puppy here, you’ll need to install the dotpup helper using Puppy’s package manager first though. I might repack it into a proper PET package if I’ll have the required time and motivation.
EDIT: I packed the required binaries and symlinks and uploaded them here. Unpack the contents of bin/ into a directory in your path. On Puppy, that would be /root/my-applications/bin/.
That’s it. Get out of the root shell using exit.

Setting up the server, the easy way

Today (28/1/11), I tried doing as I wrote above, but failed for some odd reason. So I just typed this in a root shell:
/sbin/getty /dev/ttyS0 38400
And tried connecting as below. And it worked perfectly! I have no idea why I didn’t try this before. And the best part is, this might actually work on Ubuntu too!
(This was on Puppy (a custom puplet of 4.2.1, I believe). Don’t forget to also install lrzsz as described above.)
If it fails, you’ll either need to replace ‘getty’ with ‘agetty’ or something similar, or change the port (i.e. from ‘ttyS0’ to ‘ttyS1’ or something else). As a general rule, COM1 in Windows is /dev/ttyS0, COM2 is /dev/ttyS1 and so forth.

Setting up the client

This section was written with Windows 95 + HyperTerminal in mind. The same steps should apply to later versions (98, Me, 2000, XP) too.
1. Start HyperTerminal by running hypertrm.exe from the Run box or by finding it in the Accessories menu.
2. A dialog should appear, asking you for a name and icon for the connection. Fill in whatever you want.
3. Another dialog should appear, prompting you to enter a phone number. From the lowermost dropdown box, pick “Direct to Com 1”, “COM1”, “COM2” or whatever suits your machine.
4. The COM port properties dialog should pop up. Select the following:
Bits per second: 38400
Data bits: 8
Parity: None
Stop bits: 1
Flow control: Hardware
5. You should reach HyperTerminal’s main window. After the status bar shows “Connected”, just hit Enter to bring up the login prompt (if it’s not already there). Login with your username and password. If you’re using Puppy, log in with username “root” and password “woofwoof“.

Congratulations, you now have a connection between the two machines! Give yourself a cookie before proceeding with the next section.

Transferring files from Linux to Windows

All commands here should be executed from inside HyperTerminal.

To start a text file transfer from Linux to Windows:
sz -e /path/to/file
To start a binary file transfer (e.g. images, programs) from Linux to Windows:
sz -be /path/to/file
In both cases, replace /path/to/file with the… actual path to the file. D’oh.

A dialog should pop up, displaying the file transfer progress. As a note, the maximum possible speed at 38400 baud is 4.8 kilobytes per second. You’ll have to wait. A lot. You can try to increase the baud rate, but 38400 is the fastest I could get on my configuration.
Oh, and look at the dialog to see where it actually saves the file.

Transferring files from Windows to Linux

To transfer files the other way, run rz -e from HyperTerminal, then navigate to Transfer -> Send File… and select the file. It should get saved in your Linux home folder. That’s it. The end.


3 Responses to Mini-HOWTO: Linux-Windows serial file transfer

  1. samson says:

    old but gold, thx

  2. Pingback: Dual-booting Windows 95 and 3.11 « Andy C.'s weblog

  3. Pingback: Floppies rock, provided you can write them « Andy C.'s weblog

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s