[net.sources] Source for uuslave.c

dpw@rayssd.RAY.COM (Darryl P. Wagoner) (01/14/87)

Here is the source for uuslave that has been discussed on the net.
I have tried to compile it with MicroSoft C without any success.  Please
note there are no comments.  From the defines I would guess that it
was ported from CP/M.  If anyone successfully compiles it, please post 
the new version.

Don't for the signature
-------------------- cut here ------------------------
/* @[$]uuslave.c	1.7 08/12/85 14:04:20 */

#include <stdio.h>
#include <fcntl.h>
#ifndef CPM
#include <termio.h>
#include <signal.h>
#endif

#define	MAGIC	0125252
#define	EOT	4

#define	CTRL	0
#define	ALTCHN	1
#define	LNGDAT	2
#define	SHTDAT	3

#define	CLOSE	1
#define	RJ	2
#define	SRJ	3
#define	RR	4
#define	INITC	5
#define	INITB	6
#define	INITA	7

extern errno;
char msgi[256],msgo[256],ttynam[32],cmnd[8],srcnam[32],dstnam[32],dskbuf[256],msgbld[256];
int fdtty,fddsk,tt,xxx,yyy,rseq,wseq;
#ifndef CPM
struct termio atermio,btermio;
#endif
#ifdef ERRLOG
FILE *file;
#endif

int wndsiz = 1;
int segsiz = 1;

char msgo0[] = "9800rcs login: ";
char msgo1[] = "Password:";
char msgo2[] = "\20Shere\0";
char msgo3[] = "\20ROK\0\20Pg\0";
char msgo4[] = "\20OOOOOO\0";
char msgo5[] = "...abort...";

char msgi0[] = "uucp\n";
char msgi1[] = "s8000\n";
char msgi2[] = "\20S*\0";
char msgi3[] = "\20Ug\0";

#ifdef CPM
extern xgetc(),xwrite();
#else
sigint()
{
	ioctl(fdtty,TCSETA,&atermio);
	close(fdtty);
	exit(0);
}

sigalrm()
{
}

xgetc()
{
	char data;

	signal(SIGALRM,sigalrm);
	alarm(10);
	if (read(fdtty,&data,1) > 0)
	{
		alarm(0);
		return(data & 0xFF);
	}
	return(EOF);
}

xwrite(fd,buf,ctr)
int fd;
char *buf;
int ctr;
{
	write(fd,buf,ctr);
}
#endif

zero(p,c)
char *p;
int c;
{
	while (c--)
		*p++ = 0;
}

ackmsg()
{
	int cksm,index;

	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];
#ifdef DEBUG
	
	printf("T ");
	for (index = 0; index < 6; index++)
		printf("%03o ",msgo[index] & 0xFF);
	putchar('\n');
#endif
	xwrite(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];
#ifdef DEBUG
	printf("T ");
	for (index = 0; index < 6; index++)
		printf("%03o ",msgo[index] & 0xFF);
	putchar('\n');
#endif
	xwrite(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];
#ifdef DEBUG
	printf("T ");
	for (index = 0; index < (segsiz + 1) * 32 + 6; index++)
		printf("%03o ",msgo[index] & 0xFF);
	putchar('\n');
#endif
	do
	{
		xwrite(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];
#ifdef DEBUG
	printf("T ");
	for (index = 0; index < (segsiz + 1) * 32 + 6; index++)
		printf("%03o ",msgo[index] & 0xFF);
	putchar('\n');
#endif
	do
	{
		xwrite(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;
#ifdef DEBUG
	printf("Expecting ");
	for (i = 0; i < n; i++)
		printf("%03o ",*(s+i));
	printf("\nR ");
#endif
	while ((data = xgetc()) != EOF)
	{
		msgi[count++] = data & 0x7F;
#ifdef DEBUG
		printf("%03o ",msgi[count-1]);
#endif
		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) == '*')
			{
#ifdef DEBUG
				putchar('\n');
#endif
				return(0);
			}
		}
	}
