v01i005: xtclient: use a 3b1 as a layers terminal, Part02/04
Merlin J Mathesius
merlinm at i88.isc.com
Fri Feb 15 13:11:39 AEST 1991
Submitted-by: merlinm at i88.isc.com (Merlin J Mathesius)
Posting-number: Volume 1, Issue 5
Archive-name: xtclient/part02
---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is part 02 of xtclient
# ============= xtclient/frame.h ==============
if test ! -d 'xtclient'; then
echo 'x - creating directory xtclient'
mkdir 'xtclient'
fi
if test -f 'xtclient/frame.h' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/frame.h (File already exists)'
else
echo 'x - extracting xtclient/frame.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/frame.h' &&
/*
X * File name: frame.h
X *
X * Description: Definitions of frame and packet formats for the "xt/layers"
X * system for the UNIX-PC.
X *
X * Also includes macros for mapping frames to packets and
X * vice-versa.
X *
X * Author: Merlin J. Mathesius
X */
X
/*
X * Frame format for physical layer/data link layer interface:
X *
X * +---------------+--------------------------+---------------+
X * | header | information | crc-16 |
X * +---------------+--------------------------+---------------+
X * <-- 2 bytes --> <-- 0-32 bytes --> <-- 2 bytes -->
X *
X *
X * Frame header format:
X *
X * First byte: Second byte:
X * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
X * | 1 |ctl|addr |seq | |size |
X * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
X * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
X *
X * ctl - 1 if control frame, 0 if information frame
X * addr - the "address" of the window/process to send/receive frame (0 to 7)
X * seq - sequence number (0 to 7)
X * size - size of the information part of the frame (0 to 32)
X */
X
#define DAT_SZ 32
X
typedef unsigned char Byte;
X
typedef struct _Frame {
X Byte mark : 1; /* always 1 */
X Byte ctl : 1;
X Byte addr : 3;
X Byte seq : 3;
X Byte size : 8;
X Byte data[DAT_SZ];
X unsigned short crc;
} Frame;
X
/*
X * Packet format for data link layer/network layer interface:
X *
X * +-------+-------+--------------------------+
X * | addr | size | information |
X * +-------+-------+--------------------------+
X * 1 byte 1 byte <-- 0-32 bytes -->
X *
X */
typedef struct _Packet {
X Byte addr;
X Byte size;
X Byte data[DAT_SZ];
} Packet;
X
/* macro to provide simple mapping from an information frame to a packet */
#define FrmToPkt(p,f) \
X { \
X (p)->addr = (f)->addr; \
X (p)->size = (f)->size; \
X (void)memcpy((char *)(p)->data, (char *)(f)->data, (int)(f)->size); \
X }
X
/* macro to provide simple mapping from a packet to an information frame */
#define PktToFrm(f,p) \
X { \
X (f)->addr = (p)->addr; \
X (f)->size = (p)->size; \
X (void)memcpy((char *)(f)->data, (char *)(p)->data, (int)(p)->size); \
X (f)->mark = 1; \
X (f)->ctl = 0; \
X }
SHAR_EOF
chmod 0644 xtclient/frame.h ||
echo 'restore of xtclient/frame.h failed'
Wc_c="`wc -c < 'xtclient/frame.h'`"
test 2260 -eq "$Wc_c" ||
echo 'xtclient/frame.h: original size 2260, current size' "$Wc_c"
fi
# ============= xtclient/mgrwindow.c ==============
if test -f 'xtclient/mgrwindow.c' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/mgrwindow.c (File already exists)'
else
echo 'x - extracting xtclient/mgrwindow.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/mgrwindow.c' &&
/*
X * File name: mgrwindow.c
X *
X * Description: Windowing interface specific routines for the "xt/layers"
X * system for mgr.
X *
X * This version uses pty's to handle the 7 xt data streams and 1
X * parent window. All 8 bits of each stream are passed through
X * to mgr. This is completely transparent to mgr applications
X * but requires the xtclient process (This program) to run on
X * the mgr server host.
X * Window reshape events are not passed back to the agent or
X * xt driver. Use the mgr commands to determine window size
X * for aplications that need it. All window sizes are reported
X * to the xt server as 0, 0. This prevents the TERMCAP rows and
X * columns in BSD systems from being ignored. Use the mgr
X * set_termcap command as apropriate to set the TERMCAP
X * environment variable.
X *
X * Authors: Merlin J. Mathesius
X * Brad Bosch - mgr interface specific
X *
X * Contents: Winit() initialize windowing system
X * Wshutdown() shutdown windowing system
X * Wmpx() indication that multiplexed mode is starting
X * Wunmpx() indication that multiplexed mode is ending
X * Wcreate() create a new window
X * Wdestroy() destroy an existing window
X * Wselect() make a specified window current
X * Wshape() reshape/move a window
X * Wtop() pop a window to the top of window stack
X * Wbottom() push a window to the bottom of window stack
X * Winput() grab keyboard input from a window
X * Woutput() send output to a window
X * findwnum() find window corresponding to window id <local>
X * Wlabel() display label string on window
X *
X * Data: wind_fds bit map with current window file descriptor
X * Wready indicates unprocessed keyboard data remains
X */
X
#include <stdio.h>
#include <fcntl.h>
#ifdef sun
#include <termio.h>
#endif
#include <signal.h>
#include <string.h>
#include <varargs.h>
#ifndef sun
#include <macros.h>
#else
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
X
X
#include "term.h" /* mgr macros */
#include "xtclient.h"
#include "window.h"
#include "appl.h"
#include "command.h"
X
Xextern int readfds; /* bit map of readable file desc (dlutil.h) */
X
#define EVENT_BUT1 "n%R\n" /* button 1 down event */
X
#define NORMAL 1
#define ICON_NORMAL "tty"
#define MPX 2
#define ICON_MPX "ttys"
X
X
/* globally accessible data */
X
int wind_fds; /* bit map with current window file descriptor */
int Wready; /* indicates unprocessed keyboard data remains */
X
/* locally accessible data */
X
#define MENU_COUNT (sizeof(menu)/sizeof(struct menu_entry))
X
struct menu_entry menu[] = {
X "quit","q",
X "create window","c",
X "send break","b",
};
X
struct termio term; /* new termio struct for mgr control*/
struct termio orig_termio; /* initial saved termio for mgr control dev */
X
struct _w_info {
X int ptyfd; /* mgr window fd, not the same as array index */
X int inform; /* 0 = don't call APinform() if changes occur */
};
X
static struct _w_info w_info[MAXW+1]; /* NOTE: element 0 is unused */
X
/*from startup win */
static int def_pos_x, def_pos_y, def_height, def_width, def_font, border;
X
/* forward references */
static int findwnum();
static int Wlabel();
X
/*
X * Function name: Winit()
X *
X * Description: Initialize the windowing system.
X *
X * Parameters: None
X *
X * Return values: None
X */
void
Winit()
{
X int i;
X int w, h; /* scratch width and height */
X char my_host[32]; /* my-host */
X char mgr_host[32]; /* mgr host */
X
X /* clear out all window data structures */
X for (i = 1; i <= MAXW; i++)
X {
X w_info[i].ptyfd = -1;
X w_info[i].inform = 0;
X }
X
X /* set bit map of window file descriptors */
X wind_fds = 1; /* stdin */
X
X /* initialize MGR windowing system */
X /* M_DEBUG says use stdio for mgr */
X /* M_FLUSH says flush m_termout stream after every macro call */
X m_setup(M_DEBUG|M_FLUSH);
X
X get_param(mgr_host,NULL,NULL,NULL);
#ifndef BSD
#ifndef sun
X {
#include <sys/utsname.h>
X struct utsname hostnames;
X uname(&hostnames);
X strcpy(my_host, hostnames.nodename);
X }
#else
X gethostname(my_host,sizeof(my_host));
#endif
#else
X gethostname(my_host,sizeof(my_host));
#endif
X
X if (strcmp(my_host,mgr_host) != 0) {
X fprintf(stderr, "xtclient only works on local mgr host: %s\n",
X mgr_host);
X /* exit with error */
X exit(1);
X }
X
X /* grab a copy of the termio structure for mgr */
X if (ioctl(0, TCGETA, &orig_termio) < 0)
X {
X perror("ioctl(TCGETA)");
X
X /* exit with error */
X exit(1);
X }
X
X /* set up new termio modes for mgr */
X
X term = orig_termio;
X
X /* input modes: */
X /* IGNBRK - ignore incoming break */
X term.c_iflag = IGNBRK;
X
X /* do absolutely no output processing */
X term.c_oflag = 0;
X
X /* set hardware control flags: */
X /* CREAD - enable receiver (otherwise output only) */
X /* CS8 - 8 bit character size */
X /* B9600 - Aproximate baud rate form mgr */
X term.c_cflag = CREAD | CS8 | B9600;
X
X /* disable canonical processing */
X term.c_lflag = 0;
X
X /* input control characters */
X term.c_cc[VMIN] = 1; /* a read() is normaly permanently blocked */
X term.c_cc[VTIME] = 0;
X
X if (ioctl(0, TCSETA, &term) < 0)
X {
X perror("ioctl(TCSETA)");
X
X /* exit with error */
X exit(1);
X }
X
X /* prepare to set up termio modes for created "half" slave windows */
X term.c_cc[VMIN] = 0; /* a read() is not blocked */
X
X /* get initial window data and save it */
X m_push(P_BITMAP|P_CURSOR|P_EVENT|P_FLAGS|P_FONT|P_MENU|P_POSITION|
X P_TEXT|P_WINDOW);
X
X /* get size and font of startup window to use for defaults */
X get_size(&def_pos_x, &def_pos_y, &def_width, &def_height);
X get_param(NULL, NULL, NULL, &border);
X def_width += 2 * border;
X def_height += 2 * border;
X def_font = get_font(NULL, NULL);
X
X /* set modes and request events */
X
X /* main window creates others with this event or with menu */
X m_setevent(BUTTON_1, EVENT_BUT1);
X
X menu_load(1,MENU_COUNT,menu);
X m_selectmenu(1);
X
X if (!down_load(ICON_NORMAL,NORMAL,&w,&h))
X {
X fprintf(stderr, "Can't find icon %s\n", ICON_NORMAL);
X }
X else
X {
X if (!down_load(ICON_MPX,MPX,&w,&h))
X {
X fprintf(stderr, "Can't find icon %s\n", ICON_MPX);
X sleep(2);
X }
X m_shapewindow(def_pos_x, def_pos_y, 2*border+w, 2*border+h);
X m_clear();
X m_func(B_COPY);
X m_bitcopyto(0, 0, 999, 999, 0, 0, 0, NORMAL);
X
X }
X /* create initial window */
X (void)Wcreate(1, 0L, 0L, 0L, 0L, 0, 0);
}
X
/*
X * Function name: Wshutdown()
X *
X * Description: Shutdown the windowing system.
X *
X * Parameters: None
X *
X * Return values: Never returns!!!!!!
X */
void
Wshutdown()
{
X int wd; /* file descriptor of primary window */
X int i; /* loop index */
X char buf[80]; /* buffer for mgr response */
X
X /* close any open windows (except the startup window) */
X for (i = 1; i <= MAXW; i++)
X {
X if (w_info[i].ptyfd != -1) {
X (void)Wdestroy(i);
X /*(void)close(w_info[i].ptyfd); */
X }
X }
X
X /* restore tty modes */
X if (ioctl(0, TCSETA, &orig_termio) < 0)
X {
X perror("ioctl(TCSETA)");
X }
X
X /* restore initial window data (size, location, etc.) */
X m_popall();
X
X /* exit with successful return code */
X exit(0);
X
X /* NOTREACHED */
}
X
/*
X * Function name: Wmpx()
X *
X * Description: Perform whatever is necessary for windowing routines
X * to go into "multiplexed" (ie., multi window) mode.
X *
X * This will relabel the primary window to indicate that
X * it is multiplexed, and send a message back to the host
X * telling them about our size.
X *
X * Parameters: None
X *
X * Return values: None
X */
void
Wmpx()
{
X int cols, rows, width, height;
X
X /* relabel the primary window */
X Wlabel(w_info[1].ptyfd, "Window #1");
X m_bitcopyto(0, 0, 999, 999, 0, 0, 0, MPX);
X
X /* send information back to application layer about our window */
X /* tell it our width and height in both characters */
X /* and pixels */
X
#ifdef LATER
X /* get_colrow(&cols, &rows); */
X /* get_size(NULL, NULL, &width, &height); */
#else
X cols = rows = width = height = 0;
#endif
X (void)APinform(XtCreate, 1,
X (long)cols,
X (long)rows,
X (long)width,
X (long)height);
}
X
/*
X * Function name: Wunmpx()
X *
X * Description: Perform whatever is necessary for windowing routines
X * to return to "unmultiplexed" (ie., single window)
X * mode.
X *
X * This will destroy all but the primary window and
X * re-label the primary window to indicate that we are
X * unmultiplexed. It is assumed that the "mpx_flag"
X * has been reset prior to calling this function.
X *
X * Parameters: None
X *
X * Return values: None
X */
void
Wunmpx()
{
X int i; /* loop index */
X char buf[80]; /* buffer for mgr response */
X
X if (w_info[1].ptyfd == -1) {
X /* recreate initial window */
X (void)Wcreate(1, 0L, 0L, 0L, 0L, 0, 0);
X }
X
X /* close all but the startup window and window 1 */
X for (i = 2; i <= MAXW; i++)
X {
X if (w_info[i].ptyfd != -1) {
X (void)Wdestroy(i);
X }
X }
X
X /* relabel the primary window */
X Wlabel(w_info[1].ptyfd, "Not Multiplexed");
X m_bitcopyto(0, 0, 999, 999, 0, 0, 0, NORMAL);
}
X
/*
X * Function name: Wcreate(n, orig_x, orig_y, corn_x, corn_y, inform, nc)
X *
X * Description: Creates a new window. The window number to create
X * is passed in.
X *
X * Parameters: n window number to create, -1 if unknown
X * orig_x x-coordinate to place upper left corner
X * orig_y y-coordinate to place upper left corner
X * corn_x x-coordinate to place lower right corner
X * corn_y y-coordinate to place lower right corner
X * inform if not 0, inform application layer about
X * create, else keep quiet
X * nc if not 0, don't make the new window current
X * (Not used in mgr version)
X *
X * Note: If all of the above coordinates are 0, a default
X * window location will be chosen.
X *
X * Return values: -1 unable to create window
X * else window number
X */
int
Wcreate(n, orig_x, orig_y, corn_x, corn_y, inform, nc)
int n;
long orig_x, orig_y, corn_x, corn_y;
int inform, nc;
{
X register int wid; /* mgr number of window created */
X int rc; /* return code storage */
X int columns; /* width of new window in chars */
X int width; /* width of new window */
X int rows; /* height of new window in chars */
X int height; /* height of new window */
X char buf[80]; /* text string buffer */
X
X /* if window number is unknown, try to find one */
X if (n == -1)
X n = findwnum(-1);
X
X if (n < 1 || n > MAXW)
X /* invalid window number, can't create */
X return(-1);
X
X if (w_info[n].ptyfd != -1)
X /* window already exists */
X return(n);
X
X width = corn_x - orig_x;
X height = corn_y - orig_y;
X
X /* default height and width from startup window */
X if (height <= 0)
X height = def_height;
X if (width <= 0)
X width = def_width;
X
X /* default location based upon the window number */
X if (!orig_x)
X orig_x = 20*(n);
X if (!orig_y)
X orig_y = 10*(n);
X
X /* create the mgr window */
X /* m_halfwin(orig_x, orig_y, width, height); */
X printf("\033%d,%d,%d,%d%c",orig_x, orig_y, width, height,'z');
X fflush(stdout);
X
X m_gets(buf); /* get tty name */
X buf[strlen(buf) - 1] = '\0'; /* get rid of '\n' */
X
X wid = open(buf, O_RDWR);
X
X if (wid <= 0) {
X /* couldn't create requested window */
X perror("couldn't open tty");
X return(-1);
X }
X
X if (ioctl(wid, TCSETA, &term) < 0)
X {
X perror("ioctl(TCSETA)");
X close(wid);
X
X /* return with error */
X return(-1);
X }
X
X /* window created, store in info structure */
X w_info[n].ptyfd = wid;
X
X /* update bit map of window file descriptors */
X wind_fds |= 1 << wid;
X
X /* m_font(def_font) set font same as startup window */
X sprintf(buf,"%c%d%c",m_escchar, def_font, E_FONT);
X write(wid, buf, strlen(buf));
X
X /* m_clear() clear window after changing font to enable cut */
X sprintf(buf, "%c",C_FF);
X write(wid, buf, strlen(buf));
X
X /* supply a window name */
X if (n == 1)
X /* window 1 is created before being multiplexed */
X (void)sprintf(buf, "Not Multiplexed");
X else
X /* windows other than 1 can only be created when multiplexed*/
X (void)sprintf(buf, "Window #%d", n);
X Wlabel(wid, buf);
X
#ifdef LATER
X /* get window size in chars */
X get_colrow(&columns, &rows);
#else
X columns = 0; rows = 0;
#endif
X
X /* inform application layer about our creation now */
X if (inform)
X {
X /* inform application layer of our creation. */
X /* tell it our width and height in both characters */
X /* and pixels */
X (void)APinform(XtCreate, n,
X (long)columns,
X (long)rows,
X (long)width,
X (long)height);
X }
X
X /* set indicator for informing application layer about later changes*/
X w_info[n].inform = 1;
X
X /* return window number */
X return(n);
}
X
/*
X * Function name: Wdestroy(n)
X *
X * Description: Destroy the requested window.
X *
X * Parameters: n window number to destroy
X *
X * Return values: -1 error
X * 0 requested window destroyed (or already gone)
X */
int
Wdestroy(n)
int n;
{
X int wid;
X char buf[80];
X
X if (n < 1 || n > MAXW)
X /* invalid window number, can't delete */
X return(-1);
X
X /* grab id of this window */
X wid = w_info[n].ptyfd;
X
X if (wid == -1)
X /* window doesn't exist */
X return(0);
X
X /* don't inform application layer about our destruction (yet) */
X w_info[n].inform = 0;
X
X close(wid); /* this should cause mgr to destroy the window */
X
X /* remove entry from table */
X w_info[n].ptyfd = -1;
X
X /* update bit map of window file descriptors */
X wind_fds &= ~ (1 << wid);
X
X /* inform application layer of our destruction. */
X if (mpx_flag)
X (void)APinform(XtDelete, n, 0L, 0L, 0L, 0L);
X
X /* window destroyed */
X return(0);
}
X
/*
X * Function name: Wselect(n)
X *
X * Description: select the specified window as the current
X * input window.
X *
X * Parameters: n window number to select
X *
X * Return values: 0 succesfully selected
X * -1 error
X */
X
int
Wselect(n)
int n; /* window number to select */
{
X char buf[80];
X
X if (n < 1 || n > MAXW)
X /* invalid window number, can't select */
X return(-1);
X
X if (w_info[n].ptyfd == -1)
X /* window doesn't exist */
X return(-1);
X
X /* select the window */
X /* m_setmode(M_ACTIVATE); */
X sprintf(buf, "%c%d%c",m_escchar,M_ACTIVATE,E_SETMODE);
X write(w_info[n].ptyfd, buf, strlen(buf));
X
X return(0);
}
X
/*
X * Function name: Wshape(n, orig_x, orig_y, corn_x, corn_y)
X *
X * Description: Shape/move the specified window
X *
X * Parameters: n window number to shape/move
X * orig_x x-coordinate to place upper left corner
X * orig_y y-coordinate to place upper left corner
X * corn_x x-coordinate to place lower right corner,
X * if -1 width will remain unaffected
X * corn_y y-coordinate to place lower right corner,
X * if -1 height will remain unaffected
X *
X * Return values: 0 succesfully shaped/moved
X * -1 error
X *
X */
X
int
Wshape(n, orig_x, orig_y, corn_x, corn_y)
int n;
long orig_x, orig_y, corn_x, corn_y;
{
X int wid; /* window file descriptor */
X int width; /* width of window */
X int height; /* height of window */
X char buf[80];
X
X if (n < 1 || n > MAXW)
X /* invalid window number, can't select */
X return(-1);
X
X wid = w_info[n].ptyfd;
X
X if (wid == -1)
X /* window doesn't exist */
X return(-1);
X
#ifdef LATER
X /* read, set, and update the window parameters */
X get_size(NULL, NULL, &width, &height);
#endif
X width = def_width;
X height = def_height;
X if (corn_x != -1) width = corn_x - orig_x;
X if (corn_y != -1) height = corn_y - orig_y;
X
X /* m_shapewindow(orig_x, orig_y, width, height); */
X sprintf(buf, "%c%d,%d,%d,%d%c",m_escchar,orig_x,orig_y,width,height,
X E_SHAPE);
X write(wid, buf, strlen(buf));
X
X return(0);
}
X
/*
X * Function name: Wtop(n)
X *
X * Description: Pop specified window to the top of the window stack
X *
X * Parameters: n window number to pop
X *
X * Return values: 0 succesfully popped to top
X * -1 error
X */
X
int
Wtop(n)
int n;
{
X if (n < 1 || n > MAXW)
X /* invalid window number, can't select */
X return(-1);
X
X if (w_info[n].ptyfd == -1)
X /* window doesn't exist */
X return(-1);
X
X /* We can't do this: Popping the window to the top also selects it.*/
X
X return(-1);
}
X
/*
X * Function name: Wbottom(n)
X *
X * Description: Push specified window to bottom of window stack.
X *
X * Parameters: n window number to push
X *
X * Return values: 0 succesfully pushed to bottom
X * -1 error
X *
X */
X
int
Wbottom(n)
int n;
{
X char buf[80];
X
X if (n < 1 || n > MAXW)
X /* invalid window number, can't select */
X return(-1);
X
X if (w_info[n].ptyfd == -1)
X /* window doesn't exist */
X return(-1);
X
X /* bury the window */
X /* m_clearmode(M_ACTIVATE); */
X sprintf(buf, "%c%d%c", m_escchar, M_ACTIVATE, E_CLEARMODE);
X write(w_info[n].ptyfd, buf, strlen(buf));
X
X return(0);
}
X
/*
X * Function name: Winput(n, buf, nbytes)
X *
X * Description: Return available input from a window.
X *
X * Parameters: n pointer to store window number providing data
X * buf buffer in which to store data
X * nbytes maximum number of bytes return
X *
X * Return values: number of bytes of input returned
X *
X */
int
Winput(n, buf, nbytes)
int *n; /* returned window with available data */
char *buf; /* buffer in which to place data */
int nbytes; /* max number of bytes to read */
{
X int cr; /* single integer size character buffer */
X char c; /* single character buffer */
X int count; /* number of characters read */
X int rc; /* return code storage */
X int wn; /* window number */
X int newwn; /* window number from event */
X char tbuf[80]; /* temporary buffer for mgr events */
X static int lastfd = 1; /* last fd read or tested */
X static int flags = 0; /* last flags value fcntl on mgr fd */
X int fd; /* next fd to read */
X
X /* no characters read yet */
X count = 0;
X
X /* set non-blocking i/o */
X if (! flags) { /* first time only */
X flags = fcntl(0, F_GETFL, 0);
X }
X
X /* Do we have control window input? If so, process it. */
X if ((m_termin -> _cnt) || (readfds & 1))
X {
X rc = fcntl(0, F_SETFL, flags | O_NDELAY);
X
X while ((cr = m_getchar()) != EOF)
X {
X switch (cr)
X {
X case 'c': /* create window */
X /* if multiplexed, create new window*/
X if (mpx_flag) {
X fcntl(0, F_SETFL, flags);
X Wcreate(-1,0L,0L,0L,0L,1,0);
X }
X goto done;
X
X case 'q': /* quit */
X
X /* user wants to EXIT */
X
X /* if user has already requested to exit but*/
X /* we are still multiplexed, something hung;*/
X /* force multiplex flag to false. */
X if (user_exit && mpx_flag)
X mpx_flag = 0;
X
X /* set flag to request exit */
X user_exit = 1;
X
X /* if we are multiplexed, inform application*/
X /* layer that we wish to go down! */
X if (mpx_flag)
X (void)APinform(XtExit,wn,0L,0L,0L,0L);
X
X goto done;
X
X case 'n':
X /* mgr BUTTON_1 has been pressed... */
X /* if multiplexed, create new window*/
X /* of indicated shape */
X if (mpx_flag) {
X int x1, y1, x2, y2, x, y;
X
X fcntl(0, F_SETFL, flags);/* blocking*/
X m_gets(tbuf);
X sscanf(tbuf, "%d %d %d %d",
X &x1, &y1, &x2, &y2);
X
X /* find min and max coords */
X x = min(x1, x2);
X y = min(y1, y2);
X x2 = max(x1, x2);
X y2 = max(y1, y2);
X
X Wcreate(-1,x,y,x2,y2,1,0);
X }
X goto done;
X case 'b':
X /* send break on comunications line */
X /* not implemented yet */
X break;
X default:
X break;
X }
X }
X goto done; /* don't try to process other windows input */
X }
X
X /* find next fd with data ready */
X fd = lastfd + 1;
X if (fd >= 32)
X fd = 1;
X while(fd != lastfd) {
X if (wind_fds & readfds & (1 << fd))
X break;
X fd ++;
X if (fd >= 32)
X fd = 1;
X }
X lastfd = fd; /* set up for next time */
X wn = findwnum(fd);
X if (wn < 1) { /* sanity check */
X goto done;
X }
X
X count = read(fd, buf, nbytes); /* Returns 0 if no data ready */
X
X if (count < 1) { /* eof encountered ?*/
X /* user deleted this window, clean up */
X (void)Wdestroy(wn);
X /* can't do anything else with this window! */
X goto done;
X }
X
done:
X /* if input is still buffered, report it cause select can't see it */
X /* Note: This use of _cnt may not be portable, but an equivelent */
X /* can generally be found. */
X Wready = m_termin -> _cnt; /* setup ready indication */
X
X /* clear non-blocking mode */
X rc = fcntl(0, F_SETFL, flags);
X
X /* return window number and count of characters */
X *n = wn;
X return(count);
}
X
/*
X * Function name: Woutput(n, buf, nbytes)
X *
X * Description: Output information in window.
X *
X * Parameters: n window to receive output
X * buf buffer of data to output
X * nbytes number of bytes to output
X *
X * Return values: -1 - unsuccessful output
X * 1 - successful output
X */
int
Woutput(n, buf, nbytes)
int n; /* window number in which to output data */
char *buf; /* data to output */
int nbytes; /* number of bytes from "buf" to output */
{
X int fd; /* mgr descriptor for window */
X
X if (n < 1 || n > MAXW)
X /* invalid window number */
X return(-1);
X
X fd = w_info[n].ptyfd;
X
X /* window not opened, let's try to open it! */
X if (fd == -1)
X {
X (void)Wcreate(n, 0L, 0L, 0L, 0L, 1, 1);
X
X fd = w_info[n].ptyfd;
X
X if (fd == -1)
X /* can't create it, give up */
X return(-1);
X }
X
X /* output data with 1 write */
X write(fd, buf, nbytes);
X
X return(1);
}
X
/*
X * Function name: findwnum(wfd)
X *
X * Description: Finds the window number corresponding to the mgr
X * window fd passed in. If a -1 is passed in as
X * the fd, an unused but available window
X * number is returned.
X *
X * Parameters: wfd file descriptor to locate
X *
X * Return values: -1 - cannot locate requested information
X * n - window number corresponding to "wid"
X */
static int
findwnum(wfd)
int wfd; /* mgr window id to locate */
{
X register int i; /* loop index */
X
X /* locate requested window */
X for (i = 1; i <= MAXW; i++)
X if (w_info[i].ptyfd == wfd) return(i);
X
X return(-1);
}
X
/*
X * Function name: Wlabel(wfd, label)
X *
X * Description: Sets the label of the window corresponding
X * to the mgr window fd passed in.
X *
X * Parameters: wfd mgr window fd.
X * label string containing new label.
X *
X * Return values: -1 - relabel failed.
X * 0 - operation complete.
X */
static int
Wlabel(wfd, label)
int wfd; /* mgr window id */
char * label; /* label string */
{
X return -1; /* not working yet */
}
X
/* download icon */
X
int
down_load(name,where,w,h)
char *name; /* name of icon */
int where; /* scratchpad bitmap # */
int *w, *h; /* icon size */
{
X char buff[20];
X int n;
X
X m_bitfromfile(where,name);
X m_flush();
X m_gets(buff);
X n = sscanf(buff,"%d %d",w,h);
X if (n < 2)
X return(0);
X else
X return(1);
}
SHAR_EOF
chmod 0644 xtclient/mgrwindow.c ||
echo 'restore of xtclient/mgrwindow.c failed'
Wc_c="`wc -c < 'xtclient/mgrwindow.c'`"
test 22004 -eq "$Wc_c" ||
echo 'xtclient/mgrwindow.c: original size 22004, current size' "$Wc_c"
fi
# ============= xtclient/network.c ==============
if test -f 'xtclient/network.c' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/network.c (File already exists)'
else
echo 'x - extracting xtclient/network.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/network.c' &&
/*
X * File name: network.c
X *
X * Description: The network layer for the "xt/layers" client system on the
X * UNIX-PC.
X *
X * ==> !!! ==> !!! NOTE !!! <== !!! <==
X * The network layer intentionally "short circuits" the transport
X * layer of the ISO model and directly interfaces to the session
X * layer. The transport layer performs no useful function in
X * this program, so for efficiency it has been eliminated!
X *
X * Author: Merlin J. Mathesius
X *
X * Contents: NETinit() initialize the network layer
X * NETfromDL() accept a packet from the data link layer
X * NETtoDL() return a packet to the data link layer
X *
X * Data: None
X */
X
#include <stdio.h>
#include "frame.h"
#include "network.h"
#include "session.h"
X
/*
X * Function name: NETinit()
X *
X * Description: Initialize the network layer.
X *
X * Parameters: None
X *
X * Return values: None
X */
void
NETinit()
{
X /* nothing to do */
}
X
/*
X * Function name: NETfromDL(p)
X *
X * Description: Disassemble a packet from the data link layer and
X * send it directly to the session layer.
X *
X * Parameters: p pointer to packet from data link layer
X *
X * Return values: -1 error
X * 0 OK, packet successfully accepted
X */
int
NETfromDL(p)
Packet *p;
{
X register int rc;
X
X /* call session layer interface function */
X rc = SESind((int)p->addr, (char *)p->data, (int)p->size);
#ifdef EBUG
X if (rc < 0)
X (void)fprintf(stderr, "NETfromDL: bad return from SESind, %d\n", rc);
#endif
X return(rc);
}
X
/*
X * Function name: NETtoDL(p)
X *
X * Parameters: p packet buffer in which to assemble packet
X *
X * Description: Assemble a packet of data from the session layer
X * and return it to the data link layer.
X *
X * Return values: 0 packet successfully retreived (with data)
X * -1 no data, or error
X */
int
NETtoDL(p)
Packet *p;
{
X register int rc;
X int addr;
X
X /* call session layer interface function */
X rc = SESreq(&addr, (char *)p->data, DAT_SZ);
#ifdef EBUG
X if (rc < 0)
X (void)fprintf(stderr, "NETtoDL: bad return from SESreq, %d\n", rc);
#endif
X if (rc <= 0)
X /* no data, or error */
X return(-1);
X
X /* store address and size in packet buffer */
X p->addr = (Byte)addr;
X p->size = (Byte)rc;
X
X return(0);
}
SHAR_EOF
chmod 0644 xtclient/network.c ||
echo 'restore of xtclient/network.c failed'
Wc_c="`wc -c < 'xtclient/network.c'`"
test 2168 -eq "$Wc_c" ||
echo 'xtclient/network.c: original size 2168, current size' "$Wc_c"
fi
# ============= xtclient/network.h ==============
if test -f 'xtclient/network.h' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/network.h (File already exists)'
else
echo 'x - extracting xtclient/network.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/network.h' &&
/*
X * File name: network.h
X *
X * Description: External function and data declarations for network.c
X *
X * Author: Merlin J. Mathesius
X */
X
Xextern void NETinit();
Xextern int NETfromDL(), NETtoDL();
SHAR_EOF
chmod 0644 xtclient/network.h ||
echo 'restore of xtclient/network.h failed'
Wc_c="`wc -c < 'xtclient/network.h'`"
test 197 -eq "$Wc_c" ||
echo 'xtclient/network.h: original size 197, current size' "$Wc_c"
fi
# ============= xtclient/phone.c ==============
if test -f 'xtclient/phone.c' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/phone.c (File already exists)'
else
echo 'x - extracting xtclient/phone.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/phone.c' &&
/*
X * File name: phone.c
X *
X * Description: This file contains the "particulars" for dealing
X * with the internal modem of the AT&T UNIX-PC.
X *
X * Author: Merlin J. Mathesius
X * Ugly hacks: Brad Bosch ( hacks for suns and ptys )
X *
X * Contents: connect() establish a connection
X * disconnect() destroy a connection
X * isconnected() check if connected
X * translate_baud() translate baud rate
X *
X * Data: phone_fd phone device file descriptor
X */
X
#define R_OK 04
#define W_OK 02
#include <stdio.h>
#include <fcntl.h>
#include <termio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef sun
# include <dial.h>
# include <sys/phone.h>
#endif
#include <string.h>
#include <signal.h>
X
#include "phone.h"
X
static int translate_baud();
X
Xextern void perror(); /* not declared in any header file */
Xextern char * getenv();
X
#ifdef sun
# define LINE "/dev/cua0"
# define SPEED "2400"
# define BAUDRATE B2400
#else
# define LINE "/dev/ph0"
# define SPEED "1200"
# define BAUDRATE B1200
#endif sun
X
#ifndef sun
/* errors returned from dial() call, defined in /usr/include/dial.h */
X
static char *dial_errs[] = {
X "zero",
X "interrupt",
X "dialer hung",
X "no answer",
X "illegal baud-rate",
X "acu problem",
X "line problem",
X "can't open LDEVS",
X "device not available",
X "device unknown",
X "no device available at baud-rate",
X "no device known at baud-rate"
};
X
#endif not sun
static int is_phone = 0; /* flag set if device is PHDEV (phone.h) */
static int master; /* fd of master if pty mode */
static int slave;
static int child = 0; /* pid of child if we are parent in pty mode */
static char *line; /* file global copy of c_line from connect */
X
Xextern struct termio orig_termio;/* copy of stdin termio from mgrwindow.c */
X
int c_finish(); /* for forward reference */
X
X
/* global storage for phone device's file descriptor */
X
int phone_fd = -1;
X
/*
X * Function name: connect(number, c_line, speed)
X *
X * Description: Establishes a connection. If successful, file
X * descriptor of phone device is stored in "phone_fd"
X * so it is accessible by other modules for reading
X * and writing.
X *
X * Parameters: number telephone number to dial
X * c_line path to device to use (NULL for default)
X * speed desired baud rate string (NULL for default)
X *
X * Return values: -1 failed to connect
X * >= 0 file descriptor of phone device
X */
int
connect(number, c_line, speed)
char *number; /* number to dial */
char *c_line; /* path to device */
char *speed; /* speed string */
{
#ifndef sun
X CALL call;
X struct updata phone;
#endif not sun
X struct termio term;
X
X int fd; /* file descriptor of phone device */
X int rc; /* temporary storage for return codes */
X int baud; /* baud control mode from termio.h */
X
X /* set defaults */
X line = c_line;
X if (line == NULL) line = LINE;
X if (speed == NULL) speed = SPEED;
X if (strcmp(line, "pty") == 0)
X {
X line = "/dev/ptyXX";
X if (number[0] == 0)
X {
X number = getenv("SHELL");
X if (number == 0)
X number = "/bin/sh";
X }
X if (getmaster()) return(-1);
X
X (void) signal(SIGCLD, c_finish);
X child = fork();
X if (child < 0) {
X perror("fork");
X return(-1);
X }
X if (child == 0) {
X doshell(number);
X return(-1);
X }
X fd = master;
X /* phone device should not block */
X fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NDELAY);
X }
X else
X {
X /* open phone device */
X fd = open(line, O_RDWR | O_NDELAY, 0);
X if (fd < 0)
X {
X perror("open(phone device)");
X return(-1);
X }
X
#ifndef sun
X if (strncmp(line, PHDEV, sizeof(PHDEV)-1) == 0) {
X is_phone = 1;
X rc = ioctl(fd, PIOCGETP, &phone);
X if (rc < 0)
X {
X perror("ioctl(PIOCGETP)");
X /* don't abort... */
X }
X else
X {
X /* use touch tone dialing */
X phone.c_lineparam &= ~PULSE;
X phone.c_lineparam |= DTMF;
X /* set the internal speaker to something reasonable */
X phone.c_feedback &= ~(SOFTSPK | NORMSPK | LOUDSPK);
X phone.c_feedback |= (SPEAKERON | SOFTSPK);
X rc = ioctl(fd, PIOCSETP, &phone);
X if (rc < 0)
X {
X perror("ioctl(PIOCSETP)");
X /* don't abort... */
X }
X }
X }
X
#endif sun
X /* grab a copy of the termio structure for the line */
X rc = ioctl(fd, TCGETA, &term);
X if (rc < 0)
X {
X perror("ioctl(TCGETA)");
X /* don't abort... */
X }
X
X /* set the terminal characteristics */
X
X baud = translate_baud(speed);
X if (baud < 0) {
X (void)fprintf(stderr, "illegal speed: \"%s\"\n", speed);
X return -1;
X }
X
X /* input modes: */
X /* IGNBRK - ignore incoming break */
X term.c_iflag = IGNBRK;
X
X /* do absolutely no output processing */
X term.c_oflag = 0;
X
X /* set hardware control flags: */
X /* HUPCL - hangup on last close */
X /* CREAD - enable receiver (otherwise output only) */
X /* CS8 - 8 bit character size */
X /* baud - Baud rate from above */
X term.c_cflag = HUPCL | CREAD | CS8 | baud;
X
X /* default line discipline will be used */
X term.c_lflag = 0;
X
X /* input control characters */
X term.c_cc[VMIN] = 1; /* read at least 1 character */
X term.c_cc[VTIME] = 0; /* a read() is permanently blocked */
X
#ifndef sun
X /* close the file, it will be re-opened by dial() */
X (void)close(fd);
X
X /* setup call information */
X call.attr = &term;
X call.baud = call.speed = atoi(speed); /*set baud and speed*/
X call.line = strrchr(line, '/') + 1;
X call.telno = number;
X call.modem = 0;
X
X /* place the call... */
X fd = dial(call);
X if (fd < 0)
X {
X (void)fprintf(stderr, "dial failed: %s\n",
X dial_errs[-fd]);
X return(-1);
X }
X
#endif sun
X /* blocking mode required for dial with rs232 modems */
X term.c_cc[VMIN] = 0; /* a read() is not permanently blocked */
X term.c_cc[VTIME] = 1; /* if no data present, return after 1/10 sec*/
X ioctl(fd, TCSETA, &term); /* set non-blocking mode */
X }
X /* call was successfully dialed! */
X phone_fd = fd;
X
X /* return the file descriptor for the phone device */
X return(fd);
X
} /* end of connect() */
X
/*
X * Function name: disconnect()
X *
X * Description: Destroy a previously established connection
X *
X * Parameters: None
X *
X * Return values: -1 failed to disconnect
X * 0 disconnect succeeded
X *
X */
int
disconnect()
{
X int rc; /* return code from system calls */
X
X if (phone_fd < 0)
X return(-1);
X
#ifndef sun
X if (is_phone) {
X /* hangup phone line */
X rc = ioctl(phone_fd, PIOCDISC, (char *)0);
X if (rc < 0)
X {
X perror("ioctl(PIOCDISC)");
X }
X }
X
X /* undo previous dial() call */
X undial(phone_fd);
#endif sun
X
X /* close the phone device */
X (void)close(phone_fd);
X
X /* reset file descriptor */
X phone_fd = -1;
X
X return(0);
} /* end of disconnect() */
X
/*
X * Function name: isconnected()
X *
X * Description: Determine if a connection is established
X *
X * Parameters: None
X *
X * Return values: 1 connection is established
X * 0 no connection
X */
int
isconnected()
{
#ifndef sun
X struct updata phone;
#endif not sun
X
X /* phone device not open, not connected */
X if (phone_fd < 0)
X return(0);
X
X /* if not phone device, check if shell (pty) type connection */
X if (! is_phone)
X if (child == -1)
X return(0);
X else
X /* if child not dead assume connected (allows for callback) */
X return(1);
X
#ifndef sun
X /* can't get status, not connected */
X if (ioctl(phone_fd, PIOCGETP, &phone) < 0)
X return(0);
X
X /* if connected flag is set, connected */
X if (phone.c_linestatus & MODEMCONNECTED)
X return(1);
#endif not sun
X /* otherwise, not connected */
X return(0);
} /* end of isconnected() */
X
/* table of speed strings and corresponding baud rate constants from termio.h */
X
static struct trans {
X char *speed;
X int baud;
} trans[] = {
X {"0", 0},
X {"50", B50},
X {"75", B75},
X {"110", B110},
X {"134", B134},
X {"150", B150},
X {"200", B200},
X {"300", B300},
X {"600", B600},
X {"1200", B1200},
X {"1800", B1800},
X {"2400", B2400},
X {"4800", B4800},
X {"9600", B9600},
X {"19200", B19200},
};
X
/*
X * Function name: translate_baud(speed)
X *
X * Description: Find baud rate constant from speed
X *
X * Parameters: speed desired speed string
X *
X * Return values: >=0 value of coresponding baudrate from termio.h
X * -1 speed string not found
X */
static int
translate_baud(speed)
char *speed;
{
X int i;
X
X for (i=0; i < sizeof(trans)/sizeof(struct trans); ++i)
X {
X if (strcmp(speed, trans[i].speed) == 0)
X return trans[i].baud;
X }
X
X return -1;
X
} /* end of translate_baud() */
X
getmaster()
{
X char *pty, *bank, *cp;
X struct stat stb;
X
X pty = &line[strlen("/dev/ptyp")];
X for (bank = "pqrs"; *bank; bank++) {
X line[strlen("/dev/pty")] = *bank;
X *pty = '0';
X if (stat(line, &stb) < 0)
X break;
X for (cp = "0123456789abcdef"; *cp; cp++) {
X *pty = *cp;
X master = open(line, O_RDWR|O_NDELAY);
X if (master >= 0) {
X char *tp = &line[strlen("/dev/")];
X int ok;
X
X /* verify slave side is usable */
X *tp = 't';
X ok = access(line, R_OK|W_OK) == 0;
X *tp = 'p';
X if (ok) {
/*
X ok = ioctl(0, TCGETA, &sh_term);
X if (ok < 0)
X {
X perror("ioctl(TCGETA)");
X }
*/
X return(0);
X }
X (void) close(master);
X }
X }
X }
X fprintf(stderr, "Out of pty's\n");
X return(-1);
}
X
getslave()
{
X struct termio sh_term;
X int rc;
X
X line[strlen("/dev/")] = 't';
X slave = open(line, O_RDWR);
X if (slave < 0) {
X perror(line);
X return(-1);
X }
X /* set modes same as stdin but with 8 bit i/o */
X sh_term = orig_termio;
X sh_term.c_iflag &= ~(BRKINT | INPCK | ISTRIP);
X sh_term.c_cflag |= CS8;
X sh_term.c_cflag &= ~(PARENB);
X rc = ioctl(slave, TCSETA, &sh_term);
X if (rc < 0)
X {
X perror("ioctl(TCSETA)");
X /* don't abort... */
X }
X return(0);
}
X
#include <sys/wait.h>
X
c_finish()
{
X union wait status;
X register int pid;
X
X while ((pid = wait(&status)) > 0)
X if (pid == child)
X /* mark slave as dead for is isconnected() to see */
X slave = -1;
}
X
doshell(shell)
char * shell;
{
X int t;
X
X t = open("/dev/tty", O_RDWR);
X if (t >= 0) {
#ifdef sun
X (void) ioctl(t, TIOCNOTTY, (char *)0);
#endif
X (void) close(t);
X }
X setpgrp();
X (void) close(0);
X (void) close(1);
X (void) close(2);
X if (getslave()) return(-1);
X (void) close(master);
X (void) dup(slave);
X (void) dup(slave);
X execl(shell, "sh", "-i", 0);
X perror(shell);
X return(-1);
}
X
X
SHAR_EOF
chmod 0644 xtclient/phone.c ||
echo 'restore of xtclient/phone.c failed'
Wc_c="`wc -c < 'xtclient/phone.c'`"
test 10054 -eq "$Wc_c" ||
echo 'xtclient/phone.c: original size 10054, current size' "$Wc_c"
fi
# ============= xtclient/phone.h ==============
if test -f 'xtclient/phone.h' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/phone.h (File already exists)'
else
echo 'x - extracting xtclient/phone.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/phone.h' &&
/*
X * File name: phone.h
X *
X * Description: External function and data declarations for phone.c
X *
X * Author: Merlin J. Mathesius
X */
X
Xextern int connect(), disconnect(), isconnected();
X
Xextern int phone_fd;
SHAR_EOF
chmod 0644 xtclient/phone.h ||
echo 'restore of xtclient/phone.h failed'
Wc_c="`wc -c < 'xtclient/phone.h'`"
test 208 -eq "$Wc_c" ||
echo 'xtclient/phone.h: original size 208, current size' "$Wc_c"
fi
# ============= xtclient/phys.c ==============
if test -f 'xtclient/phys.c' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/phys.c (File already exists)'
else
echo 'x - extracting xtclient/phys.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/phys.c' &&
/*
X * File name: phys.c
X *
X * Description: Physical layer functions for "xt/layers" client system for the
X * UNIX-PC
X *
X * Author: Merlin J. Mathesius
X *
X * Contents: PHinit() Initialize the physical layer.
X * PHfromDL() Accept a frame from the data link layer.
X * PHtoDL() Return a frame to the data link layer.
X * PHreset() Reset (resynchronize) the physical layer <local>
X * PHquery() Assemble an incoming frame and return status
X * PHcrcinit() Initialize CRC generation tables <local>
X * PHcrc() Compute CRC value for a frame <local>
X *
X * Data: None
X */
X
#include <stdio.h>
#include "xtclient.h"
#include "datalink.h"
#include "phys.h"
#include "phone.h"
X
/* various states of an arriving frame for finite state machine */
Xenum FrmState {
X FrmNull, /* awaiting arrival of start of frame */
X FrmHeader, /* awaiting arrival of 2nd byte of header */
X FrmData, /* awaiting arrival of remaining data */
X FrmCRC, /* awaiting arrival of CRC */
X FrmDone /* frame arrived, awaiting acceptance of frame */
X /* by data link layer */
};
X
static Frame frame; /* current arriving frame */
static enum FrmState frame_state; /* state of current arriving frame */
static char *fp; /* pointer to next byte to receive */
static unsigned count; /* count of remaining bytes in state */
X
static int PHcrc();
static void PHreset(), PHcrcinit();
X
/*
X * Function name: PHinit()
X *
X * Description: Initialize the physical layer.
X *
X * Parameters: None
X *
X * Return values: None
X */
void
PHinit()
{
X /* reset to a known state */
X PHreset();
X
X /* initialize the CRC generation tables */
X PHcrcinit();
}
X
/*
X * Function name: PHfromDL(f)
X *
X * Description: Places a frame from the data link layer onto the
X * physical medium. Logging is also performed.
X *
X * Parameters: f pointer to frame to send
X *
X * Return values: total number of bytes in frame
X */
int
PHfromDL(f)
Frame *f;
{
X unsigned nbyte; /* number of bytes to write */
X int rc1, rc2; /* return code */
X
X /* compute the CRC for the frame (ignore return value) */
X (void)PHcrc(f);
X
X nbyte = f->size + 2; /* size of data portion plus header */
X
X /* write the data to the phone device */
X rc1 = write(phone_fd, (char *)f, nbyte);
#ifdef EBUG
X if (rc1 != nbyte)
X (void)fprintf(stderr, "PHfromDL: only wrote %d of %d data bytes\n",
X rc1, nbyte);
#endif
X
X /* write the CRC to the phone device */
X rc2 = write(phone_fd, (char *)&f->crc, sizeof(f->crc));
#ifdef EBUG
X if (rc2 != sizeof(f->crc))
X (void)fprintf(stderr, "PHfromDL: only wrote %d of %d CRC bytes\n",
X rc2, sizeof(f->crc));
#endif
X
X /* log the output if logging is turned on */
X if (olog_fd != -1)
X {
X (void)write(olog_fd, (char *)f, (unsigned)rc1);
X (void)write(olog_fd, (char *)&f->crc, (unsigned)rc2);
X }
X
X return(nbyte+sizeof(f->crc));
}
X
/*
X * Function name: PHtoDL(f)
X *
X * Description: Returns (to the data link layer) a frame received
X * from the physical layer. Unless a complete frame
X * has arrived, this function will return nothing.
X * Once the frame has been copied to the passed in
X * buffer, the current incoming frame buffer is reset
X * for the next frame.
X *
X * Parameters: f pointer to buffer for incoming frame
X *
X * Return values: 0 returned frame is valid
X * -1 no frame returned
X */
int
PHtoDL(f)
Frame *f;
{
X
X /* if there really isn't a frame to send back, return error */
X if (frame_state != FrmDone)
X return(-1);
X
X /* copy the frame to the passed in buffer */
X *f = frame;
X
X /* reset to accept next frame */
X PHreset();
X
X return(0);
}
X
/*
X * Function name: PHreset()
X *
X * Description: Reset the physical layer.
X *
X * Parameters: None
X *
X * Return values: None
X */
static void
PHreset()
{
X /* reset to the null state (waiting for start of frame) */
X frame_state = FrmNull;
X
X /* reset pointer to next byte to receive to beginning of frame */
X fp = (char *)&frame;
}
X
/*
X * Function name: PHquery()
X *
X * Description: Assembles an incoming frame and checks CRC of frame.
X * Status is returned to calling data link layer.
X *
X * This routine functions as a finite state machine.
X * All available data (up to a complete frame) is read
X * from the physical medium. If a complete frame is not
X * yet available, the current state is remembered and the
X * next call to this function will continue where the
X * previous call left off.
X *
X * Input logging is also done by this function if it is
X * turned on.
X *
X * Parameters: None
X *
X * Return values: 1 frame ready, call PHtoDL() to get it
X * 0 frame not ready
X * -1 CRC error, frame discarded
X */
int
PHquery()
{
X register int rc;
X
X switch (frame_state)
X {
X case FrmNull: /* awaiting arrival of start of frame */
X
X /* try to read first byte of header */
X rc = read(phone_fd, fp, (unsigned)1);
X if (rc <= 0)
X /* no data */
X return(0);
X
X /* log the input if logging is turned on */
X if (ilog_fd != -1)
X (void)write(ilog_fd, fp, (unsigned)1);
X
X
X /* The type first byte of a valid frame will have the */
X /* "mark" bit set to 1. Ignore if it is not set. */
XSyncStart: if (frame.mark != 1)
X return(0);
X
X /* first byte OK, move to next state... */
X frame_state = FrmHeader;
X fp++;
X
X /* FALLTHROUGH */
X
X case FrmHeader: /* awaiting arrival of 2nd byte of header */
X
X /* try to read remaining byte of header */
X rc = read(phone_fd, fp, (unsigned)1);
X if (rc <= 0)
X /* no data */
X return(0);
X
X /* log the input if logging is turned on */
X if (ilog_fd != -1)
X (void)write(ilog_fd, fp, (unsigned)1);
X
X /* Size of the data portion of the frame must be in */
X /* range. We are out of sync if it is out of range, */
X /* so retry to see if it is the first byte of the frame. */
X if (frame.size > DAT_SZ) {
X PHreset();
X /* move the byte back to the starting position */
X fp[0] = fp[1];
X goto SyncStart;
X }
X
X /* header is OK, we are expecting "size" bytes in the */
X /* data section of the frame. */
X
X frame_state = FrmData;
X fp++;
X count = frame.size;
X
X /* FALLTHROUGH */
X
X case FrmData: /* awaiting arrival of remaining data */
X
X if (count != 0)
X {
X rc = read(phone_fd, fp, count);
X if (rc <= 0)
X /* no data */
X return(0);
X
X /* log the input if logging is turned on */
X if (ilog_fd != -1)
X (void)write(ilog_fd, fp, (unsigned)rc);
X
X /* got some data, figure out what's left */
X count -= rc;
X fp += rc;
X
X if (count != 0)
X /* still need more data */
X return(0);
X }
X
X /* got all the data we need, move on to next state */
X
X frame_state = FrmCRC;
X fp = (char *)&frame.crc;
X count = sizeof(frame.crc);
X
X /* FALLTHROUGH */
X
X case FrmCRC: /* awaiting arrival of CRC */
X
X rc = read(phone_fd, fp, count);
X if (rc <= 0)
X /* no data */
X return(0);
X
X /* log the input if logging is turned on */
X if (ilog_fd != -1)
X (void)write(ilog_fd, fp, (unsigned)rc);
X
X count -= rc;
X fp += rc;
X
X if (count != 0)
X /* still need remaining byte(s) of CRC */
X return(0);
X
X /* We now have a complete frame! Check the CRC. */
X
X if (PHcrc(&frame))
X {
X /* Frame arrived damaged, discard and report error */
X PHreset();
X return(-1);
X }
X
X /* We have a happy, healthy frame! */
X
X frame_state = FrmDone;
X
X /* FALLTHROUGH */
X
X case FrmDone: /* frame arrived, awaiting acceptance of frame */
X
X return(1);
X
X default:
X
X /* Don't know how we got here, reset to known state */
X PHreset();
X return(0);
X }
}
X
/*
X * crctab[]
X *
X * 256 element generator table for CRC-16 (x**16 + x**15 + x**2 + 1)
X */
X
static unsigned short crctab[256];
X
/*
X * Function name: PHcrcinit()
X *
X * Description: Initialize the CRC-16 generation table.
X *
X * The operation is not exactly clear, but it produces
X * a lookup table compatible with the "xt/layers" CRC
X * generation!
X *
X * Parameters: None.
X *
X * Return values: None.
X */
static void
PHcrcinit()
{
X unsigned short ones[8]; /* 1-bits for each bit position */
X unsigned short poly[8]; /* polynomial table for each bit */
X register unsigned short gen; /* temporary CRC generator */
X register int i, j; /* loop counters */
X
X /* build the 1-bit and polynomial tables */
X for (i = 0; i < 8; i++)
X {
X ones[i] = 0x80 >> i;
X poly[i] = 0x6000 >> i ^ 0xc001;
X }
X
X /* generate the lookup table entries */
X for (i = 0; i < 256; i++)
X {
X gen = 0;
X
X /* loop for each bit of the byte */
X for (j = 0; j < 8; j++)
X if (i & ones[j]) /* if this bit is set */
X gen ^= poly[j]; /* divide in the polynomial */
X
X crctab[i] = gen; /* store the element */
X }
}
X
/*
X * Function name: PHcrc(f)
X *
X * Description: Compute the CRC value for the header and data
X * portions of the given frame.
X *
X * The computed CRC is always stored in the "crc"
X * area of the frame.
X *
X * Parameters: f pointer to frame in which to compute CRC
X *
X * Return values: 0 computed CRC matches that in frame buffer
X * -1 computed CRC differs from frame buffer
X */
static int
PHcrc(f)
Frame *f;
{
X register unsigned char *buf; /* pointer to next byte of frame */
X register unsigned short crc; /* calculated CRC value */
X register int cnt; /* byte count */
X
X /* byte count is size of data portion plus header */
X cnt = f->size + 2;
X
X /* starting point for CRC is beginning of header */
X buf = (unsigned char *)f;
X
X /* compute the CRC one byte at a time */
X
X crc = 0;
X while (cnt-- > 0)
X /* shift and divide by the CRC table entry */
X crc = (crc >> 8) ^ crctab[((*buf++)^crc)&0xff];
X
X /* now, point the buffer at the CRC area of the frame */
X buf = (unsigned char *)&f->crc;
X
X /* compare computed low and high order bytes to those in frame */
X if (buf[0] == (crc & 0xff) && buf[1] == ((crc >> 8) & 0xff))
X return(0);
X
X /* store the computed CRC in the frame */
X buf[0] = crc & 0xff;
X buf[1] = (crc >> 8) & 0xff;
X
X return(-1);
}
SHAR_EOF
chmod 0644 xtclient/phys.c ||
echo 'restore of xtclient/phys.c failed'
Wc_c="`wc -c < 'xtclient/phys.c'`"
test 9682 -eq "$Wc_c" ||
echo 'xtclient/phys.c: original size 9682, current size' "$Wc_c"
fi
# ============= xtclient/phys.h ==============
if test -f 'xtclient/phys.h' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/phys.h (File already exists)'
else
echo 'x - extracting xtclient/phys.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/phys.h' &&
/*
X * File name: phys.h
X *
X * Description: External function declarations for phys.c
X *
X * Author: Merlin J. Mathesius
X */
X
Xextern void PHinit();
Xextern int PHtoDL(), PHfromDL(), PHquery();
SHAR_EOF
chmod 0644 xtclient/phys.h ||
echo 'restore of xtclient/phys.h failed'
Wc_c="`wc -c < 'xtclient/phys.h'`"
test 190 -eq "$Wc_c" ||
echo 'xtclient/phys.h: original size 190, current size' "$Wc_c"
fi
# ============= xtclient/select.h ==============
if test -f 'xtclient/select.h' -a X"$1" != X"-c"; then
echo 'x - skipping xtclient/select.h (File already exists)'
else
echo 'x - extracting xtclient/select.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xtclient/select.h' &&
struct timeval {
X long tv_sec; /* seconds */
X long tv_usec; /* and microseconds */
};
X
/*
X * Operations on timevals.
X *
X * NB: timercmp does not work for >= or <=.
X */
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define timercmp(tvp, uvp, cmp) \
X ((tvp)->tv_sec cmp (uvp)->tv_sec || \
X (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
X
/* extra masks for p_flag in proc struct */
#define SSEL 0x400000 /* This process is selecting */
/* #define SELPROC(tp) (*((struct proc **) (& tp->spacer[0]))) */
#define SELPROC(tp) (*((long *) (& tp->spacer[0])))
X
#define select(nfds, reads, writes, excepts, tmout) \
X syslocal(32, nfds, reads, writes, excepts, tmout)
SHAR_EOF
chmod 0644 xtclient/select.h ||
echo 'restore of xtclient/select.h failed'
Wc_c="`wc -c < 'xtclient/select.h'`"
test 755 -eq "$Wc_c" ||
echo 'xtclient/select.h: original size 755, current size' "$Wc_c"
fi
true || echo 'restore of xtclient/session.c failed'
echo End of part 2, continue with part 3
exit 0
--
David H. Brierley
Home: dave at galaxia.newport.ri.us; Work: dhb at quahog.ssd.ray.com
Send comp.sources.3b1 submissions to comp-sources-3b1 at galaxia.newport.ri.us
%% Can I be excused, my brain is full. **
More information about the Comp.sources.3b1
mailing list