🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sources.mac
Article #6

MacLayers 1.00 (part 2 of 6)

#6
From: Werner Uhrig
Date: Fri, 01 Jun 1990 19:00
1814 lines
50196 bytes
[MacLayers 1.00 - part 2 of 6]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#
#	layers.h
#	layersize.c
#	layertitle.c
#	macbput.c
#	makefile
#	protocol.c
#
# This archive created: Thu May 31 21:58:11 1990
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'layers.h'" '(2049 characters)'
if test -f 'layers.h'
then
	echo shar: will not over-write existing file "'layers.h'"
else
sed 's/^X//' << \SHAR_EOF > 'layers.h'
X/*             Copyright (C) 1989 by David W. Trissel 
X *
X *  Not derived from licensed software.
X *
X * Permission is granted to freely use, copy, modify, and redistribute
X * this software, provided that no attempt is made to gain profit from it,
X * the author is not construed to be liable for any results of using the
X * software, alterations are clearly marked as such, and this notice is
X * not modified.
X *
X */
X
X#define MAXPCHAN	7						/* maximum layers supported */
X
X#define MAXSTR		200
X#define	MAXARGS		64
X#define MAXLINE		1024
X#define IOSIZE		800						/* data gulp handling size */
X
X/* WARNING - packet sizes must be insured to never match the ESCAPE char */
X#define	ESCAPE		'}'						/* datalink escape character */
X
X#define DO 		if (Dflag)					/* for debugging */
X
X/* miscelaneous common data */
Xextern	int	Dflag;							/* debug dump indicator flag */
X
X/* Shape structure passed between MacLayers and ourselves */
Xstruct Shape
X{	short	worigv;							/* verical window bit origin */
X	short	worigh;							/* horizontal window bit origin */
X	short	wlines;							/* window height */
X	short	wchars;							/* window width */
X	short	wfont;							/* window font size */
X	short	wattr;							/* window attributes */
X};
X
X#define Wa_shell	0x01					/* window is a shell */
X
X
X  /* The following modules define the complete protocol/server interface */
X
X				/* layers.c */
X
Xextern void FQuit(/* exitcode */);
Xextern void ReceiveQuit();
Xextern void ReceiveNew(/* chanid, shape */);
Xextern void ReceiveDelete(/* chanid */);
Xextern void ReceiveSignal(/* chanid, signal */);
Xextern void	ReceiveData(/* chanid, buff, cnt */);
Xextern void ReceiveReshape(/*chanid, shape */);
Xextern void DEBUG(/* format, arg1, arg2, arg3, arg4 */);
X
X				/* protocol.c */
X
Xextern int	InitLink();
Xextern int	TopChannel();
Xextern int	SendNew(/* shape */);
Xextern void	SendTitle(/* chan, buff, cnt */);
Xextern void SendDelete(/* chan */);
Xextern void SendQuit();
Xextern void	SendReshape(/* chan, shape */);
Xextern void	SendData(/* chan, buff, cnt */);
Xextern void	ProcessStreamin();
SHAR_EOF
if test 2049 -ne "`wc -c < 'layers.h'`"
then
	echo shar: error transmitting "'layers.h'" '(should have been 2049 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'layersize.c'" '(3586 characters)'
if test -f 'layersize.c'
then
	echo shar: will not over-write existing file "'layersize.c'"
else
sed 's/^X//' << \SHAR_EOF > 'layersize.c'
X/*             Copyright (C) 1989 by David W. Trissel 
X *
X *  Not derived from licensed software.
X *
X * Permission is granted to freely use, copy, modify, and redistribute
X * this software, provided that no attempt is made to gain profit from it,
X * the author is not construed to be liable for any results of using the
X * software, alterations are clearly marked as such, and this notice is
X * not modified.
X *
X */
X				/*         All rights reserved.        */
X
X		/* layersize - update BSD Sun Unix with window size information */
X
X#include <stdio.h>
X#include <errno.h>
X#include <sys/ioctl.h>
X
Xextern int sys_nerr;
Xextern char	*sys_errlist[];
X
Xstatic void gotsyserr(/* char * */);
Xstatic void goterr(/* char * */);
Xstatic int	getnumber(/* char * */);
X
X
X						/* main() - update BSD window size */
X
Xmain(ac, av)
Xint			ac;							/* argument count */
Xchar		**av;						/* argument vector */
X{
X	struct winsize wsize;				/* window size structure for ioctl() */
X	char		*ap;					/* argument scan pointer */
X	int			lines;					/* new lines value */
X	int			cols;					/* new columns value */
X
X	if (--ac != 2)
X		goterr("Missing lines and column options");
X
X	/* get window size (actually do this to set xpixel and ypixel values) */
X	if (ioctl(0, TIOCGWINSZ, &wsize) == -1)
X		gotsyserr("No window support in host"); /* terminate with message */
X
X	/* scan looking for -l and -c line and column numeric sizes */
X	lines = cols = 0;					/* reset values */
X	while (ac > 0)
X	  {	ap = *++av;						/* point to next argument string */
X		if (ac-- > 0 && *ap == '-')		/* if option ... */
X		switch (ap[1])
X		{ case 'l':		/* lines */
X			lines = getnumber(&ap[2]);
X			break;
X
X		  case 'c':		/* columns */
X			cols = getnumber(&ap[2]);
X			break;
X
X		  default:
X			goterr("Usupported option"); /* unsupported option */
X			break;
X
X		} /* end '-' argument */
X		else
X			goterr("Unsupported parameter"); /* unsupported parameter */
X
X	  } /* end while argument vector scan */
X			
X	/* must have both lines and columns */
X	if (lines == 0 || cols == 0)
X		goterr("Must specify both lines and columns");
X
X	wsize.ws_col = cols;				/* set columns */
X	wsize.ws_row = lines;				/* set lines */
X	/* update the kernel */
X	if (ioctl(0, TIOCSWINSZ, &wsize) == -1)
X		gotsyserr("Failed to update window size"); /* didn't go */
X
X} 
X
X
X				/* goterr() - issue error and terminate */
X
Xstatic void
Xgoterr(msg)
Xchar		*msg;						/* error message string */
X{
X	printf("%s\n", msg);				/* send error message to user */
X	exit(1);							/* terminate with error */
X
X} /* goterr() */
X
X
X				/* gotsyserror() - system error return */
X
Xstatic void
Xgotsyserr(msg)
Xchar		*msg;						/* error string */
X{
X	if (errno > 0 && errno < sys_nerr)
X		printf("%s: %s\n", msg, sys_errlist[errno]);
X	else
X		printf("%s: Error %d\n", msg, errno);
X
X	exit(1);							/* exit with failure */
X
X} /* gotsyserr() */
X
X
X					/* getnumber() - parse option number */
X
Xstatic int
Xgetnumber(str)
Xchar		*str;						/* start of option string */
X{
X	int			n;						/* number being built */
X
X	if (str == NULL)
X		goterr("Invalid numeric in option");
X
X	/* skip any leading delimiters */
X	while (*str && (*str == ' ' || *str == '\t'))
X		str++;
X
X	for(n=0; *str && *str >= '0' && *str <= '9'; str++)
X		n = n*10 + *str - '0';			/* add next digit in */
X
X	/* make sure number terminates legally */
X	switch (*str)
X	{ case '\0':
X	  case ' ':
X	  case '\t':
X	  case '\n':
X		if (n <= 0 || n > 200)
X			goterr("Number out of range");
X		break;							/* these are OK */
X
X	  default:
X		goterr("Invalid numeric in option");
X
X	} /* end switch */
X
X	return ( n );						/* return the number */
X
X} /* getnumber() */
SHAR_EOF
if test 3586 -ne "`wc -c < 'layersize.c'`"
then
	echo shar: error transmitting "'layersize.c'" '(should have been 3586 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'layertitle.c'" '(1242 characters)'
