[comp.sources.mac] UW v4.2

jdb@mordor.s1.gov (John Bruner) (04/04/88)

[UW v4.2 - part 1 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	Makefile
#	doc/uw.l
#	doc/uwlib.ms
# This archive created: Mon Apr  4 07:51:41 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(4003 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X			    UW Version 4.2
X			    31 January 1988
X
XThis is version 4.2 of UW, a multiple-window interface to UNIX for
Xthe Macintosh computer.  The distribution for UW consists of two
Xbinary files for the Macintosh (in BinHex 4.0 format) and a number
Xof source files for the (BSD) UNIX server.
X
XThe distribution includes the following directories:
X
X	h	- all UW include files
X	server	- source code for the UW server
X	lib	- source code for the UW programmer's library
X	utility	- source code for miscellaneous utility programs
X	doc	- [nt]roff documentation (-ms and -man formats)
X	hqx	- Macintosh binary files
X	misc	- other things of possible interest
X
XThe two Macintosh files are "uw.hqx", which is the executable binary
Xand "uw.doc.hqx", which is a MacWrite-format document describing the
XMacintosh user interface.
X
XUW was developed alternately on a Sun 3 and 4.3BSD VAX.  It also
Xhas been tested (more briefly) on a Sun 2 (release 2.0), Integrated
XSolutions VME 68020 (release 3.05), and a Pyramid. It depends quite a
Xbit upon BSD-specific features such as interprocess communication and
Xwill not run without modification on a System V UNIX system.
X
XThis distribution, like the version 3.4 distribution, includes
Xmake files for both 4.2BSD and 4.3BSD.  The choice of make files
Xand other configuration options is determined by the top-level
X"Makefile".  Comments in that file describe the configuration options.
X
XA "make install" in the top-level directory will compile and install
Xall of the (UNIX) pieces of the UW distribution.  As distributed,
Xthis will create a link between the directory name "/usr/include/uw"
Xand the "h" subdirectory and will create a "/usr/local/bin/libuw.a"
Xlibrary file.  These two steps allow application program to use
X	#include <uw/uwlib.h>
Xand
X	cc -o xyzzy xyzzy.o -luw
Xfor greater convenience in creating programs that use the UW library.
X
XIf you do not have the "getopt" library routine, you will find the
Xsource in "misc/getopt.c"  This source code was publicly distributed by
XAT&T and is also available in the "mod.sources" archive.  You should
Xcompile it and install it in your machine's "/lib/libc.a"  (Note that
Xsince it uses "strchr", you should compile it on a BSD system with the
Xcommand "cc -O -c getopt.c -Dstrchr=index".)  [Sorry, I can't find a
Xmanual page which I can (legally) include.]  If you can't change
X"libc.a", then you should add it to the makefiles in the "server"
Xand "lib" directories.
X
XVersion 4.2 is primarily a maintenance release.  Because of constraints
Xon the author's time, few things have changed since version 4.1.  Some
Xof the differences are:
X
X    1)	UW v4.2 is compatible with Multifinder.  It understands background
X	events, so it can receive input and update windows even when
X	another application's window is active.
X
X    2)	Some problems relating to keyboard mapping have been fixed.
X	UW recognizes the Control and ESC keys.  The mapping for the
X	numeric keypad still seems to be incomplete.  The author is
X	hampered by the fact that his development machine still has
X	its original 512K Mac keyboard.  (He dislikes the Mac+ and
X	SE keyboards.)
X
X    3)	A new window type -- plot -- has been defined.  This type of
X	window can only be created by the host.  It interprets output
X	in UNIX v7 plot(5) format.
X
X    4)	Windows may use 7, 9, 10, or 12 point fixed-width fonts.
X	UW includes non-Apple-copyrighted Mishawaka fonts for these sizes.
X
XUW is not public domain.  It is copyrighted.  However, permission to
Xcopy UW is given provided that the copies are not sold and that the
Xcopyright notices are retained.
X
XComments about UW can be sent to the author (me) at the following
Xaddresses:
X
X	ARPANET/MILNET:	jdb@mordor.s1.gov
X
X	UUCP:		{lll-crg,decwrl,caip}!mordor!jdb
X
X	U.S. Mail:	John Bruner
X			Lawrence Livermore National Laboratory
X			P.O. Box 5503, L-276
X			Livermore, CA  94550
X
XI try to answer all mail, but sometimes am unable to do so for reasons
Xbeyond my control (e.g. incomplete or incorrect return addresses,
Xfinicky mailers).
SHAR_EOF
if test 4003 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 4003 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(2432 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#! /bin/make -f
X#
X#	Makefile for UW version 4.2
X#
X# Specify VERSION 4.3 for 4.3BSD, 4.2 for 4.2BSD (including Sun 3.x)
X#
X# DEFINES is a list of the site-dependent compile-time options:
X# 	-DUTMP		attempt to update "/etc/utmp" (who) file
X# 	-DV7TTYS	V7-format "/etc/ttys" (pre-4.3BSD)
X#	-DSETOWN_BUG	fcntl(fd, F_SETOWN, pgrp) is broken (pre-4.3BSD)
X#	-Dvoid=int	kludge around broken C compilers
X#
X# UTMP specifies that UW should attempt to update the "/etc/utmp" file.
X# On some (foolish) systems this file is world-writeable.  Other
X# installations may wish AFTER CAREFUL EXAMINATION OF THE ISSUES to
X# install the UW server with group write access to the utmp file.
X#
X# V7TTYS should be used for V7-derived systems that do not have 4.3BSD's
X# "/etc/ttys" file.  This includes 4.2BSD and Sun UNIX.  There is no
X# support for USG's "/etc/inittab".
X#
X# SETOWN_BUG should be defined if the fcntl(fd, F_SETOWN, pgrp) system
X# call is broken (as it is in 4.2BSD and Sun 3.0 UNIX).  On those
X# machines the third argument must be negative to specify a process ID
X# and positive to specify a process group.
X#
X# Some C compilers do not understand pointers to void functions.  The
X# common kludge around this problem is to substitute "int" for "void"
X# everywhere.  "lint" doesn't like this, but the program will compile
X# into working code.
X#
XBINDIR	=	/usr/local/bin
XINCDIR	=	/usr/include/uw
XLIBDIR	=	/usr/local/lib
XVERSION	=	4.3
X
XDEFINES	=	-DUTMP
X
XMKFILES	=	server/Makefile lib/Makefile utility/Makefile hqx/Makefile
X
Xall:	DEFINES $(MKFILES)
X	cd server; make
X	cd lib; make
X	cd utility; make
X	cd hqx; make
X
Xdepend:
X	cd server; make depend
X	cd lib; make depend
X	cd utility; make depend
X
Xinstall:	all
X	ln -s `pwd`/h $(INCDIR)
X	install -s server/uw $(BINDIR)/uw
X	install -s utility/uwtool $(BINDIR)/uwtool
X	install -s utility/uwtitle $(BINDIR)/uwtitle
X	install -s utility/uwterm $(BINDIR)/uwterm
X	install -s utility/uwplot $(BINDIR)/uwplot
X	cp lib/libuw.a $(LIBDIR); ranlib $(LIBDIR)/libuw.a
X
Xclean:
X	cd server; make clean
X	cd lib; make clean
X	cd utility; make clean
X
XDEFINES:	Makefile
X	echo "" $(DEFINES) > DEFINES
X
Xserver/Makefile:	Makefile server/Makefile_$(VERSION)
X	cd server; cp Makefile_$(VERSION) Makefile; make depend
X
Xlib/Makefile:	Makefile lib/Makefile_$(VERSION)
X	cd lib; cp Makefile_$(VERSION) Makefile; make depend
X
Xutility/Makefile:	Makefile utility/Makefile_$(VERSION)
X	cd utility; cp Makefile_$(VERSION) Makefile; make depend
SHAR_EOF
if test 2432 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 2432 characters)'
fi
fi # end of overwriting check
if test ! -d doc
then
	echo shar: mkdir doc
	mkdir doc
fi
echo shar: extracting "'doc/uw.l'" '(2391 characters)'
if test -f 'doc/uw.l'
then
	echo shar: will not over-write existing file "'doc/uw.l'"
else
sed 's/^X//' << \SHAR_EOF > 'doc/uw.l'
X.TH UW 1 "14 September 1986"
X.UC 4
X.SH NAME
Xuw \- multiple-window Macintosh interface to UNIX
X.SH SYNOPSIS
X.B uw [ 
X.BI \-f filename
X] [
X.B \-n
X] [
X.B \-s
X]
X.SH DESCRIPTION
X.I Uw
Xis a server program on UNIX that works with the program 
X.I uw
Xon the Macintosh.
XIt provides the Macintosh program with access to
Xa maximum of seven independent I/O sessions.
XAn I/O session may be directly associated with a pseudo-terminal
Xor may simply be a communications channel to an external
XUNIX process.
XThe host program multiplexes the input and output onto one RS\-232 line.
X.PP
XMost commonly,
Xsessions will be directly associated with pseudo-terminals.
XThe Macintosh program will emulate
Xa Lear Siegler ADM-31 terminal
X(tset adm31),
Xa DEC VT52,
Xan ANSI-compatible terminal
X(tset ansi or tset aaa-24),
Xand a Tektronix 4010.
XEach window
X(on the Macintosh)
Xhas its own terminal emulation and can be resized at will.
XWindow size changes on the Macintosh can be propagated to the host,
Xor the Macintosh may be directed to display the lower left portion
Xof a larger logical terminal size.
X.PP
XIf the file `.uwrc' exists in the user's home directory,
Xthen
X.I uw
Xwill execute it when starting up.
XIf `.uwrc' is an executable file,
Xit will be directly invoked;
Xotherwise,
Xa shell will be spawned to interpret it.
XAn alternate startup file may be specified using the
X`\-f' flag;
Xalternately,
Xthe `\-n' flag instructs
X.I uw
Xnot to execute any startup file.
X.PP
XThe `\-s' flag prevents
X.I uw
Xfrom listening for UNIX-domain datagrams.
XThus,
Xit prevents external processes from manipulating
Xwindows which they did not create.
XThis may be of value in an environment where
Xother users are considered `hostile.'
X.SH LIMITATIONS
X.I Uw 
Xis of no use on unix unless 
X.I uw
Xis being run on the Macintosh.  
X.br
XIf there is a stream of output in one window there will be lag in 
Xrecognizing characters typed in another.
X.SH SEE ALSO
Xuwtool(L), uwtitle(L), uwterm(L)
X.br
X.I uw
XMacintosh documentation
X(`UW \(em A Multiple-Window Interface to UNIX').
X.br
X`The UW Programmer's Library'
X.SH AUTHOR
XProgram written by John Bruner, Lawrence Livermore Laboratories 7/85,11/85,9/86
X.br
XThis document is based upon a document created by
Xby Chris Borton, UC San Diego 11/13/85,
Xedited 9/86 by John Bruner.
X.SH BUGS
XThe `\-s' flag greatly reduces the utility of a `.uwrc' file,
Xsince it prevents
X.I uwtool
Xand
X.I uwtitle
Xfrom working.
SHAR_EOF
if test 2391 -ne "`wc -c < 'doc/uw.l'`"
then
	echo shar: error transmitting "'doc/uw.l'" '(should have been 2391 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'doc/uwlib.ms'" '(25462 characters)'
if test -f 'doc/uwlib.ms'
then
	echo shar: will not over-write existing file "'doc/uwlib.ms'"
else
sed 's/^X//' << \SHAR_EOF > 'doc/uwlib.ms'
X.\" This file should be processed by nroff or troff with the -ms macro set
X.ds uw \s-2UW\s0
X.DA September 30, 1986
X.TL
XThe UW Programmer's Library
X.AU
XJohn D. Bruner
X.SH
XIntroduction
X.PP
X\*(uw is a multiple-window Macintosh interface to a 4.2BSD UNIX\**.
X.FS
XMacintosh is a trademark of McIntosh Laboratories which
Xis licensed to Apple Computer, Inc.
XUNIX is a registered trademark of Bell Laboratories.
X.FE
X\*(uw version 3 comprises a server,
Xa set of utility programs,
Xand an program-level interface.
XThis manual describes the services which are available
Xin the \*(uw programmer's library.
XThis library allow programs to create,
Xcommunicate with,
Xand perform some control operations upon
Xwindows on the Macintosh.
X.SH
XBackground
X.PP
XBefore the library routines themselves can be discussed,
Xit is necessary to consider some aspects of the \*(uw
Xserver.
XThe server which was distributed with \*(uw versions 1.6 and 2.10
Xcommunicated with the Macintosh using a protocol which
Xis referred to as the ``original protocol.''
XThe version 3 server is capable of communicating in this protocol;
Xhowever,
Xit also supports an ``extended protocol.''
XFor convenience,
Xthese protocols are assigned numbers:
Xprotocol 1 is the original protocol
Xand protocol 2 is the extended protocol.
X.PP
XProtocol 1 provides a mechanism for
Xthe creation and destruction of windows
Xas well as a means to multiplex a single
Xcommunications line among several windows.
XIt provides a mechanism for transmitting
Xcontrol and ``meta'' characters,
Xand it also provides two ``maintenance functions''
Xwhich are used for startup and shutdown.
X.PP
XProtocol 2 provides two significant enhancements
Xrelative to protocol 1.
XFirst,
Xwindow creation messages specify the window emulation type
X(\fIe.g.\fP adm-31, vt52).
XSecond,
Xadditional information about windows,
Xcalled ``window options,''
Xis transmitted between the Macintosh client and the
Xserver on the host.
X.PP
XWindow options are an ``out-of-band'' channel of
Xinformation between the Macintosh and the host.
XThere are two types:
Xgeneric
X(common to all window types)
Xand emulation-specific.
XThe following are generic:
X.DS
Xwindow visibility
Xwindow type
Xwindow position (pixel address of top left corner)
Xwindow title
Xwindow size in pixels
X.DE
XThe following window options are specific to
Xcursor-addressible terminal emulations:
X.DS
Xterminal size (number of rows and columns)
Xfont size index (small=0, large=1)
Xmouse handling (clipboard or encoded send-to-host)
Xbell characteristics (audible, visible)
Xcursor appearance (block or underscore)
X.DE
X.PP
XThe server distinguishes between two window classes \(em
Xinternal and external.
XInternal windows are handled entirely by the server.
XThey are always terminal emulations and are always
Xassociated with a pseudo-terminal device.
X.PP
XBy contrast,
Xan external window always involves some outside process.
XThe server communicates with this process through one
Xor two Internet domain network connections.
XThere is always a ``data'' connection,
Xthrough which the external process exchanges information
X(indirectly, through the server)
Xwith the Macintosh.
XThere may also be a ``control'' connection
Xthrough which the external process exchanges
Xwindow option information
X(again indirectly)
Xwith the Macintosh.
XThe server acts as a multiplexor and demultiplexor
Xfor external windows.
XIt also caches window option information;
Xhowever,
Xit does not perform host-end emulation-specific tasks.
X.PP
XInternal and external windows meet different needs.
XTerminal emulation on the local host is best performed
Xby internal windows,
Xbecause fewer processes are involved
X(and response time is better).
XExternal windows are suitable for remote processes
X(\fIi.e.\fP those on another Internet host)
Xor for non-terminal tasks such as file transfer.
XThe \*(uw application library contains routines
Xto create and manipulate both classes of windows.
X.SH
XWindow ID's and Network Addresses
X.PP
XA unique 32-bit identification number is associated
Xwith each window that a server manipulates.
XSome operations
X(described below)
Xrequire the window number to be specified.
XWhen the server creates a new internal window,
Xit passes the window ID as the environment variable
X``UW_ID''.
X.PP
XThe server creates two network sockets upon which to receive
Xincoming messages.
XOne socket receives UNIX-domain datagrams,
Xthe other listens for Internet-domain stream connections.
XThe addresses of these sockets are placed in the environment
Xas the variables ``UW_UIPC''
X(UNIX-domain)
Xand ``UW_INET''
X(Internet domain).
X.SH
XData Types and Data Structures
X.PP
XThe \*(uw programmer's library uses a number
Xof simple and structured data types.
X.IP uwid_t 1i
XUnique window ID numbers are represented by the data type ``uwid_t''.
X.IP UWIN
XLibrary routines which operate upon external windows
Xput a range of window information into a structure.
XThe type ``UWIN'' is a pointer to the structure.
XAn object of this datatype is referred to as a ``window descriptor.''
XThis declaration is intended to be used as an abstract unit
X(in the manner of the standard I/O library's ``FILE\ *'').
X.IP uwtype_t
XWindow emulation types have the data type ``uwtype_t''.
XThe following emulation types are defined:
X.DS
X.ta 8n 24n 32n
X#define	UWT_ADM31	0	/* ADM-31 cursor-addressible terminal */
X#define	UWT_VT52	1	/* VT52 cursor-addressible terminal */
X#define	UWT_ANSI	2	/* ANSI-compatible terminal */
X#define	UWT_TEK4010	3	/* Tektronix 4010 graphics terminal */
X#define	UWT_FTP	4	/* File transfer */
X#define	UWT_PRINT	5	/* Output to Macintosh printer */
X.DE
X.IP uwopt_t
XWindow options are assigned numbers whose type is ``uwopt_t''.
XThe names of the options are:
X.DS
X.ta 8n 28n 32n
X#define	UWOP_VIS	1	/* visibility */
X#define	UWOP_TYPE	2	/* window type */
X#define	UWOP_POS	3	/* window position */
X#define	UWOP_TITLE	4	/* window title */
X#define	UWOP_WSIZE	5	/* window size (in bits) */
X#define	UWOP_TSIZE	8	/* terminal size (row,col) */
X#define	UWOP_TFONTSZ	9	/* small/large font size */
X#define	UWOP_TCLIPB	10	/* clipboard/mouse encoding */
X#define	UWOP_TBELL	11	/* audible, visual bell */
X#define	UWOP_TCURS	12	/* cursor shape */
X.DE
X.IP uwoptcmd_t
XThe window option commands
Xwhich are passed between the Macintosh and the host
Xhave type ``uwoptcmd_t''.
XThese commands are:
X.DS
X.ta 8n 24n 32n
X#define	UWOC_SET	0		/* set value of option */
X#define	UWOC_ASK	2		/* ask for value of option */
X#define	UWOC_DO	4		/* report changes in value */
X#define	UWOC_DONT	5		/* don't report changes */
X#define	UWOC_WILL	6		/* will report changes */
X#define	UWOC_WONT	7		/* won't report changes */
X.DE
X.IP "union uwoptval"
XWhen a function requires a window option value as an argument,
Xthe value of the window option is placed into a
Xunion declared as ``union uwoptval''.
XThe address of this union is passed to the function.
XThis union is declared as follows:
X.DS
X.ta 8n 16n 24n
Xunion uwoptval {
X	unsigned char	uwov_1bit;
X	unsigned char	uwov_2bit;
X	unsigned char	uwov_6bit;
X	unsigned short	uwov_12bit;
X	struct {
X		unsigned short v,h;
X	}		uwov_point;
X	char		uwov_string[256];
X};
X.DE
XThe union member used for a particular option
Xdepends upon the option number.
XAt present,
Xthe types of the window options and
Xcorresponding union members are:
X.DS
X.ta 1i
Xvisibility	uwov_1bit
Xtype	uwov_6bit
Xposition	uwov_point
Xtitle		uwov_string (null terminated)
Xbit size	uwov_point
Xtty size	uwov_point
Xfont size	uwov_1bit
Xclipboard	uwov_1bit
Xbell		uwov_2bit
Xcursor type	uwov_1bit
X.DE
X.IP "uwerr_t"
XWhen a library routine returns an error indication,
Xfurther information about the type of error can be
Xobtained from the global variable ``uwerrno''.
X(Depending upon the type of error,
Xthe external variable ``errno'' may also contain
Xpertinent information.)
X\*(uw error numbers have type ``uwerr_t'',
Xand are defined as follows:
X.DS
X.ta 8n 24n 32n
X#define	UWE_NONE	0	/* no error */
X#define	UWE_ERRNO	1	/* system call error, consult errno */
X#define	UWE_NXTYPE	2	/* nonexistent window type */
X#define	UWE_DUPID	3	/* window ID duplicated (in use) */
X#define	UWE_NOTIMPL	4	/* operation not implemented yet */
X#define	UWE_NXSERV	5	/* non-existent server */
X#define	UWE_NOMEM	6	/* unable to allocate required memory */
X#define	UWE_INVAL	7	/* invalid argument to function */
X#define	UWE_NOCTL	8	/* no control file descriptor */
X.DE
X.SH
XInternal Window Interface
X.PP
XWhen an internal window is created by an external process,
Xa UNIX-domain datagram is sent to the server.
XThis datagram contains
X(as ``access rights'')
Xa file descriptor for the ``master'' side of a pseudo-terminal.
XThe server assumes that the external process
Xhas started some program on the ``slave'' side of the pseudo-terminal.
XAfter sending the datagram,
Xthe sender has no direct handle to manipulate
Xthe window.
XIt has,
Xin effect,
Xrelinquished all control.
X(It should close the master side of the pseudo-terminal
Xafter sending the datagram.)
XTo provide some additional flexibility,
Xit is possible to change the value of a window option
Xfor any window
X(even ``external'' windows)
Xif the window's unique ID is known.
XThe creator of the window has no special privileges
Xin this regard.
X.LP
X[One thing which the internal window routines
Xin the \*(uw library completely ignore
Xis the fact that datagrams are not guaranteed to be reliable.
XUNIX-domain datagrams almost always seem to work,
Xbut they can fail.
XIn the author's experience this has never been a problem,
Xbut let the user beware.]
X.LP
XThe following routines are available:
X.IP uw_fork 1i
XThis routine is similar in concept to the system call ``fork''.
XIt creates a new process
Xand returns twice \(em
Xonce in the parent and once in the child.
XIn addition to creating a new process,
X``uw_fork'' also arranges for the new process to be
Xassociated with an internal window.
XIt opens a pseudo-terminal,
Xredirects the child's standard input,
Xstandard output,
Xand standard error,
Xand sends a UNIX-domain datagram to the \*(uw server.
XIt returns the unique ID associated with the window
Xin the parent,
Xand returns 0 in the child.
X(\(mi1 is returned if the routine fails.)
X.DS
Xuwid_t uw_fork(uwtype_t wtype, int *pidp);
X.DE
XThe first argument specifies the type of the new window.
XIf the second argument to ``uw_fork'' is a non-NULL pointer,
Xthe process-ID of the child will be stored at that address
Xin the parent process.
X(In the child, ``*pidp'' will be zero.)
X.IP uw_cmd
XThis routine builds upon the functionality of the ``uw_fork'' routine.
XIt creates a new window with ``uw_fork''
Xand then executes a specified command.
XIt takes the window type,
Xthe name of an executable file,
Xand an argument list
Xas parameters;
Xit uses these as arguments to ``uw_fork''
Xand the C library routine ``execvp''.
XIt returns the window ID number to its caller:
X.DS
Xuwid_t uw_cmd(uwtype_t wtype, char *file, char **argv);
X.DE
X(\(mi1 is returned if the routine fails.)
X.IP uw_shell
X``uw_shell'' is similar to ``uw_cmd'' except that it
Xexecutes an arbitrary shell command:
X.DS
Xuwid_t uw_shell(uwtype_t wtype, char *cmd);
X.DE
X(\(mi1 is returned if the routine fails.)
XBy default the Bourne shell is used;
Xhowever,
Xthe shell may be changed by patching the global variable ``uwshellname''.
X.DS
Xchar *uwshellname = "/bin/sh";
X.DE
X.IP uw_rsetopt
XThis routine changes the value of a window option
Xfor an existing window
X(named as a window ID).
XThe window may be either internal or external.
XThe specified window option is set to a desired value.
XZero is returned if the appropriate UNIX-domain message
Xwas successfully sent;
X\(mi1 is returned if the operation failed.
X(Since ``uw_rsetopt'' does not receive a reply from the server,
Xit is unable to determine whether or not the command ``succeeded''.
XRather,
Xit returns zero if the command was successfully transmitted.)
X.DS
Xint uw_rsetopt(uwid_t uwid, uwopt_t optnum, union uwoptval *optval);
X.DE
X``optval'' points to a ``union uwoptval'' structure
X(described above)
Xin which the member corresponding to ``optnum''
Xhas been initialized.
X.IP "uw_perror"
XWhen an error is reported by a \*(uw library routine,
Xthe cause of the error is saved in the external variable
X``uwerrno''.
XIf the error was UWE_ERRNO,
Xthe standard external variable ``errno''
Xwill also be meaningful.
X(The routines which operate upon external windows,
Xdescribed in the following section,
Xalso save this information in the window descriptor.)
XThe routine ``uw_perror'' may be used to decode and print
Xerror messages:
X.DS
Xvoid uw_perror(char *usermesg, uwerr_t uwerr, int err)
X.DE
Xwhere ``usermesg'' is a pointer to a user-specified string,
X``uwerr'' is the \*(uw error code
X(usually ``uwerrno''),
Xand ``err'' is the system call error code
X(usually ``errno'').
X[System call error numbers are defined in ``/usr/include/errno.h''.]
X.sp
XThe \*(uw error messages may also be accessed directly.
XTwo external variables aid in user-formatted error messages:
X.DS
Xextern char *uwerrlist[];
Xextern unsigned uwnerr;
X.DE
XIf the error number is greater than or equal to ``uwnerr'',
Xno error message string exists.
X(This ``cannot happen.'')
XOtherwise,
Xthe error message string is obtained by indexing into
X``uwerrlist''.
X.PP
XThe preceeding routines are sufficient to implement
Xa (simplified) version of the ``uwtool'' program,
Xwhich creates a new
X(internal)
Xwindow running a specified command:
X.DS
X.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
X/*
X *      uwtool
X *
X * Copyright 1986 by John D. Bruner.  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#include <strings.h>
X#include "uwlib.h"
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X        register uwid_t uwid;
X        register char *fname, *term;
X	register wtype_t wtype;
X        char *av[2];
X        union uwoptval optval;
X        extern int errno;
X        extern char *getenv();
X
X        /*
X         * If called with no arguments, create a new window using the
X         * current shell according to the SHELL environment variable
X         * (or "/bin/sh" if that doesn't exist).  If called with
X         * arguments, argv[1] through argv[argc\-1] are the arguments
X         * to the command.
X         */
X        if (argc == 1) {
X                if ((fname = getenv("SHELL")) == (char *)0)
X                        fname = "/bin/sh";
X                av[0] = fname;
X                av[1] = (char *)0;
X                argv = av;
X        } else
X                fname = *++argv;
X	
X	if ((term=getenv("TERM")) != (char *)0)
X		wtype = uw_ttype(term);
X	else
X		wtype = UWT_ADM31;
X        
X        if ((uwid = uw_cmd(wtype, fname, argv)) < 0) {
X                (void)strncpy(optval.uwov_string, fname,
X                    sizeof optval.uwov_string);
X                (void)uw_rsetopt(uwid, UWOP_TITLE, &optval);
X                return(0);
X        } else {
X                uw_perror("uwtool", uwerrno, errno);
X                return(1);
X        }
X}
X.DE
XAfter the first part of the function has massaged the argument list,
Xthe ``uw_cmd'' routine creates a new window
Xrunning the command ``fname'' with argument list ``argv''.
XIf the window ID is positive,
Xthe window creation succeeded.
XAfter copying the name of the program into a ``union uwoptval'',
Xthe program calls ``uw_rsetopt'' to set the window title
Xto that string.
XIf the window ID returned by ``uw_cmd'' was \(mi1,
Xthe window creation failed.
XIn this case,
Xthe program calls ``uw_perror'' to report the error.
X.SH
XExternal Window Interface
X.LP
XThe remainder of the \*(uw library routines provide access to
Xexternal windows.
XIn contrast to internal windows,
Xa client process creates an external window
Xby establishing an Internet-domain stream connection
Xto the server and sending the server a ``create window'' command.
XThe server will establish a second stream connection
Xback to the client.
XData is passed between the client and the server on the first connection,
Xwhile control information is passed through the second.
X[Because the server and client communicate through one or
Xtwo stream connection(s)
Xinstead of by sending datagrams,
Xthe unreliability problems noted above for internal windows
Xdo not apply to external windows.]
X.LP
XThe \*(uw library provides mechanisms for creating external windows,
Xkilling them,
Xand manipulating window options.
XWhen a window is created a window descriptor
X(item of type UWIN)
Xis returned;
Xthis is used as an argument to all other external-window routines.
X.LP
XThe following routines are provided:
X.IP "uw_new" 1i
XThis function creates a new external window of the specified type.
XThe calling sequence is:
X.DS
XUWIN uw_new(uwtype_t uwtype, struct sockaddr_in *server)
X.DE
Xwhere ``uwtype'' is the window type
Xand ``server'' is a pointer to a structure specifying
Xthe Internet address of the server.
X(If ``server'' is a NULL pointer,
Xthe server will be determined by examining the
Xenvironment variable ``UW_INET''.)
XIf the window creation succeeded,
X``uw_new'' will return a non-NULL window descriptor;
Xotherwise,
Xit will return NULL, and
Xthe global variables ``uwerrno'' and ``errno''
Xmay be examined to determine the cause of the error.
X.IP "uw_detach"
XThis function ``detaches'' the window from the program
Xso that it no longer is able to perform control operations
Xupon the window.
XThe data connection to the window remains open.
XThis function should be used when the data connection to a window
Xwill be handled by a different process
Xthan the control connection,
X.I e.g.
Xin a child process after a ``fork''.
XIt is strongly recommended that no more than one process
Xhave control access to a window at any one time.
XThe calling sequence is
X.DS
Xuw_detach(UWIN uwin);
X.DE
Xwhere ``uwin'' is the window descriptor.
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
XIf the routine fails,
Xthe error status will be stored in the UWIN data item
Xas well as in the global variables ``uwerrno'' and ``errno''.
X.IP "uw_close"
XThis function closes a window.
XBoth the control and data connections to the window are closed.
XIf multiple processes have access to a window
X(\fIe.g.\fP because of a ``fork''),
Xthen the window will be destroyed when the last connection
Xto it is closed.
XThe calling sequence is
X.DS
Xuw_close(UWIN uwin);
X.DE
Xwhere ``uwin'' is the window descriptor
X.IP "uw_kill"
XAt times it may be desirable for one process to destroy
Xa window even if the window is in use by other processes.
XThe ``uw_kill'' function performs this task.
XThe caller must have control access to the window
X(it must not be ``detached'').
XThe syntax is:
X.DS
Xuw_kill(UWIN uwin);
X.DE
Xwhere ``uwin'' is the window descriptor.
XWhen a window is killed
X(either by ``uw_kill'' or upon command from the Macintosh)
Xthe server closes its data channel.
XAny further attempts to read or write to the window
Xwill produce end-of-file or error conditions,
Xrespectively.
X.IP "uw_optfn"
XIf a process has control access to a window,
Xthen it will periodically receive
Xwindow option messages from the Macintosh client
X(through the server).
XThe \*(uw library receives these messages by enabling
Xasynchronous I/O notification on the control channel
Xand providing a SIGIO signal handler.
XSometimes it is desirable for an external process
Xto field incoming option messages itself.
XTo do so,
Xit must notify the \*(uw library by calling the
Xroutine ``uw_optfn'':
X.DS
Xvoid (*uw_optfn(UWIN uwin, uwopt_t optnum, void (*optfn)())();
X.DE
Xwhere ``uwin'' is the window descriptor,
X``optnum'' is the desired window option,
Xand ``optfn'' is a pointer to a function which
Xwill be called when a message about window option ``optnum''
Xis received.
X``uw_optfn'' returns the previous function.
XTo disable processing for a window option,
Xspecify a NULL pointer for ``optfn''.
XThe user-supplied ``optfn'' is called with the following arguments:
X.DS
X.ta 8n
Xvoid (*optfn)(UWIN uwin, uwopt_t optnum, uwoptcmd_t optcmd,
X	union uwoptval *optval);
X.DE
Xwhere ``uwin'' is the window descriptor,
X``optnum'' is the window option number,
X``optcmd'' is the window option command,
Xand
X(if ``optcmd'' is UWOC_SET)
X``optval'' is a pointer to the new value of the window option.
X.sp
XBecause the \*(uw library provides a signal handler for SIGIO,
Xif other portions of the program wish to catch SIGIO,
Xthen some care must be taken
Xto ensure that all signal handlers are called.
XThe \*(uw library saves the return value from
X``signal'' when it installs its handler.
XIf this is not SIG_IGN,
Xthen that routine will be called after \*(uw has
Xcompleted its signal processing.
XIn a similar fashion,
Xif the calling program establishes a signal handler,
Xit should save the previous value and call the indicated
Xfunction
X(if not SIG_IGN).
XFor example,
Xif the caller uses ``signal'':
X.DS
X.ta 8n 16n
Xoldhandler = signal(SIGIO, myhandler);
X\&...
Xmyhandler(sig, code, scp)
Xint sig, code;
Xstruct sigcontext *scp;
X{
X	... code to handle exception ...
X	if (oldhandler != SIG_IGN)
X		(*oldhandler)(sig, code, scp);
X}
X.DE
XAlthough from time to time
Xthe Macintosh may ask the server for the current
Xvalue of a window option,
Xthe \*(uw server caches the current value of each
Xwindow option
Xand responds to these inquiries directly.
XTherefore,
Xthe major reason for establishing a window option function
Xwith ``uw_optfn'' is to process incoming UWOC_SET messages,
X.I i.e.
Xmessages from the Macintosh that the value of a window
Xoption has changed.
X.IP "uw_optcmd"
XThis function allows a program with control access to a window
Xto send window option commands.
XThe calling sequence is
X.DS
X.ta 8n
Xuw_optcmd(UWIN uwin, uwopt_t optnum, uwoptcmd_t optcmd,
X	union uwoptval *optval);
X.DE
Xwhere ``uwin'' is the window descriptor,
X``optnum'' is the window option number,
X``optcmd'' is the command,
Xand ``optval'' is a pointer to the option value.
XOf the six window option messages,
Xonly the UWOC_SET,
XUWOC_DO,
Xand UWOC_DONT
Xmessages are very useful.
XUWOC_SET changes the value of a window option
X(``optval'' points to the new value).
XUWOC_DO and UWOC_DONT instruct the Macintosh to
Xreport or not report
X(respectively)
Xwhen a user action changes the value of a window option there.
XWhen it creates a window,
Xthe \*(uw server instructs the Macintosh to report all
Xchanges to window options.
XMost programs will probably not need to issue UWOC_DO or UWOC_DONT commands.
X.IP uw_gvis
XThis function fetches the current visibility
Xstatus of a specified window:
X.DS
Xint uw_gvis(UWIN uwin, int *vp);
X.DE
X``vp'' is a pointer to an integer where the visibility status
X(0 or 1 for invisible or visible, respectively)
Xis returned.
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
X.IP uw_svis
XThis function changes the visibility status of a specified window:
X.DS
Xint uw_svis(UWIN uwin, int v);
X.DE
XIf ``v'' is nonzero then the window ``uwin'' will be made visible;
Xotherwise,
Xthe specified window will be made invisible.
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
X.IP uw_gpos
XThis function returns the current position on the screen
Xof a specified window:
X.DS
X.ta 8n 20n 28n
Xstruct uwpoint {
X	unsigned	uwp_v;	/* vertical component */
X	unsigned	uwp_h;	/* horizontal component */
X};
X
Xint uw_gpos(UWIN uwin, struct uwpoint *pp);
X.DE
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
X.IP uw_spos
XThis function sets the position of a specified window to
Xa desired location:
X.DS
Xint uw_spos(UWIN uwin, struct uwpoint *pp);
X.DE
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
X.IP uw_gwsize
XThis function returns the current size in pixels
Xof a specified window.
XThe size is expressed as a ``uwpoint'',
Xas defined above.
X.DS
Xint uw_gwsize(UWIN uwin, struct uwpoint *pp);
X.DE
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
X.IP uw_swsize
XThis function sets a specified window to a new size:
X.DS
Xint uw_swsize(UWIN uwin, struct uwpoint *pp);
X.DE
X.IP uw_gtitle
XThis function returns the title of a specified window.
XThe title has type ``uwtitle_t'':
X.DS
Xtypedef char uwtitle_t[256];
X
Xint uw_gtitle(UWIN uwin, uwtitle_t ttl);
X.DE
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
X.IP uw_stitle
XThis function sets the title of a specified window:
X.DS
Xint uw_stitle(UWIN uwin, uwtitle_t ttl);
X.DE
X.IP uw_gtype
XThis function returns the type of a specified window:
X.DS
Xint uw_gtype(UWIN uwin, uwtype_t *tp);
X.DE
X``tp'' points to a variable which receives the window type.
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
X.IP uw_stype
XThis function sets the type of a specified window:
X.DS
Xint uw_stype(UWIN uwin, uwtype_t t);
X.DE
X``t'' is the new window type.
XZero is returned for success,
Xwhile \(mi1 is returned for failure.
X.IP "UW_DATAFD"
XThis macro extracts the file descriptor for the data connection
Xfrom a window descriptor:
X.DS
Xint UW_DATAFD(UWIN uwin);
X.DE
X.IP "UW_ID"
XThis macro returns the unique window ID associated with a
Xwindow descriptor:
X.DS
Xuwid_t UW_ID(UWIN uwin);
X.DE
X.IP "UW_PERROR"
XWhen the \*(uw library detects an error
Xit always places the error information into the
Xglobal variables ``uwerrno'' and ``errno''.
XIf the error is associated with a valid window descriptor,
Xit will also store the information in the window descriptor.
XThe macro ``UW_PERROR'' is used to print an error message
Xaccording to the error status in a window descriptor:
X.DS
Xvoid UW_PERROR(char *message, UWIN uwin);
X.DE
Xwhere ``message'' is any user-supplied message and
X``uwin'' is a window descriptor.
X.SH
XCopyright
X.LP
XThis document copyright 1986 by John D. Bruner.
XPermission to copy is given,
Xprovided that the copies are not sold
Xand that this copyright notice is included.
SHAR_EOF
if test 25462 -ne "`wc -c < 'doc/uwlib.ms'`"
then
	echo shar: error transmitting "'doc/uwlib.ms'" '(should have been 25462 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 1 ---

jdb@mordor.s1.gov (John Bruner) (04/05/88)

[UW v4.2 - part 2 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	doc/uwproto.ms
#	doc/uwplot.l
#	doc/uwterm.l
#	doc/uwtitle.l
#	doc/uwtool.l
# This archive created: Mon Apr  4 07:51:45 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d doc
then
	echo shar: mkdir doc
	mkdir doc
fi
echo shar: extracting "'doc/uwproto.ms'" '(24952 characters)'
if test -f 'doc/uwproto.ms'
then
	echo shar: will not over-write existing file "'doc/uwproto.ms'"
else
sed 's/^X//' << \SHAR_EOF > 'doc/uwproto.ms'
X.\" This file should be processed by nroff or troff with the -ms macro set
X.ds uw "\s-2UW\s0
X.de T=
X.ie t .ta 8n 28n 36n 44n
X.el .ta 8n 24n 32n 40n
X..
X.DA September 30, 1986
X.TL
XUW Protocol
X.AU
XJohn D. Bruner
X.SH
XIntroduction
X.PP
X\*(uw is a multiple-window interface to UNIX.\**
X.FS
XUNIX is a registered trademark of American Telephone and Telegraph.
X.br
XMacintosh is a trademark of McIntosh Laboratories,
Xand is licensed to Apple Computer.
X.br
XADM-31 is a trademark of Lear Siegler, Inc.
X.br
XVT52 is a trademark of Digital Equipment Corporation.
X.br
XThe Tektronix 4010 is a graphics terminal manufactured
Xby Tektronix, Inc.
X.FE
XIt comprises two parts:
Xa program which runs on a Macintosh
X(referred to hereafter as ``the client'')
Xand a server program which runs on the UNIX system
X(``the host'').
XThese two programs exchange information by sending
Xdata across a serial communications line.
XThis information consists of data
Xand control and status messages relating to its presentation.
XThe structure of this information is defined by
Xthe \*(uw protocol
Xand is the subject matter of this document.
X.PP
X\*(uw version 3 actually defines three protocols.
XInternally they are assigned numbered,
Xwhile the user interface and documentation refer to them
Xby name.
XThe correspondence is as follows:
X.IP 0
XProtocol 0 is referred to as the ``serverless protocol''
Xor ``single terminal emulator protocol,''
Xbecause its use does not require a server on the host.
X.IP 1
XProtocol 1 is called the ``original \*(uw protocol,''
Xbecause it was the only protocol supported by the first
Xversions of \*(uw
X(versions 1.6 and 2.10).
X.IP 2
XProtocol 2 is called the ``extended \*(uw protocol,''
Xor (sometimes)
Xthe ``\*(uw version 3 protocol.''
X.SH
XProtocol 0 \(em The Serverless Protocol
X.PP
XProtocol 0 is not really a \*(uw protocol at all.
XThe client speaks protocol 0 when it is communicating
Xdirectly with a host,
Xrather than communicating through a server program
Xrunning on the host.
XProtocol 0 is simply 7-bit or 8-bit ASCII.
XEvery byte transmitted in protocol 0 represents itself,
Xwith the possible exception of the two flow-control characters
XXON (control-Q)
Xand
XXOFF (control-S).
XProtocol 0 does not specify whether these characters are
Xto be used for flow-control purposes or for data transmission.
XThe client program on the Macintosh and the host's terminal driver
Xcan be configured to use or ignore flow-control.
X.PP
XProtocol 0 does not specify whether data is transmitted
Xusing 8-bit ASCII or 7-bit ASCII.
XThe user must choose the appropriate transmission format
Xand is reponsible for configuring both the client and the host
Xaccordingly.
X.SH
XProtocol 1 \(em The Original \*(uw Protocol
X.PP
XProtocol 1 was the only protocol which was used in
Xthe first versions of \*(uw
X(versions 1.6 and 2.10).
XIt defines seven ``windows,''
Xeach of which is an independent data stream.
XThrough the transmission of appropriate commands,
Xwindows may be created or destroyed,
Xand data may be directed to a particular window.
XData which is transmitted from the client to the host
Xis referred to as ``input data,''
Xwhile data transmitted from the host to the client
Xis referred to as ``output data.''
XIn each direction a ``current window'' specifies
Xthe recipient of data bytes.
X(For example,
Xif the client wishes to send data to window 4,
Xit first sends a ``select window 4 as input window''
Xcommand and then sends the data.
XUntil the client sends another ``select input window'' command,
Xall further data that it transmits will be received
Xas data for window 4.)
XThe current input window and current output window may be different.
X.PP
XProtocol 1 encodes all information into 7-bit symbols;
Xit does not depend upon the value of the most-significant bit
X(sometimes used for parity purposes).
XCommands are encoded into two bytes:
Xa prefix byte (P1_IAC)
Xand a command byte.
XBit 7
X(the second most-significant bit, octal 0100)
Xspecifies whether the command was sent from the host to the client or
X.I "vice versa:"
X.DS
X.T=
X#define	P1_IAC	0001	/* intrepret following byte as a command */
X#define	P1_DIR	0100	/* command direction: */
X#define	P1_DIR_HTOM	0000	/*	from host to Mac (client) */
X#define	P1_DIR_MTOH	0100	/*	from Mac (client) to host */
X.DE
XThe command's function is encoded into the next three bits.
XThere are only seven commands:
X.DS
X.T=
X#define	P1_FN	0070	/* function code: */
X#define	P1_FN_NEWW	0000	/*	create new window */
X#define	P1_FN_KILLW	0010	/*	kill (destroy) window */
X#define	P1_FN_ISELW	0020	/*	select window for input data */
X#define	P1_FN_OSELW	0030	/*	select window for output data */
X#define	P1_FN_META	0050	/*	add META to next data character */
X#define	P1_FN_CTLCH	0060	/*	send control character as data */
X#define	P1_FN_MAINT	0070	/*	perform "maintenance function" */
X.DE
X(The client does not send the P1_FN_OSELW command;
Xsimilarly,
Xthe host does not send the P1_FN_ISELW command.)
X.PP
XThe least-significant three bits of the command byte
Xspecify an argument to the function.
XFor the ``new window'' (P1_FN_NEWW),
X``kill window'' (P1_FN_KILLW),
X``select input'' (P1_FN_ISELW),
Xand
X``select output'' (P1_FN_OSELW)
Xcommands,
Xthe low three bits specify a window number.
XWindow number zero is not used.
X.PP
XThere are no arguments to the P1_FN_META command.
XIt directs that the next data byte to be transmitted
Xbe considered a ``meta'' character;
X.I i.e.
Xa byte with the most-significant bit
X(octal 0200)
Xset.
X.PP
XThe P1_FN_CTLCH command is used to encode three
Xdata characters which cannot be transmitted directly as data.
XThese are P1_IAC
X(which,
Xif encountered in a transmission,
Xindicates the start of a two-character command),
Xand the flow-control characters XON (021)
Xand XOFF (023).
XThe low-order three bits of the command byte specify the character:
X.DS
X.T=
X#define	P1_CC	7	/* control character specifier: */
X#define	P1_CC_IAC	1	/*	P1_IAC (001) */
X#define	P1_CC_XON	2	/*	XON (021) */
X#define	P1_CC_XOFF	3	/*	XOFF (023) */
X.DE
XA meta-control character is transmitted as a P1_FN_META
Xcommand followed by the appropriate P1_FN_CTLCH command.
XThus,
Xthe octal character 0201 would be transmitted from the
Xhost to the client as
Xa four-byte sequence:
X.DS
X.T=
X0001	(P1_IAC)
X0050	(P1_DIR_HTOM|P1_FN_META)
X0001	(P1_IAC)
X0061	(P1_DIR_HTOM|P1_FN_CTLCH|P1_CC_IAC)
X.DE
XNote that since the host does not send P1_FN_OSELW commands
Xand the client sends commands with the 0100 bit set,
Xthe XON and XOFF control characters will never be sent as command bytes.
X.PP
X``Maintenance functions'' are defined for operations
Xwhich are performed infrequently.
XProtocol 1 defines two maintenance functions:
X.DS
X.T=
X#define	P1_MF	7	/* maintenance functions: */
X#define	P1_MF_ENTRY	0	/*	start up */
X#define	P1_MF_EXIT	7	/*	exit */
X.DE
XThe server sends the P1_MF_ENTRY command when it starts up.
XThe client responds to this by killing any windows that it
Xhas created
X(silently,
X.I i.e.
Xwithout sending P1_FN_KILLW messages to the host).
XEither the client or the server may send the P1_MF_EXIT command
Xto terminate the session.
XWhen the server on the host receives P1_MF_EXIT
Xit terminates;
Xwhen the client receives this command it will reset to a
Xsimple known state.
X.SH
XProtocol 2
X.PP
X\*(uw version 3 provides a number of capabilities
Xthat earlier versions of \*(uw did not.
XAmong these is an expansion of the host-client interaction.
XIn order to accomodate the increased flow of information
Xit was necessary to extend the \*(uw protocol.
XOne of the significant extensions in protocol 2
Xis support for a concept called ``window options.''
XWindow options are described in more detail in the next section.
X.PP
XProtocol 2 is very similar to protocol 1.
XLike protocol 1,
Xprotocol 2 multiplexes a single communications stream
Xamong a maximum of seven windows.
XCommand bytes in protocol 2 are encoded in the same
Xfashion as in protocol 1:
Xa prefix byte
X(P2_IAC)
Xfollowed by a command byte.
XHowever,
Xunlike protocol 1,
Xsome protocol 2 commands require more than one command byte.
X.PP
XThe protocol 2 functions are:
X.DS
X.T=
X#define	P2_FN	0070	/* function code: */
X#define	P2_FN_NEWW	0000	/*	create new window */
X#define	P2_FN_KILLW	0010	/*	kill (destroy) window */
X#define	P2_FN_ISELW	0020	/*	select window for input data */
X#define	P2_FN_OSELW	0030	/*	select window for output data */
X#define	P2_FN_WOPT	0040	/*	communicate window options */
X#define	P2_FN_META	0050	/*	add META to next data character */
X#define	P2_FN_CTLCH	0060	/*	send control character as data */
X#define	P2_FN_MAINT	0070	/*	perform "maintenance function" */
X.DE
XThe P2_FN_KILLW,
XP2_FN_ISELW,
XP2_FN_OSELW,
Xand P2_FN_CTLCH
Xcommands are identical to their counterparts in protocol 1.
X.PP
XThe low-order three bits of the P2_FN_META command
Xrepresent a control character.
X(The low-order three bits of the P1_FN_META command are ignored.)
XThe encoding is identical to the encoding
Xfor the P2_FN_CTLCH command:
X.DS
X.T=
X#define	P2_CC	7	/* control character specifier: */
X#define	P2_CC_IAC	1	/*	P2_IAC (001) */
X#define	P2_CC_XON	2	/*	XON (021) */
X#define	P2_CC_XOFF	3	/*	XOFF (023) */
X.DE
XIf the low-order three bits are zero,
Xthen the P2_FN_META command acts like the P1_FN_META command \(em
Xthe META bit is set in the next data byte.
XIf the low-order three bits are not all zero,
Xthe the P2_FN_META command specifies a META-control character.
XThus, the following are all equivalent:
X.DS
XP1_IAC\ \ P1_FN_META\ \ P1_IAC\ \ P1_FN_CTLCH|P1_CC_IAC
XP2_IAC\ \ P2_FN_META\ \ P2_IAC\ \ P2_FN_CTLCH|P2_CC_IAC
XP2_IAC\ \ P2_FN_META|P2_CC_IAC
X.DE
X.PP
XThe P2_FN_NEWW command differs from the P1_FN_NEWW command
Xin that the protocol 2 command includes an extra byte.
XThe byte following the command byte
Xspecifies the type of the window that is being created.
XThe numeric value of the window type is
Xadded to the ASCII value for a space (blank);
Xhence,
Xthe window type is always represented by a printable character.
XAs an example,
Xif the host wishes to create window 2
Xwith window type 1 (VT-52),
Xthe command sequence is:
X.DS
X.T=
X0001	(P2_IAC)
X0002	(P2_DIR_HTOM|P2_FN_NEWW|2)
X0041	(`!')
X.DE
X.PP
XThe following maintenance functions (P2_FN_MAINT) are defined:
X.DS
X.T=
X#define	P2_MF	7	/* maintenance functions: */
X#define	P2_MF_ENTRY	0	/*	start up */
X#define	P2_MF_ASKPCL	2	/*	request protocol negotiation */
X#define	P2_MF_CANPCL	3	/*	suggest protocol */
X#define	P2_MF_SETPCL	4	/*	set new protocol */
X#define	P2_MF_EXIT	7	/*	exit */
X.DE
XThe representations of
XP2_MF_ENTRY and P2_MF_EXIT are identical to those in protocol 1.
XThe definition of the ``entry'' function is extended
Xslightly in protocol 2.
XIn protocol 1,
Xthe P1_MF_ENTRY command is only sent by the server when it starts up.
XThe client recognizes this command and initializes itself.
XIn protocol 2,
Xthe client is permitted to send the P2_MF_ENTRY command
Xto the server.
XUpon receipt of this command,
Xthe server issues the sequence of P2_FN_NEWW commands
Xand P2_FN_WOPT commands
X(described below)
Xwhich will reconstruct all of the existing windows
Xon the client in their current state.
XThe client uses this command to ``restart'' itself after a crash
Xor other interruption on its end of the connection.
XThe three new maintenance functions are used for protocol negotiation.
XProtocol negotiation is described in detail below.
X.PP
XProtocol 2 defines the new command
XP2_FN_WOPT
Xto transmit window option information
Xbetween the client and server.
XThe P2_FN_WOPT command is followed by a variable-length
Xstring of bytes which encode the window options information.
XThe next section describes the meaning and encoding of
Xwindow option information.
X.SH
XWindow Options
X.PP
XWindow options are window attributes
X(the latter is a more meaningful name).
XFor each window,
Xa maximum of 31 window options may be defined.
XThese are divided into two categories:
Xgeneric and emulation-specific.
XGeneric window options are attributes which are common
Xto all window emulation types.
XEmulation-specific options are meaningful only for some
Xsubset of the available emulation types.
XThe following options are generic:
X.DS
X.T=
X#define	WOG_END	0	/* [used as an endmarker] */
X#define	WOG_VIS	1	/* visibility */
X#define	WOG_TYPE	2	/* window emulation type */
X#define	WOG_POS	3	/* window position on screen */
X#define	WOG_TITLE	4	/* window title */
X#define	WOG_SIZE	5	/* window size (in pixels) */
X#define	WOG_6	6	/* [unassigned, reserved] */
X#define	WOG_7	7	/* [unassigned, reserved] */
X.DE
XTerminal emulations define the following emulation-specific options:
X.DS
X.T=
X#define	WOTTY_SIZE	8	/* (row,col) terminal size */
X#define	WOTTY_FONTSZ	9	/* font size index */
X#define	WOTTY_MOUSE	10	/* mouse interpretation */
X#define	WOTTY_BELL	11	/* audible, visual bell */
X#define	WOTTY_CURSOR	12	/* cursor shape */
X.DE
XWindow option values are structured types composed
Xof the following primitive types:
X.DS
Xfixed-length character vectors
Xvariable-length character strings
Xspecified-width unsigned integer data
X.DE
X.PP
XThe host and client may exchange the following commands
Xregarding window options:
X.DS
X.T=
X#define	WOC_SET	0	/* change value of option */
X#define	WOC_INQUIRE	2	/* ask about current option value */
X#define	WOC_DO	4	/* do report changes to option */
X#define	WOC_DONT	5	/* don't report changes to option */
X#define	WOC_WILL	6	/* will report changes to option */
X#define	WOC_WONT	7	/* won't report changes to option */
X.DE
XThe ``set'' command is sent by either the client or the host
Xto specify the current value of a window option.
XThe ``inquire'' command is sent by either the client or the host
Xwhen it wishes to know the current value of an option.
XThe recipient of an ``inquire'' command responds with a
X``set'' command that specifies the current option value.
X.PP
XThe remaining four window option commands
Xare used by the host
Xto set up automatic reporting by the client
Xwhen the value of a window option changes.
XIf the host wishes to be informed
Xwhen the value of a window option changes
X(\fIe.g.\fP when a window is retitled),
Xit sends a ``do'' command to the client.
XThe client responds to the ``do'' command
Xwith a ``will'' command
Xfollowed immediately by a ``set'' command
X(reporting the current value of the option).
XThereafter,
Xwhenever the value of that option changes
Xthe client will send a ``set'' command with the new value
Xto the host.
XIf the host wishes the client to stop sending
Xthese ``set'' commands,
Xthe host sends the client a ``don't'' command.
XThe client responds with a ``won't'' message.
X.PP
XThe reporting status of generic window options is not affected
Xif the window emulation types changes;
Xhowever,
Xif the emulation type changes,
Xthen reporting for emulation-specific options is ended.
XIf the host wishes the client to continue
Xreporting changes in some emulation-specific window options,
Xit must send the appropriate ``do'' commands.
X.PP
XWindow option commands are grouped together and transmitted
Xcollectively as part of a P2_FN_WOPT command.
XThat is,
Xthe P2_IAC and P2_FN_WOPT command are immediately
Xfollowed by a variable-length string of bytes
Xwhich contain window option commands for one or
Xmore options.
XThe end of a sequence of window option (sub)commands
Xis indicated by a command which specifies window option zero
X(WOG_END).
X.PP
XAll window option commands begin with a one or two
Xbyte command specifier.
XThe one-byte form is called the ``short'' form,
Xwhile the two-byte form is the ``long'' form:
X.DS
X.ta 8n 32n 48n
X#define	WONUM_MIN	1	/* minimum option number */
X#define	WONUM_GENERIC	7	/* maximum generic option number */
X#define	WONUM_SHORT	14	/* maximum short option number */
X#define	WONUM_MAX	31	/* maximum option number */
X#define	WONUM_MASK	(017<<3)	/* mask for extraction */
X#define	WONUM_SENCODE(n)	(((n)&017)<<3)	/* short encoding function */
X#define	WONUM_SDECODE(b)	(((b)>>3)&017)	/* short decoding function */
X#define	WONUM_LPREFIX	(017<<3)	/*long encoding prefix */
X#define	WONUM_LENCODE(n)	((n)+' ')	/* long encoding function */
X#define	WONUM_LDECODE(c)	(((c)&0177)-' ')	/* long decoding function */
X.DE
XCommands
Xspecifing options whose numbers are in the range WONUM_MIN to WONUM_SHORT
Xmay use the short form.
XIn this case,
Xthe window option number is encoded according to WONUM_SENCODE:
Xit is shifted left by three bits.
XThe command byte consists of a bitwise ``or'' of
Xthe window option command
X(\fIe.g.\fP WOC_INQUIRE)
Xand the encoded short option number.
X.PP
XCommands which specify options whose numbers are greater than WONUM_SHORT
Xmust use the long form.
X(The long form may be used for options whose numbers are less than WONUM_SHORT,
Xbut there is no reason to do so.)
XIn this case,
Xthe first byte contains a bitwise ``or'' of
Xthe window option command
X(\fIe.g.\fP WOC_INQUIRE)
Xand the special prefix WONUM_LPREFIX.
XThe second byte is encoded by WONUM_LENCODE:
Xthe window option number is added to the ASCII code for a space
X(thus this byte is always printable).
X.PP
XAll of the window option commands begin with the
Xone or two byte option command specifier.
XUnlike the other window option commands
X(which use no additional bytes),
Xthe WOC_SET command is followed by encoded data
X(the value of the option).
XOption values are constructed from three primitive
Xdata types
X(as noted above).
X.IP chars 8n
XThe simplest type of data is a fixed-length character vector.
XThis is represented directly.
XThe vector must consist of printable characters.
X[This restriction may be eliminated in the future.
XThe current implementation is able to process non-printable
Xcharacters
X(including XON and XOFF)
Xcorrectly.]
X.IP string
XLike character vectors,
Xstrings have a maximum length.
XHowever,
Xunlike character vectors,
Xstrings may contain non-printing characters.
XAlso,
Xwhile all characters in a character vector are sent,
Xa string may be shorter than its maximum length.
XIt is terminated by a null (000) byte.
X[Hence,
Xa string may not contain an embedded null byte.]
X.IP udata
XThe remaining data type is unsigned integer data.
XThis data has a fixed width measured in bits.
XThe value is encoded in ``little-endian'' fashion
Xinto the low six bits of successive characters.
XThe (octal) 0100 bit of each character is set.
XThe number of characters required to hold an integer
Xvaries from one
X(for data which is one to six bits wide)
Xto six
X(for data which is thirty-two bits wide).
X.PP
XThe window options defined above have arguments as follows
X(all integers are unsigned):
X.IP WOG_VIS 20n
XThis is a 1-bit integer
Xwhich is nonzero iff the window is visible.
X.IP WOG_POS
XThis consists of two 12-bit integers
Xwhich respectively specify the vertical and horizontal
Xoffsets of the window on the client's screen.
X.IP WOG_TITLE
XThis is a string of maximum length 256
Xwhich specifies the window's title.
X.IP WOG_SIZE
XThis consists of two 12-bit integers
Xwhich respectively specify the vertical and horizontal
Xsize of the window on the client's screen
X(in pixels).
X.IP WOTTY_SIZE
XThis consists of two 12-bit integers
Xwhich respectively specify the window size in rows and columns.
X.IP WOTTY_FONTSZ
XThis is a 6-bit integer which is a font size index.
XAt present,
Xit specifies a ``small'' font if zero
Xand a ``large'' font if nonzero.
X.IP WOTTY_MOUSE
XThis is a 1-bit integer
Xwhich is nonzero iff
Xmouse events are to be encoded and sent
Xas data to the host.
X.IP WOTTY_BELL
XThis is a 2-bit integer.
XThe low-order bit is set iff the window should
Xdisplay bells visually;
Xthe other bit is set iff the client should report
Xbells within this window audibly.
X.IP WOTTY_CURSOR
XThis is a 1-bit integer
Xwhich is zero if the window is using a block cursor
Xand nonzero if the window is using an underscore cursor.
X.PP
XOne design decision which the author now regrets
Xis an overloading of the WOTTY_SIZE option.
XIf the host can handle window size changes on pseudo-terminals
X(\fIe.g.\fP 4.3BSD can),
Xthen the client is capable of changing the view size of a window
Xor its actual size,
Xaccording to the user's preference.
XIf the host cannot handle window size changes,
Xthe client does not allow the view size to be changed.
XThe client assumes that the host can handle window size
Xchanges if it receives a WOC_DO command for the WOTTY_SIZE option.
X.SH
XProtocol Negotiation
X.PP
XIt is possible that at some time the versions of a \*(uw server
Xand client will not match;
X.I e.g.
Xa version 2.10 client will be used with a version 3.4 server.
XIt is desirable that such combinations will work ``correctly'' \(em
Xthat the server will communicate with the client using protocol 1
Xrather than trying to use protocol 2.
XIn order to accomplish this,
Xthree new maintenance functions
Xare defined by which the server and client
Xmay negotiate the protocol which is to be used.
XVersion 3 clients and servers recognize these maintenance
Xfunctions in both protocol 1 and protocol 2.
XOlder clients and servers do not recognize these functions
Xat all.
X.PP
XThe protocol negotiation maintenance functions were
Xdescribed above for protocol 2.
XThey are repeated here for protocol 1
X(the encodings are identical):
X.DS
X.T=
X#define	P1_MF_ASKPCL	2	/*	request protocol negotiation */
X#define	P1_MF_CANPCL	3	/*	suggest protocol */
X#define	P1_MF_SETPCL	4	/*	set new protocol */
X.DE
XP1_MF_ASKPCL is encoded in a single command byte
X(following P1_IAC).
XThe P1_MF_CANPCL and P1_MF_SETPCL command bytes are
Xfollowed by an additional byte which names a protocol.
XFor the purposes of protocol negotiation,
Xprotocols 1 and 2 are represented by the ASCII
Xcharacters space and exclamation-mark,
Xrespectively.
X.PP
XThe client and server always start operation in protocol 1.
X(The user may have instructed the client to use protocol 2;
Xnonetheless,
Xit will use protocol 1 until protocol negotiations are complete.)
XWhen the server is started
Xit will send a P1_MF_ENTRY maintenance command to the client.
XIf the client knows about protocol 2 and wishes to use it,
Xit will send a P1_MF_ASKPCL to the server.
XIf the client does not know about protocol 2,
Xit will not send P1_MF_ASKPCL,
Xprotocol negotiation will never be started,
Xand both sides will continue to use protocol 1.
X.PP
XIf the server can support something other than protocol 1
Xit will respond to the P1_MF_ASKPCL with a
XP1_MF_CANPCL which names the most extensive protocol that it can support.
X(At present,
Xthis will be protocol 2;
Xhowever,
Xin the future it might name some other protocol.)
XOld servers,
Xwhich do not recognize P1_MF_ASKPCL,
Xwill ignore the maintenance function.
XThe client will time out after five seconds
Xand retry several times
X(three in the present implementation);
Xif the server never responds
Xthe client will ``give up'' and will
Xcontinue to use protocol 1 indefinitely.
X.PP
XWhen the client receives P1_MF_CANPCL from the server,
Xit will examine the server's suggested protocol.
XIf this protocol is unacceptable to the client,
Xit will respond with its own P1_MF_CANPCL,
Xnaming the most extensive protocol that it can support.
XThe server,
Xupon receipt of this P1_MF_CANPCL,
Xwill examine the client's suggested protocol.
XIf it is unacceptable to the server,
Xit will name the second-most extensive protocol that it can support.
XEach time that the client or server receives a
XP1_MF_CANPCL that names a protocol it cannot support,
Xit will respond with a different,
Xless extensive suggestion of its own.
XSince the number of protocols is finite,
Xeventually someone will suggest protocol 1,
Xwhich both sides are required to support.
X.PP
XWhen the client or server receives a P1_MF_CANPCL
Xthat names a protocol that it
X.I can
Xsupport,
Xit will instruct its counterpart to start using that protocol
Xby sending a P1_MF_SETPCL that names that protocol.
XHenceforth,
Xthe new protocol will be used.
X.PP
XProtocol 2 allows the client to send a P2_MF_ENTRY
Xmaintenance command to the server.
X(This is encoded identically to a P1_MF_ENTRY command.)
XIf the server receives this maintenance command and
Xit is using a protocol other than protocol 1,
Xit will immediately respond with a P1_FN_SETPCL which
Xnames the protocol that it is using.
XIt will then proceed to send ``new window'' and
X(if applicable)
X``window option'' commands to the client
Xto reconstruct the client's current state.
X.SH
XPostscript
X.PP
XThere are a number of obvious problems with the mechanism
Xfor protocol negotiation.
XIt is possible for one party to send a SETPCL
Xcommand and begin listening for input in a new protocol
Xwhile it is still receiving buffered commands in the old protocol
Xfrom the other party.
XIt probably would have been better to have established
Xa ``current protocol'',
Xsimilar to the ``current window'' scheme used for data transfer.
XThis scheme was born out of the desire to allow
Xold servers and clients to work with new ones.
XIt ``works'' if things are relatively quiescent,
Xas they are when the server first starts up
X(before it creates its first window).
X.PP
XThis document is still incomplete.
XAt this time it is more useful as a conceptual guide
Xto the \*(uw protocol
Xthan a definitive reference.
X.SH
XCopyright
X.LP
XThis document copyright 1986 by John D. Bruner.
XPermission to copy is given,
Xprovided that the copies are not sold
Xand that this copyright notice is included.
SHAR_EOF
if test 24952 -ne "`wc -c < 'doc/uwproto.ms'`"
then
	echo shar: error transmitting "'doc/uwproto.ms'" '(should have been 24952 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'doc/uwplot.l'" '(2042 characters)'
if test -f 'doc/uwplot.l'
then
	echo shar: will not over-write existing file "'doc/uwplot.l'"
else
sed 's/^X//' << \SHAR_EOF > 'doc/uwplot.l'
X.TH UWPLOT 1 "28 April 1987"
X.UC 4
X.SH NAME
Xuwplot \- plot filter for use with UW
X.SH SYNOPSIS
X.B uwplot
X[
X.BI \-t title
X] [
X.BI \-n serveraddr
X]
X.SH DESCRIPTION
X.I Uwplot
Xis a utility program for use with the
X.I uw
Xmultiple-window interface to UNIX.
XIt creates a window,
Xreads plotting instructions from the standard input,
Xand displays the result in the window.
X(The plotting commands are produced by programs
Xwhich use the standard UNIX
X.I plot
Xpackage.)
X.PP
XThe title of the newly-created window may be
Xspecified with the `\-t' option.
XIf this option is omitted,
Xthe title will be the name of the command
Xwhich created it
X(\fIi.e.\fP `uwplot').
X.PP
XNormally
X.I uwplot
Xwill examine the environment for the variable `UW_INET'
Xand will connect to the
X.I uw
Xserver with that address.
XThe `\-n' flag can be used to specify an alternate
Xserver network address.
XThe address should have the form `xxxxxxxx.ddd'
Xwhere `x' is a hexadecimal digit
Xand `d' is a decimal digit.
XThe hexadecimal number is the host's Internet address
Xand the decimal number is the port on which the
Xserver is listening for connections.
X.PP
X`linemod' commands in the plot file are
Xintended to select the color in which the
Xplot is drawn;
Xhowever, this feature is untested.
XThe old-model Quickdraw colors may be
Xspecified by name
X(all lower-case).
XThe standard plot linemod names are mapped to
Xcolors as follows:
X.sp
X.nf
X.ta 1i
Xblack	solid
Xred	shortdashed
Xgreen	dotdashed
Xblue	longdashed
Xyellow	dotted
X.fi
X.PP
XThe present implementation on the Macintosh
Xis a square window with vertical and horizontal
Xdimensions of 300 pixels.
XArcs are not drawn correctly when
Xthe vertical and horizontal scaling factors
Xare unequal.
X.SH LIMITATIONS
X.I Uwterm 
Xis of no use on unix unless 
Xthe server is running and
X.I uw
Xis being run on the Macintosh.
X.SH SEE ALSO
Xplot(1G), plot(3X), plot(5), uw(L)
X.br
X.I uw
XMacintosh documentation
X(`UW \(em A Multiple-Window Interface to UNIX')
X.br
X`The UW Programmer's Library'
X.SH AUTHOR
XJohn Bruner, Lawrence Livermore National Laboratory, 10/86.
SHAR_EOF
if test 2042 -ne "`wc -c < 'doc/uwplot.l'`"
then
	echo shar: error transmitting "'doc/uwplot.l'" '(should have been 2042 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'doc/uwterm.l'" '(2858 characters)'
if test -f 'doc/uwterm.l'
then
	echo shar: will not over-write existing file "'doc/uwterm.l'"
else
sed 's/^X//' << \SHAR_EOF > 'doc/uwterm.l'
X.TH UWTERM 1 "20 September 1986"
X.UC 4
X.SH NAME
Xuwterm \- (possibly remote) terminal emulation for UW
X.SH SYNOPSIS
X.B uwterm
X[
X.BI \-w type
X] [
X.BI \-t title
X] [
X.BI \-n serveraddr
X] [
X.BI \-l loginname
X] [ host ]
X.SH DESCRIPTION
X.I Uwterm
Xis a utility program for use with the
X.I uw
Xmultiple-window interface to UNIX.
XIt creates a window in which a terminal session
Xis conducted.
XIf no arguments are given
Xthe terminal is created on the local machine.
XA hostname may be specified;
Xin this case,
Xthe terminal is created on the remote host.
X.RI ( Uwterm
Xmust be installed on the remote host
Xand permissions for
X.I rsh
Xmust have been set up correctly
Xin order for this to work.)
X.I Uwterm
Xexamines the `SHELL' environment variable
Xand executes the program named there.
XThe `\-l' option
Xcan be used to specify the login name under which
Xthe remote process will be executed
X(the default is the current account).
X.PP
XUnlike
X.IR uwtool ,
X.I uwterm
Xdoes not exit until the window it has created
Xis destroyed;
Xhence,
Xit will usually be desirable to run it in the background.
X.PP
XNormally,
Xthe terminal type of the new window is inherited from
Xthe window in which
X.I uwterm
Xis run.
XIt is possible to override this with the `\-w' option
X(`w' stands for `window emulation type').
XThe window types are the same as those accepted by the
X.I uwtool
Xprogram.
X.PP
XThe title of the newly-created window may be
Xspecified with the `\-t' option.
XIf this option is omitted,
Xthe title will be the host name.
X.PP
XNormally
X.I uwterm
Xwill examine the environment for the variable `UW_INET'
Xand will connect to the
X.I uw
Xserver with that address.
XThe `\-n' flag can be used to specify an alternate
Xserver network address.
XThe address should have the form `xxxxxxxx.ddd'
Xwhere `x' is a hexadecimal digit
Xand `d' is a decimal digit.
XThe hexadecimal number is the host's Internet address
Xand the decimal number is the port on which the
Xserver is listening for connections.
XThe `\-n' flag is used by
X.I uwterm
Xitself:
Xit creates a remote terminal by invoking itself on
Xthe remote machine
X(using
X.IR rsh )
Xand specifying the network address
Xof the local server.
X.SH LIMITATIONS
X.I Uwterm 
Xis of no use on unix unless 
Xthe server is running and
X.I uw
Xis being run on the Macintosh.
X.br
XIf there is a stream of output in one window there will be lag in 
Xrecognizing characters typed in another.
X.br
XThere are so many levels of buffering
Xthat user-entered CTL-S/CTL-Q flow control is
Xpractically useless,
Xeven at relatively low baud rates.
X.SH SEE ALSO
Xrsh(1), uw(L), uwtitle(L), uwtool(L)
X.br
X.I uw
XMacintosh documentation
X(`UW \(em A Multiple-Window Interface to UNIX')
X.br
X`The UW Programmer's Library'
X.SH AUTHOR
XJohn Bruner, Lawrence Livermore National Laboratory, 9/86.
X.SH BUGS
XThere are so many levels of buffering that typing
XXON and XOFF
Xto suspend output within a window
Xis futile.
SHAR_EOF
if test 2858 -ne "`wc -c < 'doc/uwterm.l'`"
then
	echo shar: error transmitting "'doc/uwterm.l'" '(should have been 2858 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'doc/uwtitle.l'" '(850 characters)'
if test -f 'doc/uwtitle.l'
then
	echo shar: will not over-write existing file "'doc/uwtitle.l'"
else
sed 's/^X//' << \SHAR_EOF > 'doc/uwtitle.l'
X.TH UWTITLE 1 "14 September 1986"
X.UC 4
X.SH NAME
Xuwtitle \- retitle UW window
X.SH SYNOPSIS
X.B uwtitle
X[
X.BI \-i id
X]
Xstring ...
X.SH DESCRIPTION
X.I Uwtitle
Xis a utility program for use with the
X.I uw
Xmultiple-window interface to UNIX.
XIt retitles an existing window.
XThe title is specified as one or more
Xstrings
X(in the same fashion as arguments to the
X.I echo
Xprogram).
XThe `\-i' option can be used to specify
Xthe ID of the window to be retitled;
Xotherwise,
Xthe current window will be affected.
X.SH LIMITATIONS
X.I Uwtitle 
Xis of no use on unix unless 
Xthe server is running and
X.I uw
Xis being run on the Macintosh.
X.SH SEE ALSO
Xecho(1), uw(L), uwtool(L), uwterm(L)
X.br
X.I uw
XMacintosh documentation (`UW \(em A Multiple-Window Interface to UNIX')
X.br
X`The UW Programmer's Library'
X.SH AUTHOR
XJohn Bruner, Lawrence Livermore National Laboratory 9/86
SHAR_EOF
if test 850 -ne "`wc -c < 'doc/uwtitle.l'`"
then
	echo shar: error transmitting "'doc/uwtitle.l'" '(should have been 850 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'doc/uwtool.l'" '(2334 characters)'
if test -f 'doc/uwtool.l'
then
	echo shar: will not over-write existing file "'doc/uwtool.l'"
else
sed 's/^X//' << \SHAR_EOF > 'doc/uwtool.l'
X.TH UWTOOL 1 "14 September 1986"
X.UC 4
X.SH NAME
Xuwtool \- command-in-window utility for UW
X.SH SYNOPSIS
X.B uwtool
X[
X.BI \-w type
X] [
X.BI \-t title
X] [
X.B \-v
X] [ command [ arg1 arg2 ...  ] ]
X.SH DESCRIPTION
X.I Uwtool
Xis a utility program for use with the
X.I uw
Xmultiple-window interface to UNIX.
XIf no arguments are given,
Xit creates a new `terminal' running the shell named in the
Xenvironment variable `SHELL'.
XIf a process is named,
Xit will create a new window with that process running in it,
Xand when that process is terminated the window will disappear.
X(i.e. `uwtool vi foo' will create a new window with vi,
Xediting the file foo,
Xbut the window will go away when vi is exited)  
XAny arguments after the process name are passed as arguments to that process.
X.I Uwtool
Xexits as soon as the window is created.
X.PP
XNormally,
Xthe terminal type of the new window is inherited from
Xthe window in which
X.I uwtool
Xis run.
XIt is possible to override this with the `\-w' option
X(`w' stands for `window emulation type').
XThe following values are recognized:
X.TP 8n
Xadm31
XLear Siegler ADM-31
X.TP
Xadm3a
XLear Siegler ADM-3a (uses ADM-31)
X.TP
Xtek4010
XTektronix 4010
X.TP
Xtek
XTektronix 4010
X.TP
Xvt52
XDigital Equipment Corporation VT-52
X.TP
Xansi
XANSI-compatible terminal
X.TP
Xaaa-24
X24-line Ann Arbor Ambassador
X(uses ANSI emulation)
X.PP
XIf an unknown type is specified,
Xthe ADM-31 emulation will be used.
X.PP
XThe title of the newly-created window may be
Xspecified with the `\-t' option.
XIf this option is omitted,
Xthe window title will be the command name.
X.PP
XThe `\-v' flag causes
X.I uwtool
Xto print the 32-bit window identifier on
Xthe standard output.
XThis value can be used as an argument to a subsequent
Xcommand,
Xfor example
X.IR uwtitle .
X.SH LIMITATIONS
X.I Uwtool 
Xis of no use on unix unless 
Xthe server is running and
X.I uw
Xis being run on the Macintosh.
X.br
XIf there is a stream of output in one window there will be lag in 
Xrecognizing characters typed in another.
X.SH SEE ALSO
Xuw(L), uwtitle(L), uwterm(L)
X.br
X.I uw
XMacintosh documentation
X(`UW \(em A Multiple-Window Interface to UNIX')
X.br
X`The UW Programmer's Library'
X.SH AUTHOR
XProgram written by John Bruner, Lawrence Livermore Laboratories 7/85,11/85,9/86
X.br
XThis document is based upon a document created by
Xby Chris Borton, UC San Diego 11/13/85,
Xedited 9/86 by John Bruner.
SHAR_EOF
if test 2334 -ne "`wc -c < 'doc/uwtool.l'`"
then
	echo shar: error transmitting "'doc/uwtool.l'" '(should have been 2334 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 2 ---

jdb@mordor.s1.gov (John Bruner) (04/05/88)

[UW v4.2 - part 3 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	h/openpty.h
#	h/uw_clk.h
#	h/uw_err.h
#	h/uw_fd.h
#	h/uw_ipc.h
#	h/uw_opt.h
#	h/uw_param.h
#	h/uw_pcl.h
#	h/uw_win.h
#	h/uwlib.h
# This archive created: Mon Apr  4 07:51:49 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d h
then
	echo shar: mkdir h
	mkdir h
fi
echo shar: extracting "'h/openpty.h'" '(308 characters)'
if test -f 'h/openpty.h'
then
	echo shar: will not over-write existing file "'h/openpty.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/openpty.h'
X/*
X *	This file defines the "ptydesc" structure which is returned
X *	by the routine "openpty".
X */
X
Xstruct ptydesc {
X	int		pt_pfd;		/* file descriptor of master side */
X	int		pt_tfd;		/* file descriptor of slave side */
X	char		*pt_pname;	/* master device name */
X	char		*pt_tname;	/* slave device name */
X};
SHAR_EOF
if test 308 -ne "`wc -c < 'h/openpty.h'`"
then
	echo shar: error transmitting "'h/openpty.h'" '(should have been 308 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uw_clk.h'" '(1161 characters)'
if test -f 'h/uw_clk.h'
then
	echo shar: will not over-write existing file "'h/uw_clk.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uw_clk.h'
X/*
X *	uw_clk - timer support for UW
X *
X * Copyright 1986 by John D. Bruner.  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#ifndef UW_CLK
X#define	UW_CLK
X
X/*
X * Events which are supposed to occur at a certain time are handled by
X * setting "timeout"s.  The list of timeouts is sorted in order of
X * occurrence.  The "alarm" mechanism is used to send SIGALRM when the
X * first timeout expires.  However, the timeout is not processed
X * immediately.  Instead, it will be processed upon exit from the
X * select() in main().  This prevents timeouts from happening at
X * inappropriate times.
X *
X * The resolution of timeouts is in seconds.  The server doesn't need
X * any better resolution, and this allows all of the hair associated with
X * (struct timeval) and (struct itimerval) types to be avoided.
X */
X
X#define	CLK_HZ		1		/* one tick/second */
X
Xtypedef long toarg_t;
X
Xstruct timeout {
X	struct timeout	*to_next;
X	time_t		to_when;
X	void		(*to_fn)();
X	toarg_t		to_arg;
X};
X
Xextern int timer_rdy;
X
X#define	CLK_CHECK()	if (timer_rdy) clk_service(); else
X#endif
SHAR_EOF
if test 1161 -ne "`wc -c < 'h/uw_clk.h'`"
then
	echo shar: error transmitting "'h/uw_clk.h'" '(should have been 1161 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uw_err.h'" '(759 characters)'
if test -f 'h/uw_err.h'
then
	echo shar: will not over-write existing file "'h/uw_err.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uw_err.h'
X/*
X *	uw error codes
X *
X * Copyright 1986 by John D. Bruner.  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#ifndef UW_ERR
X#define	UW_ERR
X
Xtypedef int uwerr_t;
X
X#define	UWE_NONE	0		/* no error */
X#define	UWE_ERRNO	1		/* system call error, consult errno */
X#define	UWE_NXTYPE	2		/* nonexistent window type */
X#define	UWE_DUPID	3		/* window ID duplicated (in use) */
X#define	UWE_NOTIMPL	4		/* operation not implemented yet */
X#define	UWE_NXSERV	5		/* non-existent server */
X#define	UWE_NOMEM	6		/* unable to allocate required memory */
X#define	UWE_INVAL	7		/* invalid argument to function */
X#define	UWE_NOCTL	8		/* no control file descriptor */
X
X#endif
SHAR_EOF
if test 759 -ne "`wc -c < 'h/uw_err.h'`"
then
	echo shar: error transmitting "'h/uw_err.h'" '(should have been 759 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uw_fd.h'" '(1488 characters)'
if test -f 'h/uw_fd.h'
then
	echo shar: will not over-write existing file "'h/uw_fd.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uw_fd.h'
X/*
X *	uw_fd - file-descriptor/select data
X *
X * Copyright 1986 by John D. Bruner.  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#ifndef UW_FD
X#define	UW_FD
X
X#include "uw_param.h"
X
X/*
X * If FD_SET and friends aren't defined in <sys/types.h>, then we
X * provide simple definitions here.
X */
X#ifndef FD_SET
X#define	FD_SET(n,p)	((p)->fds_bits[0] |= (1 << (n)))
X#define	FD_CLR(n,p)	((p)->fds_bits[0] &= ~(1 << (n)))
X#define	FD_ISSET(n,p)	((p)->fds_bits[0] & (1 << (n)))
X#define	FD_ZERO(p)	((p)->fds_bits[0] = 0)
X#define	FD_SETSIZE	(NBBY*sizeof(long))
X#endif
X
X/*
X * We use file descriptors for several different things.  "fdmap" associates
X * a file descriptor number with its use.
X */
Xtypedef enum {				/* file descriptor type */
X	FDT_NONE,			/*	not in use */
X	FDT_DATA,			/*	data connection for window */
X	FDT_CTL,			/*	control connection for window */
X	FDT_MAC,			/*	tty line which talks to Mac */
X	FDT_UDSOCK,			/*	UNIX-domain datagram socket */
X	FDT_ISSOCK,			/*	Internet-domain stream sock */
X	FDT_DEBUG,			/*	debugging use */
X	FDT_OTHER			/*	other uses */
X} fdtype_t;
X
Xstruct fdmap {
X	fdtype_t	f_type;		/* file descriptor type */
X	struct window	*f_win;		/* associate window (if any) */
X};
X
Xstruct selmask {
X	struct fd_set	sm_rd;
X	struct fd_set	sm_wt;
X	struct fd_set	sm_ex;
X};
X
Xextern struct fdmap fdmap[FD_SETSIZE];
Xextern fildes_t nfds;
Xextern struct selmask selmask[2];
X#endif
SHAR_EOF
if test 1488 -ne "`wc -c < 'h/uw_fd.h'`"
then
	echo shar: error transmitting "'h/uw_fd.h'" '(should have been 1488 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uw_ipc.h'" '(5403 characters)'
if test -f 'h/uw_ipc.h'
then
	echo shar: will not over-write existing file "'h/uw_ipc.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uw_ipc.h'
X/*
X *	uw IPC definitions
X *
X * Copyright 1986 by John D. Bruner.  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#ifndef UW_IPC
X#define	UW_IPC
X
X/*
X * UW accepts network connections in both the UNIX domain and the
X * Internet domain.  UNIX domain datagrams are used by processes on
X * the local machine to create new windows and to change the value
X * of window parameters (window options).  TCP (Internet stream)
X * connections are used by local and non-local processes which wish
X * to handle their own host activity (e.g. pseudo-terminal handling).
X *
X * Some of the definitions in this file duplicate definitions in the
X * UW server source code, because this file is also intended for use
X * with the UW library.
X *
X * The code which performs byte-order conversions knows the size of the
X * types defined in this file (since there is no typeof() operator).
X */
X
X#define	UIPC_ENV	"UW_UIPC"	/* Unix-domain port environment var */
X#define	INET_ENV	"UW_INET"	/* Internet-domain port environ var */
X
Xtypedef long uwid_t;			/* unique window identifier */
X
Xtypedef short uwcmd_t;			/* commands: */
X#define	UWC_NEWW	0		/*	create new window */
X#define	UWC_NEWT	1		/*	create new tty window */
X#define	UWC_STATUS	2		/*	creation status message */
X#define	UWC_KILLW	3		/*	kill existing window */
X#define	UWC_OPTION	4		/*	act upon window option */
X
Xtypedef short uwoptcmd_t;		/* option subcommands: */
X#define	UWOC_SET	0		/*	set value of option */
X#define	UWOC_ASK	2		/*	ask for value of option */
X#define	UWOC_DO		4		/*	report changes in value */
X#define	UWOC_DONT	5		/*	don't report changes */
X#define	UWOC_WILL	6		/*	will report changes */
X#define	UWOC_WONT	7		/*	won't report changes */
X
Xtypedef short uwtype_t;			/* window type (see also uw_win.h): */
X#define	UWT_ADM31	0		/*	ADM-31 */
X#define	UWT_VT52	1		/*	VT-52 */
X#define	UWT_ANSI	2		/*	ANSI */
X#define	UWT_TEK4010	3		/*	Tektronix 4010 */
X#define	UWT_FTP		4		/*	file transfer */
X#define	UWT_PRINT	5		/*	output to Macintosh printer */
X#define	UWT_PLOT	6		/*	plot window */
X
Xtypedef short uwopt_t;			/* window option number: */
X#define	UWOP_VIS	1		/*	visibility */
X#define	UWOP_TYPE	2		/*	window type */
X#define	UWOP_POS	3		/*	window position */
X#define	UWOP_TITLE	4		/*	window title */
X#define	UWOP_WSIZE	5		/*	window size (in bits) */
X
X#define	UWOP_TSIZE	8		/*	terminal size (row,col) */
X#define	UWOP_TFONTSZ	9		/*	small/large font size */
X#define	UWOP_TCLIPB	10		/*	clipboard/mouse encoding */
X#define	UWOP_TBELL	11		/*	audible, visual bell */
X#define	UWOP_TCURS	12		/*	cursor shape */
X
Xunion uwoptval {
X	unsigned char	uwov_1bit;
X	unsigned char	uwov_6bit;
X	unsigned short	uwov_12bit;
X	struct {
X		unsigned short v,h;
X	}		uwov_point;
X	char		uwov_string[256];
X};
X
X
X/*
X * UWC_NEWW: create a new window
X *
X * This command is only valid when it is sent as the first message on an
X * Internet stream socket.  The remote port is the data fd for the window.
X * If a control fd is desired, its port number is contained in "uwnt_ctlport"
X */
Xstruct uwneww {
X	uwid_t		uwnw_id;	/* unique window identifier */
X	uwtype_t	uwnw_type;	/* window type */
X	short		uwnw_ctlport;	/* port number of control fd */
X};
X
X/*
X * UWC_NEWT: create a new tty window
X *
X * This command is only valid when it is sent as a datagram to the Unix-domain
X * socket.  It must be accompanied by an access right (file descriptor) for
X * the master side of a pty.  The server takes over all responsibilities for
X * this window.  "uwnt_pty" is variable-length.
X */
Xstruct uwnewt {
X	uwid_t		uwnt_id;	/* unique window identifier */
X	uwtype_t	uwnt_type;	/* window type */
X	char		uwnt_pty[1];	/* name of associated pty */
X};
X
X/*
X * UWC_STATUS: status report for UWC_NEWW
X *
X * This type of packet is sent by the server to the data fd in response
X * to a UWC_NEWW.  It specifies whether the window was successfully
X * created and what unique ID was assigned.
X */
Xstruct uwstatus {
X	uwid_t		uwst_id;	/* unique window identifier */
X	short		uwst_err;	/* error status */
X	short		uwst_errno;	/* UNIX error code (see <errno.h>) */
X};
X
X/*
X * UWC_KILLW: kill the window
X *
X * This command may be sent to either the Unix-domain socket or the control
X * file descriptor of an external window.  In the latter case, "uwkw_id"
X * must match the ID of the window associated with the file descriptor.
X */
Xstruct uwkillw {
X	uwid_t		uwkw_id;	/* unique window identifier */
X};
X
X/*
X * UWC_OPTION: act upon window option
X *
X * This command may be sent to either the Unix-domain socket or the control
X * file descriptor of an external window.  In the former case, only the
X * UWOC_SET command is processed.
X */
Xstruct uwoption {
X	uwid_t		uwop_id;	/* unique window identifier */
X	uwopt_t		uwop_opt;	/* option number */
X	uwoptcmd_t	uwop_cmd;	/* option subcommand */
X	union uwoptval	uwop_val;	/* option value (for UWOC_SET) */
X};
X
Xstruct uwipc {
X	unsigned short	uwip_len;	/* length of this message */
X	uwcmd_t		uwip_cmd;	/* command (message type) */
X	union {
X		struct uwneww uwipu_neww;
X		struct uwnewt uwipu_newt;
X		struct uwstatus uwipu_status;
X		struct uwkillw uwipu_killw;
X		struct uwoption uwipu_option;
X	}		uwip_u;
X#define	uwip_neww	uwip_u.uwipu_neww
X#define	uwip_newt	uwip_u.uwipu_newt
X#define	uwip_status	uwip_u.uwipu_status
X#define	uwip_killw	uwip_u.uwipu_killw
X#define	uwip_option	uwip_u.uwipu_option
X};
X
X#endif
SHAR_EOF
if test 5403 -ne "`wc -c < 'h/uw_ipc.h'`"
then
	echo shar: error transmitting "'h/uw_ipc.h'" '(should have been 5403 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uw_opt.h'" '(6447 characters)'
if test -f 'h/uw_opt.h'
then
	echo shar: will not over-write existing file "'h/uw_opt.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uw_opt.h'
X/*
X *	uw window options
X *
X * Copyright 1986 by John D. Bruner.  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 * Some protocols support the transmission of window options.  A window
X * option is a parameter (or collection of related parameters) which
X * describes the layout, appearance, or other characteristic of a
X * window.  Some options are common to all window types, while others
X * are window emulation-specific.
X *
X * Window options may be "set" by one side on its own initiative or in
X * response to an "inquiry" from the other side.  In addition, one side
X * may request that the other side "report" changes in options.
X *
X * Options are passed as part of a "new window" command or as part of
X * an "option" command (as defined by the protocol, above).  The option
X * format has been chosen to minimize the need for protocol encoding
X * of special or meta characters.
X */
X
X#ifndef	UW_OPT
X#define	UW_OPT
X
Xtypedef unsigned int woptcmd_t;		/* window option command: */
X#define	WOC_SET		0		/*	request current option value */
X#define	WOC_INQUIRE	2		/*	report current option value */
X#define	WOC_DO		4		/*	do report changes to option */
X#define	WOC_DONT	5		/*	don't report changes */
X#define	WOC_WILL	6		/*	will report changes */
X#define	WOC_WONT	7		/*	won't report changes */
X#define	WOC_MASK	7		/*	mask */
X#define	WOC_BADCMD(n)	((n)==1 || (n)==3)
X
X/*
X * Option commands include an option number specifier.  If the option
X * number is in the range 1-14 a short-form specifier can be used;
X * otherwise, a long-form specifier must be used.  Option (sub)command
X * bytes consist of 7 bits of data.  The lower order 3 bits specify the
X * option command.  The next higher 4 bits specify the option number.
X * The value zero is reserved (as described below).  If the option
X * number is greater than 14, these four bits specify 017 (15) and the
X * option number is specified in a second byte.  The value is encoded
X * by adding ' ' to the option number.  Multiple options may be specified
X * in one command -- the last option is followed by a reference to
X * "option" 0 (as an endmarker).
X */
X
Xtypedef unsigned int woption_t;		/* window option number: */
X#define	WONUM_MIN	1		/*	minimum option number */
X#define	WONUM_GENERIC	7		/*	maximum generic option number */
X#define	WONUM_SHORT	14		/*	maximum short option number */
X#define	WONUM_MAX	31		/*	maximum option number */
X#define	WONUM_MASK	(017<<3)	/*	mask for extraction */
X#define	WONUM_USELONG(n) ((unsigned)(n) > WONUM_SHORT)
X#define	WONUM_SENCODE(n) (((n)&017)<<3)	/* 	short encoding function */
X#define	WONUM_SDECODE(b) (((b)>>3)&017)	/* 	short decoding function */
X#define	WONUM_LPREFIX	(017<<3)	/*	long encoding prefix */
X#define	WONUM_LENCODE(n) ((n)+' ')	/* 	long encoding function */
X#define	WONUM_LDECODE(c) (((c)&0177)-' ') /* 	long decoding function */
X
X
X/*
X * The following option numbers are generic (recognized for all window
X * types):
X */
X#define	WOG_END		0		/* [endmarker] */
X#define	WOG_VIS		1		/* 0=invisible, 1=visible */
X#define	WOG_TYPE	2		/* window emulation type (see below) */
X#define	WOG_POS		3		/* window position on screen */
X#define	WOG_TITLE	4		/* window title */
X#define	WOG_SIZE	5		/* window size (in bits) */
X#define	WOG_6		6		/* unassigned, reserved */
X#define	WOG_7		7		/* unassigned, reserved */
X
X/*
X * Option arguments immediately follow option (sub)command bytes.  They are
X * encoded to prevent interference with flow-control and IAC recognition.
X * Three types of options are recognized: non-graphic character strings of
X * fixed length, general character strings of variable length, and binary
X * numbers of fixed width.
X *
X * Non-graphic character strings are transmitted directly.  They CANNOT
X * include IAC, XON, or XOFF and should not include "meta" characters.
X *
X * General character strings are encoded in the UW protocol fashion: "meta"
X * characters and special characters are escaped.  The string is terminated
X * with a null byte.  The string may not exceed some predetermined maximum
X * number of characters (which may be less than or equal to 256, including
X * the terminating null byte).
X *
X * Binary numbers are transmitted in 6-bit chunks, least-significant bits
X * first.  The number of 6-bit chunks required depends upon the width of
X * the number.  The 0100 bit in each byte is always set to prevent
X * collisions with special characters (such as flow control and IAC).
X */
X
X/*
X * Implementation:
X *
X * Arrays of type "woptarg_t" are used to describe the arguments associated
X * with each option.  (Note that arguments are associated only with
X * the "set" option subcommand.)
X */
X
Xtypedef unsigned woptarg_t;		/* option argument type: */
X#define	WOA_END		0		/*	endmarker */
X#define	WOA_CHARS(n)	((1<<8)|(n))	/*	"n" untranslated characters */
X#define	WOA_STRING(m)	((2<<8)|(m))	/*	string of max length "m" */
X#define	WOA_UDATA(b)	((3<<8)|(b))	/*	binary number "b" bits wide */
X#define	WOA_CMDMASK	0177400		/* command mask */
X
Xtypedef long woptbmask_t;		/* option bitmask (>= 32 bits wide) */
X#define	WOPT_SET(mask,bit)	((mask) |= (1<<(bit)))
X#define	WOPT_CLR(mask,bit)	((mask) &= ~(1<<(bit)))
X#define	WOPT_ISSET(mask,bit)	((mask) & (1<<(bit)))
X
Xstruct woptdefn {
X	woptbmask_t	wod_pending;	/* pending notifications to Mac */
X	woptbmask_t	wod_inquire;	/* pending inquiries from Mac */
X	woptbmask_t	wod_do;		/* pending DO commands to Mac */
X	woptbmask_t	wod_dont;	/* pending DONT commands to Mac */
X	woptbmask_t	wod_askrpt;	/* reports (of changes) we ask for */
X	struct woptlst {
X		woptarg_t	*wol_argdefn;	/* option argument definition */
X		char		*(*wol_get)();	/* called to get option value */
X		void		(*wol_set)();	/* called to set option value */
X		void		(*wol_ext)();	/* called for external window */
X	}		wod_optlst[WONUM_MAX+1];
X};
X
X/*
X * The following structure is used by routines that fetch and set option
X * values.
X */
Xunion optvalue {
X	unsigned char	ov_udata1;
X	unsigned char	ov_udata2;
X	unsigned char	ov_udata6;
X	unsigned short	ov_udata12;
X	struct {
X		unsigned short	v,h;
X	}		ov_point;
X	char		ov_string[256];
X};
X
X/*
X * When it is necessary to convert between host byte order and network
X * byte order, opt_netadj() is called.  A pointer to the following
X * structure is passed.
X */
Xstruct netadj {
X	short		(*na_short)();
X	long		(*na_long)();
X	unsigned short	(*na_ushort)();
X	unsigned long	(*na_ulong)();
X};
X
X#endif
SHAR_EOF
if test 6447 -ne "`wc -c < 'h/uw_opt.h'`"
then
	echo shar: error transmitting "'h/uw_opt.h'" '(should have been 6447 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uw_param.h'" '(1006 characters)'
if test -f 'h/uw_param.h'
then
	echo shar: will not over-write existing file "'h/uw_param.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uw_param.h'
X/*
X *	uw parameters
X *
X * Copyright 1986 by John D. Bruner.  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/*
X * This file exists because #include file definitions aren't in the same
X * place on all machines.  Also, it seems pointless to drag in all of
X * <stdio.h> just to define NULL.  Finally, a few declarations are
X * sufficiently global that this is the most logical place to put them.
X *
X * This file should be #included after all of the system include files
X * (e.g. <sys/types.h>) but before any other UW include files.
X */
X#ifndef UW_PARAM
X#define	UW_PARAM
X
Xtypedef int fildes_t;		/* this really should be in <sys/types.h> */
X
X#ifndef NBBY			/* this is in <sys/types.h> in 4.3BSD */
X#define	NBBY	8		/* (number of bits/byte) */
X#endif
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
Xextern char *malloc();
Xextern char *mktemp();
Xextern char *getenv();
Xextern void done();
Xextern void cwait();
X
X#endif
SHAR_EOF
if test 1006 -ne "`wc -c < 'h/uw_param.h'`"
then
	echo shar: error transmitting "'h/uw_param.h'" '(should have been 1006 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uw_pcl.h'" '(9801 characters)'
if test -f 'h/uw_pcl.h'
then
	echo shar: will not over-write existing file "'h/uw_pcl.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uw_pcl.h'
X/*
X *	uw protocol
X *
X * Copyright 1985,1986 by John D. Bruner.  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#ifndef UW_PCL
X#define	UW_PCL
X
X#include "uw_win.h"
X
X/* UW may operate over connections which speak one of several protocols.
X * Internally these protocols are assigned numbers starting at zero.
X * Three such protocols are currently defined:
X *
X *	0: no special protocol
X *	1: original UW (v1.6, v2.10) protocol
X *	2: extended protocol (v3.x)
X */
X
X/*
X * Protocol 0:
X *
X * The connection between the Macintosh and the host is simply a serial
X * line.  Flow control may be enabled, but no special commands are
X * recognized.  Only one active window is supported.  This "protocol"
X * does not require the UW server; hence, there is no need to support it.
X */
X
X/*
X * Protocol 1: (original UW protocol)
X *
X * Two types of information are exchanged through the 7-bit serial line:
X * ordinary data and command bytes.  Command bytes are preceeded by
X * an IAC byte.  IAC bytes and literal XON/XOFF characters (those which
X * are not used for flow control) are sent by a P1_FN_CTLCH command.
X * Characters with the eighth bit set (the "meta" bit) are prefixed with
X * a P1_FN_META function.
X *
X * The next most-significant bit in the byte specifies the sender and
X * recipient of the command.  If this bit is clear (0), the command byte
X * was sent from the host computer to the Macintosh; if it is set (1)
X * the command byte was sent from the Macintosh to the host computer.
X * This prevents confusion in the event that the host computer
X * (incorrectly) echos a command back to the Macintosh.
X *
X * The remaining six bits are partitioned into two fields.  The low-order
X * three bits specify a window number from 1-7 (window 0 is reserved for
X * other uses) or another type of command-dependent parameter.  The next
X * three bits specify the operation to be performed by the recipient of
X * the command byte.
X *
X * Note that the choice of command bytes prevents the ASCII XON (021) and
X * XOFF (023) characters from being sent as commands.  P1_FN_ISELW commands
X * are only sent by the Macintosh (and thus are tagged with the P1_DIR_MTOH
X * bit).  Since XON and XOFF data characters are handled via P1_FN_CTLCH,
X * this allows them to be used for flow control purposes.
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/*
X * Protocol 2: (extended UW protocol)
X *
X * Protocol 2 is an extension of protocol 1.  The P2_FN_NEWW command and
X * the new command P2_FN_WOPT communicate window options between the host
X * and the Macintosh.  (See "uw_opt.h" for details.)
X */
X#define	P2_IAC		P1_IAC		/* interpret as command */
X#define	P2_DIR		P1_DIR		/* command direction: */
X#define	P2_DIR_HTOM	P1_DIR_HTOM	/*	from host to Mac */
X#define	P2_DIR_MTOH	P1_DIR_MTOH	/*	from Mac to host */
X#define	P2_FN		P1_FN		/* function code: */
X#define	P2_FN_NEWW	P1_FN_NEWW	/*	new window */
X#define	P2_FN_KILLW	P1_FN_KILLW	/*	kill (delete) window */
X#define	P2_FN_ISELW	P1_FN_ISELW	/*	select window for input */
X#define	P2_FN_OSELW	P1_FN_OSELW	/*	select window for output */
X#define	P2_FN_WOPT	0040		/*	communicate window options */
X#define	P2_FN_META	P1_FN_META	/*	add meta to next data char */
X#define	P2_FN_CTLCH	P1_FN_CTLCH	/*	low 3 bits specify char */
X#define	P2_FN_MAINT	P1_FN_MAINT	/*	maintenance functions */
X#define	P2_WINDOW	P1_WINDOW	/* window number mask */
X#define	P2_CC		P1_CC		/* control character specifier: */
X#define	P2_CC_IAC	P1_CC_IAC	/*	IAC */
X#define	P2_CC_XON	P1_CC_XON	/*	XON */
X#define	P2_CC_XOFF	P1_CC_XOFF	/*	XOFF */
X#define	P2_MF		P1_MF		/* maintenance functions: */
X#define	P2_MF_ENTRY	P1_MF_ENTRY	/*	beginning execution */
X#define	P2_MF_ASKPCL	P1_MF_ASKPCL	/*	request protocol negotiation */
X#define	P2_MF_CANPCL	P1_MF_CANPCL	/*	suggest protocol */
X#define	P2_MF_SETPCL	P1_MF_SETPCL	/*	set current protocol */
X#define	P2_MF_EXIT	P1_MF_EXIT	/*	execution terminating */
X#define	P2_NWINDOW	P1_NWINDOW	/* maximum number of windows */
X
X/*
X * Protocol negotiation
X *
X * The server is not used for protocol 0.  For the other protocols, the
X * Macintosh and the server negotiate to select the active protocol.  The
X * basic idea is that the Macintosh will express its desire for a protocol
X * and the server will attempt to satisfy that desire.  Until negotiations
X * are complete, protocol 1 is used.
X *
X * Protocols are identified by single-character names which are formed by
X * adding the ASCII code for a space (040) to the protocol number minus 1
X * (i.e. protocol 1 is ' ', protocol 2 is '!').
X *
X * P1_FN_CANPCL and P1_FN_SETPCL are three-byte commands: P1_IAC,
X * P1_FN_XXXPCL, protocol-name.
X *
X * Macintosh:
X *	If UW v2.10 is used on the Macintosh or if a newer Macintosh program
X *	wishes to use protocol 1, it will never initiate protocol negotiation.
X *	Hence, all interaction will use protocol 1 by default.
X *
X *	If the Macintosh program is capable of supporting protocol 2 and the
X *	user requests its use, the Mac will remember this fact but will
X *	continue to use protocol 1.  The Mac program will assume that no
X *	server is present until instructed otherwise by the user or until a
X *	P1_FN_ENTRY command is received (e.g. when the server starts up).
X *	At this time, the Mac program issues P1_FN_ASKPCL.  If the server
X *	cannot support protocol 2 (i.e. it is an old server), then it will
X *	ignore the P1_FN_ASKPCL.  The Macintosh will retry the P1_FN_ASKPCL
X *	a couple of times (about five seconds apart) and, if there is no
X *	response from the server, will abandon negotiations.  Protocol 1
X *	will be used for the remainder of the session.
X *
X *	If the server recognizes the P1_FN_ASKPCL command it will respond
X *	with the name of the most complex protocol it can support (currently
X *	'!').  If this is acceptable to the Macintosh, it will instruct the
X *	server to use this protocol.  If the Macintosh cannot support this
X *	protocol it will respond with a P1_FN_CANPCL suggesting a less-complex
X *	protocol.  If the server agrees to this it will answer establish the
X *	protocol; otherwise, it will suggest an even weaker protocol.
X *	Eventually someone will suggest protocol 1 (which is universal) and
X *	the other side will issue a P1_FN_SETPCL command to establish its use.
X *
X * Host:
X *	If the host receives a P1_FN_ASKPCL it will respond with the most
X *	complex protocol it can support (using the P1_FN_CANPCL command).
X *	Negotiations will proceed as described above until one side
X *	establishes a new protocol with P1_FN_SETPCL.  At this time, the
X *	host will switch to the new protocol.
X *
X *	If the host receives a P1_FN_ENTRY (P2_FN_ENTRY) command, it will
X *	switch back to protocol 1.  Receipt of this command indicates that
X *	the Macintosh program was restarted.  The Macintosh must initiate
X *	protocol negotiations again.
X */
X
X/*
X * Although many of the functions are identical (and the code is shared
X * between them), each protocol is accessed through a (struct protocol)
X * which specifies the functions for various operations.
X *
X * In theory, the main program knows nothing about the protocol in use.
X * In practice, the externally-visible functions are accessed as macros
X * for greater efficiency.
X *
X * The protocol layer is aware of the (struct window) data structures.
X */
X
Xstruct protocol {
X	char		p_name;		/* single-character protocol name */
X	nwin_t		p_maxwin;	/* maximum window number */
X	int		*p_ctlch;	/* control character map table */
X	unsigned	p_szctlch;	/* size (# of entries) in ctlch table */
X	void		(*p_entry)();	/* start up (ENTRY maintenance fn) */
X	void		(*p_exit)();	/* shut down (EXIT maintenance fn) */
X	void		(*p_renew)();	/* renew (re-init) */
X	struct window	*(*p_neww)();	/* create new window */
X	void		(*p_killw)();	/* kill window */
X	void		(*p_xmit)();	/* transmit to specified window */
X	void		(*p_recv)();	/* receive from Macintosh */
X	void		(*p_chkopt)();	/* check for pending option output */
X	void		(*p_sendopt)();	/* send option string to Macintosh */
X	void		(*p_askpcl)();	/* send an ASKPCL maintenance command */
X	void		(*p_canpcl)();	/* send a CANPCL maintenance command */
X	void		(*p_setpcl)();	/* send a SETPCL maintenance command */
X};
X
Xextern struct protocol *protocol;
X
X#define	PCL_NEWW(mfd,class,wtype,wnum,wid,dfd,cfd) \
X	(*protocol->p_neww)(mfd,class,wtype,wnum,(long)wid,dfd,cfd)
X#define	PCL_KILLW(mfd,w)	(*protocol->p_killw)(mfd,w)
X#define	PCL_RECV(mfd,buf,len)	(*protocol->p_recv)(mfd,buf,len)
X#define	PCL_XMIT(mfd,w)	(*protocol->p_xmit)(mfd,w)
X#define	PCL_SENDOPT(mfd,fn,buf,len) \
X	(protocol->p_sendopt ? (*protocol->p_sendopt)(mfd,fn,buf,len) : 0)
X#endif
SHAR_EOF
if test 9801 -ne "`wc -c < 'h/uw_pcl.h'`"
then
	echo shar: error transmitting "'h/uw_pcl.h'" '(should have been 9801 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uw_win.h'" '(3453 characters)'
if test -f 'h/uw_win.h'
then
	echo shar: will not over-write existing file "'h/uw_win.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uw_win.h'
X/*
X *	uw window data definition
X *
X * Copyright 1986 by John D. Bruner.  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#ifndef UW_WIN
X#define	UW_WIN
X
X#include "uw_opt.h"
X
X/*
X * A "point" is a pair of 16-bit integers.  This may specify the horizontal
X * and vertical position or size of a window.
X */
Xtypedef short npixel_t;			/* number of pixels */
Xstruct point {
X	npixel_t	v,h;
X};
X
X/*
X * The type of a window determines how it responds to I/O and which
X * window options it supports.  I'd like to declare these with an "enum",
X * but the stupid PCC screams if I use enums as array indices, so they
X * are defined via #define's instead.
X */
Xtypedef unsigned int wtype_t;		/* window type: */
X#define	WT_ADM31	0		/*	ADM-31 terminal emulation */
X#define	WT_VT52		1		/*	VT52 terminal emulation */
X#define	WT_ANSI		2		/*	ANSI terminal emulation */
X#define	WT_TEK4010	3		/*	Tek4010 terminal emulation */
X#define	WT_FTP		4		/*	file transfer */
X#define	WT_PRINT	5		/*	output to printer */
X#define	WT_PLOT		6		/*	plot window */
X#define	WT_MAXTYPE	6		/* maximum window type */
X
Xextern wtype_t defwtype;		/* default window type */
X
X/*
X * There are two basic classes of windows -- those which are processed
X * directly by the server and those which are processed by outside
X * programs.  Directly-handled windows are always terminal emulations.
X * Externally-handled windows may be any window type.
X */
Xtypedef enum {				/* window class: */
X	WC_INTERNAL,			/*	processed directly */
X	WC_EXTERNAL,			/*	processed externally */
X} wclass_t;
X
Xstruct window {
X	int		w_alloc;	/* window allocated if nonzero */
X	long		w_id;		/* window unique ID */
X	wtype_t		w_type;		/* window emulation type */
X	wclass_t	w_class;	/* window class */
X	fildes_t	w_datafd;	/* data file descriptor */
X	union {
X		struct winint {
X			char wi_tty[32];	/* terminal name */
X		}	wu_int;
X		struct winext {
X			fildes_t we_ctlfd;	/* control file descriptor */
X		}	wu_ext;
X	}		w_un;
X	struct woptdefn	w_optdefn;	/* window option definitions */
X	int		w_visible;	/* nonzero if window is visible */
X	struct point	w_position;	/* position of window on screen */
X	struct point	w_size;		/* size of window in pixels */
X	char		w_title[256];	/* window title */
X	char		*w_private;	/* storage private to emulation type */
X};
X#define	w_tty		w_un.wu_int.wi_tty
X#define	w_ctlfd		w_un.wu_ext.we_ctlfd
X
Xtypedef int nwin_t;			/* window index data type */
X
X/*
X * Some operations upon windows depend upon the window type.  For each
X * emulation type there is a "emulation" structure which specifies
X * emulation-specific data.
X */
Xstruct emulation {
X	struct woptdefn	we_optdefn;	/* window option definitions */
X	int		(*we_start)();	/* emulation setup code */
X	void		(*we_stop)();	/* emulation shutdown code */
X	void		(*we_setext)();	/* make changes req'd for extern win */
X};
X
Xextern struct window *win_neww();	/* create new window */
Xextern struct window *win_search();	/* convert window ID to window ptr */
X
X/*
X * The following macros convert between a window number and a pointer to
X * the corresponding window structure (and vice versa).
X *
X * NWINDOW *must* be >= P1_NWINDOW and >= P2_NWINDOW (in "uw_pcl.h").
X */
X#define	NWINDOW		7		/* maximum number of windows */
X#define	WIN_NUM(wptr)	((wptr)-window+1)
X#define	WIN_PTR(wnum)	(window+(wnum)-1)
Xextern struct window window[];		/* window data structures */
X#endif
SHAR_EOF
if test 3453 -ne "`wc -c < 'h/uw_win.h'`"
then
	echo shar: error transmitting "'h/uw_win.h'" '(should have been 3453 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'h/uwlib.h'" '(1974 characters)'
if test -f 'h/uwlib.h'
then
	echo shar: will not over-write existing file "'h/uwlib.h'"
else
sed 's/^X//' << \SHAR_EOF > 'h/uwlib.h'
X/*
X *	uw library definitions
X *
X * Copyright 1986 by John D. Bruner.  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_err.h"
X#include "uw_ipc.h"
X
X#ifndef NBBY
X#define	NBBY		8		/* defined in <sys/types.h> in 4.3BSD */
X#endif
X
X#define	UW_NUMOPTS	32		/* number of window options */
X#define	UW_NWTYPES	6		/* number of window emulation types */
X
Xtypedef char uwtitle_t[256];
X
Xstruct uwpoint {
X	unsigned	uwp_v;		/* vertical component */
X	unsigned	uwp_h;		/* horizontal component */
X};
X
Xstruct uw_info {
X	uwid_t		uwi_id;		/* unique window ID */
X	int		uwi_datafd;	/* file descriptor for data */
X	int		uwi_ctlfd;	/* file descriptor for control */
X	uwerr_t		uwi_uwerr;	/* last error from UW */
X	int		uwi_errno;	/* last error from system call */
X	int		uwi_vis;	/* visiblility */
X	uwtype_t	uwi_type;	/* window type */
X	struct uwpoint	uwi_pos;	/* window position (in pixels) */
X	uwtitle_t	uwi_title;	/* window title */
X	struct uwpoint	uwi_wsize;	/* window size (in pixels) */
X	struct {
X		void	(*uwi_optfn)();	/* option handler */
X	}		uwi_options[UW_NUMOPTS];
X	int		uwi_ipclen;	/* length of data in IPC buffer */
X	struct uwipc	uwi_ipcbuf;	/* buffer for IPC messages */
X};
X
X#define	UW_DATAFD(uwin)		(uwin)->uwi_datafd
X#define	UW_ID(uwin)		(uwin)->uwi_id
X#define	UW_PERROR(uwin, mesg)	\
X	uw_perror(mesg, (uwin)->uwi_uwerr, (uwin)->uwi_errno)
X
Xtypedef struct uw_info *UWIN;
Xtypedef void (*uwfnptr_t)();
X
Xextern uwid_t uw_cmd();
Xextern UWIN uw_new();
Xextern uw_close(), uw_detach();
Xextern uw_optcmd();
Xextern uw_kill();
Xextern uwfnptr_t uw_optfn();
Xextern uw_rsetopt();
Xextern void uw_perror();
Xextern uwid_t uw_fork(), uw_cmd(), uw_shell();
X
Xextern uw_gvis(), uw_svis();
Xextern uw_gtype(), uw_stype();
Xextern uw_gtitle(), uw_stitle();
Xextern uw_gwsize(), uw_swsize();
Xextern uw_gpos(), uw_spos();
X
Xextern uwerr_t uwerrno;
Xextern char *uwerrlist[];
Xextern unsigned uwnerr;
SHAR_EOF
if test 1974 -ne "`wc -c < 'h/uwlib.h'`"
then
	echo shar: error transmitting "'h/uwlib.h'" '(should have been 1974 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 3 ---

jdb@mordor.s1.gov (John Bruner) (04/06/88)

[UW v4.2 - part 4 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	lib/Makefile_4.2
#	lib/Makefile_4.3
#	lib/uw_close.c
#	lib/uw_cmd.c
#	lib/uw_detach.c
#	lib/uw_fork.c
#	lib/uw_gpos.c
#	lib/uw_gtitle.c
#	lib/uw_gtype.c
#	lib/uw_gvis.c
#	lib/uw_gwsize.c
#	lib/uw_kill.c
#	lib/uw_netadj.c
#	lib/uw_new.c
#	lib/uw_optcmd.c
# This archive created: Mon Apr  4 07:51:53 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d lib
then
	echo shar: mkdir lib
	mkdir lib
fi
echo shar: extracting "'lib/Makefile_4.2'" '(1710 characters)'
if test -f 'lib/Makefile_4.2'
then
	echo shar: will not over-write existing file "'lib/Makefile_4.2'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/Makefile_4.2'
X#! /bin/make -f
X#
X#	uw library makefile (4.2BSD)
X#
X# INCDIR names the directory in which header files are located.
X# SERVERDIR names the directory containing the server source.
X# SERVER_OBJS names the object files derived from sources in SERVERDIR.
X# OBJECTS names all of the object files required for the library.
X#
XINCDIR	=	../h
X
XSERVERDIR =	../server
X
XSERVER_OBJS =	$(SERVERDIR)/openpty.o $(SERVERDIR)/uw_env.o
X
XOBJECTS	=	uw_cmd.o uw_close.o uw_detach.o uw_fork.o uw_kill.o \
X		uw_netadj.o uw_new.o uw_optcmd.o uw_optfn.o uw_options.o \
X		uw_perror.o uw_ttype.o \
X		uw_rsetopt.o uw_shell.o \
X		uw_gvis.o uw_gtype.o uw_gtitle.o uw_gwsize.o uw_gpos.o \
X		$(SERVER_OBJS)
X
XSOURCES	=	`echo $(OBJECTS) | sed -e 's/\\.o/\\.c/g'`
X
XDEFINES	=	`cat ../DEFINES`
X
XCFLAGS	=	-O -I$(INCDIR) $(DEFINES)
X
XTARGET	=	libuw.a
X
X$(TARGET):	$(OBJECTS)
X	ar cr $(TARGET) `lorder $(OBJECTS) | tsort`
X	ranlib $(TARGET)
X	-if [ ! -f uwlib.a ];then ln -s libuw.a uwlib.a;fi
X
X$(SERVER_OBJS):
X	cd $(SERVERDIR); make `basename $@`
X
Xlint:
X	lint -uhbx -I$(INCDIR) $(DEFINES) $(SOURCES)
X
Xtags:
X	ctags $(SOURCES)
X
Xdepend: 
X	grep '^#include' $(SOURCES) | \
X	sed -e '/</d' \
X	    -e 's/:[^"]*"\([^"]*\)".*/: ..\/h\/\1/' \
X	    -e 's,^../[a-zA-Z0-9]*/\([^\.]*\)\.[cs],\1.o \1.L,' | \
X	awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
X		else { if (length(rec $$3) > 78) { print rec; rec = $$0; } \
X		       else rec = rec " " $$3 } } \
X	      END { print rec } ' > makedep
X	echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
X	echo '$$r makedep' >>eddep
X	echo 'w' >>eddep
X	cp Makefile Makefile.bak
X	ex - Makefile < eddep
X	rm eddep makedep
X
Xclean:
X	-rm *.o
X
X# DO NOT DELETE THIS LINE (or the following blank line) -- make depend uses it
X
SHAR_EOF
if test 1710 -ne "`wc -c < 'lib/Makefile_4.2'`"
then
	echo shar: error transmitting "'lib/Makefile_4.2'" '(should have been 1710 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/Makefile_4.3'" '(1678 characters)'
if test -f 'lib/Makefile_4.3'
then
	echo shar: will not over-write existing file "'lib/Makefile_4.3'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/Makefile_4.3'
X#! /bin/make -f
X#
X#	uw library makefile (4.3BSD)
X#
X# INCDIR names the directory in which header files are located.
X# SERVERDIR names the directory containing the server source.
X# SERVER_OBJS names the object files derived from sources in SERVERDIR.
X# OBJECTS names all of the object files required for the library.
X#
X
XINCDIR	=	../h
X
XSERVERDIR =	../server
X
XSERVER_OBJS =	$(SERVERDIR)/openpty.o $(SERVERDIR)/uw_env.o
X
XOBJECTS	=	uw_cmd.o uw_close.o uw_detach.o uw_fork.o uw_kill.o \
X		uw_netadj.o uw_new.o uw_optcmd.o uw_optfn.o uw_options.o \
X		uw_perror.o uw_ttype.o \
X		uw_rsetopt.o uw_shell.o \
X		uw_gvis.o uw_gtype.o uw_gtitle.o uw_gwsize.o uw_gpos.o \
X		$(SERVER_OBJS)
X
XSOURCES	=	`echo $(OBJECTS) | sed -e 's/\\.o/\\.c/g'`
X
XDEFINES	=	`cat ../DEFINES`
X
XCFLAGS	=	-O -I$(INCDIR) $(DEFINES)
X
XTARGET	=	libuw.a
X
X$(TARGET):	$(OBJECTS)
X	ar cr $(TARGET) `lorder $(OBJECTS) | tsort`
X	ranlib $(TARGET)
X	-if [ ! -f uwlib.a ];then ln -s libuw.a uwlib.a;fi
X
X$(SERVER_OBJS):
X	cd $(SERVERDIR); make `basename $@`
X
Xlint:
X	lint -uhbx -I$(INCDIR) $(DEFINES) $(SOURCES)
X
Xtags:
X	ctags $(SOURCES)
X
Xdepend: 
X	$(CC) -M -I$(INCDIR) $(DEFINES) $(SOURCES) | \
X	sed -e ':loop' \
X	    -e 's/\.\.\/[^ /]*\/\.\./../' \
X	    -e 't loop' | \
X	awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
X		else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X		       else rec = rec " " $$2 } } \
X	      END { print rec } ' >> makedep
X	echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
X	echo '$$r makedep' >>eddep
X	echo 'w' >>eddep
X	cp Makefile Makefile.bak
X	ex - Makefile < eddep
X	rm eddep makedep
X
Xclean:
X	-rm *.o
X
X# DO NOT DELETE THIS LINE (or the following blank line) -- make depend uses it
X
SHAR_EOF
if test 1678 -ne "`wc -c < 'lib/Makefile_4.3'`"
then
	echo shar: error transmitting "'lib/Makefile_4.3'" '(should have been 1678 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_close.c'" '(575 characters)'
if test -f 'lib/uw_close.c'
then
	echo shar: will not over-write existing file "'lib/uw_close.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_close.c'
X/*
X *	uw library - uw_close
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xuw_close(uwin)
XUWIN uwin;
X{
X	/*
X	 * Close all connections to an existing window, but do not kill it.
X	 */
X	if (uwin != (UWIN)0) {
X		if (uwin->uwi_ctlfd >= 0)
X			(void)uw_detach(uwin);
X		if (uwin->uwi_datafd >= 0)
X			(void)close(uwin->uwi_datafd);
X		free((char *)uwin);
X		return(0);
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 575 -ne "`wc -c < 'lib/uw_close.c'`"
then
	echo shar: error transmitting "'lib/uw_close.c'" '(should have been 575 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_cmd.c'" '(799 characters)'
if test -f 'lib/uw_cmd.c'
then
	echo shar: will not over-write existing file "'lib/uw_cmd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_cmd.c'
X/*
X *	uw library - uw_cmd
X *
X * Copyright 1986 by John D. Bruner.  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 "uwlib.h"
X
Xuwid_t
Xuw_cmd(wtype, file, argv)
Xuwtype_t wtype;
Xchar *file;
Xchar **argv;
X{
X	register uwid_t uwid;
X
X	/*
X	 * Create a new window (using uw_fork()) and run the specified
X	 * command in it.  Returns the window ID of the new window
X	 * (or -1 if the window creation failed).  There is no way to
X	 * determine if the executed command failed (e.g. if the
X	 * executable file did not exist).
X	 */
X	if ((uwid = uw_fork(wtype, (int *)0)) == 0) {
X		(void)execvp(file, argv);
X		uwerrno = UWE_ERRNO;
X		perror(file);
X		_exit(1);
X		/*NOTREACHED*/
X	} else
X		return(uwid);
X}
SHAR_EOF
if test 799 -ne "`wc -c < 'lib/uw_cmd.c'`"
then
	echo shar: error transmitting "'lib/uw_cmd.c'" '(should have been 799 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_detach.c'" '(677 characters)'
if test -f 'lib/uw_detach.c'
then
	echo shar: will not over-write existing file "'lib/uw_detach.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_detach.c'
X/*
X *	uw library - uw_detach
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xuw_detach(uwin)
XUWIN uwin;
X{
X	/*
X	 * Detach the control file descriptor for a window, while still
X	 * retaining access to the data file descriptor.
X	 */
X	if (uwin != (UWIN)0) {
X		if (uwin->uwi_ctlfd >= 0) {
X			uw_optdone(uwin->uwi_ctlfd);
X			(void)close(uwin->uwi_ctlfd);
X			uwin->uwi_ctlfd = -1;
X			return(0);
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_NOCTL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 677 -ne "`wc -c < 'lib/uw_detach.c'`"
then
	echo shar: error transmitting "'lib/uw_detach.c'" '(should have been 677 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_fork.c'" '(4704 characters)'
if test -f 'lib/uw_fork.c'
then
	echo shar: will not over-write existing file "'lib/uw_fork.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_fork.c'
X/*
X *	uw library - uw_fork
X *
X * Copyright 1986 by John D. Bruner.  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#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/un.h>
X#include <sys/ioctl.h>
X#include <sys/uio.h>
X#include <sys/file.h>
X#include <strings.h>
X#include <signal.h>
X#include "openpty.h"
X
X#include "uwlib.h"
X
Xextern char *malloc();
Xextern char *getenv();
X
Xuwid_t
Xuw_fork(wtype, pidp)
Xuwtype_t wtype;
Xint *pidp;
X{
X	register int pid;
X	register int sd;
X	register struct uwipc *uwip;
X	register uwid_t wid;
X	auto int fd;
X	char *portal;
X	int lmode, ldisc;
X	struct sgttyb sg;
X	struct tchars tc;
X	struct ltchars ltc;
X	struct iovec iov;
X	struct msghdr msg;
X	struct sockaddr_un sa;
X	struct ptydesc pt;
X	char idstr[20];
X	char *env[2];
X	extern char *ltoa();
X
X	/*
X	 * Create a new window attached to a pseudo-terminal.  This routine
X	 * returns twice -- once in the parent and once in the (new) child.
X	 * The parent receives the window ID of the child (or -1 if the
X	 * window creation failed).  Zero is returned to the child.
X	 * If "pidp" is a non-NULL pointer, the process ID from the fork()
X	 * is stored there.
X	 */
X
X	/*
X	 * Get the terminal configuration for this tty.  For now we
X	 * assume that "/dev/tty" is defined.  Eventually we'll have to
X	 * provide defaults in case it is not.
X	 */
X	if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
X		(void)ioctl(fd, (int)TIOCGETP, (char *)&sg);
X		(void)ioctl(fd, (int)TIOCGETC, (char *)&tc);
X		(void)ioctl(fd, (int)TIOCGLTC, (char *)&ltc);
X		(void)ioctl(fd, (int)TIOCLGET, (char *)&lmode);
X		(void)ioctl(fd, (int)TIOCGETD, (char *)&ldisc);
X		(void)close(fd);
X	} else {
X		/* ... */
X	}
X
X	/*
X	 * Create a UNIX-domain socket.
X	 */
X	if (!(portal=getenv("UW_UIPC"))) {
X		uwerrno = UWE_NXSERV;
X		return(-1);
X	}
X
X	if ((sd=socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
X		uwerrno = UWE_ERRNO;
X		return(-1);
X	}
X	sa.sun_family = AF_UNIX;
X	(void)strncpy(sa.sun_path, portal, sizeof sa.sun_path-1);
X	sa.sun_path[sizeof sa.sun_path-1] = '\0';
X
X
X	/*
X	 * Obtain a pseudo-tty and construct the datagram we will send later.
X	 */
X	if (openpty(&pt) < 0) {
X		uwerrno = UWE_ERRNO;
X		return(-1);
X	}
X	uwip = (struct uwipc *)malloc(sizeof(struct uwipc)+strlen(pt.pt_pname));
X	env[0] = malloc(sizeof "UW_ID=" + sizeof idstr);
X	if (uwip == (struct uwipc *)0 || env[0] == (char *)0) {
X		uwerrno = UWE_NOMEM;
X		return(-1);
X	}
X	uwip->uwip_cmd = UWC_NEWT;
X	uwip->uwip_len = (char *)&uwip->uwip_newt - (char *)uwip +
X	    sizeof(struct uwnewt) + strlen(pt.pt_pname);
X	uwip->uwip_newt.uwnt_type = wtype;
X	(void)strcpy(uwip->uwip_newt.uwnt_pty, pt.pt_pname);
X
X
X	/* 
X	 * Fork a child process using this pseudo-tty.  Initialize the
X	 * terminal modes on the pseudo-tty to match those of the parent
X	 * tty.  We really want a fork() here, not a vfork().
X	 */
X	while ((pid=fork()) < 0)
X		sleep(5);
X	if (pidp != (int *)0)
X		*pidp = pid;
X	if (pid) {
X		wid = (long)pid << 16;
X		uwip->uwip_newt.uwnt_id = wid;
X	} else {
X		(void)setgid(getgid());
X		(void)setuid(getuid());
X		wid = (long)getpid() << 16;
X		(void)strcat(strcpy(env[0], "UW_ID="),
X		     ltoa(wid, idstr, sizeof idstr));
X		env[1] = (char *)0;
X		env_set(env);
X		(void)signal(SIGTSTP, SIG_IGN);
X		(void)ioctl(open("/dev/tty", 2), (int)TIOCNOTTY, (char *)0);
X		(void)close(open(pt.pt_tname, 0)); /*set new ctrl tty */
X		(void)dup2(pt.pt_tfd, 0);
X		(void)dup2(0, 1);
X		(void)dup2(0, 2);
X		fd = getdtablesize();
X		while (--fd > 2)
X			(void)close(fd);
X		(void)ioctl(fd, (int)TIOCSETD, (char *)&ldisc);
X		(void)ioctl(0, (int)TIOCSETN, (char *)&sg);
X		(void)ioctl(0, (int)TIOCSETC, (char *)&tc);
X		(void)ioctl(0, (int)TIOCSLTC, (char *)&ltc);
X		(void)ioctl(0, (int)TIOCLSET, (char *)&lmode);
X		uwerrno = UWE_NONE;
X		return(0);
X	}
X
X
X	/*
X	 * Pass the file descriptor to the window server.
X	 */
X	iov.iov_base = (char *)uwip;
X	iov.iov_len = uwip->uwip_len;
X	msg.msg_name = (caddr_t)&sa;
X	msg.msg_namelen = sizeof sa.sun_family + strlen(sa.sun_path);
X	msg.msg_iov = &iov;
X	msg.msg_iovlen = 1;
X	msg.msg_accrights = (caddr_t)&pt.pt_pfd;
X	msg.msg_accrightslen = sizeof pt.pt_pfd;
X	if (sendmsg(sd, &msg, 0) < 0) {
X		free((char *)uwip);
X		uwerrno = UWE_ERRNO;
X		return(-1);
X	}
X	free((char *)uwip);
X	uwerrno = UWE_NONE;
X	return(wid);
X}
X
Xstatic
Xchar *
Xltoa(l, buf, buflen)
Xlong l;
Xchar *buf;
Xint buflen;
X{
X	register char *cp;
X	register unsigned long ul;
X	static char digits[] = "0123456789";
X
X	/*
X	 * This routine replaces a call to sprintf() so that the library
X	 * is independent of stdio.
X	 */
X	cp = buf+buflen;
X	*--cp = '\0';
X	ul = l;
X	if (cp > buf) {
X		do {
X			*--cp = digits[ul%10];
X			ul /= 10;
X		} while (cp > buf && ul != 0);
X	}
X	return(cp);
X}
SHAR_EOF
if test 4704 -ne "`wc -c < 'lib/uw_fork.c'`"
then
	echo shar: error transmitting "'lib/uw_fork.c'" '(should have been 4704 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_gpos.c'" '(1224 characters)'
if test -f 'lib/uw_gpos.c'
then
	echo shar: will not over-write existing file "'lib/uw_gpos.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_gpos.c'
X/*
X *	uw library - uw_gpos, uw_spos
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xuw_gpos(uwin, pp)
Xregister UWIN uwin;
Xregister struct uwpoint *pp;
X{
X	/*
X	 * Get the position of window "uwin" and store it in the point
X	 * whose address is "pp".
X	 */
X	if (uwin != (UWIN)0) {
X		if (pp != (struct uwpoint *)0) {
X			*pp = uwin->uwi_pos;
X			if (uwin->uwi_ctlfd > 0) {
X				return(0);
X			} else {
X				uwerrno = uwin->uwi_uwerr = UWE_NOCTL;
X				return(-1);
X			}
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_INVAL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
X
Xuw_spos(uwin, pp)
Xregister UWIN uwin;
Xstruct uwpoint *pp;
X{
X	union uwoptval optval;
X
X	/*
X	 * Set the position of window "uwin" to "pp".
X	 */
X	if (uwin != (UWIN)0) {
X		if (pp != (struct uwpoint *)0) {
X			uwin->uwi_pos = *pp;
X			optval.uwov_point.v = pp->uwp_v;
X			optval.uwov_point.h = pp->uwp_h;
X			return(uw_optcmd(uwin, UWOP_POS, UWOC_SET, &optval));
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_INVAL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 1224 -ne "`wc -c < 'lib/uw_gpos.c'`"
then
	echo shar: error transmitting "'lib/uw_gpos.c'" '(should have been 1224 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_gtitle.c'" '(1162 characters)'
if test -f 'lib/uw_gtitle.c'
then
	echo shar: will not over-write existing file "'lib/uw_gtitle.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_gtitle.c'
X/*
X *	uw library - uw_gtitle, uw_stitle
X *
X * Copyright 1986 by John D. Bruner.  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#include <strings.h>
X#include "uwlib.h"
X
Xuw_gtitle(uwin, ttl)
Xregister UWIN uwin;
Xuwtitle_t ttl;
X{
X	/*
X	 * Get the title of window "uwin" and put it in "ttl".
X	 */
X	if (uwin != (UWIN)0) {
X		(void)strncpy(ttl, uwin->uwi_title, sizeof(uwtitle_t));
X		if (uwin->uwi_ctlfd > 0) {
X			return(0);
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_NOCTL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
X
Xuw_stitle(uwin, ttl)
Xregister UWIN uwin;
Xuwtitle_t ttl;
X{
X	union uwoptval optval;
X
X	/*
X	 * Set the title of window "uwin" to "ttl".
X	 */
X	if (uwin != (UWIN)0) {
X		(void)strncpy(uwin->uwi_title, ttl, sizeof uwin->uwi_title);
X		uwin->uwi_title[sizeof uwin->uwi_title - 1] = '\0';
X		(void)strncpy(optval.uwov_string,ttl,sizeof optval.uwov_string);
X		optval.uwov_string[sizeof optval.uwov_string - 1] = '\0';
X		return(uw_optcmd(uwin, UWOP_TITLE, UWOC_SET, &optval));
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 1162 -ne "`wc -c < 'lib/uw_gtitle.c'`"
then
	echo shar: error transmitting "'lib/uw_gtitle.c'" '(should have been 1162 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_gtype.c'" '(1182 characters)'
if test -f 'lib/uw_gtype.c'
then
	echo shar: will not over-write existing file "'lib/uw_gtype.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_gtype.c'
X/*
X *	uw library - uw_gtype, uw_stype
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xuw_gtype(uwin, tp)
Xregister UWIN uwin;
Xregister uwtype_t *tp;
X{
X	/*
X	 * Get the type of the window "uwin".  The window type is stored
X	 * in the variable whose address is passed in "tp".
X	 */
X	if (uwin != (UWIN)0) {
X		if (tp != (uwtype_t *)0) {
X			*tp = uwin->uwi_type;
X			if (uwin->uwi_ctlfd > 0) {
X				return(0);
X			} else {
X				uwerrno = uwin->uwi_uwerr = UWE_NOCTL;
X				return(-1);
X			}
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_INVAL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
X
Xuw_stype(uwin, t)
Xregister UWIN uwin;
Xint t;
X{
X	union uwoptval optval;
X
X	/*
X	 * Set the type of window "uwin" to "t".
X	 */
X
X	if (uwin != (UWIN)0) {
X		if (t < UW_NWTYPES) {
X			uwin->uwi_type = t;
X			optval.uwov_6bit = uwin->uwi_type;
X			return(uw_optcmd(uwin, UWOP_TYPE, UWOC_SET, &optval));
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_INVAL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 1182 -ne "`wc -c < 'lib/uw_gtype.c'`"
then
	echo shar: error transmitting "'lib/uw_gtype.c'" '(should have been 1182 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_gvis.c'" '(1093 characters)'
if test -f 'lib/uw_gvis.c'
then
	echo shar: will not over-write existing file "'lib/uw_gvis.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_gvis.c'
X/*
X *	uw library - uw_gvis, uw_svis
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xuw_gvis(uwin, vp)
Xregister UWIN uwin;
Xregister int *vp;
X{
X	/*
X	 * Get the visibility status of the window "uwin".  "vp" is a
X	 * pointer to the integer where the status is returned.
X	 */
X	if (uwin != (UWIN)0) {
X		if (vp != (int *)0) {
X			*vp = uwin->uwi_vis;
X			if (uwin->uwi_ctlfd > 0) {
X				return(0);
X			} else {
X				uwerrno = uwin->uwi_uwerr = UWE_NOCTL;
X				return(-1);
X			}
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_INVAL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
X
Xuw_svis(uwin, v)
Xregister UWIN uwin;
Xint v;
X{
X	union uwoptval optval;
X
X	/*
X	 * Make window "uwin" visible (v != 0) or invisible (v == 0).
X	 */
X	if (uwin != (UWIN)0) {
X		uwin->uwi_vis = (v != 0);
X		optval.uwov_1bit = uwin->uwi_vis;
X		return(uw_optcmd(uwin, UWOP_VIS, UWOC_SET, &optval));
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 1093 -ne "`wc -c < 'lib/uw_gvis.c'`"
then
	echo shar: error transmitting "'lib/uw_gvis.c'" '(should have been 1093 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_gwsize.c'" '(1246 characters)'
if test -f 'lib/uw_gwsize.c'
then
	echo shar: will not over-write existing file "'lib/uw_gwsize.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_gwsize.c'
X/*
X *	uw library - uw_gwsize, uw_swsize
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xuw_gwsize(uwin, pp)
Xregister UWIN uwin;
Xregister struct uwpoint *pp;
X{
X	/*
X	 * Get the (pixel) size of window "uwin" and store it in the
X	 * point whose address is "pp".
X	 */
X	if (uwin != (UWIN)0) {
X		if (pp != (struct uwpoint *)0) {
X			*pp = uwin->uwi_wsize;
X			if (uwin->uwi_ctlfd > 0) {
X				return(0);
X			} else {
X				uwerrno = uwin->uwi_uwerr = UWE_NOCTL;
X				return(-1);
X			}
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_INVAL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
X
Xuw_swsize(uwin, pp)
Xregister UWIN uwin;
Xstruct uwpoint *pp;
X{
X	union uwoptval optval;
X
X	/*
X	 * Set the (pixel) size of window "uwin" to "pp".
X	 */
X	if (uwin != (UWIN)0) {
X		if (pp != (struct uwpoint *)0) {
X			uwin->uwi_wsize = *pp;
X			optval.uwov_point.v = pp->uwp_v;
X			optval.uwov_point.h = pp->uwp_h;
X			return(uw_optcmd(uwin, UWOP_WSIZE, UWOC_SET, &optval));
X		} else {
X			uwerrno = uwin->uwi_uwerr = UWE_INVAL;
X			return(-1);
X		}
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 1246 -ne "`wc -c < 'lib/uw_gwsize.c'`"
then
	echo shar: error transmitting "'lib/uw_gwsize.c'" '(should have been 1246 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_kill.c'" '(1341 characters)'
if test -f 'lib/uw_kill.c'
then
	echo shar: will not over-write existing file "'lib/uw_kill.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_kill.c'
X/*
X *	uw library - uw_kill
X *
X * Copyright 1986 by John D. Bruner.  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#include <sys/types.h>
X#include <netinet/in.h>
X
X#include "uwlib.h"
X
X#ifndef htons
X/* These should have been defined in <netinet/in.h>, but weren't (in 4.2BSD) */
Xextern unsigned short htons(), ntohs();
Xextern unsigned long htonl(), ntohl();
X#endif
X
Xuw_kill(uwin)
XUWIN uwin;
X{
X	register int len;
X	struct uwipc uwip;
X	extern int errno;
X
X	/*
X	 * Kill the window "uwin".  After putting out the contract,
X	 * destroy the evidence by closing all existing connections
X	 * to the window.
X	 */
X	if (uwin != (UWIN)0) {
X		if (uwin->uwi_ctlfd >= 0) {
X			len = sizeof uwip.uwip_killw +
X			    (char *)&uwip.uwip_killw - (char *)&uwip;
X			uwip.uwip_len = htons(len);
X			uwip.uwip_cmd = htons(UWC_KILLW);
X			uwip.uwip_killw.uwkw_id = htonl(uwin->uwi_id);
X			if (write(uwin->uwi_ctlfd, (char *)&uwip, len) < 0) {
X				uwin->uwi_errno = errno;
X				uwerrno = uwin->uwi_uwerr = UWE_ERRNO;
X			} else
X				uwerrno = uwin->uwi_uwerr = UWE_NONE;
X			(void)uw_detach(uwin);
X		} else
X			uwerrno = uwin->uwi_uwerr = UWE_NOCTL;
X		if (uwin->uwi_uwerr == UWE_NONE)
X			return(0);
X		else
X			return(-1);
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 1341 -ne "`wc -c < 'lib/uw_kill.c'`"
then
	echo shar: error transmitting "'lib/uw_kill.c'" '(should have been 1341 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_netadj.c'" '(4215 characters)'
if test -f 'lib/uw_netadj.c'
then
	echo shar: will not over-write existing file "'lib/uw_netadj.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_netadj.c'
X/*
X *	uw library - uw_netadj
X *
X * Copyright 1986 by John D. Bruner.  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#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/un.h>
X#include <sys/ioctl.h>
X#include <sys/wait.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include <sys/uio.h>
X#include <sys/file.h>
X#include <netinet/in.h>
X#include <strings.h>
X#include <signal.h>
X#include "openpty.h"
X
X#include "uw_opt.h"	/* I had hoped to avoid including this */
X#include "uwlib.h"
X
Xstatic woptarg_t woa_vis[] = { WOA_UDATA(1), WOA_END };
Xstatic woptarg_t woa_type[] = { WOA_UDATA(6), WOA_END };
Xstatic woptarg_t woa_pos[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
Xstatic woptarg_t woa_title[] = { WOA_STRING(255), WOA_END };
Xstatic woptarg_t woa_size[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
Xstatic woptarg_t woa_tsize[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
Xstatic woptarg_t woa_fontsz[] = { WOA_UDATA(6), WOA_END };
Xstatic woptarg_t woa_clipb[] = { WOA_UDATA(1), WOA_END };
Xstatic woptarg_t woa_bell[] = { WOA_UDATA(2), WOA_END };
Xstatic woptarg_t woa_curs[] = { WOA_UDATA(1), WOA_END };
Xstatic woptarg_t woa_chgsz[] = { WOA_UDATA(1), WOA_END };
X
Xstatic woptarg_t *optargs[][WONUM_MAX+1] = {
X	/* window type 0 == adm31 */
X	{
X		0, woa_vis, woa_type, woa_pos, woa_title, woa_size, 0, 0,
X		woa_tsize, woa_fontsz, woa_clipb, woa_bell, woa_curs, woa_chgsz
X	},
X	/* window type 1 == vt52 */
X	{
X		0, woa_vis, woa_type, woa_pos, woa_title, woa_size, 0, 0,
X		woa_tsize, woa_fontsz, woa_clipb, woa_bell, woa_curs, woa_chgsz
X	},
X	/* window type 2 == ansi */
X	{
X		0, woa_vis, woa_type, woa_pos, woa_title, woa_size, 0, 0,
X		woa_tsize, woa_fontsz, woa_clipb, woa_bell, woa_curs, woa_chgsz
X	},
X	/* window type 3 = tek4010 */
X	{
X		0, woa_vis, woa_type, woa_pos, woa_title, woa_size, 0, 0,
X	},
X	/* window type 4 = file transfer */
X	{
X		0, woa_vis, woa_type, woa_pos, woa_title, woa_size, 0, 0,
X	},
X	/* window type 5 = printer */
X	{
X		0, woa_vis, woa_type, woa_pos, woa_title, woa_size, 0, 0,
X	},
X	/* window type 6 = plot */
X	{
X		0, woa_vis, woa_type, woa_pos, woa_title, woa_size, 0, 0,
X	},
X};
X
X#ifdef htons
Xuw_hton(wtype, optnum, data)
Xuwtype_t wtype;
Xuwopt_t optnum;
Xchar *data;
X{
X}
X
Xuw_ntoh(wtype, optnum, data)
Xuwtype_t wtype;
Xuwopt_t optnum;
Xchar *data;
X{
X}
X
X#else
X/* These should have been defined in <netinet/in.h> but weren't (in 4.2BSD) */
Xextern unsigned short htons(), ntohs();
Xextern unsigned long htonl(), ntohl();
X
Xuw_hton(wtype, optnum, data)
Xuwtype_t wtype;
Xuwopt_t optnum;
Xchar *data;
X{
X	static struct netadj na = {
X		(short (*)())htons, (long (*)())htonl, htons, htonl
X	};
X	if (data != (char *)0 && wtype < sizeof optargs / sizeof optargs[0] &&
X	    optnum <= WONUM_MAX && optargs[wtype][optnum] != (woptarg_t *)0) {
X		netadj(optargs[wtype][optnum], data, &na);
X	}
X}
X
Xuw_ntoh(wtype, optnum, data)
Xuwtype_t wtype;
Xuwopt_t optnum;
Xchar *data;
X{
X	static struct netadj na = {
X		(short (*)())ntohs, (long (*)())ntohl, ntohs, ntohl
X	};
X	if (data != (char *)0 && wtype < sizeof optargs / sizeof optargs[0] &&
X	    optnum <= WONUM_MAX && optargs[wtype][optnum] != (woptarg_t *)0) {
X		netadj(optargs[wtype][optnum], data, &na);
X	}
X}
X
Xstatic
Xnetadj(woa, data, na)
Xregister woptarg_t *woa;
Xchar *data;
Xregister struct netadj *na;
X{
X	register char *cp;
X	register int cnt;
X	union {
X		struct {
X			char	c1;
X			short	s;
X		}	cs;
X		struct {
X			char	c2;
X			long	l;
X		}	cl;
X	} u;
X
X	/*
X	 * Convert an option between host byte order and network byte order.
X	 */
X	if (data && na) {
X		for (cp=data; *woa != WOA_END; woa++) {
X			cnt = *woa & ~WOA_CMDMASK;
X			switch (*woa & WOA_CMDMASK) {
X			case WOA_CHARS(0):
X			case WOA_STRING(0):
X				cp += cnt;
X				break;
X			case WOA_UDATA(0):
X				if (cnt <= NBBY) {
X					cp++;
X				} else if (cnt <= sizeof(short)*NBBY) {
X					while ((int)cp & ((char *)&u.cs.s-&u.cs.c1-1))
X						cp++;
X					*(u_short *)cp =
X					    (*na->na_ushort)(*(u_short *)cp);
X					cp += sizeof(short);
X				} else {
X					while ((int)cp & ((char *)&u.cl.l-&u.cl.c2-1))
X						cp++;
X					*(u_short *)cp =
X					    (*na->na_ushort)(*(u_short *)cp);
X					cp += sizeof(long);
X				}
X			}
X		}
X	}
X}
X#endif
SHAR_EOF
if test 4215 -ne "`wc -c < 'lib/uw_netadj.c'`"
then
	echo shar: error transmitting "'lib/uw_netadj.c'" '(should have been 4215 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_new.c'" '(5791 characters)'
if test -f 'lib/uw_new.c'
then
	echo shar: will not over-write existing file "'lib/uw_new.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_new.c'
X/*
X *	uw library - uw_new
X *
X * Copyright 1986 by John D. Bruner.  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#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <sys/uio.h>
X#include <strings.h>
X#include <signal.h>
X#include <netdb.h>
X#include <ctype.h>
X#include "openpty.h"
X
X#include "uwlib.h"
X
Xextern char *malloc();
Xextern char *getenv();
X
X#ifndef htons
X/* These should have been defined in <netinet/in.h>, but weren't (in 4.2BSD) */
Xextern unsigned short htons(), ntohs();
Xextern unsigned long htonl(), ntohl();
X#endif
X
XUWIN
Xuw_new(uwtype, sin)
Xuwtype_t uwtype;
Xstruct sockaddr_in *sin;
X{
X	register UWIN uwin;
X	register char *cp, c;
X	register int len;
X	register int ctlfd;
X	int rdsz;
X	auto int namelen;
X	auto struct sockaddr_in sa, datasin, ctlsin;
X	auto struct uwipc uwip;
X	extern int errno;
X
X	/*
X	 * If our caller didn't supply an address for us to contact,
X	 * look in the environment to find it.
X	 */
X	if (sin == (struct sockaddr_in *)0) {
X		if ((cp = getenv(INET_ENV)) == (char *)0) {
X			uwerrno = UWE_NXSERV;
X			return((UWIN)0);
X		}
X		sin = &sa;
X		sa.sin_family = AF_INET;
X		sa.sin_addr.s_addr = 0;
X		sa.sin_port = 0;
X		bzero(sa.sin_zero, sizeof sa.sin_zero);
X		for ( ; isxdigit(c = *cp); cp++) {
X			/* Pyramid compiler blows this, must use left shift */
X			/* sa.sin_addr.s_addr *= 16; */
X			sa.sin_addr.s_addr <<= 4;
X			if (isdigit(c))
X				sa.sin_addr.s_addr += c-'0';
X			else if (islower(c))
X				sa.sin_addr.s_addr += c-'a' + 10;
X			else
X				sa.sin_addr.s_addr += c-'A' + 10;
X		}
X		if (c == '.') {
X			for (cp++; isdigit(c = *cp); cp++)
X				sa.sin_port = sa.sin_port*10 + c-'0';
X		}
X		if (sa.sin_addr.s_addr == 0 || sa.sin_port == 0 ||
X		    c != '\0') {
X			/* bad address */
X			uwerrno = UWE_INVAL;
X			return((UWIN)0);
X		}
X		sa.sin_addr.s_addr = htonl(sa.sin_addr.s_addr);
X		sa.sin_port = htons(sa.sin_port);
X	}
X
X	/*
X	 * Allocate space for a new window structure.
X	 */
X	if ((uwin = (UWIN)malloc(sizeof(*uwin))) == (UWIN)0) {
X		uwerrno = UWE_NOMEM;
X		return((UWIN)0);
X	}
X	uwin->uwi_type = uwtype;
X	for (len=0; len < UW_NUMOPTS; len++) /* "len" is a convenient "int" */
X		uwin->uwi_options[len].uwi_optfn = (uwfnptr_t)0;
X	
X	/*
X	 * Create sockets for the data and control file descriptors.
X	 */
X	if ((uwin->uwi_datafd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
X	    (uwin->uwi_ctlfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
X		if (uwin->uwi_datafd >= 0)
X			(void)close(uwin->uwi_datafd);
X		return((UWIN)0);
X	}
X
X	/*
X	 * Bind these sockets to a local address.  We figure out the
X	 * local machine's host number and use it if possible; otherwise,
X	 * we fall back to 127.0.0.1 (loopback device).  After binding,
X	 * we determine the port number for the control socket, since we
X	 * must send that to the server.  Connect to the server.
X	 */
X	datasin.sin_family = AF_INET;
X	datasin.sin_port = 0;
X	bzero(datasin.sin_zero, sizeof datasin.sin_zero);
X	getmyaddr(&datasin.sin_addr);
X	ctlsin.sin_family = AF_INET;
X	ctlsin.sin_port = 0;
X	bzero(ctlsin.sin_zero, sizeof ctlsin.sin_zero);
X	getmyaddr(&ctlsin.sin_addr);
X	if (bind(uwin->uwi_datafd, (struct sockaddr *)&datasin, sizeof datasin) < 0 ||
X	    bind(uwin->uwi_ctlfd, (struct sockaddr *)&ctlsin, sizeof ctlsin) < 0 ||
X	    listen(uwin->uwi_ctlfd, 1) < 0) {
X		uwerrno = UWE_ERRNO;
X		goto error;
X	}
X	namelen = sizeof ctlsin;
X	(void)getsockname(uwin->uwi_ctlfd, (char *)&ctlsin, &namelen);
X
X	if (connect(uwin->uwi_datafd, sin, sizeof(struct sockaddr_in)) < 0) {
X		uwerrno = UWE_ERRNO;
X		goto error;
X	}
X
X	/*
X	 * Now we have enough information to build the new-window command
X	 * and send it to the server.  The initial command is sent to the
X	 * data port.  Next, we wait for a connection from the server to
X	 * our data socket.  Finally, we expect the server to send us a
X	 * new window status message on the data fd.
X	 */
X	len = sizeof uwip.uwip_neww + (char *)&uwip.uwip_neww - (char *)&uwip;
X	uwip.uwip_len = htons(len);
X	uwip.uwip_cmd = htons(UWC_NEWW);
X	uwip.uwip_neww.uwnw_id = 0;	/* let server choose this */
X	uwip.uwip_neww.uwnw_type = htons(uwtype);
X	uwip.uwip_neww.uwnw_ctlport = ctlsin.sin_port;/* byte order correct */
X	if (write(uwin->uwi_datafd, (char *)&uwip, len) < 0) {
X		uwerrno = UWE_ERRNO;
X		goto error;
X	}
X	
X	namelen = sizeof ctlsin;
X	if ((ctlfd = accept(uwin->uwi_ctlfd, (struct sockaddr_in *)&ctlsin, &namelen)) < 0) {
X		uwerrno = UWE_ERRNO;
X		goto error;
X	}
X	(void)close(uwin->uwi_ctlfd);
X	uwin->uwi_ctlfd = ctlfd;
X	uw_optinit(ctlfd, uwin);
X
X	cp = (char *)&uwip.uwip_len;
X	rdsz = sizeof uwip.uwip_len;
X	while (rdsz > 0 && (len=read(uwin->uwi_datafd, cp, rdsz)) > 0) {
X		cp += len;
X		rdsz -= len;
X	}
X	if (len > 0) {
X		rdsz = htons(uwip.uwip_len) - sizeof uwip.uwip_len;
X		while (rdsz > 0 && (len=read(uwin->uwi_datafd, cp, rdsz)) > 0) {
X			cp += len;
X			rdsz -= len;
X		}
X	}
X	if (len <= 0) {
X		uwerrno = UWE_ERRNO;
X		goto error;
X	}
X	uwerrno = uwin->uwi_uwerr = ntohs(uwip.uwip_status.uwst_err);
X	errno = uwin->uwi_errno = ntohs(uwip.uwip_status.uwst_errno);
X	if (uwin->uwi_uwerr != UWE_NONE)
X		goto error;
X	uwin->uwi_id = ntohl(uwip.uwip_status.uwst_id);
X	return(uwin);
X
Xerror:
X	(void)close(uwin->uwi_datafd);
X	(void)close(uwin->uwi_ctlfd);
X	free((char *)uwin);
X	return((UWIN)0);
X}
X
Xstatic
Xgetmyaddr(addr)
Xstruct in_addr *addr;
X{
X	register struct hostent *h;
X	char hostname[32];
X	static int once = 1;
X	static struct in_addr myaddr;
X
X	if (once) {
X		if (gethostname(hostname, sizeof hostname) < 0) {
X			(void)strncpy(hostname, "localhost", sizeof hostname-1);
X			hostname[sizeof hostname-1] = '\0';
X		}
X		if ((h = gethostbyname(hostname)) != (struct hostent *)0)
X			myaddr = *(struct in_addr *)h->h_addr;
X		else
X			myaddr.s_addr = htonl(0x7f000001L);
X		once = 0;
X	}
X	*addr = myaddr;
X}
SHAR_EOF
if test 5791 -ne "`wc -c < 'lib/uw_new.c'`"
then
	echo shar: error transmitting "'lib/uw_new.c'" '(should have been 5791 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_optcmd.c'" '(1899 characters)'
if test -f 'lib/uw_optcmd.c'
then
	echo shar: will not over-write existing file "'lib/uw_optcmd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_optcmd.c'
X/*
X *	uw library - uw_optcmd
X *
X * Copyright 1986 by John D. Bruner.  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#include <sys/types.h>
X#include <netinet/in.h>
X
X#include "uwlib.h"
X
X#ifndef htons
X/* These should have been defined in <netinet/in.h>, but weren't (in 4.2BSD) */
Xextern unsigned short htons(), ntohs();
Xextern unsigned long htonl(), ntohl();
X#endif
X
Xuw_optcmd(uwin, optnum, optcmd, optval)
XUWIN uwin;
Xuwopt_t optnum;
Xuwoptcmd_t optcmd;
Xunion uwoptval *optval;
X{
X	register int len;
X	struct uwipc uwip;
X	extern int errno;
X
X	/*
X	 * Send an option command string to the server (and eventually
X	 * to the Macintosh).
X	 */
X	if (uwin != (UWIN)0) {
X		if (uwin->uwi_ctlfd >= 0) {
X			if (optnum < UW_NUMOPTS) {
X				len = sizeof uwip;
X				uwip.uwip_len = htons(len);
X				uwip.uwip_cmd = htons(UWC_OPTION);
X				uwip.uwip_option.uwop_id = htonl(uwin->uwi_id);
X				uwip.uwip_option.uwop_opt = htons(optnum);
X				uwip.uwip_option.uwop_cmd = htons(optcmd);
X				switch (optcmd) {
X				case UWOC_SET:
X					if (optval == (union uwoptval *)0) {
X						uwin->uwi_uwerr = UWE_INVAL;
X						break;
X					} 
X					uwip.uwip_option.uwop_val = *optval;
X					uw_hton(uwin->uwi_type, optnum,
X					    (char *)&uwip.uwip_option.uwop_val);
X					/* no break */
X				case UWOC_ASK:
X				case UWOC_DO:
X				case UWOC_DONT:
X				case UWOC_WILL:
X				case UWOC_WONT:
X					if (write(uwin->uwi_ctlfd, (char *)&uwip,
X					    len) < 0) {
X						uwin->uwi_uwerr = UWE_ERRNO;
X						uwin->uwi_errno = errno;
X					} else
X						uwin->uwi_uwerr = UWE_NONE;
X					break;
X				default:
X					uwin->uwi_uwerr = UWE_INVAL;
X					break;
X				}
X			} else
X				uwin->uwi_uwerr = UWE_INVAL;
X		}
X		uwerrno = uwin->uwi_uwerr;
X		if (uwin->uwi_uwerr == UWE_NONE)
X			return(0);
X		else
X			return(-1);
X	} else {
X		uwerrno = UWE_INVAL;
X		return(-1);
X	}
X}
SHAR_EOF
if test 1899 -ne "`wc -c < 'lib/uw_optcmd.c'`"
then
	echo shar: error transmitting "'lib/uw_optcmd.c'" '(should have been 1899 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 4 ---

jdb@mordor.s1.gov (John Bruner) (04/06/88)

[UW v4.2 - part 5 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	lib/uw_optfn.c
#	lib/uw_options.c
#	lib/uw_perror.c
#	lib/uw_rsetopt.c
#	lib/uw_shell.c
#	lib/uw_ttype.c
#	misc/README
#	misc/getopt.c
#	misc/macmouse.el
#	misc/macmouse.ml
# This archive created: Mon Apr  4 07:51:58 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d lib
then
	echo shar: mkdir lib
	mkdir lib
fi
echo shar: extracting "'lib/uw_optfn.c'" '(853 characters)'
if test -f 'lib/uw_optfn.c'
then
	echo shar: will not over-write existing file "'lib/uw_optfn.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_optfn.c'
X/*
X *	uw library - uw_optfn
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xuwfnptr_t
Xuw_optfn(uwin, optnum, optfn)
XUWIN uwin;
Xuwopt_t optnum;
Xuwfnptr_t optfn;
X{
X	uwfnptr_t oldfn;
X
X	/*
X	 * Establish an option-processing function (defined by the host).
X	 * The specified function will be called whenever an option message
X	 * is received from the server.  The previous function is returned.
X	 */
X	oldfn = (uwfnptr_t)0;
X	if (uwin != (UWIN)0) {
X		if (optnum < UW_NUMOPTS) {
X			oldfn = uwin->uwi_options[optnum].uwi_optfn;
X			uwin->uwi_options[optnum].uwi_optfn = optfn;
X			uwin->uwi_uwerr = UWE_NONE;
X		} else
X			uwin->uwi_uwerr = UWE_INVAL;
X	}
X	uwerrno = uwin->uwi_uwerr;
X	return(oldfn);
X}
SHAR_EOF
if test 853 -ne "`wc -c < 'lib/uw_optfn.c'`"
then
	echo shar: error transmitting "'lib/uw_optfn.c'" '(should have been 853 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_options.c'" '(6733 characters)'
if test -f 'lib/uw_options.c'
then
	echo shar: will not over-write existing file "'lib/uw_options.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_options.c'
X/*
X *	uw library - uw_options
X *
X * Copyright 1986 by John D. Bruner.  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#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/time.h>
X#include <netinet/in.h>
X#include <strings.h>
X#include <signal.h>
X#include <errno.h>
X
X#include "uwlib.h"
X
X#ifndef FD_SET
X#define	FD_SET(n,p)	((p)->fds_bits[0] |= (1 << (n)))
X#define	FD_CLR(n,p)	((p)->fds_bits[0] &= ~(1 << (n)))
X#define	FD_ISSET(n,p)	((p)->fds_bits[0] & (1 << (n)))
X#define	FD_ZERO(p)	((p)->fds_bits[0] = 0)
X#define	FD_SETSIZE	(NBBY*sizeof(long))
X#endif
X
X#ifndef sigmask
X#define sigmask(m)	(1 << ((m)-1))
X#endif
X
X#ifndef htons
X/* These should have been defined in <netinet/in.h>, but weren't (in 4.2BSD) */
Xextern unsigned short htons(), ntohs();
Xextern unsigned long htonl(), ntohl();
X#endif
X
Xstatic UWIN *fdmap;
Xstatic int (*oldsigio)();
Xstatic struct fd_set fdmask;
Xstatic int nfds;
X
Xextern char *malloc();
X
Xuw_optinit(fd, uwin)
Xint fd;
XUWIN uwin;
X{
X	register int i, flags;
X	static int first = 1;
X	extern uw_optinput();
X
X	/*
X	 * The first time through, allocate the file descriptor map and
X	 * bitmask, and cause SIGIO traps to be handled by uw_optinput.
X	 */
X	if (first) {
X		first = 0;
X		nfds = getdtablesize();
X		fdmap = (UWIN *)malloc((unsigned)(sizeof(UWIN)*nfds));
X		if (fdmap != (UWIN *)0)
X			for (i = 0; i < nfds; i++)
X				fdmap[i] = (UWIN)0;
X		oldsigio = signal(SIGIO, uw_optinput);
X		FD_ZERO(&fdmask);
X	}
X
X	/*
X	 * Add the new control fd to the map and mask.  Set the owner
X	 * to this process
X	 */
X	if (fd >= 0 && fd < nfds && uwin != (UWIN)0 && fdmap != (UWIN *)0) {
X		fdmap[fd] = uwin;
X		FD_SET(fd, &fdmask);
X#ifdef SETOWN_BUG
X		(void)fcntl(fd, F_SETOWN, -getpid());
X#else
X		(void)fcntl(fd, F_SETOWN, getpid());
X#endif
X		if ((flags = fcntl(fd, F_GETFL, 0)) >= 0)
X			(void)fcntl(fd, F_SETFL, flags|FASYNC|FNDELAY);
X		uwin->uwi_ipclen = 0;
X	}
X}
X
Xuw_optdone(fd)
X{
X	register int flags;
X
X	/*
X	 * Turn off asynchronous I/O notification and remove the
X	 * map and mask information for "fd".  We do not close the
X	 * file descriptor, however -- the caller is expected to
X	 * take care of that.
X	 */
X	if (fd >= 0 && fd < nfds && fdmap != (UWIN *)0) {
X		if ((flags = fcntl(fd, F_GETFL, 0)) >= 0)
X			(void)fcntl(fd, F_SETFL, flags&~FASYNC);
X		else
X			(void)fcntl(fd, F_SETFL, 0);
X		(void)fcntl(fd, F_SETFL, 0);
X		fdmap[fd] = (UWIN)0;
X		FD_CLR(fd, &fdmask);
X	}
X}
X
Xstatic
Xuw_optinput(sig, code, scp)
Xint sig, code;
Xstruct sigcontext *scp;
X{
X	register int k, n, fd;
X	register UWIN uwin;
X	register struct uwoption *uwop;
X	register union uwoptval *uwov;
X	uwopt_t optnum;
X	uwoptcmd_t optcmd;
X	uwfnptr_t userfn;
X	int oldmask;
X	struct timeval timeo;
X	struct fd_set ready;
X	extern int errno;
X
X	/*
X	 * This routine is called when input is waiting on a control
X	 * file descriptor.
X	 */
X	oldmask = sigblock(sigmask(SIGALRM));
X	do {
X		ready = fdmask;
X		timeo.tv_sec = 0;
X		timeo.tv_usec = 0;
X		n = select(nfds, &ready, (struct fd_set *)0,
X			   (struct fd_set *)0, &timeo);
X		if (n < 0 && errno == EBADF) {
X			/*
X			 * One of the file descriptors that we asked for
X			 * is no longer valid.  This isn't supposed to
X			 * happen; however, we try to handle it by testing
X			 * each bit individually and eliminating the bad
X			 * ones.
X			 */
X			for (fd=0; fd < nfds; fd++) {
X				if (FD_ISSET(fd, &fdmask)) {
X					do {
X						ready = fdmask;
X						timeo.tv_sec = 0;
X						timeo.tv_usec = 0;
X						k = select(nfds, &ready,
X						    (struct fd_set *)0,
X						    (struct fd_set *)0, &timeo);
X						if (k < 0 && errno == EBADF) {
X							fdmap[fd] = (UWIN)0;
X							FD_CLR(fd, &fdmask);
X						}
X					} while (n < 0 && errno == EINTR);
X				}
X			}
X		}
X	} while (n < 0 && errno == EINTR);
X
X	for (fd=0; n > 0 && fd < nfds; fd++) {
X		if (FD_ISSET(fd, &ready)) {
X			n--;
X			uwin = fdmap[fd];
X			while ((k = getmesg(fd, uwin)) > 0) {
X				uwin->uwi_ipclen = 0;	/* for next time */
X				if (uwin->uwi_ipcbuf.uwip_cmd == UWC_OPTION) {
X					uwop = &uwin->uwi_ipcbuf.uwip_option;
X					uwov = &uwop->uwop_val;
X					optnum = ntohs(uwop->uwop_opt);
X					optcmd = ntohs(uwop->uwop_cmd);
X					if (optcmd == UWOC_SET)
X						uw_ntoh(uwin->uwi_type, optnum,
X						    (char *)uwov);
X					if (optcmd == UWOC_SET) switch(optnum) {
X					case UWOP_VIS:
X						uwin->uwi_vis = !!uwov->uwov_6bit;
X						break;
X					case UWOP_TYPE:
X						if (uwov->uwov_6bit<UW_NWTYPES)
X							uwin->uwi_type=uwov->uwov_6bit;
X						break;
X					case UWOP_POS:
X						uwin->uwi_pos.uwp_v = uwov->uwov_point.v;
X						uwin->uwi_pos.uwp_h = uwov->uwov_point.h;
X						break;
X					case UWOP_TITLE:
X						(void)strncpy(uwin->uwi_title,
X						    uwov->uwov_string,
X						    sizeof uwin->uwi_title);
X						break;
X					case UWOP_WSIZE:
X						uwin->uwi_wsize.uwp_v = uwov->uwov_point.v;
X						uwin->uwi_wsize.uwp_h = uwov->uwov_point.h;
X						break;
X					}
X					if (optnum == UWOP_TYPE &&
X					    optcmd == UWOC_SET &&
X					    uwov->uwov_6bit < UW_NWTYPES)
X						uwin->uwi_type=uwov->uwov_6bit;
X					userfn = uwin->uwi_options[optnum].uwi_optfn;
X					if (userfn != (uwfnptr_t)0)
X						(*userfn)(uwin, optnum,
X							  optcmd, uwov);
X				}
X			}
X			if (k < 0)
X				(void)uw_detach(uwin);	/* I/O error or EOF */
X		}
X	}
X	(void)sigsetmask(oldmask);
X
X	/*
X	 * Finally, if "oldsigio" is not SIG_DFL, call it.
X	 */
X	if (oldsigio != SIG_DFL)
X		(*oldsigio)(sig, code, scp);
X}
X
Xstatic
Xgetmesg(fd, uwin)
Xregister int fd;
Xregister UWIN uwin;
X{
X	register int len;
X	register char *cp;
X
X	/*
X	 * Read some more bytes from control socket "fd" into the input
X	 * buffer.  Return 1 if the message is now complete, -1 if an
X	 * EOF was reached, or 0 otherwise.  Before returning 1, the byte
X	 * order of the common parameters (command, length) is changed
X	 * from network to host order.
X	 */
X	cp = (char *)&uwin->uwi_ipcbuf + uwin->uwi_ipclen;
X	if (uwin->uwi_ipclen < sizeof(uwin->uwi_ipcbuf.uwip_len)) {
X		len = read(fd, cp, sizeof uwin->uwi_ipcbuf.uwip_len - uwin->uwi_ipclen);
X		if (len == 0 || (len < 0 && errno != EWOULDBLOCK))
X			return(-1);
X		if (len < 0)
X			return(0);
X		if ((uwin->uwi_ipclen +=len) < sizeof uwin->uwi_ipcbuf.uwip_len)
X			return(0);
X		uwin->uwi_ipcbuf.uwip_len = ntohs(uwin->uwi_ipcbuf.uwip_len);
X		if (uwin->uwi_ipcbuf.uwip_len==sizeof uwin->uwi_ipcbuf.uwip_len)
X			return(1);
X		cp += len;
X	}
X	if (uwin->uwi_ipcbuf.uwip_len > sizeof(struct uwipc))
X		uwin->uwi_ipcbuf.uwip_len = sizeof(struct uwipc);
X	len = read(fd, cp, uwin->uwi_ipcbuf.uwip_len - uwin->uwi_ipclen);
X	if (len == 0 || (len < 0 && errno != EWOULDBLOCK))
X		return(-1);
X	if ((uwin->uwi_ipclen += len) == uwin->uwi_ipcbuf.uwip_len) {
X		uwin->uwi_ipcbuf.uwip_cmd = ntohs(uwin->uwi_ipcbuf.uwip_cmd);
X		return(1);
X	} else
X		return(0);
X}
SHAR_EOF
if test 6733 -ne "`wc -c < 'lib/uw_options.c'`"
then
	echo shar: error transmitting "'lib/uw_options.c'" '(should have been 6733 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_perror.c'" '(1157 characters)'
if test -f 'lib/uw_perror.c'
then
	echo shar: will not over-write existing file "'lib/uw_perror.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_perror.c'
X/*
X *	uw library - uw_perror
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xchar *uwerrlist[] = {
X	"no error",
X	"system call error",
X	"nonexistent window type",
X	"window ID duplicated (in use)",
X	"operation not implemented",
X	"non-existent server",
X	"unable to allocate required memory",
X	"invalid argument to function",
X	"no control file descriptor for window",
X};
Xunsigned uwnerr = sizeof uwerrlist / sizeof uwerrlist[0];
X
Xint uwerrno;
X
X/*ARGSUSED*/
Xvoid
Xuw_perror(mesg, uwerr, errno)
Xchar *mesg;
Xuwerr_t uwerr;
Xint errno;
X{
X	register char *errmsg;
X
X	/*
X	 * Print a UW error message.  We call write() directly to avoid
X	 * making the UW library dependent upon stdio.
X	 */
X	if (uwerr == UWE_ERRNO) {
X		perror(mesg);
X	} else {
X		if (mesg != (char *)0) {
X			(void)write(2, mesg, strlen(mesg));
X			(void)write(2, ": ", 2);
X		}
X		if (uwerr >= uwnerr)
X			errmsg = "unknown UW error";
X		else
X			errmsg = uwerrlist[uwerr];
X		(void)write(2, errmsg, strlen(errmsg));
X		(void)write(2, "\n", 1);
X	}
X}
SHAR_EOF
if test 1157 -ne "`wc -c < 'lib/uw_perror.c'`"
then
	echo shar: error transmitting "'lib/uw_perror.c'" '(should have been 1157 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_rsetopt.c'" '(2024 characters)'
if test -f 'lib/uw_rsetopt.c'
then
	echo shar: will not over-write existing file "'lib/uw_rsetopt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_rsetopt.c'
X/*
X *	uw library - uw_rsetopt
X *
X * Copyright 1986 by John D. Bruner.  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#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/un.h>
X#include <sys/ioctl.h>
X#include <sys/uio.h>
X#include <sys/file.h>
X#include <strings.h>
X#include <signal.h>
X#include "openpty.h"
X
X#include "uwlib.h"
X
Xextern char *malloc();
Xextern char *getenv();
X
Xuw_rsetopt(uwid, optnum, optval)
Xuwid_t uwid;
Xuwopt_t optnum;
Xunion uwoptval *optval;
X{
X	register int sd;
X	register struct uwipc *uwip;
X	char *portal;
X	struct iovec iov;
X	struct msghdr msg;
X	struct sockaddr_un sa;
X
X	/*
X	 * Set a window option on a remote window (that is, one for which
X	 * we do not have a control fd).
X	 */
X
X	/*
X	 * Create a UNIX-domain socket.
X	 */
X	if (!(portal=getenv("UW_UIPC"))) {
X		uwerrno = UWE_NXSERV;
X		return(-1);
X	}
X
X	if ((sd=socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
X		uwerrno = UWE_ERRNO;
X		return(-1);
X	}
X	sa.sun_family = AF_UNIX;
X	(void)strncpy(sa.sun_path, portal, sizeof sa.sun_path-1);
X	sa.sun_path[sizeof sa.sun_path-1] = '\0';
X
X
X	/*
X	 * Construct the datagram we will send later.
X	 */
X	uwip = (struct uwipc *)malloc(sizeof(struct uwipc));
X	if (uwip == (struct uwipc *)0) {
X		uwerrno = UWE_NOMEM;
X		return(-1);
X	}
X	uwip->uwip_cmd = UWC_OPTION;
X	uwip->uwip_len = sizeof(struct uwipc);
X	uwip->uwip_option.uwop_id = uwid;
X	uwip->uwip_option.uwop_cmd = UWOC_SET;
X	uwip->uwip_option.uwop_opt = optnum;
X	uwip->uwip_option.uwop_val = *optval;
X
X	/*
X	 * Pass the file descriptor to the window server.
X	 */
X	iov.iov_base = (char *)uwip;
X	iov.iov_len = uwip->uwip_len;
X	msg.msg_name = (caddr_t)&sa;
X	msg.msg_namelen = sizeof sa.sun_family + strlen(sa.sun_path);
X	msg.msg_iov = &iov;
X	msg.msg_iovlen = 1;
X	msg.msg_accrights = (caddr_t)0;
X	msg.msg_accrightslen = 0;
X	if (sendmsg(sd, &msg, 0) < 0) {
X		free((char *)uwip);
X		uwerrno = UWE_ERRNO;
X		return(-1);
X	}
X	free((char *)uwip);
X	uwerrno = UWE_NONE;
X	return(0);
X}
SHAR_EOF
if test 2024 -ne "`wc -c < 'lib/uw_rsetopt.c'`"
then
	echo shar: error transmitting "'lib/uw_rsetopt.c'" '(should have been 2024 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_shell.c'" '(851 characters)'
if test -f 'lib/uw_shell.c'
then
	echo shar: will not over-write existing file "'lib/uw_shell.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_shell.c'
X/*
X *	uw library - uw_shell
X *
X * Copyright 1986 by John D. Bruner.  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#include "uwlib.h"
X
Xchar *uwshellname = "/bin/sh";	/* can be patched by caller if desired */
X
Xuwid_t
Xuw_shell(wtype, cmd)
Xuwtype_t wtype;
Xchar *cmd;
X{
X	register uwid_t uwid;
X
X	/*
X	 * Create a new window (using uw_fork()) and execute the specified
X	 * shell command in it.  Returns the window ID of the new window
X	 * (or -1 if the window creation failed)  There is no way to
X	 * determine if the executed command failed.
X	 */
X	if ((uwid = uw_fork(wtype, (int *)0)) == 0) {
X		(void)execl(uwshellname, uwshellname, "-c", cmd, (char *)0);
X		_exit(1);	/* we'd better not reach this point */
X		/*NOTREACHED*/
X	} else
X		return(uwid);
X}
SHAR_EOF
if test 851 -ne "`wc -c < 'lib/uw_shell.c'`"
then
	echo shar: error transmitting "'lib/uw_shell.c'" '(should have been 851 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lib/uw_ttype.c'" '(1059 characters)'
if test -f 'lib/uw_ttype.c'
then
	echo shar: will not over-write existing file "'lib/uw_ttype.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lib/uw_ttype.c'
X/*
X *	uw library - uw_ttype
X *
X * Copyright 1986 by John D. Bruner.  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#include <strings.h>
X#include "uwlib.h"
X
Xstruct table {
X	char		*tname;
X	uwtype_t	wtype;
X};
X
X/* The following table must be sorted */
Xstatic struct table table[] = {
X	{ "aaa-24", UWT_ANSI },
X	{ "adm3", UWT_ADM31 },
X	{ "adm31", UWT_ADM31 },
X	{ "adm3a", UWT_ADM31 },
X	{ "ansi", UWT_ANSI },
X	{ "tek", UWT_TEK4010 },
X	{ "tek4010", UWT_TEK4010 },
X	{ "tek4012", UWT_TEK4010 },
X	{ "vt52", UWT_VT52 },
X};
X
Xuwtype_t
Xuw_ttype(name)
Xchar *name;
X{
X	register struct table *t, *lo, *hi;
X	register int cmp;
X
X	/*
X	 * Map a terminal name string to a UW window emulation type.
X	 */
X	lo = table;
X	hi = table + sizeof table / sizeof table[0] - 1;
X	while (lo <= hi) {
X		t = lo + (hi-lo) / 2;
X		cmp = strcmp(name, t->tname);
X		if (cmp == 0)
X			return(t->wtype);
X		if (cmp < 0)
X			hi = t-1;
X		else
X			lo = t+1;
X	}
X	return(UWT_ADM31);	/* default if no match */
X}
SHAR_EOF
if test 1059 -ne "`wc -c < 'lib/uw_ttype.c'`"
then
	echo shar: error transmitting "'lib/uw_ttype.c'" '(should have been 1059 characters)'
fi
fi # end of overwriting check
if test ! -d misc
then
	echo shar: mkdir misc
	mkdir misc
fi
echo shar: extracting "'misc/README'" '(746 characters)'
if test -f 'misc/README'
then
	echo shar: will not over-write existing file "'misc/README'"
else
sed 's/^X//' << \SHAR_EOF > 'misc/README'
XThis directory contains three items that may be of interest:
X
X
X	getopt.c	The AT&T version of the getopt() library
X			routine (for command-line processing).  This
X			version, to the best of my knowledge, was
X			placed into the public domain by AT&T.
X
X	
X	macmouse.ml	A package for use with Gosling's EMACS
X			which intreprets encoded mouse-down and
X			mouse-up events within windows to perform
X			various operations.
X
X			Author: Chris Kent (kent@decwrl.dec.com)
X
X
X	macmouse.el	A similar macro package for GNU EMACS.
X
X			Author: Gregory Lauer (glauer@bbn.arpa)
X
X
XThe two EMACS macro packages were developed for a previous version of
XUW (version 2.10).  Since I (John Bruner) am not an EMACS user, I do
Xnot know how well they will work with UW v4.2.
SHAR_EOF
if test 746 -ne "`wc -c < 'misc/README'`"
then
	echo shar: error transmitting "'misc/README'" '(should have been 746 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'misc/getopt.c'" '(1247 characters)'
if test -f 'misc/getopt.c'
then
	echo shar: will not over-write existing file "'misc/getopt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'misc/getopt.c'
X/*LINTLIBRARY*/
X#define NULL	0
X#define EOF	(-1)
X#define ERR(s, c)	if(opterr){\
X	extern int strlen(), write();\
X	char errbuf[2];\
X	errbuf[0] = c; errbuf[1] = '\n';\
X	(void) write(2, argv[0], (unsigned)strlen(argv[0]));\
X	(void) write(2, s, (unsigned)strlen(s));\
X	(void) write(2, errbuf, 2);}
X
Xextern int strcmp();
Xextern char *strchr();
X
Xint	opterr = 1;
Xint	optind = 1;
Xint	optopt;
Xchar	*optarg;
X
Xint
Xgetopt(argc, argv, opts)
Xint	argc;
Xchar	**argv, *opts;
X{
X	static int sp = 1;
X	register int c;
X	register char *cp;
X
X	if(sp == 1)
X		if(optind >= argc ||
X		   argv[optind][0] != '-' || argv[optind][1] == '\0')
X			return(EOF);
X		else if(strcmp(argv[optind], "--") == NULL) {
X			optind++;
X			return(EOF);
X		}
X	optopt = c = argv[optind][sp];
X	if(c == ':' || (cp=strchr(opts, c)) == NULL) {
X		ERR(": illegal option -- ", c);
X		if(argv[optind][++sp] == '\0') {
X			optind++;
X			sp = 1;
X		}
X		return('?');
X	}
X	if(*++cp == ':') {
X		if(argv[optind][sp+1] != '\0')
X			optarg = &argv[optind++][sp+1];
X		else if(++optind >= argc) {
X			ERR(": option requires an argument -- ", c);
X			sp = 1;
X			return('?');
X		} else
X			optarg = argv[optind++];
X		sp = 1;
X	} else {
X		if(argv[optind][++sp] == '\0') {
X			sp = 1;
X			optind++;
X		}
X		optarg = NULL;
X	}
X	return(c);
X}
SHAR_EOF
if test 1247 -ne "`wc -c < 'misc/getopt.c'`"
then
	echo shar: error transmitting "'misc/getopt.c'" '(should have been 1247 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'misc/macmouse.el'" '(9277 characters)'
if test -f 'misc/macmouse.el'
then
	echo shar: will not over-write existing file "'misc/macmouse.el'"
else
sed 's/^X//' << \SHAR_EOF > 'misc/macmouse.el'
X;;;  macmouse.el (Version: 2.0)
X
X;;;  Copyright (C) Gregory S. Lauer (glauer@bbn), 1985. 
X;;;	Please send suggestions and corrections to the above address.
X;;;
X;;;  This file contains macmouse, a GNU Emacs mouse package for UW.
X
X
X;;
X;; GNU Emacs is distributed in the hope that it will be useful,
X;; but without any warranty.  No author or distributor
X;; accepts responsibility to anyone for the consequences of using it
X;; or for whether it serves any particular purpose or works at all,
X;; unless he says so in writing.
X
X;; Everyone is granted permission to copy, modify and redistribute
X;; GNU Emacs, but only under the conditions described in the
X;; document "GNU Emacs copying permission notice".   An exact copy
X;; of the document is supposed to have been given to you along with
X;; GNU Emacs so that you can know how you may redistribute it all.
X;; It should be in a file named COPYING.  Among other things, the
X;; copyright notice and this notice must be preserved on all copies.
X
X
X;;;  Original version for Gosling emacs by Chris Kent, Purdue University 1985.
X;;;  Modified by Gregory Lauer, BBN, Novemeber 1985.
X;
X;
X;
X; Macmouse provides the following features:
X;  Up or down mouse button in a window selects that window
X;
X;  A scroll bar/thumbing area for each window with the following features:
X;       the mode lines are horizontal scroll bars
X;           (running from rightmost column to under leftmost column)
X;       the unused right window bar and the dividing lines between
X;           windows are vertical scroll bars
X;           (running from top of window THRU modeline
X;   for vertical scroll bars:
X; 	click at line 1 does previous page
X;	click at last line does next page
X; 	click anywhere else "thumbs" to the relative portion of the buffer.
X; 	shift-click at line 1 scrolls one line down
X; 	shift-click at last line scrolls one line up
X; 	shift-click elsewhere moves line to top of window
X; 	option-shift-click elsewhere moves line to bottom of window
X;   for horizontal scroll bars:
X;       click at column 1 does scroll right one window width
X;       click at last column does scroll left one window width
X;       click anywhere else moves to that "percent" of the buffer width
X;       shift-click at column 1 scrolls one column right
X;       shift-click at last column scrolls one column left
X;       shift-click elsewhere moves column to right of window
X;       option-shift-click elsewhere moves column to left of window
X;
X; There is also basic positioning and kill-buffer support:
X; 	click in a buffer moves dot there and selects that buffer
X; 	drag copies the dragged region to the kill buffer
X; 	shift-drag deletes the dragged region to the kill buffer
X;
X;   It is possible to use the scrolling and thumbing area to make the region
X;   larger than a single screen; just click, scroll, release. Make sure
X;   that the last scroll is just a down event; the up must be in the buffer.
X;   The last mouse position is remembered for each different buffer (not
X;   window), and thus you can start a drag in one buffer, select another,
X;   go back to the first buffer, etc.
X;
X; 	option-click yanks from the kill buffer
X; 	option-shift-click similarly yanks from a named buffer.
X; 
X
X(defconst mouse-max-x 95 "Maximum UW column returned on mouse click")
X(defconst mouse-max-y 95 "Maximum UW row returned on mouse click")
X
X(make-variable-buffer-local 'mouse-last-x) ; x of last event
X(set-default 'mouse-last-x 0)
X
X(make-variable-buffer-local 'mouse-last-y) ; y of last event
X(set-default 'mouse-last-y 0)
X
X(make-variable-buffer-local 'mouse-last-b) ; buttons at last event
X(set-default 'mouse-last-b 0)
X
X(make-variable-buffer-local 'mouse-last-dot) ; dot after last event
X(set-default 'mouse-last-dot 0)
X
X(make-variable-buffer-local 'scrolling-p)
X(set-default 'scrolling-p nil)
X
X(defun move-mac-cursor ()
X  (interactive)
X  (let (savest b x y up down lock shift option command)
X    (setq savest stack-trace-on-error)
X    (setq stack-trace-on-error nil)
X					; decode everything
X    (setq y (- (read-char) 32))
X    (setq x (- (read-char) 32))
X    (setq b (- (read-char) 32))
X    (setq command (< 0 (logand b 1)))	; command key
X    (setq shift (< 0 (logand b 2)))	; shift
X    (setq lock (< 0 (logand b 4)))	; caps-lock
X    (setq option (< 0 (logand b 8)))	; option
X    (setq down (< 0 (logand b 16)))	; mouse down
X    (setq up (< 0 (logand b 32)))	; mouse up
X    (condition-case ()
X	(progn
X	  (select-window-containing-x-and-y x y) ; side-effect sets scrolling-p
X	  (if scrolling-p
X	      (mouse-scroll-region b x y)
X	    (progn
X	      (move-to-window-x-y x y)	; move cursor to mouse-dot always
X	      (if down (setq mouse-last-dot (dot)))
X	      (mouse-edit-action))))
X      (error (message "Click not in selectable window")
X	     (sit-for 1)
X	     (message "")))
X    (setq stack-trace-on-error savest)
X    (if down
X	(progn 
X	  (setq mouse-last-x x)
X	  (setq mouse-last-y y)
X	  (setq mouse-last-b b))
X      (progn 
X	(setq mouse-last-x 0)
X	(setq mouse-last-y 0)
X	(setq mouse-last-b 0)))))
X
X(defun mouse-edit-action ()
X                                ;marking and editing actions on buttons:
X				;   if no movement, nothing.
X				;   if movement, save mouse-last-dot,
X				;      and edit.
X				; editing (on upstrokes):
X				;   unmodified, copy to kill buffer.
X				;   SHIFTed, delete (cut) to kill buffer.
X				; 
X				; option-click yanks from kill buffer; 
X				; shift-option-click from named buffer.
X  (let ((fun (get 'mouse-function b)))
X    (if fun (apply fun nil))))
X
X
X    ; individual button bindings
X    ; generally will only need up mouse button: mouse-last-dot
X    ; is saved automatically on down mouse button
X
X; only need to define functions for keys that get used
X
X(put 'mouse-function 32			; up
X     '(lambda ()
X     	(if (and (not (mouse-click-p))
X		 (not scrolling-p))
X	    (copy-region-as-kill (dot) mouse-last-dot))))
X
X(put 'mouse-function 34			; up/shift
X     '(lambda ()
X     	(if (and (not (mouse-click-p))
X		 (not scrolling-p))
X		   (kill-region (dot) mouse-last-dot))))
X
X(put 'mouse-function 40			; up/option
X     '(lambda ()
X     	(if (mouse-click-p)
X	    (progn
X	      (yank)
X	      (exchange-dot-and-mark)))))
X
X(put 'mouse-function 42
X     '(lambda ()		; up/option/shift
X	(if (mouse-click-p)
X	    (insert-buffer (read-buffer "Insert contents of buffer: ")))))
X
X(defun mouse-click-p ()
X  (= (dot) mouse-last-dot))
X
X(defun set-window-boundaries ()
X  (let ((edges (window-edges)))
X    (setq xl (1+ (car edges)))
X    (setq yt (1+ (car (cdr edges))))
X    (let ((temp (car (cdr (cdr edges)))))
X      (setq xr (if (= (screen-width) temp) mouse-max-x temp)))
X    (let ((temp (car (cdr (cdr (cdr edges))))))
X      (setq yb (if (= (screen-height) temp) mouse-max-y temp )))))
X
X(defun select-window-containing-x-and-y (x y)
X  (let ((starting-window (selected-window)))
X    (set-window-boundaries)
X    (while (not (point-in-window x y))
X      (other-window 1)
X      (if (eq (selected-window) starting-window)
X	  (error nil)
X	(set-window-boundaries)))
X    (if (or (= x xr) (= y yb))
X	(setq scrolling-p t)
X      (setq scrolling-p nil))))
X
X(defun point-in-window (x y)
X  (and (<= xl x)(<= x xr)(<= yt y)(<= y yb)))
X
X(defun move-to-window-x-y (x y)
X  (move-to-window-line (- y yt))
X  (move-to-window-column (- x xl)))
X
X(defun move-to-window-column (x)
X  (move-to-column (+ (max 0 (- (window-hscroll) 1)) x)))
X
X(defun mouse-scroll-region (b x y)
X  (if down
X      (if shift
X	  (do-lines b x y)
X	(do-pages b x y)))
X  (if (and up
X	   (or (/= x mouse-last-x)
X	       (/= y mouse-last-y)))
X      (if shift
X	  (do-lines b x y)
X	(do-pages b x y))))
X
X(defun do-lines (b x y)			; fine control over lines
X  (if (= x xr)
X      (cond ((= y yt)(scroll-down 1))
X	    ((= y yb)(scroll-up 1))
X	    (t (if option
X		   (scroll-down (- yb y 1))
X		 (scroll-up (- y yt))))))
X  (if (and (= y yb) (/= x xr))
X      (cond ((<= x xl)(scroll-right 1))
X	    ((>= x (1- xr))(scroll-left 1))
X	    (t (if option
X		   (move-column-right x)
X		 (move-column-left x))))))
X
X(defun move-column-left (x)		;need to mess about a bit because
X  (scroll-left				;first scroll left of 1 just writes
X   (if (= (window-hscroll) 0)		;a column of $s in column 1
X       (- x xl)
X     (- x xl 1))))
X
X(defun move-column-right (x)
X  (scroll-right (- xr x 2)))
X
X
X(defun do-pages (b x y)			; large motions via pages and thumbing
X  (if (= x xr)
X      (cond ((= y yt)(scroll-down nil))
X	    ((= y yb)(scroll-up nil))
X	    (t (goto-percent (/ (* (- y yt 1) 100)
X				(- yb yt 2))))))
X  (if (and (= y yb)(/= x xr))
X      (cond ((<= x xl)(scroll-right (- (window-width)
X				       next-screen-context-lines)))
X	    ((>= x (1- xr))(scroll-left (- (window-width)
X					   next-screen-context-lines)))
X	    (t (goto-horizontal-percent (/ (* (- x xl 1) 100)
X					   (- xr xl 2)))))))
X
X(defun goto-percent (p)
X  (goto-char (/ (* (- (dot-max) (dot-min)) p) 100)))
X
X(defun goto-horizontal-percent (p)	;try to put this percent of columns
X  (let ((window-offset (window-hscroll));in the center column of the window
X	delta)				;unless that would move the first or
X    (setq delta				;last column past the window edge
X	  (- window-offset
X	     (min (max 0 (- (/ (* (screen-width) p) 100)
X			    (/ (- xr xl) 2)))
X		  (- (screen-width) (- xr xl)))))
X    (scroll-right delta)))
X
X    
X(global-set-key "\em" 'move-mac-cursor)
SHAR_EOF
if test 9277 -ne "`wc -c < 'misc/macmouse.el'`"
then
	echo shar: error transmitting "'misc/macmouse.el'" '(should have been 9277 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'misc/macmouse.ml'" '(8406 characters)'
if test -f 'misc/macmouse.ml'
then
	echo shar: will not over-write existing file "'misc/macmouse.ml'"
else
sed 's/^X//' << \SHAR_EOF > 'misc/macmouse.ml'
X; $Header: /c/cak/lib/mlisp/RCS/macmouse.ml,v 1.5 85/11/05 14:01:44 cak Rel $
X; 
X; Macintosh mouse routines for use with John Bruner's uw program.
X; 	Chris Kent, Purdue University Fri Oct 25 1985
X; 	Copyright 1985 by Christopher A. Kent. All rights reserved.
X; 	Permission to copy is given provided that the copy is not
X; 	sold and this copyright notice is included.
X; 
X; Provides a scroll bar/thumbing area in the unused scroll bar with the
X; following features:
X; 	click at line 1 does previous page
X;	click at line 24 does next page
X; 	click anywhere else "thumbs" to the relative portion of the buffer.
X; 	shift-click at line 1 scrolls one line down
X; 	shift-click at line 24 scrolls one line up
X; 	shift-click elsewhere moves line to top of window
X; 	option-shift-click elsewhere moves line to bottom of window
X; 
X; There is also basic positioning and kill-buffer support:
X; 	click in a buffer moves dot there
X; 	drag copies the dragged region to the kill buffer (mark is left
X; 		at the beginning of the region.)
X; 	shift-drag deletes the dragged region to the kill buffer
X;   it is possible to use the scrolling and thumbing area to make the region
X;   larger than a single screen; just click, scroll, release. Make sure
X;   that the last scroll is just a down event; the up must be in the buffer.
X;
X; 	option-click yanks from the kill buffer, doesn't affect mark.
X; 	option-shift-click similarly yanks from a named buffer.
X; 
X
X(declare-global
X    #mouse-last-x		; x of last event
X    #mouse-last-y		; y of last event
X    #mouse-last-b		; buttons at last event
X    #mouse-last-dot		; dot after last event
X    #mouse-last-action		; whether last was scroll (1) or edit (2)
X)
X
X(defun
X    (move-mac-cursor savest b x y up down lock shift option command saveb
X	(setq savest stack-trace-on-error)
X	(setq stack-trace-on-error 0)
X	; decode everything
X	(setq y (- (get-tty-character) 32))
X	(setq x (- (get-tty-character) 32))
X	(setq b (- (get-tty-character) 32))
X	(setq saveb b)
X	(setq command (% b 2))(setq b (/ b 2))	; command key
X	(setq shift (% b 2))(setq b (/ b 2))	; shift 
X	(setq lock (% b 2))(setq b (/ b 2))	; caps-lock
X	(setq option (% b 2))(setq b (/ b 2))	; option
X	(setq down (% b 2))(setq b (/ b 2))	; mouse down
X	(setq up (% b 2))
X	
X	(if (= x 81)		; right margin -- move-dot-to-x-y is wrong
X	    (progn 
X		   (#mouse-scroll-region)
X		   (setq #mouse-last-action 1))
X	    (if (error-occurred 
X		    (if (= #mouse-last-action 2)	; not if just scrolled
X			(setq #mouse-last-dot (dot)))
X		    (move-dot-to-x-y x y)
X		    (backward-character)(forward-character)
X		    (#mouse-edit-action)
X		    (setq #mouse-last-action 2)
X		)
X		(progn 
X		       (#mouse-scroll-region b x y)
X		       (setq #mouse-last-action 1))
X	    ))
X	(setq stack-trace-on-error savest)
X	(if (= down 1)
X	    (progn 
X		   (setq #mouse-last-x x)
X		   (setq #mouse-last-y y)
X		   (setq #mouse-last-b saveb))
X	    (progn 
X		   (setq #mouse-last-x 0)
X		   (setq #mouse-last-y 0)
X		   (setq #mouse-last-b 0)))
X    )
X    
X    (#mouse-edit-action		; marking and editing actions on buttons:
X				;   if no movement, nothing.
X				;   if movement, put  mark at #mouse-last-dot,
X				;      leave dot here,and edit.
X				; editing (on upstrokes):
X				;   unmodified, copy to kill buffer.
X				;   SHIFTed, delete (cut) to kill buffer.
X				; 
X				; option-click yanks from kill buffer; 
X				; shift-option-click from named buffer.
X	(if (= saveb 16)
X	    (#mouse-d))
X	(if (= saveb 17)
X	    (#mouse-dc))
X	(if (= saveb 18)
X	    (#mouse-ds))
X	(if (= saveb 19)
X	    (#mouse-dsc))
X	(if (= saveb 20)
X	    (#mouse-dl))
X	(if (= saveb 21)
X	    (#mouse-dlc))
X	(if (= saveb 22)
X	    (#mouse-dls))
X	(if (= saveb 23)
X	    (#mouse-dlsc))
X	(if (= saveb 24)
X	    (#mouse-do))
X	(if (= saveb 25)
X	    (#mouse-doc))
X	(if (= saveb 26)
X	    (#mouse-dos))
X	(if (= saveb 27)
X	    (#mouse-dosc))
X	(if (= saveb 28)
X	    (#mouse-dol))
X	(if (= saveb 29)
X	    (#mouse-dolc))
X	(if (= saveb 30)
X	    (#mouse-dols))
X	(if (= saveb 31)
X	    (#mouse-dolsc))
X	(if (= saveb 32)
X	    (#mouse-u))
X	(if (= saveb 33)
X	    (#mouse-uc))
X	(if (= saveb 34)
X	    (#mouse-us))
X	(if (= saveb 35)
X	    (#mouse-usc))
X	(if (= saveb 36)
X	    (#mouse-ul))
X	(if (= saveb 37)
X	    (#mouse-ulc))
X	(if (= saveb 38)
X	    (#mouse-uls))
X	(if (= saveb 39)
X	    (#mouse-ulsc))
X	(if (= saveb 40)
X	    (#mouse-uo))
X	(if (= saveb 41)
X	    (#mouse-uoc))
X	(if (= saveb 42)
X	    (#mouse-uos))
X	(if (= saveb 43)
X	    (#mouse-uosc))
X	(if (= saveb 44)
X	    (#mouse-uol))
X	(if (= saveb 45)
X	    (#mouse-uolc))
X	(if (= saveb 46)
X	    (#mouse-uols))
X	(if (= saveb 47)
X	    (#mouse-uolsc))
X    )
X
X    ; individual button bindings
X
X    (#mouse-u			; up
X     	(if (! (#mouse-click-p))
X	    (progn 
X		   (#mouse-set-region)
X		   (Copy-region-to-kill-buffer)
X	    ))
X    )
X
X    (#mouse-uc			; up/command
X    )
X
X    (#mouse-us			; up/shift
X     	(if (! (#mouse-click-p))
X	    (progn 
X		   (#mouse-set-region)
X		   (delete-to-killbuffer)
X	    ))
X    )
X
X    (#mouse-usc			; up/shift/command
X    )
X
X    (#mouse-ul			; up/lock
X    )
X
X    (#mouse-ulc			; up/lock/command
X    )
X
X    (#mouse-uls			; up/lock/shift
X    )
X
X    (#mouse-ulsc		; up/lock/shift/command
X    )
X
X    (#mouse-uo			; up/option
X     	(if (#mouse-click-p)
X	    (yank-from-killbuffer)
X	)
X    )
X
X    (#mouse-uoc			; up/option/command
X    )
X
X    (#mouse-uos			; up/option/shift
X	(if (#mouse-click-p)	; click
X	    (yank-buffer (get-tty-buffer "Insert contents of buffer: "))
X	)
X    )
X
X    (#mouse-uosc		; up/option/shift
X    )
X
X    (#mouse-uol			; up/option/lock
X    )
X
X    (#mouse-uolc		; up/option/lock
X    )
X
X    (#mouse-uols		; up/option/lock/shift
X    )
X
X    (#mouse-uolsc		; up/option/lock/shift/command
X    )
X    
X    (#mouse-d			; down
X    )
X
X    (#mouse-dc			; down/command
X    )
X
X    (#mouse-ds			; down/shift
X    )
X
X    (#mouse-dsc			; down/shift/command
X    )
X
X    (#mouse-dl			; down/lock
X    )
X
X    (#mouse-dlc			; down/lock/command
X    )
X
X    (#mouse-dls			; down/lock/shift
X    )
X
X    (#mouse-dlsc		; down/lock/shift/command
X    )
X
X    (#mouse-do			; down/option
X    )
X
X    (#mouse-doc			; down/option/command
X    )
X
X    (#mouse-dos			; down/option/shift
X    )
X
X    (#mouse-dosc		; down/option/shift
X    )
X
X    (#mouse-dol			; down/option/lock
X    )
X
X    (#mouse-dolc		; down/option/lock
X    )
X
X    (#mouse-dols		; down/option/lock/shift
X    )
X
X    (#mouse-dolsc		; down/option/lock/shift/command
X    )
X
X    (#mouse-set-region		; set the region to be from last dot to dot.
X	(set-mark)
X	(goto-character #mouse-last-dot)
X	(exchange-dot-and-mark)
X    )
X
X    (#mouse-click-p clickp
X     	(if (= (dot) #mouse-last-dot)
X	    (setq clickp 1)
X	    (setq clickp 0)
X	))
X    
X    (#mouse-scroll-region	 ; out of range actions:
X				;    left margin -- hard to generate, ignored
X				;    right margin -- simulate scroll bar
X				;      line 1 -- previous page
X				;      line 24/25 -- next page
X				;      other lines -- thumbing
X				;    top margin -- previous page
X				;    bottom margin -- next page
X				; 
X				; if shifted, deal with lines. 
X				;    line 1 scrolls one line down
X				;    line 24/25 scrolls one line up
X				;    else line to top;  with option to bottom.
X				;
X				; if up stroke is in same place as down
X				; stroke, don't do anything, so clicks in
X				; the scroll region don't do the action
X				; twice.
X	(if (= down 1)
X	    (if (= shift 1)
X		(do-lines)
X		(do-pages))
X	)
X	(if (& (= up 1)
X	       (| (!= x #mouse-last-x) (!= y #mouse-last-y)))
X	    (if (= shift 1)
X		(do-lines)
X		(do-pages)
X	    )
X	)
X	(#mouse-set-region)
X    )
X
X    (do-pages			; large motions via pages and thumbing
X	(if (| (= y 0) (= y 1) (= y 24) (= y 25))
X	    (progn 
X		   (if (| (= y 0) (= y 1))
X		       (previous-page)
X		       (Next-Page)
X		   ))
X	    (if (= x 81)
X		(goto-percent (/ (* y 100) 25))
X	    )
X	))
X
X    (do-lines			; fine control over lines
X	(if (= x 81)
X	    (if (| (= y 1) (= y 24) (= y 25))
X		(if (| (= y 0) (= y 1))
X		    (scroll-one-line-down)
X		    (scroll-one-line-up)
X		)
X		(progn
X		      (move-dot-to-x-y 1 y)
X		      (if (= option 0)
X			  (line-to-top-of-window)
X			  (line-to-bottom-of-window))
X		)
X	    )
X	)
X    )
X
X    (line-to-bottom-of-window nlines i
X	(line-to-top-of-window)
X	(setq i 0)
X	(setq nlines (- (window-height) 1))
X	(while (< i nlines)
X	       (scroll-one-line-down)
X	       (setq i (+ i 1))
X	)
X    )
X
X    (goto-percent
X       (goto-character (/ (* (buffer-size) (arg 1)) 100))
X   )
X)
X    
X(bind-to-key "move-mac-cursor" "\em")
SHAR_EOF
if test 8406 -ne "`wc -c < 'misc/macmouse.ml'`"
then
	echo shar: error transmitting "'misc/macmouse.ml'" '(should have been 8406 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 5 ---

jdb@mordor.s1.gov (John Bruner) (04/07/88)

[UW v4.2 - part 6 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	server/Makefile_4.2
#	server/Makefile_4.3
#	server/openpty.c
#	server/uw_clk.c
#	server/uw_env.c
#	server/uw_fd.c
#	server/uw_main.c
#	server/uw_ipc.c
# This archive created: Mon Apr  4 07:52:04 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d server
then
	echo shar: mkdir server
	mkdir server
fi
echo shar: extracting "'server/Makefile_4.2'" '(1203 characters)'
if test -f 'server/Makefile_4.2'
then
	echo shar: will not over-write existing file "'server/Makefile_4.2'"
else
sed 's/^X//' << \SHAR_EOF > 'server/Makefile_4.2'
X#! /bin/make -f
X#
X#	uw makefile (4.2BSD)
X#
X# INCDIR names the directory where the header files are located.
X#
X# OBJECTS names all of the object files required for the server.
X#
X
XINCDIR	=	../h
X
XOBJECTS	=	uw_clk.o uw_env.o uw_fd.o uw_ipc.o uw_main.o uw_opt.o \
X		uw_pcl.o uw_tty.o uw_utmp.o uw_win.o openpty.o
X
XSOURCES	=	`echo $(OBJECTS) | sed -e 's/\\.o/\\.c/g'`
X
XDEFINES	=	`cat ../DEFINES`
X
XCFLAGS	=	$(DEFINES) -I$(INCDIR) -O
XLFLAGS	=
X
Xuw:		$(OBJECTS)
X	$(CC) $(LFLAGS) -o uw $(OBJECTS) $(LIBS)
X
Xlint:
X	lint -hbx -I$(INCDIR) $(DEFINES) $(SOURCES)
X
Xtags:
X	ctags $(SOURCES)
X
Xdepend: 
X	grep '^#include' $(SOURCES) | \
X	sed -e '/</d' \
X	    -e 's/:[^"]*"\([^"]*\)".*/: ..\/h\/\1/' \
X	    -e 's,^../[a-zA-Z0-9]*/\([^\.]*\)\.[cs],\1.o \1.L,' | \
X	awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
X		else { if (length(rec $$3) > 78) { print rec; rec = $$0; } \
X		       else rec = rec " " $$3 } } \
X	      END { print rec } ' > makedep
X	echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
X	echo '$$r makedep' >>eddep
X	echo 'w' >>eddep
X	cp Makefile Makefile.bak
X	ex - Makefile < eddep
X	rm eddep makedep
X
Xclean:
X	rm *.o
X
X# DO NOT DELETE THIS LINE (or the following blank line) -- make depend uses it
X
SHAR_EOF
if test 1203 -ne "`wc -c < 'server/Makefile_4.2'`"
then
	echo shar: error transmitting "'server/Makefile_4.2'" '(should have been 1203 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/Makefile_4.3'" '(1170 characters)'
if test -f 'server/Makefile_4.3'
then
	echo shar: will not over-write existing file "'server/Makefile_4.3'"
else
sed 's/^X//' << \SHAR_EOF > 'server/Makefile_4.3'
X#! /bin/make -f
X#
X#	uw makefile (4.3BSD)
X#
X# INCDIR names the directory where the header files are located.
X#
X# OBJECTS names all of the object files required for the server.
X#
X
XINCDIR	=	../h
X
XOBJECTS	=	uw_clk.o uw_env.o uw_fd.o uw_ipc.o uw_main.o uw_opt.o \
X		uw_pcl.o uw_tty.o uw_utmp.o uw_win.o openpty.o
X
XSOURCES	=	`echo $(OBJECTS) | sed -e 's/\\.o/\\.c/g'`
X
XDEFINES	=	`cat ../DEFINES`
X
XCFLAGS	=	$(DEFINES) -I$(INCDIR) -O
XLFLAGS	=
X
Xuw:		$(OBJECTS)
X	$(CC) $(LFLAGS) -o uw $(OBJECTS) $(LIBS)
X
Xlint:
X	lint -hbx -I$(INCDIR) $(DEFINES) $(SOURCES)
X
Xtags:
X	ctags $(SOURCES)
X
Xdepend: 
X	$(CC) -M -I$(INCDIR) $(DEFINES) $(SOURCES) | \
X	sed -e ':loop' \
X	    -e 's/\.\.\/[^ /]*\/\.\./../' \
X	    -e 't loop' | \
X	awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
X		else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X		       else rec = rec " " $$2 } } \
X	      END { print rec } ' >> makedep
X	echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
X	echo '$$r makedep' >>eddep
X	echo 'w' >>eddep
X	cp Makefile Makefile.bak
X	ex - Makefile < eddep
X	rm eddep makedep
X
Xclean:
X	rm *.o
X
X# DO NOT DELETE THIS LINE (or the following blank line) -- make depend uses it
X
SHAR_EOF
if test 1170 -ne "`wc -c < 'server/Makefile_4.3'`"
then
	echo shar: error transmitting "'server/Makefile_4.3'" '(should have been 1170 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/openpty.c'" '(3874 characters)'
if test -f 'server/openpty.c'
then
	echo shar: will not over-write existing file "'server/openpty.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/openpty.c'
X/*
X *	openpty - open a pseudo-terminal
X *
X * The first time that the routine is called, the device directory is
X * searched and a list of all candidate pseudo-terminals is compiled.
X * Candidates are defined to be those entries in "/dev" whose names
X * (1) are the same length as PTY_PROTO and (2) start with the
X * initial string PTY_PREFIX.  Further, the master and slave sides
X * must both exist.
X *
X * openpty() attempts to find an unused pseudo-terminal from the list
X * of candidates.  If one is found, the master and slave sides are
X * opened and the file descriptors and names of these two devices are
X * returned in a "ptydesc" structure.  (The address of this structure
X * is supplied by the caller.  Zero is returned if openpty() was
X * successful, -1 is returned if no pty could be found.
X */
X
X#include <sys/types.h>
X#include <sys/dir.h>
X#include <fcntl.h>
X#include <strings.h>
X#include "openpty.h"
X
X#define	DEV_DIR		"/dev"		/* directory where devices live */
X#define	PT_INDEX	(sizeof DEV_DIR)	/* location of 'p' in "pty" */
X
X#define	PTY_PROTO	"ptyp0"		/* prototype for pty names */
X#define	PTY_PREFIX	"pty"		/* prefix required for name of pty */
X
Xstruct ptyinfo {
X	struct ptyinfo	*pi_next;
X	char		*pi_pty;
X	char		*pi_tty;
X};
X
Xstatic struct ptyinfo *ptylist;
X
Xextern char *malloc();
X
Xstatic
Xchar *
Xdevname(name)
Xchar *name;
X{
X	register char *fullname;
X
X	/*
X	 * Construct the full name of a device in DEV_DIR.  Returns
X	 * NULL if it failed (because malloc() failed).
X	 */
X
X	fullname = malloc((unsigned)(sizeof DEV_DIR + 1 + strlen(name)));
X	if (fullname != NULL) {
X		(void)strcpy(fullname, DEV_DIR);
X		(void)strcat(fullname, "/");
X		(void)strcat(fullname, name);
X	}
X	return(fullname);
X}
X
Xstatic
Xisapty(dp)
Xstruct direct *dp;
X{
X	static struct ptyinfo *pi;
X
X	/*
X	 * We don't care about the gory details of the directory entry.
X	 * Instead, what we really want is an array of pointers to
X	 * device names (with DEV_DIR prepended).  Therefore, we create
X	 * this array ourselves and tell scandir() to ignore every
X	 * directory entry.
X	 *
X	 * If malloc() fails, the current directory entry is ignored.
X	 */
X	if (pi == NULL) {
X		pi = (struct ptyinfo *)malloc((unsigned)sizeof *pi);
X		if (pi == NULL)
X			return(0);
X	}
X
X	if (strlen(dp->d_name) == sizeof PTY_PROTO - 1 &&
X	    strncmp(dp->d_name, PTY_PREFIX, sizeof PTY_PREFIX - 1) == 0) {
X		pi->pi_pty = devname(dp->d_name);
X		if (pi->pi_pty == NULL)
X			return(0);
X		pi->pi_tty = malloc((unsigned)(strlen(pi->pi_pty) + 1));
X		if (pi->pi_tty == NULL) {
X			free(pi->pi_pty);
X			return(0);
X		}
X		(void)strcpy(pi->pi_tty, pi->pi_pty);
X		pi->pi_tty[PT_INDEX] = 't';
X		if (access(pi->pi_pty, 0) == 0 && access(pi->pi_tty, 0) == 0) {
X			pi->pi_next = ptylist;
X			ptylist = pi;
X			pi = NULL;
X		} else {
X			free(pi->pi_pty);
X			free(pi->pi_tty);
X		}
X	}
X	return(0);
X}
X
Xopenpty(pt)
Xstruct ptydesc *pt;
X{
X	register struct ptyinfo *pi;
X	static int fail;
X	auto struct direct **dirlist;
X	extern char *re_comp();
X	extern int alphasort();
X
X	/*
X	 * If scandir() fails or no possible pty's are found, then "fail"
X	 * is set non-zero.  If "fail" is non-zero then the routine bombs
X	 * out immediately.  Otherwise, the list of candidates is examined
X	 * starting with the entry following the last one chosen.
X	 */
X	if (fail)
X		return(-1);
X
X	if (!ptylist) {		/* first time */
X		if (scandir(DEV_DIR, &dirlist, isapty, alphasort) < 0 ||
X		    ptylist == NULL) {
X			fail = 1;
X			return(-1);
X		}
X		for (pi=ptylist; pi->pi_next; pi=pi->pi_next)
X			;
X		pi->pi_next = ptylist;	/* make the list circular */
X	}
X
X	pi = ptylist;
X	do {
X		if ((pt->pt_pfd = open(pi->pi_pty, O_RDWR)) >= 0) {
X			if ((pt->pt_tfd = open(pi->pi_tty, O_RDWR)) >= 0) {
X				ptylist = pi->pi_next;
X				pt->pt_pname = pi->pi_pty;
X				pt->pt_tname = pi->pi_tty;
X				return(0);
X			} else
X				(void)close(pt->pt_pfd);
X		}
X		pi = pi->pi_next;
X	} while (pi != ptylist);
X	return(-1);
X}
SHAR_EOF
if test 3874 -ne "`wc -c < 'server/openpty.c'`"
then
	echo shar: error transmitting "'server/openpty.c'" '(should have been 3874 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_clk.c'" '(1577 characters)'
if test -f 'server/uw_clk.c'
then
	echo shar: will not over-write existing file "'server/uw_clk.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_clk.c'
X/*
X *	uw_clk - timer support for UW
X *
X * Copyright 1986 by John D. Bruner.  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 <sys/types.h>
X#include <sys/time.h>
X#include <sys/signal.h>
X#include <sys/resource.h>
X
X#include "uw_param.h"
X#include "uw_clk.h"
X
Xstatic struct timeout *pending;
Xstatic struct timeout *freelist;
X
Xint timer_rdy;			/* nonzero when some timeout is ready to run */
X
Xclk_timeout(secs, fn, arg)
Xint secs;
Xvoid (*fn)();
Xtoarg_t arg;
X{
X	register struct timeout *to, **tol;
X	register time_t curtime;
X	extern time_t time();
X
X	to = freelist;
X	if (!to) {
X		if (!(to = (struct timeout *)malloc(sizeof *to)))
X			return(-1);
X	} else
X		freelist = to->to_next;
X	to->to_fn = fn;
X	to->to_arg = arg;
X
X	if (secs < 0)
X		secs = 0;
X	curtime = time((time_t *)0);
X	to->to_when = curtime + secs;
X
X	tol = &pending;
X	while (*tol && to->to_when > (*tol)->to_when)
X		tol = &(*tol)->to_next;
X	to->to_next = *tol;
X	*tol = to;
X
X	clk_service();
X	return(0);
X}
X
Xclk_service()
X{
X	register struct timeout *to;
X	register time_t curtime;
X
X	curtime = time((time_t *)0);
X	while ((to=pending) && to->to_when <= curtime) {
X		pending = to->to_next;
X		if (to->to_fn) {
X			(*to->to_fn)(to->to_arg);
X			to->to_next = freelist;
X			freelist = to;
X		}
X	}
X
X	timer_rdy = 0;
X	if (pending)
X		(void)alarm((unsigned)(pending->to_when - curtime));
X}
X
Xvoid
Xclk_alarm()
X{
X	/*
X	 * A SIGALRM has been received.
X	 */
X	timer_rdy = 1;
X}
X
Xclk_init()
X{
X	timer_rdy = 0;
X	(void)signal(SIGALRM, clk_alarm);
X}
SHAR_EOF
if test 1577 -ne "`wc -c < 'server/uw_clk.c'`"
then
	echo shar: error transmitting "'server/uw_clk.c'" '(should have been 1577 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_env.c'" '(1654 characters)'
if test -f 'server/uw_env.c'
then
	echo shar: will not over-write existing file "'server/uw_env.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_env.c'
X/*
X *	uw_env - environment manipulation
X *
X * Copyright 1985,1986 by John D. Bruner.  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	MAXENV	128	/* maximum number of arguments in environment */
X
Xstatic char *earray[MAXENV+1];
X
Xenv_set(env)
Xchar **env;
X{
X	register char **ep1, **ep2, *cp;
X	char **ep3;
X	extern char **environ;
X
X
X	/*
X	 * Merge the set of environment strings in "env" into the
X	 * environment.
X	 */
X
X	/*
X	 * The first time through, copy the environment from its
X	 * original location to the array "earray".  This makes it a
X	 * little easier to change things.
X	 */
X
X	if (environ != earray) {
X		ep1=environ;
X		ep2=earray;
X		while(*ep1 && ep2 <= earray+MAXENV)
X			*ep2++ = *ep1++;
X		*ep2++ = (char *)0;
X		environ = earray;
X	}
X
X
X	/*
X	 * If "env" is non-NULL, it points to a list of new items to
X	 * be added to the environment.  These replace existing items
X	 * with the same name.
X	 */
X
X	if (env) {
X		for (ep1=env; *ep1; ep1++) {
X			for (ep2=environ; *ep2; ep2++)
X				if (!env_cmp(*ep1, *ep2))
X					break;
X			if (ep2 < earray+MAXENV) {
X				if (!*ep2)
X					ep2[1] = (char *)0;
X				*ep2 = *ep1;
X			}
X		}
X	}
X
X
X	/* Finally, use an insertion sort to put things in order. */
X
X	for (ep1=environ+1; cp = *ep1; ep1++) {
X		for(ep2=environ; ep2 < ep1; ep2++)
X			if (env_cmp(*ep1, *ep2) < 0)
X				break;
X		ep3 = ep2;
X		for(ep2=ep1; ep2 > ep3; ep2--)
X			ep2[0] = ep2[-1];
X		*ep2 = cp;
X	}
X}
X
X
Xstatic
Xenv_cmp(e1, e2)
Xregister char *e1, *e2;
X{
X	register d;
X
X	do {
X		if (d = *e1 - *e2++)
X			return(d);
X	} while (*e1 && *e1++ != '=');
X	return(0);
X}
SHAR_EOF
if test 1654 -ne "`wc -c < 'server/uw_env.c'`"
then
	echo shar: error transmitting "'server/uw_env.c'" '(should have been 1654 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_fd.c'" '(871 characters)'
if test -f 'server/uw_fd.c'
then
	echo shar: will not over-write existing file "'server/uw_fd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_fd.c'
X/*
X *	uw_fd - file-descriptor/select data
X *
X * Copyright 1986 by John D. Bruner.  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 <sys/types.h>
X
X#include "uw_param.h"
X#include "uw_fd.h"
X
Xstruct selmask selmask[2];
Xstruct fdmap fdmap[FD_SETSIZE];
Xfildes_t nfds;				/* number of file descriptors */
X
Xfd_init()
X{
X	register fildes_t fd;
X
X	nfds = getdtablesize();
X	if (nfds > FD_SETSIZE)
X		nfds = FD_SETSIZE;
X	fdmap[0].f_type = FDT_MAC;
X	fdmap[1].f_type = FDT_MAC;
X	fdmap[2].f_type = FDT_DEBUG;
X	for (fd=3; fd < FD_SETSIZE; fd++) {
X		fdmap[fd].f_type = FDT_NONE;
X		(void)close(fd);
X	}
X	FD_ZERO(&selmask[0].sm_rd);
X	FD_ZERO(&selmask[0].sm_wt);
X	FD_ZERO(&selmask[0].sm_ex);
X}
X
Xfd_exit()
X{
X	register fildes_t fd;
X
X	for (fd=3; fd < nfds; fd++)
X		(void)close(fd);
X}
SHAR_EOF
if test 871 -ne "`wc -c < 'server/uw_fd.c'`"
then
	echo shar: error transmitting "'server/uw_fd.c'" '(should have been 871 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_main.c'" '(8884 characters)'
if test -f 'server/uw_main.c'
then
	echo shar: will not over-write existing file "'server/uw_main.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_main.c'
X/*
X *	uw - UNIX windows program for the Macintosh (host end)
X *
X * Copyright 1985,1986 by John D. Bruner.  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 <sys/types.h>
X#include <sys/file.h>
X#include <sys/wait.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include <sys/ioctl.h>
X#include <pwd.h>
X#include <signal.h>
X#include <errno.h>
X#include <strings.h>
X#include <stdio.h>
X
X#include "uw_param.h"
X#include "uw_clk.h"
X#include "uw_opt.h"
X#include "uw_win.h"
X#include "uw_fd.h"
X#include "uw_pcl.h"
X#include "uw_ipc.h"
X#include "openpty.h"
X
Xint nflag;			/* no startup file */
Xint sflag;			/* "secure" (hee hee) -- no network requests */
Xint errflag;			/* argument error */
Xchar *rcfile;			/* ".uwrc" file name */
X
Xextern void rc_kludge();	/* horrible hack (see rc_kludge()) */
X
Xmain(argc, argv)
Xchar **argv;
X{
X	register int c;
X	register fildes_t fd;
X	extern int calloptscan;
X	extern int errno;
X	extern int optind;
X	extern char *optarg;
X
X	/*
X	 * Make sure we don't accidentally try to run this inside itself.
X	 */
X	if (getenv(UIPC_ENV)) {
X		fprintf(stderr, "%s is already running\n", *argv);
X		exit(1);
X	}
X
X	/*
X	 * Process command-line arguments.
X	 */
X	while ((c=getopt(argc, argv, "f:ns")) != EOF) {
X		switch (c) {
X		case 'f':
X			if (nflag) {
X				fprintf(stderr,
X				    "Cannot specify both \"-f\" and \"-n\"\n");
X				nflag = 0;
X			}
X			rcfile = optarg;
X			break;
X		case 'n':
X			if (rcfile != (char *)0) {
X				fprintf(stderr,
X				    "Cannot specify both \"-f\" and \"-n\"\n");
X				rcfile = (char *)0;
X			}
X			nflag = 1;
X			break;
X		case 's':
X			sflag = 1;
X			break;
X		case '?':
X		default:
X			errflag = 1;
X			break;
X		}
X	}
X	if (errflag) {
X		fprintf(stderr, "Usage: \"%s [-f file] [-n] [-s]\"\n", *argv);
X		exit(1);
X	}
X
X	/*
X	 * Initialize the file descriptor table.
X	 */
X	fd_init();
X	FD_SET(0, &selmask[0].sm_rd);
X
X	/*
X	 * If we can open the "/etc/utmp" for write, do so.
X	 * Immediately afterwards, we lose any magic powers that
X	 * might have allowed us to do this.
X	 */
X#ifdef UTMP
X	fd = open("/etc/utmp", O_WRONLY);
X	(void)setgid(getgid());
X	(void)setuid(getuid());
X	if (fd >= 0)
X		fdmap[fd].f_type = FDT_OTHER;
X	utmp_init(fd);
X#endif
X
X	/*
X	 * Initialize the window structures.
X	 */
X	win_init();
X
X	/*
X	 * Initialize timeouts.
X	 */
X	clk_init();
X
X
X	/*
X	 * Create a UNIX-domain network address, and put its name into
X	 * the environment so that descendents can contact us with new
X	 * window requests.  If we want to be "secure", we don't allow
X	 * any UNIX-domain messages to come in.
X	 */
X	ipc_init(!sflag);
X	if (!sflag)
X		clk_timeout(5, rc_kludge, (toarg_t)0);
X
X
X	/*
X	 * Ignore interrupts, quits, and terminal stops.  Clean up and exit
X	 * if a hangup or termination is received.  Also catch changes in
X	 * child status (so that we can wait for them).  Set up the terminal
X	 * modes.
X	 */
X	(void)signal(SIGHUP, done);
X	(void)signal(SIGINT, SIG_IGN);
X	(void)signal(SIGQUIT, SIG_IGN);
X	(void)signal(SIGTERM, done);
X	(void)signal(SIGTSTP, SIG_IGN);
X	(void)signal(SIGCHLD, cwait);
X
X	tty_mode(1);
X
X
X	/*
X	 * Tell the Macintosh to initialize.
X	 */
X	pcl_entry(0);
X
X	
X	/*
X	 * Create window 1 (to start things off) and wait for input.
X	 * When input is available, process it.
X	 */
X	if (!nflag)
X		finduwrc();
X
X	while (1) {
X		CLK_CHECK();
X		if (calloptscan && protocol->p_chkopt) {
X			calloptscan = 0;
X			(*protocol->p_chkopt)(0);
X		}
X		selmask[1] = selmask[0];
X		if (select(nfds, &selmask[1].sm_rd, &selmask[1].sm_wt,
X		    &selmask[1].sm_ex, (struct timeval *)0) < 0) {
X			if (errno == EINTR)
X				continue;
X			perror("select");
X			done(1);	/* for now -- fix this! */
X		}
X		for (fd=0; fd < nfds; fd++) {
X			if (FD_ISSET(fd, &selmask[1].sm_rd)) {
X				switch (fdmap[fd].f_type) {
X				case FDT_MAC:
X					PCL_RECV(0, (char *)0, 0);
X					break;
X				case FDT_UDSOCK:
X					ipc_udrecv(fd);
X					break;
X				case FDT_ISSOCK:
X					ipc_isrecv(fd);
X					break;
X				case FDT_DATA:
X					PCL_XMIT(0, fdmap[fd].f_win);
X					break;
X				case FDT_CTL:
X					ipc_ctlrecv(0, fd, fdmap[fd].f_win);
X					break;
X				default:
X					/* "can't happen" */
X					FD_CLR(fd, &selmask[0].sm_rd);
X					break;
X				}
X			}
X			if (FD_ISSET(fd, &selmask[1].sm_wt)) {
X				/* "can't happen" */
X				FD_CLR(fd, &selmask[0].sm_wt);
X				break;
X			}
X			if (FD_ISSET(fd, &selmask[1].sm_ex)) {
X				/* "can't happen" */
X				FD_CLR(fd, &selmask[0].sm_ex);
X				break;
X			}
X		}
X	}
X}
X
Xfinduwrc()
X{
X	register struct passwd *pw;
X	register char *homedir;
X
X	/*
X	 * If the global variable "rcfile" is non-NULL, then it specifies
X	 * the name of the startup file.  Otherwise, the name of the startup
X	 * file is "$HOME/.uwrc".  If $HOME is undefined or null, the password
X	 * file is consulted.  The ".uwrc" file is an executable program or
X	 * "/bin/sh" command file.  (For "csh" (ugh) use "#! /bin/csh".)
X	 *
X	 * Returns 0 if the ".uwrc" file doesn't exist, 1 if it does.  As
X	 * a side-effect, this routine sets the global variable "rcfile"
X	 * to the name of the ".uwrc" file.
X	 */
X	if (rcfile == (char *)0) {
X		if ((homedir=getenv("HOME")) == NULL || !*homedir) {
X			if ((pw = getpwuid(getuid())) != NULL)
X				homedir = pw->pw_dir;
X			else
X				return;
X		}
X		rcfile = malloc((unsigned)(strlen(homedir) + sizeof "/.uwrc"));
X		if (rcfile == (char *)0)
X			return;
X		(void)strcpy(rcfile, homedir);
X		(void)strcat(rcfile, "/.uwrc");
X	}
X	if (access(rcfile, F_OK) < 0)
X		rcfile = (char *)0;
X}
X
Xrunuwrc()
X{
X	register int pid;
X	register fildes_t fd;
X	struct ptydesc pt;
X
X	/*
X	 * We use a real fork (rather than a vfork()) because the parent
X	 * doesn't wait for the child.  The caller knows that the file
X	 * exists; however, it cannot determine whether or not it is
X	 * successfully executed.
X	 *
X	 * We acquire a pseudo-terminal for rather convoluted reasons.
X	 * Programs such as "uwtool" expect to be able to inherit tty
X	 * modes from their controlling terminal.  By the time that we
X	 * reach this point, we've already changed our controlling
X	 * terminal to use cbreak mode with no special characters except
X	 * XON/XOFF.  Therefore, we obtain a pseudo-terminal and
X	 * restore our original modes onto it.  We double-fork (sigh,
X	 * another miserable kludge) so that the server does not have
X	 * to wait for the completion of the ".uwrc" file.  (The child
X	 * waits for the grandchild so that the master side of the pty
X	 * remains open until the grandchild is finished.)
X	 */
X	if (openpty(&pt) < 0)
X		return;
X	while ((pid = fork()) < 0)
X		sleep(5);
X	if (pid > 0) {
X		(void)close(pt.pt_pfd);
X		(void)close(pt.pt_tfd);
X	} else {
X		/* child */
X		while ((pid = fork()) < 0)
X			sleep(5);
X		if (pid > 0) {
X			while (wait((int *)0) < 0 && errno == EINTR)
X				;
X			_exit(1);
X			/*NOTREACHED*/
X		} else {
X			/* grandchild */
X			(void)setgid(getgid());
X			(void)setuid(getuid());
X			(void)close(pt.pt_pfd);
X			if (pt.pt_tfd != 0)
X				(void)dup2(pt.pt_tfd, 0);
X			if (pt.pt_tfd != 1);
X				(void)dup2(pt.pt_tfd, 1);
X			if (pt.pt_tfd != 2)
X				(void)dup2(pt.pt_tfd, 2);
X			win_envinit(defwtype, (long)0);
X			(void)signal(SIGHUP, SIG_DFL);
X			(void)signal(SIGINT, SIG_DFL);
X			(void)signal(SIGQUIT, SIG_DFL);
X			(void)signal(SIGTERM, SIG_DFL);
X			(void)signal(SIGTSTP, SIG_IGN);
X			(void)signal(SIGCHLD, SIG_DFL);
X			(void)ioctl(open("/dev/tty",O_RDWR),
X			    (int)TIOCNOTTY, (char *)0);
X			(void)open(pt.pt_tname, O_RDONLY);
X			for (fd=3; fd < nfds; fd++)
X				(void)close(fd);
X			tty_mode(0);
X			(void)execlp(rcfile, rcfile, (char *)0);
X			(void)execl("/bin/sh", "sh", rcfile, (char *)0);
X			_exit(1);
X			/*NOTREACHED*/
X		}
X	}
X}
X
Xvoid
Xrc_kludge()
X{
X	static int firsttime = 1;
X
X	/*
X	 * A problem which occurs with ".uwrc" file handling is that
X	 * the "rc" file is interpreted immediately after the server
X	 * begins, i.e. before it and the Macintosh have (possibly)
X	 * changed from the default protocol to an extended one.
X	 *
X	 * To get around this problem, if a ".uwrc" file exists, it
X	 * is not executed immediately.  Instead, it will be executed
X	 * when this routine is called, either directly by pcl_newpcl()
X	 * when the protocol changes, or after an initial timeout.
X	 *
X	 * It is most unfortunate that "pcl_newpcl" must call "upwards"
X	 * into this source file.
X	 */
X	if (firsttime) {
X		firsttime = 0;
X		if (rcfile != (char *)0)
X			runuwrc();
X		else
X			(void)PCL_NEWW(0, WC_INTERNAL, defwtype, (nwin_t)1, 0L,
X			    (fildes_t)-1, (fildes_t)-1);
X	}
X}
X
Xvoid
Xdone(s)
X{
X	/*
X	 * Clean up and exit.  It is overkill to close all of the file
X	 * descriptors, but it causes no harm.
X	 */
X	pcl_exit(0);
X	utmp_exit();
X	fd_exit();
X	ipc_exit();
X	tty_mode(0);
X	exit(s);
X}
X
Xvoid
Xcwait()
X{
X	register int pid;
X	union wait status;
X	struct rusage rusage;
X
X	/*
X	 * Collect dead children.  Restart any children that have stopped.
X	 */
X	while ((pid=wait3(&status, WNOHANG|WUNTRACED, &rusage)) > 0)
X		if (WIFSTOPPED(status))
X			(void)kill(pid, SIGCONT);
X}
SHAR_EOF
if test 8884 -ne "`wc -c < 'server/uw_main.c'`"
then
	echo shar: error transmitting "'server/uw_main.c'" '(should have been 8884 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_ipc.c'" '(13438 characters)'
if test -f 'server/uw_ipc.c'
then
	echo shar: will not over-write existing file "'server/uw_ipc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_ipc.c'
X/*
X *	uw IPC
X *
X * Copyright 1986 by John D. Bruner.  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 <sys/types.h>
X#include <sys/file.h>
X#include <sys/stat.h>
X#include <sys/socket.h>
X#include <sys/un.h>
X#include <sys/ioctl.h>
X#include <sys/uio.h>
X#include <netinet/in.h>
X#include <strings.h>
X#include <netdb.h>
X#include <errno.h>
X#include <stdio.h>
X
X#include "uw_param.h"
X#include "uw_err.h"
X#include "uw_opt.h"
X#include "uw_win.h"
X#include "uw_fd.h"
X#include "uw_pcl.h"
X#include "uw_ipc.h"
X
X#ifndef ntohs
X/* declaring these as one-element arrays or as NULL pointers is a HACK */
Xextern unsigned long ntohl(), htonl();
Xextern unsigned short ntohs(), htons();
Xstatic struct netadj na_ntoh[1] = {
X	(short (*)())ntohs, (long (*)())ntohl, ntohs, ntohl
X};
Xstatic struct netadj na_hton[1] = {
X	(short (*)())htons, (long (*)())htonl, htons, htonl
X};
X#else
Xstatic struct netadj *na_ntoh = NULL;
Xstatic struct netadj *na_hton = NULL;
X#endif
X
Xstatic int have_udport;
Xstatic char uipc_port[] = "/tmp/uwXXXXXX";
X
Xstatic int inet_sd;
Xstatic struct ipcmsg {
X	int		im_len;
X	struct uwipc	im_msg;
X} *inet_buf;
X
Xextern int errno;
X
Xipc_init(use_uipc)
X{
X	ipc_isinit();
X	if (use_uipc)
X		ipc_udinit();
X}
X
X
X/*
X * UNIX-domain
X */
X
Xstatic
Xipc_udinit()
X{
X	register int len;
X	register char *cp;
X	register fildes_t sd;
X	auto struct sockaddr_un sa;
X	auto char *env[2];
X	extern char *mktemp();
X
X	len = strlen(UIPC_ENV) + sizeof uipc_port + 1;
X	if ((cp = malloc(len)) != NULL) {
X		(void)sprintf(cp, "%s=%s", UIPC_ENV, mktemp(uipc_port));
X		env[0] = cp;
X		env[1] = (char *)0;
X		env_set(env);
X
X		sa.sun_family = AF_UNIX;
X		(void)strncpy(sa.sun_path, uipc_port, sizeof sa.sun_path-1);
X		sa.sun_path[sizeof sa.sun_path-1] = '\0';
X		if ((sd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0 &&
X		    bind(sd,&sa,sizeof sa.sun_family+strlen(sa.sun_path)) >= 0){
X			have_udport = 1;
X			(void)chmod(uipc_port, S_IREAD|S_IWRITE);
X			(void)fcntl(sd, F_SETFL, FNDELAY);
X			fdmap[sd].f_type = FDT_UDSOCK;
X			FD_SET(sd, &selmask[0].sm_rd);
X		}
X	}
X}
X
Xipc_exit()
X{
X	if (have_udport)
X		(void)unlink(uipc_port);
X}
X
Xipc_udrecv(sd)
Xregister fildes_t sd;
X{
X	register struct window *w;
X	register int cnt;
X	struct msghdr msg;
X	auto int fd;
X	struct iovec iov;
X	struct stat st1, st2;
X	union {
X		struct uwipc uwip;
X		char data[1024];
X	} buf;
X
X
X	/*
X	 * main() calls this routine when there is a message waiting on
X	 * the UNIX-domain socket.  The message's access rights are
X	 * expected to contain the file descriptor for the "master" side
X	 * of a pseudo-tty.  The message contains the name of the pty.
X	 * The sender is expected to start up a process on the slave side
X	 * of the pty.  This allows the host end to create windows which
X	 * run something other than the shell.
X	 */
X	fd = -1;
X
X	iov.iov_base = (caddr_t)buf.data;
X	iov.iov_len = sizeof buf - 1;
X
X	msg.msg_name = (caddr_t)0;
X	msg.msg_namelen = 0;
X	msg.msg_iov = &iov;
X	msg.msg_iovlen = 1;
X	msg.msg_accrights = (caddr_t)&fd;
X	msg.msg_accrightslen = sizeof fd;
X
X	if ((cnt=recvmsg(sd, &msg, 0)) < 0 || cnt != buf.uwip.uwip_len)
X		return;
X	switch (buf.uwip.uwip_cmd) {
X	case UWC_NEWT:
X		if (msg.msg_accrightslen > 0 && fd >= 0) {
X			/*
X			 * We can't trust the process which connected to us,
X			 * so we verify that it really passed us a pseudo-tty's
X			 * file descriptor by checking the device name and its
X			 * inode number.  [Of course, if someone else wants to
X			 * hand us a terminal session running under their
X			 * uid....]
X			 */
X			if (cnt == sizeof buf)
X				cnt--;
X			buf.data[cnt] = '\0';
X			if (strncmp(buf.uwip.uwip_newt.uwnt_pty,
X			    "/dev/pty", sizeof "/dev/pty"-1) ||
X			    fstat(fd, &st1) < 0 ||
X			    stat(buf.uwip.uwip_newt.uwnt_pty, &st2) < 0 ||
X			    st1.st_dev != st2.st_dev ||
X			    st1.st_ino != st2.st_ino) {
X				(void)close(fd);
X				return;
X			}
X			/*
X			 * OK, we believe the sender.  We allocate a window and
X			 * tell the Macintosh to create that window on its end.
X			 * If we have no free windows, then we close the file
X			 * descriptor (which will terminate the slave process).
X			 */
X			w = PCL_NEWW(0, WC_INTERNAL,
X			      buf.uwip.uwip_newt.uwnt_type,
X			      (nwin_t)0, buf.uwip.uwip_newt.uwnt_id,
X			      fd, (fildes_t)-1);
X			if (w != NULL) {
X				(void)strncpy(w->w_tty,
X				    buf.uwip.uwip_newt.uwnt_pty,
X				    sizeof w->w_tty-1);
X				w->w_tty[5] = 't'; /* switch to "/dev/ttyp?" */
X				utmp_add(w->w_tty);
X			} else
X				(void)close(fd);
X		}
X		break;
X	case UWC_OPTION:
X		w = win_search(buf.uwip.uwip_option.uwop_id,
X		    protocol->p_maxwin);
X		if (w != NULL) {
X			opt_extopt((caddr_t)w, &w->w_optdefn,
X			    (woptcmd_t)buf.uwip.uwip_option.uwop_cmd,
X			    (woption_t)buf.uwip.uwip_option.uwop_opt,
X			    (char *)&buf.uwip.uwip_option.uwop_val,
X			    (struct netadj *)0);
X		}
X		break;
X	}
X}
X
X
X/*
X * Internet domain
X */
X
Xstatic
Xipc_isinit()
X{
X	register fildes_t sd;
X	register char *cp;
X	struct hostent *h;
X	struct sockaddr_in sin;
X	auto int sinlen;
X	char hostname[32];
X	char *env[2];
X
X	/*
X	 * Allocate enough buffers for each file descriptor to have one.
X	 * This is overkill.
X	 */
X	inet_buf = (struct ipcmsg *)malloc(nfds * sizeof(struct ipcmsg));
X	if (inet_buf == NULL)
X		return;
X
X	/*
X	 * Determine our host name and get an Internet stream socket.
X	 * We really should specify the protocol here (rather than 0)
X	 * but we "know" that it defaults to TCP.
X	 */
X	if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
X		return;
X	sin.sin_family = AF_INET;
X	sin.sin_port = 0;
X	bzero(sin.sin_zero, sizeof sin.sin_zero);
X	if (gethostname(hostname, sizeof hostname) < 0 || hostname[0] == '\0')
X		(void)strcpy(hostname, "localhost");
X	if ((h = gethostbyname(hostname)) != NULL)
X		bcopy(h->h_addr, (char *)&sin.sin_addr, h->h_length);
X	else
X		sin.sin_addr.s_addr = htonl(0x7f000001L); /* 128.0.0.1 (lo0) */
X	if (bind(sd, &sin, sizeof sin) < 0) {
X		/*
X		 * Unable to bind to unspecified port -- try once more with
X		 * loopback device.  If we already were using the loopback
X		 * device we just suffer the inefficiency of doing this twice.
X		 */
X		sin.sin_addr.s_addr = htonl(0x7f000001L);
X		if (bind(sd, &sin, sizeof sin) < 0) {
X			(void)close(sd);
X			return;
X		}
X	}
X
X	/*
X	 * Listen for incoming connections
X	 */
X	if (listen(sd, NWINDOW) < 0) {
X		(void)close(sd);
X		return;
X	}
X
X	/*
X	 * Determine our port number and put our address in the environment.
X	 */
X	sinlen = sizeof sin;
X	if (getsockname(sd, (char *)&sin, &sinlen) < 0) {
X		/* huh?  Oh well, give up */
X		(void)close(sd);
X		return;
X	}
X	if ((cp = malloc(sizeof INET_ENV + 1 + 8 + 1 + 5)) == NULL) {
X		/* no memory, give up */
X		(void)close(sd);
X		return;
X	}
X	sprintf(cp, "%s=%08lx.%05u", INET_ENV,
X	    ntohl(sin.sin_addr.s_addr), ntohs(sin.sin_port));
X	env[0] = cp;
X	env[1] = (char *)0;
X	env_set(env);
X
X	inet_sd = sd;
X	fdmap[sd].f_type = FDT_ISSOCK;
X	FD_SET(sd, &selmask[0].sm_rd);
X}
X
Xipc_isrecv(sd)
Xregister fildes_t sd;
X{
X	register fildes_t fd;
X	register struct uwipc *uwip;
X	register struct window *w;
X	register uwerr_t uwerr;
X	register int len;
X	struct sockaddr sin;
X	struct uwipc reply;
X	auto int sinlen;
X
X	/*
X	 * This routine is called when one of two conditions occur.  It is
X	 * called when an outside process tries to establish a steam
X	 * Internet connection.
X	 *
X	 * Later, as soon as data is available, this routine will be
X	 * called again to handle the external message (which must be
X	 * a "new window" command).
X	 */
X	if (sd == inet_sd) {
X		sinlen = sizeof sin;
X		if ((fd = accept(sd, &sin, &sinlen)) >= 0) {
X			(void)fcntl(fd, F_SETFL, FNDELAY);
X			fdmap[fd].f_type = FDT_ISSOCK;
X			fdmap[fd].f_win = (struct window *)0;
X			FD_SET(fd, &selmask[0].sm_rd);
X			inet_buf[fd].im_len = 0;
X		}
X	} else {
X		switch (ipc_getmsg(sd, inet_buf + sd)) {
X		case -1:
X			(void)close(sd);
X			fdmap[sd].f_type = FDT_NONE;
X			FD_CLR(sd, &selmask[0].sm_rd);
X			FD_CLR(sd, &selmask[0].sm_wt);
X			FD_CLR(sd, &selmask[0].sm_ex);
X			break;
X		case 1:
X			uwip = &inet_buf[sd].im_msg;
X			uwerr = UWE_NONE;
X			if ((uwip->uwip_len < sizeof(struct uwneww) + 
X			    ((char *)&uwip->uwip_neww - (char *)uwip)) ||
X			    uwip->uwip_cmd != UWC_NEWW) {
X				uwerr = UWE_NXTYPE;
X			} else {
X				fd = ipc_ctlopen(sd,
X				    (unsigned)uwip->uwip_neww.uwnw_ctlport);
X				w = PCL_NEWW(0, WC_EXTERNAL,
X				      ntohs(uwip->uwip_neww.uwnw_type),
X				      (nwin_t)0, ntohl(uwip->uwip_neww.uwnw_id),
X				      sd, fd);
X				if (w == (struct window *)0)
X					uwerr = UWE_NXTYPE;	/* for now */
X				else
X					uwerr = UWE_NONE;
X			}
X			len = sizeof(struct uwstatus) +
X			    ((char *)&reply.uwip_status - (char *)&reply);
X			reply.uwip_len = htons(len);
X			reply.uwip_cmd = htons(UWC_STATUS);
X			reply.uwip_status.uwst_err = htons(uwerr);
X			reply.uwip_status.uwst_errno = htons(errno);
X			if (uwerr == UWE_NONE)
X				reply.uwip_status.uwst_id = htonl(w->w_id);
X			else
X				reply.uwip_status.uwst_id = 0;
X			(void)write(sd, (char *)&reply, len);
X			if (uwerr != UWE_NONE) {
X				(void)close(sd);
X				fdmap[sd].f_type = FDT_NONE;
X				FD_CLR(sd, &selmask[0].sm_rd);
X				FD_CLR(sd, &selmask[0].sm_wt);
X				FD_CLR(sd, &selmask[0].sm_ex);
X			}
X			inet_buf[sd].im_len = 0;
X		}
X	}
X}
X
Xipc_ctlopen(sd, port)
Xfildes_t sd;
Xunsigned port;
X{
X	register int fd;
X	auto struct sockaddr_in sin;
X	auto int sinlen;
X
X	/*
X	 * Create a control socket and connect it to the same host as
X	 * "sd" on the specified port.
X	 */
X	sinlen = sizeof sin;
X	if (port == 0 ||
X	    getpeername(sd, (struct sockaddr *)&sin, &sinlen) < 0 ||
X	    (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
X		return(-1);
X	} else {
X		sin.sin_port = port;
X		(void)fcntl(fd, F_SETFL, FNDELAY);
X		if (connect(fd, &sin, sinlen) < 0 && errno != EINPROGRESS) {
X			(void)close(fd);
X			return(-1);
X		} else
X			return(fd);
X	}
X}
X
Xvoid
Xipc_optmsg(win, optcmd, optnum, data, datalen)
Xcaddr_t win;
Xwoptcmd_t optcmd;
Xwoption_t optnum;
Xchar *data;
Xunsigned datalen;
X{
X	register struct window *w;
X	register int len;
X	struct uwipc uwip;
X
X	/*
X	 * Propagate a window option message (WILL, WONT, SET) from the Mac
X	 * to the remote process (external windows only).
X	 */
X	if ((w = (struct window *)win) != NULL && w->w_alloc &&
X	    w->w_class == WC_EXTERNAL && w->w_ctlfd >= 0 &&
X	    optnum <= WONUM_MAX && (optcmd == WOC_WILL || optcmd == WOC_WONT ||
X	     (optcmd == WOC_SET && data != NULL))) {
X		len = datalen +
X		    ((char *)&uwip.uwip_option.uwop_val - (char *)&uwip);
X		uwip.uwip_len = htons(len);
X		uwip.uwip_cmd = htons(UWC_OPTION);
X		uwip.uwip_option.uwop_id = htonl(w->w_id);
X		uwip.uwip_option.uwop_opt = htons(optnum);
X		uwip.uwip_option.uwop_cmd = htons(optcmd);
X		if (optcmd == WOC_SET) {
X			bcopy(data, (char *)&uwip.uwip_option.uwop_val,
X			    (int)datalen);
X			opt_netadj(w->w_optdefn.wod_optlst[optnum].wol_argdefn,
X			    (char *)&uwip.uwip_option.uwop_val, na_hton);
X		}
X		(void)write(w->w_ctlfd, (char *)&uwip, len);
X	}
X}
X
Xipc_ctlrecv(mfd, sd, win)
Xfildes_t mfd;
Xregister fildes_t sd;
Xregister struct window *win;
X{
X	register struct window *w;
X	register struct uwipc *uwip;
X
X	switch (ipc_getmsg(sd, inet_buf + sd)) {
X	case -1:
X		(void)close(sd);
X		fdmap[sd].f_type = FDT_NONE;
X		FD_CLR(sd, &selmask[0].sm_rd);
X		FD_CLR(sd, &selmask[0].sm_wt);
X		FD_CLR(sd, &selmask[0].sm_ex);
X		break;
X	case 1:
X		uwip = &inet_buf[sd].im_msg;
X		switch (uwip->uwip_cmd) {
X		case UWC_KILLW:
X			if ((uwip->uwip_len == sizeof(struct uwkillw) + 
X			    ((char *)&uwip->uwip_killw - (char *)uwip))) {
X				w = win_search(ntohl(uwip->uwip_killw.uwkw_id),
X				    protocol->p_maxwin);
X				if (w == win)
X					PCL_KILLW(mfd, w);
X			}
X			break;
X		case UWC_OPTION:
X			/* hope the message is long enough... sigh */
X			if (uwip->uwip_len > 
X			 ((char *)&uwip->uwip_option.uwop_val - (char *)uwip)) {
X				w = win_search(ntohl(uwip->uwip_option.uwop_id),
X				    protocol->p_maxwin);
X				if (w == win) {
X					opt_extopt((caddr_t)w, &w->w_optdefn,
X					    (woptcmd_t)ntohs(uwip->uwip_option.uwop_cmd),
X					    (woption_t)ntohs(uwip->uwip_option.uwop_opt),
X					    (char *)&uwip->uwip_option.uwop_val,
X					    na_ntoh);
X				}
X			}
X			break;
X		}
X		inet_buf[sd].im_len = 0;
X	}
X}
X
Xipc_getmsg(sd, im)
Xregister fildes_t sd;
Xregister struct ipcmsg *im;
X{
X	register int len;
X	register char *cp;
X
X	/*
X	 * Read some more bytes from socket "sd" into the message buffer
X	 * contained in "im".  Return 1 if the message is now complete,
X	 * -1 if an EOF was reached, or 0 otherwise.  Before returning 1,
X	 * the byte order of the common parameters (command, length) is
X	 * changed from network to host order.
X	 *
X	 * This routine expects the socket to use non-blocking I/O (which
X	 * is enabled by ipc_isrecv() when the connection is accepted).
X	 */
X	cp = (char *)&im->im_msg + im->im_len;
X	if (im->im_len < sizeof(im->im_msg.uwip_len)) {
X		len = read(sd, cp, sizeof im->im_msg.uwip_len - im->im_len);
X		if (len == 0 || (len < 0 && errno != EWOULDBLOCK))
X			return(-1);
X		if ((im->im_len += len) < sizeof im->im_msg.uwip_len)
X			return(0);
X		im->im_msg.uwip_len = ntohs(im->im_msg.uwip_len);
X		if (im->im_msg.uwip_len == sizeof im->im_msg.uwip_len)
X			return(1);
X		cp += len;
X	}
X	if (im->im_msg.uwip_len > sizeof(struct ipcmsg))
X		im->im_msg.uwip_len = sizeof(struct ipcmsg);
X	len = read(sd, cp, im->im_msg.uwip_len - im->im_len);
X	if (len == 0)
X		return(-1);
X	if (len < 0)
X		return((errno==EWOULDBLOCK) ? 0 : -1);
X	if ((im->im_len += len) == im->im_msg.uwip_len) {
X		im->im_msg.uwip_cmd = ntohs(im->im_msg.uwip_cmd);
X		return(1);
X	} else
X		return(0);
X}
SHAR_EOF
if test 13438 -ne "`wc -c < 'server/uw_ipc.c'`"
then
	echo shar: error transmitting "'server/uw_ipc.c'" '(should have been 13438 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 6 ---

jdb@mordor.s1.gov (John Bruner) (04/07/88)

[UW v4.2 - part 7 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	server/uw_opt.c
#	server/uw_pcl.c
# This archive created: Mon Apr  4 07:52:09 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d server
then
	echo shar: mkdir server
	mkdir server
fi
echo shar: extracting "'server/uw_opt.c'" '(14287 characters)'
if test -f 'server/uw_opt.c'
then
	echo shar: will not over-write existing file "'server/uw_opt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_opt.c'
X/*
X *	uw_opt - window option handling for UW
X *
X * Copyright 1986 by John D. Bruner.  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 <sys/types.h>
X
X#include "uw_param.h"
X#include "uw_opt.h"
X
X/*
X * The following variable is a kludge for efficiency.  It is set to
X * a nonzero value when a bitmask is changed, indicating that opt_scan()
X * should be called.
X */
Xint calloptscan;			/* pending,do,dont awaits opt_scan */
X
X/* option input state variables */
Xstatic caddr_t optwin;			/* window */
Xstatic struct woptdefn *optwod;		/* window option definition */
Xstatic woptcmd_t optcmd;		/* option command */
Xstatic woption_t optnum;		/* current option number */
Xstatic woptarg_t *optarg;		/* current encoding */
Xstatic int optcnt;			/* count in current encoding */
Xstatic char *optout;			/* decoded option */
Xstatic char optbuf[512];		/* buffer for decoded option */
X
Xopt_new(wod, generic, unique)
Xregister struct woptdefn *wod, *generic, *unique;
X{
X	register int n, mask;
X
X	/*
X	 * Set up the option definition structure pointed to by "wod" to
X	 * correspond with the option definitions in "generic" (common to
X	 * all window types) and "unique" (per-window).
X	 */
X	mask = (1<<(WONUM_GENERIC+1))-1;
X	if (unique) {
X		wod->wod_askrpt = unique->wod_askrpt & ~mask;
X		wod->wod_pending = unique->wod_pending & ~mask;
X		for (n=WONUM_GENERIC+1; n <= WONUM_MAX; n++)
X			wod->wod_optlst[n] = unique->wod_optlst[n];
X	} else {
X		wod->wod_askrpt = 0;
X		wod->wod_pending = 0;
X		for (n=WONUM_GENERIC+1; n <= WONUM_MAX; n++)
X			wod->wod_optlst[n].wol_argdefn = (woptarg_t *)0;
X	}
X	if (generic) {
X		wod->wod_askrpt |= generic->wod_askrpt & mask;
X		wod->wod_pending |= generic->wod_pending & mask;
X		for (n=1; n <= WONUM_GENERIC; n++)
X			wod->wod_optlst[n] = generic->wod_optlst[n];
X	} else {
X		for (n=1; n <= WONUM_GENERIC; n++)
X			wod->wod_optlst[n].wol_argdefn = (woptarg_t *)0;
X	}
X	wod->wod_do = wod->wod_askrpt;
X	wod->wod_dont = 0;
X	wod->wod_inquire = 0;
X	calloptscan = 1;
X}
X
Xopt_renew(wod, report)
Xregister struct woptdefn *wod;
Xint report;
X{
X	/*
X	 * Reset "wod_do" for all window options that we want the Macintosh
X	 * to report to us.  If "report" is nonzero, send the Mac the
X	 * current values of these options.
X	 */
X	wod->wod_do = wod->wod_askrpt;
X	wod->wod_dont = 0;
X	if (report)
X		wod->wod_pending = wod->wod_askrpt;
X	calloptscan = 1;
X}
X
Xopt_newtype(wod, generic, unique)
Xregister struct woptdefn *wod, *generic, *unique;
X{
X	register int n, bit;
X	register woptbmask_t oldask;
X
X	/*
X	 * Change the window options to reflect a new window emulation type.
X	 * The new emulation may not support all of the events that the old
X	 * one did, and in any event they may not mean the same thing.
X	 */
X	oldask = wod->wod_askrpt;
X	opt_new(wod, generic, unique);
X	for (n=1, bit=2; n <= WONUM_GENERIC; n++,bit<<=1) {
X		if ((oldask&bit) && !(wod->wod_askrpt&bit))
X			wod->wod_dont |= bit;
X		if (!(oldask&bit) && (wod->wod_askrpt&bit))
X			wod->wod_do |= bit;
X	}
X	for ( ; n <= WONUM_MAX; n++, bit<<=1)
X		if (wod->wod_askrpt&bit)
X			wod->wod_do |= bit;
X	calloptscan = 1;
X}
X
Xopt_setext(wod, fn)
Xregister struct woptdefn *wod;
Xregister void (*fn)();
X{
X	register int n;
X
X	/*
X	 * Set "wol_ext" to "fn" for each option that has a defined "wol_set".
X	 */
X	for (n=1; n <= WONUM_MAX; n++)
X		if (wod->wod_optlst[n].wol_set)
X			wod->wod_optlst[n].wol_ext = fn;
X}
X
Xopt_scan(w, wod, fn, mfd, cmd)
Xcaddr_t w;
Xregister struct woptdefn *wod;
Xvoid (*fn)();
Xfildes_t mfd;
Xint cmd;
X{
X	register struct woptlst *wol;
X	register char *cp;
X	register int n, bit, maxsize;
X	char buf[512];
X
X	/*
X	 * Scan the entire list of options for pending ones.  For each
X	 * one, call "fn".  "cmd" is the command that we are to pass as the
X	 * first argument to "fn".
X	 *
X	 * Note that we must send data (wod_pending) before processing
X	 * DO commands (wod_do); otherwise, the host and Mac may not
X	 * agree upon the value of a window option.  (The Mac might
X	 * respond to the "do" command before it sees the new value.)
X	 */
X	cp = buf;
X#ifdef notdef
X	for (n=1,bit=2,wol=wod->wod_optlst+1; n<=WONUM_MAX; n++,bit<<=1,wol++) {
X#else
X	for (n=WONUM_MAX, bit=(1<<WONUM_MAX), wol=wod->wod_optlst+WONUM_MAX;
X	     n > 0;
X	     n--, bit >>= 1, wol--) {
X#endif
X		if (wod->wod_pending&bit) {
X			wod->wod_pending &= ~bit;
X			if (wol->wol_argdefn) {
X				maxsize = 2 +
X				    opt_size(wol->wol_argdefn);
X				if (cp > buf + sizeof buf - maxsize - 1) {
X					*cp++ = 0;
X					(*fn)(mfd, cmd, buf, cp-buf);
X					cp = buf;
X				}
X				if (WONUM_USELONG(n)) {
X					*cp++ = WOC_SET|WONUM_LPREFIX;
X					*cp++ = WONUM_LENCODE(n);
X				} else
X					*cp++ = WOC_SET|WONUM_SENCODE(n);
X				cp += opt_encode(cp, wol->wol_argdefn,
X				    (*wol->wol_get)(w, n));
X			}
X		}
X		if (wod->wod_inquire&bit) {
X			wod->wod_inquire &= ~bit;
X			if (cp > buf + sizeof buf - 3) {
X				*cp++ = 0;
X				(*fn)(mfd, cmd, buf, cp-buf);
X				cp = buf;
X			}
X			if (wol->wol_argdefn) {
X				if (WONUM_USELONG(n)) {
X					*cp++ = WOC_INQUIRE|WONUM_LPREFIX;
X					*cp++ = WONUM_LENCODE(n);
X				} else
X					*cp++ = WOC_INQUIRE|WONUM_SENCODE(n);
X			}
X		}
X		if ((wod->wod_do|wod->wod_dont)&bit) {
X			if (cp > buf + sizeof buf - 3) {
X				*cp++ = 0;
X				(*fn)(mfd, cmd, buf, cp-buf);
X				cp = buf;
X			}
X			if (wod->wod_do&bit) {
X				wod->wod_do &= ~bit;
X				wod->wod_dont &= ~bit;
X				if (wol->wol_argdefn) {
X					if (WONUM_USELONG(n)) {
X						*cp++ = WOC_DO|WONUM_LPREFIX;
X						*cp++ = WONUM_LENCODE(n);
X					} else
X						*cp++ = WOC_DO|WONUM_SENCODE(n);
X				}
X			} else if (wod->wod_dont&bit) {
X				wod->wod_do &= ~bit;
X				wod->wod_dont &= ~bit;
X				if (wol->wol_argdefn) {
X					if (WONUM_USELONG(n)) {
X						*cp++ = WOC_DONT|WONUM_LPREFIX;
X						*cp++ = WONUM_LENCODE(n);
X					} else
X						*cp++=WOC_DONT|WONUM_SENCODE(n);
X				}
X			}
X		}
X		if (cp > buf) {
X			*cp++ = 0;
X			(*fn)(mfd, cmd, buf, cp-buf);
X			cp = buf;
X		}
X	}
X}
X
Xopt_size(woa)
Xregister woptarg_t *woa;
X{
X	register int size, cnt;
X
X	/*
X	 * Determine the maximum size of an option whose argument encoding
X	 * is specified by "woa".  This does NOT include additional encoding
X	 * (e.g. for meta characters) at the protocol level.
X	 */
X	if (woa) {
X		for (size=0; *woa != WOA_END; woa++) {
X			cnt = *woa & ~WOA_CMDMASK;
X			switch (*woa & WOA_CMDMASK) {
X			case WOA_CHARS(0):
X			case WOA_STRING(0):
X				size += cnt;
X				break;
X			case WOA_UDATA(0):
X				size += (cnt + 5) / 6;
X				break;
X			}
X		}
X	} else
X		size = 0;
X	return(size);
X}
X
Xopt_encode(buf, woa, data)
Xchar *buf;
Xregister woptarg_t *woa;
Xchar *data;
X{
X	register char *cp, *cq;
X	register int n, cnt;
X	register unsigned long ival;
X	union {
X		struct {
X			char	c1;
X			short	s;
X		}	cs;
X		struct {
X			char	c2;
X			long	l;
X		}	cl;
X	} u;
X
X	/*
X	 * Encode "data" according to the option argument specifier "woa"
X	 * into the buffer "buf".  Return the number of bytes of "buf"
X	 * actually used.  The caller has already verified that "buf" is
X	 * large enough.
X	 */
X	if (!data)
X		return(0);
X	for (cp=buf,cq=data; *woa != WOA_END; woa++) {
X		cnt = *woa & ~WOA_CMDMASK;
X		switch (*woa & WOA_CMDMASK) {
X		case WOA_CHARS(0):
X			for (n=0; n < cnt; n++)
X				*cp++ = *cq++;
X			break;
X		case WOA_STRING(0):
X			for (n=0; n < cnt-1 && *cq; n++)
X				*cp++ = *cq++;
X			if (n < cnt)
X				cq += cnt-n;
X			*cp++ = '\0';
X			break;
X		case WOA_UDATA(0):
X			if (cnt <= NBBY) {
X				ival = (unsigned char)*cq++;
X			} else if (cnt <= sizeof(short)*NBBY) {
X				while ((int)cq & ((char *)&u.cs.s-&u.cs.c1-1))
X					cq++;
X				ival = *(unsigned short *)cq;
X				cq += sizeof(short);
X			} else {
X				while ((int)cq & ((char *)&u.cl.l-&u.cl.c2-1))
X					cq++;
X				ival = *(unsigned long *)cq;
X				cq += sizeof(long);
X			}
X			if (cnt != sizeof(long)*NBBY)
X				ival &= (1<<cnt) - 1;
X			for (n=0; n < cnt; n += 6, ival >>= 6)
X				*cp++ = (ival & 077) | 0100;
X			break;
X		}
X	}
X	return(cp-buf);
X}
X			
Xopt_istart(w, wod)
Xcaddr_t w;
Xstruct woptdefn *wod;
X{
X	/*
X	 * Start collecting input for a window option specification.
X	 */
X	optwin = w;
X	optwod = wod;
X	optnum = 0;
X}
X
Xopt_input(c)
Xchar c;
X{
X	register int cnt, bit;
X	register struct woptdefn *wod;
X	register struct woptlst *wol;
X	register unsigned long ival;
X	union {
X		struct {
X			char	c1;
X			short	s;
X		}	cs;
X		struct {
X			char	c2;
X			long	l;
X		}	cl;
X	} u;
X
X	/*
X	 * Add the received character "c" to the current option specification.
X	 * If it is complete, take the appropriate action.  If option 0
X	 * (the endmarker) is received, return 0 (to notify the caller that
X	 * we are done).  Otherwise, return 1 -- more option data remains
X	 * to be processed.
X	 *
X	 * This code isn't as readable as it should be; there are far too
X	 * many return statements floating around.  Sorry about that.
X	 */
X	if (optwin) {
X		wod = optwod;
X		if (optnum == 0 || optnum == WONUM_MAX+1) {
X			/* start (or continue) decoding a new option */
X			if (optnum == 0) {
X				/* start new option (or decode endmarker) */
X				if (c & WONUM_MASK) {
X					/* new option */
X					optcmd = c & WOC_MASK;
X					if (WOC_BADCMD(optcmd)) {
X						opt_iflush();
X						return(0);
X					}
X					if (c == WONUM_LPREFIX) {
X						optnum = WONUM_MAX+1;
X						return(1);
X					} else
X						optnum = WONUM_SDECODE(c);
X				} else {
X					/* end of options */
X					opt_iflush();
X					return(0);
X				}
X			} else {
X				/* read second byte of long option number */
X				optnum = WONUM_LDECODE(c);
X				if (optnum > WONUM_MAX) {
X					opt_iflush();
X					return(0);
X				}
X			}
X			/*
X			 * This point is reached when the option number has
X			 * been completely decoded.  If the command is not
X			 * WOC_SET, then it has no arguments and we can
X			 * process it immediately.
X			 */
X			wol = &wod->wod_optlst[optnum];
X			bit = 1<<optnum;
X			if (optcmd == WOC_SET) {
X				optout = optbuf;
X				optcnt = 0;
X				optarg = wol->wol_argdefn;
X				if (!optarg) {
X					opt_iflush();
X					return(0);
X				}
X			} else {
X				if (wol->wol_ext &&
X				    (optcmd == WOC_WILL || optcmd == WOC_WONT))
X					(*wol->wol_ext)(optwin, optcmd,
X					    optnum, (char *)0, 0);
X				switch (optcmd) {
X				case WOC_INQUIRE:
X					wod->wod_pending |= bit;
X					calloptscan = 1;
X					break;
X				case WOC_DO:
X				case WOC_DONT:
X					break;
X				case WOC_WILL:
X					wod->wod_askrpt |= bit;
X					wod->wod_do &= ~bit;
X					break;
X				case WOC_WONT:
X					wod->wod_askrpt &= ~bit;
X					wod->wod_dont &= ~bit;
X					break;
X				}
X				optnum = 0;
X			}
X			return(1);
X		} else {
X			/* continue processing argument to option */
X			wol = &wod->wod_optlst[optnum];
X			bit = 1<<optnum;
X			cnt = *optarg & ~WOA_CMDMASK;
X			switch (*optarg & WOA_CMDMASK) {
X			case WOA_CHARS(0):
X				*optout++ = c;
X				optcnt++;
X				break;
X			case WOA_STRING(0):
X				*optout++ = c;
X				optcnt++;
X				if (!c) {
X					optout += cnt - optcnt;
X					optcnt = cnt;
X				} else if (optcnt == cnt-1) {
X					*optout++ = '\0';
X					optcnt = cnt;
X				}
X				break;
X			case WOA_UDATA(0):
X				if (optcnt == 0) {
X					if (cnt <= NBBY) {
X						*optout = 0;
X					} else if (cnt <= sizeof(short)*NBBY) {
X						while ((int)optout & ((char *)&u.cs.s-&u.cs.c1-1))
X							optout++;
X						*(short *)optout = 0;
X					} else {
X						while ((int)optout & ((char *)&u.cl.l-&u.cl.c2-1))
X							optout++;
X						*(long *)optout = 0;
X					}
X				}
X				ival = (c & 077) << optcnt;
X				if (cnt != NBBY*sizeof(long))
X					ival &= (1<<cnt) - 1;
X				optcnt += 6;
X				if (cnt <= NBBY) {
X					*(unsigned char *)optout |= (unsigned char)ival;
X					if (optcnt >= cnt)
X						optout++;
X				} else if (cnt <= sizeof(short)*NBBY) {
X					*(unsigned short *)optout |= (unsigned short)ival;
X					if (optcnt >= cnt)
X						optout += sizeof(short);
X				} else {
X					*(unsigned long *)optout |= ival;
X					if (optcnt >= cnt)
X						optout += sizeof(long);
X				}
X				break;
X			}
X			if (optcnt >= cnt) {
X				optcnt = 0;
X				if (*++optarg == WOA_END) {
X					wod->wod_pending &= ~bit;
X					(*wol->wol_set)(optwin, optnum, optbuf);
X					if (wol->wol_ext) {
X						(*wol->wol_ext)(optwin, WOC_SET,
X						    optnum, optbuf,
X						    optout-optbuf);
X					}
X					optnum = 0;
X				}
X			}
X			return(1);
X		}
X		/*NOTREACHED*/
X	}
X	return(0);
X}
X
Xopt_iflush()
X{
X	optwin = (caddr_t)0;
X}
X
Xopt_extopt(w, wod, cmd, num, data, na)
Xcaddr_t w;
Xregister struct woptdefn *wod;
Xwoptcmd_t cmd;
Xwoption_t num;
Xchar *data;
Xstruct netadj *na;
X{
X	register struct woptlst *wol;
X
X	if (w != NULL && wod != NULL && num <= WONUM_MAX) {
X		wol = wod->wod_optlst + num;
X		if (wol->wol_argdefn) {
X			switch (cmd) {
X			case WOC_SET:
X				if (data && wol->wol_set) {
X					if (na) {
X						opt_netadj(wol->wol_argdefn,
X						    data, na);
X					}
X					/*
X					 * Set the new value and notify the Mac.
X					 * Because of a race condition (the Mac
X					 * might concurrently be sending us its
X					 * value for this option), we ask the
X					 * Mac to send back the value after it
X					 * is set.
X					 */
X					(*wol->wol_set)(w, num, data);
X					WOPT_SET(wod->wod_pending, num);
X					WOPT_SET(wod->wod_inquire, num);
X					calloptscan = 1;
X				}
X				break;
X			case WOC_INQUIRE:
X				WOPT_SET(wod->wod_inquire, num);
X				calloptscan = 1;
X				break;
X			case WOC_DO:
X				WOPT_SET(wod->wod_do, num);
X				WOPT_SET(wod->wod_askrpt, num);
X				calloptscan = 1;
X				break;
X			case WOC_DONT:
X				WOPT_SET(wod->wod_dont, num);
X				WOPT_CLR(wod->wod_askrpt, num);
X				calloptscan = 1;
X				break;
X			}
X		}
X	}
X}
X
Xopt_netadj(woa, data, na)
Xregister woptarg_t *woa;
Xchar *data;
Xregister struct netadj *na;
X{
X	register char *cp;
X	register int cnt;
X	union {
X		struct {
X			char	c1;
X			short	s;
X		}	cs;
X		struct {
X			char	c2;
X			long	l;
X		}	cl;
X	} u;
X
X	/*
X	 * Convert an option (in internal format) from host byte order
X	 * to network byte order.  If the two are the same then this is
X	 * a NOP.
X	 */
X	if (data && na) {
X		for (cp=data; *woa != WOA_END; woa++) {
X			cnt = *woa & ~WOA_CMDMASK;
X			switch (*woa & WOA_CMDMASK) {
X			case WOA_CHARS(0):
X			case WOA_STRING(0):
X				cp += cnt;
X				break;
X			case WOA_UDATA(0):
X				if (cnt <= NBBY) {
X					cp++;
X				} else if (cnt <= sizeof(short)*NBBY) {
X					while ((int)cp & ((char *)&u.cs.s-&u.cs.c1-1))
X						cp++;
X					*(u_short *)cp =
X					    (*na->na_ushort)(*(u_short *)cp);
X					cp += sizeof(short);
X				} else {
X					while ((int)cp & ((char *)&u.cl.l-&u.cl.c2-1))
X						cp++;
X					*(u_short *)cp =
X					    (*na->na_ushort)(*(u_short *)cp);
X					cp += sizeof(long);
X				}
X			}
X		}
X	}
X}
SHAR_EOF
if test 14287 -ne "`wc -c < 'server/uw_opt.c'`"
then
	echo shar: error transmitting "'server/uw_opt.c'" '(should have been 14287 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_pcl.c'" '(21808 characters)'
if test -f 'server/uw_pcl.c'
then
	echo shar: will not over-write existing file "'server/uw_pcl.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_pcl.c'
X/*
X *	uw_pcl - protocol handling for UW
X *
X * Copyright 1985,1986 by John D. Bruner.  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 <sys/types.h>
X#include <sys/ioctl.h>
X#include <errno.h>
X
X#include "uw_param.h"
X#include "uw_clk.h"
X#include "uw_opt.h"
X#include "uw_win.h"
X#include "uw_pcl.h"
X#include "openpty.h"
X
X#define	XON	0021			/* ASCII XON */
X#define	XOFF	0023			/* ASCII XOFF */
X#define	RUB	0177			/* ASCII RUBout */
X#define	META	0200			/* "meta" bit for whatever it's worth */
X
X/*
X * Protocol negotiation is performed by a finite state machine (implemented
X * in pcl_haggle()).  The states are defined as the enumerated type
X * "pnstate_t".  The inputs have type "pnreq_t".
X */
Xtypedef enum {
X	PNST_NOP,			/* no protocol negotiation */
X	PNST_AWAIT,			/* timing out an ASKPCL */
X	PNST_CWAIT,			/* timing out a CANPCL */
X	PNST_OK,			/* negotiations completed */
X	PNST_FAIL			/* negotiation failed */
X} pnstate_t;
X
Xtypedef unsigned short pnreq_t;		/* finite state machine requests */
X#define	PNRQ_PCL	0000377		/* protocol mask */
X#define	PNRQ_CMD	0177400		/* command mask: */
X#define	PNRQ_NONE	(pnreq_t)(0<<8)	/*	no request */
X#define	PNRQ_START	(pnreq_t)(1<<8)	/*	start negotiation */
X#define	PNRQ_AWAIT	(pnreq_t)(2<<8)	/*	timeout waiting for ASKPCL */
X#define	PNRQ_ASK	(pnreq_t)(3<<8)	/*	process received ASKPCL */
X#define	PNRQ_CAN	(pnreq_t)(4<<8)	/*	process received CANPCL */
X#define	PNRQ_SET	(pnreq_t)(5<<8)	/*	process received SETPCL */
X#define	PNRQ_CWAIT	(pnreq_t)(6<<8)	/*	timeout waiting for CANPCL */
X#define	PNRQ_INIT	(pnreq_t)(7<<8)	/*	initialize everything */
X
Xstatic int p1_ctlch[] = { -1, P1_IAC, XON, XOFF, -1, -1, -1, -1 };
X
Xextern void p1_entry(), p1_renew(), p2_renew();
Xextern struct window *p1_neww(), *p2_neww();
Xextern void p1_killw(), p1_xmit(), p1_recv();
Xextern void p1_askpcl(), p1_canpcl(), p1_setpcl();
Xextern void p2_recv(), p2_chkopt(), p2_sendopt();
X
Xstatic struct protocol pcl_table[] = {
X	{
X	  ' ',
X	  P1_NWINDOW,
X	  p1_ctlch, sizeof p1_ctlch / sizeof p1_ctlch[0],
X	  p1_entry, NULL, p1_renew,
X	  p1_neww, p1_killw,
X	  p1_xmit, p1_recv, NULL, NULL,
X	  p1_askpcl, p1_canpcl, p1_setpcl
X	},
X	{
X	  '!',
X	  P2_NWINDOW,
X	  p1_ctlch, sizeof p1_ctlch / sizeof p1_ctlch[0],
X	  p1_entry, NULL, p2_renew,
X	  p2_neww, p1_killw,
X	  p1_xmit, p2_recv, p2_chkopt, p2_sendopt,
X	  p1_askpcl, p1_canpcl, p1_setpcl
X	},
X};
X
Xstruct protocol *protocol = pcl_table;
X
X/*
X * Two "current" windows are defined: the current input window (for
X * input from the Macintosh) and the current output window (for output
X * to the Macintosh).
X */
Xstatic struct {
X	struct window	*in;
X	struct window	*out;
X} curwin;
X
X
Xpcl_entry(mfd)
Xregister fildes_t mfd;
X{
X	/*
X	 * This routine is called to start up protocol handling.  We always
X	 * start with protocol 1 (the original UW protocol).
X	 */
X	protocol = pcl_table;
X	pcl_haggle(mfd, PNRQ_INIT);
X	if (protocol->p_entry)
X		(*protocol->p_entry)(mfd);
X}
X
Xpcl_exit(mfd)
Xregister fildes_t mfd;
X{
X	/*
X	 * This routine is called when we shut down (just before the server
X	 * exits).
X	 */
X	if (protocol->p_exit)
X		(*protocol->p_exit)(mfd);
X	protocol = pcl_table;
X}
X
Xstatic
Xpcl_newpcl(newproto)
Xstruct protocol *newproto;
X{
X	extern void rc_kludge();
X
X	/*
X	 * Switch to new protocol "newproto".  Right now we can get away
X	 * with just changing the value of "protocol".  Eventually we will
X	 * probably want to call protocol-dependent functions to shut down
X	 * the old protocol and start up the new one.
X	 */
X	protocol = newproto;
X
X	/*
X	 * This is a horrible kludge.  See rc_kludge() in "main.c" for
X	 * further details.
X	 */
X	rc_kludge();
X}
X
Xstatic
Xvoid
Xpcl_tohaggle(arg)
Xregister toarg_t arg;
X{
X	/*
X	 * This is a kludge to get around the single-argument restriction
X	 * on clk_timeout.  We split the argument "arg" into two 16-bit
X	 * pieces and invoke pcl_haggle.
X	 */
X	pcl_haggle((fildes_t)((arg>>16)&0177777), (pnreq_t)(arg&0177777));
X}
X
Xstatic
Xpcl_haggle(mfd, req)
Xfildes_t mfd;
Xregister pnreq_t req;
X{
X	register struct protocol *p, *q;
X	register char pname;
X	register int request;
X	static pnstate_t pnstate;
X	static int waitcnt;
X
X	/*
X	 * This routine implements the finite-state machine that handles
X	 * protocol negotiation.  This routine is called by routines which
X	 * recognize incoming protocol commands and at 5 second intervals
X	 * when negotiations are in progress.  The current protocol is
X	 * described by the variable "protocol".
X	 */
X	if (req == PNRQ_INIT) {
X		waitcnt = 0;
X		pnstate = PNST_NOP;
X		req = PNRQ_NONE;
X	}
X	if (!(p = protocol) || !p->p_askpcl || !p->p_canpcl || !p->p_setpcl) {
X		req = PNRQ_NONE;
X	} else {
X		pname = req & PNRQ_PCL;
X		request = req & PNRQ_CMD;
X		switch (request) {
X		case PNRQ_START:	/* start protocol negotiation */
X			/*
X			 * The Macintosh is responsible for starting protocol
X			 * negotiation (if it wants something other than the
X			 * standard protocol).  This code is present for
X			 * purposes of exposition only.
X			 */
X			(*p->p_askpcl)(mfd);
X			req = PNRQ_AWAIT | pname;
X			waitcnt = 0;
X			pnstate = PNST_AWAIT;
X			break;
X		case PNRQ_AWAIT:	/* timeout an ASKPCL */
X			/*
X			 * This state also is not reached on the host.
X			 */
X			if (pnstate == PNST_AWAIT) {
X				if (++waitcnt > 3) {
X					pnstate = PNST_FAIL;
X					req = PNRQ_NONE;
X				} else
X					(*p->p_askpcl)(mfd);
X			} else
X				req = PNRQ_NONE;
X			break;
X		case PNRQ_ASK:		/* handle received ASKPCL */
X			q = pcl_table+sizeof pcl_table/sizeof pcl_table[0] - 1;
X			(*p->p_canpcl)(mfd, q->p_name);
X			pnstate = PNST_CWAIT;
X			req = PNRQ_CWAIT | q->p_name;
X			waitcnt = 0;
X			break;
X		case PNRQ_CAN:		/* handle received CANPCL */
X			for (q=pcl_table+sizeof pcl_table/sizeof pcl_table[0]-1;
X			     q > pcl_table && q->p_name > pname;
X			     q--)
X				;
X			if (q->p_name == pname || q == pcl_table) {
X				(*p->p_setpcl)(mfd, q->p_name);
X				pcl_newpcl(q);
X				pnstate = PNST_OK;
X				req = PNRQ_NONE;
X			} else {
X				(*p->p_canpcl)(mfd, q->p_name);
X				pnstate = PNST_CWAIT;
X				req = PNRQ_CWAIT | q->p_name;
X				waitcnt = 0;
X			}
X			break;
X		case PNRQ_CWAIT:	/* timeout a CANPCL */
X			if (pnstate == PNST_CWAIT) {
X				if (++waitcnt > 3) {
X					pnstate = PNST_FAIL;
X					req = PNRQ_NONE;
X				} else
X					(*p->p_canpcl)(mfd, pname);
X			} else
X				req = PNRQ_NONE;
X			break;
X		case PNRQ_SET:		/* handle a received SETPCL */
X			for (q=pcl_table+sizeof pcl_table/sizeof pcl_table[0]-1;
X			     q > pcl_table && q->p_name != pname;
X			     q--)
X				;
X			if (q->p_name == pname) {
X				pcl_newpcl(q);
X				pnstate = PNST_OK;
X				req = PNRQ_NONE;
X			} else {
X				/*
X				 * We are in trouble now -- the Mac has
X				 * instructed us to switch to a protocol
X				 * that we can't support.  We switch back
X				 * to protocol 1 and hope that our message
X				 * to the Mac (telling it to switch to
X				 * protocol 1) will be interpreted correctly.
X				 */
X				pnstate = PNST_FAIL;
X				req = PNRQ_NONE;
X				(*p->p_setpcl)(mfd, ' ');
X				if (p != pcl_table)
X					pcl_newpcl(pcl_table);
X			}
X			break;
X		}
X		if (req != PNRQ_NONE)
X			(void)clk_timeout(5*CLK_HZ,
X			    pcl_tohaggle, (toarg_t)(((long)mfd<<16)|req));
X	}
X}
X
Xstatic
Xvoid
Xp1_entry(mfd)
Xfildes_t mfd;
X{
X	static char cmdbuf[2] = { P1_IAC };
X
X	cmdbuf[1] = P1_DIR_HTOM|P1_FN_MAINT|P1_MF_ENTRY;
X	(void)write(mfd, cmdbuf, sizeof cmdbuf);
X}
X
Xstatic
Xstruct window *
Xp1_neww(mfd, wclass, wtype, wnum, wid, datafd, ctlfd)
Xfildes_t mfd;
Xwclass_t wclass;
Xwtype_t wtype;
Xnwin_t wnum;
Xlong wid;
Xfildes_t datafd;
Xfildes_t ctlfd;
X{
X	register struct window *w;
X	static char cmdbuf[2] = { P1_IAC, 0 };
X
X	/*
X	 * Create a new window for the host.  This routine is not called when
X	 * the Macintosh creates a window.
X	 */
X	w = win_neww(wclass, wtype, wnum, protocol->p_maxwin, wid,
X	    datafd, ctlfd, (struct woptdefn *)0);
X	if (w) {
X		cmdbuf[1] = P1_DIR_HTOM|P1_FN_NEWW|WIN_NUM(w);
X		(void)write(mfd, cmdbuf, sizeof cmdbuf);
X	}
X	return(w);
X}
X
Xstatic
Xvoid
Xp1_killw(mfd, w)
Xregister struct window *w;
X{
X	static char cmdbuf[] = { P1_IAC, P1_DIR_HTOM|P1_FN_KILLW };
X
X	/*
X	 * Kill window "w" and tell the Macintosh to do the same.
X	 */
X	if (w && w->w_alloc) {
X		if (curwin.in == w)
X			curwin.in = (struct window *)0;
X		if (curwin.out == w)
X			curwin.out = (struct window *)0;
X		cmdbuf[1] = P1_DIR_HTOM|P1_FN_KILLW|WIN_NUM(w);
X		(void)write(mfd, cmdbuf, sizeof cmdbuf);
X		win_killw(w);
X	}
X}
X
Xstatic
Xvoid
Xp1_xmit(mfd, w)
Xfildes_t mfd;
Xregister struct window *w;
X{
X	register char *cp, *cq;
X	register int i, len;
X	char ibuf[32], obuf[32];
X	static char refresh;
X	static char cmdbuf[] = { P1_IAC, 0 };
X	extern int errno;
X
X	/*
X	 * Transmit data to the Macintosh (via file descriptor "mfd)
X	 * on behalf of window "w".  Be sure to convert any embedded
X	 * control characters and meta characters.
X	 *
X	 * Note that the input/output buffers should NOT be very large.
X	 * It is undesirable to perform large reads and effectively
X	 * "lock out" all other file descriptors.  The chosen size
X	 * should preserve a reasonable amount of efficiency.
X	 *
X	 * The UW protocol only requires an OSELW command when the
X	 * output window changes.  We issue this command more often
X	 * to "refresh" the Mac's idea of what the output window is.
X	 * This helps (slightly) to overcome spurious output redirects
X	 * caused by a noisy line.
X	 */
X	if (w && w->w_alloc) {
X		if (curwin.out != w || ++refresh == 0) {
X			refresh = 0;
X			curwin.out = w;
X			cmdbuf[1] = P1_DIR_HTOM|P1_FN_OSELW|WIN_NUM(w);
X			(void)write(mfd, cmdbuf, sizeof cmdbuf);
X		}
X		cq = obuf;
X		if ((len = read(w->w_datafd, ibuf, sizeof ibuf)) < 0 &&
X		    errno != EWOULDBLOCK)
X			(*protocol->p_killw)(mfd, w);
X		for (cp=ibuf; cp < ibuf+len; cp++) {
X			if (*cp&META) {
X				if (cq > obuf) {
X					(void)write(mfd, obuf, cq-obuf);
X					cq = obuf;
X				}
X				cmdbuf[1] = P1_DIR_HTOM|P1_FN_META;
X				(void)write(mfd, cmdbuf, sizeof cmdbuf);
X				*cp &= ~META;
X			}
X			i = -1;
X			if (*cp == RUB || *cp < ' ') {
X				i = protocol->p_szctlch - 1;
X				while (i >= 0 && protocol->p_ctlch[i] != *cp)
X					i--;
X			}
X			if (i >= 0) {
X				if (cq > obuf) {
X					(void)write(mfd, obuf, cq-obuf);
X					cq = obuf;
X				}
X				cmdbuf[1] = P1_DIR_HTOM|P1_FN_CTLCH|i;
X				(void)write(mfd, cmdbuf, sizeof cmdbuf);
X			} else {
X				*cq++ = *cp;
X				if (cq >= obuf+sizeof obuf) {
X					(void)write(mfd, obuf, cq-obuf);
X					cq = obuf;
X				}
X			}
X		}
X		if (cq > obuf)
X			(void)write(mfd, obuf, cq-obuf);
X	} else
X		(void)read(w->w_datafd, ibuf, sizeof ibuf);
X}
X
Xstatic
Xvoid
Xp1_recv(mfd, cbuf, clen)
Xfildes_t mfd;
Xchar *cbuf;
Xint clen;
X{
X	register int len;
X	register char *buf, *cp, *cq;
X	register struct window *w;
X	nwin_t wnum;
X	auto int nready;
X	char ibuf[512], obuf[512];
X	static int seen_iac, seen_meta;
X	static pnreq_t pnrq_cmd;
X	static char cmdbuf[2] = { P1_IAC };
X
X	/*
X	 * The received bytestream is examined.  Non-command bytes are
X	 * written to the file descriptor corresponding to the current
X	 * "input" window (relative to the Macintosh -- the window the
X	 * user types input to).
X	 *
X	 * If "clen" is nonzero, then the contents of the buffer "cbuf"
X	 * are processed before any input is read.
X	 */
X	if (ioctl(mfd, (int)FIONREAD, (char *)&nready) < 0) {
X		perror("FIONREAD");
X		return;
X	}
X	nready += clen;
X
X	for (cq = obuf; nready > 0; nready -= len) {
X		if (clen > 0) {
X			len = clen;
X			buf = cbuf;
X			clen = 0;
X		} else {
X			if (nready > sizeof ibuf)
X				len = read(mfd, ibuf, sizeof ibuf);
X			else
X				len = read(mfd, ibuf, nready);
X			if (len <= 0) {
X				perror("read");
X				return;
X			}
X			buf = ibuf;
X		}
X		for (cp=buf; cp < buf+len; cp++) {
X			if (pnrq_cmd) {
X				pcl_haggle(mfd, pnrq_cmd|*cp);
X				pnrq_cmd = 0;
X				/* pcl_haggle may have changed the protocol */
X				if (protocol != pcl_table) {
X					if (protocol->p_recv)
X						(*protocol->p_recv)(mfd,
X						    cp+1, buf+len-cp-1);
X					return;
X				}
X			} else if (seen_iac) {
X				if ((*cp&P1_DIR) == P1_DIR_MTOH) {
X					if (cq > obuf) {
X						(void)write(curwin.in->w_datafd,
X							    obuf, cq-obuf);
X						cq = obuf;
X					}
X					switch (*cp & P1_FN) {
X					case P1_FN_NEWW:
X						wnum = *cp & P1_WINDOW;
X						if (!wnum)
X							break;
X						w = WIN_PTR(wnum);
X						if (w->w_alloc)
X							break;
X						if (!win_neww(WC_INTERNAL,
X						    defwtype, wnum,
X						    protocol->p_maxwin, 0L,
X						    (fildes_t)-1, (fildes_t)-1,
X						    (struct woptdefn *)0)) {
X							cmdbuf[1] = P1_DIR_HTOM|
X							    P1_FN_KILLW|wnum;
X							(void)write(mfd, cmdbuf,
X							    sizeof cmdbuf);
X						}
X						break;
X					case P1_FN_KILLW:
X						wnum = *cp & P1_WINDOW;
X						if (!wnum)
X							break;
X						win_killw(WIN_PTR(wnum));
X						break;
X					case P1_FN_ISELW:
X						wnum = *cp & P1_WINDOW;
X						if (!wnum)
X							break;
X						w = WIN_PTR(wnum);
X						if (w->w_alloc)
X							curwin.in = w;
X						else
X							curwin.in = NULL;
X						break;
X					case P1_FN_META:
X						seen_meta = 1;
X						break;
X					case P1_FN_CTLCH:
X						*cq = protocol->p_ctlch[*cp&P1_CC];
X						if (seen_meta) {
X							seen_meta = 0;
X							*cq |= META;
X						}
X						if (curwin.in)
X							cq++;
X						break;
X					case P1_FN_MAINT:
X						switch (*cp & P1_MF) {
X						case P1_MF_ENTRY:
X							(*protocol->p_renew)(mfd);
X							break;
X						case P1_MF_ASKPCL:
X							pcl_haggle(mfd,PNRQ_ASK);
X							break;
X						case P1_MF_CANPCL:
X							pnrq_cmd = PNRQ_CAN;
X							break;
X						case P1_MF_SETPCL:
X							pnrq_cmd = PNRQ_SET;
X							break;
X						case P1_MF_EXIT:
X							done(0);
X							break;
X						}
X						break;
X					}
X				}
X				seen_iac = 0;
X			} else if (*cp == P1_IAC)
X				seen_iac++;
X			else {
X				if (seen_meta) {
X					seen_meta = 0;
X					*cq = *cp | META;
X				} else
X					*cq = *cp;
X				if (curwin.in) {
X					if (++cq >= obuf+sizeof obuf) {
X						(void)write(curwin.in->w_datafd,
X							    obuf, cq-obuf);
X						cq = obuf;
X					}
X				}
X			}
X		}
X	}
X	if (cq > obuf)
X		(void)write(curwin.in->w_datafd, obuf, cq-obuf);
X}
X
Xstatic
Xvoid
Xp1_askpcl(mfd)
Xfildes_t mfd;
X{
X	static char cmdbuf[2] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_ASKPCL };
X
X	(void)write(mfd, cmdbuf, sizeof cmdbuf);
X}
X
Xstatic
Xvoid
Xp1_canpcl(mfd, pname)
Xfildes_t mfd;
Xchar pname;
X{
X	static char cmdbuf[3] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_CANPCL };
X
X	cmdbuf[2] = pname;
X	(void)write(mfd, cmdbuf, sizeof cmdbuf);
X}
X
Xstatic
Xvoid
Xp1_setpcl(mfd, pname)
Xfildes_t mfd;
Xchar pname;
X{
X	static char cmdbuf[3] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_SETPCL };
X
X	cmdbuf[2] = pname;
X	(void)write(mfd, cmdbuf, sizeof cmdbuf);
X}
X
Xstatic
Xvoid
Xp1_renew(mfd)
Xfildes_t mfd;
X{
X	register struct window *w;
X	static char cmdbuf[2] = { P1_IAC };
X
X	/*
X	 * Re-init (re-NEW) an existing connection.  Send a NEWW command
X	 * for each existing window.  This function is invoked when the
X	 * Macintosh sends an ENTRY maintenance command.
X	 */
X	for (w=window; w < window+protocol->p_maxwin; w++) {
X		if (w->w_alloc) {
X			win_renew(w, 0);
X			cmdbuf[1] = P1_DIR_HTOM|P1_FN_NEWW|WIN_NUM(w);
X			(void)write(mfd, cmdbuf, sizeof cmdbuf);
X		}
X	}
X}
X
Xstatic
Xvoid
Xp2_renew(mfd)
Xfildes_t mfd;
X{
X	register struct window *w;
X	static char cmdbuf[3] = { P2_IAC };
X
X	/*
X	 * Re-init (re-NEW) an existing connection.  Send a NEWW command
X	 * for each existing window.  This function is invoked when the
X	 * Macintosh sends an ENTRY maintenance command.
X	 */
X	for (w=window; w < window+protocol->p_maxwin; w++) {
X		if (w->w_alloc) {
X			win_renew(w, 1);
X			cmdbuf[1] = P2_DIR_HTOM|P2_FN_NEWW|WIN_NUM(w);
X			cmdbuf[2] = w->w_type + ' ';
X			(void)write(mfd, cmdbuf, sizeof cmdbuf);
X		}
X	}
X}
X
Xstatic
Xstruct window *
Xp2_neww(mfd, wclass, wtype, wnum, wid, datafd, ctlfd)
Xfildes_t mfd;
Xwclass_t wclass;
Xwtype_t wtype;
Xnwin_t wnum;
Xlong wid;
Xfildes_t datafd;
Xfildes_t ctlfd;
X{
X	register struct window *w;
X	static char cmdbuf[3] = { P2_IAC };
X
X	/*
X	 * Create a new window as requested by the host.  This routine is not
X	 * called when the Macintosh creates a window.
X	 */
X	w = win_neww(wclass, wtype, wnum, protocol->p_maxwin, wid,
X	    datafd, ctlfd, (struct woptdefn *)0);
X	if (w) {
X		cmdbuf[1] = P2_DIR_HTOM|P2_FN_NEWW|WIN_NUM(w);
X		cmdbuf[2] = ' ' + wtype;
X		(void)write(mfd, cmdbuf, sizeof cmdbuf);
X	}
X	return(w);
X}
X
Xstatic
Xvoid
Xp2_chkopt(mfd)
Xfildes_t mfd;
X{
X	register struct window *w;
X	nwin_t maxwin;
X
X	/*
X	 * Ideally, this routine would call a routine in the window
X	 * module (perhaps win_chkopt()), passing the maximum window
X	 * number as one argument.  The "for" loop would be in that
X	 * routine.  However, I'm not willing to accept the overhead
X	 * for that conceptual nicety.
X	 */
X	maxwin = protocol->p_maxwin;
X	for (w=window; w < window+maxwin; w++)
X		if (w->w_alloc)
X			opt_scan((caddr_t)w, &w->w_optdefn, p2_sendopt, mfd,
X			    P2_FN_WOPT|WIN_NUM(w));
X}
X
Xstatic
Xvoid
Xp2_sendopt(mfd, fn, buf, len)
Xfildes_t mfd;
Xint fn;
Xregister char *buf;
Xregister int len;
X{
X	register char *cp;
X	register int i;
X	char outbuf[512];
X
X	/*
X	 * Encode and transmit the option string contained in "buf".  The
X	 * initial command (which will be P2_FN_WOPT|WIN_NUM(w)) is
X	 * contained in "fn".
X	 *
X	 * The caller is responsible for handing us a correctly-formed
X	 * option string.  This routine merely performs the protocol encoding
X	 * which is required for control and meta characters.
X	 */
X	curwin.out = NULL;
X	outbuf[0] = P2_IAC;
X	outbuf[1] = fn|P2_DIR_HTOM;
X	for (cp=outbuf+2; len > 0; buf++,len--) {
X		if (cp > outbuf+sizeof outbuf - 4) {
X			(void)write(mfd, outbuf, cp-outbuf);
X			cp = outbuf;
X		}
X		if (*buf & META) {
X			*cp++ = P2_IAC;
X			*cp++ = P2_DIR_HTOM|P2_FN_META;
X			*buf &= ~META;
X		}
X		i = -1;
X		if (*buf == RUB || *buf < ' ') {
X			i = protocol->p_szctlch - 1;
X			while (i >= 0 && protocol->p_ctlch[i] != *buf)
X				i--;
X		}
X		if (i >= 0) {
X			*cp++ = P2_IAC;
X			*cp++ = P2_DIR_HTOM|P2_FN_CTLCH|(i&7);
X		} else
X			*cp++ = *buf;
X	}
X	if (cp > outbuf)
X		(void)write(mfd, outbuf, cp-outbuf);
X}
X
Xstatic
Xvoid
Xp2_recv(mfd, cbuf, clen)
Xfildes_t mfd;
Xchar *cbuf;
Xint clen;
X{
X	register int len;
X	register char *buf, *cp, *cq;
X	register struct window *w;
X	register char c;
X	nwin_t wnum;
X	auto int nready;
X	char ibuf[512], obuf[512];
X	static int seen_iac, seen_meta, is_option;
X	static pnreq_t pnrq_cmd;
X	static nwin_t neww;
X	static char cmdbuf[2] = { P2_IAC };
X
X	/*
X	 * The received bytestream is examined.  Non-command bytes are
X	 * written to the file descriptor corresponding to the current
X	 * "input" window (relative to the Macintosh -- the window the
X	 * user types input to).
X	 *
X	 * If "clen" is nonzero, then the contents of the buffer "cbuf"
X	 * are processed before any input is read.
X	 */
X	if (ioctl(mfd, (int)FIONREAD, (char *)&nready) < 0) {
X		perror("FIONREAD");
X		return;
X	}
X	nready += clen;
X
X	for (cq = obuf; nready > 0; nready -= len) {
X		if (clen > 0) {
X			len = clen;
X			buf = cbuf;
X			clen = 0;
X		} else {
X			if (nready > sizeof ibuf)
X				len = read(mfd, ibuf, sizeof ibuf);
X			else
X				len = read(mfd, ibuf, nready);
X			if (len <= 0) {
X				perror("read");
X				return;
X			}
X			buf = ibuf;
X		}
X		for (cp=buf; cp < buf+len; cp++) {
X			if (pnrq_cmd) {
X				pcl_haggle(mfd, pnrq_cmd|*cp);
X				pnrq_cmd = 0;
X				/* pcl_haggle may have changed the protocol */
X				if (protocol != pcl_table) {
X					if (protocol->p_recv)
X						(*protocol->p_recv)(mfd,
X						    cp+1, buf+len-cp-1);
X					return;
X				}
X			} else if (neww) {
X				w = WIN_PTR(neww);
X				if (!w->w_alloc &&
X				    !win_neww(WC_INTERNAL, (wtype_t)(*cp-' '),
X				    neww, protocol->p_maxwin, 0L,
X				    (fildes_t)-1, (fildes_t)-1,
X				    (struct woptdefn *)0)) {
X					cmdbuf[1] = P2_DIR_HTOM|
X					    P2_FN_KILLW|neww;
X					(void)write(mfd, cmdbuf,
X					    sizeof cmdbuf);
X				}
X				neww = 0;
X			} else if (seen_iac) {
X				if ((*cp&P2_DIR) == P2_DIR_MTOH) {
X					c = *cp & P2_FN;
X					if (is_option &&
X					    c!=P2_FN_META && c!=P2_FN_CTLCH) {
X						opt_iflush();
X						is_option = 0;
X					}
X					if (cq > obuf) {
X						(void)write(curwin.in->w_datafd,
X							    obuf, cq-obuf);
X						cq = obuf;
X					}
X					switch (*cp & P2_FN) {
X					case P2_FN_NEWW:
X						neww = *cp & P2_WINDOW;
X						break;
X					case P2_FN_WOPT:
X						wnum = *cp & P2_WINDOW;
X						if (!wnum)
X							break;
X						w = WIN_PTR(wnum);
X						if (!w->w_alloc) {
X							curwin.in = NULL;
X							break;
X						}
X						is_option = 1;
X						opt_istart((caddr_t)w, &w->w_optdefn);
X						break;
X					case P2_FN_KILLW:
X						wnum = *cp & P2_WINDOW;
X						if (!wnum)
X							break;
X						win_killw(WIN_PTR(wnum));
X						break;
X					case P2_FN_ISELW:
X						wnum = *cp & P2_WINDOW;
X						if (!wnum)
X							break;
X						w = WIN_PTR(wnum);
X						if (w->w_alloc)
X							curwin.in = w;
X						else
X							curwin.in = NULL;
X						break;
X					case P2_FN_META:
X						seen_meta = 1;
X						if ((*cp&P2_CC) == 0)
X							break;
X						/* no break */
X					case P2_FN_CTLCH:
X						c=protocol->p_ctlch[*cp&P2_CC];
X						if (seen_meta) {
X							seen_meta = 0;
X							c |= META;
X						}
X						if (is_option)
X							is_option=opt_input(c);
X						else
X							if (curwin.in)
X								*cq++ = c;
X						break;
X					case P2_FN_MAINT:
X						switch (*cp & P2_MF) {
X						case P2_MF_ENTRY:
X							(*protocol->p_setpcl)(mfd, protocol->p_name);
X							(*protocol->p_renew)(mfd);
X							break;
X						case P2_MF_ASKPCL:
X							pcl_haggle(mfd,PNRQ_ASK);
X							break;
X						case P2_MF_CANPCL:
X							pnrq_cmd = PNRQ_CAN;
X							break;
X						case P2_MF_SETPCL:
X							pnrq_cmd = PNRQ_SET;
X							break;
X						case P2_MF_EXIT:
X							done(0);
X							break;
X						}
X						break;
X					}
X				}
X				seen_iac = 0;
X			} else if (*cp == P2_IAC)
X				seen_iac++;
X			else {
X				if (seen_meta) {
X					c = *cp | META;
X					seen_meta = 0;
X				} else
X					c = *cp;
X				if (is_option)
X					is_option = opt_input(c);
X				else
X					if (curwin.in)
X						*cq++ = c;
X				if (cq >= obuf+sizeof obuf) {
X					(void)write(curwin.in->w_datafd,
X						    obuf, cq-obuf);
X					cq = obuf;
X				}
X			}
X		}
X	}
X	if (cq > obuf)
X		(void)write(curwin.in->w_datafd, obuf, cq-obuf);
X}
SHAR_EOF
if test 21808 -ne "`wc -c < 'server/uw_pcl.c'`"
then
	echo shar: error transmitting "'server/uw_pcl.c'" '(should have been 21808 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 7 ---

jdb@mordor.s1.gov (John Bruner) (04/08/88)

[UW v4.2 - part 8 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	server/uw_tty.c
#	server/uw_utmp.c
#	server/uw_win.c
# This archive created: Mon Apr  4 07:52:12 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d server
then
	echo shar: mkdir server
	mkdir server
fi
echo shar: extracting "'server/uw_tty.c'" '(8756 characters)'
if test -f 'server/uw_tty.c'
then
	echo shar: will not over-write existing file "'server/uw_tty.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_tty.c'
X/*
X *	uw_tty - terminal support for UW
X *
X * Copyright 1985,1986 by John D. Bruner.  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 <sys/types.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <sys/stat.h>
X
X#include "uw_param.h"
X#include "uw_win.h"
X#include "uw_opt.h"
X
X#define	XON	021	/* ASCII XON (ASR-33 paper-tape reader on) */
X#define	XOFF	023	/* ASCII XOFF (ASR-33 paper-tape reader off) */
X
Xstatic char *envinfo[][3] = {
X	{
X		"TERM=adm31",
X		"TERMCAP=adm31:cr=^M:do=^J:nl=^J:al=\\EE:am:le=^H:bs:ce=\\ET:cm=\\E=%+ %+ :cl=^Z:cd=\\EY:co#80:dc=\\EW:dl=\\ER:ei=\\Er:ho=^^:im=\\Eq:li#24:mi:nd=^L:up=^K:MT:km:so=\\EG1:se=\\EG0:",
X		(char *)0
X	},
X	{
X		"TERM=vt52",
X		(char *)0
X	},
X	{
X		"TERM=ansi",
X		(char *)0
X	},
X	{
X		"TERM=tek4010",
X		(char *)0
X	}
X};
X
X/* private (emulation-specific) data */
Xstruct tty {
X	struct {
X		unsigned short	h,v;
X	}		t_size;
X	unsigned	t_fontsz;
X	unsigned	t_clipb;
X	unsigned	t_bell;
X	unsigned	t_curs;
X	unsigned	t_chgsz;
X};
X
X#define	WOTTY_SIZE	8		/* terminal size in (row, col) */
X#define	WOTTY_FONTSZ	9		/* font size index (0=7pt, 1=9pt) */
X#define	WOTTY_CLIPB	10		/* 0=clipboard, 1=encode mouse clicks */
X#define	WOTTY_BELL	11		/* bell: bit 0=visible, bit 1=audible */
X#define	WOTTY_CURSOR	12		/* cursor type: 0=block, 1=underscore */
X#define	WOTTY_CHGSZ	13		/* change actual size (not view size) */
X
Xstatic woptarg_t size_xdr[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
Xstatic woptarg_t fontsz_xdr[] = { WOA_UDATA(6), WOA_END };
Xstatic woptarg_t clipb_xdr[] = { WOA_UDATA(1), WOA_END };
Xstatic woptarg_t bell_xdr[] = { WOA_UDATA(2), WOA_END };
Xstatic woptarg_t curs_xdr[] = { WOA_UDATA(1), WOA_END };
Xstatic woptarg_t chgsz_xdr[] = { WOA_UDATA(1), WOA_END };
X
X/* TIOCSWINSZ is in 4.3BSD, TIOCSSIZE is in Sun UNIX */
X#if defined(TIOCSWINSZ) || defined(TIOCSSIZE)
X#define	RPTWINSZ	(1<<WOTTY_SIZE)
X#else
X#define	RPTWINSZ	0
X#endif
X
X#define	TTY_WOPT	{					\
X	0, 0, 0, 0,						\
X	RPTWINSZ|(1<<WOTTY_FONTSZ)|(1<<WOTTY_CLIPB)|		\
X	 (1<<WOTTY_BELL)|(1<<WOTTY_CURSOR)|(1<<WOTTY_CHGSZ),	\
X	{							\
X		{ NULL, NULL, NULL },				\
X		{ NULL, NULL, NULL },				\
X		{ NULL, NULL, NULL },				\
X		{ NULL, NULL, NULL },				\
X		{ NULL, NULL, NULL },				\
X		{ NULL, NULL, NULL },				\
X		{ NULL, NULL, NULL },				\
X		{ NULL, NULL, NULL },				\
X		{ size_xdr, tty_getopt, tty_setopt },		\
X		{ fontsz_xdr, tty_getopt, tty_setopt },		\
X		{ clipb_xdr, tty_getopt, tty_setopt },		\
X		{ bell_xdr, tty_getopt, tty_setopt },		\
X		{ curs_xdr, tty_getopt, tty_setopt },		\
X		{ chgsz_xdr, tty_getopt, tty_setopt }		\
X	}							\
X}
Xextern int tty_start();
Xextern void tty_stop(), tty_setopt(), tty_setext();
Xextern char *tty_getopt();
X
Xstruct emulation adm31_emul = { TTY_WOPT, tty_start, tty_stop, tty_setext };
Xstruct emulation vt52_emul = { TTY_WOPT, tty_start, tty_stop, tty_setext };
Xstruct emulation ansi_emul = { TTY_WOPT, tty_start, tty_stop, tty_setext };
Xstruct emulation tek_emul = { { 0, 0, 0, 0, 0 }, tty_start, tty_stop };
X
Xtty_mode(f)
Xint f;
X{
X	static struct sgttyb ostty, nstty;
X	static struct tchars otchars, ntchars;
X	static struct ltchars oltchars, nltchars;
X	static int olmode, nlmode;
X	static int operm;
X	static saved;
X	static int inout = FREAD|FWRITE;
X	struct stat st;
X
X	/*
X	 * This routine either saves the current terminal modes and then
X	 * sets up the terminal line or resets the terminal modes (depending
X	 * upon the value of "f").  The terminal line is used in "cbreak"
X	 * mode with all special characters except XON/XOFF disabled.  The
X	 * hated (by me) LDECCTQ mode is required for the Macintosh to
X	 * handle flow control properly.
X	 */
X	if (f == 1) {
X		if (fstat(0, &st) == 0)
X			operm = st.st_mode & 06777;
X		else
X			operm = -1;
X		if (ioctl(0, (int)TIOCGETP, (char *)&ostty) < 0) {
X			perror("ioctl((int)TIOCGETP)");
X			done(1);
X		}
X		if (ioctl(0, (int)TIOCGETC, (char *)&otchars) < 0) {
X			perror("ioctl((int)TIOCGETC)");
X			done(1);
X		}
X		if (ioctl(0, (int)TIOCGLTC, (char *)&oltchars) < 0) {
X			perror("ioctl((int)TIOCGLTC)");
X			done(1);
X		}
X		if (ioctl(0, (int)TIOCLGET, (char *)&olmode) < 0) {
X			perror("ioctl((int)TIOCLGET)");
X			done(1);
X		}
X		nstty = ostty;
X		nstty.sg_erase = nstty.sg_kill = -1;
X		nstty.sg_flags |= CBREAK;
X		nstty.sg_flags &= ~(RAW|CRMOD|ECHO|LCASE|XTABS|ALLDELAY);
X		ntchars.t_intrc = ntchars.t_quitc = -1;
X		ntchars.t_eofc = ntchars.t_brkc = -1;
X		ntchars.t_startc = XON;
X		ntchars.t_stopc = XOFF;
X		nltchars.t_suspc = nltchars.t_dsuspc = -1;
X		nltchars.t_rprntc = nltchars.t_flushc = -1;
X		nltchars.t_werasc = nltchars.t_lnextc = -1;
X		nlmode = olmode | LDECCTQ;
X		if (operm != -1 && fchmod(0, S_IREAD|S_IWRITE) < 0)
X			operm = -1;
X		if (ioctl(0, (int)TIOCSETN, (char *)&nstty) < 0) {
X			perror("ioctl((int)TIOCSETN)");
X			done(1);
X		}
X		if (ioctl(0, (int)TIOCSETC, (char *)&ntchars) < 0) {
X			perror("ioctl((int)TIOCSETC");
X			done(1);
X		}
X		if (ioctl(0, (int)TIOCSLTC, (char *)&nltchars) < 0) {
X			perror("ioctl((int)TIOCSLTC");
X			done(1);
X		}
X		if (ioctl(0, (int)TIOCLSET, (char *)&nlmode) < 0) {
X			perror("ioctl((int)TIOCLSET)");
X			done(1);
X		}
X		saved = 1;
X	} else if (saved) {
X		(void)ioctl(0, (int)TIOCFLUSH, (char *)&inout);
X		(void)ioctl(0, (int)TIOCSETP, (char *)&ostty);
X		(void)ioctl(0, (int)TIOCSETC, (char *)&otchars);
X		(void)ioctl(0, (int)TIOCSLTC, (char *)&oltchars);
X		(void)ioctl(0, (int)TIOCLSET, (char *)&olmode);
X		if (operm != -1)
X			(void)fchmod(0, operm);
X	}
X}
X
Xstatic
Xtty_start(w)
Xregister struct window *w;
X{
X	register struct tty *t;
X	extern char *malloc();
X
X	/*
X	 * Start up a terminal emulation.  Establish reasonable defaults
X	 * for the terminal-specific window options.
X	 */
X	if (w->w_type != WT_TEK4010) {
X		if ((w->w_private = malloc(sizeof(struct tty))) != NULL) {
X			t = (struct tty *)w->w_private;
X			t->t_size.h = 80;
X			t->t_size.v = 24;
X			t->t_fontsz = 0;
X			t->t_clipb = 0;
X			t->t_bell = 3;
X			t->t_curs = 0;
X			t->t_chgsz = 0;
X			return(1);
X		} else
X			return(0);
X	} else {
X		w->w_private = (char *)0;
X		return(1);
X	}
X}
X
Xstatic
Xvoid
Xtty_stop(w)
Xregister struct window *w;
X{
X	/*
X	 * Shut down (stop) a terminal emulation.
X	 */
X	free(w->w_private);
X	w->w_private = (char *)0;
X}
X
Xstatic
Xvoid
Xtty_setext(wod)
Xregister struct woptdefn *wod;
X{
X	/*
X	 * This routine makes adjustments to the window option definitions
X	 * for external windows.  Basically, we turn off reporting for
X	 * WOTTY_SIZE.  (If the external process wants to handle this, it
X	 * can turn it back on.)
X	 */
X	WOPT_CLR(wod->wod_do, WOTTY_SIZE);
X	WOPT_CLR(wod->wod_askrpt, WOTTY_SIZE);
X}
X
Xtty_envinit(wtype)
Xregister wtype_t wtype;
X{
X	/*
X	 * Set up environment variables corresponding to the window type
X	 * "wtype".
X	 */
X	env_set(envinfo[wtype]);
X}
X
Xstatic
Xchar *
Xtty_getopt(win, num)
Xcaddr_t win;
Xwoption_t num;
X{
X	register struct tty *t;
X	static union optvalue ov;
X	struct window *w;
X
X	if ((w=(struct window *)win) != NULL && w->w_alloc &&
X	    (t=(struct tty *)w->w_private) != NULL) {
X		switch (num) {
X		case WOTTY_SIZE:
X			ov.ov_point.h = t->t_size.h;
X			ov.ov_point.v = t->t_size.v;
X			break;
X		case WOTTY_FONTSZ:
X			ov.ov_udata6 = t->t_fontsz;
X			break;
X		case WOTTY_CLIPB:
X			ov.ov_udata1 = t->t_clipb;
X			break;
X		case WOTTY_BELL:
X			ov.ov_udata2 = t->t_bell;
X			break;
X		case WOTTY_CURSOR:
X			ov.ov_udata1 = t->t_curs;
X			break;
X		case WOTTY_CHGSZ:
X			ov.ov_udata1 = t->t_chgsz;
X			break;
X		}
X	}
X	return((char *)&ov);
X}
X
Xstatic
Xvoid
Xtty_setopt(win, num, value)
Xcaddr_t win;
Xwoption_t num;
Xchar *value;
X{
X	register struct tty *t;
X	register union optvalue *ovp;
X	register struct window *w;
X
X	if ((w=(struct window *)win) != NULL && w->w_alloc &&
X	    (t=(struct tty *)w->w_private) != NULL &&
X	    (ovp = (union optvalue *)value) != NULL) {
X		switch (num) {
X		case WOTTY_SIZE:
X			t->t_size.h = ovp->ov_point.h;
X			t->t_size.v = ovp->ov_point.v;
X#ifdef TIOCSWINSZ
X			if (w->w_class == WC_INTERNAL) {
X				/* set window size on pty (4.3BSD) */
X				struct winsize ws;
X				ws.ws_row = t->t_size.v;
X				ws.ws_col = t->t_size.h;
X				ws.ws_xpixel = w->w_size.h;
X				ws.ws_ypixel = w->w_size.v;
X				(void)ioctl(w->w_datafd, (int)TIOCSWINSZ,
X				    (char *)&ws);
X			}
X#else
X#ifdef TIOCSSIZE
X			if (w->w_class == WC_INTERNAL) {
X				/* set window size on pty (Sun) */
X				struct ttysize ts;
X				ts.ts_lines = t->t_size.v;
X				ts.ts_cols = t->t_size.h;
X				(void)ioctl(w->w_datafd, (int)TIOCSSIZE,
X				    (char *)&ts);
X			}
X#endif
X#endif
X			break;
X		case WOTTY_FONTSZ:
X			t->t_fontsz = ovp->ov_udata6;
X			break;
X		case WOTTY_CLIPB:
X			t->t_clipb = ovp->ov_udata1;
X			break;
X		case WOTTY_BELL:
X			t->t_bell = ovp->ov_udata2;
X			break;
X		case WOTTY_CURSOR:
X			t->t_curs = ovp->ov_udata1;
X			break;
X		case WOTTY_CHGSZ:
X			t->t_chgsz = ovp->ov_udata1;
X			break;
X		}
X	}
X}
SHAR_EOF
if test 8756 -ne "`wc -c < 'server/uw_tty.c'`"
then
	echo shar: error transmitting "'server/uw_tty.c'" '(should have been 8756 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_utmp.c'" '(3885 characters)'
if test -f 'server/uw_utmp.c'
then
	echo shar: will not over-write existing file "'server/uw_utmp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_utmp.c'
X/*
X *	uw_utmp - /etc/utmp handling
X *
X * Copyright 1985,1986 by John D. Bruner.  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#ifdef UTMP
X
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/time.h>
X#include <pwd.h>
X#include <utmp.h>
X#include <strings.h>
X#include <ctype.h>
X#include <stdio.h>
X
X#include "uw_param.h"
X
Xstruct utinfo {
X	struct utinfo	*ui_next;
X	struct utinfo	*ui_chain;
X	char		*ui_line;
X	int		ui_slot;
X	int		ui_inuse;
X};
X
Xstatic struct utinfo *hash[31];
Xstatic struct utinfo *head;
X
Xstatic char *myname;
Xstatic fildes_t utmpfd;
X
Xextern time_t time();
X
Xutmp_init(fd)
Xfildes_t fd;
X{
X	register char *cp, *cq;
X	register struct utinfo *ui;
X	register int hashidx, slot;
X	struct passwd *pw;
X	FILE *fp;
X	char line[256];
X
X	if ((utmpfd = fd) >= 0 && (fp = fopen("/etc/ttys", "r")) == NULL) {
X		(void)close(utmpfd);
X		utmpfd = -1;
X	}
X	if (utmpfd >= 0) {
X		slot = 0;
X		while (fgets(line, sizeof line, fp) != NULL) {
X#ifdef V7TTYS
X			if (!line[0] || !line[1]) {	/* malformed line */
X				slot++;
X				continue;
X			}
X			cp = line+2;	/* skip flag and speed index */
X#else
X			for (cp=line; *cp && isspace(*cp); cp++)
X				;
X			if (*cp == '#')
X				continue;
X#endif
X			slot++;
X			if ((ui=(struct utinfo *)malloc(sizeof *ui)) != NULL) {
X				for (cq=cp; *cq && !isspace(*cq); cq++)
X					;
X				if ((ui->ui_line=malloc(cq-cp+1)) != NULL) {
X					(void)strncpy(ui->ui_line, cp, cq-cp);
X					ui->ui_line[cq-cp] = '\0';
X				} else {
X					free((char *)ui);
X					ui = (struct utinfo *)0;
X				}
X			}
X			if (ui != NULL) {
X				ui->ui_slot = slot;
X				ui->ui_inuse = 0;
X				ui->ui_chain = head;
X				head = ui;
X				hashidx = utmp_hash(ui->ui_line);
X				ui->ui_next = hash[hashidx];
X				hash[hashidx] = ui;
X			}
X		}
X		(void)fclose(fp);
X	}
X	if ((pw = getpwuid(getuid())) != NULL &&
X	    (myname=malloc(1+strlen(pw->pw_name))) != NULL)
X		(void)strcpy(myname, pw->pw_name);
X}
X
Xstatic
Xstruct utinfo *
Xutmp_find(tty)
Xchar *tty;
X{
X	register char *cp;
X	register struct utinfo *ui;
X
X	if ((cp = rindex(tty, '/')) != NULL)
X		cp++;
X	else
X		cp = tty;
X	ui = hash[utmp_hash(cp)];
X	while (ui != NULL && strcmp(ui->ui_line, cp) != 0)
X		ui = ui->ui_next;
X	return(ui);
X}
X
Xutmp_add(tty)
Xchar *tty;
X{
X	register struct utinfo *ui;
X	struct utmp ut;
X
X	if ((ui = utmp_find(tty)) != NULL) {
X		(void)strncpy(ut.ut_line, ui->ui_line, sizeof ut.ut_line);
X		(void)strncpy(ut.ut_name, myname, sizeof ut.ut_name);
X		(void)strncpy(ut.ut_host, "", sizeof ut.ut_host);
X		ut.ut_time = (long)time((time_t)0);
X		ui->ui_inuse = 1;
X		utmp_write(ui->ui_slot, &ut);
X	}
X}
X
X
Xutmp_rm(tty)
Xchar *tty;
X{
X	register struct utinfo *ui;
X	struct utmp ut;
X
X	if ((ui = utmp_find(tty)) != NULL) {
X		(void)strncpy(ut.ut_line, ui->ui_line, sizeof ut.ut_line);
X		(void)strncpy(ut.ut_name, "", sizeof ut.ut_name);
X		(void)strncpy(ut.ut_host, "", sizeof ut.ut_host);
X		ut.ut_time = (long)time((time_t)0);
X		ui->ui_inuse = 0;
X		utmp_write(ui->ui_slot, &ut);
X	}
X}
X
Xutmp_exit()
X{
X	register struct utinfo *ui;
X	struct utmp ut;
X
X	for (ui=head; ui; ui=ui->ui_chain) {
X		if (ui->ui_inuse) {
X			(void)strncpy(ut.ut_line,ui->ui_line,sizeof ut.ut_line);
X			(void)strncpy(ut.ut_name, "", sizeof ut.ut_name);
X			(void)strncpy(ut.ut_host, "", sizeof ut.ut_host);
X			ut.ut_time = (long)time((time_t)0);
X			ui->ui_inuse = 0;
X			utmp_write(ui->ui_slot, &ut);
X		}
X	}
X}
X
Xutmp_write(slot, ut)
Xregister int slot;
Xstruct utmp *ut;
X{
X	extern off_t lseek();
X
X	if (utmpfd >= 0 &&
X	    lseek(utmpfd, slot*sizeof(*ut), L_SET) == (off_t)(slot*sizeof(*ut)))
X		(void)write(utmpfd, (char *)ut, sizeof *ut);
X}
X
Xstatic
Xutmp_hash(s)
Xregister char *s;
X{
X	register short h;
X
X	for (h=0; *s; s++)
X		h = (h << ((*s)&7)) | (h >> (sizeof h - ((*s)&7))) + *s;
X	return(h % sizeof hash / sizeof hash[0]);
X}
X#else
Xutmp_add(tty)
Xchar *tty;
X{
X}
X
Xutmp_rm(tty)
Xchar *tty;
X{
X}
X
Xutmp_exit()
X{
X}
X#endif
SHAR_EOF
if test 3885 -ne "`wc -c < 'server/uw_utmp.c'`"
then
	echo shar: error transmitting "'server/uw_utmp.c'" '(should have been 3885 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_win.c'" '(10772 characters)'
if test -f 'server/uw_win.c'
then
	echo shar: will not over-write existing file "'server/uw_win.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_win.c'
X/*
X *	uw_win - window handling for UW
X *
X * Copyright 1986 by John D. Bruner.  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 <sys/types.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <signal.h>
X#include <strings.h>
X#include <stdio.h>
X
X#include "openpty.h"
X#include "uw_param.h"
X#include "uw_opt.h"
X#include "uw_win.h"
X#include "uw_fd.h"
X
X/*
X * "defwtype" specifies the default window type.  This type is used when
X * more specific information is not available.
X */
Xwtype_t defwtype = WT_ADM31;
X
X/*
X * "window" is declared in "uw_win.h"  Here we define it.
X */
Xstruct window window[NWINDOW];		/* window data structures */
X
X/*
X * "emulation" describes window emulation-specific data.  "generic_emul"
X * describes emulations which do not require special server attention
X * (e.g. file transfer, all of whose real work is done by a separate process).
X */
Xextern struct emulation adm31_emul, vt52_emul, ansi_emul, tek_emul;
Xstatic struct emulation generic_emul;
Xstatic struct emulation *emulation[WT_MAXTYPE+1] = {
X	&adm31_emul,
X	&vt52_emul,
X	&ansi_emul,
X	&tek_emul,
X	&generic_emul,
X	&generic_emul,
X	&generic_emul,
X};
X
Xextern char *win_getopt();
Xextern void win_setopt();
X
Xstatic woptarg_t woa_vis[] = { WOA_UDATA(1), WOA_END };
Xstatic woptarg_t woa_type[] = { WOA_UDATA(6), WOA_END };
Xstatic woptarg_t woa_pos[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
Xstatic woptarg_t woa_title[] = { WOA_STRING(255), WOA_END };
Xstatic woptarg_t woa_size[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
X
Xstatic struct woptdefn genwinopt = {
X	(1<<WOG_VIS), 0, 0, 0,
X	(1<<WOG_VIS)|(1<<WOG_TYPE)|(1<<WOG_POS)|(1<<WOG_TITLE)|(1<<WOG_SIZE),
X	{
X/* WOG_END */	{ NULL, NULL, NULL },
X/* WOG_VIS */	{ woa_vis, win_getopt, win_setopt },
X/* WOG_TYPE */	{ woa_type, win_getopt, win_setopt },
X/* WOG_POS */	{ woa_pos, win_getopt, win_setopt },
X/* WOG_TITLE */	{ woa_title, win_getopt, win_setopt },
X/* WOG_SIZE */	{ woa_size, win_getopt, win_setopt },
X/* WOG_6 */	{ NULL, NULL, NULL },
X/* WOG_7 */	{ NULL, NULL, NULL }
X	}
X};
X
X/*
X * This is a violation of the level structure, but it is expedient.
X */
Xextern void ipc_optmsg();
X
Xwin_init()
X{
X	register struct window *w;
X
X	/*
X	 * Initialize.  Mark all windows unallocated.
X	 */
X	for (w=window; w < window+NWINDOW; w++)
X		w->w_alloc = 0;
X}
X
Xlong
Xwin_mkid()
X{
X	static unsigned short i = 0;
X	static long pid = -1;
X
X	if (pid == -1)
X		pid = getpid();
X	return((pid << (NBBY*(sizeof(long)/sizeof(short)))) | i++);
X}
X
Xstruct window *
Xwin_search(wid, maxwin)
Xlong wid;
Xnwin_t maxwin;
X{
X	register struct window *w;
X
X	for (w=window; w < window+maxwin; w++)
X		if (w->w_alloc && w->w_id == wid)
X			return(w);
X	return((struct window *)0);
X}
X
Xstruct window *
Xwin_neww(wclass, wtype, wnum, maxwin, wid, datafd, ctlfd, options)
Xwclass_t wclass;
Xwtype_t wtype;
Xnwin_t wnum;
Xnwin_t maxwin;
Xlong wid;
Xfildes_t datafd;
Xfildes_t ctlfd;
Xstruct woptdefn *options;
X{
X	fildes_t fd;
X	int pid;
X	struct window *w;
X	char *tty, *shell;
X	auto struct ptydesc pt;
X	extern char *getenv();
X
X	/*
X	 * Create a new window.  "wclass" specifies the window wclass.
X	 * If "wnum" is negative, choose a window number; otherwise,
X	 * "wnum" is the window number.  "datafd" and "ctlfd" are the
X	 * data and control file descriptors to be associated with
X	 * this window.  If "datafd" is negative and "wclass" is
X	 * WC_INTERNAL, allocate a pseudo-terminal.
X	 *
X	 * If "options" is non-NULL it specifies the address of an
X	 * option definition structure; otherwise, a new one is constructed
X	 * from the generic and emulation-specific prototype structures.
X	 *
X	 * If "wid" is nonzero it is a proposed window ID.  It must be
X	 * unique (not in use).  If "wid" is zero, a new ID is assigned.
X	 *
X	 * The window type "wtype" will always be a terminal emulation
X	 * if the wclass is WC_INTERNAL.
X	 *
X	 * Internal-class windows are visible by default, while external
X	 * ones are initially invisible.
X	 *
X	 * Return the address of the window structure or NULL if
X	 * none could be created.
X	 */
X	tty = (char *)0;
X	if (wtype > WT_MAXTYPE)
X		return((struct window *)0);
X	if (wid == 0) {
X		while (win_search(wid=win_mkid(), maxwin) != NULL)
X			;
X	} else if (win_search(wid, maxwin) != NULL)
X		return((struct window *)0);
X	if (datafd < 0 && wclass == WC_INTERNAL) {
X		if (!openpty(&pt)) {
X			datafd = pt.pt_pfd;
X			tty = pt.pt_tname;
X			while ((pid = fork()) < 0)
X				sleep(5);
X			if (!pid) {
X				win_envinit(wtype, wid);
X				(void)signal(SIGHUP, SIG_DFL);
X				(void)signal(SIGINT, SIG_DFL);
X				(void)signal(SIGQUIT, SIG_DFL);
X				(void)signal(SIGTERM, SIG_DFL);
X				(void)signal(SIGTSTP, SIG_IGN);
X				(void)signal(SIGCHLD, SIG_DFL);
X				(void)ioctl(open("/dev/tty",O_RDWR),
X				    (int)TIOCNOTTY, (char *)0);
X				(void)close(open(pt.pt_tname, O_RDONLY));
X				(void)setuid(getuid());
X				if (!(shell = getenv("SHELL")))
X					shell = "/bin/sh";
X				if (pt.pt_tfd != 0)
X					(void)dup2(pt.pt_tfd, 0);
X				if (pt.pt_tfd != 1);
X					(void)dup2(pt.pt_tfd, 1);
X				if (pt.pt_tfd != 2)
X					(void)dup2(pt.pt_tfd, 2);
X				for (fd=3; fd < nfds; fd++)
X					(void)close(fd);
X				tty_mode(0);	/* HACK! */
X				execl(shell, shell, (char *)0);
X				_exit(1);
X			} else {
X				utmp_add(tty);
X				(void)close(pt.pt_tfd);
X			}
X		}
X	}
X
X	if (datafd >= 0) {
X		if (wnum > 0) {
X			w = WIN_PTR(wnum);
X			if (w->w_alloc)
X				w = (struct window *)0;
X		} else {
X			for (w=window; w < window+maxwin && w->w_alloc; w++)
X				;
X			if (w >= window+maxwin)
X				w = (struct window *)0;
X		}
X	} else
X		w = (struct window *)0;
X
X	if (w) {
X		w->w_alloc = 1;
X		w->w_id = wid;
X		w->w_class = wclass;
X		w->w_type = wtype;
X		w->w_visible = (w->w_class == WC_INTERNAL);
X		w->w_position.h = w->w_position.v = 0;
X		w->w_size.h = w->w_size.v = 0;
X		w->w_title[0] = '\0';
X		if (emulation[wtype]->we_start &&
X		    !(*emulation[wtype]->we_start)(w)) {
X			if (options)
X				w->w_optdefn = *options;
X			else
X				opt_new(&w->w_optdefn, &genwinopt,
X				    (struct woptdefn *)0);
X		} else {
X			if (options)
X				w->w_optdefn = *options;
X			else
X				opt_new(&w->w_optdefn, &genwinopt,
X				    &emulation[wtype]->we_optdefn);
X		}
X		w->w_datafd = datafd;
X		(void)fcntl(datafd, F_SETFL, FNDELAY);
X		FD_SET(datafd, &selmask[0].sm_rd);
X		fdmap[datafd].f_type = FDT_DATA;
X		fdmap[datafd].f_win = w;
X		if (w->w_class == WC_INTERNAL) {
X			if (tty)
X				(void)strncpy(w->w_tty, tty, sizeof w->w_tty);
X		} else {
X			w->w_ctlfd = ctlfd;
X			if (ctlfd >= 0) {
X				(void)fcntl(ctlfd, F_SETFL, FNDELAY);
X				FD_SET(ctlfd, &selmask[0].sm_rd);
X				fdmap[ctlfd].f_type = FDT_CTL;
X				fdmap[ctlfd].f_win = w;
X				if (emulation[wtype]->we_setext)
X					(*emulation[wtype]->we_setext)(&w->w_optdefn);
X				opt_setext(&w->w_optdefn, ipc_optmsg);
X			}
X		}
X	}
X			
X	return(w);
X}
X
Xwin_killw(w)
Xregister struct window *w;
X{
X	/*
X	 * Kill the window "w".  This is pretty simple; we just close
X	 * the data and control file descriptors and mark the structure
X	 * inactive.
X	 */
X	if (w && w->w_alloc) {
X		if (w->w_datafd >= 0) {
X			if (w->w_class == WC_INTERNAL)
X				utmp_rm(w->w_tty);
X			FD_CLR(w->w_datafd, &selmask[0].sm_rd);
X			FD_CLR(w->w_datafd, &selmask[0].sm_wt);
X			FD_CLR(w->w_datafd, &selmask[0].sm_ex);
X			fdmap[w->w_datafd].f_type = FDT_NONE;
X			(void)close(w->w_datafd);
X		}
X		if (w->w_class == WC_EXTERNAL && w->w_ctlfd >= 0) {
X			FD_CLR(w->w_ctlfd, &selmask[0].sm_rd);
X			FD_CLR(w->w_ctlfd, &selmask[0].sm_wt);
X			FD_CLR(w->w_ctlfd, &selmask[0].sm_ex);
X			fdmap[w->w_ctlfd].f_type = FDT_NONE;
X			(void)close(w->w_ctlfd);
X		}
X		w->w_alloc = 0;
X	}
X}
X
Xwin_renew(w, report)
Xstruct window *w;
Xint report;
X{
X	/*
X	 * Reinitialize (re-NEW) the window "w".  Report the state of the
X	 * window to the Mac if "report" is nonzero.
X	 */
X	opt_renew(&w->w_optdefn, report);
X}
X
Xwin_newtype(w, wtype)
Xregister struct window *w;
Xregister wtype_t wtype;
X{
X	/*
X	 * Change the window emulation type to "wtype".
X	 */
X	if (wtype <= WT_MAXTYPE && wtype != w->w_type) {
X		if (emulation[w->w_type]->we_stop)
X			(*emulation[w->w_type]->we_stop)(w);
X		w->w_type = wtype;
X		if (emulation[wtype]->we_start &&
X		    !(*emulation[wtype]->we_start)(w)) {
X			opt_newtype(&w->w_optdefn, &genwinopt,
X			    (struct woptdefn *)0);
X		} else {
X			opt_newtype(&w->w_optdefn, &genwinopt,
X			    &emulation[wtype]->we_optdefn);
X		}
X		if (w->w_class == WC_EXTERNAL && w->w_ctlfd >= 0) {
X			if (emulation[wtype]->we_setext)
X				(*emulation[wtype]->we_setext)(&w->w_optdefn);
X			opt_setext(&w->w_optdefn, ipc_optmsg);
X		}
X	}
X}
X
Xwin_envinit(wtype, wid)
Xregister wtype_t wtype;
Xlong wid;
X{
X	register char *widstr;
X	auto char *env[2];
X
X	/*
X	 * Set up the environment according to the new window type and
X	 * window ID.
X	 *
X	 * A 64-bit integer will fit in 20 digits.  If a "long" is wider
X	 * than this, then this code will have to be adjusted.
X	 */
X	if (wtype <= WT_TEK4010)
X		tty_envinit(wtype);
X	if ((widstr = malloc(sizeof "UW_ID=" + 20)) != NULL) {
X		sprintf(widstr, "UW_ID=%ld", wid);
X		env[0] = widstr;
X		env[1] = (char *)0;
X		env_set(env);
X	}
X}
X
Xstatic
Xchar *
Xwin_getopt(win, num)
Xcaddr_t win;
Xwoption_t num;
X{
X	register struct window *w;
X	static union optvalue ov;
X
X	/*
X	 * Get the value of window option "num".  It is arguably wrong to
X	 * always return the address of "ov" (even if the window isn't
X	 * allocated or an unknown option type was requested); however,
X	 * we're already in trouble and there is no good way to recover
X	 * at this point.
X	 */
X	if ((w = (struct window *)win) != NULL && w->w_alloc) {
X		switch (num) {
X		case WOG_VIS:
X			ov.ov_udata1 = w->w_visible;
X			break;
X		case WOG_TYPE:
X			ov.ov_udata6 = w->w_type;
X			break;
X		case WOG_POS:
X			ov.ov_point.h = w->w_position.h;
X			ov.ov_point.v = w->w_position.v;
X			break;
X		case WOG_TITLE:
X			(void)strncpy(ov.ov_string, w->w_title,
X			    sizeof ov.ov_string);
X			ov.ov_string[sizeof ov.ov_string-1] = '\0';
X			break;
X		case WOG_SIZE:
X			ov.ov_point.h = w->w_size.h;
X			ov.ov_point.v = w->w_size.v;
X			break;
X		}
X	}
X	return((char *)&ov);
X}
X
Xstatic
Xvoid
Xwin_setopt(win, num, value)
Xcaddr_t win;
Xwoption_t num;
Xchar *value;
X{
X	register struct window *w;
X	register union optvalue *ov;
X
X	/*
X	 * Set window option "num" to "value"
X	 */
X	if ((w = (struct window *)win) != NULL && w->w_alloc &&
X	    (ov = (union optvalue *)value) != NULL) {
X		switch (num) {
X		case WOG_VIS:
X			w->w_visible = ov->ov_udata1;
X			break;
X		case WOG_TYPE:
X			win_newtype(w, (wtype_t)ov->ov_udata6);
X			break;
X		case WOG_POS:
X			w->w_position.h = ov->ov_point.h;
X			w->w_position.v = ov->ov_point.v;
X			break;
X		case WOG_TITLE:
X			(void)strncpy(w->w_title, ov->ov_string,
X			    sizeof w->w_title);
X			w->w_title[sizeof w->w_title-1] = '\0';
X			break;
X		case WOG_SIZE:
X			w->w_size.h = ov->ov_point.h;
X			w->w_size.v = ov->ov_point.v;
X			break;
X		}
X	}
X}
SHAR_EOF
if test 10772 -ne "`wc -c < 'server/uw_win.c'`"
then
	echo shar: error transmitting "'server/uw_win.c'" '(should have been 10772 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 8 ---

jdb@mordor.s1.gov (John Bruner) (04/08/88)

[UW v4.2 - part 9 of 9]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	utility/Makefile_4.2
#	utility/Makefile_4.3
#	utility/uwplot.c
#	utility/uwterm.c
#	utility/uwtitle.c
#	utility/uwtool.c
# This archive created: Mon Apr  4 07:52:15 1988
# By:	Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d utility
then
	echo shar: mkdir utility
	mkdir utility
fi
echo shar: extracting "'utility/Makefile_4.2'" '(1893 characters)'
if test -f 'utility/Makefile_4.2'
then
	echo shar: will not over-write existing file "'utility/Makefile_4.2'"
else
sed 's/^X//' << \SHAR_EOF > 'utility/Makefile_4.2'
X#! /bin/make -f
X#
X#	uw utility makefile (4.2BSD)
X#
X#	INCDIR should be set to the directory containing header files.
X#
X#	LIBUW should be set to the name of the library file (or, if it is
X#	installed in a system directory, "-luw").
X#
X#	Note: in order for "uwterm" to work on remote machines it is
X#	necessary for it to be installed in a directly where "rsh"
X#	will find it.  The #defined symbol UWTERM in the source can
X#	be set to the desired absolute pathname, if necessary.
X#
X
XINCDIR	=	../h
X
XLIBUW	=	../lib/libuw.a
X
XUWTOOL_OBJS =	uwtool.o
XUWTITLE_OBJS =	uwtitle.o
XUWTERM_OBJS =	uwterm.o
XUWPLOT_OBJS =	uwplot.o
X
XOBJECTS	=	$(UWTOOL_OBJS) $(UWTITLE_OBJS) $(UWTERM_OBJS) $(UWPLOT_OBJS)
X
XSOURCES	=	`echo $(OBJECTS) | sed -e 's/\\.o/\\.c/g'`
X
XDEFINES	=	`cat ../DEFINES`
X
XCFLAGS	=	-O -I$(INCDIR) $(DEFINES)
XLFLAGS	=
X
Xall:		uwtool uwtitle uwterm uwplot
X
Xuwtool:		$(UWTOOL_OBJS)
X	$(CC) -o $@ $(LFLAGS) $(UWTOOL_OBJS) $(LIBUW)
X
Xuwtitle:	$(UWTITLE_OBJS)
X	$(CC) -o $@ $(LFLAGS) $(UWTITLE_OBJS) $(LIBUW)
X
Xuwterm:		$(UWTERM_OBJS)
X	$(CC) -o $@ $(LFLAGS) $(UWTERM_OBJS) $(LIBUW)
X
Xuwplot:		$(UWPLOT_OBJS)
X	$(CC) -o $@ $(LFLAGS) $(UWPLOT_OBJS) $(LIBUW)
X
Xlint:
X	for src in $(SOURCES); \
X	do echo $$src:; lint -hubx -I$(INCDIR) $(DEFINES) $$src; done
X
Xtags:
X	ctags $(SOURCES)
X
Xdepend: 
X	grep '^#include' $(SOURCES) | \
X	sed -e '/</d' \
X	    -e 's/:[^"]*"\([^"]*\)".*/: ..\/h\/\1/' \
X	    -e 's,^../[a-zA-Z0-9]*/\([^\.]*\)\.[cs],\1.o \1.L,' | \
X	awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
X		else { if (length(rec $$3) > 78) { print rec; rec = $$0; } \
X		       else rec = rec " " $$3 } } \
X	      END { print rec } ' > makedep
X	echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
X	echo '$$r makedep' >>eddep
X	echo 'w' >>eddep
X	cp Makefile Makefile.bak
X	ex - Makefile < eddep
X	rm eddep makedep
X
Xclean:
X	-rm -f *.o
X
X# DO NOT DELETE THIS LINE (or the following blank line) -- make depend uses it
X
SHAR_EOF
if test 1893 -ne "`wc -c < 'utility/Makefile_4.2'`"
then
	echo shar: error transmitting "'utility/Makefile_4.2'" '(should have been 1893 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'utility/Makefile_4.3'" '(1860 characters)'
if test -f 'utility/Makefile_4.3'
then
	echo shar: will not over-write existing file "'utility/Makefile_4.3'"
else
sed 's/^X//' << \SHAR_EOF > 'utility/Makefile_4.3'
X#! /bin/make -f
X#
X#	uw utility makefile (4.3BSD)
X#
X#	INCDIR should be set to the directory containing header files.
X#
X#	LIBUW should be set to the name of the library file (or, if it is
X#	installed in a system directory, "-luw").
X#
X#	Note: in order for "uwterm" to work on remote machines it is
X#	necessary for it to be installed in a directly where "rsh"
X#	will find it.  The #defined symbol UWTERM in the source can
X#	be set to the desired absolute pathname, if necessary.
X#
X
XINCDIR	=	../h
X
XLIBUW	=	../lib/libuw.a
X
XUWTOOL_OBJS =	uwtool.o
XUWTITLE_OBJS =	uwtitle.o
XUWTERM_OBJS =	uwterm.o
XUWPLOT_OBJS =	uwplot.o
X
XOBJECTS	=	$(UWTOOL_OBJS) $(UWTITLE_OBJS) $(UWTERM_OBJS) $(UWPLOT_OBJS)
X
XSOURCES	=	`echo $(OBJECTS) | sed -e 's/\\.o/\\.c/g'`
X
XDEFINES	=	`cat ../DEFINES`
X
XCFLAGS	=	-O -I$(INCDIR) $(DEFINES)
XLFLAGS	=
X
Xall:		uwtool uwtitle uwterm uwplot
X
Xuwtool:		$(UWTOOL_OBJS)
X	$(CC) -o $@ $(LFLAGS) $(UWTOOL_OBJS) $(LIBUW)
X
Xuwtitle:	$(UWTITLE_OBJS)
X	$(CC) -o $@ $(LFLAGS) $(UWTITLE_OBJS) $(LIBUW)
X
Xuwterm:		$(UWTERM_OBJS)
X	$(CC) -o $@ $(LFLAGS) $(UWTERM_OBJS) $(LIBUW)
X
Xuwplot:		$(UWPLOT_OBJS)
X	$(CC) -o $@ $(LFLAGS) $(UWPLOT_OBJS) $(LIBUW)
X
Xlint:
X	for src in $(SOURCES); \
X	do echo $$src:; lint -hubx -I$(INCDIR) $(DEFINES) $$src; done
X
Xtags:
X	ctags $(SOURCES)
X
Xdepend: 
X	$(CC) -M -I$(INCDIR) $(DEFINES) $(SOURCES) | \
X	sed -e ':loop' \
X	    -e 's/\.\.\/[^ /]*\/\.\./../' \
X	    -e 't loop' | \
X	awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
X		else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X		       else rec = rec " " $$2 } } \
X	      END { print rec } ' >> makedep
X	echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
X	echo '$$r makedep' >>eddep
X	echo 'w' >>eddep
X	cp Makefile Makefile.bak
X	ex - Makefile < eddep
X	rm eddep makedep
X
Xclean:
X	-rm -f *.o
X
X# DO NOT DELETE THIS LINE (or the following blank line) -- make depend uses it
X
SHAR_EOF
if test 1860 -ne "`wc -c < 'utility/Makefile_4.3'`"
then
	echo shar: error transmitting "'utility/Makefile_4.3'" '(should have been 1860 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'utility/uwplot.c'" '(2810 characters)'
if test -f 'utility/uwplot.c'
then
	echo shar: will not over-write existing file "'utility/uwplot.c'"
else
sed 's/^X//' << \SHAR_EOF > 'utility/uwplot.c'
X/*
X *	uwplot
X *
X * Copyright 1986 by John D. Bruner.  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 <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <sys/signal.h>
X#include <sys/errno.h>
X#include <ctype.h>
X#include <stdio.h>
X
X#include "uwlib.h"
X
Xchar *argv0;
XUWIN uwin;
X
Xmain(argc, argv)
Xchar **argv;
X{
X	register int c, len;
X	register char *cp;
X	register char *title;
X	register struct sockaddr_in *sin;
X	auto struct sockaddr_in sa;
X	auto char buf[4096];
X	extern char *optarg;
X	extern int errno;
X	extern onintr();
X
X	/*
X	 * Options which are recognized directly are:
X	 *
X	 *	-ninet	connect to server at address "inet"
X	 *	-ttitle	label window with "title" (default is argv[0])
X	 */
X	argv0 = argv[0];
X	sin = (struct sockaddr_in *)0;
X	title = argv0;
X	while ((c = getopt(argc, argv, "n:t:")) != EOF) {
X		switch (c) {
X		case 'n':
X			sa.sin_family = AF_INET;
X			sa.sin_addr.s_addr = 0;
X			sa.sin_port = 0;
X			bzero(sa.sin_zero, sizeof sa.sin_zero);
X			for (cp=optarg; isxdigit(c = *cp); cp++) {
X				/* Pyramid compiler botch */
X				/* sa.sin_addr.s_addr *= 16; */
X				sa.sin_addr.s_addr <<= 4;
X				if (isdigit(c))
X					sa.sin_addr.s_addr += c - '0';
X				else if (islower(c))
X					sa.sin_addr.s_addr += c-'a' + 10;
X				else
X					sa.sin_addr.s_addr += c-'A' + 10;
X			}
X			if (c == '.')
X				for (cp++; isdigit(c = *cp); cp++)
X					sa.sin_port = sa.sin_port*10 + c-'0';
X			if (sa.sin_addr.s_addr == 0 || sa.sin_port == 0) {
X				fprintf(stderr,
X				    "%s: bad Internet address: %s\n",
X				    argv0, optarg);
X				return(1);
X			}
X			sa.sin_addr.s_addr = htonl(sa.sin_addr.s_addr);
X			sa.sin_port = htons(sa.sin_port);
X			sin = &sa;
X			break;
X		case 't':
X			title = optarg;
X			break;
X		}
X	}
X
X	/*
X	 * Catch hangup, interrupt, quit, and termination signals.  Kill
X	 * the window if one of these is received.
X	 */
X	(void)signal(SIGHUP, onintr);
X	(void)signal(SIGINT, onintr);
X	(void)signal(SIGQUIT, onintr);
X	(void)signal(SIGTERM, onintr);
X
X	/*
X	 * Create a new plot window, title it, and make it visible.
X	 */
X	if ((uwin = uw_new(UWT_PLOT, sin)) == (UWIN)0) {
X		uw_perror(argv[0], uwerrno, errno);
X		return(1);
X	}
X	(void)uw_stitle(uwin, title);
X	(void)uw_svis(uwin, 1);
X
X	/*
X	 * Copy the standard input to the plot window.
X	 */
X	while ((len = read(0, buf, sizeof buf)) > 0 ||
X	    (len < 0 && errno == EINTR)) {
X		if (len > 0)
X			(void)write(UW_DATAFD(uwin), buf, len);
X	}
X
X	/*
X	 * This is something of a hack.  We don't expect to be able to
X	 * read anything from the window.  The read will hang until the
X	 * window is killed.
X	 */
X	while ((len = read(UW_DATAFD(uwin), buf, sizeof buf)) > 0 ||
X	    len < 0 && errno == EINTR)
X		;
X	return(0);
X}
X
Xonintr()
X{
X	uw_kill(uwin);
X	exit(0);
X}
SHAR_EOF
if test 2810 -ne "`wc -c < 'utility/uwplot.c'`"
then
	echo shar: error transmitting "'utility/uwplot.c'" '(should have been 2810 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'utility/uwterm.c'" '(15896 characters)'
if test -f 'utility/uwterm.c'
then
	echo shar: will not over-write existing file "'utility/uwterm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'utility/uwterm.c'
X/*
X *	uwterm
X *
X * Copyright 1986 by John D. Bruner.  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#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include <sys/wait.h>
X#include <netinet/in.h>
X#include <signal.h>
X#include <strings.h>
X#include <ctype.h>
X#include <errno.h>
X#include <stdio.h>
X
X#include "openpty.h"
X#include "uwlib.h"
X
X#ifndef UWTERM
X#define	UWTERM	"uwterm"
X#endif
X
X#define	CTL(c)		((c)&037)
X
X#ifndef FD_SET
X/* 4.2 retrofit: better definitions for these are in 4.3BSD's <sys/types.h> */
X#define	FD_SET(n,p)	((p)->fds_bits[0] |= (1 << (n)))
X#define	FD_CLR(n,p)	((p)->fds_bits[0] &= ~(1 << (n)))
X#define	FD_ISSET(n,p)	((p)->fds_bits[0] & (1 << (n)))
X#define	FD_ZERO(p)	((p)->fds_bits[0] = 0)
X#define	FD_SETSIZE	(NBBY*sizeof(long))
X#endif
X
Xextern int optind;
Xextern char *optarg;
Xextern char *getenv();
Xextern char *malloc();
Xextern deadkid();
Xextern int errno;
X
X#ifndef htons
X/* These should have been defined in <netinet/in.h>, but weren't (in 4.2BSD) */
Xextern unsigned short htons(), ntohs();
Xextern unsigned long htonl(), ntohl();
X#endif
X
Xchar *argv0;
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	register char *cp;
X	register int c;
X	int wflag;
X	uwtype_t wtype;
X	char *term, *title, *server, *login;
X	struct sockaddr_in sa, *sin;
X	char hostname[32];
X
X	/*
X	 * If called with no arguments, create a new window using the
X	 * current shell according to the SHELL environment variable
X	 * (or "/bin/sh" if that doesn't exist).
X	 *
X	 * Options which are recognized directly are:
X	 *
X	 *	-ninet	connect to server at address "inet"
X	 *	-wtype	create window with emulation "type"
X	 *	-ttitle	label window with "title"
X	 *	-llogin	use login name "login" on remote machine
X	 *
X	 * If no explicit title is specified, the command name is used.
X	 */
X	argv0 = argv[0];
X	sin = (struct sockaddr_in *)0;
X	server = (char *)0;
X	login = (char *)0;
X	title = (char *)0;
X	wflag = 0;
X	term = (char *)0;
X	while ((c = getopt(argc, argv, "l:n:t:w:")) != EOF) {
X		switch (c) {
X		case 'l':
X			if (optarg[0] == '\0') {
X				fprintf(stderr,
X				    "%s: \"-l\" requires user name\n", argv0);
X			} else
X				login = optarg;
X			break;
X		case 'n':
X			server = optarg;
X			sa.sin_family = AF_INET;
X			sa.sin_addr.s_addr = 0;
X			sa.sin_port = 0;
X			bzero(sa.sin_zero, sizeof sa.sin_zero);
X			for (cp=optarg; isxdigit(c = *cp); cp++) {
X				/* Pyramid compiler botch */
X				/* sa.sin_addr.s_addr *= 16; */
X				sa.sin_addr.s_addr <<= 4;
X				if (isdigit(c))
X					sa.sin_addr.s_addr += c - '0';
X				else if (islower(c))
X					sa.sin_addr.s_addr += c-'a' + 10;
X				else
X					sa.sin_addr.s_addr += c-'A' + 10;
X			}
X			if (c == '.')
X				for (cp++; isdigit(c = *cp); cp++)
X					sa.sin_port = sa.sin_port*10 + c-'0';
X			if (sa.sin_addr.s_addr == 0 || sa.sin_port == 0) {
X				fprintf(stderr,
X				    "%s: bad Internet address: %s\n",
X				    argv0, optarg);
X				return(1);
X			}
X			sa.sin_addr.s_addr = htonl(sa.sin_addr.s_addr);
X			sa.sin_port = htons(sa.sin_port);
X			sin = &sa;
X			break;
X		case 'w':
X			wflag++;
X			term = optarg;
X			wtype = uw_ttype(optarg);
X			break;
X		case 't':
X			title = optarg;
X			break;
X		}
X	}
X
X	gethostname(hostname, sizeof hostname);
X	if (title == (char *)0) {
X		/*
X		 * If there was no "-t" argument, then "title" will still
X		 * be NULL.  In this case we use the host name.
X		 */
X		if (optind == argc)
X			title = hostname;
X		else
X			title = argv[optind];
X	}
X	
X	if (!term) {
X		/*
X		 * If there was no "-w" argument, fetch the window
X		 * type from the environment.  If that fails, use
X		 * a default.
X		 */
X		if ((term=getenv("TERM")) != (char *)0)
X			wtype = uw_ttype(term);
X		else
X			wtype = UWT_ADM31;
X	}
X
X	if (optind == argc-1) {
X		/*
X		 * The remaining argument is the host name.  Fork an "rsh"
X		 * to execute this on the remote machine.
X		 */
X		return(doremote(argv[optind], server, title, term, login));
X	} else if (optind == argc) {
X		/*
X		 * There are no other arguments.  Set up the connection
X		 * to this machine.
X		 */
X		return(dolocal(sin, title, wtype, term));
X	} else {
X		fprintf(stderr,
X		    "Usage: \"%s [-ttitle] [-wtype] [-naddr] [-llogin] host\"\n",
X		    argv0);
X		return(1);
X	}
X}
X
Xdoremote(host, server, title, term, login)
Xchar *host;
Xchar *server;
Xchar *title;
Xchar *term;
Xchar *login;
X{
X	register int fd, i, pid;
X	register char *cp;
X	char *av[16];
X
X	/*
X	 * Invoke a remote "uwterm" via "rsh".
X	 */
X	i = 0;
X	av[i++] = "rsh";
X	av[i++] = host;
X	av[i++] = "-n";
X	if (login != NULL) {
X		av[i++] = "-l";
X		av[i++] = login;
X	}
X	av[i++] = UWTERM;
X	if (server == (char *)0) {
X		if ((server = getenv("UW_INET")) == (char *)0) {
X			fprintf(stderr,"%s: Can't find window server\n",argv0);
X			return(1);
X		}
X	}
X	if ((cp = malloc(3+strlen(server))) == (char *)0) {
X		fprintf(stderr, "%s: out of memory\n", argv0);
X		return(1);
X	}
X	(void)strcat(strcpy(cp, "-n"), server);
X	av[i++] = cp;
X
X	if (title != (char *)0) {
X		if ((cp = malloc(3+strlen(title))) == (char *)0) {
X			fprintf(stderr, "%s: out of memory\n", argv0);
X			return(1);
X		}
X		(void)strcat(strcpy(cp, "-t"), title);
X		av[i++] = cp;
X	}
X
X	if (term != (char *)0) {
X		if ((cp = malloc(3+strlen(term))) == (char *)0) {
X			fprintf(stderr, "%s: out of memory\n", argv0);
X			return(1);
X		}
X		(void)strcat(strcpy(cp, "-w"), term);
X		av[i++] = cp;
X	}
X
X	av[i] = (char *)0;
X
X	for (fd=getdtablesize()-1; fd > 2; fd--)
X		(void)fcntl(fd, F_SETFD, 1);
X	(void)execvp(av[0], av);
X	(void)execv("/usr/ucb/rsh", av);	/* last-ditch try */
X	perror(av[0]);
X	return(1);
X}
X
X			
Xdolocal(sin, title, wtype, term)
Xstruct sockaddr_in *sin;
Xchar *title;
Xuwtype_t wtype;
Xchar *term;
X{
X	register UWIN uwin;
X	register int fd;
X	register int s;
X	struct ptydesc pt;
X
X	/*
X	 * Create and initialize a pseudo-terminal.
X	 */
X	if (openpty(&pt) < 0) {
X		fprintf(stderr, "No pseudo-terminals are available\n");
X		return(1);
X	}
X	ttyinit(pt.pt_tfd);
X
X
X	/*
X	 * Make fd's 0 and 1 be "/dev/null".  We'd like to force a known
X	 * definition for fd 2 at this point, but we may need it for
X	 * uw_perror() if uw_new() fails.
X	 */
X	if ((fd = open("/dev/null", O_RDWR)) >= 0) {	/* should be zero */
X		if (fd != 0 && pt.pt_tfd != 0 && pt.pt_pfd != 0)
X			dup2(fd, 0);
X		if (fd != 1 && pt.pt_tfd != 1 && pt.pt_pfd != 1)
X			dup2(fd, 1);
X		if (fd > 2)
X			(void)close(fd);
X	}
X
X	/*
X	 * Create and title the window.  Make it visible.
X	 */
X	if ((uwin = uw_new(wtype, sin)) == (UWIN)0) {
X		uw_perror(argv0, uwerrno, errno);
X		return(1);
X	}
X	(void)uw_stitle(uwin, title);
X	(void)uw_svis(uwin, 1);
X
X	/*
X	 * We no longer have use for fd 2, so make it "/dev/null" (the
X	 * same as fd 0.
X	 */
X	(void)dup2(0, 2);
X
X	/*
X	 * Adjust the environment to contain the correct values of TERM,
X	 * UW_ID, and UW_INET.  These will be inherited by the child
X	 * we will create next.
X	 */
X	adjenv(term, sin, UW_ID(uwin));
X
X	/*
X	 * Create a process to execute the command connected to the pty.
X	 */
X	runcmd(pt.pt_tfd, pt.pt_tname);
X
X	/*
X	 * Ignore signals that might cause us trouble.  We do NOT ignore
X	 * SIGTSTP so that the user can move us from the foreground into
X	 * the background if desired.
X	 */
X	signal(SIGINT, SIG_IGN);
X	signal(SIGQUIT, SIG_IGN);
X	signal(SIGCHLD, deadkid);
X
X#if defined(TIOCSWINSZ) || defined(TIOCSSIZE)
X	/*
X	 * Install an option handling routine to catch window size
X	 * changes from the Mac and make the appropriate changes to
X	 * the pseudo-terminal.
X	 */
X	setresize(uwin, pt.pt_pfd);
X#endif
X
X	/*
X	 * Close the slave side of the pty.  Copy data between the pty
X	 * and the window.  The return value from copy() is the exit
X	 * status.
X	 */
X	(void)close(pt.pt_tfd);
X	s = copy(pt.pt_pfd, UW_DATAFD(uwin));
X	uw_kill(uwin);
X	return(s);
X}
X
Xttyinit(ptyfd)
Xregister int ptyfd;
X{
X	register int ttyfd;
X	struct sgttyb sg;
X	struct tchars tc;
X	struct ltchars ltc;
X	int ldisc;
X	int lmode;
X
X	/*
X	 * Initialize the modes of the terminal whose file descriptor
X	 * is "ptyfd" to the same modes as the current terminal.  If there
X	 * isn't a "current terminal" handy, then use hardcoded defaults.
X	 */
X	for (ttyfd=0; ttyfd < 3 && ioctl(ttyfd, TIOCGETD, &ldisc) < 0; ttyfd++)
X		;
X	if (ttyfd < 3) {
X		(void)ioctl(ttyfd, TIOCGETP, &sg);
X		(void)ioctl(ttyfd, TIOCGETC, &tc);
X		(void)ioctl(ttyfd, TIOCGLTC, &ltc);
X		(void)ioctl(ttyfd, TIOCLGET, &lmode);
X	} else {
X		ldisc = NTTYDISC;
X
X		sg.sg_ispeed = sg.sg_ospeed = 13; /* doesn't really matter */
X		sg.sg_erase = 0177;	/* ugh */
X		sg.sg_kill = CTL('u');	/* ugh */
X		sg.sg_flags = ECHO|CRMOD|ANYP;
X
X		tc.t_intrc = CTL('c');	/* yuck, should be 0177 */
X		tc.t_quitc = CTL('\\');
X		tc.t_startc = CTL('q');
X		tc.t_stopc = CTL('s');
X		tc.t_eofc = CTL('d');
X		tc.t_brkc = -1;
X
X		ltc.t_suspc = CTL('z');
X		ltc.t_dsuspc = CTL('y');
X		ltc.t_rprntc = CTL('r');
X		ltc.t_flushc = CTL('o');
X		ltc.t_werasc = CTL('w');
X		ltc.t_lnextc = CTL('v');
X
X		lmode = LCRTBS|LCRTERA|LCRTKIL|LCTLECH;
X	}
X	(void)ioctl(ptyfd, TIOCSETD, &ldisc);
X	(void)ioctl(ptyfd, TIOCSETP, &sg);
X	(void)ioctl(ptyfd, TIOCSETC, &tc);
X	(void)ioctl(ptyfd, TIOCSLTC, &ltc);
X	(void)ioctl(ptyfd, TIOCLSET, &lmode);
X}
X
Xadjenv(term, sin, wid)
Xchar *term;
Xstruct sockaddr_in *sin;
Xuwid_t wid;
X{
X	char *env[4];
X	static char ttype[sizeof "TERM=" + 16];
X	static char inet[sizeof INET_ENV + 16];
X	static char idstr[sizeof "UW_ID=" + 20];
X
X	/*
X	 * Redefine the environment variable UW_ID.  Redefine UW_INET
X	 * if "sin" is non-NULL.  Redefine TERM.
X	 */
X	(void)sprintf(ttype, "TERM=%.15s", term);
X	env[0] = ttype;
X	
X	(void)sprintf(idstr, "UW_ID=%ld", wid);
X	env[1] = idstr;
X
X	if (sin != NULL) {
X		(void)sprintf(inet, "%s=%08lx.%d", INET_ENV,
X		    ntohl(sin->sin_addr.s_addr), ntohs(sin->sin_port));
X		env[2] = inet;
X		env[3] = (char *)0;
X	}  else
X		env[2] = (char *)0;
X	env_set(env);
X}
X
Xruncmd(fd, tname)
Xint fd;
Xchar *tname;
X{
X	register int pid;
X	register char *shell;
X
X	/*
X	 * Figure out the name of the user's shell.  If unknown,
X	 * use a default.
X	 */
X	if ((shell = getenv("SHELL")) == (char *)0)
X		shell = "/bin/sh";
X
X	/*
X	 * Fork a new process and attach "fd" to fd's 0, 1, and 2 of
X	 * that new process.  Disassociate the current controlling
X	 * terminal and attach the new one (whose name is "tname").
X	 */
X	while ((pid = fork()) < 0)
X		sleep(5);
X	if (pid == 0) {
X		if (fd != 0)
X			dup2(fd, 0);
X		if (fd != 1)
X			dup2(fd, 1);
X		if (fd != 2)
X			dup2(fd, 2);
X		if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
X			(void)ioctl(fd, TIOCNOTTY, (char *)0);
X			(void)close(fd);
X		} else
X			setpgrp(0, 0);
X		(void)open(tname, O_RDWR);
X		for (fd=getdtablesize()-1; fd > 2; fd--)
X			(void)fcntl(fd, F_SETFD, 1);
X		execlp(shell, "-", (char *)0);
X		execl(shell, "-", (char *)0);
X		_exit(1);
X	}
X}
X
Xcopy(fd1, fd2)
Xint fd1, fd2;
X{
X	struct fdinfo {
X		int	fi_fd;		/* associated file descriptor */
X		int	fi_size;	/* amount of data in buffer */
X		char	*fi_ptr;	/* pointer to data in fi_buf */
X		char	fi_buf[1024];
X	};
X	register struct fdinfo *fi, *fo;
X	register int n, nfds, len;
X	struct fdinfo fdinfo[2];
X	struct fd_set rdmask[2], wtmask[2], exmask[2];
X	struct timeval tv;
X
X	/*
X	 * Copy data between file descriptors fd1 and fd2.  Return when an
X	 * EOF is read or an I/O error (other than an interrupted system
X	 * call or non-blocking I/O message) is encountered.
X	 */
X	FD_ZERO(&rdmask[1]);
X	FD_ZERO(&wtmask[1]);
X	FD_ZERO(&exmask[1]);
X
X	fdinfo[0].fi_fd = fd1;
X	fdinfo[0].fi_size = 0;
X	fdinfo[1].fi_fd = fd2;
X	fdinfo[1].fi_size = 0;
X
X	FD_SET(fd1, &rdmask[1]);
X	FD_SET(fd2, &rdmask[1]);
X
X	(void)fcntl(fd1, F_SETFL, FNDELAY);
X	(void)fcntl(fd2, F_SETFL, FNDELAY);
X
X	nfds = ((fd1 > fd2) ? fd1 : fd2) + 1;
X
X	while (1) {
X		rdmask[0] = rdmask[1];
X		wtmask[0] = wtmask[1];
X		exmask[0] = exmask[1];
X		errno = 0;
X		if (fdinfo[0].fi_size != 0 || fdinfo[1].fi_size != 0) {
X			/*
X			 * Select does not work correctly for writes on
X			 * some machines, so we must fake it.  If a write
X			 * is pending, we time out after 1/50 second and
X			 * pretend that select told us that writes could
X			 * now be performed.  The code below will do the
X			 * correct thing if the write would still block.
X			 */
X			tv.tv_sec = 0;
X			tv.tv_usec = 1000000 / 50;
X			n = select(nfds, rdmask, wtmask, exmask, &tv);
X			wtmask[0] = wtmask[1];
X		} else
X			n = select(nfds, rdmask, wtmask, exmask, (struct timeval *)0);
X		if (n < 0 && errno == EINTR) {
X			continue;
X		} else if (n <= 0) {
X			perror("select");
X			return(1);
X		}
X		for (fi=fdinfo; fi < fdinfo+2; fi++) {
X			fo = fdinfo + !(fi - fdinfo);
X			if (FD_ISSET(fi->fi_fd, rdmask)) {
X				/* data available for reading */
X				len = read(fi->fi_fd, fi->fi_buf,
X				    sizeof fi->fi_buf);
X				if (len > 0) {
X					fi->fi_size = len;
X					fi->fi_ptr = fi->fi_buf;
X					FD_CLR(fi->fi_fd, &rdmask[1]);
X					FD_SET(fo->fi_fd, &wtmask[1]);
X					FD_SET(fo->fi_fd, &wtmask[0]);
X				} else if (len == 0) {
X					/* EOF, exit */
X					return(0);
X				} else if (errno != EWOULDBLOCK &&
X				    errno != EINTR) {
X					/* error, exit */
X					return(1);
X				}
X			}
X			if (FD_ISSET(fo->fi_fd, wtmask)) {
X				/* data ready for writing */
X				errno = 0;
X				len = write(fo->fi_fd, fi->fi_ptr, fi->fi_size);
X				if (len > 0) {
X					fi->fi_ptr += len;
X					fi->fi_size -= len;
X					if (fi->fi_size == 0) {
X						FD_SET(fi->fi_fd, &rdmask[1]);
X						FD_CLR(fo->fi_fd, &wtmask[1]);
X					}
X				} else if (errno != EWOULDBLOCK &&
X				    errno != EINTR) {
X					/* error, exit */
X					return(1);
X				}
X			}
X		}
X	}
X}
X
Xdeadkid()
X{
X	register int pid;
X
X	/*
X	 * Collect dead children.  Don't bother with their exit status
X	 * or resource usage.
X	 */
X	while ((pid = wait3((union wait *)0, WNOHANG, (struct rusage *)0)) > 0)
X		;
X}
X
X#if defined(TIOCSWINSZ) || defined(TIOCSSIZE)
Xstatic int ptyfd;
X
X#ifdef TIOCSWINSZ
Xstatic struct winsize winsz;
X
Xvoid
Xdoresize(uwin, optnum, optcmd, uwoptval)
XUWIN uwin;
Xuwopt_t optnum;
Xuwoptcmd_t optcmd;
Xunion uwoptval *uwoptval;
X{
X	uwtype_t wtype;
X
X	/*
X	 * 4.3BSD-style window resizing
X	 */
X	if (uw_gtype(uwin, &wtype) < 0)
X		wtype = UWT_ADM31;	/* probably wrong to do this here */
X	if (optcmd == UWOC_SET) {
X		switch (optnum) {
X		case UWOP_WSIZE:
X			winsz.ws_ypixel = uwoptval->uwov_point.v;
X			winsz.ws_xpixel = uwoptval->uwov_point.h;
X			break;
X		case UWOP_TSIZE:
X			if (wtype <= UWT_ANSI) {
X				winsz.ws_row = uwoptval->uwov_point.v;
X				winsz.ws_col = uwoptval->uwov_point.h;
X			}
X			break;
X		}
X		if (wtype <= UWT_ANSI &&
X		    (optnum == UWOP_WSIZE || optnum == UWOP_TSIZE))
X			(void)ioctl(ptyfd, TIOCSWINSZ, &winsz);
X	}
X}
X
Xsetresize(uwin, fd)
XUWIN uwin;
Xint fd;
X{
X	struct uwpoint pt;
X	uwtype_t wtype;
X
X	/*
X	 * Set up the option-handling routine "doresize".
X	 */
X	ptyfd = fd;
X	uw_optfn(uwin, UWOP_TSIZE, doresize);
X	uw_optfn(uwin, UWOP_WSIZE, doresize);
X	winsz.ws_row = 24;	/* default to standard terminal size */
X	winsz.ws_col = 80;
X	if (uw_gwsize(uwin, &pt) == 0) {
X		winsz.ws_ypixel = pt.uwp_v;
X		winsz.ws_xpixel = pt.uwp_h;
X	} else {
X		/* make up something plausible */
X		winsz.ws_ypixel = 8 * winsz.ws_row;
X		winsz.ws_xpixel = 8 * winsz.ws_col;
X	}
X
X	if (uw_gtype(uwin, &wtype) == 0 && wtype <= UWT_ANSI)
X		(void)uw_optcmd(uwin, UWOP_TSIZE, UWOC_DO, (union uwoptval *)0);
X}
X
X#else
X#ifdef TIOCSSIZE
Xvoid
Xdoresize(uwin, optnum, optcmd, uwoptval)
XUWIN uwin;
Xuwopt_t optnum;
Xuwoptcmd_t optcmd;
Xunion uwoptval *uwoptval;
X{
X	struct ttysize ts;
X	uwtype_t wtype;
X
X	/*
X	 * Sun-style window resizing
X	 */
X	if (uw_gtype(uwin, &wtype) < 0)
X		wtype = UWT_ADM31;	/* probably wrong to do this here */
X	if (wtype <= UWT_ANSI && optnum == UWOP_TSIZE && optcmd == UWOC_SET) {
X		ts.ts_lines = uwoptval->uwov_point.v;
X		ts.ts_cols = uwoptval->uwov_point.h;
X		(void)ioctl(ptyfd, TIOCSSIZE, &ts);
X	}
X}
X
Xsetresize(uwin, fd)
XUWIN uwin;
Xint fd;
X{
X	uwtype_t wtype;
X
X	/*
X	 * Set up the option-handling routine "doresize".
X	 */
X	ptyfd = fd;
X	uw_optfn(uwin, UWOP_TSIZE, doresize);
X
X	if (uw_gtype(uwin, &wtype) == 0 && wtype <= UWT_ANSI)
X		(void)uw_optcmd(uwin, UWOP_TSIZE, UWOC_DO, (union uwoptval *)0);
X}
X#endif
X#endif
X#endif
SHAR_EOF
if test 15896 -ne "`wc -c < 'utility/uwterm.c'`"
then
	echo shar: error transmitting "'utility/uwterm.c'" '(should have been 15896 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'utility/uwtitle.c'" '(1860 characters)'
if test -f 'utility/uwtitle.c'
then
	echo shar: will not over-write existing file "'utility/uwtitle.c'"
else
sed 's/^X//' << \SHAR_EOF > 'utility/uwtitle.c'
X/*
X *	uwtitle
X *
X * Copyright 1986 by John D. Bruner.  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#include <strings.h>
X#include <stdio.h>
X
X#include "uwlib.h"
X
Xextern char *optarg;
Xextern int optind;
Xextern int errno;
X
Xextern char *getenv();
Xextern long atol();
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	register int c;
X	register char *cp, *cq, **av;
X	register uwid_t uwid;
X	char *argv0;
X	char *cqlimit;
X	union uwoptval uwoptval;
X
X	/*
X	 * If called with no arguments, print a syntax message.  Otherwise,
X	 * set the title of the current window to argv[1..argc-1].  The
X	 * window ID is obtained from the environment or the "-i" argument.
X	 */
X	argv0 = argv[0];
X	uwid = 0;
X	while ((c = getopt(argc, argv, "i:")) != EOF) {
X		switch (c) {
X		case 'i':
X			if ((uwid = atol(optarg)) == 0) {
X				fprintf(stderr,
X				    "%s: malformed \"-i\" argument\n", argv0);
X				return(1);
X			}
X			break;
X		}
X	}
X	if (optind >= argc) {
X		fprintf(stderr, "Syntax: \"%s [-iID] title ...\"\n", *argv);
X		return(1);
X	}
X
X	if (uwid == 0) {
X		if ((cp = getenv("UW_ID")) == NULL) {
X			fprintf(stderr,
X			    "%s: can't determine window ID\n", argv0);
X			return(1);
X		}
X
X		if ((uwid = (uwid_t)atol(cp)) == 0) {
X			fprintf(stderr,
X			    "%s: garbaged window ID in environment: %s",
X			    argv0, cp);
X			return(1);
X		}
X	}
X
X	/*
X	 * Copy the argv list into "uwoptval" and change the title.
X	 */
X	av = argv + optind - 1;
X	cq = uwoptval.uwov_string;
X	cqlimit = uwoptval.uwov_string + sizeof uwoptval.uwov_string;
X	while ((cp = *++av) != NULL && cq < cqlimit) {
X		while (cq < cqlimit && (*cq++ = *cp++) != '\0')
X			;
X		cq[-1] = ' ';
X	}
X	cq[-1] = '\0';
X
X	if (uw_rsetopt(uwid, UWOP_TITLE, &uwoptval) < 0) {
X		uw_perror("uw_rsetopt", uwerrno, errno);
X		return(1);
X	} else
X		return(0);
X}
SHAR_EOF
if test 1860 -ne "`wc -c < 'utility/uwtitle.c'`"
then
	echo shar: error transmitting "'utility/uwtitle.c'" '(should have been 1860 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'utility/uwtool.c'" '(2550 characters)'
if test -f 'utility/uwtool.c'
then
	echo shar: will not over-write existing file "'utility/uwtool.c'"
else
sed 's/^X//' << \SHAR_EOF > 'utility/uwtool.c'
X/*
X *	uwtool
X *
X * Copyright 1986 by John D. Bruner.  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#include <strings.h>
X#include <stdio.h>
X
X#include "uwlib.h"
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	register uwid_t uwid;
X	register char *fname, *term;
X	register int c;
X	register uwtype_t wtype;
X	char *argv0;
X	char *av[2];
X	int vflag;
X	int wflag;
X	char *title;
X	union uwoptval uwoptval;
X	extern int errno;
X	extern int optind;
X	extern char *optarg;
X	extern char *getenv();
X
X	/*
X	 * If called with no arguments, create a new window using the
X	 * current shell according to the SHELL environment variable
X	 * (or "/bin/sh" if that doesn't exist).  If called with
X	 * arguments, argv[optind] through argv[argc-1] are the arguments
X	 * to the command.
X	 *
X	 * Options which are recognized directly are:
X	 *
X	 *	-v	(verbose) print new window ID on stdout
X	 *	-wtype	create window with emulation "type"
X	 *	-ttitle	label window with "title"
X	 *
X	 * If no explicit title is specified, the command name is used.
X	 */
X	argv0 = argv[0];
X	wflag = 0;
X	vflag = 0;
X	title = (char *)0;
X	while ((c = getopt(argc, argv, "vw:t:")) != EOF) {
X		switch (c) {
X		case 'v':
X			vflag++;
X			break;
X		case 'w':
X			wflag++;
X			wtype = uw_ttype(optarg);
X			break;
X		case 't':
X			title = optarg;
X			break;
X		}
X	}
X			
X	if (optind < argc) {
X		/*
X		 * Adjust the "argv" pointer according to the number of
X		 * arguments we've processed.
X		 */
X		argv += optind;
X		fname = *argv;
X	} else {
X		/*
X		 * No (non-option) arguments -- use SHELL
X		 */
X		if ((fname = getenv("SHELL")) == (char *)0)
X			fname = "/bin/sh";
X		av[0] = fname;
X		av[1] = (char *)0;
X		argv = av;
X	}
X
X	if (title == (char *)0) {
X		/*
X		 * If there was no "-t" argument, then "title" will still
X		 * be NULL.  In this case we use the command name as
X		 * the title.
X		 */
X		title = fname;
X	}
X	
X	if (!wflag) {
X		/*
X		 * If there was no "-w" argument, fetch the window
X		 * type from the environment.  If that fails, use
X		 * a default.
X		 */
X		if ((term=getenv("TERM")) != (char *)0)
X			wtype = uw_ttype(term);
X		else
X			wtype = UWT_ADM31;
X	}
X	
X	if ((uwid = uw_cmd(wtype, fname, argv)) > 0) {
X		(void)strncpy(uwoptval.uwov_string, title,
X		    sizeof uwoptval.uwov_string);
X		(void)uw_rsetopt(uwid, UWOP_TITLE, &uwoptval);
X		if (vflag)
X			printf("%d\n", uwid);
X		return(0);
X	} else {
X		if (uwerrno != UWE_NXSERV)
X			uw_perror(fname, uwerrno, errno);
X		else
X			uw_perror(argv0, uwerrno, errno);
X		return(1);
X	}
X}
SHAR_EOF
if test 2550 -ne "`wc -c < 'utility/uwtool.c'`"
then
	echo shar: error transmitting "'utility/uwtool.c'" '(should have been 2550 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 9 ---