merlinm@i88.isc.com (Merlin J Mathesius) (02/15/91)
Submitted-by: merlinm@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@galaxia.newport.ri.us; Work: dhb@quahog.ssd.ray.com Send comp.sources.3b1 submissions to comp-sources-3b1@galaxia.newport.ri.us %% Can I be excused, my brain is full. **