if test -f 'layertitle.c'
then
	echo shar: will not over-write existing file "'layertitle.c'"
else
sed 's/^X//' << \SHAR_EOF > 'layertitle.c'
X/*             Copyright (C) 1989 by David W. Trissel
X *
X *  Not derived from licensed software.
X *
X * Permission is granted to freely use, copy, modify, and redistribute
X * this software, provided that no attempt is made to gain profit from it,
X * the author is not construed to be liable for any results of using the
X * software, alterations are clearly marked as such, and this notice is
X * not modified.
X *
X */
X                /*         All rights reserved.        */
X
X            /* layertitle - utility to specify window title */
X
X#include <stdio.h>
X
X#define ESC 0x1b
X
X            /* main() - send string designating layers window title */
X
Xmain(ac, av)
Xint         ac;                         /* argument count */
Xchar        **av;                       /* argument vector */
X{
X    char        *ap;                    /* argument scan pointer */
X
X    if (--ac != 1)
X      { printf("usage: layertitle \"new window title\"\n");
X        exit(1);
X      }
X       
X    ap = *++av;                         /* point to argument string */
X
X    /* Transmit the title string in the ANSI Private Message format
X    ** which is
X    **              ESC '^' message ESC '\'
X    */
X    printf("%c%c%s%c%c", ESC, '^', ap, ESC, '\\');
X
X}  /* main() */
SHAR_EOF
if test 1242 -ne "`wc -c < 'layertitle.c'`"
then
	echo shar: error transmitting "'layertitle.c'" '(should have been 1242 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'macbput.c'" '(9383 characters)'
if test -f 'macbput.c'
then
	echo shar: will not over-write existing file "'macbput.c'"
