Xref: utzoo unix-pc.sources:344 comp.sys.att:6973 Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!usc!elroy.jpl.nasa.gov!cit-vax!andy From: andy@cit-vax.Caltech.Edu (Andy Fyfe) Newsgroups: unix-pc.sources,comp.sys.att Subject: a revised "uw" for the 3b1 Message-ID: <11272@cit-vax.Caltech.Edu> Date: 13 Jul 89 23:43:44 GMT Reply-To: andy@csvax.caltech.edu (Andy Fyfe) Organization: California Institute of Technology Lines: 2115 Here is the source to my uw client for the 3b1. Since the last posting of this, I've added the ability to transfer files using zmodem (or, I guess, the program of your choice). In the case the file transfers, the code tends to be more functional than general, but it serves my needs. Uw is written in ansi-C, and a (uuencoded, compressed) binary is enclosed for those without gcc. To run this you need the uw server written by John Bruner (jdb@mordor.s1.gov) (who also wrote a client side for the Macintosh). The sources for the server are not included here. They are archived in Mac-sorts of places, including sumex-aim.stanford.edu [info-mac/unix/uw-42-part?.shar] and simtel20.army.mil [PD2:UW42.TAR-Z]. (I reserve the right to have gotten those file names wrong! :-)) The server runs on Bsd-like machines. (Uw 4.2 is the current version of the server, I believe.) Andy Fyfe andy@csvax.caltech.edu wjafyfe@caltech.bitnet andy@cit-vax.UUCP (...!ames!elroy!cit-vax!andy) #! /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 '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 uses dial(3) to do the calling, and allows any Xdevice to be specified as the line. It must be in X/usr/lib/uucp/L-devices. I've used it both with the OBM and a direct X9600 baud line to a sun3. X XThe basic use of the program is "uw []". The phone Xnumber is required if the L-devices entry is "OBM" or "ACU", and must Xnot be specified if the L-devices entry is "DIR". Once you're logged Xin, run "uw" on the host. Any windows that the "uw" server creates Xwill be assumed to be "adm31" type windows ("uw" will set the TERM and XTERMCAP variables to such) and so it's necessary to override that since Xthe "uw" client does not do any terminal emulation (and thus windows Xare "s4"s). One way to do this is to set an environment variable when Xyou log in (say "ATT_3B1") and in your .cshrc (or .shrc or .kshrc) Xcheck to see if it's set and if it is, override "TERM" and "TERMCAP". XThis even works for commands like "uwtool rn", but only if typed at the Xkeyboard -- for some reason it doesn't if they appear in your .uwrc X(though commands in the .uwrc that just create shells work fine). 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 "). A default escape character can be compiled in (see Xconfig.h), 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 XIn it's windowless mode the keyboard commands are 'b' (or 'B') to send Xa break, and 'x' (or 'X') to terminate uw. If you're using /dev/ph?, Xthen uw will terminate automatically when the OBM hangs up. There is Xalso 'u' (or 'U') to upload a file, and 'd' (or 'D') to download a Xfile. At the moment these get translated to "sz -y upload" and "rz -p" X(and it's compiled in, along with the path to sz and rz). It might Xbe worthwhile to prompt for information, but I haven't found that to be Xthe case for me. To upload a file, just type escape or meta u. To Xdownload, first type "rz file.1 file.2 ..." and then escape or meta d. X XAn alternate line can be specified with '-l' and an alternate baud rate Xwith '-s'. X XThe defaults are set in "config.h". All save the file transfer stuff Xcan be overriden with command line options. 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 Xsome function defs). A uuencoded binary is included (it's stripped, Xand uses the shared library). The file is included -- it's Xnot necessary, as it just provides prototypes for most of libc, but Xit's handy 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@csvax.caltech.edu X wjafyfe@caltech.bitnet X andy@cit-vax.uucp (...ames!elroy!cit-vax!andy) END_OF_FILE if test 4790 -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'\" \(251 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' XCC = gcc XCFLAGS = -Wall -O XLDFLAGS = -shlib -s X XOBJS = controller.o dial.o msg_queues.o reader.o updnload.o utils.o \ X 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 updnload.o: config.h END_OF_FILE if test 251 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'config.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'config.h'\" else echo shar: Extracting \"'config.h'\" \(2386 characters\) sed "s/^X//" >'config.h' <<'END_OF_FILE' X/* X * any of the following defaults can be overriden by command line X * options. X*/ X X/* X * uw accepts commands from the keyboard via certain meta-keys. X * X * the commands can be entered in one of two ways. the first is X * to press the meta-key (left ctrl key -- this requires Michael X * "Ford" Ditto's nkbd driver) and the other is to prefix the X * character with an escape character. you can use one or the X * other, or both, or neither. if you use the escape char, you X * can send it to the host by typing it twice. X * X * there are 2 sets of available commands depending on the state X * of uw. there is the simple terminal emulator, and the windowed X * one. in the simple the commands are: X * meta-B -- send break X * meta-X -- terminate uw X * meta-U -- upload the file "upload" (from /usr/spool/uucppublic) X * meta-D -- download the file (into /usr/spool/uucppublic) X * in the windowed emulator, they are: X * meta-C -- create a new window X * meta-K -- kill the current window X * meta-1 -- select window 1, through X * meta-7 -- select window 7 (inclusively) X * X * the alphabetic commands can be entered in either upper or lower case X * X * choose one or the other (or both, or neither) to be the default X */ X X#undef DEFAULT_META /* use the meta key */ X#define DEFAULT_KBD_ESC "^A" /* escape char is cntl-A */ X X/* X * the default terminal line X * X * this will probably be either "/dev/ph1" or "/dev/tty0000" X * X */ X X#define DEFAULT_PHONE_LINE "/dev/ph1" X X/* X * the default baud rate X * X * this will probably always be 0. it must be a string. "0" takes X * the baud rate from L-devices. if there's more than one entry in X * L-devices, make it the most common one. X */ X X#define DEFAULT_BAUD_RATE "0" X X/* X * options for file transfer X * X * Uw will do a chdir to DEFAULT_DIR before exec'ing the upload or X * download program. Sz only sends a fixed file name (it's easier X * than asking for one, and I don't upload often enough to change it. X * The last arg must be a (char *)0. X */ X X#define DEFAULT_DIR "/usr/spool/uucppublic" X X#define UPLOAD_PROGRAM "/usr/local/bin/sz" X#define UPLOAD_ARG_0 "sz" X#define UPLOAD_ARG_1 "-y" X#define UPLOAD_ARG_2 "upload" X#define UPLOAD_ARG_3 (char *)0 X X#define DOWNLOAD_PROGRAM "/usr/local/bin/rz" X#define DOWNLOAD_ARG_0 "rz" X#define DOWNLOAD_ARG_1 "-p" X#define DOWNLOAD_ARG_2 (char *)0 X#define DOWNLOAD_ARG_3 (char *)0 END_OF_FILE if test 2386 -ne `wc -c <'config.h'`; then echo shar: \"'config.h'\" unpacked with wrong size! fi # end of 'config.h' 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'\" \(3037 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 X#include X#include X#include X Xstatic void startup_0(void); Xstatic void new_window(int logical_window); Xstatic int all_windows_gone(void); Xstatic int stop = 0; X Xstatic void catch(void); X Xvoid Xcontroller(void) X{ X struct message msg; 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_INTERNAL) { X switch(msg.text[SERVER_BYTE]) { X case P1_INT_DIE: X send_rd_wr(DIE_CMD, 0, 0); X return; X case P1_INT_UPLOAD: X send_rd_wr(PAUSE_CMD, 0, 0); X upload(); X send_rd_wr(CONT_CMD, 0, 0); X break; X case P1_INT_DOWNLOAD: X send_rd_wr(PAUSE_CMD, 0, 0); X download(); X send_rd_wr(CONT_CMD, 0, 0); X break; X } X } X else { 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 } X return; X} X Xstatic void Xstartup_0(void) X{ X int window, fd; 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 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 3037 -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'\" \(2971 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 X#include X#include X#include X Xstatic const char * const 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); Xvoid undial(int); Xstatic int translate_baud(const char *speed); Xstatic int is_phone = 0; X Xint Xdial_number(const char *line, const char *speed, const char *number) X{ X CALL call; X struct termio term; X struct updata phone; X int fd; X int baud; X X fd = open(line, O_RDWR | O_NDELAY, 0); X if (fd < 0) { X fprintf(stderr, "%s: Can't open %s: ", cmd_name, line); X perror(""); X return -1; X } X if (strncmp(line, PHDEV, sizeof(PHDEV)-1) == 0) { X is_phone = 1; X if (ioctl(fd, PIOCGETP, &phone) >= 0) { X phone.c_lineparam &= ~PULSE; X phone.c_lineparam |= DTMF; X phone.c_feedback &= ~(SOFTSPK | NORMSPK | LOUDSPK); X phone.c_feedback |= (SPEAKERON | SOFTSPK); X ioctl(fd, PIOCSETP, &phone); X } X } X ioctl(fd, TCGETA, &term); X close(fd); X X baud = translate_baud(speed); X if (baud < 0) { X fprintf(stderr, "%s: illegal speed: \"%s\"\n", cmd_name, speed); X return -1; X } X X term.c_iflag = IXOFF | IXON | ISTRIP | IGNPAR; X term.c_oflag = 0; X term.c_cflag = HUPCL | CREAD | CS8 | baud; X term.c_lflag = 0; X term.c_cc[VMIN] = 1; X term.c_cc[VTIME] = 0; X call.attr = &term; X call.baud = call.speed = atoi(speed); X call.line = strrchr(line, '/') + 1; X call.telno = (char *)number; X call.modem = 0; X 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 Xvoid Xundial_number(const char *line) X{ X if (phone_fd >= 0) { X if (is_phone) X ioctl(phone_fd, PIOCDISC, (char *)0); X undial(phone_fd); X close(phone_fd); X } X X} X Xstatic const struct trans { X char *speed; X int baud; X} trans[] = { X {"0", 0}, X {"50", B50}, X {"75", B75}, X {"110", B110}, X {"134", B134}, X {"150", B150}, X {"200", B200}, X {"300", B300}, X {"600", B600}, X {"1200", B1200}, X {"1800", B1800}, X {"2400", B2400}, X {"4800", B4800}, X {"9600", B9600}, X {"19200", B19200}, X}; X Xstatic int Xtranslate_baud(const char *speed) X{ X int i; X X for (i=0; i < sizeof(trans)/sizeof(struct trans); ++i) { X if (strcmp(speed, trans[i].speed) == 0) X return trans[i].baud; X } X return -1; X} X Xint Xmodem_connected(void) X{ X struct updata d; X X if (!is_phone || ioctl(phone_fd, PIOCGETP, &d) < 0) X return 1; X X return d.c_linestatus & MODEMCONNECTED; X} END_OF_FILE if test 2971 -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 X#include X#include 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'\" \(5317 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 X#include X#include X#include X#include X#include 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 = -1, sig_usr1 = 1; 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 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 = 0; X unsigned char c; X X if (read(win_info[window].fd, &c, 1) <= 0) X return; X 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 (protocol == PROTOCOL_0) { X if (!keyboard_escape || (keyboard_escape && c == kbd_esc_char)) { X write(phone_fd, &c, 1); X } X else { X switch(c) { X case 'b': X case 'B': X ioctl(phone_fd, TCSBRK, (char *)0); X break; X#if 0 X case 's': X case 'S': X send_controller(P1_INT_STARTUP); X break; X#endif X case 'u': X case 'U': X send_controller(P1_INT_UPLOAD); X break; X case 'd': X case 'D': X send_controller(P1_INT_DOWNLOAD); X break; X case 'x': X case 'X': X send_controller(P1_INT_DIE); X break; X default: X c = '\a'; X write(1, &c, 1); X break; X } X } X } X if (protocol == PROTOCOL_1) { 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 } X switch(c) { X case IAC: X send_to_server(P1_FN_CTLCH | P1_CC_IAC); X break; X case XON: X send_to_server(P1_FN_CTLCH | P1_CC_XON); X break; X case XOFF: X send_to_server(P1_FN_CTLCH | P1_CC_XOFF); X break; X default: X write(phone_fd, &c, 1); X break; X } X } X else { X switch(c) { X#if 0 X case 's': X case 'S': X send_controller(P1_INT_SHUTDOWN); X break; X#endif X case 'C': X case 'c': X for (i=1; i<=MAX_WINDOWS; ++i) { X if (win_info[i].fd < 0) { X send_controller(P1_FN_NEWW | i); X send_to_server(P1_FN_NEWW | i); X break; X } 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 (win_info[i].fd >= 0) X ioctl(win_info[i].fd, WIOCSELECT, (char *)0); X break; X default: X c = '\a'; X write(1, &c, 1); X break; X } X } X } X keyboard_escape = 0; X return; X} X Xstatic void Xcheck_command(void) X{ X struct message msg; X X if (msgrcv(r_id, &msg, MSG_SIZE, MSG_TYPE, IPC_NOWAIT) < 0) X return; X X --sig_usr1; 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_INT_DIE); 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 case PAUSE_CMD: X while (sig_usr1 == 0) X pause(); X break; X case CONT_CMD: 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 5317 -ne `wc -c <'reader.c'`; then echo shar: \"'reader.c'\" unpacked with wrong size! fi # end of 'reader.c' fi if test -f 'updnload.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'updnload.c'\" else echo shar: Extracting \"'updnload.c'\" \(2631 characters\) sed "s/^X//" >'updnload.c' <<'END_OF_FILE' X/* X * updnload -- do file trasfer between 3b1 and 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 "config.h" X X#include X#include X#include X#include X#include X Xstatic void Xupdnload(const char *path, ...) X{ X va_list args; X struct termio t; X int pid, ret; X union wait status; X X if (ioctl(phone_fd, TCGETA, &t) < 0) { X fprintf(stderr, "%s: can't get termio for phone fd %d: ", X cmd_name, phone_fd); X perror(""); X return; X } X X pid = fork(); X if (pid < 0) { X va_start(args, path); X fprintf(stderr, "%s: can't fork \"%s\"\n", X cmd_name, *(const char **)args); X perror(""); X va_end(args); X } X else if (pid == 0) { /* child */ X setpgrp(); X chdir(DEFAULT_DIR); X close(0); X close(1); X if (fcntl(phone_fd, F_DUPFD, 0) < 0) { X fprintf(stderr, "%s: can't dup phone fd %d to 0\n", X cmd_name, phone_fd); X perror(""); X exit(1); X } X if (fcntl(phone_fd, F_DUPFD, 1) < 0) { X fprintf(stderr, "%s: can't dup phone fd %d to 1\n", X cmd_name, phone_fd); X perror(""); X exit(1); X } X setgid(getgid()); X setuid(getuid()); X va_start(args, path); X execv(path, (const char **)args); X fprintf(stderr, "%s: can't exec \"%s\": ", cmd_name, path); X perror(""); X va_end(args); X exit(1); X } X else { /* parent */ X va_start(args, path); X while (1) { X ret = wait(&status); X if (ret < 0) { X fprintf(stderr, "\n%s: %s: wait failed: ", X cmd_name, *(const char **)args); X perror(""); X } X else if (ret != pid) { X fprintf(stderr, X "\n%s: %s: " X "wait returned status [%.8x] for unknown pid %d\n", X cmd_name, *(const char **)args, status.w_status, ret); X } X else X break; X } X if (status.w_termsig == 0) { X if (status.w_retcode != 0) X fprintf(stderr, "%s: %s: exit status %d\n", X cmd_name, *(const char **)args, status.w_retcode); X else X fprintf(stderr, "%s: up/down load complete\n", cmd_name); X } X else X fprintf(stderr, "%s: %s: killed signal %d\n", X cmd_name, *(const char **)args, status.w_termsig); X va_end(args); X } X X if (ioctl(phone_fd, TCSETA, &t) < 0) { X fprintf(stderr, "%s: can't set termio for phone fd %d: ", X cmd_name, phone_fd); X perror(""); X } X} X Xvoid Xupload(void) X{ X updnload(UPLOAD_PROGRAM, X UPLOAD_ARG_0, UPLOAD_ARG_1, UPLOAD_ARG_2, UPLOAD_ARG_3); X} X Xvoid Xdownload(void) X{ X updnload(DOWNLOAD_PROGRAM, X DOWNLOAD_ARG_0, DOWNLOAD_ARG_1, DOWNLOAD_ARG_2, DOWNLOAD_ARG_3); X} END_OF_FILE if test 2631 -ne `wc -c <'updnload.c'`; then echo shar: \"'updnload.c'\" unpacked with wrong size! fi # end of 'updnload.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'\" \(2476 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 X#include X#include X#include X#include X#include 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 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 static int first = 1; 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 if (first) /* no signals on the first message */ X first = 0; X else { X kill(pid_rd, SIGUSR1); X kill(pid_wr, SIGUSR1); X } X} END_OF_FILE if test 2476 -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'\" \(4441 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#include "config.h" X X#include X#include X#include X#include X Xchar *cmd_name; X Xstatic volatile void usage(void); Xstatic volatile void terminate(void); Xstatic void reap(void); X Xint phone_fd; Xstatic char *phone_line = DEFAULT_PHONE_LINE; Xstruct window_info win_info[MAX_WINDOWS + 1]; Xint protocol = PROTOCOL_NONE; Xint pid_rd, pid_wr; Xint use_meta, kbd_esc_char; X Xstatic int conv_esc(const char *); X Xextern char *optarg; Xextern int optind; X Xvoid Xmain(int argc, char *argv[]) X{ X int i; X char *baud_rate = DEFAULT_BAUD_RATE; X char *phone_number = 0; 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 if (init_window() < 0) X exit(1); 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 while((i = getopt(argc, argv, "mMe:El:s:")) != EOF) { X switch (i) { 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(optarg); X break; X case 'E': X kbd_esc_char = -1; X break; X case 'l': X phone_line = optarg; X break; X case 's': X baud_rate = optarg; X break; X case '?': X usage(); X break; X } X } X if (optind == argc - 1) X phone_number = argv[optind]; X else if (optind < argc) X usage(); X X printf("uw: connecting"); X if (phone_number) X printf(", dialing %s", phone_number); 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 phone_fd = dial_number(phone_line, baud_rate, phone_number); X X if (phone_fd < 0) X 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 X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGHUP, SIG_IGN); X signal(SIGUSR1, SIG_IGN); X X if (create_message_queues() < 0) X terminate(); 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]" X " [-l ] [-s ] []\n", X cmd_name, cmd_name); X exit(1); X} X Xstatic volatile void Xterminate(void) X{ X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGHUP, SIG_IGN); X X reap(); X X delete_message_queues(); X X close_window(0); X close_all_windows(); X X undial_number(phone_line); 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 4441 -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'\" \(2247 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 X#include X#include "uw_pcl.h" 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_NONE -1 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#define PAUSE_CMD 'P' X#define CONT_CMD 'R' 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 unsigned 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 *line, const char *speed, const char *number); Xvoid undial_number(const char *line); Xint modem_connected(void); X Xint create_message_queues(void); Xvoid delete_message_queues(void); X Xint init_window(void); 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 Xvoid upload(void); Xvoid download(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 2247 -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'\" \(1669 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_INTERNAL 0200 X#define P1_INT_DIE 0201 X#define P1_INT_SHUTDOWN 0202 X#define P1_INT_STARTUP 0203 X#define P1_INT_UPLOAD 0204 X#define P1_INT_DOWNLOAD 0205 END_OF_FILE if test 1669 -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'\" \(1961 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 X#include X#include X#include X#include X#include X#include X Xstatic int window_major_number; X Xint Xinit_window(void) X{ X struct stat buf; X int stat(const char *, struct stat *); X X if (stat(WINDOW_DEVICE, &buf) < 0) { X fprintf(stderr, "%s: can't stat %s: ", cmd_name, WINDOW_DEVICE); X perror(""); X return -1; X } X X window_major_number = major(buf.st_rdev); X return 0; X} 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 buf; X int fstat(int, struct stat *); X X if (fd < 0) X return -1; X X if (fstat(fd, &buf) < 0) { X fprintf(stderr, "%s: can't stat fd %d: ", cmd_name, fd); X perror(""); X return -1; X } X X if (major(buf.st_rdev) == window_major_number) X return minor(buf.st_rdev); X else X return -1; X} END_OF_FILE if test 1961 -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'\" \(3888 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 X#include X#include X#include X#include X X#define BUF_SIZE 256 X Xstatic void check_input(void); Xstatic void check_command(void); X Xstatic int window = 0, sig_usr1 = 1; 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 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 void Xflush_output(int window) X{ X if (win_info[window].fd >= 0 && out_buf[window].count > 0) { X write(win_info[window].fd, out_buf[window].buf, out_buf[window].count); X out_buf[window].count = 0; X } X} X Xstatic void Xcheck_input(void) X{ X static int escape = 0; X static unsigned char meta_flag = 0; X int count, i, j; X unsigned char c; X unsigned char buf[BUF_SIZE]; X X if (protocol == PROTOCOL_NONE) X return; X X count = read(phone_fd, buf, sizeof(buf)); X X for (i=0; i < count; ++i) { X c = buf[i]; X X if (escape) { X escape = 0; X if ((c & P1_DIR) != P1_DIR_STOC) X continue; X switch (c & P1_FN) { X case P1_FN_NEWW: X send_controller(c); X continue; X case P1_FN_KILLW: X send_controller(c); X flush_output(c & P1_WINDOW); X close_window(c & P1_WINDOW); X continue; X case P1_FN_MAINT: X send_controller(c); X for (j=0; j <= MAX_WINDOWS; ++j) X flush_output(j); X switch(c & P1_MF) { X case P1_MF_EXIT: X if (protocol == PROTOCOL_1) X close_all_windows(); X protocol = PROTOCOL_0; X window = 0; X break; X case P1_MF_ENTRY: 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 } X continue; X case P1_FN_OSELW: X if (c & P1_WINDOW) X window = c & P1_WINDOW; X continue; X case P1_FN_META: X meta_flag = META_BIT; X continue; 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 continue; X } X X if (window >= 0 && out_buf[window].count < sizeof(out_buf[window].buf)) X out_buf[window].buf[out_buf[window].count++] = c | meta_flag; X meta_flag = 0; X } X X for (i=0; i <= MAX_WINDOWS; ++i) X flush_output(i); X X return; X} X Xstatic void Xcheck_command(void) X{ X struct message msg; X X if (msgrcv(w_id, &msg, MSG_SIZE, MSG_TYPE, IPC_NOWAIT) < 0) X return; X X --sig_usr1; X X switch (msg.text[COMMAND]) { X case PROTOCOL_0_CMD: X if (protocol == PROTOCOL_1) X close_all_windows(); X if (open_window(0, msg.text[REAL_WINDOW], WRITE_ONLY) < 0) X send_controller(P1_INT_DIE); X else { X if (protocol == PROTOCOL_1) X window = 0; X protocol = PROTOCOL_0; X flush_output(0); X } X break; X case PROTOCOL_1_CMD: 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 else X flush_output(msg.text[LOGICAL_WINDOW]); X break; X case KILL_WINDOW_CMD: X flush_output(msg.text[LOGICAL_WINDOW]); X close_window(msg.text[LOGICAL_WINDOW]); X break; X case DIE_CMD: X close(phone_fd); X exit(0); X break; X case PAUSE_CMD: X while (sig_usr1 == 0) X pause(); X break; X case CONT_CMD: X break; X } X} END_OF_FILE if test 3888 -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'\" \(9219 characters\) sed "s/^X//" >'uw.uue' <<'END_OF_FILE' Xbegin 755 uw.Z XM'YV0`:0`($#B5H-4`!(J5,A!P(,`"Q:B`*,01D($E``@4+@Q88*$+NB4P4-G XM84>-$BD.7,BR)0`0+LB$H1-FX4>/+"T"T.G2)1`78N;,8?G18M&+&7LJ!0#( XM!9LT8H@B(`8@P=2E6+-JWO8,.*'4NVK-FS:-.J7HD%X`8";$\`O$DRB,7F%X@&:@$DQD`__@IUC@"V4X(!/IJS*#M XM!0#-@/'`T!O`"1`G5O[10W(.!@@GN@3P0*)'@#`D>`"4]ALC@!LH3P0(4OA/ XMB=^;CP'HT8S@@#DE@,XD=(-[(V[=UQ$@<:/Z18Z]5$`#X.>-'P`*T-DDE'!] XM`.@!ZK`\H?C/EA(7__*I!T"(`OY\#`R7$"'2`4"#&PE!$*!"@11(`7V.+)A0 XM(07*0!\@0IR2X75$,(`!C0QP($_PF0D(^!2`"`'0C8TF!"/$`I91L),:#$ XME`!(0)\!=N`@98%J4.2//A(D&0``!TCGCSM"``)!`)[!%@`P\IGI39KY";!F XMFP#X(TV<$@*G_GXR2:A='ZVHP7AZ1*`-T-"`)V;GL`&@"]F6H)D XMGPD=($23`&Q9H`-V'#!F0E"8B8<=`=AR'``<)`=!ABY2D6="%-@A@*U5X9H< XM`BY"\F-N,2@J[`C#%,O!D`R8Z8*PQ'Z4:Z`B).LI#V92P(0[!##P#SI.>.%$ XM'56XD08>(%R1AAMDO'''4"7,H0,(8X3AQ@ET@/`&'&6X`8(88''&Q0(P)`?0[@7&",+L->(I+PAP'0R*C@N` XMN?BDN^[$``RM\4W7!1`V:+YIS>X5(+30`L,.VPM""61\EAHL%0-@@@L:DP,-@A#&E@0QC^U\`'1G!AV5L#]^Z`(.Z!P($0E*#W XM+IC!#5;/>P%#F/K8YSX`F!"%'P2!".UEL)F@;X;M$PE'!F`9!`R@&1H9P#62 XM.(XDMB.)_]`(`2("N\S!+@52]($4FR!%-^1K7T/P%\`$1C"#?1$$"7D!"E\` XM!S0`X(P9+-_YYD"P,I!A7R+(EP@4\$9]G7!Z;`"!&3!8O3N^;0Y\E-L_G,$: XM'H``!7A#@`KPQH!#&>`%F>%-`!"0,FKM1P68=)E58*:'?PAB9C6[&6\&D+-2 XM&H)GQ$C"&A!Q#[D8`^18D`4OHC'2I11`_X0`$2P%,( XMW,$&`(!``%CT``C_T`9$_\&-#O!!-_\8AQ#P0PXY6$,:CFA!$,ZE3UU:H048 XMA0=,_\&.Z[P@E[PA``ND`(B9TJ,%"(+`/_`A!%=$YC4O`$%2EZK4IH(&`2CH XMI'E(\$DB`"((^O`'",H!B!?`8",$-:@=4&D15?Z%E;%4"0%`((!Q$8`'_]B9 XMNNK`->/LA1.RTX%=/T*``LF(1NF\Y'>LPHEZ4HN@A>4-`FB`6/$(P6P6J8%% XM;E"#O\3`(C&8`0W^(ED`R``&%ID!:`%@@]'&X+.8Q<%H94"#T=)`M1;)06DQ XMFP/4$!"8`+63@B#DX`!9 XM"")N_\!&+-W*@7_`@W2IP<=>!U(@#KP3'\FDTV`1D%AG`B,]%P%>[62`'WT( XM(`A``$"<8%":N;Z@#G.0PPO8\(9^L>$%8IC7C^_0QWV9@0YO6(,@"6G'1X[A XM#6Z@`_+8D(*(-1D$;9C#&70R4H\#9! XM82'N>",`%,5&P;GC2;.RXNS9X5FE(M*:$`+$"<0)V2NJ96>!&1$TX!`-G<((5;,:#E+[\.!6;> XM\A^,&%G%,&CJ/IK%'S(`"&0`V!!!&B:[P`%X!&Q@B,)HT9:>$ XM$2-`=AR0'0]0US@0#%8CK)/%ZP!0(!.\H#2Z`(`.Y`-C(C$].0YHSWOB\P2O XM8^D?BO`4B"`C"!)PAWASI>\Y"GPWC>`A`+BXU;8`(`*R(X`+MH!$6[$QIU_P-[L XMQV>=5V%'-A;T$A#)&X`=1@R!Y/B`4/CY!RPX3@N\/WX$5/D(!"@R`"A('!=^ XM=1__\`_[`0'WEW_&=DT`\`<#^'BJIRV/$0#H<2L04"`64"`D`'\#.'][47_` XM$C;O]`^(I1(:)2?QAP>^``V$@`(1&F(1(N(1):`A):`E*&(5,"(1"2(1,>(52F(5" XMZ(1(:`DE0@4%T%A7IQ(Z(@>_`@`>X%%L,H`@V'UC XMHTG:0"VH]X#&`@!*PGX66"".H('R1W_)X0<"2(#K<1TH`!L#0`T*R(#_(!^& XMB`<1@`O1`1*8J(FRXP`.N(E=HA(R@`<3H(D%X@$J80+7T2RZ,`"6$"*0V(W@^(WBR`(`\'CA>([?"`"T,([LB([NV([P XM"([E&(_I2`NN!WL",`BT!V"M\SH$L!\6@#@X(@ESP`@`C?=W8(P#J[%SL)(0=X@`"(,'HXI2)R(`%G%Q&_!2EU$ANQ XM$G'YY1\-"`W40`C?QX\;*3LN,'5A^%4'!AC`H!(:0(<'8(?;%X)Y^!'/[``+3"``I0S$`(`H!8`E[V9=\^9=^&9B`.9A^"0#6 XM$``70YB$R02"V9>,X)=T(`"T('G)(0')1')$IF>B2L1*8#YH"LF XM62PHJ1$JD6K;%YJ&4HSZ4">38IHD!U`)H0%\(ETI*2>1HIH_J('Z$&\:,9P? XM49R[@ITK"0!:H!),P)W.69M4$)FQ^1$(D!PR0`>>UC3PN8IBZ$Q"0)NA0383 XM6"Q-!QGR(#P>9C9K4CH_5Y2E)`^(-71)R2+;-%$`L`!W.*&-)0F&%QEFQJ%B9&8F*F5Y-`=[-#)`)F1T XM]`9O<&1U4`=C``=P4`?W$T%?UJ$!0P;/@Z(J*D@M6F=0!@(PP$D9K$$=5-@=I<`9N<#YP XMLZEBJC`!$Z(CFJ@GFJ7[XZ10!$" XMP`7BH0@I\TDO0$GGA@9D93,'IP?^<`4\$R+VH`2"$($[ITE$\&Q3(!XJD"%# XMIV-&MWTLDG*$)1Z$,"084'<:W_H`XOT+0O0[!T$+5G XM5;/F4220(0I\H@[BD`"0PF`3)8#K4"`:H('KT+5B.TH$&P[;4 XMHA(JT+9OJY(CL[<%1;!J,+@"B[;G4:SRM$X,JZQ74W<"-[%.:P20.[!ZP`\7 XMP#-N92[>8#;/$ZIQTP(T,P=Z@*-!-F1%1CU(IF2NFQ!P#'=P#'<`!O\``XX XM=PX@``+-U#C"@W:"H`2R@`(<220#IKZ.U6DE$`CJ"[_R"P!NU4U9DWA6D$8" XMX'J!HPO_@`OR(6%P<`!KV3OP0*"(MRYJ]$`O<`=P56,NTJHD"%Z$`"ZX`K&=BRE XM-Q#`XQET``Y_?VTK_0%<*QW``H`+?1\+C XMEQEQ1P;0\7?D4,6L$P*$L!%Q8C5P!0T;&J83_*&X2J**NJ4N^F9H;*6V"J+' XM(Z)L?*)N;$B*Y`Y14[Y6^0_&B@?S=$_/=)KK$37(]@^0H!(^0("L55*\4.!P@$:K3ZJQH7 XMHU*J08=3,%0=@"`+D!]2F1WOA)7@(1[V\)2L$;ZQO%+T<,L3:LL(\@#Y@4`)C``!>\`-O%-0B XM\$@GP`6$.@-O<`)81*L37*)RL`9>-KTN=PZ.U'B76&3'F)?`)-C+#E^#%24'<,`-=X('I[@0L<\P`J00IP$`S0$`AZ XM0`.P4`@P"`TSJ`-QB8-04)W=F@ XM_=F>/1RA7=FD``#J4=H`(`LS/`+%D-)"YZ*TPX'-F&P,"8`U91RTF XM'`B/\0\,,,)3``@&QB@[._=E:<`!P$10L$FPD+#AQ!ON"(3`"B1"3,40`(X&^J[]IE*!S XMCN9(671RSN;EM.9CTR)QAW$(H``HE];LF2Q)C@',80!/3L[\68X9NL!TM;^? XM,5>4VCQMC#R]7J=T$#'T54K<8.C[X`$\DRF&RX%6T>CB96KP3/,(8.J0H0DX;Q4_"1F%J.^` XMD>\6/W,>7_,420'7X>DK!NK`9@P$OA?`0)'LD1M.3_6A/NL@,"\7]!1UANPW XMO3#YDDB*)Z4F@""P`!.\@$4Z0:&#P!^@"``8`80P!Z`@`3```B!H!)TX)Z#GQ!2L/A> XMD!Q*P``J``!$'0`4R0"B#P!?H!L4:0&I'R(4J0&I_[J^D2`0,/H!0`^GQ`'5-6H XM\0_B\$[=7TK40#9TL&!*RP(<(PR)3`R&_@_(`$O;UB4P@!_N``Y`0/G>"0,/ XMI_!Q/$8%9$9^]&74SVV,J(\62!2-'9%XJ4$3##.X!UBP0RE!`F2#DVB=J[$? XMS%\I82PK;]R1LH`%NOZ!#G!_*B&&:;*%$CK@P4(1`-#@'\@#&<`#N)$DL&0] XMP)B1P$=F#R@7'K@"G>R3U9WJMO*L@*'S!]B`9Q`R(2#%?``)-"<*,#=$@9?U XML_Z!`E0#@$B7W"W\P`Y\#FZX`C"+W?FD>058KD`8\F22@*WDLQ:A__9%K<)^ XM>0Q8<;\^%DED!\S@#N(`B`$"\B<[1$#\`V3T#P8`@5C`.':"?+J#[D````+B XM@)^P6>,J)9S@!R*+*/8/"-3I2CQQ8.)!LY@S`H'0!]0QO"P/E?-!^`` XM/O`/>('DD0X#0`C@AC7Q3D;&Y=(D+&#T"8&'=35T`2%('B@P"80P+G`$^B`- XM"`(U$`!8`!00148,"I`.`@`+S+:E940`@`%X#`*`$T"``;!=F(23X`,X0!88 XM@JC05E3'#.(!BVT?@(&ZI`,40F32`0(`(`K$@$@0^Z$A*(@(<2`JQ(28$"$/ XM0UR($/$A!L0```TDHD(,`-S`(A9$```GY,3FD!0DZ5<$`'I`*#[B&UJ'V\54 XMH`KY0`)6Q_FB!>H+)XE"4A@(UAL00%^X``!0I.0G`W(B$I`#N`#)T0#WI8>$ XM@"S(B=1"`K##/Z&X>H5(9`0E<3T-I/PB'T0`@`D$2H`65`Z9*`!&X5FRB3A1 XM)R*_`>,3@:)0K!QD0Z,@`/C``^*(%^GT6@#2LHN0(`")`<6.. XM$T`EN+[C$@#PSF$4C1]A(B2$FW@KP$Q"@`$BX.R$KP#@%6LB(&``LX`X;`08 XM9`&"P#S8""(`"4P#:&`(S@X+F`!#8"!(`65A'Z4`(7"&"*(?`(%E*`V=1C4L XM%C1`!!"`R)$5MR)(``$$P"L2`K"X%GZY6MAM8``[S9G/MCO@S4:"5_LL4`$0`(2Y=P+-D!LS0([(!: XM&@3,"!W,(!N0#V%`7;I++B<`8`,ER227I)-LDE#R24K)*`D`F,'KHC XMK4@:VD+B@`&O)`/&EX%0`I(@>00`M\,>H""26S%@("T*`4D0(AP`<"H0/(!$ XME,GE-"J:$TCD$6H2E$VGZJ0;9@=YNI08`$XF!&9P%VL,[&F)Y^!\P8*8F!!H XMP8'\"#1@)I9"5G83*V1"X`07\B<&1:]"%)&26LR)*D$0E$IH=BI=HNM@E0;B XM589"\D@3*61.M)`]$4/N2AC0*WO#KV2+ZNE24@K\=`SUT\!3=4CI/WV$5RB@ XMQ@7J^P?D8)_=A77)+MNENWR7\#)>RLMY22_KI;V\E_@R7^K+?8D6!M``\BTN X.X;=D`!K@+Z-(2U@3+@&E X` Xend END_OF_FILE if test 9219 -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