ocker@lan.informatik.tu-muenchen.dbp.de (Wolfgang Ocker) (01/25/89)
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 3)."
# Contents: screen.c
# Wrapped by weo@recco on Fri Jan 6 14:32:22 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'screen.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'screen.c'\"
else
echo shar: Extracting \"'screen.c'\" \(37756 characters\)
sed "s/^X//" >'screen.c' <<'END_OF_FILE'
X/* Copyright (c) 1987, 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 * Adapted to OS-9/68000 by reccoware systems, Wolfgang Ocker, Puchheim 1988
X */
X
Xstatic char ScreenVersion[] = "screen 1.1i 1-Jul-87 (OSK/88)";
X
X#include <stdio.h>
X#ifdef OSK
X#include <sgstat.h>
X#else
X#include <sgtty.h>
X#endif
X#include <signal.h>
X#include <errno.h>
X#include <ctype.h>
X#ifndef OSK
X#include <utmp.h>
X#endif
X#include <pwd.h>
X#ifdef OSK
X#include <types.h>
X#include <time.h>
X#include <stat.h>
X#include <modes.h>
X#else
X#include <nlist.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/wait.h>
X#include <sys/socket.h>
X#include <sys/un.h>
X#include <sys/stat.h>
X#include <sys/file.h>
X#endif
X#include "screen.h"
X
X#ifndef OSK
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#endif
X
X#define MAXWIN 10
X#define MAXARGS 64
X#define MAXLINE 1024
X#define MSGWAIT 5
X
X#define Ctrl(c) ((c)&037)
X
Xextern char *blank, Term[], **environ;
Xextern rows, cols;
Xextern status;
Xextern time_t TimeDisplayed;
Xextern char AnsiVersion[];
Xextern short ospeed;
Xextern flowctl;
Xextern errno;
Xextern sys_nerr;
Xextern char *sys_errlist[];
Xextern char *index(), *rindex(), *malloc(), *getenv(), *MakeTermcap();
Xextern char *getlogin(), *ttyname();
Xstatic Finit(), SigChld();
Xstatic char *MakeBellMsg(), *Filename(), **SaveArgs();
X
Xstatic char PtyName[32], TtyName[32];
Xstatic char *ShellProg;
Xstatic char *ShellArgs[2];
Xstatic char inbuf[IOSIZE];
Xstatic inlen;
Xstatic ESCseen;
Xstatic GotSignal;
X#ifdef OSK
Xstatic char DefaultShell[] = "sh";
Xstatic char DefaultPath[] = "/h0/CMDS:/h0/USR/CMDS";
Xstatic char PtyProto[] = "/pty%02d";
Xstatic char TtyProto[] = "/tty%02d";
X#else
Xstatic char DefaultShell[] = "/bin/sh";
Xstatic char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin";
Xstatic char PtyProto[] = "/dev/ptyXY";
Xstatic char TtyProto[] = "/dev/ttyXY";
X#endif
Xstatic char SockPath[512];
Xstatic char SockDir[] = ".screen";
Xstatic char *SockName;
Xstatic char *NewEnv[MAXARGS];
Xstatic char Esc = Ctrl('a');
Xstatic char MetaEsc = 'a';
Xstatic char *home;
Xstatic HasWindow;
Xstatic utmp, utmpf;
Xstatic char UtmpName[] = "/etc/utmp";
Xstatic char *LoginName;
Xstatic char *BellString = "Bell in window %";
Xstatic mflag, nflag, fflag;
Xstatic char HostName[MAXSTR];
X#ifdef LOADAV
X static char KmemName[] = "/dev/kmem";
X static char UnixName[] = "/vmunix";
X static char AvenrunSym[] = "_avenrun";
X static struct nlist nl[2];
X static avenrun, kmemf;
X#endif
X
X#ifdef OSK
Xstruct _sgs OldMode, NewMode;
X
Xint innum;
X#define min min_
X
Xmin(a, b)
X int a, b;
X{
X if (a < b)
X return(a);
X else
X return(b);
X}
X#else
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#endif
X
Xstatic struct win *curr, *other;
Xstatic CurrNum, OtherNum;
Xstatic struct win *wtab[MAXWIN];
X
X#define MSG_CREATE 0
X#define MSG_ERROR 1
X
Xstruct msg {
X int type;
X union {
X struct {
X int aflag;
X int nargs;
X char line[MAXLINE];
X char dir[1024];
X } create;
X char message[MAXLINE];
X } m;
X};
X
X#define KEY_IGNORE 0
X#define KEY_HARDCOPY 1
X#define KEY_SUSPEND 2
X#define KEY_SHELL 3
X#define KEY_NEXT 4
X#define KEY_PREV 5
X#define KEY_KILL 6
X#define KEY_REDISPLAY 7
X#define KEY_WINDOWS 8
X#define KEY_VERSION 9
X#define KEY_OTHER 10
X#define KEY_0 11
X#define KEY_1 12
X#define KEY_2 13
X#define KEY_3 14
X#define KEY_4 15
X#define KEY_5 16
X#define KEY_6 17
X#define KEY_7 18
X#define KEY_8 19
X#define KEY_9 20
X#define KEY_XON 21
X#define KEY_XOFF 22
X#define KEY_INFO 23
X#define KEY_TERMCAP 24
X#define KEY_QUIT 25
X#define KEY_CREATE 26
X
Xstruct key {
X int type;
X char **args;
X} ktab[256];
X
Xchar *KeyNames[] = {
X "hardcopy", "suspend", "shell", "next", "prev", "kill", "redisplay",
X "windows", "version", "other", "select0", "select1", "select2", "select3",
X "select4", "select5", "select6", "select7", "select8", "select9",
X "xon", "xoff", "info", "termcap", "quit",
X 0
X};
X
X#ifdef OSK
X#define bcopy(a,b,c) memcpy(b,a,c)
X#endif
X
Xmain (ac, av) char **av; {
X register n, len;
X register struct win **pp, *p;
X char *ap;
X int s, r, w, x = 0;
X int aflag = 0;
X#ifndef OSK
X struct timeval tv;
X#endif
X time_t now;
X char buf[IOSIZE], *myname = (ac == 0) ? "screen" : av[0];
X char rc[256];
X
X#ifdef OSK
X if ((home = getenv("HOME")) == NULL)
X exit(_errmsg(1, "HOME undefined\n"));
X#endif
X
X while (ac > 0) {
X ap = *++av;
X if (--ac > 0 && *ap == '-') {
X switch (ap[1]) {
X case 'c': /* Compatibility with older versions. */
X break;
X case 'a':
X aflag = 1;
X break;
X case 'm':
X mflag = 1;
X break;
X case 'n':
X nflag = 1;
X break;
X case 'f':
X fflag = 1;
X break;
X case 'e':
X if (ap[2]) {
X ap += 2;
X } else {
X if (--ac == 0) goto help;
X ap = *++av;
X }
X if (strlen (ap) != 2)
X Msg (0, "Two characters are required with -e option.");
X Esc = ap[0];
X MetaEsc = ap[1];
X break;
X default:
X help:
X Msg (0, "Use: %s [-a] [-f] [-n] [-exy] [cmd args]", myname);
X }
X } else break;
X }
X if (nflag && fflag)
X Msg (0, "-f and -n are conflicting options.");
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
X if (GetSockName ()) {
X /* Client */
X s = MakeClientSocket ();
X SendCreateMsg (s, ac, av, aflag);
X close (s);
X exit (0);
X }
X
X (void) gethostname (HostName, MAXSTR);
X HostName[MAXSTR-1] = '\0';
X if (ap = index (HostName, '.'))
X *ap = '\0';
X s = MakeServerSocket ();
X
X InitTerm ();
X if (fflag)
X flowctl = 1;
X else if (nflag)
X flowctl = 0;
X MakeNewEnv ();
X
X GetTTY (0, &OldMode);
X#ifdef OSK
X ospeed = (short)OldMode._sgs_baud;
X#else
X ospeed = (short)OldMode.m_ttyb.sg_ospeed;
X#endif
X InitUtmp ();
X#ifdef LOADAV
X InitKmem ();
X#endif
X signal (SIGHUP, Finit);
X signal (SIGINT, Finit);
X signal (SIGQUIT, Finit);
X#ifndef OSK
X signal (SIGTERM, Finit);
X#endif
X InitKeytab ();
X#ifdef OSK
X sprintf (rc, "%s/.screenrc", home);
X#else
X sprintf (rc, "%.*s/.screenrc", 245, home);
X#endif
X ReadRc (rc);
X if ((n = MakeWindow (*av, av, aflag, 0, (char *)0)) == -1) {
X SetTTY (0, &OldMode);
X FinitTerm ();
X exit (1);
X }
X SetCurrWindow (n);
X HasWindow = 1;
X SetMode (&OldMode, &NewMode);
X SetTTY (0, &NewMode);
X#ifndef OSK
X signal (SIGCHLD, SigChld);
X tv.tv_usec = 0;
X#endif
X while (1) {
X if (status) {
X time (&now);
X#ifndef OSK
X if (now - TimeDisplayed < MSGWAIT) {
X tv.tv_sec = MSGWAIT - (now - TimeDisplayed);
X } else RemoveStatus (curr);
X#endif
X }
X r = 0;
X w = 0;
X if (inlen)
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 ((*pp)->active && status)
X continue;
X if ((*pp)->outlen > 0)
X continue;
X r |= 1 << (*pp)->ptyfd;
X }
X
X r |= 1 << s;
X
X fflush (stdout);
X#ifdef OSK
X if (select (32, &r, &w, &x) == -1) {
X#define EINTR 3
X#else
X if (select (32, &r, &w, &x, status ? &tv : (struct timeval *)0) == -1) {
X#endif
X if (errno == EINTR)
X continue;
X HasWindow = 0;
X Msg (errno, "select");
X /*NOTREACHED*/
X }
X if (GotSignal && !status) {
X SigHandler ();
X continue;
X }
X if (r & 1 << s) {
X RemoveStatus (curr);
X ReceiveMsg (s);
X }
X
X if (r & 1) {
X RemoveStatus (curr);
X if (ESCseen) {
X inbuf[0] = Esc;
X#ifdef OSK
X innum = _gs_rdy(0);
X inlen = read (0, inbuf+1, min(innum, IOSIZE-1)) + 1;
X#else
X inlen = read (0, inbuf+1, IOSIZE-1) + 1;
X#endif
X ESCseen = 0;
X } else {
X#ifdef OSK
X innum = _gs_rdy(0);
X inlen = read (0, inbuf, min(IOSIZE, innum));
X#else
X inlen = read (0, inbuf, IOSIZE);
X#endif
X }
X if (inlen > 0)
X inlen = ProcessInput (inbuf, inlen);
X if (inlen > 0)
X continue;
X }
X if (GotSignal && !status) {
X SigHandler ();
X continue;
X }
X if (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 && !status) {
X SigHandler ();
X continue;
X }
X for (pp = wtab; pp < wtab+MAXWIN; ++pp) {
X if (!(p = *pp))
X continue;
X if (p->outlen) {
X WriteString (p, p->outbuf, p->outlen);
X } else if (r & 1 << p->ptyfd) {
X#ifdef OSK
X innum = _gs_rdy(p->ptyfd);
X if ((len = read (p->ptyfd, buf, min(innum, IOSIZE))) == -1) {
X#else
X if ((len = read (p->ptyfd, buf, IOSIZE)) == -1) {
X#endif
X if (errno == EWOULDBLOCK)
X len = 0;
X }
X if (len > 0)
X WriteString (p, buf, len);
X }
X if (p->bell) {
X p->bell = 0;
X Msg (0, MakeBellMsg (pp-wtab));
X }
X }
X if (GotSignal && !status)
X SigHandler ();
X }
X /*NOTREACHED*/
X}
X
Xstatic SigHandler () {
X while (GotSignal) {
X GotSignal = 0;
X DoWait ();
X }
X}
X
Xstatic SigChld () {
X GotSignal = 1;
X}
X
X#ifdef OSK
XDoWait () {
X#else
Xstatic DoWait () {
X#endif
X register pid;
X register struct win **pp;
X#ifndef OSK
X union wait wstat;
X#else
X int change;
X#endif
X
X#ifdef OSK
X change = 0;
X for (pp = wtab; pp < wtab+MAXWIN; ++pp) {
X if (*pp && (*pp)->wpid != 0 &&
X ((pid = wait_nw((*pp)->wpid, NULL)) == (*pp)->wpid)) {
X if (*pp == curr)
X curr = 0;
X if (*pp == other)
X other = 0;
X (*pp)->wpid = 0;
X FreeWindow (*pp);
X *pp = 0;
X change = 1;
X }
X }
X#else
X while ((pid = wait3 (&wstat, WNOHANG|WUNTRACED, NULL)) > 0) {
X for (pp = wtab; pp < wtab+MAXWIN; ++pp) {
X if (*pp && pid == (*pp)->wpid) {
X if (WIFSTOPPED (wstat)) {
X kill((*pp)->wpid, SIGCONT);
X } else {
X if (*pp == curr)
X curr = 0;
X if (*pp == other)
X other = 0;
X FreeWindow (*pp);
X *pp = 0;
X }
X }
X }
X }
X#endif
X CheckWindows ();
X#ifdef OSK
X return(change);
X#endif
X}
X
Xstatic CheckWindows () {
X register struct win **pp;
X
X /* If the current window disappeared and the "other" window is still
X * there, switch to the "other" window, else switch to the window
X * with the lowest index.
X * If there current window is still there, but the "other" window
X * vanished, "SetCurrWindow" is called in order to assign a new value
X * to "other".
X * If no window is alive at all, exit.
X */
X if (!curr && other) {
X SwitchWindow (OtherNum);
X return;
X }
X if (curr && !other) {
X SetCurrWindow (CurrNum);
X return;
X }
X for (pp = wtab; pp < wtab+MAXWIN; ++pp) {
X if (*pp) {
X if (!curr)
X SwitchWindow (pp-wtab);
X return;
X }
X }
X Finit ();
X}
X
Xstatic Finit () {
X register struct win *p, **pp;
X
X for (pp = wtab; pp < wtab+MAXWIN; ++pp) {
X if (p = *pp)
X FreeWindow (p);
X }
X SetTTY (0, &OldMode);
X FinitTerm ();
X printf ("[screen is terminating]\n");
X exit (0);
X}
X
Xstatic InitKeytab () {
X register i;
X
X ktab['h'].type = ktab[Ctrl('h')].type = KEY_HARDCOPY;
X ktab['z'].type = ktab[Ctrl('z')].type = KEY_SUSPEND;
X ktab['c'].type = ktab[Ctrl('c')].type = KEY_SHELL;
X ktab[' '].type = ktab[Ctrl(' ')].type =
X ktab['n'].type = ktab[Ctrl('n')].type = KEY_NEXT;
X ktab['-'].type = ktab['p'].type = ktab[Ctrl('p')].type = KEY_PREV;
X ktab['k'].type = ktab[Ctrl('k')].type = KEY_KILL;
X ktab['l'].type = ktab[Ctrl('l')].type = KEY_REDISPLAY;
X ktab['w'].type = ktab[Ctrl('w')].type = KEY_WINDOWS;
X ktab['v'].type = ktab[Ctrl('v')].type = KEY_VERSION;
X ktab['q'].type = ktab[Ctrl('q')].type = KEY_XON;
X ktab['s'].type = ktab[Ctrl('s')].type = KEY_XOFF;
X ktab['t'].type = ktab[Ctrl('t')].type = KEY_INFO;
X ktab['.'].type = KEY_TERMCAP;
X ktab[Ctrl('\\')].type = KEY_QUIT;
X ktab[Esc].type = KEY_OTHER;
X for (i = 0; i <= 9; i++)
X ktab[i+'0'].type = KEY_0+i;
X}
X
Xstatic ProcessInput (buf, len) char *buf; {
X register n, k;
X register char *s, *p;
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 k = ktab[*s].type;
X if (*s == MetaEsc) {
X *p++ = Esc;
X } else if (k >= KEY_0 && k <= KEY_9) {
X p = buf;
X SwitchWindow (k - KEY_0);
X } else switch (ktab[*s].type) {
X case KEY_TERMCAP:
X p = buf;
X WriteFile (0);
X break;
X case KEY_HARDCOPY:
X p = buf;
X WriteFile (1);
X break;
X#ifndef OSK
X case KEY_SUSPEND:
X p = buf;
X SetTTY (0, &OldMode);
X FinitTerm ();
X kill (getpid (), SIGTSTP);
X SetTTY (0, &NewMode);
X Activate (wtab[CurrNum]);
X break;
X#endif
X case KEY_SHELL:
X p = buf;
X if ((n = MakeWindow (ShellProg, ShellArgs,
X 0, 0, (char *)0)) != -1)
X SwitchWindow (n);
X break;
X case KEY_NEXT:
X p = buf;
X if (MoreWindows ())
X SwitchWindow (NextWindow ());
X break;
X case KEY_PREV:
X p = buf;
X if (MoreWindows ())
X SwitchWindow (PreviousWindow ());
X break;
X case KEY_KILL:
X p = buf;
X FreeWindow (wtab[CurrNum]);
X if (other == curr)
X other = 0;
X curr = wtab[CurrNum] = 0;
X CheckWindows ();
X break;
X case KEY_QUIT:
X for (pp = wtab; pp < wtab+MAXWIN; ++pp)
X if (*pp) FreeWindow (*pp);
X Finit ();
X /*NOTREACHED*/
X case KEY_REDISPLAY:
X p = buf;
X Activate (wtab[CurrNum]);
X break;
X case KEY_WINDOWS:
X p = buf;
X ShowWindows ();
X break;
X case KEY_VERSION:
X p = buf;
X Msg (0, "%s %s", ScreenVersion, AnsiVersion);
X break;
X case KEY_INFO:
X p = buf;
X ShowInfo ();
X break;
X case KEY_OTHER:
X p = buf;
X if (MoreWindows ())
X SwitchWindow (OtherNum);
X break;
X case KEY_XON:
X *p++ = Ctrl('q');
X break;
X case KEY_XOFF:
X *p++ = Ctrl('s');
X break;
X case KEY_CREATE:
X p = buf;
X if ((n = MakeWindow (ktab[*s].args[0], ktab[*s].args,
X 0, 0, (char *)0)) != -1)
X SwitchWindow (n);
X break;
X }
X } else ESCseen = 1;
X } else *p++ = *s;
X }
X return p - buf;
X}
X
Xstatic SwitchWindow (n) {
X if (!wtab[n])
X return;
X SetCurrWindow (n);
X Activate (wtab[n]);
X}
X
Xstatic SetCurrWindow (n) {
X /*
X * If we come from another window, this window becomes the
X * "other" window:
X */
X if (curr) {
X curr->active = 0;
X other = curr;
X OtherNum = CurrNum;
X }
X CurrNum = n;
X curr = wtab[n];
X curr->active = 1;
X /*
X * If the "other" window is currently undefined (at program start
X * or because it has died), or if the "other" window is equal to the
X * one just selected, we try to find a new one:
X */
X if (other == 0 || other == curr) {
X OtherNum = NextWindow ();
X other = wtab[OtherNum];
X }
X}
X
Xstatic NextWindow () {
X register struct win **pp;
X
X for (pp = wtab+CurrNum+1; pp != wtab+CurrNum; ++pp) {
X if (pp == wtab+MAXWIN)
X pp = wtab;
X if (*pp)
X break;
X }
X return pp-wtab;
X}
X
Xstatic PreviousWindow () {
X register struct win **pp;
X
X for (pp = wtab+CurrNum-1; pp != wtab+CurrNum; --pp) {
X if (pp < wtab)
X pp = wtab+MAXWIN-1;
X if (*pp)
X break;
X }
X return pp-wtab;
X}
X
Xstatic MoreWindows () {
X register struct win **pp;
X register n;
X
X for (n = 0, pp = wtab; pp < wtab+MAXWIN; ++pp)
X if (*pp) ++n;
X if (n <= 1)
X Msg (0, "No other window.");
X return n > 1;
X}
X
Xstatic FreeWindow (wp) struct win *wp; {
X register i;
X
X RemoveUtmp (wp->slot);
X#ifndef OSK
X (void) chmod (wp->tty, 0666);
X (void) chown (wp->tty, 0, 0);
X#endif
X close (wp->ptyfd);
X
X for (i = 0; i < rows; ++i) {
X free (wp->image[i]);
X free (wp->attr[i]);
X }
X free (wp->image);
X free (wp->attr);
X#ifdef OSK
X if (wp->wpid != 0)
X wait(NULL);
X#endif
X free (wp);
X}
X
Xstatic MakeWindow (prog, args, aflag, StartAt, dir)
X char *prog, **args, *dir; {
X register struct win **pp, *p;
X register char **cp;
X register n, f;
X int tf;
X int mypid;
X char ebuf[10];
X#ifdef OSK
X int savfd0, savfd1, savfd2;
X char pbuf[MAXSTR];
X extern int os9fork();
X#endif
X
X pp = wtab+StartAt;
X do {
X if (*pp == 0)
X break;
X if (++pp == wtab+MAXWIN)
X pp = wtab;
X } while (pp != wtab+StartAt);
X if (*pp) {
X Msg (0, "No more windows.");
X return -1;
X }
X n = pp - wtab;
X if ((f = OpenPTY ()) == -1) {
X Msg (0, "No more PTYs.");
X return -1;
X }
X#ifndef OSK
X fcntl (f, F_SETFL, FNDELAY);
X#endif
X if ((p = *pp = (struct win *)malloc (sizeof (struct win))) == 0) {
Xnomem:
X Msg (0, "Out of memory.");
X return -1;
X }
X if ((p->image = (char **)malloc (rows * sizeof (char *))) == 0)
X goto nomem;
X for (cp = p->image; cp < p->image+rows; ++cp) {
X if ((*cp = malloc (cols)) == 0)
X goto nomem;
X bclear (*cp, cols);
X }
X if ((p->attr = (char **)malloc (rows * sizeof (char *))) == 0)
X goto nomem;
X for (cp = p->attr; cp < p->attr+rows; ++cp) {
X if ((*cp = malloc (cols)) == 0)
X goto nomem;
X bzero (*cp, cols);
X }
X if ((p->tabs = malloc (cols+1)) == 0) /* +1 because 0 <= x <= cols */
X goto nomem;
X ResetScreen (p);
X p->aflag = aflag;
X p->active = 0;
X p->bell = 0;
X p->outlen = 0;
X p->ptyfd = f;
X strncpy (p->cmd, Filename (args[0]), MAXSTR-1);
X p->cmd[MAXSTR-1] = '\0';
X strncpy (p->tty, TtyName, MAXSTR-1);
X#ifndef OSK
X (void) chown (TtyName, getuid (), getgid ());
X (void) chmod (TtyName, 0622);
X#endif
X p->slot = SetUtmp (TtyName);
X
X#ifdef OSK
X#define O_RDWR S_IREAD | S_IWRITE
X
X if ((tf = open (TtyName, O_RDWR)) == -1) {
X SendErrorMsg ("Cannot open %s: %s", TtyName, sys_errlist[errno]);
X return -1;
X }
X savfd0 = dup(0);
X savfd1 = dup(1);
X savfd2 = dup(2);
X dup2 (tf, 0);
X dup2 (tf, 1);
X dup2 (tf, 2);
X
X NewEnv[2] = MakeTermcap (aflag);
X sprintf (ebuf, "WINDOW=%d", n);
X NewEnv[3] = ebuf;
X sprintf(pbuf, "PORT=%s", TtyName);
X NewEnv[4] = pbuf;
X p->wpid = os9exec(os9fork, args[0], args, NewEnv, 0, 0, 0);
X close(0);
X close(1);
X close(2);
X dup(savfd0);
X dup(savfd1);
X dup(savfd2);
X close(savfd0);
X close(savfd1);
X close(savfd2);
X close(tf);
X if (p->wpid == -1) {
X Msg (errno, "Cannot fork");
X free (p);
X return(-1);
X }
X
X#else
X switch (p->wpid = fork ()) {
X case -1:
X Msg (errno, "Cannot fork");
X free (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 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 if ((f = open ("/dev/tty", O_RDWR)) != -1) {
X ioctl (f, TIOCNOTTY, (char *)0);
X close (f);
X }
X if ((tf = open (TtyName, O_RDWR)) == -1) {
X SendErrorMsg ("Cannot open %s: %s", TtyName, sys_errlist[errno]);
X exit (1);
X }
X dup2 (tf, 0);
X dup2 (tf, 1);
X dup2 (tf, 2);
X for (f = getdtablesize () - 1; f > 2; f--)
X close (f);
X ioctl (0, TIOCSPGRP, &mypid);
X setpgrp (0, mypid);
X SetTTY (0, &OldMode);
X NewEnv[2] = MakeTermcap (aflag);
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#endif
X return n;
X}
X
X#ifndef OSK
Xexecvpe (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#endif
X
Xstatic WriteFile (dump) { /* dump==0: create .termcap, dump==1: hardcopy */
X#ifdef OSK
X register i, j, k;
X register char *p;
X register FILE *f;
X char fn[1024];
X int pid, s;
X
X if (dump)
X sprintf (fn, "hardcopy.%d", CurrNum);
X else
X sprintf (fn, "%s/%s/.termcap", home, SockDir);
X if ((f = fopen (fn, "w")) == NULL)
X return;
X if (dump) {
X for (i = 0; i < rows; ++i) {
X p = curr->image[i];
X for (k = cols-1; k >= 0 && p[k] == ' '; --k) ;
X for (j = 0; j <= k; ++j)
X putc (p[j], f);
X putc ('\n', f);
X }
X } else {
X if (p = index (MakeTermcap (curr->aflag), '=')) {
X fputs (++p, f);
X putc ('\n', f);
X }
X }
X fclose (f);
X
X Msg (0, "%s written to \"%s\".", dump ? "Screen image" :
X "Termcap entry", fn);
X#else
X register i, j, k;
X register char *p;
X register FILE *f;
X char fn[1024];
X int pid, s;
X
X if (dump)
X sprintf (fn, "hardcopy.%d", CurrNum);
X else
X sprintf (fn, "%s/%s/.termcap", home, SockDir);
X switch (pid = fork ()) {
X case -1:
X Msg (errno, "fork");
X return;
X case 0:
X setuid (getuid ());
X setgid (getgid ());
X if ((f = fopen (fn, "w")) == NULL)
X exit (1);
X if (dump) {
X for (i = 0; i < rows; ++i) {
X p = curr->image[i];
X for (k = cols-1; k >= 0 && p[k] == ' '; --k) ;
X for (j = 0; j <= k; ++j)
X putc (p[j], f);
X putc ('\n', f);
X }
X } else {
X if (p = index (MakeTermcap (curr->aflag), '=')) {
X fputs (++p, f);
X putc ('\n', f);
X }
X }
X fclose (f);
X exit (0);
X default:
X while ((i = wait (&s)) != pid)
X if (i == -1) return;
X if ((s >> 8) & 0377)
X Msg (0, "Cannot open \"%s\".", fn);
X else
X Msg (0, "%s written to \"%s\".", dump ? "Screen image" :
X "Termcap entry", fn);
X }
X#endif
X}
X
Xstatic ShowWindows () {
X char buf[1024];
X register char *s;
X register struct win **pp, *p;
X
X for (s = buf, pp = wtab; pp < wtab+MAXWIN; ++pp) {
X if ((p = *pp) == 0)
X continue;
X if (s - buf + 5 + strlen (p->cmd) > cols-1)
X break;
X if (s > buf) {
X *s++ = ' '; *s++ = ' ';
X }
X *s++ = pp - wtab + '0';
X if (p == curr)
X *s++ = '*';
X else if (p == other)
X *s++ = '-';
X *s++ = ' ';
X strcpy (s, p->cmd);
X s += strlen (s);
X }
X Msg (0, buf);
X}
X
Xstatic ShowInfo () {
X char buf[1024], *p;
X register struct win *wp = curr;
X struct tm *tp;
X time_t now;
X#ifdef LOADAV
X double av[3];
X#endif
X
X time (&now);
X tp = localtime (&now);
X sprintf (buf, "%2d:%02.2d:%02.2d %s", tp->tm_hour, tp->tm_min, tp->tm_sec,
X HostName);
X#ifdef LOADAV
X if (avenrun && GetAvenrun (av)) {
X p = buf + strlen (buf);
X sprintf (p, " %2.2f %2.2f %2.2f", av[0], av[1], av[2]);
X }
X#endif
X p = buf + strlen (buf);
X sprintf (p, " (%d,%d) %cflow %cins %corg %cwrap %cpad", wp->y, wp->x,
X flowctl ? '+' : '-',
X wp->insert ? '+' : '-', wp->origin ? '+' : '-',
X wp->wrap ? '+' : '-', wp->keypad ? '+' : '-');
X Msg (0, buf);
X}
X
Xstatic OpenPTY () {
X register char *p, *l, *d;
X register i, f, tf;
X#ifdef OSK
X char pty[20], tty[20];
X int mp;
X#endif
X
X#ifdef OSK
X for (i = 0; i < 32; i++) {
X sprintf(pty, PtyProto, i);
X sprintf(tty, TtyProto, i);
X if ((f = open (pty, O_RDWR)) != -1) {
X if ((tf = open (tty, O_RDWR)) != -1) {
X strcpy(TtyName, tty);
X strcpy(PtyName, pty);
X close (tf);
X return f;
X }
X close (f);
X }
X }
X
X#else
X strcpy (PtyName, PtyProto);
X strcpy (TtyName, TtyProto);
X for (p = PtyName, i = 0; *p != 'X'; ++p, ++i) ;
X for (l = "pqr"; *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#endif
X return -1;
X}
X
X#ifdef OSK
Xstatic SetTTY (fd, mp)
X struct _sgs *mp;
X{
X _ss_opt(fd, mp);
X}
Xstatic GetTTY (fd, mp)
X struct _sgs *mp;
X{
X _gs_opt(fd, mp);
X}
X
Xstatic SetMode (op, np)
X struct _sgs *op, *np;
X{
X *np = *op;
X np->_sgs_case = '\0';
X np->_sgs_backsp = '\0';
X np->_sgs_delete = '\0';
X np->_sgs_echo = '\0';
X np->_sgs_alf = '\0';
X np->_sgs_nulls = '\0';
X np->_sgs_pause = '\0';
X np->_sgs_page = '\0';
X np->_sgs_bspch = '\0';
X np->_sgs_dlnch = '\0';
X np->_sgs_eorch = '\0';
X np->_sgs_eofch = '\0';
X np->_sgs_rlnch = '\0';
X np->_sgs_dulnch = '\0';
X np->_sgs_psch = '\0';
X np->_sgs_kbich = '\0';
X np->_sgs_kbach = '\0';
X np->_sgs_bsech = '\0';
X np->_sgs_bellch = '\0';
X np->_sgs_tabcr = '\0';
X if (!flowctl)
X np->_sgs_xon = np->_sgs_xoff = '\0';
X}
X#else
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 if (!flowctl) {
X np->m_tchars.t_startc = -1;
X np->m_tchars.t_stopc = -1;
X }
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#endif
X
Xstatic GetSockName () {
X struct stat s;
X register client;
X register char *p;
X
X if (!mflag && (SockName = getenv ("STY")) != 0 && *SockName != '\0') {
X client = 1;
X#ifndef OSK
X setuid (getuid ());
X setgid (getgid ());
X#endif
X } else {
X if ((p = ttyname (0)) == 0 || (p = ttyname (1)) == 0 ||
X (p = ttyname (2)) == 0 || *p == '\0')
X Msg (0, "screen must run on a tty.");
X SockName = Filename (p);
X client = 0;
X }
X if ((home = getenv ("HOME")) == 0)
X Msg (0, "$HOME is undefined.");
X#ifdef OSK
X sprintf (SockPath, "/pipe/screen.");
X#else
X sprintf (SockPath, "%s/%s", home, SockDir);
X if (stat (SockPath, &s) == -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 ((s.st_mode & S_IFMT) != S_IFDIR)
X Msg (0, "%s is not a directory.", SockPath);
X if ((s.st_mode & 0777) != 0700)
X Msg (0, "Directory %s must have mode 700.", SockPath);
X if (s.st_uid != getuid ())
X Msg (0, "You are not the owner of %s.", SockPath);
X }
X strcat (SockPath, "/");
X#endif
X strcat (SockPath, SockName);
X return client;
X}
X
Xstatic MakeServerSocket () {
X register s;
X#ifndef OSK
X struct sockaddr_un a;
X#endif
X
X (void) unlink (SockPath);
X#ifdef OSK
X if ((s = create(SockPath, S_IREAD+S_IWRITE+S_ISIZE,
X S_IREAD+S_IWRITE+S_IOWRITE,
X sizeof(struct msg)+20)) == -1)
X Msg (errno, "pipe");
X#else
X if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1)
X Msg (errno, "socket");
X a.sun_family = AF_UNIX;
X strcpy (a.sun_path, 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#endif
X return s;
X}
X
Xstatic MakeClientSocket () {
X register s;
X#ifndef OSK
X struct sockaddr_un a;
X#endif
X
X#ifdef OSK
X if ((s = open(SockPath, S_IWRITE)) == -1)
X Msg (errno, "pipe");
X#else
X if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1)
X Msg (errno, "socket");
X a.sun_family = AF_UNIX;
X strcpy (a.sun_path, SockPath);
X if (connect (s, (struct sockaddr *)&a, strlen (SockPath)+2) == -1)
X Msg (errno, "connect: %s", SockPath);
X#endif
X return s;
X}
X
Xstatic SendCreateMsg (s, ac, av, aflag) char **av; {
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+MAXLINE)
X break;
X strcpy (p, *av);
X p += len;
X }
X m.m.create.nargs = n;
X m.m.create.aflag = aflag;
X if (getwd (m.m.create.dir) == 0)
X Msg (0, "%s", m.m.create.dir);
X if (write (s, &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 ();
X m.type = MSG_ERROR;
X sprintf (m.m.message, fmt, p1, p2, p3, p4, p5, p6);
X (void) write (s, &m, sizeof (m));
X close (s);
X sleep (2);
X}
X
Xstatic ReceiveMsg (s) {
X register ns;
X#ifndef OSK
X struct sockaddr_un a;
X int len = sizeof (a);
X#else
X int len;
X#endif
X struct msg m;
X
X#ifdef OSK
X ns = s;
X#else
X
X if ((ns = accept (s, (struct sockaddr *)&a, &len)) == -1) {
X Msg (errno, "accept");
X return;
X }
X#endif
X if ((len = read (ns, &m, sizeof (m))) != sizeof (m)) {
X if (len == -1)
X Msg (errno, "read");
X else
X Msg (0, "Short message (%d bytes)", len);
X#ifndef OSK
X close (ns);
X#endif
X return;
X }
X switch (m.type) {
X case MSG_CREATE:
X ExecCreate (&m);
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#ifndef OSK
X close (ns);
X#endif
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.aflag, 0,
X mp->m.create.dir)) != -1)
X SwitchWindow (n);
X}
X
Xstatic ReadRc (fn) char *fn; {
X FILE *f;
X register char *p, **pp, **ap;
X register argc, num, c;
X char buf[256];
X char *args[MAXARGS];
X int key;
X
X#ifdef OSK
X#define R_OK S_IREAD
X#endif
X
X ap = args;
X if (access (fn, R_OK) == -1)
X return;
X if ((f = fopen (fn, "r")) == NULL)
X return;
X while (fgets (buf, 256, f) != NULL) {
X if (p = rindex (buf, '\n'))
X *p = '\0';
X if ((argc = Parse (fn, buf, ap)) == 0)
X continue;
X if (strcmp (ap[0], "escape") == 0) {
X p = ap[1];
X if (argc < 2 || strlen (p) != 2)
X Msg (0, "%s: two characters required after escape.", fn);
X Esc = *p++;
X MetaEsc = *p;
X } else if (strcmp (ap[0], "chdir") == 0) {
X p = argc < 2 ? home : ap[1];
X if (chdir (p) == -1)
X Msg (errno, "%s", p);
X } else if (strcmp (ap[0], "bell") == 0) {
X if (argc != 2) {
X Msg (0, "%s: bell: one argument required.", fn);
X } else {
X if ((BellString = malloc (strlen (ap[1]) + 1)) == 0)
X Msg (0, "Out of memory.");
X strcpy (BellString, ap[1]);
X }
X } else if (strcmp (ap[0], "screen") == 0) {
X num = 0;
X if (argc > 1 && IsNum (ap[1], 10)) {
X num = atoi (ap[1]);
X if (num < 0 || num > MAXWIN-1)
X Msg (0, "%s: illegal screen number %d.", fn, num);
X --argc; ++ap;
X }
X if (argc < 2) {
X ap[1] = ShellProg; argc = 2;
X }
X ap[argc] = 0;
X (void) MakeWindow (ap[1], ap+1, 0, num, (char *)0);
X } else if (strcmp (ap[0], "bind") == 0) {
X p = ap[1];
X if (argc < 2 || *p == '\0')
X Msg (0, "%s: key expected after bind.", fn);
X if (p[1] == '\0') {
X key = *p;
X } else if (p[0] == '^' && p[1] != '\0' && p[2] == '\0') {
X c = p[1];
X if (isupper (c))
X p[1] = tolower (c);
X key = Ctrl(c);
X } else if (IsNum (p, 7)) {
X (void) sscanf (p, "%o", &key);
X } else {
X Msg (0,
X "%s: bind: character, ^x, or octal number expected.", fn);
X }
X if (argc < 3) {
X ktab[key].type = 0;
X } else {
X for (pp = KeyNames; *pp; ++pp)
X if (strcmp (ap[2], *pp) == 0) break;
X if (*pp) {
X ktab[key].type = pp-KeyNames+1;
X } else {
X ktab[key].type = KEY_CREATE;
X ktab[key].args = SaveArgs (argc-2, ap+2);
X }
X }
X } else Msg (0, "%s: unknown keyword \"%s\".", fn, ap[0]);
X }
X fclose (f);
X}
X
Xstatic Parse (fn, buf, args) char *fn, *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, "%s: too many tokens.", fn);
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, "%s: Missing quote.", fn);
X else
X return argc;
X }
X *p++ = '\0';
X }
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#ifdef OSK
X static char buf2[MAXSTR];
X#endif
X
X if (strlen (SockName) > MAXSTR-5)
X SockName = "?";
X sprintf (buf, "STY=%s", SockName);
X#ifdef OSK
X sprintf(buf2, "PORT=???\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
X#endif
X *np++ = buf;
X *np++ = Term;
X#ifdef OSK
X *np++ = buf2;
X#endif
X np += 2;
X for (op = environ; *op; ++op) {
X if (np == NewEnv + MAXARGS - 1)
X break;
X#ifdef OSK
X if (!IsSymbol (*op, "TERM") && !IsSymbol (*op, "TERMCAP")
X && !IsSymbol (*op, "STY") && !IsSymbol (*op, "PORT"))
X#else
X if (!IsSymbol (*op, "TERM") && !IsSymbol (*op, "TERMCAP")
X && !IsSymbol (*op, "STY"))
X#endif
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 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 if (HasWindow) {
X MakeStatus (buf, curr);
X } else {
X printf ("%s\r\n", buf);
X exit (1);
X }
X}
X
Xbclear (p, n) char *p; {
X bcopy (blank, p, n);
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 char *MakeBellMsg (n) {
X static char buf[MAXSTR];
X register char *p = buf, *s = BellString;
X
X for (s = BellString; *s && p < buf+MAXSTR-1; s++)
X *p++ = (*s == '%') ? n + '0' : *s;
X *p = '\0';
X return buf;
X}
X
Xstatic InitUtmp () {
X#ifndef OSK
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#endif
X}
X
Xstatic SetUtmp (name) char *name; {
X#ifndef OSK
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, &u, sizeof (u));
X return slot;
X#endif
X}
X
Xstatic RemoveUtmp (slot) {
X#ifndef OSK
X struct utmp u;
X
X if (slot) {
X bzero (&u, sizeof (u));
X (void) lseek (utmpf, (long)(slot * sizeof (u)), 0);
X (void) write (utmpf, &u, sizeof (u));
X }
X#endif
X}
X
X#ifndef OSK
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#endif
X
X#ifdef LOADAV
X
Xstatic InitKmem () {
X if ((kmemf = open (KmemName, O_RDONLY)) == -1)
X return;
X nl[0].n_name = AvenrunSym;
X nlist (UnixName, nl);
X if (nl[0].n_type == 0 || nl[0].n_value == 0)
X return;
X avenrun = 1;
X}
X
Xstatic GetAvenrun (av) double av[]; {
X if (lseek (kmemf, nl[0].n_value, 0) == -1)
X return 0;
X if (read (kmemf, av, 3*sizeof (double)) != 3*sizeof (double))
X return 0;
X return 1;
X}
X
X#endif
END_OF_FILE
if test 37756 -ne `wc -c <'screen.c'`; then
echo shar: \"'screen.c'\" unpacked with wrong size!
fi
# end of 'screen.c'
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
| Wolfgang Ocker | ocker@lan.informatik.tu-muenchen.dbp.de |
| Lochhauserstr. 35a | pyramid!tmpmbx!recco!weo (home) |
| D-8039 Puchheim | Technische Universitaet Muenchen |
| Voice: +49 89 80 77 02 | Huh, What? Where am I? |