else
sed 's/^X//' << \SHAR_EOF > 'macbput.c'
X/*
X * (originally macput) -- send file to Macintosh using MacBinary XMODEM protocol
X * Dave Johnson, Brown University Computer Science
X *
X * (c) 1984 Brown University 
X * may be used but not sold without permission
X *
X */
X
X/* To compile:    
X                  cc -O -o macbput macbput.c
X    (Sun 4.2 BSD) cc -O -DSUNBSD42 -o macbput macbput.c
X    (System V)    cc -O -DSYSV -o macbput macbput.c
X
X   Latest modifications 10/20/88 by Trissel -
X
X 1. General cleanup by removal of unused definitions and headers.
X 2. Added #ifdefs to support System V and BSD 4.2 Sun compilation.
X 3. Removed ancient Macterminal Beta 0.5X code.
X 4. Fixed bad bug where XMODEM block count was not bumped up
X    after the first fork transfer.
X
X	Dave Trissel
X	Motorola Inc.
X	ut-sally!oakhill!davet
X
X   This code is fundamentally from two earlier programmers:
X
X	Jon Hueras
X	Symantec/THINK Technologies
X	singer@endor.harvard.edu
X
X    who added 2-Byte CRC capability to code from:
X
X	Dave Johnson
X	ddj%brown@csnet-relay.arpa
X	Brown University Computer Science
X
X   who did the initial MacTerminal 1.1 transfer protocol.
X*/
X
X/* If you have System V define the following: */
X	/* #define SYSV */
X
X/* Sun BSD 4.2 systems should define the following: */
X	/* #define SUNBSD42 */
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#ifdef SYSV
X#include <termio.h>
X#else
X#include <sgtty.h>
X#endif
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#ifdef SUNBSD42
X/* RAW is no longer being found on latest Sun system (??) (Trissel) */
X#define RAW 0x20
X#endif
X
X#define RECORDBYTES 132
X#define DATABYTES 128
X#define NAMEBYTES 63
X
X#define RETRIES 10
X#define ACKTIMO 10
X
X#define MAXRECNO 0xff
X#define BYTEMASK 0xff
X
X#define TMO -1
X#define DUP '\000'
X#define SOH '\001'
X#define EOT '\004'
X#define ACK '\006'
X#define NAK '\025'
X#define CAN '\030'
X#define EEF '\032'
X#define ESC '\033'
X
X#define H_NLENOFF 1
X#define H_NAMEOFF 2
X/* 65 <-> 80 is the FInfo structure */
X#define H_TYPEOFF 65
X#define H_AUTHOFF 69
X
X#define H_LOCKOFF 81
X#define H_DLENOFF 83
X#define H_RLENOFF 87
X#define H_CTIMOFF 91
X#define H_MTIMOFF 95
X
X#define H_OLD_DLENOFF 81
X#define H_OLD_RLENOFF 85
X
X#define TEXT 0
X#define DATA 1
X#define RSRC 2
X#define FULL 3
X
Xint mode, txtmode;
X
Xstruct macheader {
X	char m_name[NAMEBYTES+1];
X	char m_type[4];
X	char m_author[4];
X	long m_datalen;
X	long m_rsrclen;
X	long m_createtime;
X	long m_modifytime;
X} mh;
X
Xstruct filenames {
X	char f_info[256];
X	char f_data[256];
X	char f_rsrc[256];
X} files;
X
Xint recno, crc;
Xchar buf[DATABYTES];
X
Xchar usage[] =
X    "usage: \"macbput [-rdu] [-t type] [-c creator] [-n name] filename\"\n";
X
Xmain(ac, av)
Xchar **av;
X{
X	int n;
X	char *filename;
X
X	if (ac == 1) {
X		fprintf(stderr, usage);
X		exit(1);
X	}
X
X	mode = FULL;
X	ac--; av++;
X	while (ac) {
X		if (av[0][0] == '-') {
X			switch (av[0][1]) {
X			case 'r':
X				mode = RSRC;
X				strncpy(mh.m_type, "????", 4);
X				strncpy(mh.m_author, "????", 4);
X				break;
X			case 'u':
X				mode = TEXT;
X				strncpy(mh.m_type, "TEXT", 4);
X				strncpy(mh.m_author, "MACA", 4);
X				break;
X			case 'd':
X				mode = DATA;
X				strncpy(mh.m_type, "????", 4);
X				strncpy(mh.m_author, "????", 4);
X				break;
X			case 'n':
X				if (ac > 1) {
X					ac--; av++;
X					n = strlen(av[0]);
X					if (n > NAMEBYTES) n = NAMEBYTES;
X					strncpy(mh.m_name, av[0], n);
X					mh.m_name[n] = '\0';
X					break;
X				}
X				else goto bad_usage;
X			case 't':
X				if (ac > 1) {
X					ac--; av++;
X					strncpy(mh.m_type, av[0], 4);
X					break;
X				}
X				else goto bad_usage;
X			case 'c':
X				if (ac > 1) {
X					ac--; av++;
X					strncpy(mh.m_author, av[0], 4);
X					break;
X				}
X				else goto bad_usage;
X			default:
Xbad_usage:
X				fprintf(stderr, usage);
X				exit(1);
X			}
X		}
X		else {
X			filename = av[0];
X		}
X		ac--; av++;
X	}
X
X	setup_tty();
X	find_files(filename, mode);
X	if (mode != FULL)
X		forge_info();
X
X	if (send_sync()) {
X		recno = 1;
X		txtmode = 0;
X		send_file(files.f_info, 1);
X
X		if (mode != FULL)
X			unlink(files.f_info);
X
X		if (mode == TEXT) txtmode++;
X		send_file(files.f_data, 1);
X
X		txtmode = 0;
X		send_file(files.f_rsrc, 0);
X	}
X	reset_tty();
X}
X
Xfind_files(filename, mode)
Xchar *filename;
X{
X	int n, tdiff;
X	struct stat stbuf;
X
X	sprintf(files.f_data, "%s.data", filename);
X	sprintf(files.f_rsrc, "%s.rsrc", filename);
X
X	if (mode == FULL) {
X		sprintf(files.f_info, "%s.info", filename);
X		if (stat(files.f_info, &stbuf) != 0) {
X			perror(files.f_info);
X			cleanup(-1);
X		}
X		return;
X	}
X	else {
X		strcpy(files.f_info, "#machdrXXXXXX");
X		mktemp(files.f_info);
X	}
X
X	if (mode == RSRC) {
X		strcpy(files.f_data, "/dev/null");
X		if (stat(files.f_rsrc, &stbuf) != 0) {
X			strcpy(files.f_rsrc, filename);
X			if (stat(files.f_rsrc, &stbuf) != 0) {
X				perror(files.f_rsrc);
X				cleanup(-1);
X			}
X		}
X		mh.m_datalen = 0;
X		mh.m_rsrclen = stbuf.st_size;
X	}
X	else {
X		strcpy(files.f_rsrc, "/dev/null");
X		if (stat(files.f_data, &stbuf) != 0) {
X			sprintf(files.f_data, "%s.text", filename);
X			if (stat(files.f_data, &stbuf) != 0) {
X				strcpy(files.f_data, filename);
X				if (stat(files.f_data, &stbuf) != 0) {
X					perror(files.f_data);
X					cleanup(-1);
X				}
X			}
X		}
X		mh.m_datalen = stbuf.st_size;
X		mh.m_rsrclen = 0;
X	}
X
X	if (mh.m_name[0] == '\0') {
X		n = strlen(filename);
X		if (n > NAMEBYTES) n = NAMEBYTES;
X		strncpy(mh.m_name, filename, n);
X		mh.m_name[n] = '\0';
X	}
X}
X
Xforge_info()
X{
X	int n;
X	char *np;
X	FILE *fp;
X
X	for (np = mh.m_name; *np; np++)
X		if (*np == '_') *np = ' ';
X
X	buf[H_NLENOFF] = n = np - mh.m_name;
X	strncpy(buf + H_NAMEOFF, mh.m_name, n);
X	strncpy(buf + H_TYPEOFF, mh.m_type, 4);
X	strncpy(buf + H_AUTHOFF, mh.m_author, 4);
X	put4(buf + H_DLENOFF, mh.m_datalen);
X	put4(buf + H_RLENOFF, mh.m_rsrclen);
X	put4(buf + H_CTIMOFF, mh.m_createtime);
X	put4(buf + H_MTIMOFF, mh.m_modifytime);
X	fp = fopen(files.f_info, "w");
X	if (fp == NULL) {
X		perror("temp file");
X		cleanup(-1);
X	}
X	fwrite(buf, 1, DATABYTES, fp);
X	fclose(fp);
X}
X
Xsend_sync()
X	{
X		int c;
X		
X		tputc(ESC);
X		tputc('b');
X
X		for (;;) {
X
X			if ((c = tgetc(ACKTIMO)) == TMO)
X			  {
X				return(0);
X				}
X
X			if (c == NAK)
X			  {
X				return(1);
X				}
X
X			if (c == 'C') {
X				crc++;
X				return(1);
X			}
X		}
X	}
X
Xsend_file(fname, more)
Xchar *fname;
Xint more;
X{
X	register int status, i, n;
X	FILE *inf;
X
X	inf = fopen(fname, "r");
X	if (inf == NULL) {
X		perror(fname);
X		cleanup(-1);
X	}
X	for (;;) {
X		n = fread(buf, 1, DATABYTES, inf);
X		if (n > 0) {
X			for (i = 0; i < RETRIES; i++) {
X				send_rec(buf, DATABYTES);
X				while ((status = tgetc(ACKTIMO)) != ACK && status != NAK && status != CAN);
X				if (status != NAK)
X					break;
X			} 
X			if (status != ACK) {
X				if (status != CAN)
X					while ((status = tgetc(ACKTIMO)) != CAN);
X				fclose(inf);
X				cleanup(-1);
X				/* NOTREACHED */
X			}
X		}
X		if (n < DATABYTES) {
X			if (!more) {
X				tputc(EOT);
X				tgetc(ACKTIMO);
X			}
X			return;
X		}
X		recno++;
X		recno &= MAXRECNO;
X	}
X}
X
Xsend_rec(buf, recsize)
Xchar buf[];
Xint recsize;
X{
X	int i, cksum;
X	char *bp;
X 
X	if (txtmode || !crc) {
X		cksum = 0;
X		bp = buf;
X		for (i = 0; i < recsize; i++, bp++) {
X			if (txtmode && *bp == '\n')
X				*bp = '\r';
X			cksum += *bp;
X		}
X	}
X
X	if (crc)
X		cksum = calcrc(buf, recsize);
X
X	tputc(SOH);
X	tputc((char) recno);
X	tputc((char) (MAXRECNO - recno));
X	tputrec(buf, recsize);
X	
X	if (crc) {
X		tputc((char) (cksum >> 8));
X		tputc((char) cksum);
X	} else
X		tputc((char) cksum);
X}
X
Xstatic int ttyfd;
Xstatic FILE *ttyf;
Xstatic jmp_buf timobuf;
X
Xtgetc(timeout)
Xint timeout;
X{
X	int c;
X
X	if (setjmp(timobuf))
X		return TMO;
X
X	alarm(timeout);
X	c = getc(ttyf);
X	alarm(0);
X
X	if (c == -1)	/* probably hung up or logged off */
X		return EOT;
X	else
X		return c & BYTEMASK;
X}
X
Xtputrec(buf, count)
Xchar *buf;
Xint count;
X{
X	write(ttyfd, buf, count);
X}
X
Xtputc(c)
Xchar c;
X{
X	write(ttyfd, &c, 1);
X}
X
Xtimedout()
X{
X	signal(SIGALRM, timedout);	/* for pre-4.2 systems */
X	longjmp(timobuf, 1);
X}
X
X#ifdef SYSV
Xstatic struct termio otty, ntty;
X#else
Xstatic struct sgttyb otty, ntty;
X#endif
X
X/* should turn messages off */
X
Xsetup_tty()
X{
X	int cleanup();
X	int timedout();
X
X	ttyf = stdin;
X	ttyfd = fileno(stdout);
X#ifdef SYSV
X	ioctl(ttyfd, TCGETA, &otty);		/* get termio info */
X#else
X	ioctl(ttyfd, TIOCGETP, &otty);
X#endif
X	signal(SIGHUP, cleanup);
X	signal(SIGINT, cleanup);
X	signal(SIGQUIT, cleanup);
X	signal(SIGTERM, cleanup);
X	signal(SIGALRM, timedout);
X	ntty = otty;
X#ifdef SYSV
X	ntty.c_iflag = BRKINT;				/* only interrupt on break */
X	ntty.c_oflag = 0;					/* no output processing */
X	ntty.c_cflag |= CS8;				/* 8 bit characters */
X	ntty.c_lflag = 0;					/* no echoing */
X	ntty.c_cc[VEOF] = 1;				/* "MIN" minimum chars before input */
X	ntty.c_cc[VEOL] = 1;				/* "TIME" maximum .1 secs before feed */
X	ioctl(ttyfd, TCSETAF, &ntty);		/* set mode and flush input */
X#else
X	ntty.sg_flags = RAW;
X	ioctl(ttyfd, TIOCSETP, &ntty);
X#endif
X}
X
Xreset_tty()
X{
X	if (ttyf != NULL) {
X#ifdef SYSV
X		ioctl(ttyfd, TCSETAF, &otty);	/* reset after output drains */
X#else
X		sleep (5);						/* wait for output to drain */
X		ioctl(ttyfd, TIOCSETP, &otty);
X#endif
X	}
X}
X
Xcleanup(sig)
Xint sig;
X{
X	reset_tty();
X	exit(sig);
X}
X
Xput4(bp, value)
Xchar *bp;
Xlong value;
X{
X	register int i, c;
X
X	for (i = 0; i < 4; i++) {
X		c = (value >> 24) & BYTEMASK;
X		value <<= 8;
X		*bp++ = c;
X	}
X}
X
Xint calcrc(ptr,	count)
Xchar *ptr;
Xint count;
X	{
X		int	crc, i;
X
X		crc	= 0;
X		while (--count >= 0) {
X		 crc ^= ((int) *ptr++) << 8;
X		 for (i = 0; i < 8; ++i)
X				 if (crc & 0x8000)
X			 crc = crc <<	1 ^ 0x1021;
X				 else
X			 crc <<= 1;
X		 }
X		return (crc	& 0xFFFF);
X	}
SHAR_EOF
if test 9383 -ne "`wc -c < 'macbput.c'`"
then
	echo shar: error transmitting "'macbput.c'" '(should have been 9383 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile'" '(1674 characters)'
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile'
X#                   Makefile for Layers 1.0
X
XBIN    = /usr/local
XMANDIR = /usr/local/manl
X
XPGM    = layers
XPGM2   = layersize
XPGM3   = layertitle
XPGM4   = macbput
XMS     = l
XCFLAGS = -O
XCFILES = layers.c protocol.c
XOFILES = layers.o protocol.o
X
Xall: $(PGM) $(PGM2) $(PGM3) $(PGM4)
X
X$(PGM): $(OFILES)
X	$(CC) $(CFLAGS) -o $(PGM) $(OFILES)
X
X#	$(CC) $(CFLAGS) -o $(PGM) $(OFILES) -ltermcap
X
Xlayers.o: layers.c layers.h
X	$(CC) $(CFLAGS) -c layers.c
X
Xprotocol.o: protocol.c layers.h
X	$(CC) $(CFLAGS) -c protocol.c
X
X$(PGM2): layersize.o
X	$(CC) $(CFLAGS) -o $(PGM2) layersize.o
X
X$(PGM3): layertitle.o
X	$(CC) $(CFLAGS) -o $(PGM3) layertitle.o
X
X$(PGM4): macbput.o
X	$(CC) $(CFLAGS) -o $(PGM4) macbput.o
X
Xlayersize.o: layersize.c
X	$(CC) $(CFLAGS) -c layersize.c
X
Xlayertitle.o: layertitle.c
X	$(CC) $(CFLAGS) -c layertitle.c
X
Xmacbput.o: macbput.c
X	$(CC) $(CFLAGS) -c macbput.c
X
Xinstall: $(PGM) $(PGM2) $(PGM3) $(PGM4)
X	rm -f $(BIN)/$(PGM)
X	install -c -s -o root -g daemon -m 4711 $(PGM) $(BIN)/$(PGM)
X	install -c -s $(PGM2) $(BIN)/$(PGM2)
X	install -c -s $(PGM3) $(BIN)/$(PGM3)
X#	install -c -s $(PGM4) $(BIN)/$(PGM4)
X
Xinstallnopriv: $(PGM) $(PGM2) $(PGM3) $(PGM4)
X	rm -f $(BIN)/$(PGM)
X	install -c -s $(PGM) $(BIN)/$(PGM)
X	install -c -s $(PGM2) $(BIN)/$(PGM2)
X	install -c -s $(PGM3) $(BIN)/$(PGM3)
X#	install -c -s $(PGM4) $(BIN)/$(PGM4)
X
Xmanpage: layers.1
X	rm -f $(MANDIR)/$(PGM).$(MS)
X	cp layers.1 $(MANDIR)/$(PGM).$(MS)
X	chmod 664 $(MANDIR)/$(PGM).$(MS)
X
Xclean:
X	rm -f a.out core $(PGM) $(PGM2) $(PGM3) $(PGM4) *.o
X
Xshar: makefile 
X	shar README layers.1 makefile layers.h layers.c \
X	protocol.c layersize.c layertitle.c MacLayers.sit.Hqx MacLayers.doc \
X	macbput.c macbput.1 >layers.shar
SHAR_EOF
if test 1674 -ne "`wc -c < 'makefile'`"
then
	echo shar: error transmitting "'makefile'" '(should have been 1674 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'protocol.c'" '(25546 characters)'