#ifdef DEBUG
	putchar('\n');
#endif
	msgi[count] = 0;
	return(1);
}

inpkt()
{
	int data,count,need;

	count = 0;
#ifdef DEBUG
	printf("R ");
#endif
	while ((data = xgetc()) != EOF)
	{
#ifdef DEBUG
		printf("%03o ",data & 0xFF);
#endif
		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)
			{
#ifdef DEBUG
				putchar('\n');
#endif
				return(0);
			}
			break;
		}
	}
#ifdef DEBUG
	putchar('\n');
#endif
	return(1);
}

chksum(s,n)
register char *s;
register 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);
}

main(argc,argv)
int argc;
char *argv[];
{
	char *p;
	int data,count;

#ifdef CPM
	sioinit();
#else
	if (argc > 1)
		strcpy(ttynam,argv[1]);
	else
		strcpy(ttynam,"/dev/tty12");
	if ((fdtty = open(ttynam,O_RDWR)) < 0)
	{
		printf("Cannot open %s for read/write %d\n",ttynam,errno);
		exit(1);
	}
	ioctl(fdtty,TCGETA,&atermio);
	btermio = atermio;
	btermio.c_iflag = btermio.c_oflag = btermio.c_lflag = 0;
	btermio.c_cc[VMIN] = 1;
	btermio.c_cc[VTIME] = 0;
	btermio.c_cflag = (btermio.c_cflag & ~CBAUD) | B1200;
	ioctl(fdtty,TCSETA,&btermio);
	signal(SIGINT,sigint);
#endif
	while (1)
	{
#ifdef DEBUG
		puts("restarting");
#endif
		rseq = 0;
		wseq = 1;

/* wait for EOT */

		while ((data = xgetc()) == EOF || (data &= 0x7F) != EOT);

/* output login request, verify uucp */

		xwrite(fdtty,msgo0,sizeof(msgo0)-1);
		if (instr(msgi0,sizeof(msgi0)-1))
			goto abort;

/* output password request, verify s8000 */

		xwrite(fdtty,msgo1,sizeof(msgo1)-1);
		if (instr(msgi1,sizeof(msgi1)-1))
			goto abort;

/* output here message, wait for response */

		xwrite(fdtty,msgo2,sizeof(msgo2)-1);
		if (instr(msgi2,sizeof(msgi2)-1))
			goto abort;

/* output ok message, output protocol request, wait for response */

		xwrite(fdtty,msgo3,sizeof(msgo3)-1);
		if (instr(msgi3,sizeof(msgi3)-1))
			goto abort;

/* output inita message, wait for response */

		ctlmsg((INITA << 3) | wndsiz);
		if (inpkt() || tt != CTRL || xxx != INITA)
			goto abort;

/* output initb message, wait for response */

		ctlmsg((INITB << 3) | segsiz);
		if (inpkt() || tt != CTRL || xxx != INITB)
			goto abort;

/* output initc message, wait for response */

		ctlmsg((INITC << 3) | wndsiz);
		if (inpkt() || tt != CTRL || xxx != INITC)
			goto abort;

/* output initial acknowledge, wait for command */

		ackmsg();
		while (1)
		{
			if (inpkt() || tt != LNGDAT)
			{
				intf("OVER EIGHT");
				goto abort;
			}
			strcpy(msgbld,&msgi[6]);
			while (strlen(&msgi[6]) == (segsiz + 1) * 32)
			{
				ackmsg();
				if (inpkt() || tt != LNGDAT)
				{
					intf("OVER ABORT SEVEN");
					goto abort;
				}
				strcat(msgbld,&msgi[6]);
			}
			switch (msgbld[0])
			{
			case 'S' :
				sscanf(msgbld,"%s %s %s",cmnd,srcnam,dstnam);
#ifdef CPM
				for (p = dstnam + strlen(dstnam); p != dstnam && *(p-1) != '/'; p--);
#else
				p = dstnam;
#endif
				if ((fddsk = creat(p,0644)) >= 0)
				{
					ackmsg();
					if (lngput("SY",2))
					{
						intf("OVER NINE");
						goto abort;
					}
					do
						if (inpkt())
						{
							intf("OVER TEN");	
							goto abort;
						}	
						else
							switch (tt)
							{
							case LNGDAT :
								write(fddsk,&msgi[6],(segsiz + 1) * 32);
								ackmsg();
								break;
							case SHTDAT :
								if (msgi[6] & 0x80)
								{
									intf("OVER ELEVEN");
#ifdef DEBUG
									puts("short packet error");
#endif
									goto abort;
								}
								else
								{
									if (msgi[6] != (segsiz + 1) * 32)
										write(fddsk,&msgi[7],(segsiz + 1) * 32 - msgi[6]);
									ackmsg();
								}
								break;
							default :
								intf("OVER TWELVE");
								goto abort;
							}
					while (tt != SHTDAT || msgi[6] != (segsiz + 1) * 32);
					close(fddsk);
					if (lngput("CY",2))
						goto abort;
				}
				else
				{
					ackmsg();
#ifdef ERRLOG
					if (file = fopen("uuslave.log","a+"))
					{
						fprintf(file,"Cannot open file=%s for writing errno=%d\n",p,errno);
						fclose(file);
					}
#endif
					sprintf(dskbuf,"SN%d",errno);
					if (lngput(dskbuf,strlen(dskbuf)))
						goto abort;
				}
				break;
			case 'R' :
				sscanf(msgbld,"%s %s %s",cmnd,srcnam,dstnam);
#ifdef CPM
				for (p = srcnam + strlen(srcnam); p != srcnam && *(p-1) != '/'; p--);
#else
				p = srcnam;
#endif
				if ((fddsk = open(p,O_RDONLY)) >= 0)
				{
					ackmsg();
					if (lngput("RY",2))
						goto abort;
					do
						if ((count = read(fddsk,dskbuf,(segsiz + 1) * 32)) == (segsiz + 1) * 32)
							if (lngput(dskbuf,(segsiz + 1) * 32))
								goto abort;
							else;
						else
							if (shtput(dskbuf,count))
								goto abort;
					while (count);
					close(fddsk);
					do
						if (inpkt())
							goto abort;
					while (tt != LNGDAT);
					ackmsg();
				}
				else
				{
					ackmsg();
#ifdef ERRLOG
					if (file = fopen("uuslave.log","a+"))
					{
						fprintf(file,"Cannot open file=%s for reading errno=%d\n",p,errno);
						fclose(file);
					}
#endif
					sprintf(dskbuf,"RN%d",errno);
					if (lngput(dskbuf,strlen(dskbuf)))
						goto abort;
				}
				break;
			case 'H' :
				intf("IN H CASE");
				if (lngput("HY",2))
				{
					intf("OVER ABORT ONE");	
					goto abort;
				}
				if (inpkt() || tt != LNGDAT)
				{
					intf("OVER ABORT TWO");		
					goto abort;
				}
				if (!strcmp(&msgi[6],"HY"))
				{
					ctlmsg(CLOSE << 3);
					do
						if (inpkt())
						{
							intf("OVER ABORT THREE");
							goto abort;
						}
					while (tt != CTRL && xxx != CLOSE);
					xwrite(fdtty,msgo4,sizeof(msgo4)-1);
					instr(msgo4,sizeof(msgo4)-1);
				}
				intf("OVER ABORT FIVE");
				break;
				/*goto abort;*/
			}
		}
abort:;
		xwrite(fdtty,msgo5,sizeof(msgo5)-1);
	}
}
intf(buffer)
register char *buffer;
{
	int fd;
	fd = open("UUCP.DAT",O_RDWR + O_CREAT);
	lseek(fd,0L,2);
	write(fd,buffer,strlen(buffer));
	close(fd);
}