merlinm@i88.isc.com (Merlin J Mathesius) (02/15/91)
Submitted-by: merlinm@i88.isc.com (Merlin J Mathesius) Posting-number: Volume 1, Issue 7 Archive-name: xtclient/part04 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is part 04 of xtclient # ============= pty/interface.c ============== if test ! -d 'pty'; then echo 'x - creating directory pty' mkdir 'pty' fi if test -f 'pty/interface.c' -a X"$1" != X"-c"; then echo 'x - skipping pty/interface.c (File already exists)' else echo 'x - extracting pty/interface.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'pty/interface.c' && /* X * interface.c - extra system calls interface. X * X * This started life as a file written by Alex Crain. X * X */ X #include "pty.h" #include <sys/types.h> #include <sys/systm.h> #include <sys/errno.h> #include <sys/user.h> #include <sys/conf.h> X #include "sysent.h" X void dosyscall(); X /* stuff to wake up on */ Xextern int select_sleep; Xextern nulldev(); Xextern int se_register(); Xextern int ptyopen(); X int (*old_locsys)(); /* saved value of sysent[SYSL_LOCSYS].sy_call */ int pty_major = 0; /* major number of pty device for use by select */ X void ptyinit () { X int i; X X /* X * add our own system call processor. X */ X old_locsys = sysent[SYSL_LOCSYS].sy_call; X sysent[SYSL_LOCSYS].sy_call = (int (*)()) dosyscall; X X X /* X * find out where the pty major device is X */ X for(i=0;i<cdevcnt;i++) { X if(cdevsw[i].d_open == ptyopen) X pty_major = i; /* got it */ X } # ifdef DEBUGA X eprintf("ptyinit: pty_major = %d\n", pty_major); # endif X X se_linesw_setup(); /* initalize line switch */ X cdevsw[pty_major].d_ttys = pts_tty; /* tell gettty where to find us */ X X /* X * tell other drivers how to register for select service (polling) X */ X ldmisc[SEL_REGISTER] = se_register; } X void dosyscall() { X int index = u.u_ap[0] - SYSL_FIRST; X /* X * Intercept our calls X */ X X if (index >= 0 && index <= (SYSL_LAST - SYSL_FIRST)) X { X /* X * syscall arguments are available via the users %sp, at u.u_ar0[15]. X * These arguments must be copied to the argument vector u.u_arg[] X * for access by the kernal. Noting that the stack looks like: X * %sp -> [ frame link, &68, arg1, arg2 ... ] X */ X int arg = 0; X int * ap = (int *) (u.u_ar0[15]) + 2; X while (arg < sysentries[index].sy_narg) X u.u_arg[arg++] = fuword(ap++); X X /* X * Perform the call. X */ # ifdef DEBUGA X eprintf("pty.select: calling sysentries[%d].sy_call", index); # endif X (* sysentries[index].sy_call) (); X } X else X (*old_locsys) (); } X X int serelease () { X int s = spl5(); X # ifdef DEBUGA X eprintf("pty.select: in serelease\n"); # endif X /* Did we get here without going through our system call interface? */ X if (sysent[SYSL_LOCSYS].sy_call != old_locsys) { X /* check if any other system call drivers were loaded after us but not X * unloaded yet. Drivers which add system calls through SYSL_LOCSYS X * must be uninstalled in the oposite order that they are installed X */ X if (sysent[SYSL_LOCSYS].sy_call != (int (*)()) dosyscall) { X u.u_error = EBUSY; /* order of driver unloads must be wrong! */ X return; X } X sysent[SYSL_LOCSYS].sy_call = old_locsys; X ldmisc[SEL_REGISTER] = nulldev; # ifdef DEBUG X eprintf("pty.select: calling se_linesw_release and setting error\n"); # endif X se_linesw_release(); X u.u_error = EAGAIN; /* we can't release our memory yet, since we X still have stuff on the kernel return X stack. The next call will succeed. */ X } X splx (s); X return; } SHAR_EOF chmod 0644 pty/interface.c || echo 'restore of pty/interface.c failed' Wc_c="`wc -c < 'pty/interface.c'`" test 3028 -eq "$Wc_c" || echo 'pty/interface.c: original size 3028, current size' "$Wc_c" fi # ============= pty/linesw.c ============== if test -f 'pty/linesw.c' -a X"$1" != X"-c"; then echo 'x - skipping pty/linesw.c (File already exists)' else echo 'x - extracting pty/linesw.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'pty/linesw.c' && /* X * This file contains hooks to intercept tty line input and notify selecting X * processes to poll for fd's ready to read. X */ #include <sys/types.h> #include <sys/sysmacros.h> #include <sys/conf.h> #include <sys/tty.h> #include "select.h" X int (*real_linesw_l_input)(); X /* extern int selecting; */ X se_linesw_l_input(tp) struct tty *tp; { X /* check for wakeup maybe? */ X X if((SELPROC(tp) & 0xffffffL) != 0xffffffL) { # ifdef DEBUGA X eprintf("select: linesw: got input wakeing up select\n"); # endif X selwakeup(SELPROC(tp) & 0xffffffL); X SELPROC(tp) |= 0xffffffL; X } X /* call real input routine */ X (*real_linesw_l_input)(tp); } se_linesw_setup() { X /* setup to route tty input to here */ X X real_linesw_l_input = linesw[0].l_input; X linesw[0].l_input = se_linesw_l_input; } se_linesw_release() { X /* setup to route tty back to normal */ X X linesw[0].l_input = real_linesw_l_input; } SHAR_EOF chmod 0644 pty/linesw.c || echo 'restore of pty/linesw.c failed' Wc_c="`wc -c < 'pty/linesw.c'`" test 894 -eq "$Wc_c" || echo 'pty/linesw.c: original size 894, current size' "$Wc_c" fi # ============= pty/number-ptys.h ============== if test -f 'pty/number-ptys.h' -a X"$1" != X"-c"; then echo 'x - skipping pty/number-ptys.h (File already exists)' else echo 'x - extracting pty/number-ptys.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'pty/number-ptys.h' && /* number-ptys.h - Eric H. Herrin II X * X * define the number of ptys here so the actual number only has to be in X * one place. X * X * Version 2.1 X */ #define NUMBER_OF_PTYS 32 SHAR_EOF chmod 0644 pty/number-ptys.h || echo 'restore of pty/number-ptys.h failed' Wc_c="`wc -c < 'pty/number-ptys.h'`" test 176 -eq "$Wc_c" || echo 'pty/number-ptys.h: original size 176, current size' "$Wc_c" fi # ============= pty/pty.c ============== if test -f 'pty/pty.c' -a X"$1" != X"-c"; then echo 'x - skipping pty/pty.c (File already exists)' else echo 'x - extracting pty/pty.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'pty/pty.c' && /* X * pty.c - Berkeley style pseudo tty driver for system V X * X * Copyright (c) 1987, Jens-Uwe Mager, FOCUS Computer GmbH X * Not derived from licensed software. X * X * Permission is granted to freely use, copy, modify, and redistribute X * this software, provided that no attempt is made to gain profit from it, X * the author is not construed to be liable for any results of using the X * software, alterations are clearly marked as such, and this notice is X * not modified. X */ X /* X * Modified for use on the UnixPC by: X * Eric H. Herrin II X * University of Kentucky Mathematical Sciences Laboratories X * eric@ms.uky.edu, eric@ms.uky.csnet, !cbosgd!ukma!eric X * X * See README.3b1 for details of port and installation. X * Version 2.1 X */ X #include "pty.h" #include "sys/param.h" #include "sys/types.h" #include "sys/sysmacros.h" #include "sys/systm.h" #include "sys/file.h" #include "sys/conf.h" #include "sys/proc.h" #include "sys/dir.h" #include "sys/tty.h" #include "sys/signal.h" #include "sys/user.h" #include "sys/errno.h" #include "sys/termio.h" #include "sys/ttold.h" X #ifdef SELECT struct proc *pty_proc[PTYCNT]; /* selecting process for each master */ #endif X X /* The tty structures must be local to this driver. One doesn't have X * conf.c X */ struct tty pts_tty[PTYCNT]; int pts_cnt = PTYCNT; int ptystate[PTYCNT]; X ptyopen(dev, flag) X register dev_t dev; X register int flag; { X register struct tty *tp; X X dev = minor(dev); X if (Master(dev) == True) { # ifdef DEBUG X eprintf("open(master): \n"); # endif X dev -= PTYCNT; X tp = &pts_tty[dev]; X if (dev >= pts_cnt) { X u.u_error = ENXIO; X return; X } X /* X * allow only one controlling process X */ X if (ptystate[dev] & MOPEN) { X u.u_error = EBUSY; X return; X } X pty_proc[dev] = (struct proc *) -1L; X if (tp->t_state & WOPEN) X wakeup((caddr_t)&tp->t_canq); X tp->t_state |= CARR_ON; X ptystate[dev] |= MOPEN; #ifdef SELECT X ptystate[dev] &= ~(SCLOSED); #endif X } else { # ifdef DEBUG X eprintf("open(slave): \n"); # endif X tp = &pts_tty[dev]; X if (dev >= pts_cnt) { X u.u_error = ENXIO; X return; X } X if ((tp->t_state & (ISOPEN|WOPEN)) == 0) { X ttinit(tp); X tp->t_proc = ptsproc; X } X /* X * if master is still open, don't wait for carrier X */ X if (ptystate[dev] & MOPEN) X tp->t_state |= CARR_ON; X if (!(flag & FNDELAY)) { X while ((tp->t_state & CARR_ON) == 0) { X tp->t_state |= WOPEN; X sleep((caddr_t)&tp->t_canq, TTIPRI); X } X } X (*linesw[tp->t_line].l_open)(tp); X } } X ptyclose(dev, flag) X register dev_t dev; X register int flag; { X register struct tty *tp; X X dev = minor(dev); X if (Master(dev) == True) { # ifdef DEBUG X eprintf("close(master): \n"); # endif X dev -= PTYCNT; X tp = &pts_tty[dev]; X if (tp->t_state & ISOPEN) { X signal(tp->t_pgrp, SIGHUP); X ttyflush(tp, FREAD|FWRITE); X } X else { /* must get rid of buffered output */ X while (tp->t_tbuf.c_count) { # ifdef DEBUG X eprintf("c_count = %d\n", tp->t_tbuf.c_count); # endif X ptsproc(tp, T_WFLUSH); /* side effects? */ X } X } X /* X * virtual carrier gone X */ X tp->t_state &= ~(CARR_ON); X ptystate[dev] &= ~MOPEN; X } else { # ifdef DEBUG X eprintf("close(slave): \n"); # endif X tp = &pts_tty[dev]; X (*linesw[tp->t_line].l_close)(tp); X tp->t_state &= ~CARR_ON; # ifdef SELECT X ptystate[dev] |= SCLOSED; X { X int indx = tp - pts_tty; X /* X * We just closed the slave device. The master won't block X * on a read. Now Wake up any processes which might be X * selecting so it can poll again. X */ X if (indx >= 0 && indx < PTYCNT X && pty_proc[indx] != (struct proc *) -1L) { X selwakeup(pty_proc[indx]); X pty_proc[indx] = (struct proc *) -1L; X } X } # endif X X } } X ptyread(dev) X register dev_t dev; { X register struct tty *tp; X register n; X X dev = minor(dev); X if (Master(dev) == True) { # ifdef DEBUG X eprintf("read(master): \n"); # endif X dev -= PTYCNT; X tp = &pts_tty[dev]; X X /* added fix for hanging master side when the slave hangs X * up too early. Fix by Michael Bloom (mb@ttidca.tti.com). X */ /* if ((tp->t_state & (ISOPEN|TTIOW)) == 0) { */ X if (ptystate[dev] & SCLOSED) { X u.u_error = EIO; X return; X } X while (u.u_count > 0) { X ptsproc(tp, T_OUTPUT); X if ((tp->t_state & (TTSTOP|TIMEOUT)) X || tp->t_tbuf.c_ptr == NULL || tp->t_tbuf.c_count == 0) { X if (u.u_fmode & FNDELAY) X break; # ifdef DEBUG X eprintf("read(master): master going to sleep\n"); # endif X ptystate[dev] |= MRWAIT; X sleep((caddr_t)&tp->t_rloc, TTIPRI); # ifdef DEBUG X eprintf("read(master): master woke up\n"); # endif X X continue; X } X n = min(u.u_count, tp->t_tbuf.c_count); X if (n) { # ifdef DEBUG X eprintf("read(master): got some stuff\n"); # endif X if (copyout(tp->t_tbuf.c_ptr, u.u_base, n)) { X u.u_error = EFAULT; X break; X } X tp->t_tbuf.c_count -= n; X tp->t_tbuf.c_ptr += n; X u.u_base += n; X u.u_count -= n; X } X } X /* wakeup slave write if required */ X ptsproc(tp, T_OUTPUT); X } else { # ifdef DEBUG X eprintf("read(slave): \n"); # endif X tp = &pts_tty[dev]; # ifdef DEBUG X eprintf("read(slave): got some stuff\n"); # endif X (*linesw[tp->t_line].l_read)(tp); X } } X ptywrite(dev) X register dev_t dev; { X register struct tty *tp; X register n; X X dev = minor(dev); X if (Master(dev) == True) { # ifdef DEBUG X eprintf("write(master): \n"); # endif X dev -= PTYCNT; X tp = &pts_tty[dev]; X X if ((tp->t_state & ISOPEN) == 0) { X u.u_error = EIO; X return; X } X while (u.u_count > 0) { X if ((tp->t_state & TBLOCK) || tp->t_rbuf.c_ptr == NULL) { X if (u.u_fmode & FNDELAY) X break; X ptystate[dev] |= MWWAIT; # ifdef DEBUG X eprintf("write(master): going to sleep\n"); # endif X X sleep((caddr_t)&tp->t_wloc, TTOPRI); X # ifdef DEBUG X eprintf("write: waking up\n"); # endif X X continue; X } X n = min(u.u_count, tp->t_rbuf.c_count); X if (n) { # ifdef DEBUG X eprintf("write(master): sending some stuff\n"); # endif X if (copyin(u.u_base,tp->t_rbuf.c_ptr, n)) { X u.u_error = EFAULT; X break; X } X if (tp->t_iflag & IXON) { X /* check for flow control */ X register char c; X register int i; X for (i = 0; i < n; i++) { X c = tp->t_rbuf.c_ptr[i]; X if (tp->t_state & TTSTOP) X { X if ((c == CSTART) X || (tp->t_iflag & IXANY) ) { X (*tp->t_proc)(tp, T_RESUME); X } X } X else X { X if (c==CSTOP) { X (*tp->t_proc)(tp, T_SUSPEND); X } X } X if (c==CSTART || c==CSTOP) { X /* through away this char and proc X remaining on next while loop*/ X n = i; X u.u_count -= 1; X if (u.u_count == 0) { X return; X } X break; /* exit for loop */ X } X } X } X X tp->t_rbuf.c_count -= n; X u.u_base += n; X u.u_count -= n; X } X (*linesw[tp->t_line].l_input)(tp); X } X } else { # ifdef DEBUG X eprintf("write(slave): \n"); # endif X tp = &pts_tty[dev]; # ifdef DEBUG X eprintf("write(slave): sending some stuff\n"); # endif X (*linesw[tp->t_line].l_write)(tp); X } } X ptyioctl(dev, cmd, arg, mode) X dev_t dev; X int cmd, arg, mode; { X register struct tty *tp; X X dev = minor(dev); X if (Master(dev) == True) { # ifdef DEBUG X eprintf("ioctl(master): \n"); # endif X dev -= PTYCNT; X tp = &pts_tty[dev]; X /* X * sorry, but we can't fiddle with the tty struct without X * having done LDOPEN X */ X if (tp->t_state & ISOPEN) { X if (cmd == TCSBRK && arg == NULL) { X signal(tp->t_pgrp, SIGINT); X if ((tp->t_iflag & NOFLSH) == 0) X ttyflush(tp, FREAD|FWRITE); X } else { X /* X * we must flush output to avoid hang in ttywait X */ X if (cmd == TCSETAW || cmd == TCSETAF || X cmd == TCSBRK || cmd == TIOCSETP) X ttyflush(tp, FWRITE); X ttiocom(tp, cmd, arg, mode); X } X } X } else { # ifdef DEBUG X eprintf("ioctl(slave): \n"); # endif X tp = &pts_tty[dev]; X ttiocom(tp, cmd, arg, mode); X } } X ptsproc(tp, cmd) register struct tty *tp; { X register struct ccblock *tbuf; X extern ttrstrt(); X X switch (cmd) { X case T_TIME: # ifdef DEBUG X eprintf("ptsproc: T_TIME:\n"); # endif X tp->t_state &= ~TIMEOUT; X goto start; X case T_WFLUSH: # ifdef DEBUG X eprintf("ptsproc: T_WFLUSH:\n"); # endif X tp->t_tbuf.c_size -= tp->t_tbuf.c_count; X tp->t_tbuf.c_count = 0; X /* fall through */ X case T_RESUME: # ifdef DEBUG X eprintf("ptsproc: T_RESUME:\n"); # endif X tp->t_state &= ~TTSTOP; X /* fall through */ X case T_OUTPUT: start: # ifdef DEBUG X eprintf("ptsproc: T_OUTPUT:\n"); # endif X if (tp->t_state & (TTSTOP|TIMEOUT)) X break; # ifdef DEBUG X eprintf("ptsproc: T_OUTPUT: past(TTSTOP|TIMEOUT)"); # endif X tbuf = &tp->t_tbuf; X if (tbuf->c_ptr == NULL || tbuf->c_count == 0) { # ifdef DEBUG X eprintf("ptsproc: T_OUTPUT: tbuf empty, may break\n"); # endif X if (tbuf->c_ptr) X tbuf->c_ptr -= tbuf->c_size; X if (!(CPRES & (*linesw[tp->t_line].l_output)(tp))) X break; X } # ifdef SELECT X { X int indx = tp - pts_tty; X /* X * We just got some stuff that the master device might want X * to read. Now Wake up any processes which might be X * selecting so it can poll again. X */ X if (indx >= 0 && indx < PTYCNT X && pty_proc[indx] != (struct proc *) -1L) { X selwakeup(pty_proc[indx]); X pty_proc[indx] = (struct proc *) -1L; X } X } # endif X if (tbuf->c_count && (ptystate[tp-pts_tty] & MRWAIT)) { # ifdef DEBUG X eprintf("ptsproc: T_OUTPUT: waking up master\n"); # endif X ptystate[tp-pts_tty] &= ~MRWAIT; X wakeup((caddr_t)&tp->t_rloc); X } # ifdef DEBUG X eprintf("ptsproc: T_OUTPUT: leaving end\n"); # endif X break; X case T_SUSPEND: # ifdef DEBUG X eprintf("ptsproc: T_SUSPEND:\n"); # endif X tp->t_state |= TTSTOP; X break; X case T_BLOCK: # ifdef DEBUG X eprintf("ptsproc: T_BLOCK:\n"); # endif X /* X * the check for ICANON appears to be neccessary X * to avoid a hang when overflowing input X */ X if ((tp->t_iflag & ICANON) == 0) X tp->t_state |= TBLOCK; X break; X case T_BREAK: # ifdef DEBUG X eprintf("ptsproc: T_BREAK:\n"); # endif X tp->t_state |= TIMEOUT; X timeout(ttrstrt, tp, HZ/4); X break; #ifdef T_LOG_FLUSH X case T_LOG_FLUSH: #endif X case T_RFLUSH: # ifdef DEBUG X eprintf("ptsproc: T_RFLUSH:\n"); # endif X if (!(tp->t_state & TBLOCK)) X break; X /* fall through */ X case T_UNBLOCK: # ifdef DEBUG X eprintf("ptsproc: T_UNBLOCK:\n"); # endif X tp->t_state &= ~(TTXOFF|TBLOCK); X /* fall through */ X case T_INPUT: # ifdef DEBUG X eprintf("ptsproc: T_INPUT:\n"); # endif X if (ptystate[tp-pts_tty] & MWWAIT) { X ptystate[tp-pts_tty] &= ~MWWAIT; # ifdef DEBUG X eprintf("ptsproc: T_INPUT: waking up master\n"); # endif X wakeup((caddr_t)&tp->t_wloc); X } X break; X default: # ifdef DEBUG X eprintf("ptsproc: default:\n"); # else X ; # endif X } } X /* This routine used to be a stub, however, an industrious soul found X * the release routine caused a panic whenever the driver is released X * and some ptys are still open. The simple 'for' loop fixes this X * problem. X * X * Credit should be given to: X * Mike "Ford" Ditto X * kenobi!ford@crash.CTS.COM, ...!crash!kenobi!ford X * for finding the bug and writing the for loop. X * X * [Eric H. Herrin II, 10-7-87] X */ ptyrelease() { X register int i; X # ifdef DEBUG X eprintf("ptyrelease:\n"); # endif X for (i=0; i<PTYCNT; i++) X if ((ptystate[i] & (ISOPEN|MOPEN)) || X (pts_tty[i].t_state & WOPEN)) { X u.u_error = EBUSY; X return; X } # ifdef SELECT X serelease(); # endif X return; } SHAR_EOF chmod 0644 pty/pty.c || echo 'restore of pty/pty.c failed' Wc_c="`wc -c < 'pty/pty.c'`" test 11612 -eq "$Wc_c" || echo 'pty/pty.c: original size 11612, current size' "$Wc_c" fi # ============= pty/pty.h ============== if test -f 'pty/pty.h' -a X"$1" != X"-c"; then echo 'x - skipping pty/pty.h (File already exists)' else echo 'x - extracting pty/pty.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'pty/pty.h' && /* pty.h - Eric H. Herrin II (eric@ms.uky.edu) X * X * some elementary definitions for the pty driver (UnixPC version) X * X * Version 2.1 X */ X /* X * the following are arbitrary 3 unused bits from t_state X * in sys/tty.h X */ /* The UnixPC does not have any extra bits in t_state, thus X * one must provide other means of storing the state. X */ #define MRWAIT 01 /* master waiting in read */ #define t_rloc t_cc[0] /* wchannel */ #define MWWAIT 02 /* master waiting in write */ #define t_wloc t_cc[1] /* wchannel */ #define MOPEN 04 /* master is open */ #ifdef SELECT #define SCLOSED 010 /* slave was opened and closed */ X /* cleared in master open, set in slave close */ #endif X int ptsproc(); Xextern struct tty pts_tty[]; X #define True (1 == 1) #define False (0 == 1) X /* This is the total number of ptys. Note the maximum number here is X * currently 64 for the UnixPC (128 minor devices/2 minor devices per pty X * yields 64 total ptys). I really don't see the need for more than 32 X * on the 3B1, however, if someone does, then (s)he can change it. X */ #include "number-ptys.h" #define PTYCNT (dev_t)NUMBER_OF_PTYS X /* some definitions to include kernel info from system header files. X */ #define KERNEL 1 #define defined_io 1 /* #define NOSTREAMS 1 Seems that this was not defined in 3.51 */ X #define UNIXPC 1 X /* This macro returns True if the parameter is a master minor device number, X * False otherwise. X */ #define Master( dev ) (minor(dev) >= PTYCNT) X /* Index in ldmisc to use for pointer to se_register X * se_register(poll_routine, maj_dev) is how other drivers tell us the X * address of their select polling routine. X */ #define SEL_REGISTER (LDMISCSLOTS - 1) X /* This is the maximum major device number which can be used above */ #define NUM_SEL_DRIVERS 32 SHAR_EOF chmod 0644 pty/pty.h || echo 'restore of pty/pty.h failed' Wc_c="`wc -c < 'pty/pty.h'`" test 1777 -eq "$Wc_c" || echo 'pty/pty.h: original size 1777, current size' "$Wc_c" fi # ============= pty/select.c ============== if test -f 'pty/select.c' -a X"$1" != X"-c"; then echo 'x - skipping pty/select.c (File already exists)' else echo 'x - extracting pty/select.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'pty/select.c' && /* X * syscalls.c - system call kernal interface routines. X * X * Written by Alex Crain. X * Extensivly hacked by Brad Bosch. X * X * I don't think there is anything left here to which this applies, but... X * X * This file is based in the Berkeley file uipc_syscalls.c, X * but is *not* guarenteed to be in any way compatable. It is X * close enough to the Berkeley code that the following applies... X * X * Copyright (c) 1982, 1986, 1988 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided "as is" without express or implied warranty. X * X */ X X #include "pty.h" #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/user.h> #include <sys/file.h> #include <sys/buf.h> #include <sys/errno.h> #include <sys/systm.h> #include <sys/tty.h> #include <sys/conf.h> #include <sys/var.h> #include "select.h" X void unselect(); X Xextern int pty_major; /* we will need this in the select loop */ Xextern int ptystate[]; /* needed to test for slave closed */ Xextern struct proc *pty_proc[]; /* selecting process for each master */ X X /* This returns a pointer to the tty structure for a device number. X * Returns NULL if unknown or error. This works for tty*, console, and ttyp*. X * extern struct tty * gettty(); X * The above didn't work for ph*. Have to write our own. See below. X */ X /* we now sleep on ldmisc[SEL_REGISTER] since this is known to other drivers*/ X #ifdef NO_LONGER_NEEDED int so_win_major = 0; /* major device of window */ unsigned int so_win_tty = 0; /* address of wintty */ #endif /*NO_LONGER_NEEDED*/ X /* Table of driver's select poll entry points indexed by major number */ static int (*poll_table[NUM_SEL_DRIVERS])(); X X /* This routine is no longer needed (Yea!) */ sesetup() /* setup variables */ { #ifdef NO_LONGER_NEEDED X register struct a { X int w_major; X unsigned int w_tty; X } * uap = (struct a *) u.u_ap; X X if (suser()) { /* must be root to set this stuff */ X so_win_major = uap->w_major; X so_win_tty = uap->w_tty; X } X else X u.u_error = EPERM; #endif /*NO_LONGER_NEEDED*/ } X Xextern struct tty *pser_tty[]; X /* replacement gettty for broken one in kernel */ struct tty * gettty(dev) dev_t dev; { X register int maj, min; X X maj = major(dev); X if (maj >= cdevcnt) X return(NULL); X min = minor(dev); X switch (maj) X { X case 0: /* tty000 */ /* these are hardcoded in kernel too! */ X return (pser_tty[min]); X case 8: /* ph* */ X return (pser_tty[1]); X case 7: /* win* */ X if (min < 12) X return (&(cdevsw[maj].d_ttys)[min-1]); X else X return (NULL); X default: /* other normal cases */ X return (&(cdevsw[maj].d_ttys)[min]); X } } X void selwakeup(); /* forward reference comming */ X /* X * This is called by other drivers to register their select routine with us. X * We return the address of the routine which the driver should call when i/o X * may be possible on a device which is under selection. The driver should X * save this address for later use. The address of se_register is stored in X * ldmisc[SEL_REGISTER] for reference by other drivers. X */ void (*se_register (poll_routine, maj_dev))() int (*poll_routine)(); int maj_dev; { # ifdef DEBUG X eprintf("se_register: maj_dev=%d, poll_routine=%x\n", X maj_dev, poll_routine); # endif X if (maj_dev < NUM_SEL_DRIVERS) X poll_table[maj_dev] = poll_routine; X return(selwakeup); } X seselect () { X register struct a { X int nfds; X int *readfds; X int *writefds; X int *execptfds; X struct timeval *timeout; X } * uap = (struct a *) u.u_ap; X int mask, cnt, tim, timout, rds; X int i, j, k, l, s; X dev_t rdev; X struct timeval utimeout; X struct file *fp; X struct inode *ip; X struct tty *tp; X struct socket *so; X /* X * If timeout specified, convert time to hz and set timer. X */ /* select_timed_out = 0; */ X u.u_procp->p_flag &= ~STIMO; X tim = -1; X if ( uap->timeout ) { X if (copyin(uap->timeout, &utimeout, sizeof(utimeout))) { X u.u_error = EINVAL; X return; X } X tim = utimeout.tv_sec * HZ + utimeout.tv_usec * 6/100000; # ifdef DEBUG X eprintf("select: timeout set to %d\n", tim); # endif X if (tim) X timout = timeout(unselect, u.u_procp, tim); X } X if (uap->nfds > 32) uap->nfds = 32; X # ifdef DEBUG X eprintf("select: rds=%x nfds=%d\n", *uap->readfds, uap->nfds); # endif X poll: X u.u_procp->p_flag |= SSEL; X cnt = 0; X if(uap->readfds) { /* have readbitmask */ X rds = fuword(uap->readfds); X X for(i=0;i < uap->nfds; i++) { X u.u_error = 0; /* reset it */ X mask = 1 << i; X if(rds & mask) { /* is this one? */ # ifdef DEBUGA X eprintf("select: mask=%d getf=%d ofile=%d, i=%d\n", mask, X getf(i), u.u_ofile[i], i); # endif X if((fp = getf(i)) != 0) { /* valid open file */ X ip = fp->f_inode; X rdev = (dev_t) ip->i_rdev; # ifdef DEBUG X eprintf("select: fd=%d dev id=%x tp=%x\n", X i, rdev, gettty(rdev)); # endif X if(major(rdev) == pty_major && Master(rdev) == True) { X /* got a master pty file descriptor */ X /* get slot in tty table */ X k = minor(rdev) - PTYCNT; X tp = &pts_tty[k]; /* ok */ # ifdef DEBUGB X eprintf("select: mstr min=%d cnt=%d,%d\n", X k, tp->t_tbuf.c_count, tp->t_outq.c_cc); # endif X /* check buffers */ X if((tp->t_outq.c_cc || tp->t_tbuf.c_count) && X !(tp->t_state & TTSTOP) X || ptystate[k] & SCLOSED) { X /* ok to read */ X cnt++; X } else { X short s=spl7(); /* protect pty_proc */ X if (pty_proc[k]) X if (pty_proc[k]!=(struct proc *) -1L X && pty_proc[k]->p_wchan X == (caddr_t) se_register) X pty_proc[k] = NULL; X else X pty_proc[k] = u.u_procp; X rds &= ~mask; X splx(s); X } X } X else if((tp = gettty(rdev)) != NULL) { X /* got a tty file descriptor */ X X /* check buffers */ # ifdef DEBUGA X eprintf("select: tty rdev=%x cnt=%d,%d\n", X rdev, tp->t_rawq.c_cc, tp->t_canq.c_cc); # endif X if(tp->t_rawq.c_cc || tp->t_canq.c_cc || X !(tp->t_state & CARR_ON)) X cnt++; X else { X short s=spl7(); /* protect SELPROC */ X rds &= ~mask; X if (SELPROC(tp) & 0xffffffL) X if ((SELPROC(tp) & 0xffffffL) != 0xffffffL X && ((struct proc *)SELPROC(tp))->p_wchan X == (caddr_t) ldmisc[SEL_REGISTER]) X SELPROC(tp) &= 0xff000000L; /*clear*/ X else /* no collision */ X SELPROC(tp) = (long) u.u_procp | X ((SELPROC(tp) & 0xff000000L)); X splx(s); X } X } #ifdef NOT_WORKING /* this can't possibly work! */ X /* here we have pipes */ X else if(ip->i_mode & IFIFO) { X /* if i_count == 1 no opens left X * we notify select of this X */ X if (ip->i_count == 1) X cnt++; X else if (ip->i_fwptr) X cnt++; X else X rds &= ~mask; X } #endif /*NOT_WORKING*/ X /* else check to see if a driver has registerd itself X * to provide select for this major number */ X else if (poll_table[major(rdev)]!=NULL) { X if (!poll_table[major(rdev)](fp,FREAD)) X rds &= ~mask; X else X cnt++; X } else { X /* Don't know about this device */ X rds &= ~mask; X } X } else {/* invalid fd */ X /* should set u.u_error here */ X rds &= ~mask; X } X } X X } X } X X s = spl7(); /* begin critical section */ X X if(cnt || u.u_procp->p_flag & STIMO || ! tim) { X u.u_rval1 = cnt; X if (uap->readfds) X suword(uap->readfds, rds); /* copy rds back to user*/ X if ( uap->timeout ) X untimeout(timout); X splx(s); X return; X } X X X if (! (u.u_procp->p_flag & SSEL)) { X splx(s); X goto poll; /* poll again if we had i/o while polling */ X } X X /* sleep until timeout or device activity */ # ifdef DEBUG X eprintf("select: going to sleep\n"); # endif X sleep( (caddr_t) ldmisc[SEL_REGISTER], PZERO+1 ); X X splx(s); /* end critical section */ X X /* check for activity while we were asleep */ X goto poll; /* poll again */ } X /* unselect is called when the select timer expires */ void unselect(p) X register struct proc *p; { # ifdef DEBUGA X eprintf("select: timed out\n"); # endif X /* set select_timed_out process flag*/ X p->p_flag |= STIMO; X selwakeup(p); } X /* Call with p = NULL if collision */ void selwakeup(p) X register struct proc *p; { X int s = spl7(); X X if (p) { X if (p->p_wchan == (caddr_t) ldmisc[SEL_REGISTER]) { # ifdef DEBUG X eprintf("select: in selwakeup p->p_stat = %x\n", p->p_stat); # endif X if (p->p_stat == SSLEEP) X setrun(p); X else X unsleep(p); X } X else if (p->p_flag & SSEL) X p->p_flag &= ~SSEL; /* clear selecting flag for this process */ X } X else { X register struct proc *procp; X register int i; # ifdef DEBUGD X eprintf("select: calling wakeup\n"); # endif X /* collision, clear all selecting flags */ X procp = proc; X for (i = 1; i < v.v_proc; i++, procp ++) X procp->p_flag &= ~SSEL; X wakeup((caddr_t) ldmisc[SEL_REGISTER]); X } X splx(s); } SHAR_EOF chmod 0644 pty/select.c || echo 'restore of pty/select.c failed' Wc_c="`wc -c < 'pty/select.c'`" test 9262 -eq "$Wc_c" || echo 'pty/select.c: original size 9262, current size' "$Wc_c" fi # ============= pty/select.h ============== if test -f 'pty/select.h' -a X"$1" != X"-c"; then echo 'x - skipping pty/select.h (File already exists)' else echo 'x - extracting pty/select.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'pty/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 pty/select.h || echo 'restore of pty/select.h failed' Wc_c="`wc -c < 'pty/select.h'`" test 755 -eq "$Wc_c" || echo 'pty/select.h: original size 755, current size' "$Wc_c" fi # ============= pty/sysent.h ============== if test -f 'pty/sysent.h' -a X"$1" != X"-c"; then echo 'x - skipping pty/sysent.h (File already exists)' else echo 'x - extracting pty/sysent.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'pty/sysent.h' && /* X * sysent.h - system call entry definitions. X * X */ X Xextern seselect(); Xextern sesetup(); X /* our extra system call table */ struct sysent sysentries[] = { X {5,seselect}, /* SYSL_FIRST */ {2,sesetup}, /* SYSL_LAST */ X }; X #define SYSL_LOCSYS 68 X /* Note: it would have been safer to use numbers farther away from the used X * syslocal numbers, but/because changing them requires recompiling all user X * code which uses them. X */ #define SYSL_FIRST 32 /* 18 is the last used syslocal */ #define SYSL_LAST 33 SHAR_EOF chmod 0644 pty/sysent.h || echo 'restore of pty/sysent.h failed' Wc_c="`wc -c < 'pty/sysent.h'`" test 510 -eq "$Wc_c" || echo 'pty/sysent.h: original size 510, current size' "$Wc_c" fi # ============= font/Makefile ============== if test ! -d 'font'; then echo 'x - creating directory font' mkdir 'font' fi if test -f 'font/Makefile' -a X"$1" != X"-c"; then echo 'x - skipping font/Makefile (File already exists)' else echo 'x - extracting font/Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'font/Makefile' && default: xtclient.f X xtclient.f: xtclient.ft X -cfont xtclient.ft > xtclient.f SHAR_EOF chmod 0644 font/Makefile || echo 'restore of font/Makefile failed' Wc_c="`wc -c < 'font/Makefile'`" test 78 -eq "$Wc_c" || echo 'font/Makefile: original size 78, current size' "$Wc_c" fi # ============= font/xtclient.ft ============== if test -f 'font/xtclient.ft' -a X"$1" != X"-c"; then echo 'x - skipping font/xtclient.ft (File already exists)' else echo 'x - extracting font/xtclient.ft (Text)' sed 's/^X//' << 'SHAR_EOF' > 'font/xtclient.ft' && # magic 0x18e # flags 0x0 hs 5 vs 9 basel 9 X ############### Character 0x20, 040, 32 char 32 hs 4 vs 9 ha 0 va -9 hi 5 vi 0 bits bits bits bits bits bits bits bits bits X ############### Character 0x21, 041, 33 ! ! ! ! ! ! ! ! ! ! char 33 hs 1 vs 7 ha 3 va -8 hi 5 vi 0 bits * bits * bits * bits * bits * bits bits * X ############### Character 0x22, 042, 34 " " " " " " " " " " char 34 hs 3 vs 3 ha 2 va -8 hi 5 vi 0 bits * * bits * * bits * * X ############### Character 0x23, 043, 35 # # # # # # # # # # char 35 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits ** bits **** bits ** bits **** bits ** bits ** X ############### Character 0x24, 044, 36 $ $ $ $ $ $ $ $ $ $ char 36 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits *** bits * bits ** bits * bits *** bits * X ############### Character 0x25, 045, 37 % % % % % % % % % % char 37 hs 4 vs 6 ha 1 va -8 hi 5 vi 0 bits ** bits ** * bits * bits * bits * ** bits ** X ############### Character 0x26, 046, 38 & & & & & & & & & & char 38 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits ** bits * bits * * bits * * bits ** * X ############### Character 0x27, 047, 39 ' ' ' ' ' ' ' ' ' ' char 39 hs 2 vs 3 ha 2 va -8 hi 5 vi 0 bits ** bits * bits * X ############### Character 0x28, 050, 40 ( ( ( ( ( ( ( ( ( ( char 40 hs 4 vs 7 ha 2 va -8 hi 5 vi 0 bits * bits * bits * bits * bits * bits * bits * X ############### Character 0x29, 051, 41 ) ) ) ) ) ) ) ) ) ) char 41 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits * bits * bits * bits * bits * X ############### Character 0x2a, 052, 42 * * * * * * * * * * char 42 hs 4 vs 5 ha 1 va -8 hi 5 vi 0 bits * * bits ** bits **** bits ** bits * * X ############### Character 0x2b, 053, 43 + + + + + + + + + + char 43 hs 3 vs 3 ha 2 va -6 hi 5 vi 0 bits * bits *** bits * X ############### Character 0x2c, 054, 44 , , , , , , , , , , char 44 hs 2 vs 3 ha 3 va -3 hi 5 vi 0 bits ** bits * bits * X ############### Character 0x2d, 055, 45 - - - - - - - - - - char 45 hs 4 vs 1 ha 1 va -5 hi 5 vi 0 bits **** X ############### Character 0x2e, 056, 46 . . . . . . . . . . char 46 hs 2 vs 1 ha 2 va -2 hi 5 vi 0 bits ** X ############### Character 0x2f, 057, 47 / / / / / / / / / / char 47 hs 4 vs 6 ha 1 va -7 hi 5 vi 0 bits * bits * bits * bits * bits * bits * X ############### Character 0x30, 060, 48 0 0 0 0 0 0 0 0 0 0 char 48 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * ** bits ** * bits * * bits * * bits ** X ############### Character 0x31, 061, 49 1 1 1 1 1 1 1 1 1 1 char 49 hs 3 vs 7 ha 2 va -8 hi 5 vi 0 bits * bits ** bits * bits * bits * bits * bits *** X ############### Character 0x32, 062, 50 2 2 2 2 2 2 2 2 2 2 char 50 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * bits * bits * bits * bits **** X ############### Character 0x33, 063, 51 3 3 3 3 3 3 3 3 3 3 char 51 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits **** bits * bits * bits * bits * bits * * bits ** X ############### Character 0x34, 064, 52 4 4 4 4 4 4 4 4 4 4 char 52 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits * * bits * * bits **** bits * bits * X ############### Character 0x35, 065, 53 5 5 5 5 5 5 5 5 5 5 char 53 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits **** bits * bits *** bits * bits * bits * bits *** X ############### Character 0x36, 066, 54 6 6 6 6 6 6 6 6 6 6 char 54 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * bits *** bits * * bits * * bits ** X ############### Character 0x37, 067, 55 7 7 7 7 7 7 7 7 7 7 char 55 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits **** bits * bits * bits * bits * bits * bits * X ############### Character 0x38, 070, 56 8 8 8 8 8 8 8 8 8 8 char 56 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * * bits ** bits * * bits * * bits ** X ############### Character 0x39, 071, 57 9 9 9 9 9 9 9 9 9 9 char 57 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * * bits *** bits * bits * * bits ** X ############### Character 0x3a, 072, 58 : : : : : : : : : : char 58 hs 1 vs 5 ha 3 va -6 hi 5 vi 0 bits * bits * bits bits * bits * X ############### Character 0x3b, 073, 59 ; ; ; ; ; ; ; ; ; ; char 59 hs 2 vs 7 ha 1 va -7 hi 5 vi 0 bits * bits * bits bits bits * bits * bits * X ############### Character 0x3c, 074, 60 < < < < < < < < < < char 60 hs 4 vs 5 ha 1 va -7 hi 5 vi 0 bits * bits * bits * bits * bits * X ############### Character 0x3d, 075, 61 = = = = = = = = = = char 61 hs 4 vs 3 ha 1 va -6 hi 5 vi 0 bits **** bits bits **** X ############### Character 0x3e, 076, 62 > > > > > > > > > > char 62 hs 4 vs 5 ha 1 va -7 hi 5 vi 0 bits * bits * bits * bits * bits * X ############### Character 0x3f, 077, 63 ? ? ? ? ? ? ? ? ? ? char 63 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * bits * bits * bits bits * X ############### Character 0x40, 0100, 64 @ @ @ @ @ @ @ @ @ @ char 64 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * ** bits ** * bits * ** bits * bits ** X ############### Character 0x41, 0101, 65 A A A A A A A A A A char 65 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * * bits * * bits **** bits * * bits * * X ############### Character 0x42, 0102, 66 B B B B B B B B B B char 66 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits *** bits * * bits * * bits *** bits * * bits * * bits *** X ############### Character 0x43, 0103, 67 C C C C C C C C C C char 67 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * bits * bits * bits * * bits ** X ############### Character 0x44, 0104, 68 D D D D D D D D D D char 68 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits *** bits * * bits * * bits * * bits * * bits * * bits *** X ############### Character 0x45, 0105, 69 E E E E E E E E E E char 69 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits **** bits * bits * bits *** bits * bits * bits **** X ############### Character 0x46, 0106, 70 F F F F F F F F F F char 70 hs 4 vs 7 ha 2 va -8 hi 5 vi 0 bits **** bits * bits * bits *** bits * bits * bits * X ############### Character 0x47, 0107, 71 G G G G G G G G G G char 71 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * bits * ** bits * * bits * * bits ** X ############### Character 0x48, 0110, 72 H H H H H H H H H H char 72 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits * * bits * * bits **** bits * * bits * * bits * * X ############### Character 0x49, 0111, 73 I I I I I I I I I I char 73 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits *** bits * bits * bits * bits * bits * bits *** X ############### Character 0x4a, 0112, 74 J J J J J J J J J J char 74 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits * bits * bits * bits * * bits ** X ############### Character 0x4b, 0113, 75 K K K K K K K K K K char 75 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits * * bits ** bits ** bits * * bits * * bits * * X ############### Character 0x4c, 0114, 76 L L L L L L L L L L char 76 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits * bits * bits * bits * bits **** X ############### Character 0x4d, 0115, 77 M M M M M M M M M M char 77 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits **** bits **** bits **** bits * * bits * * bits * * X ############### Character 0x4e, 0116, 78 N N N N N N N N N N char 78 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits ** * bits * ** bits * * bits * * bits * * bits * * X ############### Character 0x4f, 0117, 79 O O O O O O O O O O char 79 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * * bits * * bits * * bits * * bits ** X ############### Character 0x50, 0120, 80 P P P P P P P P P P char 80 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits *** bits * * bits * * bits * * bits *** bits * bits * X ############### Character 0x51, 0121, 81 Q Q Q Q Q Q Q Q Q Q char 81 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * * bits * * bits ** * bits * * bits * * X ############### Character 0x52, 0122, 82 R R R R R R R R R R char 82 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits *** bits * * bits * * bits *** bits * * bits * * bits * * X ############### Character 0x53, 0123, 83 S S S S S S S S S S char 83 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * * bits * bits ** bits * bits * * bits ** X ############### Character 0x54, 0124, 84 T T T T T T T T T T char 84 hs 3 vs 7 ha 1 va -8 hi 5 vi 0 bits *** bits * bits * bits * bits * bits * bits * X ############### Character 0x55, 0125, 85 U U U U U U U U U U char 85 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits * * bits * * bits * * bits * * bits * * bits ** X ############### Character 0x56, 0126, 86 V V V V V V V V V V char 86 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits * * bits * * bits * * bits * * bits ** bits * X ############### Character 0x57, 0127, 87 W W W W W W W W W W char 87 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits * * bits * * bits **** bits **** bits **** bits * * X ############### Character 0x58, 0130, 88 X X X X X X X X X X char 88 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits * * bits ** bits ** bits ** bits * * bits * * X ############### Character 0x59, 0131, 89 Y Y Y Y Y Y Y Y Y Y char 89 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * * bits * * bits * * bits ** bits * bits * bits * X ############### Character 0x5a, 0132, 90 Z Z Z Z Z Z Z Z Z Z char 90 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits **** bits * bits * bits **** bits * bits * bits **** X ############### Character 0x5b, 0133, 91 [ [ [ [ [ [ [ [ [ [ char 91 hs 3 vs 7 ha 2 va -8 hi 5 vi 0 bits *** bits * bits * bits * bits * bits * bits *** X ############### Character 0x5c, 0134, 92 \ \ \ \ \ \ \ \ \ \ char 92 hs 4 vs 6 ha 1 va -7 hi 5 vi 0 bits * bits * bits * bits * bits * bits * X ############### Character 0x5d, 0135, 93 ] ] ] ] ] ] ] ] ] ] char 93 hs 3 vs 7 ha 1 va -8 hi 5 vi 0 bits *** bits * bits * bits * bits * bits * bits *** X ############### Character 0x5e, 0136, 94 ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ char 94 hs 3 vs 2 ha 1 va -8 hi 5 vi 0 bits * bits * * X ############### Character 0x5f, 0137, 95 _ _ _ _ _ _ _ _ _ _ char 95 hs 5 vs 1 ha 0 va -1 hi 5 vi 0 bits ***** X ############### Character 0x60, 0140, 96 ` ` ` ` ` ` ` ` ` ` char 96 hs 3 vs 3 ha 2 va -8 hi 5 vi 0 bits * bits * bits * X ############### Character 0x61, 0141, 97 a a a a a a a a a a char 97 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits ** bits * bits *** bits * * bits *** X ############### Character 0x62, 0142, 98 b b b b b b b b b b char 98 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits *** bits * * bits * * bits * * bits *** X ############### Character 0x63, 0143, 99 c c c c c c c c c c char 99 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits ** bits * * bits * bits * * bits ** X ############### Character 0x64, 0144, 100 d d d d d d d d d d char 100 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits *** bits * * bits * * bits * * bits *** X ############### Character 0x65, 0145, 101 e e e e e e e e e e char 101 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits ** bits * * bits **** bits * bits *** X ############### Character 0x66, 0146, 102 f f f f f f f f f f char 102 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * bits * bits **** bits * bits * bits * X ############### Character 0x67, 0147, 103 g g g g g g g g g g char 103 hs 4 vs 6 ha 1 va -6 hi 5 vi 0 bits *** bits * * bits * * bits *** bits * bits ** X ############### Character 0x68, 0150, 104 h h h h h h h h h h char 104 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits *** bits * * bits * * bits * * bits * * X ############### Character 0x69, 0151, 105 i i i i i i i i i i char 105 hs 3 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits bits ** bits * bits * bits * bits *** X ############### Character 0x6a, 0152, 106 j j j j j j j j j j char 106 hs 3 vs 8 ha 1 va -8 hi 5 vi 0 bits * bits bits ** bits * bits * bits * bits * * bits * X ############### Character 0x6b, 0153, 107 k k k k k k k k k k char 107 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits * * bits * * bits ** bits * * bits * * X ############### Character 0x6c, 0154, 108 l l l l l l l l l l char 108 hs 3 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * bits * bits * bits * bits * bits *** X ############### Character 0x6d, 0155, 109 m m m m m m m m m m char 109 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits * * bits **** bits **** bits * * bits * * X ############### Character 0x6e, 0156, 110 n n n n n n n n n n char 110 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits *** bits * * bits * * bits * * bits * * X ############### Character 0x6f, 0157, 111 o o o o o o o o o o char 111 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits ** bits * * bits * * bits * * bits ** X ############### Character 0x70, 0160, 112 p p p p p p p p p p char 112 hs 4 vs 6 ha 1 va -6 hi 5 vi 0 bits *** bits * * bits * * bits *** bits * bits * X ############### Character 0x71, 0161, 113 q q q q q q q q q q char 113 hs 4 vs 6 ha 1 va -6 hi 5 vi 0 bits *** bits * * bits * * bits *** bits * bits * X ############### Character 0x72, 0162, 114 r r r r r r r r r r char 114 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits *** bits * * bits * bits * bits * X ############### Character 0x73, 0163, 115 s s s s s s s s s s char 115 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits *** bits * bits ** bits * bits *** X ############### Character 0x74, 0164, 116 t t t t t t t t t t char 116 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits * bits * bits *** bits * bits * bits * * bits ** X ############### Character 0x75, 0165, 117 u u u u u u u u u u char 117 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits * * bits * * bits * * bits * * bits *** X ############### Character 0x76, 0166, 118 v v v v v v v v v v char 118 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits * * bits * * bits * * bits ** bits * X ############### Character 0x77, 0167, 119 w w w w w w w w w w char 119 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits * * bits * * bits **** bits **** bits * * X ############### Character 0x78, 0170, 120 x x x x x x x x x x char 120 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits * * bits * * bits ** bits * * bits * * X ############### Character 0x79, 0171, 121 y y y y y y y y y y char 121 hs 4 vs 6 ha 1 va -6 hi 5 vi 0 bits * * bits * * bits * * bits *** bits * bits ** X ############### Character 0x7a, 0172, 122 z z z z z z z z z z char 122 hs 4 vs 5 ha 1 va -6 hi 5 vi 0 bits **** bits * bits * bits * bits **** X ############### Character 0x7b, 0173, 123 { { { { { { { { { { char 123 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * bits * bits ** bits * bits * bits ** X ############### Character 0x7c, 0174, 124 | | | | | | | | | | char 124 hs 1 vs 9 ha 4 va -9 hi 5 vi 0 bits * bits * bits * bits * bits bits * bits * bits * bits * X ############### Character 0x7d, 0175, 125 } } } } } } } } } } char 125 hs 4 vs 7 ha 1 va -8 hi 5 vi 0 bits ** bits * bits * bits ** bits * bits * bits ** X ############### Character 0x7e, 0176, 126 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ char 126 hs 4 vs 2 ha 1 va -6 hi 5 vi 0 bits * * bits * * X ############### Character 0x7f, 0177, 127 char 127 hs 4 vs 8 ha 3 va -9 hi 5 vi 0 bits **** bits **** bits **** bits **** bits **** bits **** bits **** bits **** X SHAR_EOF chmod 0644 font/xtclient.ft || echo 'restore of font/xtclient.ft failed' Wc_c="`wc -c < 'font/xtclient.ft'`" test 16814 -eq "$Wc_c" || echo 'font/xtclient.ft: original size 16814, current size' "$Wc_c" fi 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. **