	Porting hints for gnuucp

	John Gilmore
	19 February 1990

Gnuucp should be a lot easier to port than its predecessor, uuslave.
The routines that should need changing on different systems have
been broken out into separate files to make it easy to see what
to work on.

Before doing much work with gnuucp, I found it best to print it out and
actually read it; it has formfeeds and block comments at strategic
points to make it more readable.  Mark up your listing where you have
questions or comments, and later, go through it and send them to me.
Or edit in more comments and questions about unclear places as you port
it.  As I merge your diffs into the master source, I'll either leave
the questions, or answer them with more comments there.

Porting the code to a Unix system should be little effort.  Porting
it to another operating system should be doable, but more work.
Most of gnuucp is invariant code, but you'll need to hack on the
parts that do serial I/O to the modem, and the parts that talk
to the file system (typically file names need to be munged to fit
in the obscene limitations of the average non-Unix operating system.)

All the code that should need to change has been isolated into two
files:  includes.h  and  sysdep.something.  Say you are doing a port
to the brand new WHIZZO personal computer.  You'll need to insert
a block of #include's and definitions into the file "includes.h",
something like this:

	#ifdef WHIZZO
	#include <stdio.h>
	#include <......>

	#define	SPOOLDIR	":uud:spool:uucp:duuh"
	#define NAMELEN		FN_MAXLEN
		...etc...
	#endif

You can use the existing examples in "includes.h" to figure out most
of what you need to include.  The rest will be found by trial and
error as you try compiling it and find undefined symbols.  Then you
have to figure out how gnuucp gets that symbol defined on other systems,
and how to get its definition on your system.

Then you would make a file called sysdep.whizzo which will probably
start out as a copy of one of the other sysdep.something files.
(Sysdep.unix is likely to be the most complete, since the master
sources are kept and maintained on a Unix system.)  Work it over until
it looks like it will do the job on your system.  The definition of
what the rest of gnuucp is expecting these routines to do is in the
file "sysdep.h".  If in doubt, see how other ones did it, or look at
the sources in the various .c files that call the sysdep routines.  Once
gnuucp has been ported to a bunch of systems, you shouldn't need to
change gnuuio.c or gio.c to do a port to a new system.  You definitely
shouldn't need to change the interface to the sysdep routines -- since
such a change breaks all the other sysdep.something files.  Currently
there are still a few system dependencies in the "common" files, and
the system-dependent/system-independent interface is probably not
complete.

To compile gnuucp, you will need to make a symbolic link between
sysdep.c and sysdep.whizzo.  (The Makefile compiles sysdep.c.)  If your
system doesn't have symbolic links, it's probably best to just move
sysdep.whizzo to sysdep.c and work on it there.

If you want to port gnuucp, download it to whatever system you are doing the
port on, and get it to compile.  Don't even make it run.  Then upload
the sources to a Unix system, if necessary, and mail me the new
includes.h and sysdep.whizzo, and any changes to other files, that
make it compile OK.  That way I will get a bunch of these diffs and
even if you get hung up in the next step and never send me anything
else, other people trying to port it won't have to straighten out the
include files and such.  Best way to make diffs is to save a pristine copy
of the gnuucp directory that this file came from (call it, say, gnuucp.dist),
and use the Unix diff command to compare the contents of that directory to
your modified directory, e.g.:

	diff -c gnuucp.dist gnuucp > diffs

(or just "diff" if -c doesn't work on your Unix).  I can then use the
"patch" program to merge your changes into my main sources.  If you
don't have a Unix diff program, just send me back the FULL SOURCE; it
will be easier and less error prone than me trying to merge your stuff
in by hand.  In fact, if you send me more than about 10 lines of
changes in some odd form (like VMS compare output, or Minix diff) I'll
just throw them away.  I'm a volunteer, remember...and I didn't
volunteer for manual labor when there are easier ways.

Once you've sent me back your diffs (or a note saying it compiled
without any changes), go ahead and debug it and hack it and slash it
and make it write bad checks.  Try to resist the temptation to reformat
the whole source into your favorite form -- it makes it very tough to
figure out what it is you changed.  Try to leave the tabs and the
formfeeds where they are.  Also resist putting a fancy user interface
on it (e.g. windows and stuff) -- first, make it run, then later, make
it pretty.

The code is instrumented with lots of debug options.  You can set
a debug level with the -xN command (N a number); higher numbers give
more and more output.  You can also set a default debug level in the
"gnuucp.ctl" file.

I've been compiling with -DBSD (for BSD Unix), and -DSUBDIR (for a file
name munging hack that makes it compatible with 4.2BSD and Sun Unix
uuxqt, when both are running on the same machine).

Once you have it compiled on the target system, hook up a 1200 baud
terminal to a serial port on the target machine.  Run gnuuio with the
name of the serial port as its argument.  It should give you a "login:
" prompt, which you can respond to with "uucp".  If it sees this
string, it should prompt "Password:" and you can type the password (see
the strings msgo0-5 and msgi0-4 in gnuuio.c).  This should get you a
response of "Shere" which means that gnuuio is trying to initiate the
uucp protocol.  You won't be able to test the packet protocol with a
terminal, but you can test the serial I/O code and the timeouts, which
will probably be the hardest part of this port.  (It should time out
after 60 seconds of no-data-received and go back to waiting for someone
to log in.)  Make sure you have this working before you do the next
step.

When you can "log in" to gnuuio by typing on a terminal on gnuuio's
serial port, STOP THERE!  Upload that ol' source to Unix again (NOT via
gnuuio!) and send me your code.  RESIST the temptation to have Unix
call it up.  If you get Unix to call, it will fail and then you'll want
to debug it.  I've been through this, I know what it's like!  Send in
your diffs first.

