home *** CD-ROM | disk | FTP | other *** search
- From: hyc@math.lsa.umich.edu (Howard Chu)
- Newsgroups: comp.windows.misc,alt.sources,unix-pc.sources,comp.sys.att
- Subject: Re: rmgr Remote Window Manager for MGR
- Message-ID: <1990Oct17.010306.4846@math.lsa.umich.edu>
- Date: 17 Oct 90 01:03:06 GMT
-
- Oops. Left the editor before including the actual sources. Here ya go.
-
- #--------------------------------CUT HERE-------------------------------------
- #! /bin/sh
- #
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- #
- # -r--r--r-- 1 hyc 725 Oct 14 05:39 Makefile
- # -r--r--r-- 1 hyc 1027 Oct 14 08:43 README
- # -r--r--r-- 1 hyc 9341 Oct 14 08:29 rmgr.1
- # -rw-r--r-- 1 hyc 32339 Oct 15 03:39 rmgr.c
- # -r--r--r-- 1 hyc 1169 Oct 14 08:29 rmgr.h
- #
- echo 'x - Makefile'
- if test -f Makefile; then echo 'shar: not overwriting Makefile'; else
- sed 's/^X//' << '________This_Is_The_END________' > Makefile
- X# The following options can be set:
- X#
- X# -DGETTTYENT -- your system has the new format /etc/ttys (like 4.3 BSD)
- X# and the getttyent(3) library functions.
- X#
- X# -DUSEBCOPY -- use the bcopy() from the system's C-library. If this
- X# is set, bcopy must support overlapping source and
- X# destination. If USEBCOPY is not set, screen uses its
- X# own version of bcopy.
- X#
- X# You should install as set-uid with owner root, so that it can read/write
- X# /etc/utmp, read /dev/kmem, and chown/chmod the allocated pseudo-ttys.
- X
- XOPTIONS= -DUSEBCOPY -DGETTTYENT
- X
- XCFLAGS= -O
- X
- Xrmgr: rmgr.o
- X $(CC) $(CFLAGS) -o rmgr rmgr.o -lmgr
- X
- Xrmgr.o: rmgr.c rmgr.h
- X $(CC) $(OPTIONS) $(CFLAGS) -c rmgr.c
- ________This_Is_The_END________
- if test `wc -c < Makefile` -ne 725; then
- echo 'shar: Makefile was damaged during transit (should have been 725 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - README'
- if test -f README; then echo 'shar: not overwriting README'; else
- sed 's/^X//' << '________This_Is_The_END________' > README
- X Howard Chu
- X October 14, 1990
- X
- XHowdy. This is rmgr, my program for managing multiple remote sessions
- Xthru a single communications line (e.g., a dial-up serial port). The
- Xheader file rmgr.h tries to #include <mgr/term.h>, so you will need to
- Xhave the MGR client library header files installed in a reasonable spot,
- Xlike /usr/include/mgr. (Or just add the -Ipath option to the Makefile
- Xand fake it...)
- X
- XThis program is derived from Oliver Laumann's "screen" program, and has
- Xnearly the same system requirements as that program. (I.e., BSD sockets
- Xand pseudo-ttys are necessary.) Plus, obviously, the console you are
- Xsitting in front of must be running an MGR server for you to use this
- Xprogram at all.
- X
- XI am calling this a beta-release, although the program is very stable
- Xand I don't expect many problems to crop up. (But read the man page,
- Xyou may find that the "features" I note could hamper your use... You're
- Xwelcome to tackle the two noted problems and tell me how it went.)
- X -- Howard
- X hyc@math.lsa.umich.edu
- ________This_Is_The_END________
- if test `wc -c < README` -ne 1027; then
- echo 'shar: README was damaged during transit (should have been 1027 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - rmgr.1'
- if test -f rmgr.1; then echo 'shar: not overwriting rmgr.1'; else
- sed 's/^X//' << '________This_Is_The_END________' > rmgr.1
- X.if n .ds Q \&"
- X.if n .ds U \&"
- X.if t .ds Q ``
- X.if t .ds U ''
- X.TH RMGR 1 "14 October 1990"
- X.UC 4
- X.SH NAME
- Xrmgr \- remote graphical window manager
- X.SH SYNOPSIS
- X.B rmgr
- X[
- X.B \-n \fIwindowname\fP
- X] [
- X.BR \fIcmd args\fP ]
- X.br
- X.B rmgr \-r
- X[
- X.BR \fIhost.tty\fP ]
- X.ta .5i 1.8i
- X.SH DESCRIPTION
- X.I rmgr
- Xis a client for MGR, the Bellcore window manager, that
- Xmultiplexes a communications line between several processes (typically
- Xinteractive shells). As the name implies, the program is meant to be run
- Xon a host other than where the MGR server resides.
- X.I Rmgr
- Xcreates a window on the local MGR server for each process spawned on the
- Xremote host. Each process has the full facilities of MGR at its disposal.
- X.PP
- XWhen
- X.I rmgr
- Xis called, it creates a single window with a shell; the pathname of the
- Xshell is taken from the environment symbol $SHELL; if this is not
- Xdefined, \*Q/bin/sh\*U is used.
- XNew windows can be created at any time by calling
- X.I rmgr
- Xfrom within a previously created window.
- XThe program to be started in a newly created
- Xwindow and optional arguments to the program can be supplied when
- X.I rmgr
- Xis invoked.
- XFor instance,
- X.IP
- Xrmgr csh
- X.PP
- Xwill create a window with a C-Shell and switch to that window.
- XWhen the process associated with the currently displayed window
- Xterminates (e.\|g. ^D has been typed to a shell),
- X.I rmgr
- Xswitches to the previously displayed window;
- Xwhen no more windows are left,
- X.I rmgr
- Xexits.
- X.PP
- XWhen \*Q/etc/utmp\*U is writable by
- X.IR rmgr ,
- Xan appropriate record is written to this file for each window and
- Xremoved when the window is terminated.
- X.PP
- XThe
- X.B \-r
- Xoption is used to resume a
- X.I rmgr
- Xsession that has been \fIdetached\fP from the terminal by means
- Xof the \*QDetach\*U menu option (see below).
- XThis mechanism allows a user to disconnect
- X.I rmgr
- Xtogether with all currently active windows from the terminal
- Xand resume it at a later point in time, e.\|g. at a later
- Xlogin session, and even from a different MGR host.
- XWhen more than one detached session exists, the
- X.B \-r
- Xoption displays a list of
- X.I host.tty
- Xpairs identifying the detached
- X.IR sessions .
- XIn this case an additional
- X.I host.tty
- Xargument can be given to resume a specific
- X.I rmgr
- Xsession.
- X.SH "MENU ITEMS"
- X.I Rmgr
- Xadds two menus to each window it creates, invoked by pressing the
- Xright mouse button. The first three menu items are simply place-holders.
- XThe first item is a title-bar, reading \*QMGR Windows =>\*U, the second
- Xitem is the name of the currently selected window, and the third is a
- Xdividing line. No actions are associated with these three items. The rest
- Xof this menu shows the available commands:
- X
- X.IP "\fBShell Window\fP"
- XCreate a new window with a shell and switch to that window.
- X.IP "\fBOther Window\fP"
- XCreate a new window, switch to that window, and prompt for a command
- Xto run in the window. A window name may also be specified by typing
- X\*Q-n \fIwindowname\fP\*U at the beginning of the line.
- X.IP "\fBKill Window\fP"
- XClose the current window and kill its associated process.
- X.IP "\fBSuspend\fP"
- XSuspend
- X.IR rmgr .
- XThe window context is pushed onto the environment stack.
- X.IP "\fBDetach\fP"
- XDetach
- X.I rmgr
- X(put it into the background and disconnect it from its control terminal).
- XThis also pushes the window context onto the environment stack, in case
- Xthe session will be resumed without first destroying any created windows.
- XA detached
- X.I rmgr
- Xsession may be resumed by invoking
- X.I rmgr
- Xwith the
- X.B \-r
- Xoption.
- X.IR Rmgr
- Xmaintains a circular buffer for the last 2048 bytes written to each window,
- Xand will replay the contents of each window when the session is resumed and
- Xthe windows are recreated. Note that detached processes continue to run, and
- Xmay continue to generate output. So while the buffer will usually preserve all
- Xnecessary context, sometimes it may lose information, but it will almost
- Xalways yield an accurate representation of what the window should contain.
- X.IP "\fBQuit\fP\0\0\0\0\0"
- XKill all windows and terminate
- X.IR rmgr .
- X.PP
- XThe \*QMGR Windows =>\*U menu item is linked to a second menu. Moving the mouse
- Xto that item and sliding right displays the menu, a list of the names of all
- Xcurrently active
- X.IR rmgr
- Xwindows. Selecting any of these items will cause the associated window to
- Xpop forward and become the active window. Of course, windows may always be
- Xselected in the usual manner, i.\|e., move the mouse cursor to the window
- Xand click the left button.
- X
- X.SH OPERATION DETAILS
- XWhen
- X.I rmgr
- Xis invoked, it pushes a number of elements of the current window environment
- Xonto the stack, including the current font, window size and location, defined
- Xmenus, events, and text regions, and mode flags. It then sets up an escape
- Xcode to be used for its own event and menu strings. Then the main window is
- Xmoved to the top left corner of the screen and resized to 80 columns by 24
- Xrows of text. Codes are set for window activation, destruction, and reshaping,
- Xand the menus are downloaded to the window in menu slots 1 and 2. Finally, a
- Xshell (or other process, if specified) is started in the window.
- X
- XNew windows are always created near the top left corner of the screen, in
- Xthe default font, sized for 80 columns by 24 rows. If the window is resized,
- X.I rmgr
- Xwill attempt to inform the remote process of the new window size. The window's
- Xname defaults to the command name if no other name is explicitly given.
- X
- XKilling a window closes its control terminal and should cause the associated
- Xprocesses to terminate. If a process in an obscured window (i.\|e., a window
- Xthat is not the active window) terminates, the window is not closed. Instead,
- Xthe message \*Q[window shut down]\*U is written in the window. The window
- Xmay be removed by activating it, and then using either the
- X.I rmgr
- X\*QKill Window\*U option, or the system \*Qdestroy\*U option. This behavior
- Xis intended to prevent inadvertent loss of information when a hidden window
- Xis exited. Also, window 0, the main window, is never closed, though it may
- Xbe reused any number of times for different commands.
- X
- X.I Rmgr
- Xmay be suspended to temporarily disable the alternate windows and allow direct
- Xcommunication with the remote host. This is most useful for users dialing up
- Xon a serial line, who may wish to perform some file transfer functions, and
- Xthen resume the windowing sessions. As with a detached session, the processes
- Xin the various windows are not stopped, and may continue to generate output.
- XThe windows created by
- X.I rmgr
- Xremain on the screen, and should not be destroyed while
- X.I rmgr
- Xis suspended. They may safely be selected for viewing, and moved around, but
- Xshould not be changed in any way, or else when
- X.I rmgr
- Xis restarted the program will get confused. The Detach option should be used
- Xif the alternate windows are likely to be modified or nonexistent by the time
- Xthe
- X.I rmgr
- Xsession is resumed.
- X
- XWhen a detached
- X.I rmgr
- Xsession is resumed,
- X.I rmgr
- Xpolls the MGR server to see which alternate windows exist, if any. If the
- Xsame windows exist as at the time of detachment, then no special state
- Xrestoration is performed. If, instead, alternate windows exist which
- X.I rmgr
- Xdidn't expect to find, they are destroyed. Also, if expected windows are
- Xmissing, they are recreated and the contents of the history buffer are
- Xreplayed into the new window. This polling process is not particularly
- Xclever; the only checks are that the window IDs and text dimensions match,
- Xso it is possible to artifically create an environment that fits what
- X.I rmgr
- Xexpected to find, thus bypassing the restoration of state, but it would be
- Xsilly to try to contrive this situation. Usually resuming a detached session
- Xwill recreate all the alternate windows in nearly the exact same state as
- Xthey were before, plus any new output that may have appeared. Also, if any
- Xprocesses terminated while
- X.I rmgr
- Xwas detached, their windows will still be created, but will have the
- X\*Q[window shut down]\*U message attached. (This is also true when
- Xresuming a \fIsuspended\fP session.)
- X
- XAll new windows are created with the TERM and TERMCAP variables set. Most
- XMGR clients that expect to talk directly to the MGR server can also work
- Xnormally through
- X.I rmgr .
- XHowever, any client that directs queries to the MGR server and needs a reply
- Xcan only run if its window is the active window. This is a necessary
- Xrestriction, because MGR doesn't tag replies with the window ID of the
- Xintended recipient, so
- X.I rmgr
- Xsimply feeds the data to the active window. Clients that only issue commands
- Xand never expect replies should be able to work regardless of whether
- Xtheir window is active or obscured. However, it is still possible that some
- Xcommands will get garbled, as
- X.I rmgr
- Xdoes no interpretation of the data streams sent by the alternate windows,
- Xand does not guard against escape sequences being split or interleaved with
- Xdata from other windows. Perhaps a future version of
- X.I rmgr
- Xwill address these issues.
- X
- X.SH FILES
- X.nf
- X.ta 2i
- X$(HOME)/.rmgr Directory created by \fIrmgr\fP
- X.br
- X$(HOME)/.rmgr/\fIhost.tty\fP Socket created by \fIrmgr\fP
- X.br
- X/etc/utmp Login records
- X.fi
- X.SH "SEE ALSO"
- Xtermcap(5), utmp(5)
- X.br
- XMGR, a window system for Unix, by Stephen A. Uhler, Bell Communications Research
- X.SH AUTHOR
- XHoward Chu @ University of Michigan, hyc@math.lsa.umich.edu
- XDerived from \fIscreen\fP by Oliver Laumann @ Technical University of Berlin
- ________This_Is_The_END________
- if test `wc -c < rmgr.1` -ne 9341; then
- echo 'shar: rmgr.1 was damaged during transit (should have been 9341 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - rmgr.c'
- if test -f rmgr.c; then echo 'shar: not overwriting rmgr.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > rmgr.c
- X/* Copyright (c) 1987,1988 Oliver Laumann, Technical University of Berlin.
- X * Not derived from licensed software.
- X *
- X * Permission is granted to freely use, copy, modify, and redistribute
- X * this software, provided that no attempt is made to gain profit from it,
- X * the author is not construed to be liable for any results of using the
- X * software, alterations are clearly marked as such, and this notice is
- X * not modified.
- X */
- X
- X/* This program Copyright 1990 by Howard Chu.
- X *
- X * This is rmgr, a remote window manager for Bellcore's MGR window
- X * manager, by Howard Chu @ University of Michigan (Ann Arbor, MI).
- X * Much of this program consists of Oliver Laumann's code; I have not
- X * (usually) highlighted my changes in any way. Oliver didn't use any
- X * comments at all; for the most part I have followed his lead... }-)
- X * Suffice to say, some of the routines are original, some are heavily
- X * hacked upon versions of his code, and some are untouched from his
- X * program. Of course, the volume of code here represents only half
- X * of the code used in the screen program; the rest, support for ANSI
- X * terminal emulation, was discarded.
- X */
- X
- Xstatic char Version[] = "$Header: /usr/src/rmgr/RCS/rmgr.c,v 1.5 90/10/15 03:39:02 hyc Stable $";
- X
- X#include <stdio.h>
- X#include <sgtty.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <ctype.h>
- X#include <utmp.h>
- X#include <pwd.h>
- X#include <nlist.h>
- X#include <fcntl.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/file.h>
- X#include <sys/wait.h>
- X#include <sys/socket.h>
- X#include <sys/un.h>
- X#include <sys/stat.h>
- X#include <sys/dir.h>
- X#include "rmgr.h"
- X
- X#ifdef GETTTYENT
- X# include <ttyent.h>
- X#else
- X static struct ttyent {
- X char *ty_name;
- X } *getttyent();
- X static char *tt, *ttnext;
- X static char ttys[] = "/etc/ttys";
- X#endif
- X
- X#define MAXWIN 10
- X#define MSGWAIT 5
- X
- X#define Ctrl(c) ((c)&037)
- X
- Xextern char **environ;
- Xextern errno;
- Xextern sys_nerr;
- Xextern char *sys_errlist[];
- Xextern char *index(), *rindex(), *malloc(), *getenv(), *MakeTermcap();
- Xextern char *getlogin(), *ttyname();
- Xstatic void AttacherFinit(), Finit(), SigHup(), SigChld();
- Xstatic char *Filename(), **SaveArgs(), *GetTtyName();
- X
- Xstatic char PtyName[32], TtyName[32];
- Xstatic char *ShellProg;
- Xstatic char *ShellArgs[2];
- Xstatic char inbuf[IOSIZE];
- Xstatic inlen;
- Xstatic ESCseen;
- Xstatic GotSignal;
- Xstatic char DefaultShell[] = "/bin/sh";
- Xstatic char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin";
- Xstatic char PtyProto[] = "/dev/ptyXY";
- Xstatic char TtyProto[] = "/dev/ttyXY";
- Xstatic int TtyMode = 0622;
- Xstatic char SockPath[512];
- Xstatic char SockDir[] = ".rmgr";
- Xstatic char *SockNamePtr, *SockName;
- Xstatic ServerSocket;
- Xstatic char *NewEnv[MAXARGS];
- Xstatic char Esc = Ctrl('a');
- Xstatic char *home;
- Xstatic HasWindow;
- Xstatic utmp, utmpf;
- Xstatic char UtmpName[] = "/etc/utmp";
- Xstatic char *LoginName;
- Xstatic char HostName[MAXSTR];
- Xstatic Detached;
- Xstatic AttacherPid; /* Non-Zero in child if we have an attacher */
- Xstatic DevTty;
- Xstatic char EventStr[]="%c%cA";
- Xstatic char CommNames[MAXLINE];
- Xstatic int VoluntaryDetach = 0;
- X
- Xstruct mode {
- X struct sgttyb m_ttyb;
- X struct tchars m_tchars;
- X struct ltchars m_ltchars;
- X int m_ldisc;
- X int m_lmode;
- X} OldMode, NewMode;
- X
- Xstatic struct win *curr, *other;
- Xstatic CurrNum, OtherNum;
- Xstatic struct win *wtab[MAXWIN];
- X
- Xmain (ac, av) char **av; {
- X register n, len;
- X register struct win **pp, *p;
- X char *ap;
- X static InitMenu();
- X int s, r, w, x = 0;
- X int rflag = 0;
- X struct timeval tv;
- X time_t now;
- X char buf[IOSIZE], *myname = (ac == 0) ? "rmgr" : av[0];
- X struct stat st;
- X char *winname="";
- X
- X while (ac > 0) {
- X ap = *++av;
- X if (--ac > 0 && *ap == '-') {
- X switch (ap[1]) {
- X case 'r':
- X rflag = 1;
- X if (ap[2]) {
- X SockName = ap+2;
- X if (ac != 1) goto help;
- X } else if (--ac == 1) {
- X SockName = *++av;
- X } else if (ac != 0) goto help;
- X break;
- X case 'n':
- X if (ap[2]) {
- X ap += 2;
- X } else {
- X if (--ac == 0) goto help;
- X ap = *++av;
- X }
- X winname=ap;
- X break;
- X default:
- X help:
- X Msg (0, "Use: %s [-n windowname] [cmd args]\n\
- X or: %s -r [host.tty]", myname, myname);
- X }
- X } else break;
- X }
- X CommNames[0]='}';
- X if ((ShellProg = getenv ("SHELL")) == 0)
- X ShellProg = DefaultShell;
- X ShellArgs[0] = ShellProg;
- X if (ac == 0) {
- X ac = 1;
- X av = ShellArgs;
- X }
- X if ((home = getenv ("HOME")) == 0)
- X Msg (0, "$HOME is undefined.");
- X sprintf (SockPath, "%s/%s", home, SockDir);
- X if (stat (SockPath, &st) == -1) {
- X if (errno == ENOENT) {
- X if (mkdir (SockPath, 0700) == -1)
- X Msg (errno, "Cannot make directory %s", SockPath);
- X (void) chown (SockPath, getuid (), getgid ());
- X } else Msg (errno, "Cannot get status of %s", SockPath);
- X } else {
- X if ((st.st_mode & S_IFMT) != S_IFDIR)
- X Msg (0, "%s is not a directory.", SockPath);
- X if ((st.st_mode & 0777) != 0700)
- X Msg (0, "Directory %s must have mode 700.", SockPath);
- X if (st.st_uid != getuid ())
- X Msg (0, "You are not the owner of %s.", SockPath);
- X }
- X (void) gethostname (HostName, MAXSTR);
- X HostName[MAXSTR-1] = '\0';
- X if (ap = index (HostName, '.'))
- X *ap = '\0';
- X strcat (SockPath, "/");
- X SockNamePtr = SockPath + strlen (SockPath);
- X if ((DevTty = open ("/dev/tty", O_RDWR|O_NDELAY)) == -1)
- X Msg (errno, "/dev/tty");
- X if (rflag) {
- X Attach (MSG_ATTACH);
- X Attacher ();
- X /*NOTREACHED*/
- X }
- X if (GetSockName ()) {
- X s = MakeClientSocket (1);
- X SendCreateMsg (s, ac, av, winname);
- X close (s);
- X exit (0);
- X }
- X switch (fork ()) {
- X case -1:
- X Msg (errno, "fork");
- X /*NOTREACHED*/
- X case 0:
- X break;
- X default:
- X Attacher ();
- X /*NOTREACHED*/
- X }
- X AttacherPid = getppid ();
- X ServerSocket = s = MakeServerSocket ();
- X InitTerm ();
- X InitMenu ();
- X MakeNewEnv ();
- X GetTTY (0, &OldMode);
- X InitUtmp ();
- X signal (SIGHUP, SigHup);
- X signal (SIGINT, Finit);
- X signal (SIGQUIT, Finit);
- X signal (SIGTERM, Finit);
- X signal (SIGTTIN, SIG_IGN);
- X signal (SIGTTOU, SIG_IGN);
- X if ((n = MakeWindow (*av, av, winname, (char *)0)) == -1) {
- X SetTTY (0, &OldMode);
- X FinitTerm ();
- X Kill (AttacherPid, SIGHUP);
- X exit (1);
- X }
- X SetCurrWindow (n);
- X HasWindow = 1;
- X SetMode (&OldMode, &NewMode);
- X SetTTY (0, &NewMode);
- X signal (SIGCHLD, SigChld);
- X tv.tv_usec = 0;
- X while (1) {
- X r = 0;
- X w = 0;
- X if (inlen && curr->wpid>=0)
- X w |= 1 << curr->ptyfd;
- X else
- X r |= 1 << 0;
- X for (pp = wtab; pp < wtab+MAXWIN; ++pp) {
- X if (!(p = *pp))
- X continue;
- X if (p->wpid >=0)
- X r |= 1 << p->ptyfd;
- X }
- X r |= 1 << s;
- X (void) fflush (stdout);
- X if (GotSignal) {
- X SigHandler ();
- X continue;
- X }
- X if (select (32, &r, &w, &x, (struct timeval *)0) == -1) {
- X if (errno == EINTR)
- X continue;
- X HasWindow = 0;
- X Msg (errno, "select");
- X /*NOTREACHED*/
- X }
- X if (GotSignal) {
- X SigHandler ();
- X continue;
- X }
- X if (r & 1 << s) {
- X ReceiveMsg (s);
- X }
- X if (r & 1 << 0) {
- X if (ESCseen) {
- X inbuf[0] = Esc;
- X inlen = read (0, inbuf+1, IOSIZE-1) + 1;
- X ESCseen = 0;
- X } else {
- X inlen = read (0, inbuf, IOSIZE);
- X }
- X if (inlen > 0)
- X inlen = ProcessInput (inbuf, inlen);
- X if (inlen > 0)
- X continue;
- X }
- X if (GotSignal) {
- X SigHandler ();
- X continue;
- X }
- X if (curr && w & 1 << curr->ptyfd && inlen > 0) {
- X if ((len = write (curr->ptyfd, inbuf, inlen)) > 0) {
- X inlen -= len;
- X bcopy (inbuf+len, inbuf, inlen);
- X }
- X }
- X if (GotSignal) {
- X SigHandler ();
- X continue;
- X }
- X for (n=0; n<MAXWIN; n++) {
- X if (!(p = wtab[n]))
- X continue;
- X if (r & 1 << p->ptyfd) {
- X if ((len = read (p->ptyfd, buf, IOSIZE)) == -1) {
- X if (errno == EWOULDBLOCK)
- X len = 0;
- X }
- X if (len > 0)
- X WriteString (n, buf, len);
- X }
- X }
- X if (GotSignal)
- X SigHandler ();
- X }
- X /*NOTREACHED*/
- X}
- X
- Xstatic InitTerm() {
- X register char *s;
- X
- X if ((s = getenv("TERM")) == 0)
- X Msg(0, "No TERM in environment.");
- X if (strcmp(s,"mgr"))
- X Msg(0, "Only runs on mgr terminals.");
- X
- X m_setup(M_FLUSH);
- X m_push(P_DEFAULT|P_POSITION);
- X m_dupkey(Esc);
- X}
- X
- Xstatic FinitTerm() {
- X m_nomenu2(); m_nomenu();
- X m_clearmenu(1); m_clearmenu(2);
- X m_clearevent(ACTIVATE); m_clearevent(RESHAPE); m_clearevent(DESTROY);
- X m_popall();
- X}
- X
- Xstatic WriteString(n, buf, len) int n, len; char *buf; {
- X register int i, j;
- X register struct win *p;
- X
- X p=wtab[n];
- X
- X if (!Detached) {
- X m_selectwin(n);
- X write(fileno(m_termout), buf, len);
- X } else
- X p->win_ok=0; /* Screen no longer matches reality... */
- X
- X i=SCRBUFSIZE - (p->outptr - p->outbuf);
- X if (i>=len) {
- X bcopy(buf,p->outptr,len);
- X if (i==len) {
- X p->outptr=p->outbuf;
- X p->outful=1;
- X } else
- X p->outptr+=len;
- X } else {
- X j=len-i;
- X bcopy(buf,p->outptr,i);
- X bcopy(&buf[i],p->outbuf,j);
- X p->outptr=p->outbuf+j;
- X p->outful=1;
- X }
- X}
- X
- Xstatic SigHandler () {
- X while (GotSignal) {
- X GotSignal = 0;
- X DoWait ();
- X }
- X}
- X
- Xstatic void SigChld () {
- X GotSignal = 1;
- X}
- X
- Xstatic void SigHup () {
- X Detach (0);
- X}
- X
- Xstatic DoWait () {
- X register pid;
- X register int n;
- X register struct win **pp;
- X union wait wstat;
- X
- X while ((pid = wait3 (&wstat, WNOHANG|WUNTRACED, NULL)) > 0) {
- X for (n = 0; n<MAXWIN; n++) {
- X if (wtab[n] && pid == wtab[n]->wpid) {
- X if (WIFSTOPPED (wstat)) {
- X (void) killpg (getpgrp (wtab[n]->wpid), SIGCONT);
- X } else
- X KillWindow(n);
- X }
- X }
- X }
- X for (n=0; n<MAXWIN; n++)
- X if (wtab[n] && wtab[n]->wpid >=0)
- X break;
- X if (n == MAXWIN)
- X Finit();
- X}
- X
- Xstatic KillWindow (n) int n; {
- X if (Detached || n!=CurrNum || !n) {
- X WriteString(n,"[window shut down]",18);
- X wtab[n]->wpid = -1; /* Shut it down, but don't close */
- X if (!n)
- X FreeWindow (n); /* Don't ever close window 0, but free it */
- X } else {
- X CurrNum = 0;
- X curr = 0;
- X FreeWindow (n);
- X }
- X}
- X
- Xstatic void Finit () {
- X register int n;
- X register struct win *p, **pp;
- X
- X for (n=0; n<MAXWIN; n++) {
- X if (wtab[n])
- X FreeWindow(n);
- X }
- X SetTTY (0, &OldMode);
- X FinitTerm ();
- X printf ("\r[rmgr is terminating]\033c\n");
- X Kill (AttacherPid, SIGHUP);
- X exit (0);
- X}
- X
- Xstatic linemode(onoff) int onoff; {
- X struct sgttyb buff;
- X gtty(0,&buff);
- X if (onoff)
- X buff.sg_flags &= ~CBREAK;
- X else
- X buff.sg_flags |= CBREAK;
- X stty(0,&buff);
- X}
- X
- Xstatic ProcessInput (buf, len) char *buf; {
- X register n, k;
- X register char *s, *p, *q;
- X register struct win **pp;
- X
- X for (s = p = buf; len > 0; len--, s++) {
- X if (*s == Esc) {
- X if (len > 1) {
- X len--; s++;
- X if (*s == Esc) {
- X *p++ = Esc;
- X } else { /* Process event or menu string */
- X if (*s != ' ') {
- X n=(*s++)-'!';
- X len--;
- X if (!len) { /* Make sure to get 3rd char */
- X while(!read(0,s,1));
- X len++;
- X }
- X p=buf;
- X switch (*s) { /* Event Strings */
- X case 'A':
- X SetCurrWindow(n);
- X break;
- X case 'D':
- X FreeWindow(n);
- X break;
- X case 'R':
- X SizeWindow(n);
- X break;
- X case 'c': /* Menu Strings */
- X if ((n=MakeWindow((char *)0, (char *)0,
- X "", (char *)0)) != -1)
- X SetCurrWindow(n);
- X break;
- X case 'd':
- X VoluntaryDetach=1;
- X Detach(0);
- X break;
- X case 'f':
- X SwitchWindow(n);
- X break;
- X case 'k':
- X KillWindow(n);
- X break;
- X case 'n':
- X if ((n=MakeWindow(ShellProg, ShellArgs,
- X "", (char *)0)) != -1)
- X SetCurrWindow(n);
- X break;
- X case 'q':
- X Finit();
- X break;
- X case 's':
- X VoluntaryDetach=1;
- X Detach(1);
- X break;
- X }
- X }
- X }
- X } else ESCseen = 1;
- X } else *p++ = *s;
- X }
- X return p - buf;
- X}
- X
- Xstatic SwitchWindow(n) {
- X if (wtab[n]) {
- X SetCurrWindow(n);
- X m_setmode(M_ACTIVATE);
- X }
- X}
- X
- Xstatic SetCurrWindow (n) {
- X CurrNum = n;
- X curr = wtab[n];
- X m_selectwin(n);
- X if (curr->wpid < 0)
- X m_setmode(M_NOINPUT); /* Dead window, disallow input */
- X}
- X
- Xstatic SizeWindow (n) int n; {
- X struct winsize wbuf;
- X char buf[32];
- X
- X m_selectwin(n);
- X m_getinfo(G_WINSIZE);
- X linemode(1);
- X read(0,buf,31);
- X linemode(0);
- X buf[31]='\0';
- X sscanf(buf,"%*c %d %d",&(wtab[n]->cols),&(wtab[n]->rows));
- X#ifdef TIOCSWINSZ
- X wbuf.ws_row = wtab[n]->rows;
- X wbuf.ws_col = wtab[n]->cols;
- X ioctl (wtab[n]->ptyfd, TIOCSWINSZ, &wbuf);
- X#endif
- X}
- X
- Xstatic FreeWindow (n) register int n; {
- X register i;
- X register struct win *wp;
- X
- X wp=wtab[n];
- X if (wp) {
- X RemoveUtmp (wp->slot);
- X (void) chmod (wp->tty, 0666);
- X (void) chown (wp->tty, 0, 0);
- X close (wp->ptyfd);
- X free (wp);
- X wtab[n]=0;
- X }
- X if (n) {
- X m_selectwin(n);
- X m_clearevent(DESTROY); /* Avoid redundant calling of FreeWindow */
- X m_destroywin(n);
- X }
- X CollectNames();
- X sleep(1);
- X UpdateMenu(n);
- X}
- X
- Xstatic CollectNames() { /* Collect command names for second menu */
- X register struct win **wp;
- X register int n;
- X char buf[8];
- X
- X CommNames[1]='\0';
- X for (wp=wtab; wp<wtab+MAXWIN; wp++)
- X if (*wp) {
- X strcat(CommNames,(*wp)->cmd);
- X strcat(CommNames,"}");
- X }
- X
- X buf[0]=Esc;
- X buf[1]='!';
- X buf[2]='f';
- X buf[3]='}';
- X buf[4]='\0';
- X for (n=0;n<MAXWIN;n++)
- X if (wtab[n]) {
- X buf[1]=n+'!';
- X strcat(CommNames,buf);
- X }
- X}
- X
- Xstatic char *MenuNames[]={"MGR Windows =>", "", "-=-=-=-=-=-=-",
- X "Shell Window","Other Window","Kill Window","Suspend","Detach","Quit"};
- Xstatic char MenuNull='\0';
- Xstatic char MenuActs[24];
- Xstatic char MenuLabs[8]="ncksdq";
- Xstatic struct menu_entry MainMenu[9];
- X
- Xstatic InitMenu() {
- X register int i;
- X register char *ptr;
- X
- X ptr=MenuActs;
- X for (i=3;i<9;i++) {
- X MainMenu[i].action=ptr;
- X *ptr++=Esc;
- X *ptr++='!';
- X *ptr++=MenuLabs[i-3];
- X *ptr++='\0';
- X }
- X for (i=0;i<3;i++)
- X MainMenu[i].action=(&MenuNull);
- X
- X for (i=0;i<9;i++)
- X MainMenu[i].value=MenuNames[i];
- X}
- X
- Xstatic MakeMenu(n) int n; {
- X MenuActs[9]=n+'!';
- X MainMenu[1].value=wtab[n]->cmd;
- X menu_load(1,9,MainMenu);
- X m_loadmenu(2,CommNames);
- X m_linkmenu(1,0,2,MF_SNIP);
- X m_selectmenu2(1);
- X}
- X
- Xstatic UpdateMenu(n) int n; {
- X register int i;
- X
- X for (i=0; i<MAXWIN; i++)
- X if (wtab[i] && i!=n) {
- X m_selectwin(i);
- X m_loadmenu(2,CommNames);
- X }
- X}
- X
- Xstatic Parse (buf, args) char *buf, **args; {
- X register char *p = buf, **ap = args;
- X register delim, argc = 0;
- X
- X argc = 0;
- X for (;;) {
- X while (*p && (*p == ' ' || *p == '\t')) ++p;
- X if (*p == '\0' || *p == '#')
- X return argc;
- X if (argc > MAXARGS-1)
- X Msg (0, "Too many tokens.");
- X delim = 0;
- X if (*p == '"' || *p == '\'') {
- X delim = *p; *p = '\0'; ++p;
- X }
- X ++argc;
- X *ap = p; ++ap;
- X while (*p && !(delim ? *p == delim : (*p == ' ' || *p == '\t')))
- X ++p;
- X if (*p == '\0') {
- X if (delim)
- X Msg (0, "Missing quote.");
- X else
- X return argc;
- X }
- X *p++ = '\0';
- X }
- X}
- X
- Xstatic char TermBuf[MAXLINE];
- X
- Xstatic MakeWindow (prog, args, name, dir)
- X char *prog, *name, **args, *dir; {
- X register struct win *p;
- X register char **cp;
- X register n, f;
- X int tf;
- X int mypid;
- X char ebuf[16];
- X char ibuf[MY_MAXLINE];
- X char *av[MAXARGS];
- X char *ptr,*index();
- X
- X if ((f = OpenPTY ()) == -1) {
- X Msg (0, "No more PTYs.");
- X return -1;
- X }
- X (void) fcntl (f, F_SETFL, FNDELAY);
- X if ((p = (struct win *)malloc (sizeof (struct win))) == 0) {
- X Msg (0, "Out of memory.");
- X return -1;
- X }
- X p->outful=0;
- X p->outptr=p->outbuf;
- X
- X m_ttyset();
- X if (!wtab[0]) {
- X n=0;
- X } else {
- X m_resetflags(CBREAK);
- X m_newwin(0,0,50,50);
- X read(0, TermBuf, MAXLINE);
- X TermBuf[MAXLINE-1]='\0';
- X n = atoi(&TermBuf[2]);
- X }
- X m_selectwin(n);
- X m_dupkey(Esc);
- X m_sizeall(n*5,n*5,80,24);
- X strcpy(TermBuf,"TERMCAP=");
- X m_getinfo(G_TERMCAP);
- X read(0, &TermBuf[6], MAXLINE);
- X TermBuf[MAXLINE-1]='\0';
- X m_setflags(CBREAK);
- X TermBuf[6]='P';
- X TermBuf[7]='=';
- X ptr=index(TermBuf,'\n');
- X *ptr='\0';
- X m_clear();
- X sprintf(ebuf,EventStr,Esc,n+'!');
- X m_setevent(ACTIVATE,ebuf);
- X ebuf[2]='D';
- X m_setevent(DESTROY,ebuf);
- X ebuf[2]='R';
- X m_setevent(RESHAPE,ebuf);
- X m_ttyreset();
- X wtab[n]=p;
- X
- X p->ptyfd = f;
- X
- X if (!prog) {
- X int argc;
- X
- X SetTTY(0, &OldMode);
- X printf("Enter command and arguments: ");
- X fflush(stdout);
- X ptr=gets(ibuf);
- X SetTTY(0, &NewMode);
- X if (!ptr || ((argc = Parse(ibuf, av)) == 0)) {
- X KillWindow(n);
- X return;
- X }
- X if (strcmp(av[0],"-n") == 0) {
- X name=av[1];
- X args=(&av[2]);
- X } else
- X args=av;
- X prog=args[0];
- X }
- X
- X strncpy (p->cmd, *name ? name : Filename (args[0]), MAXSTR-1);
- X p->cmd[MAXSTR-1] = '\0';
- X
- X CollectNames();
- X MakeMenu(n);
- X UpdateMenu(n);
- X strncpy (p->tty, TtyName, MAXSTR-1);
- X (void) chown (TtyName, getuid (), getgid ());
- X (void) chmod (TtyName, TtyMode);
- X p->slot = SetUtmp (TtyName);
- X p->rows=24;
- X p->cols=80;
- X switch (p->wpid = fork ()) {
- X case -1:
- X Msg (errno, "fork");
- X free ((char *)p);
- X return -1;
- X case 0:
- X signal (SIGHUP, SIG_DFL);
- X signal (SIGINT, SIG_DFL);
- X signal (SIGQUIT, SIG_DFL);
- X signal (SIGTERM, SIG_DFL);
- X signal (SIGTTIN, SIG_DFL);
- X signal (SIGTTOU, SIG_DFL);
- X setuid (getuid ());
- X setgid (getgid ());
- X if (dir && chdir (dir) == -1) {
- X SendErrorMsg ("Cannot chdir to %s: %s", dir, sys_errlist[errno]);
- X exit (1);
- X }
- X mypid = getpid ();
- X ioctl (DevTty, TIOCNOTTY, (char *)0);
- X if ((tf = open (TtyName, O_RDWR)) == -1) {
- X SendErrorMsg ("Cannot open %s: %s", TtyName, sys_errlist[errno]);
- X exit (1);
- X }
- X (void) dup2 (tf, 0);
- X (void) dup2 (tf, 1);
- X (void) dup2 (tf, 2);
- X for (f = getdtablesize () - 1; f > 2; f--)
- X close (f);
- X ioctl (0, TIOCSPGRP, &mypid);
- X (void) setpgrp (0, mypid);
- X SetTTY (0, &OldMode);
- X#ifdef TIOCSWINSZ
- X {
- X struct winsize wbuf;
- X wbuf.ws_row = p->rows;
- X wbuf.ws_col=p->cols;
- X ioctl (0, TIOCSWINSZ, &wbuf);
- X }
- X#endif
- X NewEnv[2] = TermBuf;
- X sprintf (ebuf, "WINDOW=%d", n);
- X NewEnv[3] = ebuf;
- X execvpe (prog, args, NewEnv);
- X SendErrorMsg ("Cannot exec %s: %s", prog, sys_errlist[errno]);
- X exit (1);
- X }
- X return n;
- X}
- X
- Xstatic execvpe (prog, args, env) char *prog, **args, **env; {
- X register char *path, *p;
- X char buf[1024];
- X char *shargs[MAXARGS+1];
- X register i, eaccess = 0;
- X
- X if (prog[0] == '/')
- X path = "";
- X else if ((path = getenv ("PATH")) == 0)
- X path = DefaultPath;
- X do {
- X p = buf;
- X while (*path && *path != ':')
- X *p++ = *path++;
- X if (p > buf)
- X *p++ = '/';
- X strcpy (p, prog);
- X if (*path)
- X ++path;
- X execve (buf, args, env);
- X switch (errno) {
- X case ENOEXEC:
- X shargs[0] = DefaultShell;
- X shargs[1] = buf;
- X for (i = 1; shargs[i+1] = args[i]; ++i)
- X ;
- X execve (DefaultShell, shargs, env);
- X return;
- X case EACCES:
- X eaccess = 1;
- X break;
- X case ENOMEM: case E2BIG: case ETXTBSY:
- X return;
- X }
- X } while (*path);
- X if (eaccess)
- X errno = EACCES;
- X}
- X
- Xstatic OpenPTY () {
- X register char *p, *l, *d;
- X register i, f, tf;
- X
- X strcpy (PtyName, PtyProto);
- X strcpy (TtyName, TtyProto);
- X for (p = PtyName, i = 0; *p != 'X'; ++p, ++i) ;
- X for (l = "qpr"; *p = *l; ++l) {
- X for (d = "0123456789abcdef"; p[1] = *d; ++d) {
- X if ((f = open (PtyName, O_RDWR)) != -1) {
- X TtyName[i] = p[0];
- X TtyName[i+1] = p[1];
- X if ((tf = open (TtyName, O_RDWR)) != -1) {
- X close (tf);
- X return f;
- X }
- X close (f);
- X }
- X }
- X }
- X return -1;
- X}
- X
- Xstatic SetTTY (fd, mp) struct mode *mp; {
- X ioctl (fd, TIOCSETP, &mp->m_ttyb);
- X ioctl (fd, TIOCSETC, &mp->m_tchars);
- X ioctl (fd, TIOCSLTC, &mp->m_ltchars);
- X ioctl (fd, TIOCLSET, &mp->m_lmode);
- X ioctl (fd, TIOCSETD, &mp->m_ldisc);
- X}
- X
- Xstatic GetTTY (fd, mp) struct mode *mp; {
- X ioctl (fd, TIOCGETP, &mp->m_ttyb);
- X ioctl (fd, TIOCGETC, &mp->m_tchars);
- X ioctl (fd, TIOCGLTC, &mp->m_ltchars);
- X ioctl (fd, TIOCLGET, &mp->m_lmode);
- X ioctl (fd, TIOCGETD, &mp->m_ldisc);
- X}
- X
- Xstatic SetMode (op, np) struct mode *op, *np; {
- X *np = *op;
- X np->m_ttyb.sg_flags &= ~(CRMOD|ECHO);
- X np->m_ttyb.sg_flags |= CBREAK;
- X np->m_tchars.t_intrc = -1;
- X np->m_tchars.t_quitc = -1;
- X np->m_ltchars.t_suspc = -1;
- X np->m_ltchars.t_dsuspc = -1;
- X np->m_ltchars.t_flushc = -1;
- X np->m_ltchars.t_lnextc = -1;
- X}
- X
- Xstatic char *GetTtyName () {
- X register char *p;
- X register n;
- X
- X for (p = 0, n = 0; n <= 2 && !(p = ttyname (n)); n++)
- X ;
- X if (!p || *p == '\0')
- X Msg (0, "rmgr must run on a tty.");
- X return p;
- X}
- X
- Xstatic Attach (how) {
- X register s, lasts, found = 0;
- X register DIR *dirp;
- X register struct direct *dp;
- X struct msg m;
- X char last[MAXNAMLEN+1];
- X
- X if (SockName) {
- X if ((lasts = MakeClientSocket (0)) == -1)
- X if (how == MSG_CONT)
- X Msg (0,
- X "This session has already been continued from elsewhere.");
- X else
- X Msg (0, "There is no session to be resumed from %s.", SockName);
- X } else {
- X if ((dirp = opendir (SockPath)) == NULL)
- X Msg (0, "Cannot open %s", SockPath);
- X while ((dp = readdir (dirp)) != NULL) {
- X SockName = dp->d_name;
- X if (SockName[0] == '.')
- X continue;
- X if ((s = MakeClientSocket (0)) != -1) {
- X if (found == 0) {
- X strcpy (last, SockName);
- X lasts = s;
- X } else {
- X if (found == 1) {
- X printf ("There are detached sessions on:\n");
- X printf (" %s\n", last);
- X close (lasts);
- X }
- X printf (" %s\n", SockName);
- X close (s);
- X }
- X found++;
- X }
- X }
- X if (found == 0)
- X Msg (0, "There is no session to be resumed.");
- X if (found > 1)
- X Msg (0, "Type \"rmgr -r host.tty\" to resume one of them.");
- X closedir (dirp);
- X strcpy (SockNamePtr, last);
- X SockName = SockNamePtr;
- X }
- X m.type = how;
- X strcpy (m.m.attach.tty, GetTtyName ());
- X m.m.attach.apid = getpid ();
- X if (write (lasts, (char *)&m, sizeof (m)) != sizeof (m))
- X Msg (errno, "write");
- X}
- X
- Xstatic void AttacherFinit () {
- X exit (0);
- X}
- X
- Xstatic void ReAttach () {
- X Attach (MSG_CONT);
- X}
- X
- Xstatic Attacher () {
- X signal (SIGHUP, AttacherFinit);
- X signal (SIGCONT, ReAttach);
- X while (1)
- X pause ();
- X}
- X
- Xstatic Detach (suspend) {
- X register struct win **pp;
- X register int i;
- X
- X if (Detached)
- X return;
- X signal (SIGHUP, SIG_IGN);
- X if (VoluntaryDetach) { /* Can't save state if line dropped */
- X for (i=MAXWIN-1;i>0;i--) {
- X if (wtab[i]) {
- X m_selectwin(i);
- X m_nomenu2();
- X m_push(P_EVENT);
- X }
- X }
- X m_selectwin(0);
- X m_nomenu2(); m_nomenu();
- X m_push(P_ALL);
- X m_setmode(M_ACTIVATE);
- X }
- X SetTTY (0, &OldMode);
- X if (suspend) {
- X Kill (AttacherPid, SIGTSTP);
- X for (pp=wtab; pp < wtab+MAXWIN; ++pp)
- X if (*pp) (*pp)->win_ok=1;
- X } else {
- X for (pp=wtab; pp < wtab+MAXWIN; ++pp)
- X if (*pp) RemoveUtmp ((*pp)->slot);
- X printf ("\n[detached]\n");
- X Kill (AttacherPid, SIGHUP);
- X AttacherPid = 0;
- X }
- X close (0);
- X close (1);
- X close (2);
- X ioctl (DevTty, TIOCNOTTY, (char *)0);
- X Detached = 1;
- X do {
- X ReceiveMsg (ServerSocket);
- X } while (Detached);
- X if (!suspend) {
- X for (pp = wtab; pp < wtab+MAXWIN; ++pp)
- X if (*pp) (*pp)->slot = SetUtmp ((*pp)->tty);
- X }
- X signal (SIGHUP, SigHup);
- X}
- X
- Xstatic Kill (pid, sig) {
- X if (pid != 0)
- X (void) kill (pid, sig);
- X}
- X
- Xstatic GetSockName () {
- X register client;
- X static char buf[2*MAXSTR];
- X
- X if ((SockName = getenv ("STY")) != 0 && *SockName != '\0') {
- X client = 1;
- X setuid (getuid ());
- X setgid (getgid ());
- X } else {
- X sprintf (buf, "%s.%s", HostName, Filename (GetTtyName ()));
- X SockName = buf;
- X client = 0;
- X }
- X return client;
- X}
- X
- Xstatic MakeServerSocket () {
- X register s;
- X struct sockaddr_un a;
- X char *p;
- X
- X if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1)
- X Msg (errno, "socket");
- X a.sun_family = AF_UNIX;
- X strcpy (SockNamePtr, SockName);
- X strcpy (a.sun_path, SockPath);
- X if (connect (s, (struct sockaddr *)&a, strlen (SockPath)+2) != -1) {
- X p = Filename (SockPath);
- X Msg (0, "You already have a session running on %s.\n\
- XIf it has been detached, try \"rmgr -r\".", p);
- X /*NOTREACHED*/
- X }
- X (void) unlink (SockPath);
- X if (bind (s, (struct sockaddr *)&a, strlen (SockPath)+2) == -1)
- X Msg (errno, "bind");
- X (void) chown (SockPath, getuid (), getgid ());
- X if (listen (s, 5) == -1)
- X Msg (errno, "listen");
- X return s;
- X}
- X
- Xstatic MakeClientSocket (err) {
- X register s;
- X struct sockaddr_un a;
- X
- X if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1)
- X Msg (errno, "socket");
- X a.sun_family = AF_UNIX;
- X strcpy (SockNamePtr, SockName);
- X strcpy (a.sun_path, SockPath);
- X if (connect (s, (struct sockaddr *)&a, strlen (SockPath)+2) == -1) {
- X if (err) {
- X Msg (errno, "connect: %s", SockPath);
- X } else {
- X close (s);
- X return -1;
- X }
- X }
- X return s;
- X}
- X
- Xstatic SendCreateMsg (s, ac, av, name) char **av, *name; {
- X struct msg m;
- X register char *p;
- X register len, n;
- X
- X m.type = MSG_CREATE;
- X p = m.m.create.line;
- X for (n = 0; ac > 0 && n < MAXARGS-1; ++av, --ac, ++n) {
- X len = strlen (*av) + 1;
- X if (p + len >= m.m.create.line+MY_MAXLINE)
- X break;
- X strcpy (p, *av);
- X p += len;
- X }
- X m.m.create.nargs = n;
- X if (name)
- X strcpy(m.m.create.name,name);
- X else
- X m.m.create.name[0]='\0';
- X if (getwd (m.m.create.dir) == 0)
- X Msg (0, "%s", m.m.create.dir);
- X if (write (s, (char *)&m, sizeof (m)) != sizeof (m))
- X Msg (errno, "write");
- X}
- X
- X/*VARARGS1*/
- Xstatic SendErrorMsg (fmt, p1, p2, p3, p4, p5, p6) char *fmt; {
- X register s;
- X struct msg m;
- X
- X s = MakeClientSocket (1);
- X m.type = MSG_ERROR;
- X sprintf (m.m.message, fmt, p1, p2, p3, p4, p5, p6);
- X (void) write (s, (char *)&m, sizeof (m));
- X close (s);
- X sleep (2);
- X}
- X
- Xstatic char m_rbuf[MAXLINE];
- X
- Xstatic char *m_read() {
- X register char *ptr; char *index();
- X register int i;
- X
- X i=read(0,m_rbuf,MAXLINE-1);
- X m_rbuf[i]='\0';
- X ptr=index(m_rbuf,Esc);
- X if (!ptr)
- X ptr=m_rbuf;
- X else
- X ptr++;
- X return(ptr);
- X}
- X
- Xstatic ReplayWindow(p) struct win *p; {
- X register int n;
- X
- X n=p->outptr-p->outbuf;
- X if (p->outful) /* Replay last screen of data */
- X write(1,p->outptr,SCRBUFSIZE-n);
- X write(1,p->outbuf,n);
- X}
- X
- Xstatic RestoreWindows(mt) int mt; {
- X register int i, j=0;
- X struct window_data wd;
- X register char *ptr;
- X register struct win *p;
- X char buf[8];
- X int n, nw;
- X int oldset=1;
- X
- X if (mt != MSG_CONT) { /* Restore after a detach, not suspend */
- X linemode(1);
- X for (i=MAXWIN-1; i>=0; i--) {
- X m_selectwin(i);
- X m_getinfo(G_ID);
- X ptr=m_read();
- X sscanf(ptr,"%d %d",&n, &nw);
- X if (wtab[i]) {
- X p=wtab[i];
- X if (n!=i) { /* That one didn't exist, remake it... */
- X oldset=0; /* Looks like the old context is gone. */
- X m_newwin(j,j,50,50);
- X ptr=m_read();
- X n=atoi(ptr);
- X if (!n)
- X Msg(0, "Error restoring window.");
- X m_selectwin(n);
- X }
- X if (!oldset) {
- X m_size(p->cols,p->rows);
- X m_dupkey(Esc);
- X sprintf(buf,EventStr,Esc,n+'!');
- X m_setevent(ACTIVATE,buf);
- X buf[2]='D';
- X m_setevent(DESTROY,buf);
- X buf[2]='R';
- X m_setevent(RESHAPE,buf);
- X MakeMenu(n);
- X ReplayWindow(p);
- X } else if (VoluntaryDetach) {
- X m_pop();
- X } else ReplayWindow(p); /* Redraw for hangup */
- X } else if (i) { /* Gee, a window we didn't create. Byebye. */
- X oldset=0; /* Again, we must have lost the old stuff */
- X m_destroywin(i);
- X }
- X }
- X linemode(0);
- X } else {
- X for (i=0;i<MAXWIN;i++) {
- X p=wtab[i];
- X if (p) {
- X m_selectwin(i);
- X m_pop();
- X m_selectmenu2(1);
- X if (!p->win_ok)
- X ReplayWindow(p);
- X }
- X }
- X }
- X VoluntaryDetach=0;
- X}
- X
- Xstatic ReceiveMsg (s) {
- X register ns;
- X struct sockaddr_un a;
- X int left, len = sizeof (a);
- X struct msg m;
- X char *p;
- X
- X if ((ns = accept (s, (struct sockaddr *)&a, &len)) == -1) {
- X Msg (errno, "accept");
- X return;
- X }
- X p = (char *)&m;
- X left = sizeof (m);
- X while (left > 0 && (len = read (ns, p, left)) > 0) {
- X p += len;
- X left -= len;
- X }
- X close (ns);
- X if (len == -1)
- X Msg (errno, "read");
- X if (left > 0)
- X return;
- X switch (m.type) {
- X case MSG_CREATE:
- X if (!Detached)
- X ExecCreate (&m);
- X break;
- X case MSG_CONT:
- X if (m.m.attach.apid != AttacherPid || !Detached)
- X break; /* Intruder Alert */
- X /*FALLTHROUGH*/
- X case MSG_ATTACH:
- X if (Detached) {
- X if (kill (m.m.attach.apid, 0) == 0 &&
- X open (m.m.attach.tty, O_RDWR) == 0) {
- X (void) dup (0);
- X (void) dup (0);
- X AttacherPid = m.m.attach.apid;
- X Detached = 0;
- X GetTTY (0, &OldMode);
- X SetMode (&OldMode, &NewMode);
- X SetTTY (0, &NewMode);
- X RestoreWindows(m.type);
- X SwitchWindow(CurrNum);
- X }
- X } else {
- X Kill (m.m.attach.apid, SIGHUP);
- X Msg (0, "Not detached.");
- X }
- X break;
- X case MSG_ERROR:
- X Msg (0, "%s", m.m.message);
- X break;
- X default:
- X Msg (0, "Invalid message (type %d).", m.type);
- X }
- X}
- X
- Xstatic ExecCreate (mp) struct msg *mp; {
- X char *args[MAXARGS];
- X register n;
- X register char **pp = args, *p = mp->m.create.line;
- X
- X for (n = mp->m.create.nargs; n > 0; --n) {
- X *pp++ = p;
- X p += strlen (p) + 1;
- X }
- X *pp = 0;
- X if ((n = MakeWindow (mp->m.create.line, args, mp->m.create.name,
- X mp->m.create.dir)) != -1)
- X SwitchWindow (n);
- X}
- X
- Xstatic char **SaveArgs (argc, argv) register argc; register char **argv; {
- X register char **ap, **pp;
- X
- X if ((pp = ap = (char **)malloc ((argc+1) * sizeof (char **))) == 0)
- X Msg (0, "Out of memory.");
- X while (argc--) {
- X if ((*pp = malloc (strlen (*argv)+1)) == 0)
- X Msg (0, "Out of memory.");
- X strcpy (*pp, *argv);
- X ++pp; ++argv;
- X }
- X *pp = 0;
- X return ap;
- X}
- X
- Xstatic MakeNewEnv () {
- X register char **op, **np = NewEnv;
- X static char buf[MAXSTR];
- X
- X if (strlen (SockName) > MAXSTR-5)
- X SockName = "?";
- X sprintf (buf, "STY=%s", SockName);
- X *np++ = buf;
- X *np++ = "TERM=mgr";
- X np += 2;
- X for (op = environ; *op; ++op) {
- X if (np == NewEnv + MAXARGS - 1)
- X break;
- X if (!IsSymbol (*op, "TERM") && !IsSymbol (*op, "TERMCAP")
- X && !IsSymbol (*op, "STY"))
- X *np++ = *op;
- X }
- X *np = 0;
- X}
- X
- Xstatic IsSymbol (e, s) register char *e, *s; {
- X register char *p;
- X register n;
- X
- X for (p = e; *p && *p != '='; ++p) ;
- X if (*p) {
- X *p = '\0';
- X n = strcmp (e, s);
- X *p = '=';
- X return n == 0;
- X }
- X return 0;
- X}
- X
- X/*VARARGS2*/
- XMsg (err, fmt, p1, p2, p3, p4, p5, p6) char *fmt; {
- X char buf[1024];
- X register char *p = buf;
- X
- X if (Detached)
- X return;
- X sprintf (p, fmt, p1, p2, p3, p4, p5, p6);
- X if (err) {
- X p += strlen (p);
- X if (err > 0 && err < sys_nerr)
- X sprintf (p, ": %s", sys_errlist[err]);
- X else
- X sprintf (p, ": Error %d", err);
- X }
- X printf ("%s\r\n", buf);
- X if (!HasWindow) {
- X Kill (AttacherPid, SIGHUP);
- X exit (1);
- X }
- X}
- X
- Xstatic char *Filename (s) char *s; {
- X register char *p;
- X
- X p = s + strlen (s) - 1;
- X while (p >= s && *p != '/') --p;
- X return ++p;
- X}
- X
- Xstatic IsNum (s, base) register char *s; register base; {
- X for (base += '0'; *s; ++s)
- X if (*s < '0' || *s > base)
- X return 0;
- X return 1;
- X}
- X
- Xstatic InitUtmp () {
- X struct passwd *p;
- X
- X if ((utmpf = open (UtmpName, O_WRONLY)) == -1) {
- X if (errno != EACCES)
- X Msg (errno, UtmpName);
- X return;
- X }
- X if ((LoginName = getlogin ()) == 0 || LoginName[0] == '\0') {
- X if ((p = getpwuid (getuid ())) == 0)
- X return;
- X LoginName = p->pw_name;
- X }
- X utmp = 1;
- X}
- X
- Xstatic SetUtmp (name) char *name; {
- X register char *p;
- X register struct ttyent *tp;
- X register slot = 1;
- X struct utmp u;
- X
- X if (!utmp)
- X return 0;
- X if (p = rindex (name, '/'))
- X ++p;
- X else p = name;
- X setttyent ();
- X while ((tp = getttyent ()) != NULL && strcmp (p, tp->ty_name) != 0)
- X ++slot;
- X if (tp == NULL)
- X return 0;
- X strncpy (u.ut_line, p, 8);
- X strncpy (u.ut_name, LoginName, 8);
- X u.ut_host[0] = '\0';
- X time (&u.ut_time);
- X (void) lseek (utmpf, (long)(slot * sizeof (u)), 0);
- X (void) write (utmpf, (char *)&u, sizeof (u));
- X return slot;
- X}
- X
- Xstatic RemoveUtmp (slot) {
- X struct utmp u;
- X
- X if (slot) {
- X bzero ((char *)&u, sizeof (u));
- X (void) lseek (utmpf, (long)(slot * sizeof (u)), 0);
- X (void) write (utmpf, (char *)&u, sizeof (u));
- X }
- X}
- X
- X#ifndef GETTTYENT
- X
- Xstatic setttyent () {
- X struct stat s;
- X register f;
- X register char *p, *ep;
- X
- X if (ttnext) {
- X ttnext = tt;
- X return;
- X }
- X if ((f = open (ttys, O_RDONLY)) == -1 || fstat (f, &s) == -1)
- X Msg (errno, ttys);
- X if ((tt = malloc (s.st_size + 1)) == 0)
- X Msg (0, "Out of memory.");
- X if (read (f, tt, s.st_size) != s.st_size)
- X Msg (errno, ttys);
- X close (f);
- X for (p = tt, ep = p + s.st_size; p < ep; ++p)
- X if (*p == '\n') *p = '\0';
- X *p = '\0';
- X ttnext = tt;
- X}
- X
- Xstatic struct ttyent *getttyent () {
- X static struct ttyent t;
- X
- X if (*ttnext == '\0')
- X return NULL;
- X t.ty_name = ttnext + 2;
- X ttnext += strlen (ttnext) + 1;
- X return &t;
- X}
- X
- X#endif
- X
- X#ifndef USEBCOPY
- Xbcopy (s1, s2, len) register char *s1, *s2; register len; {
- X if (s1 < s2 && s2 < s1 + len) {
- X s1 += len; s2 += len;
- X while (len-- > 0) {
- X *--s2 = *--s1;
- X }
- X } else {
- X while (len-- > 0) {
- X *s2++ = *s1++;
- X }
- X }
- X}
- X#endif
- ________This_Is_The_END________
- if test `wc -c < rmgr.c` -ne 32339; then
- echo 'shar: rmgr.c was damaged during transit (should have been 32339 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - rmgr.h'
- if test -f rmgr.h; then echo 'shar: not overwriting rmgr.h'; else
- sed 's/^X//' << '________This_Is_The_END________' > rmgr.h
- X/* Copyright (c) 1987,1988 Oliver Laumann, Technical University of Berlin.
- X * Not derived from licensed software.
- X *
- X * Permission is granted to freely use, copy, modify, and redistribute
- X * this software, provided that no attempt is made to gain profit from it,
- X * the author is not construed to be liable for any results of using the
- X * software, alterations are clearly marked as such, and this notice is
- X * not modified.
- X */
- X
- X#include <mgr/term.h>
- X
- X#define MAXSTR 128
- X#define MAXARGS 64
- X
- X#define IOSIZE 256
- X#define SCRBUFSIZE 2048 /* About 1 screenful of characters */
- X
- Xstruct win {
- X int wpid;
- X int ptyfd;
- X int rows;
- X int cols;
- X char cmd[MAXSTR];
- X char tty[MAXSTR];
- X int slot;
- X int win_ok;
- X int outful;
- X char outbuf[SCRBUFSIZE];
- X char *outptr;
- X};
- X
- X#define MY_MAXLINE 1024
- X
- X#define MSG_CREATE 0
- X#define MSG_ERROR 1
- X#define MSG_ATTACH 2
- X#define MSG_CONT 3
- X
- Xstruct msg {
- X int type;
- X union {
- X struct {
- X int nargs;
- X char line[MY_MAXLINE];
- X char dir[1024];
- X char name[MAXSTR];
- X } create;
- X struct {
- X int apid;
- X char tty[1024];
- X } attach;
- X char message[MY_MAXLINE];
- X } m;
- X};
- ________This_Is_The_END________
- if test `wc -c < rmgr.h` -ne 1169; then
- echo 'shar: rmgr.h was damaged during transit (should have been 1169 bytes)'
- fi
- fi ; : end of overwriting check
- exit 0
- --
- -- Howard Chu @ University of Michigan
- one million data bits stored on a chip, one million bits per chip
- if one of those data bits happens to flip,
- one million data bits stored on the chip...
-