UUSLAVE.c
mjranum at osiris.UUCP
mjranum at osiris.UUCP
Fri Feb 6 10:09:10 AEST 1987
This is the mangled version of uuslave. I've fixed some parts, and
done my best to provide machine independence. The job is probably
not complete, but it will compile OK on a PC with Lattice C, as
well as a SUN workstation. (from the ridiculous to the sublime, eh ?)
Anyhow, this is code "as is". It may need some work. If I was a
dummy anywhere, flame me personally, don't E-mail to the net.
--mjr;
-------------fold here-------------
/* uuslave.c - client uucp(R) connection */
/* (uucp is copyright AT&T) */
/* this is designed to run on IBM PCs w/ */
/* a modem or direct connection to UNIX */
/* no guarantees of functionality... */
/* original author ? */
/* very extensive and brutal hacks by Marcus J Ranum */
/* I take no responsibility for the working code here. */
/* all the comments (for what they're worth) are mine) */
/* I added all the incremental debug information stuff */
#include "stdio.h"
#include "signal.h"
/* if your system does not support signal, comment all */
/* references to signal out and it may still work. */
#define O_RDONLY 000 /* open for reading */
#define O_WRONLY 001 /* open for writing */
#define O_RDWR 002 /* open for read & write */
/* mysterious numbers that are possibly CP/M specific. */
/* they are used as masks for file I/O */
#define CLOSE 1
#define CTRL 0
#define LNGDAT 2
#define SHTDAT 3
#define MAGIC 0125252
#define EOT 4
#define RR 4
#define INITC 5
#define INITB 6
#define INITA 7
int sigint ();
int abort ();
char *strcat ();
char *strcpy ();
long lseek ();
extern errno;
int wndsiz = 1;
int segsiz = 1;
/* these are used later as buffers for ttynames, etc, etc, etc. */
char msgi[256],
msgo[256],
cmnd[8],
srcnam[32];
char dstnam[32],
dskbuf[256],
msgbld[256];
/* fdtty is terminal file descriptor */
/* fddsk is disk file descriptor */
int fdtty,
fddsk;
/* I believe these are the message sequence numbers */
int tt,
xxx,
yyy,
rseq,
wseq;
/* this is the communications device/port/whatever */
char *ttynam;
/* error log file name, debug flags, etc.*/
FILE * errfile;
char *errlog;
int errflg;
int debugmode = 0;
/* these next few strings are strings uucp expects to see. */
/* they shouldn't need changing */
/* messages that get sent out */
char *msgo0;
char msgo1[] = "Password:";
char msgo2[] = "\20Shere\0";
char msgo3[] = "\20ROK\0\20Pg\0";
char msgo4[] = "\20OOOOOO\0";
char msgo5[] = "...abort...";
/* messages that are read in */
char msgi0[] = "uucp\n";
char msgi1[] = "s8000\n";
char msgi2[] = "\20S*\0";
char *msgi3;
main (argc, argv)
int argc;
char *argv[];
{
char *p;
int data,
ttisflg,
unamflg,
themflg,
count;
errflg = ttisflg = 0;
unamflg = themflg = 0;
errlog = "uuerr.log";
/* mjr - this part completely mine. original version did not */
/* give a damn about arguments */
/* we try to remove compiled-in dependencies (ugh) */
for (count = 1; count <= argc; count++) {
if (argv[count][0] == '-') {
switch (argv[count][1]) {
/* line name */
case 'l':
case 'L':
if (strlen (argv[count]) > 2) {
ttynam = &argv[count][2];
ttisflg++;
}
break;
/* error log file (default is uuerr.log) */
case 'e':
case 'E':
if (strlen (argv[count]) > 2) {
errlog = &argv[count][2];
}
break;
/* this system's name */
case 'h':
case 'H':
if (strlen (argv[count]) > 2) {
unamflg++;
msgo0 = &argv[count][2];
}
break;
/* the other systems name */
case 's':
case 'S':
if (strlen (argv[count]) > 2) {
themflg++;
msgi3 = &argv[count][2];
}
break;
/* turn on debug */
case 'x':
case 'X':
debugmode = atoi (&argv[count][2]);
if (!debugmode)
debugmode++;
break;
/* options */
case 'o':
case 'O':
fprintf (stderr, "uuslave options: \n");
fprintf (stderr, "(mandatory) -ldevicename\n");
fprintf (stderr, "(mandatory) -hhostname\n");
fprintf (stderr, "(mandatory) -stheirname\n");
fprintf (stderr, "errlog -efilename\n");
fprintf (stderr, "debug -x#\n");
fprintf (stderr, "options -o\n");
exit (-9);
default:
fprintf (stderr, "uuslave:invalid option %s\n", &argv[count][1]);
exit (-1);
}
}
}
if (!ttisflg) {
fprintf (stderr, "uuslave: ");
fprintf (stderr, "MUST specify line with -l<line> flag\n");
exit (-1);
}
if (!themflg) {
fprintf (stderr, "uuslave: ");
fprintf (stderr, "MUST name other system with -s<name> flag\n");
fprintf (stderr, "(use the name they will try to login as)\n");
exit (-1);
}
if (!unamflg) {
fprintf (stderr, "uuslave: ");
fprintf (stderr, "MUST specify this system name with -h<name> flag\n");
fprintf (stderr, "(use the name they are trying to log in to)\n");
exit (-1);
}
if (debugmode) {
fprintf (stderr, "using line %s to communicate.\n", ttynam);
fprintf (stderr, "expecting them to log in as %s.\n", msgi3);
fprintf (stderr, "this system name is expected to be %s.\n", msgo0);
fprintf (stderr, "error log file is %s.\n", errlog);
}
/* open the communications device/tty for read/write */
if ((fdtty = open (ttynam, O_RDWR)) < 0) {
printf ("Cannot open %s for read/write %d\n", ttynam, errno);
exit (1);
}
if (debugmode > 3) {
printf ("opened %s read/write\n", ttynam);
}
/* trap interrupt to close communications line */
signal (SIGINT, sigint);
while (1) {
if (debugmode) {
puts ("restarting\n");
}
rseq = 0;
wseq = 1;
/* wait for EOT */
while ((data = xgetc ()) == EOF || (data &= 0x7F) != EOT);
if (debugmode > 6) {
puts ("got EOT\n");
}
/* output login request, verify uucp */
write (fdtty, msgo0, sizeof (msgo0) - 1);
if (instr (msgi0, sizeof (msgi0) - 1))
abort ();
if (debugmode > 3) {
puts ("requested and got login\n");
}
/* output password request */
write (fdtty, msgo1, sizeof (msgo1) - 1);
if (instr (msgi1, sizeof (msgi1) - 1))
abort ();
if (debugmode > 4) {
puts ("requested and got password\n");
}
/* output system here message, wait for response */
write (fdtty, msgo2, sizeof (msgo2) - 1);
if (instr (msgi2, sizeof (msgi2) - 1))
abort ();
if (debugmode > 6) {
puts ("sent and got system here name\n");
}
/* output ok message, protocol request, wait for response */
write (fdtty, msgo3, sizeof (msgo3) - 1);
if (instr (msgi3, sizeof (msgi3) - 1))
abort ();
if (debugmode > 6) {
puts ("sent OK\n");
}
/* output inital message, wait for response */
ctlmsg ((INITA << 3) | wndsiz);
if (inpkt () || tt != CTRL || xxx != INITA)
abort ();
if (debugmode > 6) {
puts ("sent initial message\n");
}
/* output initb message, wait for response */
ctlmsg ((INITB << 3) | segsiz);
if (inpkt () || tt != CTRL || xxx != INITB)
abort ();
if (debugmode > 6) {
puts ("sent initb message\n");
}
/* output initc message, wait for response */
ctlmsg ((INITC << 3) | wndsiz);
if (inpkt () || tt != CTRL || xxx != INITC)
abort ();
if (debugmode > 6) {
puts ("sent initc message\n");
}
/* output initial acknowledge, wait for command */
ackmsg ();
while (1) {
if (inpkt () || tt != LNGDAT) {
intf ("OVER EIGHT");
abort ();
}
strcpy (msgbld, &msgi[6]);
while (strlen (&msgi[6]) == (segsiz + 1) * 32) {
ackmsg ();
if (inpkt () || tt != LNGDAT) {
intf ("OVER ABORT SEVEN");
abort ();
}
strcat (msgbld, &msgi[6]);
}
switch (msgbld[0]) {
case 'S':
sscanf (msgbld, "%s %s %s", cmnd, srcnam, dstnam);
p = dstnam;
if ((fddsk = creat (p, 0644)) >= 0) {
ackmsg ();
if (lngput ("SY", 2)) {
intf ("OVER NINE");
abort ();
}
do
if (inpkt ()) {
intf ("OVER TEN");
abort ();
}
else
switch (tt) {
case LNGDAT:
write (fddsk, &msgi[6], ((segsiz + 1) * 32));
ackmsg ();
break;
case SHTDAT:
if (msgi[6] & 0x80) {
intf ("OVER ELEVEN");
if (debugmode) {
puts ("short packet error");
}
abort ();
}
else {
if (msgi[6] != (segsiz + 1) * 32)
write (fddsk, &msgi[7], (segsiz + 1) * 32 - msgi[6]);
ackmsg ();
}
break;
default:
intf ("OVER TWELVE");
abort ();
}
while (tt != SHTDAT || msgi[6] != (segsiz + 1) * 32);
close (fddsk);
if (lngput ("CY", 2))
abort ();
}
else {
ackmsg ();
if (errflg) {
if (errfile = fopen (errlog, "a+")) {
fprintf (errfile, "Cannot write %s errno%d\n", p, errno);
fclose (errfile);
}
}
sprintf (dskbuf, "SN%d", errno);
if (lngput (dskbuf, strlen (dskbuf)))
abort ();
}
break;
case 'R':
sscanf (msgbld, "%s %s %s", cmnd, srcnam, dstnam);
p = srcnam;
if ((fddsk = open (p, O_RDONLY)) >= 0) {
ackmsg ();
if (lngput ("RY", 2))
abort ();
do
if ((count = read (fddsk, dskbuf, ((segsiz + 1) * 32))) == (segsiz + 1) * 32)
if (lngput (dskbuf, (segsiz + 1) * 32))
abort ();
else;
else
if (shtput (dskbuf, count))
abort ();
while (count);
close (fddsk);
do
if (inpkt ())
abort ();
while (tt != LNGDAT);
ackmsg ();
}
else {
ackmsg ();
if (errflg) {
if (errfile = fopen (errlog, "a+")) {
fprintf (errfile, "Cannot read file %s errno:%d\n", p, errno);
fclose (errfile);
}
}
sprintf (dskbuf, "RN%d", errno);
if (lngput (dskbuf, strlen (dskbuf)))
abort ();
}
break;
case 'H':
intf ("IN H CASE");
if (lngput ("HY", 2)) {
intf ("OVER ABORT ONE");
abort ();
}
if (inpkt () || tt != LNGDAT) {
intf ("OVER ABORT TWO");
abort ();
}
if (!strcmp (&msgi[6], "HY")) {
ctlmsg (CLOSE << 3);
do
if (inpkt ()) {
intf ("OVER ABORT THREE");
abort ();
}
while (tt != CTRL && xxx != CLOSE);
write (fdtty, msgo4, sizeof (msgo4) - 1);
instr (msgo4, sizeof (msgo4) - 1);
}
intf ("OVER ABORT FIVE");
break;
}
}
}
}
intf (buffer)
register char *buffer;
{
int fd;
/* make entry in UUCP.DAT file */
fd = open ("UUCP.DAT", O_RDWR);
lseek (fd, (long) 0, 2);
write (fd, buffer, strlen (buffer));
close (fd);
}
xgetc () {
char data;
/* get some stuff from acu/tty line */
if (read (fdtty, &data, 1) > 0)
return (data & 0xFF);
return (EOF);
}
sigint () {
/* interrupt - close acu/tty line */
if (debugmode) {
fprintf (stderr, "...interrupt...\n");
}
close (fdtty);
exit (0);
}
zero (p, c)
char *p;
int c;
{
/* zero a string */
while (c--)
*p++ = 0;
}
ackmsg () {
int cksm,
index;
/* looks like this writes a UUCp format ack message */
msgo[0] = 020;
msgo[1] = 9;
msgo[4] = (CTRL << 6) | (RR << 3) | rseq;
cksm = MAGIC - msgo[4];
msgo[2] = cksm;
msgo[3] = cksm >> 8;
msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4];
if (debugmode > 6) {
printf ("T ");
for (index = 0; index < 6; index++)
printf ("%03o ", msgo[index] & 0xFF);
putchar ('\n');
}
write (fdtty, msgo, 6);
rseq = (rseq + 1) & 7;
}
ctlmsg (byte)
char byte;
{
int cksm,
index;
msgo[0] = 020;
msgo[1] = 9;
msgo[4] = (CTRL << 6) | byte;
cksm = MAGIC - msgo[4];
msgo[2] = cksm;
msgo[3] = cksm >> 8;
msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4];
if (debugmode > 6) {
printf ("T ");
for (index = 0; index < 6; index++)
printf ("%03o ", msgo[index] & 0xFF);
putchar ('\n');
}
write (fdtty, msgo, 6);
}
lngput (s, n)
char *s;
int n;
{
int cksm,
index;
zero (msgo, 256);
msgo[0] = 020;
msgo[1] = segsiz + 1;
msgo[4] = (LNGDAT << 6) + (wseq << 3) + rseq;
for (index = 0; index < (segsiz + 1) * 32; index++)
msgo[6 + index] = 0;
for (index = 0; index < n; index++)
msgo[6 + index] = *(s + index);
cksm = MAGIC - (chksum (&msgo[6], (segsiz + 1) * 32) ^ (0377 & msgo[4]));
msgo[2] = cksm;
msgo[3] = cksm >> 8;
msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4];
if (debugmode > 6) {
printf ("T ");
for (index = 0; index < (segsiz + 1) * 32 + 6; index++)
printf ("%03o ", msgo[index] & 0xFF);
putchar ('\n');
}
do {
write (fdtty, msgo, (segsiz + 1) * 32 + 6);
if (inpkt ())
return (1);
}
while (tt != CTRL || xxx != RR || yyy != wseq);
wseq = (wseq + 1) & 7;
return (0);
}
shtput (s, n)
char *s;
int n;
{
int cksm,
index;
zero (msgo, 256);
msgo[0] = 020;
msgo[1] = segsiz + 1;
msgo[4] = (SHTDAT << 6) + (wseq << 3) + rseq;
for (index = 0; index < (segsiz + 1) * 32; index++)
msgo[6 + index] = 0;
msgo[6] = (segsiz + 1) * 32 - n;
for (index = 0; index < n; index++)
msgo[7 + index] = *(s + index);
cksm = MAGIC - (chksum (&msgo[6], (segsiz + 1) * 32) ^ (0377 & msgo[4]));
msgo[2] = cksm;
msgo[3] = cksm >> 8;
msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4];
if (debugmode > 4) {
printf ("T ");
for (index = 0; index < (segsiz + 1) * 32 + 6; index++)
printf ("%03o ", msgo[index] & 0xFF);
putchar ('\n');
}
do {
write (fdtty, msgo, (segsiz + 1) * 32 + 6);
if (inpkt ())
return (1);
}
while (tt != CTRL || xxx != RR || yyy != wseq);
wseq = (wseq + 1) & 7;
return (0);
}
instr (s, n)
char *s;
int n;
{
int data,
count,
i,
j;
count = 0;
if (debugmode > 4) {
printf ("Expecting ");
for (i = 0; i < n; i++)
printf ("%03o ", *(s + i));
printf ("\nR ");
}
while ((data = xgetc ()) != EOF) {
msgi[count++] = data & 0x7F;
if (debugmode > 4) {
printf ("%03o ", msgi[count - 1]);
}
if (count >= n) {
for (i = n - 1, j = count - 1; i >= 0; i--, j--)
if (*(s + i) == '*' || *(s + i) != msgi[j])
break;
if (i < 0 || *(s + i) == '*') {
if (debugmode > 4) {
putchar ('\n');
}
return (0);
}
}
}
if (debugmode > 4) {
putchar ('\n');
}
msgi[count] = 0;
return (1);
}
inpkt () {
int data,
count,
need;
count = 0;
if (debugmode > 4) {
printf ("R ");
}
while ((data = xgetc ()) != EOF) {
if (debugmode > 4) {
printf ("%03o ", data & 0xFF);
}
switch (count) {
case 0:
if (data == 020)
msgi[count++] = 020;
break;
case 1:
msgi[count++] = data;
if (data == 9)
need = 4;
else
need = 32 * data + 4;
break;
case 4:
tt = (data >> 6) & 3;
xxx = (data >> 3) & 7;
yyy = data & 7;
default:
msgi[count++] = data;
if (!--need) {
if (debugmode > 4) {
putchar ('\n');
}
return (0);
}
break;
}
}
if (debugmode > 4) {
putchar ('\n');
}
return (1);
}
chksum (s, n)
register char *s;
register int n;
{
register short sum;
register unsigned short t;
register short x;
sum = -1;
x = 0;
do {
if (sum < 0) {
sum <<= 1;
sum++;
}
else
sum <<= 1;
t = sum;
sum += *s++ & 0377;
x += sum ^ n;
if ((unsigned) sum <= t)
sum ^= x;
}
while (--n > 0);
return (sum);
}
int
abort () {
write (fdtty, msgo5, sizeof (msgo5) - 1);
if (debugmode) {
fprintf (stderr, "%s\n", msgo5);
}
exit (-1);
}
--
{decuac}!gouldsd!mjranum || {decuac}!osiris!mjranum
"It is better to shred the bugger than to bugger the shredder."
-ancient doltic proverb.
More information about the Comp.sources.unix
mailing list