if test -f 'protocol.c'
then
	echo shar: will not over-write existing file "'protocol.c'"
else
sed 's/^X//' << \SHAR_EOF > 'protocol.c'
X/*             Copyright (C) 1989 by David W. Trissel 
X *
X *              Not derived from licensed software.
X *
X * Permission is granted to freely use, copy, modify, and redistribute
X * this software, provided that no attempt is made to gain profit from it,
X * the author is not construed to be liable for any results of using the
X * software, alterations are clearly marked as such, and this notice is
X * not modified.
X *
X */
X
X#include	<stdio.h>
X#include	<signal.h>
X#include	<errno.h>
X#include	"layers.h"
X
X				/* protocol.c - BSD MacLayers protocol driver */
X
X/*	This module handles all interaction with the Macintosh MacLayers
X**	program. Services provided are:
X**
X**		InitLink()	- initialize link to MacLayers
X**
X**		TopChannel() - return highest prority channel
X**
X**		SendNew()	- request new layer channel of MacLayers
X**
X**		SendTitle() - change window title to given string (NOT IMPLENTED YET)
X**
X**		SendDelete()- tell MacLayers indicated layer has died
X**
X**		SendQuit()	- order MacLayers to terminate layers mode
X**
X**		SendData()	- send output to indicated channel's window
X**
X**		SendReshape() - send Shape structure to MacLayers
X**
X**		ProcessStreamin() - data is ready to be processed from MacLayers
X**
X*/
X
X#define DUMPALL
X#undef	DUMPALL
X
X/* C library calls */
Xunsigned alarm();				/* alarm system call */
X
Xstatic int		GetData();
Xstatic void		Packet();
Xstatic void		Parse();
Xstatic void		AwaitInput();
Xstatic void		asciishape();
Xstatic void		fill4();
Xstatic void		fill2();
Xstatic void		fill1();
Xstatic int		parseshape();
Xstatic unsigned	get4();
Xstatic unsigned	get2();
Xstatic unsigned	get1();
X
Xstatic char		inbuff[IOSIZE];		/* input buffer from MacLayers */
Xstatic char 	*inpos;				/* current input position in buffer */
Xstatic int		insize = 0;			/* characters left to process */
Xstatic int		Outstream = -1;		/* current output stream channel */
Xstatic int		Instream = -1;		/* current input stream channel */
X
Xstatic struct Shape	SNshape;		/* SendNew() shape response */
Xstatic int		SNresp = 0;			/* SendNew() reponse poll flag */
Xstatic int		SNchan = 0;			/* SendNew() channel return */
X#define SN_WAITING	-1000			/* SendNew() waiting response value */
X
X#define ATTRSIZE	15				/* size of window attribute string */
X
X#define FLUSH	fflush(stdout)
X
X
X				/* Initlink() - initialize link with MacLayers */
X
X/* Returns:
X**				0 - linkup failed
X**				1 - linkup successful, Maclayers now in protocol mode
X*/
X
Xint
XInitlink()
X{
X	int Outstream = -1;				/* no default stream yet */
X	int	Instream = -1;				/* no default stream yet */
X	int		num1, num2, num3;		/* scanf item result */
X	int		err;					/* error code */
X
X#define WAITTIME	10				/* second wait response time */
X#define INITTIME	2				/* wait time after succesful startup */
X
X	/* we must non-buffer input since all input must be immediate */
X	setbuf(stdin, NULL);			/* non-buffer all input */
X
X	/* send intitial request for terminal type and version number */
X	DO DEBUG("write: ESC [ c\n");
X	if ((err=printf("\033[c")) < 0)
X	  {
X		DO DEBUG(" printf() error code %d\n", err);
X		return ( 0 );				/* problem with stdout */
X	  }
X	FLUSH;							/* force output buffer */
X
X	/* attempt to read "ESC [ ? 8 ; typedigits ; versiondigits c" */
X	num1 = num2 = num3 = -1;		/* default to unsupplied values */
X	(void) alarm(WAITTIME);			/* set timeout */
X	DO DEBUG(" doing first scanf\n");
X	(void) scanf("\033[?%d;%d;%dc", &num1, &num2, &num3);
X	(void) alarm(0);				/* cancel alarm */
X	DO DEBUG("read ESC [ ? %d ; %d; %d c\n", num1, num2, num3);
X	if (num1 != 8 || num2 != 10)
X		return ( 0 );				/* not correct response or layers term ID */
X
X	/* ask terminal if ENC_ENABLE is to be forced */
X	DO DEBUG("write: ESC [ F\n");
X	(void) printf("\033[F");
X	FLUSH;							/* force output buffer */
X	(void) alarm(WAITTIME);			/* set timeout */
X
X	/* attempt to read "ESC [ flag F" (flag indicates ENC_ENABLE status) */
X	num1 = -1;						/* default to invalid response */
X	(void) scanf("\033[%dF", &num1);
X	(void) alarm(0);				/* cancel alarm */
X	DO DEBUG("read ESC [ %d F\n", num1);
X	if (num1 != 2 && num1 != 0)
X		return ( 0 );				/* something's wrong */
X
X	/* now startup packet mode in non ENC_ENABLE processing */
X	DO DEBUG("write: ESC [ 2 ; 0 v\n");
X	(void) printf("\033[2;0v");		/* "ESC [ 2 ; 0 v" */
X	FLUSH;							/* force output buffer */
X
X	/* we are now in packet mode */
X	sleep( INITTIME );				/* let Macintosh keep up with us */
X	return ( 1 );					/* return successful startup */
X
X} /* Initlink() */
X
X
X			/* TopChannel() - return highest prority channel */
X
Xint
XTopChannel()
X{
X	return ( Instream );
X
X} /* TopChannel() */
X
X
X	/*
X	** WARNING: Most of the following functions may be recursively called
X	**			as control commands are processed from the input stream
X	*/
X
X
X			/* ProcessStreamin() - MacLayers has input to process */
X
Xvoid
XProcessStreamin()
X{
X	int		c;						/* input character being processed */
X
X	DO DEBUG("ProcessStreamin()\n");
X
X	GetData(0);						/* read some and don't timeout */
X
X	while (insize > 0)				/* while more data to process ... */
X		Parse();					/* process next chuck of data */
X
X} /* ProcessStreamin() */
X
X
X		/* SendNew() - request new layer channel from MacLayers */
X
X/*	This command is unique in that it returns a response from MacLayers.
X**	To do this we continue processing the input stream until we get
X**	our return. (This leads to recursive conditions.) The variables
X**	'SNresp', 'SNshape' and 'SNchan' are set when our reply is received.
X*/
Xint
XSendNew(shape)
Xstruct Shape	*shape;				/* shape to use for new window */
X{
X	int			i;					/* attribute count variable */
X	char		astring[ATTRSIZE];	/* copy of attribute string */
X
X	DO DEBUG("SendNew() new layer requested: '~%cA'\n", '1'+ATTRSIZE);
X
X	/* check for a recursive call */
X	if (SNresp == SN_WAITING)
X	  {	DO DEBUG("return 0 - recursive call\n");
X		return ( 0 );				/* return failure */
X	  }
X
X	putchar(ESCAPE);				/* send start of control packet char */
X	putchar('1' + ATTRSIZE);		/* send command size */
X	putchar('A');					/* send command */
X	asciishape(shape, astring);		/* convert shape to string */
X	for (i=0; i < ATTRSIZE; i++)
X		putchar(astring[i]);		/* send next attribute digit */
X	FLUSH;
X
X	/* now stay here and process the input stream until we see our response */
X/**** THIS SHOULD BE ENHANCED TO TIMEOUT WITH GetData() AND REISSUE REQUEST */
X	SNresp = SN_WAITING;			/* indicate we are waiting a response */
X	while (SNresp == SN_WAITING)
X	  { DO DEBUG(" while (SNresp %d == %d)\n", SNresp, SN_WAITING);
X		AwaitInput();				/* wait till input from MacLayers arrives */
X		ProcessStreamin();			/* process available input */
X	  }
X
X	if (SNresp == -1)				/* if Maclayers rejected request */
X		SNchan = 0;					/* return failure channel of zero */
X	else
X		*shape = SNshape;			/* else update shape structure */
X
X	DO DEBUG("SendNew() returning channel %d\n", SNchan);
X
X	return ( SNchan );				/* return the indicated channel */
X
X} /* SendNew() */
X
X
X			/* SendReshape() - send to shape to MacLayers */
X
Xvoid
XSendReshape(chan, shape)
Xint				chan;				/* channel shape belongs to */
Xstruct Shape	*shape;				/* shape to use for new window */
X{
X	int			i;					/* attribute count variable */
X	char		astring[ATTRSIZE];	/* copy of attribute string */
X
X	DO DEBUG("SendReshape() reshape: '~%cA'\n", '2'+ATTRSIZE);
X
X	if (chan <= 0 || chan > MAXPCHAN)
X	  {	DO DEBUG("BAD CHANNEL!!!\n");
X		return;						/* ignore request */
X	  }
X
X	putchar(ESCAPE);				/* send start of control packet char */
X	putchar('2' + ATTRSIZE);		/* send command size */
X	putchar('R');					/* send command */
X	putchar(chan + '0');			/* send channel */
X	asciishape(shape, astring);		/* convert shape to string */
X	DO DEBUG("shape: %.*s\n", ATTRSIZE, astring);
X	for (i=0; i < ATTRSIZE; i++)
X		putchar(astring[i]);		/* send next attribute digit */
X	FLUSH;
X
X} /* SendReshape() */
X
X
X			/* SendTitle() - set layer's window title */
X
Xvoid
XSendTitle(chan, buff, cnt)
Xint			chan;					/* layer window ID */
Xchar		*buff;					/* new title string */
Xint			cnt;					/* count of title length */
X{
X	int		i;						/* work variable */
X
X	DO DEBUG("SendTitle(chan%d, len %d, '%.*s')\n", chan, cnt, cnt, buff);
X
X	if (chan <= 0 || chan > MAXPCHAN)
X	  {	DO DEBUG("BAD CHANNEL!!!\n");
X		return;						/* ignore request */
X	  }
X
X	if (cnt < 0)
X	  {	DO DEBUG("BAD COUNT!!!\n");
X		return;						/* ignore request */
X	  }
X
X	/* for now chop title size to 29 chars since that's MacLayer's limit */
X	if (cnt > 29)
X		cnt = 29;					/* due to packet size limit */
X
X	/* we must guarantee that the size will not appear to be another ESCAPE */
X	if ('2' + cnt == ESCAPE)
X		cnt--;						/* truncate to avoid ESCAPE ESCAPE */
X	
X	putchar(ESCAPE);				/* send start of control packet char */
X	putchar('2' + cnt);				/* send size of packet */
X	putchar('T');					/* send command */
X	putchar(chan + '0');			/* send channel ID */
X	for (i=0; i<cnt; i++)
X		putchar(buff[i]);			/* send out title */
X	FLUSH;
X
X} /* SendTitle() */
X
X
X			/* SendDelete() - tell Maclayers layer died */
X
Xvoid
XSendDelete(chan)
Xint		chan;						/* dead channel ID */
X{
X	DO DEBUG("SendDelete(%d) '~2D%d'\n", chan, chan);
X
X	if (chan <= 0 || chan > MAXPCHAN) /* check channel ID */
X	  {	DO DEBUG("BAD CHANNEL!!!\n");
X		return;						/* ignore request */
X	  }
X
X	putchar(ESCAPE);				/* send control packet start char */
X	putchar('2');					/* send command size */
X	putchar('D');					/* send command character */
X	putchar(chan + '0');			/* channel ID in ascii */
X	FLUSH;
X
X} /* SendDelete() */
X
X
X			/* SendQuit() - order MacLayers to end layers mode */
X
Xvoid
XSendQuit(chan)
Xint		chan;						/* dead channel ID */
X{
X	DO DEBUG("SendQuit() '~1E'\n");
X
X	putchar(ESCAPE);				/* send control packet start char */
X	putchar('1');					/* send command size */
X	putchar('E');					/* send command */
X	FLUSH;
X
X} /* SendQuit() */
X
X
X			/* SendData() - send output to layer's window */
X
Xvoid
XSendData(chan, buff, cnt)
Xint			chan;					/* layer window ID */
Xunsigned char *buff;				/* new title string */
Xint			cnt;					/* count of title length */
X{
X	unsigned c;						/* output character being sent */
X
X	DO
X	  {	int		dcnt;
X
X		DEBUG("SendData(chan %d, len %d, '", chan, cnt, cnt, buff);
X		for (dcnt=0; dcnt<cnt; dcnt++)
X			DEBUG("%c", buff[dcnt]); /* dump each char so null doesn't stop */
X		DEBUG("')\n");
X	  }
X
X	if (chan <= 0 || chan > MAXPCHAN)
X	  {	DO DEBUG("BAD CHANNEL!!!\n");
X		return;						/* ignore request */
X	  }
X
X	/* if new output channel stream then prefix redirect command */
X	if (chan != Outstream)
X	  {	DO DEBUG("Redirecting output to %d '~2O%d'\n", chan, chan);
X		putchar(ESCAPE);			/* start of command sequence */
X		putchar('2');				/* send command size */
X		putchar('O');				/* send command */
X		putchar(chan + '0');		/* put out channel in ASCII */
X		Outstream = chan;			/* new output stream set */
X	  }
X
X	/* transmit the buffer converting the ESCAPE sequence to double ESCAPE */
X	while (cnt--)
X	  {	c = *buff++;				/* get next output character */
X#ifdef DUMPALL
X		DO DEBUG("outchar %c 0x%x\n", c, c);
X#endif
X		if (c == ESCAPE || c == (ESCAPE + 0x80))
X		  {	putchar(c);				/* put it out twice */
X#ifdef DUMPALL
X			DO DEBUG(" Doubled Escape!\n");
X#endif
X		  }
X		putchar(c);					/* write character out */
X	  }
X
X	FLUSH;							/* force out queued output characters */
X		
X} /* SendData() */
X
X
X			/* Parse() - process next chunk of input stream */
X
Xstatic void
XParse()
X{
X#define	ST_NULL		0				/* not primed for next state yet */
X#define	ST_STREAM	1				/* processing default stream input */
X#define	ST_PKT		2				/* processing packet data */
X
X	int		c;						/* input character being processed */
X
X	static	int state = ST_NULL;	/* current input state */
X	static	int psize = 0;			/* packet size */
X	static	int	rempsize = 0;		/* remembered packet size */
X	static	char pdata[MAXSTR];		/* area for packet data */
X	static	char *ppos;				/* packet read insert position */
X	static	int escapemode = 0;		/* processing escape character */
X	static	int	escapechar;			/* escape character being processed */
X	static	pchan = -1;				/* packet input stream channel */
X
X	while (insize-- > 0)			/* while more data */
X	  {	c = *inpos++;				/* get next character */
X		switch (state)				/* process according to state */
X		{ case ST_NULL:				/* prepare for new packet */
X			DO DEBUG("ST_NULL\n");
X			psize = 0;				/* clear packet size */
X			ppos = pdata;			/* start fill at data position */
X			pchan = Instream;		/* packet channel is current input stream */
X			state = ST_STREAM;		/* default is stream processing */
X
X		  case ST_STREAM:
X			/* stream keyboard input for layer */
X			/* check for escape char with possible high bit on */
X#ifdef DUMPALL
X			DO DEBUG("ST_STREAM %x/%x esc %d insz %d\n",
X						c, c & 0x7f, escapemode, insize);
X#endif
X			if (c == ESCAPE || c == (ESCAPE | 0x80))
X		 	 {	if (escapemode && c == escapechar) /* previous was ESCAPE */
X				/* this is really a single ESCAPE character */
X					escapemode = 0;		/* back out of ESCAPE mode */
X				else
X					/* what do we do with back to back esc esc+0x80 ? */
X				  {	/* flag in escape mode */
X					escapemode++;
X					escapechar = c;		/* remember character used for escape */
X					continue;			/* and continue scan */
X				  }
X			  }
X			else
X			if (escapemode)
X			  { /* this is the start of a control packet */
X				if (psize)				/* if we have previous data packet */
X					Packet(pchan, psize, pdata); /* finish up previous pkt */
X				/* process packet size */
X				psize = (c & 0x7f) - '0'; /* save size byte */
X				if (psize <= 0 || psize > MAXSTR)
X				  {	/* bad size */
X					DO DEBUG("Bad pkt size %d\n", psize);
X					break;				/* trash this packet */
X				  }
X				rempsize = psize;		/* remember this size for later */
X#if 0
X				ptimo = rtimo;			/* start receive timeout */				
X#endif
X				escapemode = 0;			/* escape mode now off */
X				ppos = pdata;			/* initialize data store pointer */
X				state = ST_PKT;			/* expect packet data next */
X				continue;				/* continue scan */
X			  }
X				  
X			/* process standard data output character for current stream */
X			
X			*ppos++ = c;				/* save next data character */
X				
X			if (++psize >= MAXSTR)		/* if packet full ... */
X			  {	Packet(pchan, psize, pdata); /* process this packet */
X				break;					/* end packet processing */
X			  }				  
X			continue;					/* continue scan */
X												
X		  case ST_PKT:
X			/* process next paket data byte */
X			*ppos++ = c & 0x7f;		/* store next data byte */
X#ifdef DUMPALL
X			DO DEBUG("ST_PKT: %x sz %d\n", c & 0x7f, psize);
X#endif
X			if (--psize != 0)
X				continue;
X#if 0
X			if (crc((unsigned char *) &rpkt, rpkt.pkt.HEADER_DSIZE+2))
X				STATS(Scrcerr);			/* communications error */
X			else
X#endif
X			Packet(0, rempsize, pdata); /* process it */
X				
X			} /* end build packet switch */
X			
X#if 0
X		ptimo = 0;						/* no more receive timeout */
X#endif
X		state = ST_NULL;				/* no more receive packet in progress */
X			
X	  } /* end while (insize) */
X		  
X	if (state == ST_STREAM && psize )	/* if we have some data ... */
X	  {	Packet(Instream, psize, pdata); /* process this data */
X#if 0
X		ptimo = 0;						/* no more receive timeout */
X#endif
X		state = ST_NULL;				/* no more receive packet in progress */
X	  }
X
X} /* Parse() */
X
X
X		/* Packet() - prcess next input data string or control packet */
Xstatic void
XPacket(chan, size, buff)
Xint			chan;						/* channel (0 if control packet) */
Xint			size;						/* amount of data */
Xchar		*buff;						/* pointer to packet data */
X{
X	static struct Shape shape;			/* Shape structure */
X
X	DO DEBUG("Packet(chan %d, size %d, '%.*s')\n", chan, size, size, buff);
X
X	/* verify channel */
X	if (chan < 0 || chan > MAXPCHAN)
X	  {	DO DEBUG("BAD CHANNEL!!\n");
X		return;							/* ignore bad channel */
X	  }
X
X	/* if data packet (chan>0) feed data to server */
X	if (chan > 0)
X	  {	ReceiveData(chan, buff, size);
X		return;							/* we are through */
X	  }
X
X	/* control packet (channel 0) */
X	chan = buff[1] - '0';				/* assume channel specified */
X	if (chan < 0 || chan > MAXPCHAN)	/* if invalid ... */
X		chan = 0;						/* set to zero */
X
X	switch (buff[0])
X	{ case 'I':		/* redirect stream */
X		DO DEBUG("CMD 'I' redirect stream to %c\n", buff[1]);
X		if (size != 2)					/* verify size */
X			break;						/* break if bad */
X		if (chan == 0)					/* verify channel */
X			break;						/* break if bad */
X		Instream = chan;				/* new instream channel */
X		return;							/* we are through */
X
X	  case 'A':		/* returned A_NEWLAYER packet */
X		DO DEBUG("CMD 'A' A_NEWLAYER response %c newchan %c SNresp %d\n",
X					buff[2], buff[1], SNresp);
X		if (size != 3 + ATTRSIZE)
X			break;						/* break if bad */
X
X		/* if SendNew() not waiting for a response this is invalid */
X		if (SNresp != SN_WAITING)
X			break;						/* break if bad */
X
X		if (buff[2] == '1')				/* if response is "failed" ... */
X			SNresp = -1;				/* show -1 response */
X		else
X		if (buff[2] == '0')				/* if response is "success" ... */
X		  {	if (chan == 0)				/* if invalid channel */
X				break;					/* break if bad */
X			/* build shape structure for SendNew() */
X			if (parseshape(&SNshape, &buff[3]) == -1)
X				break;					/* if invalid data then bad packet */
X			SNresp = 0;					/* show good response */
X			SNchan = chan;				/* indicate channel returned */
X		  }
X		else
X			break;						/* break if bad */
X
X		DO DEBUG("SNresp = %d, SNchan = %d\n", SNresp, SNchan);
X		return;							/* we are through */
X		
X	  case 'N':		/* new layer creation */
X		DO DEBUG("CMD 'N' new layer creation newchan %c\n", buff[1]);
X		if (size != 2 + ATTRSIZE)		/* verify size */
X			break;						/* break if bad */
X		if (chan == 0)					/* verify channel */
X			break;						/* break if bad */
X		/* build shape structure */
X		if (parseshape(&shape, &buff[2]) == -1)
X			break;						/* if invalid data then bad packet */
X		ReceiveNew(chan, &shape);		/* pass to server */
X		return;							/* packet is done */
X
X	  case 'D':		/* deleted layer */
X		DO DEBUG("CMD 'D' deleted layer %c\n", buff[1]);
X		if (size != 2)					/* verify size */
X			break;						/* break if bad */
X		if (chan == 0)					/* verify channel */
X			break;						/* break if bad */
X		ReceiveDelete(chan);			/* pass on to server */
X		return;							/* packet is done */
X
X	  case 'E':		/* exit - awaiting shutdown */
X		DO DEBUG("CMD 'E' exit MacLayers awaiting shutdown msg\n");
X		if (size != 1)					/* verify size */
X			break;						/* break if bad */
X		ReceiveQuit();					/* pass to server */
X		/* NOT REACHED*/
X		return;							/* ?? should never reach here */
X
X	  case 'R':		/* reshaped */
X		DO DEBUG("CMD 'R' reshape chan %c\n", buff[1]);
X
X		if (size != 2 + ATTRSIZE)		/* verify size */
X			break;						/* break if bad */
X
X		if (chan == 0)					/* verify channel */
X			break;						/* break if bad */
X
X		/* build shape structure */
X		if (parseshape(&shape, &buff[2]) == -1)
X			break;						/* if invalid data then bad packet */
X
X		ReceiveReshape(chan, &shape); 	/* tell server about shape */
X		return;							/* packet processed */
X
X	  case 'S':		/* signal */
X		DO DEBUG("CMD 'S' SIGNAL chan %c sig %c\n", buff[1], buff[2]);
X		if (size != 3)					/* verify size */
X			break;						/* break if bad */
X		if (chan == 0)
X			break;						/* break if bad */
X
X		if (buff[2] == '0')				/* if SIGINT */
X			size = SIGINT;				/* yes */
X		else
X		if (buff[2] == '1')				/* if SIGHUP */
X			size = SIGHUP;				/* yes */
X		else
X			break;						/* invalid signal */
X			
X		ReceiveSignal(chan, size);		/* pass to server */
X		return;							/* packet processed */
X
X	  default:
X		DO DEBUG("ILLEGAL CONTROL PACKET!!!\n");
X		return;							/* ignore bad packet */
X
X	} /* end command packet switch */
X
X	/* switch falls out if bad size or channel for given command */
X	DO DEBUG("Invalid size or channel!!!\n");	/* dump error */
X	return;								/* ignore packet */
X
X} /* Packet() */
X
X
X			/* GetData() - read next input from MacLayers stream */
X
X/*	An input timout parameter can indicate that we return if nothing
X**	is read within a certain amount of seconds. The return code is:
X**
X**		0 - timeout occured and no data was read
X**
X**		1 - no timeout occured, data read
X*/
Xstatic int
XGetData(timeout)
Xint			timeout;				/* timeout in seconds (or zero) */
X{
X	int		result;					/* return from read() */
X
X	DO DEBUG("GetData(timout %d)\n", timeout);
X
X	/* if buffer still has data simply return (SHOULD NOT OCCUR?) */
X	if (insize > 0)
X		return ( 1 );				/* act as through data read */
X	inpos = inbuff;					/* next get will start at beginning */
X	insize = 0;						/* default insize back to zero */
X
X	/* set timeout if we are to do so */
X	if (timeout)
X		(void) alarm(timeout);		/* set timeout in seconds */
X
X	/* do the read from stdin */
X	result = read(0, inbuff, IOSIZE);
X
X	/* if alarm was set cancel it now */
X	if (timeout)
X		(void) alarm(0);			/* cancel alarm */
X
X	/* check for timeout or error */
X	/* EWOULDBLOCK for no data avail -(but we should not see this) */
X	/* EINTR if signal stopped the read -(rare but could happen) */
X	if (result <= 0)
X		return ( 0 );				/* return nothing read */
X
X	/* return with fresh buffer data */
X	insize = result;
X	DO DEBUG("read %d bytes\n", insize);
X	return ( 1 );					/* return OK code */
X
X} /* GetData() */
X
X
X			/* AwaitInput() - wait for more input from MacLayers */
X
Xstatic void
XAwaitInput()
X{
X	int		r;						/*  read descriptor bits */
X
X	DO DEBUG("AwaitInput()\n");
X
X	do
X	  {	r = 1<<0;					/* wait for read from input device */
X		if (select(32, &r, NULL, NULL, NULL) == -1)	/* if problem waiting ... */
X		  {	if (errno != EINTR)			/* if not simply signal taken ... */
X			  {	/* SHOULD NOT OCCUR - shutdown layers */
X				DO DEBUG("AwaitInput: select error %d\n", errno);
X				printf("layers: AwaitInput: bad select %d\n", errno);
X				FQuit();					/* shutdown layers */
X				/* NOT REACHED */
X			  }
X		  }
X	  } while ((r & 1<<0) == 0);
X		
X} /* AwaitInput() */
X
X				/* asciishape() - convert Shape structure to ASCII */
Xstatic void
Xasciishape(shape, loc)
Xstruct Shape	*shape;						/* Shape structure for channel */
Xchar			*loc;						/* location to start filling result */
X{
X	char		*origloc;					/* (for debuggin) */
X
X	origloc = loc;							/* remember start of string */
X	fill4(&loc, shape->worigh);				/* origin h */
X	fill4(&loc, shape->worigv);				/* origin v */
X	fill2(&loc, shape->wlines);				/* lines high */
X	fill2(&loc, shape->wchars);				/* chars wide */
X	fill1(&loc, shape->wfont);				/* font size */
X	fill2(&loc, shape->wattr);				/* attributes */
X
X	DO DEBUG("asciishape(): %.*s\n", ATTRSIZE, origloc);
X
X} /* asciishape() */
X
X
X					/* fill4() - convert parameter to ASCII */
X
Xstatic void
Xfill4(loc, valu)
Xchar		**loc;							/* pointer to fill area pointer */
Xunsigned	valu;							/* value to use */
X{
X	fill2(loc, valu>>8);					/* fill high half word */
X	fill2(loc, valu & 0xff);				/* fill low half word */
X
X} /* fill4() */
X
X
X					/* fill2() - convert parameter to ASCII */
X
Xstatic void
Xfill2(loc, valu)
Xchar		**loc;							/* pointer to fill area pointer */
Xunsigned	valu;							/* value to use */
X{
X	fill1(loc, valu>>4);					/* fill high byte */
X	fill1(loc, valu & 0xf);					/* fill low byte */
X	
X} /* fill2() */
X
X
X					/* fill1() - convert parameter to ASCII */
X
Xstatic void
Xfill1(loc, valu)
Xchar		**loc;							/* pointer to fill area pointer */
Xunsigned	valu;							/* value to use */
X{
X	*(*loc)++ = "0123456789ABCDEF"[valu & 0xf]; /* return hex value */
X
X} /* fill1() */
X
X
X			/* parseshape() - convert ASCII image to Shape structure */
X				
Xstatic int	Badconvert;						/* indicates bad conversion */
X
Xstatic int
Xparseshape(shape, loc)
Xstruct Shape	*shape;						/* Shape structure for channel */
Xchar			*loc;						/* location to start parsing */
X{
X	Badconvert = 0;							/* clear bad characters indicator */
X	shape->worigh = get4(&loc);				/* origin h */
X	shape->worigv = get4(&loc);				/* origin v */
X	shape->wlines = get2(&loc);				/* lines high */
X	shape->wchars = get2(&loc);				/* chars wide */
X	shape->wfont = get1(&loc);				/* font size */
X	shape->wattr = get2(&loc);				/* attributes */
X
X    DO DEBUG("ParseShape(): origv %d, origh %d, lines %d, chars %d\n",
X                shape->worigv, shape->worigh, shape->wlines, shape->wchars);
X    DO DEBUG("   font %d, attr 0x%x, badconv %d\n",
X					shape->wfont, shape->wattr, Badconvert);
X
X	return ( Badconvert ? -1 : 0 );			/* return conversion code */
X
X} /* parseshape() */
X
X
X					/* get4() - convert ASCII to parameter */
X
Xstatic unsigned
Xget4(loc)
Xchar		**loc;							/* pointer to fill area pointer */
X{
X	unsigned	hi;							/* high portion */
X	unsigned	low;						/* low portion */
X
X	hi = get2(loc);							/* get high byte */
X	low = get2(loc);						/* get low byte */
X
X	return ( (hi<<8) + low );				/* return word value */
X
X} /* get4() */
X
X
X					/* get2() - convert ASCII to parameter */
X
Xstatic unsigned
Xget2(loc)
Xchar		**loc;							/* pointer to fill area pointer */
X{
X	unsigned	hi;							/* high portion */
X	unsigned	low;						/* low portion */
X
X	hi = get1(loc);							/* get high half */
X	low = get1(loc);						/* get low half */
X
X	return ( (hi<<4) + low );				/* return byte value */
X	
X} /* get2() */
X
X
X					/* get1() - convert ASCII to parameter */
X
X/*	This function sets 'Badconvert' if an invalid character is detected */
X
Xstatic unsigned
Xget1(loc)
Xchar		**loc;							/* pointer to fill area pointer */
X{
X	int			c;							/* character to convert */
X	
X	c = *(*loc)++;							/* fetch character */
X	
X	if (c >= '0' && c <= '9')
X		/* zero through nine */
X		return ( c - '0' );					/* return it's binary value */
X	
X	if (c >= 'a' && c <= 'f')
X		/* lower case hex */
X		return ( c - 'a' + 10);				/* return it's binary value */
X		
X	if (c >= 'A' && c <= 'F')
X		/* upper case hex */
X		return ( c - 'A' + 10);				/* return it's binary value */
X		
X	/* invalid digit! */
X	Badconvert++;							/* set bad character flag */
X	return ( 0 );							/* return a zero */
X
X} /* get1() */
SHAR_EOF
if test 25546 -ne "`wc -c < 'protocol.c'`"
then
	echo shar: error transmitting "'protocol.c'" '(should have been 25546 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 2 ---
Technical Details
Message-ID: <1990Jun1.190100.8893@dhw68k.cts.com>
Path: arc1-ca.pugleaf.net!wuarchive!swbatl!texbell!cs.utexas.edu!usc!elroy.jpl.nasa.gov!zardoz.cpd.com!dhw68k!macintosh
References: <1990Jun1.070105.1489@dhw68k.cts.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!wuarchive!swbatl!texbell!cs.utexas.edu!usc!elroy.jpl.nasa.gov!zardoz.cpd.com!dhw68k!macintosh
From: werner@rascal.ics.utexas.edu (Werner Uhrig)
Newsgroups: comp.sources.mac
Subject: MacLayers 1.00 (part 2 of 6)
Message-ID: <1990Jun1.190100.8893@dhw68k.cts.com>
Date: 1 Jun 90 19:00:09 GMT
References: <1990Jun1.070105.1489@dhw68k.cts.com>
Reply-To: layers@rascal.ics.utexas.edu
Organization: U. Texas CS Dept., Austin, Texas
Lines: 1814
Approved: bytebug@dhw68k.cts.com (Roger L. Long)