(What follows is no longer fully accurate; now you can have gnuuio try
to dial out to a remote Unix system, and there's a good chance that from
watching your debug output, you can debug it even if you aren't
logged in to the remote system watching what is going on.)

Debugging it with Unix requires a lot more setup.  You'll need a
terminal logged into Unix, so you can watch what Unix is doing, and a
link between your micro and the Unix system (either a hardwired serial
line, or a dialout modem on the Unix machine and a dialin modem on the
micro).  Also, having access to the console of the micro so you can see
the debug output, recompile, etc is essential.  Having all this stuff
in front of you, rather than in different rooms, is very useful.

Once you've set this up, you can get it to actually work with a Unix
system.  Leave gnuuio running on the micro, and get the Unix machine
to call it up -- talk to the Unix system administrator about how to
run uucp on your Unix machine.  The administrator will need to add a
line to your L.sys or Systems file to tell uucp how to call your micro.
Here is an L.sys line that works to talk to it:

gnuucp Any ACU 1200 5551212 in: uucp word: s8000

Insert your micro's modem phone # in the place of 5551212.  If you are
using a hardwired line, you'll have to fix this line, and also change
L.devices or a similar file.

On the Unix machine, you can then do

	/usr/lib/uucp/uucico -r1 -sgnuucp -x9 &

to cause it to call the micro and log what it sees at your terminal.
(-r1 says uucico should be the master; -sgnuucp says which system to
call; -x9 sets the debug level to 9, meaning "tell me everything".)
Get it to where Unix can "log in" to the micro and they can
send INITA, INITB, INITC, and then a few data packets negotiating
about hanging up the phone (sending "H" and "HY" packets), then work
on being able to move files.  See the "uucp(1)" man page of your Unix
system, and talk to the system administrator about how uucp works.

Once it can call in, talk, and hang up, you should queue up a file to
be sent from your Unix system, and have it call your program again.
See if the file gets there, etc.  Do checksums on the file before and
after.  Transfer the file back to Unix (using kermit or xmodem or
something) and compare the two.  Make sure that the file is exactly the
same on both ends.  Then queue up a file to be received from your micro
to your Unix system and call up gnuucp to try that.  When both work,
great!  SEND ME MORE DIFFS and buy champagne.  You have a gnuucp that
actually can move files in the presence of no errors on the phone
line.

When you've done that and sent the diffs, try plugging in another phone
on the line it's using, while it moves a file, and pushing the
touchtone buttons or drumming your fingers on the microphone, or
otherwise making noise on the line so it will have to retry a few
times.  Make sure it doesn't get stuck anywhere when you do this; it
should pause a bit, then the Unix side should send another packet and
they should get back into sync.  You can see this happening in the
modem lights, or in the debug output of gnuuio.  Do this a few times,
then leave the poor programs alone and let them finish moving that
file.  Then make sure that the file you moved over through all that
noise came out just the same as it started.  I had a bunch of bugs in
this area, you might find some more.  When you have that working (which
might work on the first try, but be sure you injected a lot of noise at
random points, and really saw it retry), then send in more diffs!  You
have successfully ported it.

You can go on to debugging the master mode, where it calls out on
the phone line.  I'm not going to go into that right now.  You can get
it to call out before you have your file system stuff working by writing
a kludge version of work_scan in sysdep.whizzo like this:

	int
	work_scan(a, b)
		char *a, *b;
	{
		return 0;
	}

This will tell it that there is no queue of work, which indeed there
isn't.  To make it actually move files, you have to get the "uucp"
and "uux" commands working -- see uux.c and uucp.c.

If you run out of things to do, look in the file BUGS for suggested things
to work on.

You can search for the strings FIXME in the sources.  I've marked various
places with it, which I noticed will need further work.  Feel free
to work on these places and send me back the changes, or to add more
FIXME comments about bad or fragile code that you notice.

I have marked my sources as copyright by the Free Software Foundation,
distribution via the GNU General Public License.  If you give sources
out, with no conditions, you have satisfied the license.  If you never
give out sources or binaries to anybody else, you have also satisfied
the license.  A full copy of the license is in the file COPYING that
comes with gnuucp.  If this copy is missing, you can get one by writing
to:

	Free Software Foundation
	675 Mass Avenue
	Cambridge, MA  02139  USA

or by electronic mail from gnu@prep.ai.mit.edu.

If you make significant changes to gnuucp and we adopt them into the
master sources, we will want to get a copyright assignment from you, so
we can protect users of gnuucp in court by suing abusers for copyright
violation.  (A case like this was already settled out of court when someone
tried distributing binaries of gnuucp and refusing to provide sources.)

Read the uucp protocol documentation.  It's vital for understanding
what this code is doing down in the guts, though most of you
won't have to understand the guts (gio.c).  The best part is Greg
Chesson's paper explaining the packet protocol (packet.driver.ms),
which you can format with "nroff -ms packet.driver.ms" or "troff -ms
packet.driver.ms".  You can also just read it as-is, though you
have to ignore a lot of formatting commands.  There is also "Protocol.doc"
which describes the higher level protocols (implemented in
gnuuio.c) in some detail.

Earlier versions of this code have been run in production between
hoptoad and lll-crg for several weeks, and much later versions are now
being used to gateway uucp mail to and from FidoNet mail.  But the
current release is definitely an alpha test release, I find something
new to fix in it every day that I run it.

Good luck...

	John Gilmore

Copyright 1990 John Gilmore; distribution via GNU General Public License.
{sun,pacbell,uunet,pyramid,amdahl}!hoptoad!gnu               gnu@toad.com
