uw client for the 3b1
Andy Fyfe
andy at cit-vax.Caltech.Edu
Tue Feb 14 19:23:57 AEST 1989
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: README Makefile controller.c dial.c msg_queues.c reader.c
# utils.c uw.c uw.h uw_pcl.h window.c writer.c uw.uue
# Wrapped by andy at marmot on Mon Feb 13 22:38:53 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(3940 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XUW client for the AT&T 3b1
X
XThe original UW program is by John D. Bruner. The copyright on this
Xprogram is the same as that for the original.
X
XThis client program supports only UW protocol 1. It is at the level of
Xsomething just above a quick hack. It works fine for me (I'm running
Xversion 3.5 unix). It supports only the built-in modem, but I suspect
Xit would be quite easy to get it to use the tty port.
X
XThe basic use of the program is "uw <phone-number>". Once you're
Xlogged in, run "uw" on the host. Any windows that the "uw" server
Xcreates will be assumed to be "adm31" type windows ("uw" will set the
XTERM and TERMCAP variables to such) and so it's necessary to override
Xthat since the "uw" client does not do any terminal emulation (and thus
Xwindows are "s4"s). One way to do this is to set an environment
Xvariable when you log in (say "ATT_3B1") and in your .cshrc (or .shrc
Xor .kshrc) check to see if it's set and if it is, override "TERM" and
X"TERMCAP". This even works for commands like "uwtool rn", but only if
Xtyped at the keyboard -- for some reason it doesn't if they appear in
Xyour .uwrc (though commands in the .uwrc that just create shells work
Xfine).
X
XYou can use the 3b1 window manager to change windows -- the "uw" client
Xwill notice the change (though there may be a few seconds of delay if
Xyour previous window was not a uw window). New windows can be created
Xwith "uwtool", and when all windows die, the client will automatically
Xshut down the server and return to a simple non-windowed terminal
Xprogram.
X
XBecause of the above, it is not necessary to have any control of
Xcreating, destroying or changing windows from the keyboard (via the
Xclient). If you want to, though, it is possible. The commands are
Xentered via an escape character followed by a command letter: 'c' (or
X'C') creates a window, 'k' (or 'K') kills the current window, and '1'
Xthrough '7' switch to window number '1' through '7' respectively. (To
Xenter the escape character, type it twice.) Any character can be the
Xescape character. It is entered with the "-e" option. Printable
Xcharacters are entered as themselves, control characters (or delete)
Xare entered as the 2-character string ^A, ^B, etc. with ^? for delete.
XFurthermore, they can be preceeded by 'M' to indicate that the high
Xorder bit should be on (so \201 can be make the escape char with "uw -e
XM^A <number>"). A default escape character can be compiled in (see the
XMakefile), and can be disabled by using the "-E" option. Alternately,
Xthose characters can be typed along with the 'meta' key (if you have
XMichael "Ford" Ditto's nkbd driver). It is available with the "-m"
Xoption, and like "-e" can be made the default at compile time and
Xoverrided with "-M". Both can be used, either, or neither. Whatever
Xsuits you. Be warned though, since invalid commands wind up as a
X"beep", with -m all other meta-characters become "beeps".
X
X"uw" will terminate automatically when the modem hangs up. If you
Xneed to kill it some other time, you'll need to send a SIGHUP to
Xthe controller process (which will have the lowest process number).
X
XThe program was written knowing that it would be compiled with Gnu C
X(and version 33 is required unless you delete the "volatile" from some
Xfunction defs). A uuencoded binary is included (it's stripped, and
Xuses the shared library). The file <stdlib.h> is included -- it's not
Xnecessary, as it just provides prototypes for most of libc, but it's
Xhandy for finding bugs.
X
XThere may well be bugs (or worse, race conditions). If you find any
Xlet me know. Occasionally windows hang (with the death star looming in
Xthe corner of the screen). So far it's been enough to use the window
Xmanager to change windows to something else and back again to fix it. I
Xdon't expect to upgrade this to use protocol 2 any time soon.
X
XAndy Fyfe
X andy at csvax.caltech.edu
X wjafyfe at caltech.bitnet
X andy at cit-vax.uucp (...ames!elroy!cit-vax!andy)
END_OF_FILE
if test 3940 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(265 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCC = gcc
XCFLAGS = -Wall -O # -DDEFAULT_META -DDEFAULT_KBD_ESC='"^A"'
XLDFLAGS = -shlib -s
X
XOBJS = controller.o dial.o msg_queues.o reader.o utils.o uw.o window.o writer.o
X
Xuw: $(OBJS)
X $(CC) $(CFLAGS) -o uw $(OBJS) $(LDFLAGS)
X
X$(OBJS): uw.h uw_pcl.h
X
Xuw.o: Makefile
END_OF_FILE
if test 265 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'controller.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'controller.c'\"
else
echo shar: Extracting \"'controller.c'\" \(2860 characters\)
sed "s/^X//" >'controller.c' <<'END_OF_FILE'
X/*
X * controller -- not much happens unless the controller requests it
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include "uw.h"
X
X#include <stdio.h>
X#include <signal.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X#include <errno.h>
X
Xstatic void startup_0(void);
Xstatic void new_window(int logical_window);
Xstatic int all_windows_gone(void);
Xstatic int stop;
X
Xstatic void catch(void);
X
Xvoid
Xcontroller(void)
X{
X struct message msg;
X extern int errno;
X
X stop = 0;
X
X startup_0();
X
X signal(SIGHUP, catch);
X
X while(1) {
X if (stop || !modem_connected()) {
X send_rd_wr(DIE_CMD, 0, 0);
X break;
X }
X if (msgrcv(c_id, &msg, MSG_SIZE, MSG_TYPE, IPC_NOWAIT) < 0) {
X sleep(TIMEOUT);
X continue;
X }
X if (msg.text[SERVER_BYTE] & P1_FORCE_SHUTDOWN) {
X send_rd_wr(DIE_CMD, 0, 0);
X break;
X }
X switch(msg.text[SERVER_BYTE] & P1_FN) {
X case P1_FN_NEWW:
X if (msg.text[SERVER_BYTE] & P1_WINDOW)
X new_window(msg.text[SERVER_BYTE] & P1_WINDOW);
X break;
X case P1_FN_KILLW:
X if (msg.text[SERVER_BYTE] & P1_WINDOW) {
X send_rd_wr(KILL_WINDOW_CMD, 0,
X msg.text[SERVER_BYTE] & P1_WINDOW);
X close_window(msg.text[SERVER_BYTE] & P1_WINDOW);
X if (all_windows_gone())
X startup_0();
X }
X break;
X case P1_FN_MAINT:
X switch (msg.text[SERVER_BYTE] & P1_MF) {
X case P1_MF_ENTRY:
X if (protocol == PROTOCOL_0)
X close_window(0);
X else if (protocol == PROTOCOL_1)
X close_all_windows();
X send_rd_wr(PROTOCOL_1_CMD, 0, 0);
X protocol = PROTOCOL_1;
X break;
X case P1_MF_EXIT:
X if (protocol == PROTOCOL_1) {
X close_all_windows();
X startup_0();
X }
X break;
X }
X break;
X }
X }
X return;
X}
X
Xstatic void
Xstartup_0(void)
X{
X int window, fd, ret;
X struct message msg;
X extern int errno;
X
X protocol = PROTOCOL_0;
X
X fd = get_window("Unix Windows");
X window = window_number(fd);
X
X if (window < 0) {
X fprintf(stderr, "%s: can't open base window: ", cmd_name);
X perror("");
X send_rd_wr(DIE_CMD, 0, 0);
X stop = 1;
X }
X
X win_info[0].fd = fd;
X win_info[0].window_number = window;
X
X send_rd_wr(PROTOCOL_0_CMD, window, 0);
X}
X
Xstatic void
Xcatch(void)
X{
X stop = 1;
X
X signal(SIGHUP, SIG_IGN);
X}
X
Xstatic void
Xnew_window(int logical_window)
X{
X int window, fd;
X struct message msg;
X char title[80];
X
X sprintf(title, "UW -- window %d", logical_window);
X fd = get_window(title);
X window = window_number(fd);
X
X win_info[logical_window].fd = fd;
X win_info[logical_window].window_number = window;
X
X send_rd_wr(CREATE_WINDOW_CMD, window, logical_window);
X}
X
Xstatic int
Xall_windows_gone(void)
X{
X int i;
X
X for (i=1; i <= MAX_WINDOWS; ++i)
X if (win_info[i].fd >= 0)
X return 0;
X return 1;
X}
END_OF_FILE
if test 2860 -ne `wc -c <'controller.c'`; then
echo shar: \"'controller.c'\" unpacked with wrong size!
fi
# end of 'controller.c'
fi
if test -f 'dial.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dial.c'\"
else
echo shar: Extracting \"'dial.c'\" \(1832 characters\)
sed "s/^X//" >'dial.c' <<'END_OF_FILE'
X/*
X * dial -- dial the phone number
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include "uw.h"
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <dial.h>
X#include <sys/phone.h>
X
Xstatic const char *errs[] = { "zero", "interrupt", "dialer hung",
X "no answer", "illegal baud-rate", "acu problem",
X "line problem", "can't open LDEVS",
X "device not available", "device unknown",
X "no device available at baud-rate",
X "no device known at baud-rate" };
X
Xint dial(CALL);
X
Xint
Xdial_number(const char *number)
X{
X CALL call;
X struct termio term;
X struct updata phone;
X int fd;
X
X fd = open(PHONE_PATH, O_RDONLY, 0);
X if (fd >= 0) {
X ioctl(fd, PIOCGETP, &phone);
X phone.c_lineparam = DTMF;
X phone.c_feedback = SPEAKERON | SOFTSPK;
X ioctl(fd, PIOCSETP, &phone);
X close(fd);
X }
X
X fd = open(PHONE_PATH, O_RDWR | O_NDELAY, 0);
X if (fd < 0) {
X fprintf(stderr, "%s: Can't open %s: ", cmd_name, PHONE_PATH);
X perror("");
X return -1;;
X }
X ioctl(fd, TCGETA, &term);
X close(fd);
X
X term.c_iflag = IXOFF | IXON | ISTRIP | IGNPAR;
X term.c_oflag = 0;
X term.c_cflag = HUPCL | CREAD | CS8 | B1200;
X term.c_lflag = 0;
X term.c_cc[VMIN] = 1;
X term.c_cc[VTIME] = 0;
X call.attr = &term;
X call.baud = 1200;
X call.speed = 1200;
X call.line = PHONE_LINE;
X call.telno = (char *)number;
X call.modem = 0;
X
X fd = -1;
X fd = dial(call);
X if (fd < 0) {
X fprintf(stderr, "%s: dial failed: %s\n", cmd_name, errs[-fd]);
X return -1;;
X }
X
X return fd;
X}
X
Xint
Xmodem_connected(void)
X{
X struct updata d;
X
X if (ioctl(phone_fd, PIOCGETP, &d) < 0)
X return 1;
X
X return d.c_linestatus & MODEMCONNECTED;
X}
END_OF_FILE
if test 1832 -ne `wc -c <'dial.c'`; then
echo shar: \"'dial.c'\" unpacked with wrong size!
fi
# end of 'dial.c'
fi
if test -f 'msg_queues.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'msg_queues.c'\"
else
echo shar: Extracting \"'msg_queues.c'\" \(1901 characters\)
sed "s/^X//" >'msg_queues.c' <<'END_OF_FILE'
X/*
X * msg_queues -- create and destroy the message queues
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include "uw.h"
X
X#include <stdio.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X
Xkey_t c_key, r_key, w_key;
Xint c_id, r_id, w_id;
X
X/*
X * The 'c' queue is to send messages to the control process.
X * Both the reader and the write can do this.
X *
X * The 'r' queue is to send messages from the controller to the reader.
X *
X * The 'w' queue is to send messages from the controller to the writer.
X */
Xint
Xcreate_message_queues(void)
X{
X c_id = r_id = w_id = -1;
X
X c_key = ftok(UW_PROGRAM, 'c');
X if (c_key < 0) {
X fprintf(stderr, "%s: ftok failed (control): ", cmd_name);
X perror("");
X return -1;
X }
X c_id = msgget(c_key, IPC_CREAT | IPC_EXCL | 0722);
X if (c_id < 0) {
X fprintf(stderr, "%s: msgget failed (control): ", cmd_name);
X perror("");
X return -1;
X }
X
X r_key = ftok(UW_PROGRAM, 'r');
X if (r_key < 0) {
X fprintf(stderr, "%s: ftok failed (reader): ", cmd_name);
X perror("");
X return -1;
X }
X r_id = msgget(r_key, IPC_CREAT | IPC_EXCL | 0744);
X if (r_id < 0) {
X fprintf(stderr, "%s: msgget failed (reader): ", cmd_name);
X perror("");
X return -1;
X }
X
X w_key = ftok(UW_PROGRAM, 'w');
X if (w_key < 0) {
X fprintf(stderr, "%s: ftok failed (writer): ", cmd_name);
X perror("");
X return -1;
X }
X w_id = msgget(w_key, IPC_CREAT | IPC_EXCL | 0744);
X if (w_id < 0) {
X fprintf(stderr, "%s: msgget failed (writer): ", cmd_name);
X perror("");
X return -1;
X }
X
X return 0;
X}
X
Xvoid
Xdelete_message_queues(void)
X{
X if (c_id >= 0)
X msgctl(c_id, IPC_RMID, (struct msqid_ds *)0);
X if (r_id >= 0)
X msgctl(r_id, IPC_RMID, (struct msqid_ds *)0);
X if (w_id >= 0)
X msgctl(w_id, IPC_RMID, (struct msqid_ds *)0);
X}
END_OF_FILE
if test 1901 -ne `wc -c <'msg_queues.c'`; then
echo shar: \"'msg_queues.c'\" unpacked with wrong size!
fi
# end of 'msg_queues.c'
fi
if test -f 'reader.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'reader.c'\"
else
echo shar: Extracting \"'reader.c'\" \(4731 characters\)
sed "s/^X//" >'reader.c' <<'END_OF_FILE'
X/*
X * reader -- get input from the keyboard and sent it to the host
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include "uw.h"
X#include <sys/window.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X#include <errno.h>
X#include <stdio.h>
X#include <signal.h>
X
Xstatic int set_current(int real_window);
Xstatic void check_input(void);
Xstatic void check_command(void);
Xstatic void send_to_server(unsigned char);
X
Xstatic int window, sig_usr1;
X
Xstatic void
Xcatch_usr1(void)
X{
X signal(SIGUSR1, catch_usr1);
X ++sig_usr1;
X}
X
Xstatic void
Xcatch_wind(void)
X{
X signal(SIGWIND, catch_wind);
X}
X
Xvoid
Xreader(void)
X{
X int current;
X
X signal(SIGUSR1, catch_usr1);
X signal(SIGWIND, catch_wind);
X
X ++sig_usr1; /* we may have missed the first signal */
X
X window = -1;
X
X while (1) {
X if (sig_usr1)
X check_command();
X
X current = ioctl(STDIN, WIOCGCURR, (char *)0);
X if (current >= 0 && (window < 0 ||
X (window >= 0 && current != win_info[window].window_number)))
X if (set_current(current) < 0 && !sig_usr1)
X sleep(TIMEOUT);
X
X if (window >= 0)
X check_input();
X }
X}
X
Xstatic int
Xset_current(int real_window)
X{
X int i;
X
X if (protocol == PROTOCOL_0) {
X if (win_info[0].window_number == real_window && win_info[0].fd >= 0) {
X window = 0;
X return 0;
X }
X }
X else if (protocol == PROTOCOL_1) {
X for (i=1; i<=MAX_WINDOWS; ++i) {
X if (win_info[i].window_number == real_window
X && win_info[i].fd >= 0) {
X send_to_server(P1_FN_ISELW | i);
X window = i;
X return 0;
X }
X }
X }
X
X return -1;
X}
X
Xstatic void
Xcheck_input(void)
X{
X int i;
X static int keyboard_escape;
X unsigned char c;
X
X if (read(win_info[window].fd, &c, 1) <= 0)
X return;
X
X if (protocol == PROTOCOL_0) {
X write(phone_fd, &c, 1);
X return;
X }
X if (protocol == PROTOCOL_1) {
X if (!keyboard_escape) {
X if (c == kbd_esc_char) {
X keyboard_escape = 1;
X return;
X }
X if (use_meta && (c & META_BIT)) {
X keyboard_escape = 1;
X c &= ~META_BIT;
X }
X }
X if (!keyboard_escape || (keyboard_escape && c == kbd_esc_char)) {
X if (c & META_BIT)
X send_to_server(P1_FN_META);
X c &= ~META_BIT;
X if (c == IAC)
X send_to_server(P1_FN_CTLCH | P1_CC_IAC);
X else if (c == XON)
X send_to_server(P1_FN_CTLCH | P1_CC_XON);
X else if (c == XOFF)
X send_to_server(P1_FN_CTLCH | P1_CC_XOFF);
X else
X write(phone_fd, &c, 1);
X }
X else {
X switch(c) {
X case 'C':
X case 'c':
X for (i=1; i<=MAX_WINDOWS; ++i) {
X if (win_info[i].fd < 0)
X break;
X }
X if (i <= MAX_WINDOWS) {
X send_controller(P1_FN_NEWW | i);
X send_to_server(P1_FN_NEWW | i);
X }
X break;
X case 'K':
X case 'k':
X if (window > 0 && win_info[window].fd >= 0) {
X send_controller(P1_FN_KILLW | window);
X send_to_server(P1_FN_KILLW | window);
X }
X break;
X case '1':
X case '2':
X case '3':
X case '4':
X case '5':
X case '6':
X case '7':
X i = c - '1' + 1;
X if (i > 0 && win_info[i].fd >= 0) {
X if (ioctl(win_info[i].fd, WIOCSELECT, (char *)0) >= 0)
X send_to_server(P1_FN_ISELW | i);
X }
X break;
X default:
X c = '\a';
X write(1, &c, 1);
X break;
X }
X }
X keyboard_escape = 0;
X }
X return;
X}
X
Xstatic void
Xcheck_command(void)
X{
X struct message msg;
X extern int errno;
X
X if (msgrcv(r_id, &msg, MSG_SIZE, MSG_TYPE, IPC_NOWAIT) < 0) {
X --sig_usr1;
X return;
X }
X
X switch (msg.text[COMMAND]) {
X case PROTOCOL_0_CMD:
X if (protocol == PROTOCOL_1) {
X close_all_windows();
X send_to_server(P1_FN_MAINT | P1_MF_EXIT);
X }
X protocol = PROTOCOL_0;
X if (open_window(0, msg.text[REAL_WINDOW], READ_ONLY) < 0)
X send_controller(P1_FORCE_SHUTDOWN);
X else
X window = 0;
X break;
X case PROTOCOL_1_CMD:
X if (protocol == PROTOCOL_0)
X close_window(0);
X if (protocol == PROTOCOL_1)
X close_all_windows();
X protocol = PROTOCOL_1;
X window = -1;
X break;
X case CREATE_WINDOW_CMD:
X if (msg.text[REAL_WINDOW] <= 0) {
X send_to_server(P1_FN_KILLW | window);
X }
X else {
X if (open_window(msg.text[LOGICAL_WINDOW], msg.text[REAL_WINDOW],
X READ_ONLY) < 0)
X send_controller(P1_FN_KILLW | msg.text[LOGICAL_WINDOW]);
X else {
X window = msg.text[LOGICAL_WINDOW];
X send_to_server(P1_FN_ISELW | window);
X }
X }
X break;
X case KILL_WINDOW_CMD:
X close_window(msg.text[LOGICAL_WINDOW]);
X if (window == LOGICAL_WINDOW)
X window = -1;
X break;
X case DIE_CMD:
X close(phone_fd);
X exit(0);
X break;
X }
X}
X
Xstatic void
Xsend_to_server(unsigned char c)
X{
X static const unsigned char prefix = P1_IAC;
X
X write(phone_fd, &prefix, 1);
X c = c | P1_DIR_CTOS;
X write(phone_fd, &c, 1);
X}
END_OF_FILE
if test 4731 -ne `wc -c <'reader.c'`; then
echo shar: \"'reader.c'\" unpacked with wrong size!
fi
# end of 'reader.c'
fi
if test -f 'utils.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'utils.c'\"
else
echo shar: Extracting \"'utils.c'\" \(2379 characters\)
sed "s/^X//" >'utils.c' <<'END_OF_FILE'
X/*
X * utils -- open and close windows, etc.
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include "uw.h"
X#include <fcntl.h>
X#include <stdio.h>
X#include <termio.h>
X#include <signal.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X
Xstatic int set_window_modes(int fd);
X
Xvoid
Xclose_window(int logical_window)
X{
X if (win_info[logical_window].fd >= 0) {
X close(win_info[logical_window].fd);
X win_info[logical_window].fd = -1;
X win_info[logical_window].window_number = -1;
X }
X}
X
Xvoid
Xclose_all_windows(void)
X{
X int i;
X
X for (i=1; i<=MAX_WINDOWS; ++i)
X close_window(i);
X}
X
Xint
Xopen_window(int logical_window, int real_window, int rdonly)
X{
X static char window_name[32];
X
X if (real_window <= 0)
X return -1;
X
X if (win_info[logical_window].fd != -1)
X return -1;
X
X sprintf(window_name, WINDOW_DEVICE_BY_NUMBER, real_window);
X win_info[logical_window].fd =
X open(window_name, (rdonly == READ_ONLY ? O_RDONLY : O_WRONLY), 0);
X
X if (win_info[logical_window].fd < 0) {
X fprintf(stderr, "%s: can't open %s: ", cmd_name, window_name);
X perror("");
X return -1;;
X }
X if (set_window_modes(win_info[logical_window].fd) < 0)
X return -1;
X
X win_info[logical_window].window_number = real_window;
X
X return 0;
X}
X
Xstatic int
Xset_window_modes(int fd)
X{
X struct termio t;
X
X if (ioctl(fd, TCGETA, &t) < 0) {
X fprintf(stderr, "%s: can't get termio for fd %d: ", cmd_name, fd);
X perror("");
X return -1;
X }
X
X t.c_cc[VMIN] = 1;
X t.c_cc[VTIME] = 0;
X t.c_iflag = 0;
X t.c_oflag = 0;
X t.c_lflag = 0;
X
X if (ioctl(fd, TCSETA, &t) < 0) {
X fprintf(stderr, "%s: can't set termio for fd %d: ", cmd_name, fd);
X perror("");
X return -1;
X }
X
X return 0;
X}
X
Xvoid
Xsend_controller(int byte)
X{
X struct message msg;
X
X msg.type = MSG_TYPE;
X msg.text[COMMAND] = SERVER_CMD;
X msg.text[SERVER_BYTE] = byte;
X msgsnd(c_id, &msg, MSG_SIZE, IPC_NOWAIT);
X}
X
Xvoid
Xsend_rd_wr(int command, int param1, int param2)
X{
X struct message msg;
X
X msg.type = MSG_TYPE;
X msg.text[COMMAND] = command;
X msg.text[PARAM1] = param1;
X msg.text[PARAM2] = param2;
X msgsnd(r_id, &msg, MSG_SIZE, IPC_NOWAIT);
X msgsnd(w_id, &msg, MSG_SIZE, IPC_NOWAIT);
X kill(pid_rd, SIGUSR1);
X kill(pid_wr, SIGUSR1);
X}
END_OF_FILE
if test 2379 -ne `wc -c <'utils.c'`; then
echo shar: \"'utils.c'\" unpacked with wrong size!
fi
# end of 'utils.c'
fi
if test -f 'uw.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'uw.c'\"
else
echo shar: Extracting \"'uw.c'\" \(4132 characters\)
sed "s/^X//" >'uw.c' <<'END_OF_FILE'
X/*
X * uw -- the main program
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include "uw.h"
X
X#include <stdio.h>
X#include <signal.h>
X#include <errno.h>
X#include <sys/window.h>
X
Xchar *cmd_name;
X
Xstatic volatile void usage(void);
Xstatic volatile void terminate(void);
Xstatic void reap(void);
X
Xint phone_fd;
Xstruct window_info win_info[MAX_WINDOWS + 1];
Xint protocol;
Xint pid_rd, pid_wr;
Xint use_meta, kbd_esc_char;
X
Xint undial(int);
Xstatic int conv_esc(const char *);
X
Xvoid
Xmain(int argc, char *argv[])
X{
X int i;
X
X cmd_name = argv[0];
X
X if (ioctl(STDIN, WIOCGCURR, (char *)0) < 0) {
X fprintf(stderr, "%s: can't get current window\n", cmd_name);
X exit(1);
X }
X
X#ifdef DEFAULT_META
X use_meta = 1;
X#else
X use_meta = 0;
X#endif
X
X#ifdef DEFAULT_KBD_ESC
X kbd_esc_char = conv_esc(DEFAULT_KBD_ESC);
X#else
X kbd_esc_char = -1;
X#endif
X
X for (i=1; i < argc; ++i) {
X if (argv[i][0] == '-') {
X switch (argv[i][1]) {
X case 'm':
X use_meta = 1;
X break;
X case 'M':
X use_meta = 0;
X break;
X case 'e':
X kbd_esc_char = conv_esc(argv[++i]);
X break;
X case 'E':
X kbd_esc_char = -1;
X break;
X default:
X usage();
X break;
X }
X }
X else
X break;
X }
X if (i != argc - 1)
X usage();
X
X printf("Dialing %s", argv[argc-1]);
X if (use_meta)
X printf(", using meta key");
X if (kbd_esc_char >= 0) {
X printf(", using escape char \"");
X if (kbd_esc_char & 0200)
X printf("M");
X i = kbd_esc_char & 0177;
X if (i < ' ')
X printf("^%c", i + '@');
X else if (i == 0177)
X printf("^?");
X else
X printf("%c", i);
X printf("\" ('\\%.3o')", kbd_esc_char);
X }
X printf("\n");
X
X signal(SIGINT, terminate);
X signal(SIGQUIT, terminate);
X signal(SIGHUP, terminate);
X
X for (i=0; i<=MAX_WINDOWS; ++i) {
X win_info[i].window_number = -1;
X win_info[i].fd = -1;
X }
X protocol = -1;
X
X if (create_message_queues() < 0)
X terminate();
X
X phone_fd = dial_number(argv[argc-1]);
X
X if (phone_fd < 0)
X terminate();
X
X signal(SIGINT, SIG_IGN);
X signal(SIGQUIT, SIG_IGN);
X signal(SIGHUP, SIG_IGN);
X signal(SIGUSR1, SIG_IGN);
X
X pid_rd = fork();
X if (pid_rd < 0) {
X fprintf(stderr, "%s: can't fork: ", cmd_name);
X perror("");
X terminate();
X }
X
X if (pid_rd == 0)
X reader();
X
X pid_wr = fork();
X if (pid_wr < 0) {
X fprintf(stderr, "%s: can't fork: ", cmd_name);
X perror("");
X kill(pid_rd, SIGKILL);
X terminate();
X }
X
X if (pid_wr == 0)
X writer();
X
X controller();
X
X terminate();
X}
X
Xstatic volatile void
Xusage(void)
X{
X fprintf(stderr, "%s: Usage: %s [-m | -M | -E | -e esc] <telno>\n",
X cmd_name, cmd_name);
X exit(1);
X}
X
Xstatic volatile void
Xterminate(void)
X{
X signal(SIGINT, terminate);
X signal(SIGQUIT, terminate);
X signal(SIGHUP, terminate);
X
X reap();
X
X delete_message_queues();
X
X close_window(0);
X close_all_windows();
X
X if (phone_fd >= 0) {
X undial(phone_fd);
X }
X
X exit(0);
X}
X
Xstatic void
Xcatch(void)
X{
X}
X
Xstatic void
Xreap(void)
X{
X int pid;
X
X signal(SIGALRM, catch);
X alarm(10);
X
X while (pid_rd > 0 && pid_wr > 0) {
X pid = wait((int *)0);
X if (pid < 0) {
X fprintf(stderr, "%s: error from wait: ", cmd_name);
X perror("");
X break;
X }
X if (pid == pid_rd)
X pid_rd = -1;
X if (pid == pid_wr)
X pid_wr = -1;
X }
X
X alarm(0);
X signal(SIGALRM, SIG_DFL);
X
X if (pid_rd > 0)
X kill(pid_rd, SIGKILL);
X if (pid_wr > 0)
X kill(pid_wr, SIGKILL);
X}
X
Xstatic int
Xconv_esc(const char *p)
X{
X const char *q = p;
X int l = strlen(p);
X int meta = 0;
X
X if (l > 1) {
X if (q[0] == 'M') {
X meta = 0200;
X q++;
X l--;
X }
X }
X if (l == 1) {
X if (q[0] >= ' ' && q[0] < '\177')
X return q[0] | meta;
X }
X else if (l == 2) {
X if (q[0] == '^') {
X if (q[1] >= '@' && q[1] <= '_')
X return (q[1] & 0x1f) | meta;
X else if (q[1] >= 'a' && q[1] <= 'z')
X return (q[1] & 0x1f) | meta;
X else if (q[1] == '?')
X return '\177' | meta;
X }
X }
X
X fprintf(stderr, "%s: invalid escape %s\n", cmd_name, p);
X return -1;
X}
END_OF_FILE
if test 4132 -ne `wc -c <'uw.c'`; then
echo shar: \"'uw.c'\" unpacked with wrong size!
fi
# end of 'uw.c'
fi
if test -f 'uw.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'uw.h'\"
else
echo shar: Extracting \"'uw.h'\" \(2086 characters\)
sed "s/^X//" >'uw.h' <<'END_OF_FILE'
X/*
X * uw.h -- random stuff needed by the C source
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include <stdlib.h>
X#include <sys/types.h>
X#include "uw_pcl.h"
X
X#define PHONE_LINE "ph1"
X#define PHONE_PATH "/dev/ph1"
X
X#define WINDOW_DEVICE "/dev/window"
X#define WINDOW_DEVICE_BY_NUMBER "/dev/w%d"
X
X#define UW_PROGRAM "/usr/local/bin/uw"
X
X#define STDIN 0
X
X#define MAX_WINDOWS P1_NWINDOW
X
X#define READ_ONLY 1
X#define WRITE_ONLY 0
X
X#define PROTOCOL_0 1
X#define PROTOCOL_1 2
X
X#define PROTOCOL_0_CMD '0'
X#define PROTOCOL_1_CMD '1'
X#define CREATE_WINDOW_CMD 'C'
X#define KILL_WINDOW_CMD 'K'
X#define DIE_CMD 'D'
X#define SERVER_CMD 'S'
X
X#define COMMAND 0
X#define PARAM1 1
X#define PARAM2 2
X#define REAL_WINDOW PARAM1
X#define LOGICAL_WINDOW PARAM2
X#define SERVER_BYTE PARAM1
X
X#define MSG_SIZE 8
X#define MSG_TYPE 1
X
X#define IAC P1_IAC
X#define XON '\021'
X#define XOFF '\023'
X#define META_BIT 0200
X
X#define TIMEOUT 3
X
Xstruct message {
X long type;
X char text[MSG_SIZE];
X};
X
Xstruct window_info {
X int window_number;
X int fd;
X};
X
Xextern char *cmd_name;
Xextern int phone_fd;
Xextern struct window_info win_info[MAX_WINDOWS + 1];
Xextern int pid_rd, pid_wr;
Xextern int protocol;
Xextern key_t c_key, r_key, w_key;
Xextern int c_id, r_id, w_id;
Xextern int use_meta, kbd_esc_char;
X
Xint dial_number(const char *number);
Xint modem_connected(void);
X
Xint create_message_queues(void);
Xvoid delete_message_queues(void);
X
Xint get_window(const char *win_name);
Xint window_number(int fd);
X
Xvoid close_window(int logical_window);
Xvoid close_all_windows(void);
Xint open_window(int logical_window, int real_window, int rdonly);
X
Xvoid send_controller(int byte);
Xvoid send_rd_wr(int command, int param1, int param2);
X
Xvolatile void reader(void);
Xvolatile void writer(void);
Xvoid controller(void);
X
Xint msgctl(int, int, void *);
Xint msgget(key_t, int);
Xint msgsnd(int, void *, int, int);
Xint msgrcv(int, void *, int, long, int);
END_OF_FILE
if test 2086 -ne `wc -c <'uw.h'`; then
echo shar: \"'uw.h'\" unpacked with wrong size!
fi
# end of 'uw.h'
fi
if test -f 'uw_pcl.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'uw_pcl.h'\"
else
echo shar: Extracting \"'uw_pcl.h'\" \(1538 characters\)
sed "s/^X//" >'uw_pcl.h' <<'END_OF_FILE'
X/*
X * uw_pcl.h -- defines protocol 1. taken from John D Bruner's source
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#define P1_IAC 0001 /* interpret as command */
X#define P1_DIR 0100 /* command direction: */
X#define P1_DIR_HTOM 0000 /* from host to Mac */
X#define P1_DIR_MTOH 0100 /* from Mac to host */
X#define P1_FN 0070 /* function code: */
X#define P1_FN_NEWW 0000 /* new window */
X#define P1_FN_KILLW 0010 /* kill (delete) window */
X#define P1_FN_ISELW 0020 /* select window for input */
X#define P1_FN_OSELW 0030 /* select window for output */
X#define P1_FN_META 0050 /* add meta to next data char */
X#define P1_FN_CTLCH 0060 /* low 3 bits specify char */
X#define P1_FN_MAINT 0070 /* maintenance functions */
X#define P1_WINDOW 0007 /* window number mask */
X#define P1_CC 0007 /* control character specifier: */
X#define P1_CC_IAC 1 /* IAC */
X#define P1_CC_XON 2 /* XON */
X#define P1_CC_XOFF 3 /* XOFF */
X#define P1_MF 0007 /* maintenance functions: */
X#define P1_MF_ENTRY 0 /* beginning execution */
X#define P1_MF_ASKPCL 2 /* request protocol negotiation */
X#define P1_MF_CANPCL 3 /* suggest protocol */
X#define P1_MF_SETPCL 4 /* set current protocol */
X#define P1_MF_EXIT 7 /* execution terminating */
X#define P1_NWINDOW 7 /* maximum number of windows */
X
X#define P1_DIR_STOC P1_DIR_HTOM
X#define P1_DIR_CTOS P1_DIR_MTOH
X
X#define P1_FORCE_SHUTDOWN 0200
END_OF_FILE
if test 1538 -ne `wc -c <'uw_pcl.h'`; then
echo shar: \"'uw_pcl.h'\" unpacked with wrong size!
fi
# end of 'uw_pcl.h'
fi
if test -f 'window.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'window.c'\"
else
echo shar: Extracting \"'window.c'\" \(1822 characters\)
sed "s/^X//" >'window.c' <<'END_OF_FILE'
X/*
X * window -- create windows
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include "uw.h"
X
X#include <stdio.h>
X#include <string.h>
X#include <sys/window.h>
X#include <fcntl.h>
X#include <termio.h>
X#include <sys/stat.h>
X#include <sys/sysmacros.h>
X
Xint
Xget_window(const char *win_name)
X{
X struct uwdata d;
X struct utdata t;
X int fd;
X
X /*
X * Create a new window.
X */
X fd = open(WINDOW_DEVICE, O_WRONLY, 0);
X if (fd < 0) {
X fprintf(stderr, "%s: can't open %s: ", cmd_name, WINDOW_DEVICE);
X perror("");
X return -1;
X }
X
X /*
X * Set the window to use the full screen
X */
X d.uw_x = 0;
X d.uw_y = WLINE(2);
X d.uw_width = WINWIDTH;
X d.uw_height = WINHEIGHT - d.uw_y;
X d.uw_uflags = NBORDER;
X if (ioctl(fd, WIOCSETD, &d) < 0) {
X fprintf(stderr, "%s: window ioctl failed: ", cmd_name);
X perror("");
X close(fd);
X return -1;
X }
X
X /*
X * Give the window a name. We don't care if it fails.
X */
X t.ut_num = WTXTUSER;
X strncpy(t.ut_text, win_name, WTXTLEN);
X t.ut_text[WTXTLEN-1] = '\0';
X (void)ioctl(fd, WIOCSETTEXT, &t);
X
X (void)ioctl(fd, WIOCSELECT, (char *)0);
X
X return fd;
X}
X
Xint
Xwindow_number(int fd)
X{
X struct stat buf1, buf2;
X int fstat(int, struct stat *), stat(const char *, struct stat *);
X
X if (fd < 0)
X return -1;
X
X if (stat(WINDOW_DEVICE, &buf1) < 0) {
X fprintf(stderr, "%s: can't stat %s: ", cmd_name, WINDOW_DEVICE);
X perror("");
X return -1;
X }
X
X if (fstat(fd, &buf2) < 0) {
X fprintf(stderr, "%s: can't stat fd %d: ", cmd_name, fd);
X perror("");
X return -1;
X }
X
X if (major(buf1.st_rdev) == major(buf2.st_rdev))
X return minor(buf2.st_rdev);
X else
X return -1;
X}
END_OF_FILE
if test 1822 -ne `wc -c <'window.c'`; then
echo shar: \"'window.c'\" unpacked with wrong size!
fi
# end of 'window.c'
fi
if test -f 'writer.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'writer.c'\"
else
echo shar: Extracting \"'writer.c'\" \(3729 characters\)
sed "s/^X//" >'writer.c' <<'END_OF_FILE'
X/*
X * writer -- take input from the host and send it to the windows.
X *
X * Copyright 1989 by W J Andrew Fyfe. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include "uw.h"
X#include <sys/window.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X#include <errno.h>
X#include <stdio.h>
X#include <signal.h>
X
X#define BUF_SIZE 120
X
Xstatic void check_input(void);
Xstatic void check_command(void);
X
Xstatic int window, sig_usr1;
X
Xstatic struct output_buffer {
X int count;
X unsigned char buf[BUF_SIZE];
X} out_buf[MAX_WINDOWS + 1];
X
Xstatic void
Xcatch_usr1(void)
X{
X signal(SIGUSR1, catch_usr1);
X ++sig_usr1;
X}
X
Xvoid
Xwriter(void)
X{
X int i;
X
X signal(SIGUSR1, catch_usr1);
X
X ++sig_usr1; /* we may have missed the first signal */
X
X window = -1;
X
X for (i=0; i<=MAX_WINDOWS; ++i)
X out_buf[i].count = 0;
X
X while (1) {
X if (sig_usr1)
X check_command();
X
X check_input();
X }
X}
X
Xstatic inline int
Xget_char(int fd)
X{
X static int count = 0, index = 0;
X static unsigned char buf[BUF_SIZE];
X
X if (count <= 0) {
X count = read(fd, buf, sizeof(buf));
X if (count <= 0)
X return -1;
X index = 0;
X }
X count--;
X return buf[index++];
X}
X
Xstatic void
Xcheck_input(void)
X{
X static int meta_flag = 0, escape = 0;
X int c;
X unsigned char ch;
X struct message msg;
X
X if (window < 0 && protocol != PROTOCOL_1)
X return;
X
X c = get_char(phone_fd);
X if (c < 0)
X return;
X
X if (escape) {
X escape = 0;
X if ((c & P1_DIR) != P1_DIR_STOC)
X return;
X switch (c & P1_FN) {
X case P1_FN_NEWW:
X case P1_FN_KILLW:
X case P1_FN_MAINT:
X send_controller(c);
X return;
X break;
X case P1_FN_OSELW:
X if (c & P1_WINDOW)
X window = c & P1_WINDOW;
X return;
X break;
X case P1_FN_META:
X meta_flag = META_BIT;
X return;
X break;
X case P1_FN_CTLCH:
X switch(c & P1_CC) {
X case P1_CC_IAC:
X c = IAC;
X break;
X case P1_CC_XON:
X c = XON;
X break;
X case P1_CC_XOFF:
X c = XOFF;
X break;
X }
X break;
X }
X }
X else if (c == P1_IAC) {
X escape = 1;
X return;
X }
X
X ch = c | meta_flag;
X meta_flag = 0;
X if (window >= 0)
X if (win_info[window].fd >= 0) {
X if (out_buf[window].count > 0) {
X write(win_info[window].fd, out_buf[window].buf,
X out_buf[window].count);
X out_buf[window].count = 0;
X }
X write(win_info[window].fd, &ch, 1);
X }
X else
X if (out_buf[window].count < sizeof(out_buf[window].buf))
X out_buf[window].buf[out_buf[window].count++] = ch;
X
X return;
X}
X
Xstatic void
Xcheck_command(void)
X{
X struct message msg;
X extern int errno;
X
X if (msgrcv(w_id, &msg, MSG_SIZE, MSG_TYPE, IPC_NOWAIT) < 0) {
X --sig_usr1;
X return;
X }
X
X switch (msg.text[COMMAND]) {
X case PROTOCOL_0_CMD:
X if (protocol == PROTOCOL_1)
X close_all_windows();
X protocol = PROTOCOL_0;
X if (open_window(0, msg.text[REAL_WINDOW], WRITE_ONLY) < 0)
X send_controller(P1_FORCE_SHUTDOWN);
X else {
X window = 0;
X out_buf[window].count = 0;
X }
X break;
X case PROTOCOL_1_CMD:
X if (protocol == PROTOCOL_0) {
X close_window(0);
X out_buf[0].count = 0;
X }
X if (protocol == PROTOCOL_1) {
X int i;
X close_all_windows();
X for (i=1; i<=MAX_WINDOWS; ++i)
X out_buf[i].count = 0;
X }
X protocol = PROTOCOL_1;
X window = -1;
X break;
X case CREATE_WINDOW_CMD:
X if (msg.text[REAL_WINDOW] > 0 &&
X open_window(msg.text[LOGICAL_WINDOW], msg.text[REAL_WINDOW],
X WRITE_ONLY) < 0)
X send_controller(P1_FN_KILLW | msg.text[LOGICAL_WINDOW]);
X break;
X case KILL_WINDOW_CMD:
X close_window(msg.text[LOGICAL_WINDOW]);
X out_buf[msg.text[LOGICAL_WINDOW]].count = 0;
X break;
X case DIE_CMD:
X close(phone_fd);
X exit(0);
X break;
X }
X}
END_OF_FILE
if test 3729 -ne `wc -c <'writer.c'`; then
echo shar: \"'writer.c'\" unpacked with wrong size!
fi
# end of 'writer.c'
fi
if test -f 'uw.uue' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'uw.uue'\"
else
echo shar: Extracting \"'uw.uue'\" \(12809 characters\)
sed "s/^X//" >'uw.uue' <<'END_OF_FILE'
Xbegin 755 uw
XM`5(`!"/WR2`````````````<`@\!"P`````>\````$````4$``@````(````
XM"0``+G1E>'0`````"`````@`````'O````0`````````````````````("YD
XM871A``````D````)``````!````D`````````````````````$`N8G-S````
XM```)`$``"0!````%!`````````````````````````"`+FQI8@``````"05$
XM``D%1```````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM`````````````````````````````````````````````"\\``D%1$ZY`#$`
XM`%B/($]1CRZ8+T@`!$J89@#__"](``@CR``P$`1.N0`($;0O`$ZY`#$`>#`\
XM``%.0$Y6__0O`D*Y``D`0$ZZ`;9(>@(\2'@``4ZY`#$!;E!/2KD`"0!`9@``
XM4$ZY``@%CDJ`9P``1$AX"`!(>``!2'@`"$AN__0O.0`)!-!.N0`Q`/S>_``4
XM2H!L```22'@``TZY`#$#ZEA/8`#_MA`N__E(@$H`;```%$*G0J=(>`!$3KD`
XM"!"^8``!"!`N__D"```X#```"&<``#AN```,2@!G```28`#_>@P``#AG``!F
XM8`#_;A`N__D"```'9P#_8DB`2,`O`$ZZ`;183V``_U(0+O_Y`@``!V<`_T9(
XM@$C`+P!"ITAX`$M.N0`($+X2+O_Y=`?"@B\!3KD`"`YH3KH!UM[\`!!*@&<`
XM_Q9.N@"V8`#_#A`N__D"```'9P``#@P```=G``!08`#^]G(!LKD`"0349@``
XM$$*G3KD`"`YH6$]@```4<@*RN0`)!-1F```(3KD`"`ZD0J="ITAX`#%.N0`(
XM$+YR`B/!``D$U-[\``Q@`/ZL<@*RN0`)!-1F`/Z at 3KD`"`ZD3KH`.F``_I(D
XM+O_P3EY.=55N:7@@5VEN9&]W<P`E<SH at 8V%N)W0@;W!E;B!B87-E('=I;F1O
XM=SH@````3E;_]$CG,`!R`2/!``D$U$AZ_\).N0`(%_PF`"\#3KD`"!DD)`!0
XM3VP``#PO.0`)!-A(>O^M2'D`,`"X3KD`,0.B2'K_NDZY`#$#BD*G0J=(>`!$
XM3KD`"!"^<@$CP0`)`$#>_``<(\,`"03@(\(`"03<0J<O`DAX`#!.N0`($+Y,
XM[@`,_^Q.7DYU3E8``'(!(\$`"0!`2'@``4AX``%.N0`Q`6Y.7DYU55<@+2T@
XM=VEN9&]W("5D`$Y6_Z1(YS``)BX`""\#2'K_X'2DU(XO`DZY`#$#J"\"3KD`
XM"!?\)``O`DZY``@9)$'Y``D$W"(#YX$A at A@$(8`8`"\#+P!(>`!#3KD`"!"^
XM3.X`#/^<3EY.=4Y6```O`G(!0?D`"03<(`'G@$JP"`1M```(0H!@```.4H%T
XM![2!;`#_YG`!)"[__$Y>3G5.<7IE<F\`:6YT97)R=7!T`&1I86QE<B!H=6YG
XM`&YO(&%N<W=E<@!I;&QE9V%L(&)A=60M<F%T90!A8W4@<')O8FQE;0!L:6YE
XM('!R;V)L96T`8V%N)W0@;W!E;B!,1$564P!D979I8V4@;F]T(&%V86EL86)L
XM90!D979I8V4@=6YK;F]W;@!N;R!D979I8V4 at 879A:6QA8FQE(&%T(&)A=60M
XM<F%T90!N;R!D979I8V4@:VYO=VX at 870@8F%U9"UR871E`"]D978O<&@Q`"5S
XM.B!#86XG="!O<&5N("5S.B```'!H,0`E<SH at 9&EA;"!F86EL960Z("5S"@!.
XM5O_.2.<P($*G0J=(>O^[3KD`,0$()@#>_``,;0``.'3.U(XO`DAX4`$O`T7Y
XM`#$`P$Z2'7P`!/_./7P``__2+P)(>%`"+P-.DB\#3KD`,0!"WOP`'$*G2'@`
XM!DAZ_VM.N0`Q`0 at F`-[\``QL```L2'K_5R\Y``D$V$AZ_U9(>0`P`+A.N0`Q
XM`Z)(>O]:3KD`,0.*</]@``"J=-;4CB\"2'A4`2\#3KD`,0#`+P-.N0`Q`$(]
XM?!0D_]9";O_8/7P$N?_:0F[_W!U\``'_XT(N_^0M0O_H+7P```2P_^PM?```
XM!+#_\"U\``@$*?_T+6X`"/_X0J[__"!.+R`O("\@+R`O("\@3KD`,0 at H)@#>
XM_``H;```+$2`0?D`"0``Y8`O,`@`+SD`"0382'K^OTAY`#``N$ZY`#$#HG#_
XM8```!"`#3.X$#/_"3EY.=4Y6__A(;O_X2'A0`2\Y``D%'$ZY`#$`P$J`;```
XM"'`!8```#C(N__H"04``0H`P`4Y>3G5.<2]U<W(O;&]C86PO8FEN+W5W`"5S
XM.B!F=&]K(&9A:6QE9"`H8V]N=')O;"DZ(```)7,Z(&US9V=E="!F86EL960@
XM*&-O;G1R;VPI.B``)7,Z(&9T;VL at 9F%I;&5D("AR96%D97(I.B``)7,Z(&US
XM9V=E="!F86EL960@*')E861E<BDZ(``E<SH at 9G1O:R!F86EL960@*'=R:71E
XM<BDZ(``E<SH@;7-G9V5T(&9A:6QE9"`H=W)I=&5R*3H@``!.5@``<O\CP0`)
XM!2!R_R/!``D%)'+_(\$`"0302'@`8TAZ_R!.N0`Q"'8CP``)!2A03VP``!`O
XM.0`)!-A(>O\68```S$AX!](O.0`)!2A.N0`Q`/`CP``)!-!03VP``!`O.0`)
XM!-A(>O\)8```HDAX`')(>O[.3KD`,0AV(\``"04L4$]L```0+SD`"0382'K^
XM_V```'I(>`?D+SD`"04L3KD`,0#P(\``"04D4$]L```0+SD`"0382'K^\&``
XM`%!(>`!W2'K^?$ZY`#$(=B/```D%,%!/;```$"\Y``D$V$AZ_N5@```H2'@'
XMY"\Y``D%,$ZY`#$`\"/```D%(%!/;```*"\Y``D$V$AZ_M9(>0`P`+A.N0`Q
XM`Z)(>OY43KD`,0.*</]@```$0H!.7DYU3E8``$JY``D$T&T``!9"IT*G+SD`
XM"0303KD`,0#JWOP`#$JY``D%)&T``!9"IT*G+SD`"04D3KD`,0#JWOP`#$JY
XM``D%(&T``!)"IT*G+SD`"04 at 3KD`,0#J3EY.=4Y6``!(>O_Z2'@`$$ZY`#$!
XM;E*Y``D`2$Y>3G5.5@``2'K_^DAX`!1.N0`Q`6Y.7DYU3E8``$CG("!(>O_$
XM2'@`$$7Y`#$!;DZ22'K_T$AX`!1.DE*Y``D`2'3_(\(`"0!,WOP`$$JY``D`
XM2&<```9.N@/&0J=(>%</0J=.N0`Q`,`B`-[\``QM``!*2KD`"0!,;0``'&T`
XM`#Q!^0`)!-P at .0`)`$SG at +*P"`!G```F+P%.N@`\6$]*@&P``!A*N0`)`$AF
XM```.2'@``TZY`#$#ZEA/2KD`"0!,;0#_BDZZ`*)@`/^"3.X$!/_X3EY.=4Y6
XM``!(YS@`)BX`"'@!N+D`"0349@``(D'Y``D$W+:09@``9$JH``1M``!<0KD`
XM"0!,0H!@``!2>`*XN0`)!-1F``!$=`%!^0`)!-Q"@2`"YX"VL`@`9@``)$JP
XM"`1M```<$`(````0$@`O`4ZZ!+XCP@`)`$Q"@&````Y2 at G@'N()L`/_*</],
XM[@`<__1.7DYU3E;__DCG,`!(>``!)`Y3 at B\"0?D`"03<(#D`"0!,YX`O,`@$
XM3KD`,0$LWOP`#$J`;P`">G8!MKD`"0349@``&$AX``$O`B\Y``D%'$ZY`#$!
XMVF```EAV`K:Y``D$U&8``DQ*N0`)`$1F```^0H`0+O__L+D`"04T9@``#G8!
XM(\,`"0!$8``")DJY``D%.&<``!A*+O__;```$'8!(\,`"0!$`BX`?___2KD`
XM"0!$9P``%F<``'Y"@!`N__^PN0`)!31F``!N2B[__VP```Q(>``H3KH#QEA/
XM`BX`?___#"X``?__9@``#DAX`#%.N at .L8``!M`PN`!'__V8```Y(>``R3KH#
XMEF```9X,+@`3__]F```.2'@`,TZZ`X!@``&(2'@``4AN__\O.0`)!1Q@``%P
XM0H`0+O__=L_0 at W8ZL(-B``%,XX`V.P`,3OLP!DK\`#P```#L`.P`[`#L`.P`
XM[`#L`3P!/`$\`3P!/`$\`3P!/`$\`3P!/`!X`3P!/`$\`3P!/`$\`3P`K@$\
XM`3P!/`$\`3P!/`$\`3P!/`$\`3P!/`$\`3P!/`$\`3P!/`$\`3P!/`$\`3P`
XM>`$\`3P!/`$\`3P!/`$\`*YT`4'Y``D$W"`"YX!*L`@$;0``#%*"=@>V at FP`
XM_^QV![:";0``N"\"3KD`"!",0H`0`F```(9*N0`)`$QO``">0?D`"03<(#D`
XM"0!,YX!*L`@$;0``B'8(AKD`"0!,+P-.N0`($(P2.0`)`$\``0`(8```1$*"
XM%"[__W;0U(-*@F\``%I!^0`)!-P@`N>`2K`(!&T``$A"ITAX5P4O,`@$3KD`
XM,0#`WOP`#$J`;0``+A("``$`$$*`$`$O`$ZZ`A)@```:'7P`!___2'@``4AN
XM__](>``!3KD`,0':0KD`"0!$3.X`#/_V3EY.=4Y6__0O`DAX"`!(>``!2'@`
XM"$AN__0O.0`)!21.N0`Q`/S>_``42H!L```,4[D`"0!(8``!IA`N__A(@#!`
XM<-#0B'0;L()B``&2XX`T.P`,3OL@!DK\`!T````Z`)8!@@&"`8(!@@&"`8(!
XM@@&"`8(!@@&"`8(!@@&"`8(!@@&"`,H!;@&"`8(!@@&"`8(!@@%&=`*TN0`)
XM!-1F```23KD`"`ZD2'@`/TZZ`3I83W0!(\(`"0342'@``1`N__E(@$C`+P!"
XMITZY``@.Y-[\``Q*@&P``!!(>`"`3KD`"!",8```^$*Y``D`3&```.YT`;2Y
XM``D$U&8```Q"ITZY``@.:%A/=`*TN0`)!-1F```(3KD`"`ZD=`(CP@`)!-1@
XM``":2B[_^6X``!`2.0`)`$\``0`(8```6DAX``$0+O_Y2(!(P"\`$"[_^DB`
XM2,`O`$ZY``@.Y-[\``Q*@&P``!H0+O_Z````"$B`2,`O`$ZY``@0C&```&00
XM+O_Z2(!(P"/```D`3!(Y``D`3P`!`!!"@!`!+P!.N@!,8```/A`N__I(@$C`
XM+P!.N0`(#FAT`K2Y``D`3&8``")T_R/"``D`3&```!8O.0`)!1Q.N0`Q`$)"
XMITZY`#$`>"0N__!.7DYU`0!.5@``+PI(>``!2'K_\B\Y``D%'$7Y`#$!VDZ2
XM`"X`0``+2'@``4AN``LO.0`)!1Q.DB1N__Q.7DYU3G%.5@``2.<@($7Y``D$
XMW"0N``CG at DJR*`1M```8+S(H!$ZY`#$`0G+_)8$H!'+_)8$H`$SN!`3_^$Y>
XM3G5.5@``+P)T`2\"3KK_N%A/4H)P!["";`#_\"0N__Q.7DYU+V1E=B]W)60`
XM)7,Z(&-A;B=T(&]P96X@)7,Z(```3E8``$CG.``D+@`()BX`#&\``(9!^0`)
XM!-P@`N>`>/^XL`@$9@``<B\#2'K_MDAY``D`4$ZY`#$#J$*G>`&XK@`09@``
XM"$*`8```!'`!+P!(>0`)`%!.N0`Q`0A!^0`)!-PB`N>!(8`8!-[\`!AL```N
XM2'D`"0!0+SD`"0382'K_:TAY`#``N$ZY`#$#HDAZ_V].N0`Q`XIP_V```"I!
XM^0`)!-P@`N>`+S`(!$ZZ`&1*@&T`_^1!^0`)!-P@`N>`(8,(`$*`3.X`'/_T
XM3EY.=25S.B!C86XG="!G970@=&5R;6EO(&9O<B!F9"`E9#H@`"5S.B!C86XG
XM="!S970@=&5R;6EO(&9O<B!F9"`E9#H@`$Y6_^XO`B0N``A(;O_N2'A4`2\"
XM3KD`,0#`WOP`#$J`;```$B\"+SD`"0382'K_D&```#X=?``!__M"+O_\0F[_
XM[D)N__!";O_T2&[_[DAX5`(O`DZY`#$`P-[\``Q*@&P``"HO`B\Y``D$V$AZ
XM_W%(>0`P`+A.N0`Q`Z)(>OYO3KD`,0.*</]@```$0H`D+O_J3EY.=4Y6__1R
XM`2U!__0=?`!3__@=;@`+__E(>`@`2'@`"$AN__0O.0`)!-!.N0`Q`/9.7DYU
XM3E;_]$CG("!R`2U!__0=;@`+__@=;@`/__D=;@`3__I(>`@`2'@`"'3TU(XO
XM`B\Y``D%)$7Y`#$`]DZ22'@(`$AX``@O`B\Y``D%($Z2WOP`($AX`!`O.0`)
XM!3Q%^0`Q`,9.DDAX`!`O.0`)!4!.DDSN!`3_[$Y>3G4E<SH at 8V%N)W0 at 9V5T
XM(&-U<G)E;G0@=VEN9&]W"@!$:6%L:6YG("5S`"P@=7-I;F<@;65T82!K97D`
XM+"!U<VEN9R!E<V-A<&4 at 8VAA<B`B`$T`7B5C`%X_`"5C`"(@*"=<)2XS;R<I
XM``H`)7,Z(&-A;B=T(&9O<FLZ(```3E8``$CG,#`F+@`()FX`#"/3``D$V$*G
XM2'A7#T*G3KD`,0#`WOP`#$J`;```(B\Y``D$V$AZ_TY(>0`P`+A.N0`Q`Z)(
XM>``!3KD`,0!X0KD`"04X<O\CP0`)!31T`;:";P``T"`"Y8`@<P@`#!``+68`
XM`,`0*``!2(`P0'"[T(AR*+"!8@``H..`,CL`#$[[$`9*_``J````A`"0`)``
XMD`"0`)``D`"0`&``D`"0`)``D`"0`)``D`"0`)``D`"0`)``D`"0`)``D`"0
XM`)``D`"0`)``D`"0`&H`D`"0`)``D`"0`)``D`!4<@$CP0`)!3A@```V0KD`
XM"04X8```+%*"(`+E@"\S"`!.N at 0L(\``"04T6$]@```2<O\CP0`)!31@```&
XM3KH"6%*"MH)N`/\T(`-3 at +""9P``!DZZ`D(@`^6`+S,(_$AZ_EA%^0`Q`YQ.
XMDE!/2KD`"04X9P``"DAZ_DM.DEA/2KD`"04T;0``>$AZ_DI%^0`Q`YQ.DEA/
XM2CD`"04W;```"DAZ_DA.DEA/='_$N0`)!31R'[*";0``$")"2&D`0$AZ_BQ@
XM```@<G^R at F8``!)(>OX at 3KD`,0.<6$]@```0+P)(>OX13KD`,0.<4$\O.0`)
XM!31(>OX"3KD`,0.<4$](>OX"3KD`,0.<2'H!NDAX``)%^0`Q`6Y.DDAZ`:I(
XM>``#3I)(>@&@2'@``4Z20H+>_``<0?D`"03<(`+G@'+_(8$(`'+_(8$(!%*"
XM<@>R at FP`_^AR_R/!``D$U$ZY``@&@DJ`;```!DZZ`5P@`^6`+S,(_$ZY``@$
XM0B/```D%'%A/;```!DZZ`3Y(>``!2'@``D7Y`#$!;DZ22'@``4AX``-.DDAX
XM``%(>``!3I)(>``!2'@`$$Z2WOP`($ZY`#$`BB/```D%/&P``"8O.0`)!-A(
XM>OTR2'D`,`"X3KD`,0.B2'K],TZY`#$#BDZZ`-A*N0`)!3QF```(3KD`"`A"
XM3KD`,0"*(\``"05`;```-B\Y``D$V$AZ_.Y(>0`P`+A.N0`Q`Z)(>OSO3KD`
XM,0.*2'@`"2\Y``D%/$ZY`#$`QDZZ`(1*N0`)!4!F```(3KD`"!G83KD`"``\
XM3KH`:DSN#`S_\$Y>3G4E<SH at 57-A9V4Z("5S(%LM;2!\("U-('P at +44@?"`M
XM92!E<V-=(#QT96QN;SX*``!.5@``+SD`"038+SD`"0382'K_ODAY`#``N$ZY
XM`#$#HDAX``%.N0`Q`'A.7DYU3E8``"\*2'K_^$AX``)%^0`Q`6Y.DDAZ_^A(
XM>``#3I)(>O_>2'@``4Z23KH`8$ZY``@'LD*G3KD`"`YH3KD`"`ZDWOP`'$JY
XM``D%'&T``!`O.0`)!1Q.N0`Q"#183T*G3KD`,0!X)&[__$Y>3G5.5@``3EY.
XM=25S.B!E<G)O<B!F<F]M('=A:70Z(`!.5@``2'K_W$AX``Y.N0`Q`6Y(>``*
XM3KD`,0`2WOP`#$JY``D%/&\``&Q*N0`)!4!O``!B0J=.N0`Q`=183TJ`;```
XM*B\Y``D$V$AZ_YY(>0`P`+A.N0`Q`Z)(>OMI3KD`,0.*WOP`$&```"JPN0`)
XM!3QF```*<O\CP0`)!3RPN0`)!4!F`/^:<O\CP0`)!4!@`/^.0J=.N0`Q`!)"
XMITAX``Y.N0`Q`6[>_``,2KD`"04\;P``%$AX``DO.0`)!3Q.N0`Q`,903TJY
XM``D%0&\``!)(>``)+SD`"05`3KD`,0#&3EY.=25S.B!I;G9A;&ED(&5S8V%P
XM92`E<PH``$Y6``!(YR`P)FX`""1++PM.N0`Q!"!"@5A/=`&T@&P``!0,$P!-
XM9@``#"(\````@%)*4X!T`;2`9@``'@P2`!]O``!N#!(`?FX``&80$DB`2,"`
XM at 6```'1T`K2`9@``4 at P2`%YF``!*#"H`/P`!;P``#`PJ`%\``6\``!8,*@!@
XM``%O```:#"H`>@`!;@``$!`J``%T'\""@(%@```N#"H`/P`!9@``"G!_@(%@
XM```<+PLO.0`)!-A(>O\N2'D`,`"X3KD`,0.B</],[@P$__1.7DYU+V1E=B]W
XM:6YD;W<`)7,Z(&-A;B=T(&]P96X@)7,Z(```)7,Z('=I;F1O=R!I;V-T;"!F
XM86EL960Z(```3E;_FDCG("!"ITAX``%(>O^T3KD`,0$()`#>_``,;```+$AZ
XM_Z`O.0`)!-A(>O^B2'D`,`"X3KD`,0.B2'K_IDZY`#$#BG#_8```J$)N_^X]
XM?``,__`]?`+0__(R/`$LDF[_\#U!__0]?``!__9(;O_N2'A7`B\"3KD`,0#`
XMWOP`#$J`;```,"\Y``D$V$AZ_U5(>0`P`+A.N0`Q`Z)(>O]$3KD`,0.*+P).
XMN0`Q`$)P_V```#X]?``#_YI(>`!1+RX`"$7N_YI(:@`"3KD`,00:0B[_["\*
XM2'A7""\"1?D`,0#`3I)"ITAX5P4O`DZ2(`),[@0$_Y).7DYU)7,Z(&-A;B=T
XM('-T870@)7,Z(``E<SH at 8V%N)W0@<W1A="!F9"`E9#H@``!.5O_$+P(D+@`(
XM;0``@$AN_^)(>OZ(3KD`,0%T4$]*@&P``!1(>OYV+SD`"0382'K_I&```$)(
XM;O_$+P).N0`Q`8!03TJ`;0``(C`N_^[@0#(N_]#@0;)`9@``,C`N_]`"@```
XM`/]@```F+P(O.0`)!-A(>O]T2'D`,`"X3KD`,0.B2'K^.$ZY`#$#BG#_)"[_
XMP$Y>3G5.<4Y6``!(>O_Z2'@`$$ZY`#$!;E*Y``D$R$Y>3G5.5@``2.<@($AZ
XM_]I(>``03KD`,0%N4KD`"03(<O\CP0`)!,Q"@E!/1?D`"0#H2'@`?"\"3KD`
XM,02D4$]"L@@`4H)R![*";`#_YDJY``D$R&<```9.N at +<3KH`$&``_^Q,[@0$
XM__A.7DYU3E;_\DCG(#A*N0`)!,QL```.=`*TN0`)!-1F``*B(#D`"04<1?D`
XM"0`P2I)N```J2'@`>$AY``D`<"\`3KD`,0$L)(#>_``,;@``"'+_8```)D*Y
XM``D`-%.Y``D`,$/Y``D`<$'Y``D`-"100H`0,I@`(@!2D$J!;0`"1$JY``D`
XM/&<``0A"N0`)`#P(`0`&9@`"+'`XP(%T.+""8@`!`N.`-#L`#$[[(`9*_``Z
XM````=`#R`/(`\@#R`/(`\@#R`'0`\@#R`/(`\@#R`/(`\@#R`/(`\@#R`/(`
XM\@#R`/(`@`#R`/(`\@#R`/(`\@#R`/(`\@#R`/(`\@#R`/(`\@"2`/(`\@#R
XM`/(`\@#R`/(`H`#R`/(`\@#R`/(`\@#R`'0O`4ZY``@0C&```9)P!\"!9P`!
XMBB/```D$S&```8`C_````(``"0`X8``!<G`'P(%T`K2`9P``*'0"M(!M```.
XM=`&T@&<``!)@```T=`.T@&<``!)@```H<@%@```B<A%@```<<A-@```6=`&T
XM at 68```YT`2/"``D`/&```2"".0`)`#L=0?_S0KD`"0`X2KD`"03,;0`!!B(Y
XM``D$S$GY``D$W"`!YX!*M`@$;0``E$?Y``D`Z$7Y`#$$I$AX`'PO`4Z24$]*
XMLP@`;P``4B`Y``D$S$AX`'PO`$Z24$\O,P@`2'@`?"\Y``D$S$Z24$](<P@$
XM(#D`"03,YX`O-`@$3KD`,0':(#D`"03,2'@`?"\`3I)03T*S"`#>_``,2'@`
XM`4AN__-!^0`)!-P at .0`)!,SG@"\P"`1.N0`Q`=I@``!<(#D`"03,2?D`"0#H
XM1_D`,02D2'@`?"\`3I-03W1WM+0(`&4``#8 at .0`)!,Q(>`!\+P!.DU!/)$`@
XM.0`)!,Q(>`!\+P!.DR!`0?2(`$7TJ`#5T!5N__,`!%*03.X<!/_B3EY.=4Y6
XM__1(YR`@2'@(`$AX``%(>``(2&[_]"\Y``D%($ZY`#$`_-[\`!1*@&P```Q3
XMN0`)!,A@``&F$"[_^$B`,$!PT-"(<ANP at 6(``9+C@#([``Q.^Q`&2OP`'0``
XM`#H`D`&"`8(!@@&"`8(!@@&"`8(!@@&"`8(!@@&"`8(!@@&"`8(`]@%N`8(!
XM@@&"`8(!@@&"`3QR`K*Y``D$U&8```A.N0`(#J1R`2/!``D$U$*G$"[_^4B`
XM2,`O`$*G3KD`"`[DWOP`#$J`;```$$AX`(!.N0`($(Q@``$$0KD`"03,0KD`
XM"0#H8```]'(!LKD`"0349@``$D*G3KD`"`YH0KD`"0#H6$]R`K*Y``D$U&8`
XM`"Q.N0`(#J1T`47Y``D`Z$AX`'PO`DZY`#$$I%!/0K((`%*"<@>R at FP`_^9R
XM`B/!``D$U'+_(\$`"03,8```CDHN__EO``"&0J<0+O_Y2(!(P"\`$"[_^DB`
XM2,`O`$ZY``@.Y-[\``Q*@&P``&`0+O_Z````"$B`2,`O`$ZY``@0C&```$@0
XM+O_Z2(!(P"\`3KD`"`YH$"[_^DB`1?D`"0#H2'@`?$C`+P!.N0`Q!*1"L@@`
XM8```%B\Y``D%'$ZY`#$`0D*G3KD`,0!X3.X$!/_L3EY.=0``````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM``````````````````````````````````````````````````@#2``(`TT`
XM"`-7``@#8P`(`VT`"`-_``@#BP`(`Y@`"`.I``@#O@`(`\T`"`/N````````
X*`````````````&T`
X`
Xend
END_OF_FILE
if test 12809 -ne `wc -c <'uw.uue'`; then
echo shar: \"'uw.uue'\" unpacked with wrong size!
fi
# end of 'uw.uue'
fi
echo shar: End of shell archive.
exit 0
More information about the Unix-pc.sources
mailing list