home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1991
- * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
- * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
- * Copyright (c) 1987 Oliver Laumann
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 1, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program (see the file COPYING); if not, write to the
- * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Noteworthy contributors to screen's design and implementation:
- * Wayne Davison (davison@borland.com)
- * Patrick Wolfe (pat@kai.com, kailand!pat)
- * Bart Schaefer (schaefer@cse.ogi.edu)
- * Nathan Glasser (nathan@brokaw.lcs.mit.edu)
- * Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
- * Howard Chu (hyc@hanauma.jpl.nasa.gov)
- * Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
- * Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
- * Marc Boucher (marc@CAM.ORG)
- *
- ****************************************************************
- */
-
- #ifndef lint
- static char rcs_id[] = "$Id: screen.c,v 1.2 92/02/03 02:28:05 jnweiger Exp $ FAU";
- #endif
-
-
- #include <sys/param.h>
- /* #include <signal.h> */
- #include <ctype.h>
- #include <pwd.h>
- #include <fcntl.h>
- #ifdef sgi
- # include <sys/sysmacros.h>
- #endif /* sgi */
- #if !defined(sun) && !defined(B43) && !defined(ISC)
- # include <time.h>
- #endif
- /*
- * Gee!! We should reverse that #if!
- */
- #if defined(sun) || defined(_AIX) || defined(sysV68) || defined(MIPS) || defined(GOULD_NP1) || defined(B43) || defined(ISC) || defined(apollo) || defined(BSDI) || defined(sgi)
- # include <sys/time.h>
- #endif
- #if defined(M_XENIX) || defined(M_UNIX)
- #include <sys/select.h> /* for timeval */
- #endif
- #include <sys/types.h>
- #ifdef ISC
- # include <sys/bsdtypes.h>
- #endif
- #if !defined(sysV68) && !defined(M_XENIX)
- # include <sys/wait.h>
- #endif
- #include <sys/stat.h>
- #ifndef sgi
- # include <sys/file.h>
- #endif /* sgi */
- #ifndef sun
- # include <sys/ioctl.h>
- #endif /* sun */
-
- #include <signal.h>
- #if defined(SVR4) && !defined(NSIG)
- #define NSIG 32
- #endif
-
- #include "config.h"
-
- #ifdef SHADOWPW
- # include <shadow.h>
- #endif /* SHADOWPW */
-
- #ifdef SVR4
- # include <sys/stropts.h>
- #endif
-
- #ifdef SYSV
- # include <sys/utsname.h>
- #endif
-
- #if defined(_SEQUENT_)
- /* for the FD.. stuff */
- # include <sys/select.h>
- #endif
-
- #if defined(sequent) || defined(SVR4)
- # include <sys/resource.h>
- #endif /* sequent || SVR4 */
-
- #ifdef ISC
- # include <sys/tty.h>
- # include <sys/sioctl.h>
- # include <sys/pty.h>
- #endif
-
- #include "screen.h"
-
- #include "patchlevel.h"
-
- #if defined(xelos) || defined(sysV68) || defined(M_XENIX)
- struct passwd *getpwuid __P((uid_t));
- struct passwd *getpwnam __P((char *));
- #endif
-
- #ifdef USEVARARGS
- # if defined(__STDC__)
- # include <stdarg.h>
- # else
- # include <varargs.h>
- # endif
- #endif
-
- #ifdef DEBUG
- FILE *dfp;
- #endif
-
-
- #ifdef COPY_PASTE
- extern char *copybuffer; /* def in mark.c jw. */
- extern copylen;
- #endif /* COPY_PASTE */
-
- extern char *blank, *null, Term[], screenterm[], **environ, *Termcap;
- int force_vt = 1, assume_LP = 0;
- extern int in_ovl;
- extern int ovl_blockfore;
- extern void (*ovl_process)();
- extern int help_page;
- extern int screenwidth, screenheight;
- extern char display_tty[];
- extern int default_width, default_height;
- extern int Z0width, Z1width;
- extern int ISO2022;
- extern int status, HS;
- extern char *Z0, *WS, *LastMsg;
- extern time_t TimeDisplayed;
- int BellDisplayed;
- int VBellWait, MsgWait, MsgMinWait;
-
- /* tputs uses that: jw */
- extern short ospeed;
-
- extern int flow, default_flow, wrap, visual_bell, default_monitor;
- extern int errno;
- extern sys_nerr;
- extern char *sys_errlist[];
- extern char mark_key_tab[];
-
- #if defined(TIOCSWINSZ) || defined(TIOCGWINSZ)
- extern struct winsize glwz;
- #endif
-
- static char *MakeWinMsg __P((char *, int));
- static void MakeNewEnv __P((void));
- static int Attach __P((int));
- static void Attacher __P((void));
- static void SigHandler __P((void));
- static sig_t AttacherSigInt __P(SIGPROTOARG);
- static sig_t SigChld __P(SIGPROTOARG);
- static sig_t SigInt __P(SIGPROTOARG);
- static sig_t CoreDump __P((int));
- static void DoWait __P((void));
- static sig_t Finit __P((int));
- static void InitKeytab __P((void));
- static void SetForeWindow __P((int));
- static int NextWindow __P((void));
- static int PreviousWindow __P((void));
- static int MoreWindows __P((void));
- static void FreeWindow __P((struct win *));
- static void execvpe __P((char *, char **, char **));
- static void LogToggle __P((void));
- static void ShowWindows __P((void));
- static void ShowTime __P((void));
- static void ShowInfo __P((void));
- static int OpenPTY __P((void));
- #ifdef PASSWORD
- static void trysend __P((int, struct msg *, char *));
- #endif
- #if defined(SIGWINCH) && defined(TIOCGWINSZ)
- static sig_t SigAttWinch __P(SIGPROTOARG);
- #endif
- static void fgtty __P((void));
- static void freetty __P((void));
- static void brktty __P((void));
-
- #if defined(LOCK)
- static sig_t DoLock __P(SIGPROTOARG);
- static void LockTerminal __P((void));
- #endif
-
- #ifdef COPY_PASTE
- static pastelen;
- static char *pastebuffer;
- #endif
- #ifdef PASSWORD
- extern char Password[];
- #endif
-
- static struct passwd *ppp;
-
- /* used for opening a new pty-pair: */
- static char PtyName[32], TtyName[32];
-
- /* used for the attacher's tty: */
- static char *attach_tty;
-
- char *ShellProg;
- char *ShellArgs[2];
- static char inbuf[MAXWIN][IOSIZE];
- static inlen[MAXWIN];
- static inbuf_ct;
- static ESCseen;
- static GotSignal;
-
- static char DefaultShell[] = "/bin/sh";
- static char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin";
-
- #ifdef hpux
- char PtyProto[] = "/dev/ptym/ptyXY";
- char TtyProto[] = "/dev/pty/ttyXY";
- #else
- # if !(defined(sequent) || defined(_SEQUENT_) || defined(SVR4))
- static char PtyProto[] = "/dev/ptyXY";
- static char TtyProto[] = "/dev/ttyXY";
- # endif
- #endif /* hpux */
- int TtyMode = 0622;
- #ifdef SOCKDIR
- char *SockDir = SOCKDIR;
- #else
- char *SockDir = ".iscreen";
- #endif
- extern char SockPath[], *SockNamePtr, *SockName;
- int ServerSocket = -1;
- static char **NewEnv;
-
- char *RcFileName = NULL;
- char Esc = Ctrl('a');
- char MetaEsc = 'a';
- char *home;
-
- int HasWindow;
- char *LoginName;
- char *BellString;
- char *VisualBellString;
- char *ActivityString;
- char *BufferFile;
- char *PowDetachString;
- int auto_detach = 1;
- int iflag, rflag, dflag, lsflag, quietflag, wipeflag;
- int adaptflag, loginflag = -1, allflag;
- static intrc, startc, stopc;
- char HostName[MAXSTR];
- int Detached, Suspended;
- int DeadlyMsg = 1;
- int AttacherPid; /* Non-Zero in child if we have an attacher */
- int MasterPid;
- int real_uid, real_gid, eff_uid, eff_gid;
- int default_histheight;
- int default_startup;
- int slowpaste;
-
- #if defined(BSDJOBS) && !(defined(POSIX) || defined(SYSV))
- int DevTty = -1;
- #endif
-
- #ifdef NETHACK
- int nethackflag = 0;
- #endif
-
- struct mode OldMode, NewMode;
-
- struct win *fore = NULL;
- int WinList = -1;
- int ForeNum;
- struct win *wtab[MAXWIN];
-
- struct key ktab[256];
-
- #ifndef FD_SET
- typedef struct fd_set
- {
- int fd_bits[1];
- } fd_set;
- # define FD_ZERO(fd) ((fd)->fd_bits[0] = 0)
- # define FD_SET(b, fd) ((fd)->fd_bits[0] |= 1 << (b))
- # define FD_ISSET(b, fd) ((fd)->fd_bits[0] & 1 << (b))
- # define FD_SETSIZE 32
- #endif
-
-
- #ifndef WTERMSIG
- # ifndef BSDWAIT /* if wait is NOT a union: */
- # define WTERMSIG(status) (status & 0177)
- # else
- # define WTERMSIG(status) status.w_T.w_Termsig
- # endif
- #endif
-
- #ifndef WIFCORESIG
- # ifndef BSDWAIT /* if wait is NOT a union: */
- # define WIFCORESIG(status) (status & 0200)
- # else
- # define WIFCORESIG(status) status.w_T.w_Coredump
- # endif
- #endif
-
- #ifndef WEXITSTATUS
- # ifndef BSDWAIT /* if wait is NOT a union: */
- # define WEXITSTATUS(status) ((status >> 8) & 0377)
- # else
- # define WEXITSTATUS(status) status.w_T.w_Retcode
- # endif
- #endif
-
- char *shellaka = NULL;
-
- /*
- * Do this last
- */
- #include "extern.h"
-
- /*
- * XXX: Missing system header files.
- */
- #ifdef USEVARARGS
- # ifndef VPRNT_DECLARED
- int vsprintf __P((char *, char *, va_list));
- # endif /* VPRNT_DECLARED */
- #endif
- int select __P((int, fd_set *, fd_set *, fd_set *, struct timeval *));
-
- static void
- brktty()
- {
- #ifdef POSIX
- setsid(); /* will break terminal affiliation */
- # ifdef BSD
- ioctl(0, TIOCSCTTY, 0);
- # endif /* BSD */
- #else
- # ifdef SYSV
- setpgrp(); /* will break terminal affiliation */
- # else
- # ifdef BSDJOBS
- if (DevTty)
- if (ioctl(DevTty, TIOCNOTTY, (char *) 0) != 0)
- debug2("brktty: ioctl(DevTty=%d, TIOCNOTTY, 0) = %d\n", DevTty, errno);
- # endif
- # endif
- #endif
- }
-
- static void
- freetty()
- {
- brktty();
- #if defined(BSDJOBS) && !(defined(POSIX) || defined(SYSV))
- if (DevTty >= 0)
- {
- close(DevTty);
- DevTty = -1;
- }
- #endif
- close(0);
- close(1);
- close(2);
- debug("did freetty\n");
- }
-
- static void
- fgtty()
- {
- #ifdef BSDJOBS
- int mypid;
-
- mypid = getpid();
-
- # ifdef BSDI
- setsid();
- ioctl(0, TIOCSCTTY, 0);
- # endif /* BSDI */
-
- # ifdef POSIX
- if (tcsetpgrp(0, mypid))
- {
- debug1("fgtty: tcsetpgrp: %d\n", errno);
- /* error is likely to have side-effects -- better to warn our user */
- SendErrorMsg("fgtty: Could not set process group id in tty");
- }
- # else
- if (ioctl(0, TIOCSPGRP, &mypid) != 0)
- debug1("fgtty: TIOSETPGRP: %d\n", errno);
- /* posix setsid() in brktty() from freetty() already made us leader */
- if (setpgrp(0, mypid))
- debug1("fgtty: setpgrp: %d\n", errno);
- # endif /* POSIX */
- #endif /* BSDJOBS */
- }
-
- #ifdef hpux
- /*
- * hpux has berkeley signal semantics if we use sigvector,
- * but not, if we use signal, so we define our own signal() routine.
- * (jw)
- */
- void (*signal(sig, func)) ()
- int sig;
- void (*func) ();
- {
- struct sigvec osv, sv;
-
- sv.sv_handler = func;
- sv.sv_mask = sigmask(sig);
- sv.sv_flags = SV_BSDSIG;
- if (sigvector(sig, &sv, &osv) < 0)
- return (BADSIG);
- return (osv.sv_handler);
- }
- #endif /* hpux */
-
- #ifndef USEBCOPY
- #ifdef bcopy
- #undef bcopy
- #endif
- void bcopy(s1, s2, len)
- register char *s1, *s2;
- register int len;
- {
- if (s1 < s2 && s2 < s1 + len)
- {
- s1 += len;
- s2 += len;
- while (len-- > 0)
- *--s2 = *--s1;
- }
- else
- while (len-- > 0)
- *s2++ = *s1++;
- }
- #endif /* USEBCOPY */
-
- void bclear(p, n)
- int n;
- char *p;
- {
- bcopy(blank, p, n);
- }
-
- static void
- closeallfiles()
- {
- int f;
- #ifdef SVR4
- struct rlimit rl;
-
- if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) && rl.rlim_max != RLIM_INFINITY)
- f = rl.rlim_max;
- else
- #endif /* SVR4 */
- #if defined(SYSV) && !defined(ISC)
- f = NOFILE;
- #else /* SYSV && !ISC */
- f = getdtablesize();
- #endif /* SYSV && !ISC */
- while (--f > 2)
- close(f);
- }
-
- static int InterruptPlease = 0;
-
- void main(ac, av)
- int ac;
- char **av;
- {
- register int n, len;
- register struct win *p;
- char *ap, *aka = NULL;
- char *av0;
- char socknamebuf[2 * MAXSTR];
- int s = 0;
- fd_set r, w, e;
- int mflag = 0;
- struct timeval tv;
- int nsel;
- char buf[IOSIZE], *bufp, *myname = (ac == 0) ? "screen" : av[0];
- struct stat st;
- int buflen, tmp;
- #ifdef _MODE_T /* (jw) */
- mode_t oumask;
- #else
- int oumask;
- #endif
- #ifdef SYSV
- struct utsname utsnam;
- #endif
-
- /*
- * First, close all unused descriptors
- * (otherwise, we might have problems with the select() call)
- */
- closeallfiles();
- #ifdef DEBUG
- (void) mkdir("/tmp/debug", 0777);
- if ((dfp = fopen("/tmp/debug/screen.front", "w")) == NULL)
- dfp = stderr;
- else
- (void) chmod("/tmp/debug/screen.front", 0666);
- #endif
- debug1("-- screen debug started %s\n", *av);
- #ifdef POSIX
- debug("POSIX\n");
- #endif
- #ifdef TERMIO
- debug("TERMIO\n");
- #endif
- #ifdef SYSV
- debug("SYSV\n");
- #endif
- #ifdef NAMEDPIPE
- debug("NAMEDPIPE\n");
- #endif
- #if defined(SIGWINCH) && defined(TIOCGWINSZ)
- debug("Window changing enabled\n");
- #endif
- #ifdef NOREUID
- debug("NOREUID\n");
- #endif
- #ifdef hpux
- debug("hpux\n");
- #endif
- #ifdef USEBCOPY
- debug("USEBCOPY\n");
- #endif
- #ifdef UTMPOK
- debug("UTMPOK\n");
- #endif
- #ifdef NETHACK
- debug("NETHACK\n");
- #endif
- #ifdef TERMINFO
- debug("TERMINFO\n");
- #endif
- #ifdef NAME_MAX
- debug1("NAME_MAX = %d\n", NAME_MAX);
- #endif
-
- BellString = SaveStr("Bell in window %");
- VisualBellString = SaveStr(" Wuff, Wuff!! ");
- ActivityString = SaveStr("Activity in window %");
- BufferFile = SaveStr("/tmp/screen-exchange");
- PowDetachString = 0;
- default_histheight = DEFAULTHISTHEIGHT;
- default_startup = (ac > 1) ? 0 : 1;
- adaptflag = 0;
- slowpaste = 0;
- VBellWait = VBELLWAIT;
- MsgWait = MSGWAIT;
- MsgMinWait = MSGMINWAIT;
- CompileKeys((char *)NULL, mark_key_tab);
-
- av0 = *av;
- while (ac > 0)
- {
- ap = *++av;
- if (--ac > 0 && *ap == '-')
- {
- switch (ap[1])
- {
- case 'a':
- allflag = 1;
- break;
- case 'A':
- adaptflag = 1;
- break;
- case 'c':
- if (ap[2])
- RcFileName = ap + 2;
- else
- {
- if (--ac == 0)
- exit_with_usage(myname);
- RcFileName = *++av;
- }
- break;
- case 'e':
- if (ap[2])
- ap += 2;
- else
- {
- if (--ac == 0)
- exit_with_usage(myname);
- ap = *++av;
- }
- if (!ParseEscape(ap))
- Msg(0, "Two characters are required with -e option.");
- break;
- case 'f':
- switch (ap[2])
- {
- case 'n':
- case '0':
- default_flow = FLOW_NOW * 0;
- break;
- case 'y':
- case '1':
- case '\0':
- default_flow = FLOW_NOW * 1;
- break;
- case 'a':
- default_flow = FLOW_AUTOFLAG;
- break;
- default:
- exit_with_usage(myname);
- }
- break;
- case 'h':
- if (ap[2])
- default_histheight = atoi(ap + 2);
- else
- {
- if (--ac == 0)
- exit_with_usage(myname);
- default_histheight = atoi(*++av);
- }
- if (default_histheight < 0)
- default_histheight = 0;
- break;
- case 'i':
- iflag = 1;
- break;
- case 't': /* title is a synonym for AkA */
- case 'k':
- if (ap[2])
- aka = ap + 2;
- else
- {
- if (--ac == 0)
- exit_with_usage(myname);
- aka = *++av;
- }
- break;
- case 'l':
- switch (ap[2])
- {
- case 'n':
- case '0':
- loginflag = 0;
- break;
- case 'y':
- case '1':
- case '\0':
- loginflag = 1;
- break;
- case 's':
- case 'i':
- lsflag = 1;
- break;
- default:
- exit_with_usage(myname);
- }
- break;
- case 'w':
- lsflag = 1;
- wipeflag = 1;
- break;
- case 'L':
- assume_LP = 1;
- break;
- case 'm':
- mflag = 1;
- break;
- case 'O':
- force_vt = 0;
- break;
- case 'T':
- if (ap[2])
- {
- if (strlen(ap+2) < 20)
- strcpy(screenterm, ap + 2);
- }
- else
- {
- if (--ac == 0)
- exit_with_usage(myname);
- if (strlen(*++av) < 20)
- strcpy(screenterm, *av);
- }
- break;
- case 'q':
- quietflag = 1;
- break;
- case 'r':
- case 'R':
- if (ap[2])
- {
- SockName = ap + 2;
- if (ac != 1)
- exit_with_usage(myname);
- }
- else if (ac > 1 && *av[1] != '-')
- {
- SockName = *++av;
- ac--;
- }
- rflag = (ap[1] == 'r') ? 1 : 2;
- break;
- #ifdef REMOTE_DETACH
- case 'd':
- dflag = 1;
- /* FALLTHRU */
- case 'D':
- if (!dflag)
- dflag = 2;
- if (ap[2])
- SockName = ap + 2;
- if (ac == 2)
- {
- if (*av[1] != '-')
- {
- SockName = *++av;
- ac--;
- }
- }
- break;
- #endif
- case 's':
- if (ap[2])
- ShellProg = ap + 2;
- else
- {
- if (--ac == 0)
- exit_with_usage(myname);
- ShellProg = *++av;
- }
- break;
- default:
- exit_with_usage(myname);
- }
- }
- else
- break;
- }
- real_uid = getuid();
- real_gid = getgid();
- eff_uid = geteuid();
- eff_gid = getegid();
- if (eff_uid != real_uid)
- {
- /* if running with s-bit, we must install a special signal
- * handler routine that resets the s-bit, so that we get a
- * core file anyway.
- */
- signal(SIGBUS, CoreDump);
- signal(SIGSEGV, CoreDump);
- }
- if (!ShellProg && (ShellProg = getenv("SHELL")) == 0)
- ShellProg = DefaultShell;
- ShellArgs[0] = ShellProg;
- #ifdef NETHACK
- nethackflag = (getenv("NETHACKOPTIONS") != NULL);
- #endif
- home = getenv("HOME"); /* may or may not return a result. jw. */
- if ((LoginName = getlogin()) && LoginName[0] != '\0')
- {
- if ((ppp = getpwnam(LoginName)) != (struct passwd *) 0)
- if (ppp->pw_uid != real_uid)
- ppp = (struct passwd *) 0;
- }
- if (ppp == 0)
- {
- if ((ppp = getpwuid(real_uid)) == 0)
- {
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "An alarm sounds through the dungeon...\nWarning, the kops are coming.");
- else
- #endif
- Msg(0, "getpwuid() can't identify your account!");
- exit(1);
- }
- LoginName = ppp->pw_name;
- }
- if (home == 0 || *home == '\0')
- home = ppp->pw_dir;
- if (strlen(LoginName) > 20)
- Msg(0, "LoginName too long - sorry.");
- if (strlen(home) > MAXPATH - 25)
- Msg(0, "$HOME too long - sorry.");
- #ifdef PASSWORD
- strcpy(Password, ppp->pw_passwd);
- #endif
-
- /* ttyname implies isatty */
- if (!(attach_tty = ttyname(0)))
- {
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "You must play from a terminal.");
- else
- #endif
- Msg(0, "Must be connected to a terminal.");
- exit(1);
- }
- if (strlen(attach_tty) >= MAXPATH)
- Msg(0, "TtyName too long - sorry.");
- if ((n = secopen(attach_tty, O_RDWR, 0)) < 0)
- Msg(0, "Cannot open '%s' - please check.", attach_tty);
- close(n);
-
- debug1("attach_tty is %s\n", attach_tty);
-
- #ifdef _MODE_T
- oumask = umask(0); /* well, unsigned never fails? jw. */
- #else
- if ((oumask = umask(0)) == -1)
- Msg(errno, "Cannot change umask to zero");
- #endif
- if ((SockDir = getenv("ISCREENDIR")) == NULL)
- SockDir = getenv("SCREENDIR");
- if (SockDir && strlen(SockDir) >= MAXPATH - 1)
- Msg(0, "ridiculous long $(I)SCREENDIR - try again.");
- #ifndef SOCKDIR
- if (SockDir == 0)
- {
- sprintf(SockPath, "%s/.iscreen", home);
- SockDir = SockPath;
- }
- #endif
- if (SockDir)
- {
- if (access(SockDir, F_OK))
- {
- if (UserContext() > 0)
- {
- if (mkdir(SockDir, 0700))
- UserReturn(0);
- UserReturn(1);
- }
- if (UserStatus() <= 0)
- Msg(0, "Cannot make directory '%s'", SockDir);
- }
- if (SockDir != SockPath)
- strcpy(SockPath, SockDir);
- }
- #ifdef SOCKDIR
- else
- {
- SockDir = SOCKDIR;
- if (stat(SockDir, &st))
- {
- if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1)
- Msg(errno, "Cannot make directory '%s'", SockDir);
- }
- else
- {
- n = eff_uid ? 0777 : 0755;
- if ((st.st_mode & 0777) != n)
- Msg(0, "Directory '%s' must have mode %03o.", SockDir, n);
- }
- sprintf(SockPath, "%s/S-%s", SockDir, LoginName);
- if (access(SockPath, F_OK))
- {
- if (mkdir(SockPath, 0700) == -1)
- Msg(errno, "Cannot make directory '%s'", SockPath);
- (void) chown(SockPath, real_uid, real_gid);
- }
- }
- #endif
- if (stat(SockPath, &st) == -1)
- {
- Msg(errno, "Cannot access %s", SockPath);
- }
- else
- {
- #ifdef _POSIX_SOURCE
- if (S_ISDIR(st.st_mode) == 0)
- #else
- if ((st.st_mode & S_IFMT) != S_IFDIR)
- #endif
- Msg(0, "%s is not a directory.", SockPath);
- if (st.st_uid != real_uid)
- Msg(0, "You are not the owner of %s.", SockPath);
- if ((st.st_mode & 0777) != 0700)
- Msg(0, "Directory %s must have mode 700.", SockPath);
- }
- strcat(SockPath, "/");
- SockNamePtr = SockPath + strlen(SockPath);
- (void) umask(oumask);
- #if defined(SYSV) && !defined(ISC)
- if (uname(&utsnam) == -1)
- Msg(0, "uname() failed, errno = %d", errno);
- else
- {
- strncpy(HostName, utsnam.nodename, MAXSTR);
- HostName[(sizeof(utsnam.nodename) <= MAXSTR) ?
- sizeof(utsnam.nodename) : MAXSTR] = '\0';
- }
- #else
- (void) gethostname(HostName, MAXSTR);
- #endif
- HostName[MAXSTR - 1] = '\0';
- if ((ap = index(HostName, '.')) != NULL)
- *ap = '\0';
- GetTTY(0, &OldMode);
- #ifdef POSIX
- ospeed = (short) cfgetospeed(&OldMode.tio);
- #else
- # ifndef TERMIO
- ospeed = (short) OldMode.m_ttyb.sg_ospeed;
- # endif
- #endif
- debug1("...setting extern short ospeed = %d\n", ospeed);
-
- if (lsflag)
- {
- int i;
- i = FindSocket(0, (int *)NULL);
- /* MakeClientSocket appended the last (Sock)Name there: */
- *SockNamePtr = '\0';
- if (i == 0)
- {
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "This room is empty (%s)\n", SockPath);
- else
- #endif /* NETHACK */
- Msg(0, "No Sockets found in %s\n", SockPath);
- }
- else
- Msg(0, "%d Socket%s in %s.\n", i, i > 1 ? "s" : "", SockPath);
- /* NOTREACHED */
- }
- if (rflag)
- {
- debug("screen -r: - is there anybody out there?\n");
- #ifdef SHADOWPW
- setspent(); /* open shadow file while we are still root */
- #endif /* SHADOWPW */
- if (Attach(MSG_ATTACH))
- {
- Attacher();
- /* NOTREACHED */
- }
- debug("screen -r: backend not responding -- still crying\n");
- }
- else if (dflag)
- {
- (void) Attach(MSG_DETACH);
- DeadlyMsg = 0;
- Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : ""));
- eexit(0);
- /* NOTREACHED */
- }
- if (!mflag && (SockName = getenv("STY")) != 0 && *SockName != '\0')
- {
- setuid(real_uid);
- setgid(real_gid);
- s = MakeClientSocket(1, SockName);
- if (ac == 0)
- {
- ac = 1;
- av = ShellArgs;
- }
- av[ac] = aka;
- SendCreateMsg(s, ac, av, allflag, default_flow, loginflag, default_histheight,
- screenterm);
- close(s);
- exit(0);
- }
- #if defined(BSDJOBS) && !(defined(POSIX) || defined(SYSV))
- if ((DevTty = open("/dev/tty", O_RDWR | O_NDELAY)) == -1)
- Msg(errno, "/dev/tty");
- #endif
- switch (MasterPid = fork())
- {
- case -1:
- Msg(errno, "fork");
- /* NOTREACHED */
- case 0:
- break;
- default:
- sprintf(socknamebuf, "%d.%s.%s", MasterPid, stripdev(attach_tty),
- HostName);
- for (ap = socknamebuf; *ap; ap++)
- if (*ap == '/')
- *ap = '-';
- SockName = socknamebuf;
- #ifdef SHADOWPW
- setspent(); /* open shadow file while we are still root */
- #endif /* SHADOWPW */
- Attacher();
- /* NOTREACHED */
- }
- #ifdef DEBUG
- if (dfp != stderr)
- fclose(dfp);
- if ((dfp = fopen("/tmp/debug/screen.back", "w")) == NULL)
- dfp = stderr;
- else
- (void) chmod("/tmp/debug/screen.back", 0666);
- #endif
- debug("-- screen.back debug started\n");
- ap = av0 + strlen(av0) - 1;
- while (ap >= av0)
- {
- if (!strncmp("screen", ap, 6))
- {
- strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */
- break;
- }
- ap--;
- }
- if (ap < av0)
- *av0 = 'S';
-
- AttacherPid = getppid();
- sprintf(socknamebuf, "%d.%s.%s", getpid(), stripdev(attach_tty), HostName);
- for (ap = socknamebuf; *ap; ap++)
- if (*ap == '/')
- *ap = '-';
- SockName = socknamebuf;
- ServerSocket = s = MakeServerSocket();
- #ifdef ETCSCREENRC
- if ((ap = getenv("SYSSCREENRC")) == NULL)
- StartRc(ETCSCREENRC);
- else
- StartRc(ap);
- #endif
- StartRc(RcFileName);
- InitTermcap();
- InitTerm(0);
- MakeNewEnv();
- strcpy(display_tty, attach_tty);
- #ifdef UTMPOK
- # ifdef apollo
- ReInitUtmp();
- # else
- InitUtmp();
- # endif /* apollo */
- #endif /* UTMPOK */
- signal(SIGHUP, SigHup);
- signal(SIGINT, Finit);
- signal(SIGQUIT, Finit);
- signal(SIGTERM, Finit);
- #ifdef BSDJOBS
- signal(SIGTTIN, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- #endif
- InitKeytab();
- #ifdef ETCSCREENRC
- if ((ap = getenv("SYSSCREENRC")) == NULL)
- FinishRc(ETCSCREENRC);
- else
- FinishRc(ap);
- #endif
- FinishRc(RcFileName);
-
- /* Note: SetMode must be called _after_ FinishRc (flow is set there).
- */
- SetMode(&OldMode, &NewMode);
- SetTTY(0, &NewMode);
- if (loginflag == -1)
- loginflag = LOGINDEFAULT;
- if (ac == 0)
- {
- ac = 1;
- av = ShellArgs;
- if (!aka)
- aka = shellaka;
- }
- if (!HasWindow)
- {
- debug("We open one default window, as screenrc did not specify one.\n");
- if (MakeWindow(aka, av, allflag, default_flow, 0, (char *)0, loginflag, -1, (char *)0) == -1)
- {
- Finit(1);
- /* NOTREACHED */
- }
- }
- if (default_startup)
- display_copyright();
- #ifdef SYSV
- signal(SIGCLD, SigChld);
- #else
- signal(SIGCHLD, SigChld);
- #endif
- signal(SIGINT, SigInt);
- tv.tv_usec = 0;
- if (rflag == 2)
- {
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "I can't seem to find a... Hey, wait a minute! Here comes a screen now.");
- else
- #endif
- Msg(0, "New screen...");
- rflag = 0;
- }
- brktty();
- for (;;)
- {
- /*
- * check to see if message line should be removed
- */
- if (status)
- {
- int time_left;
-
- debug("checking status...\n");
- time_left = TimeDisplayed + (BellDisplayed ? VBellWait : MsgWait) - time((time_t *)0);
- if (time_left > 0)
- {
- tv.tv_sec = time_left;
- debug(" not yet.\n");
- }
- else
- {
- debug(" removing now.\n");
- RemoveStatus();
- }
- }
- /*
- * check for I/O on all available I/O descriptors
- */
- FD_ZERO(&r);
- FD_ZERO(&w);
- FD_ZERO(&e);
- if (inbuf_ct > 0)
- for (n = 0; n < MAXWIN; n++)
- #ifdef COPY_PASTE /* wrong here? jw. */
- if (inlen[n] > 0 || (pastelen > 0 && n == ForeNum))
- #else
- if (inlen[n] > 0)
- #endif
- FD_SET(wtab[n]->ptyfd, &w);
- if (!Detached)
- FD_SET(0, &r);
- for (n = WinList; n != -1; n = p->WinLink)
- {
- p = wtab[n];
- if (p->active && status && !BellDisplayed && !HS)
- continue;
- if (p->outlen > 0)
- continue;
- if (in_ovl && ovl_blockfore && n == ForeNum)
- continue;
- FD_SET(p->ptyfd, &r);
- }
- FD_SET(s, &r);
- (void) fflush(stdout);
- if (GotSignal && !status)
- {
- SigHandler();
- continue;
- }
- if ((nsel = select(FD_SETSIZE, &r, &w, &e, (status) ? &tv : (struct timeval *) 0)) < 0)
- {
- debug1("Bad select - errno %d\n", errno);
- if (errno != EINTR)
- {
- perror("select");
- Finit(1);
- }
- else
- {
- errno = 0;
- if ((!GotSignal || status) && !InterruptPlease)
- continue;
- }
- }
- if (InterruptPlease)
- {
- char buf[1];
-
- debug("Backend received interrupt\n");
- *buf = intrc;
- write(wtab[ForeNum]->ptyfd, buf, 1);
- debug1("Backend wrote interrupt to %d\n", ForeNum);
- InterruptPlease = 0;
-
- continue;
- }
- if (GotSignal && !status)
- {
- SigHandler();
- continue;
- }
- /* Process a client connect attempt and message */
- if (nsel && FD_ISSET(s, &r))
- {
- nsel--;
- if (!HS)
- RemoveStatus();
- if (in_ovl)
- {
- SetOvlCurr();
- (*ovl_process)(0, 0); /* We have to abort first!! */
- CheckScreenSize(1); /* Change fore */
- DeadlyMsg = 0;
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "KAABLAMM!!! You triggered a land mine!");
- else
- #endif
- Msg(0, "Aborted because of window change or message.");
- }
- else
- CheckScreenSize(1); /* Change fore */
- ReceiveMsg(s);
- continue;
- }
- /*
- * Write the stored user input to the window descriptors first.
- * We do not want to choke, if he types fast.
- */
- if (nsel && inbuf_ct > 0)
- {
- for (n = 0; n < MAXWIN ; n++)
- {
- if (inlen[n] <= 0)
- continue;
- tmp = wtab[n]->ptyfd;
- if (FD_ISSET(tmp, &w))
- {
- if ((len = write(tmp, inbuf[n], inlen[n])) > 0)
- {
- if ((inlen[n] -= len) == 0)
- inbuf_ct--;
- bcopy(inbuf[n] + len, inbuf[n], inlen[n]);
- }
- if (--nsel == 0)
- break;
- }
- }
- }
- /* Read, process, and store the user input */
- if (nsel && FD_ISSET(0, &r))
- {
- nsel--;
- if (!HS)
- RemoveStatus();
- if (ESCseen)
- {
- buf[0] = Esc;
- buflen = read(0, buf + 1, IOSIZE - 1) + 1;
- ESCseen = 0;
- }
- else
- buflen = read(0, buf, IOSIZE);
- if (buflen < 0)
- {
- debug1("Read error: %d - SigHup()ing!\n", errno);
- SigHup(SIGARG);
- continue;
- }
- if (buflen == 0)
- {
- debug("Found EOF - SigHup()ing!\n");
- SigHup(SIGARG);
- continue;
- }
- bufp = buf;
- if (in_ovl)
- {
- SetOvlCurr();
- (*ovl_process)(&bufp, &buflen);
- }
- while (buflen > 0)
- {
- n = ForeNum;
- len = inlen[n];
- bufp = ProcessInput(bufp, &buflen, inbuf[n], &inlen[n],
- sizeof *inbuf);
- if (inlen[n] > 0 && len == 0)
- inbuf_ct++;
- }
- if (inbuf_ct > 0)
- continue;
- }
- if (GotSignal && !status)
- {
- SigHandler();
- continue;
- }
- #ifdef COPY_PASTE
- /* Write the copybuffer contents first, if any. jw. */
- if (pastelen > 0)
- {
- n = ForeNum;
- debug1("writing pastebuffer (%d)\n", pastelen);
- tmp = wtab[n]->ptyfd;
- if ( /* FD_ISSET(tmp, &w) && */
- (len = write(tmp, pastebuffer,
- pastelen > IOSIZE ? IOSIZE : pastelen)) > 0)
- {
- pastebuffer += len;
- pastelen -= len;
- debug1("%d bytes pasted\n", len);
- if (slowpaste > 0)
- {
- struct timeval t;
-
- debug1("slowpaste %d\n", slowpaste);
- t.tv_usec = (long) (slowpaste * 1000);
- t.tv_sec = 0;
- select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
- }
- else
- continue;
- }
- /*
- * We could not paste? Let's see if the pty did echo the lot.
- * Then continue by processing some pty output.
- */
- }
- #endif
- if (GotSignal && !status)
- {
- SigHandler();
- continue;
- }
- /* Read and process the output from the window descriptors */
- for (n = WinList; n != -1; n = p->WinLink)
- {
- p = wtab[n];
- if (in_ovl && ovl_blockfore && n == ForeNum)
- continue;
- if (p->outlen)
- WriteString(p, p->outbuf, p->outlen);
- else if (nsel && FD_ISSET(p->ptyfd, &r))
- {
- nsel--;
- if ((len = read(p->ptyfd, buf, IOSIZE)) == -1)
- {
- #ifdef EWOULDBLOCK
- if (errno == EWOULDBLOCK)
- len = 0;
- #endif
- }
- #if defined(TIOCPKT) && !defined(sgi)
- if (buf[0])
- {
- debug1("PAKET %x\n", buf[0]);
- if (buf[0] & TIOCPKT_NOSTOP)
- {
- NewAutoFlow(p, 0);
- }
- if (buf[0] & TIOCPKT_DOSTOP)
- {
- NewAutoFlow(p, 1);
- }
- }
- if (len > 1)
- WriteString(p, buf + 1, len - 1);
- #else /* TIOCPKT && !sgi */
- if (len > 0)
- WriteString(p, buf, len);
- #endif /* TIOCPKT && !sgi */
- }
- if (p->bell == BELL_ON)
- {
- p->bell = BELL_DONE;
- Msg(0, MakeWinMsg(BellString, n));
- if (p->monitor == MON_FOUND)
- p->monitor = MON_DONE;
- }
- else if (p->bell == BELL_VISUAL)
- {
- if (!BellDisplayed)
- {
- p->bell = BELL_DONE;
- Msg(0, VisualBellString);
- BellDisplayed = 1;
- }
- }
- else if (p->monitor == MON_FOUND)
- {
- p->monitor = MON_DONE;
- Msg(0, MakeWinMsg(ActivityString, n));
- }
- }
- if (GotSignal && !status)
- SigHandler();
- #ifdef DEBUG
- if (nsel)
- debug1("Left over nsel: %d\n", nsel);
- #endif
- }
- /* NOTREACHED */
- }
-
- static void SigHandler()
- {
- struct stat st;
- while (GotSignal)
- {
- GotSignal = 0;
- DoWait();
- #ifdef SYSV
- signal(SIGCLD, SigChld);
- #endif
- }
- if (stat(SockPath, &st) == -1)
- {
- debug1("SigHandler: Yuck! cannot stat '%s'\n", SockPath);
- if (!RecoverSocket())
- {
- debug("SCREEN cannot recover from corrupt Socket, bye\n");
- Finit(1);
- }
- else
- debug1("'%s' reconstructed\n", SockPath);
- }
- else
- debug2("SigHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode);
- }
-
- #ifdef DEBUG
- int FEpanic;
-
- sig_t FEChld(SIGDEFARG)
- {
- FEpanic=1;
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
- #endif
-
- static sig_t SigChld(SIGDEFARG)
- {
- debug("SigChld()\n");
- GotSignal = 1;
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
-
- sig_t SigHup(SIGDEFARG)
- {
- debug("SigHup()\n");
- if (auto_detach)
- Detach(D_DETACH);
- else
- Finit(0);
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
-
- /*
- * the frontend's Interrupt handler
- * we forward SIGINT to the backend
- */
- static sig_t
- AttacherSigInt(SIGDEFARG)
- {
- Kill(MasterPid, SIGINT);
- signal(SIGINT, AttacherSigInt);
- # ifndef SIGVOID
- return (sig_t) 0;
- # endif
- }
-
-
- /*
- * the backend's Interrupt handler
- * we cannot insert the intrc directly, as we never know
- * if fore and ForeNum are valid.
- */
- static sig_t SigInt(SIGDEFARG)
- {
- #if HAZARDOUS
- char buf[1];
-
- debug("SigInt()\n");
- *buf = (char) intrc;
- inlen[ForeNum] = 0;
- if (fore && !in_ovl)
- write(fore->ptyfd, buf, 1);
- #else
- debug("SigInt() careful\n");
- InterruptPlease = 1;
- signal(SIGINT, SigInt);
- #endif
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
-
- static sig_t CoreDump(sig)
- int sig;
- {
- setgid(getgid());
- setuid(getuid());
- unlink("core");
- fprintf(stderr, "\r\n[screen caught signal %d.%s]\r\n", sig,
- #ifdef SHADOWPW
- ""
- #else /* SHADOWPW */
- " (core dumped)"
- #endif /* SHADOWPW */
- );
- fflush(stderr);
- Kill(AttacherPid, SIG_BYE);
- #ifdef SHADOWPW
- eexit(sig);
- #else /* SHADOWPW */
- abort();
- #endif /* SHADOWPW */
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
-
- static void DoWait()
- {
- register int n, next, pid;
- #ifdef BSDWAIT
- union wait wstat;
- #else
- int wstat;
- #endif
-
- #ifdef BSDJOBS
- # ifndef BSDWAIT
- while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0)
- # else
- while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0)
- # endif
- #else /* BSDJOBS */
- while ((pid = wait(&wstat)) < 0)
- if (errno != EINTR)
- break;
- if (pid >= 0)
- #endif /* BSDJOBS */
- {
- for (n = WinList; n != -1; n = next)
- {
- next = wtab[n]->WinLink;
- if (pid == wtab[n]->wpid)
- {
- #ifdef BSDJOBS
- if (WIFSTOPPED(wstat))
- {
- # ifdef NETHACK
- if (nethackflag)
- Msg(0, "You regain consciousness.");
- else
- # endif /* NETHACK */
- Msg(0, "Child has been stopped, restarting.");
- debug1("WIFSTOPPED: %d SIGCONT\n", wtab[n]->wpid);
- if (killpg(wtab[n]->wpid, SIGCONT))
- kill(wtab[n]->wpid, SIGCONT);
- }
- else
- #endif
- KillWindow(n);
- }
- }
- }
- }
-
- void KillWindow(n)
- int n;
- {
- register int i;
- /*
- * Remove window from linked list.
- */
- if (n == WinList) /* WinList = ForeNum */
- {
- RemoveStatus();
- WinList = fore->WinLink;
- fore = 0;
- }
- else
- {
- i = WinList;
- while (wtab[i]->WinLink != n)
- i = wtab[i]->WinLink;
- wtab[i]->WinLink = wtab[n]->WinLink;
- }
- FreeWindow(wtab[n]);
- wtab[n] = 0;
- if (inlen[n] > 0)
- {
- inlen[n] = 0;
- inbuf_ct--;
- }
- /*
- * If the foreground window disappeared check the head of the linked list
- * of windows for the most recently used window. If no window is alive at
- * all, exit.
- */
- if (WinList == -1)
- Finit(0);
- if (!fore)
- SwitchWindow(WinList);
- }
-
- static sig_t Finit(i)
- int i;
- {
- register int n, next;
-
- #ifdef SYSV
- signal(SIGCLD, SIG_IGN);
- #else
- signal(SIGCHLD, SIG_IGN);
- #endif
- signal(SIGHUP, SIG_IGN);
- debug1("Finit(%d);\n", i);
- for (n = WinList; n != -1; n = next)
- {
- next = wtab[n]->WinLink;
- FreeWindow(wtab[n]);
- }
- FinitTerm();
- SetTTY(0, &OldMode);
- #ifdef UTMPOK
- RestoreLoginSlot();
- #endif
- printf("\n[screen is terminating]\n");
- freetty();
- if (ServerSocket != -1)
- {
- debug1("we unlink(%s)\n", SockPath);
- (void) unlink(SockPath);
- }
- Kill(AttacherPid, SIG_BYE);
- exit(i);
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
-
- void
- eexit(e)
- int e;
- {
- if (ServerSocket != -1)
- {
- debug1("we unlink(%s)\n", SockPath);
- (void) unlink(SockPath);
- }
- exit(e);
- }
-
- static void InitKeytab()
- {
- register unsigned int i;
-
- for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++)
- ktab[i].type = KEY_IGNORE;
-
- ktab['h'].type = ktab[Ctrl('h')].type = KEY_HARDCOPY;
- #ifdef BSDJOBS
- ktab['z'].type = ktab[Ctrl('z')].type = KEY_SUSPEND;
- #endif
- ktab['c'].type = ktab[Ctrl('c')].type = KEY_SHELL;
- ktab[' '].type = ktab[Ctrl(' ')].type =
- ktab['n'].type = ktab[Ctrl('n')].type = KEY_NEXT;
- ktab['-'].type = ktab['p'].type = ktab[Ctrl('p')].type = KEY_PREV;
- ktab['k'].type = ktab[Ctrl('k')].type = KEY_KILL;
- ktab['l'].type = ktab[Ctrl('l')].type = KEY_REDISPLAY;
- ktab['w'].type = ktab[Ctrl('w')].type = KEY_WINDOWS;
- ktab['v'].type = ktab[Ctrl('v')].type = KEY_VERSION;
- ktab['q'].type = ktab[Ctrl('q')].type = KEY_XON;
- ktab['s'].type = ktab[Ctrl('s')].type = KEY_XOFF;
- ktab['t'].type = ktab[Ctrl('t')].type = KEY_TIME;
- ktab['i'].type = ktab[Ctrl('i')].type = KEY_INFO;
- ktab['m'].type = ktab[Ctrl('m')].type = KEY_LASTMSG;
- ktab['A'].type = KEY_AKA, ktab['A'].args = NULL;
- ktab['L'].type = KEY_LOGIN;
- ktab[','].type = KEY_LICENSE;
- ktab['W'].type = KEY_WIDTH;
- ktab['.'].type = KEY_TERMCAP;
- ktab[Ctrl('\\')].type = KEY_QUIT;
- ktab['d'].type = ktab[Ctrl('d')].type = KEY_DETACH;
- ktab['r'].type = ktab[Ctrl('r')].type = KEY_WRAP;
- ktab['f'].type = ktab[Ctrl('f')].type = KEY_FLOW;
- ktab['C'].type = KEY_CLEAR;
- ktab['Z'].type = KEY_RESET;
- ktab['H'].type = KEY_LOGTOGGLE;
- if (Esc != MetaEsc)
- ktab[Esc].type = KEY_OTHER;
- else
- ktab[Esc].type = KEY_IGNORE;
- ktab['M'].type = KEY_MONITOR;
- ktab['?'].type = KEY_HELP;
- for (i = 0; i <= 9; i++)
- ktab['0' + i].type = (enum keytype) (i + (int)KEY_0);
- ktab[Ctrl('G')].type = KEY_VBELL;
- ktab[':'].type = KEY_COLON;
- #ifdef COPY_PASTE
- ktab['['].type = ktab[Ctrl('[')].type = KEY_COPY;
- ktab[']'].type = ktab[Ctrl(']')].type = KEY_PASTE;
- ktab['{'].type = KEY_HISTORY;
- ktab['}'].type = KEY_HISTNEXT;
- ktab['>'].type = KEY_WRITE_BUFFER;
- ktab['<'].type = KEY_READ_BUFFER;
- ktab['='].type = KEY_REMOVE_BUFFERS;
- #endif
- #ifdef POW_DETACH
- ktab['D'].type = KEY_POW_DETACH;
- #endif
- #ifdef LOCK
- ktab['x'].type = ktab[Ctrl('x')].type = KEY_LOCK;
- #endif
- }
-
- /*
- * this is a braindamaged hack: if (obuf == NULL) then we provided
- * a key_type as a second char in ibuf. not a key.
- */
- char *ProcessInput(ibuf, pilen, obuf, polen, obuf_size)
- char *ibuf, *obuf;
- register int *pilen, *polen, obuf_size;
- {
- register int n;
- register enum keytype k;
- register char *s, *p;
- char buf[2];
- int newwidth;
-
- if (!obuf)
- obuf_size = 0;
-
- for (s = ibuf, p = obuf + *polen; *pilen > 0; --*pilen, s++)
- {
- if (*s == Esc)
- {
- debug2("'%c %c ", s[0], s[1]);
- debug2("%c %c' ", s[2], s[3]);
- if (*pilen > 1)
- {
- --*pilen;
- s++;
- #if defined(GOULD_NP1)
- k = (obuf)?(ktab[*s].type):(enum keytype)(int)(*s);
- #else
- k = (obuf)?(ktab[*s].type):(enum keytype)(*s);
- #endif
- debug2("Processinput C-A %02x '%c' ", k, k);
- debug1("%s\n", (obuf)?"std":"NOOBUF");
- if (*s == MetaEsc)
- {
- if (*polen < obuf_size)
- {
- *p++ = Esc;
- ++*polen;
- }
- }
- else if ((int)k >= (int)KEY_0 && (int)k <= (int)KEY_9)
- SwitchWindow((int)k - (int)KEY_0);
- else
- switch (k)
- {
- case KEY_TERMCAP:
- WriteFile(DUMP_TERMCAP);
- break;
- case KEY_HARDCOPY:
- WriteFile(DUMP_HARDCOPY);
- break;
- case KEY_LOGTOGGLE:
- LogToggle();
- break;
- #ifdef BSDJOBS
- case KEY_SUSPEND:
- *pilen = 0;
- Detach(D_STOP);
- break;
- #endif
- case KEY_SHELL:
- debug("calling MakeWindow with shell\n");
- MakeWindow(shellaka, ShellArgs, allflag, default_flow,
- 0, (char *) 0, loginflag, -1, (char *)0);
- break;
- case KEY_NEXT:
- if (MoreWindows())
- SwitchWindow(NextWindow());
- break;
- case KEY_PREV:
- if (MoreWindows())
- SwitchWindow(PreviousWindow());
- break;
- case KEY_KILL:
- KillWindow(n = ForeNum);
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "You destroy poor window %d", n);
- #endif
- break;
- case KEY_QUIT:
- Finit(0);
- /* NOTREACHED */
- case KEY_DETACH:
- *pilen = 0;
- Detach(D_DETACH);
- break;
- #ifdef POW_DETACH
- case KEY_POW_DETACH:
- *pilen = 0;
- if (obuf)
- {
- buf[0] = *s;
- buf[1] = '\0';
- Msg(0, buf);
- read(0, buf, 1);
- if (*buf != *s)
- {
- write(1, "\007", 1);
- RemoveStatus();
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "The blast of disintegration whizzes by you!");
- #endif
- break;
- }
- }
- Detach(D_POWER); /* detach and kill Attacher's
- * parent */
- break;
- #endif
- case KEY_REDISPLAY:
- Activate(0);
- break;
- case KEY_WINDOWS:
- ShowWindows();
- break;
- case KEY_VERSION:
- Msg(0, "screen %d.%.2d.%.2d%s (%s) %s", REV, VERS,
- PATCHLEVEL, STATE, ORIGIN, DATE);
- break;
- case KEY_TIME:
- ShowTime();
- break;
- case KEY_INFO:
- ShowInfo();
- break;
- case KEY_OTHER:
- if (MoreWindows())
- SwitchWindow(fore->WinLink);
- break;
- case KEY_XON:
- if (*polen < obuf_size)
- {
- *p++ = Ctrl('q');
- ++*polen;
- }
- break;
- case KEY_XOFF:
- if (*polen < obuf_size)
- {
- *p++ = Ctrl('s');
- ++*polen;
- }
- break;
- #ifdef LOCK
- case KEY_LOCK:
- Detach(D_LOCK); /* do it micha's way */
- break;
- #endif
- case KEY_WIDTH:
- if (Z0 || WS)
- {
- if (fore->width == Z0width)
- newwidth = Z1width;
- else if (fore->width == Z1width)
- newwidth = Z0width;
- else if (fore->width > (Z0width+Z1width)/2)
- newwidth = Z0width;
- else
- newwidth = Z1width;
- ChangeWindowSize(fore, newwidth, fore->height);
- Activate(fore->norefresh);
- }
- else
- Msg(0, "Your termcap does not specify how to change the terminal's width.");
- break;
- case KEY_LOGIN:
- SlotToggle(0);
- break;
- case KEY_AKA:
- if (!ktab[*s].args)
- InputAKA();
- else
- strncpy(fore->cmd + fore->akapos, ktab[*s].args[0], 20);
- break;
- case KEY_COLON:
- InputColon();
- break;
- case KEY_LASTMSG:
- Msg(0, "%s", LastMsg);
- break;
- case KEY_SET:
- DoSet(ktab[*s].args);
- break;
- case KEY_SCREEN:
- debug3("KEY_SCREEN DoSc(, ktab[%d].args(='%s','%s')...)\n",
- *s, ktab[*s].args[0], ktab[*s].args[1]);
- DoScreen("key", ktab[*s].args);
- break;
- case KEY_CREATE:
- debug2("KEY_CREATE MaWi(0, ktab[%d].args(='%s')...)\n",
- *s, ktab[*s].args);
- MakeWindow((char *) 0, ktab[*s].args, allflag, default_flow, 0, (char *) 0, loginflag, -1, (char *)0);
- break;
- case KEY_WRAP:
- fore->wrap = !fore->wrap;
- Msg(0, "%cwrap", fore->wrap ? '+' : '-');
- break;
- case KEY_FLOW:
- if (fore->flow & FLOW_AUTOFLAG)
- fore->flow = (fore->flow & FLOW_AUTO) | FLOW_NOW;
- else if (fore->flow & FLOW_NOW)
- fore->flow &= ~FLOW_NOW;
- else
- fore->flow = fore->flow ? FLOW_AUTOFLAG|FLOW_AUTO|FLOW_NOW : FLOW_AUTOFLAG;
- SetFlow(fore->flow & FLOW_NOW);
- Msg(0, "%cflow%s", (fore->flow & FLOW_NOW) ? '+' : '-',
- (fore->flow & FLOW_AUTOFLAG) ? "(auto)" : "");
- break;
- case KEY_CLEAR:
- if (fore->state == LIT)
- WriteString(fore, "\033[H\033[J", 6);
- break;
- case KEY_RESET:
- if (fore->state == LIT)
- WriteString(fore, "\033c", 2);
- break;
- case KEY_MONITOR:
- if (fore->monitor == MON_OFF)
- {
- fore->monitor = MON_ON;
- Msg(0,
- "Window %d is now being monitored for all activity.",
- ForeNum);
- }
- else
- {
- fore->monitor = MON_OFF;
- Msg(0,
- "Window %d is no longer being monitored for activity.",
- ForeNum);
- }
- break;
- case KEY_HELP:
- display_help();
- break;
- case KEY_LICENSE:
- display_copyright();
- break;
- #ifdef COPY_PASTE
- case KEY_COPY:
- (void) MarkRoutine(PLAIN);
- break;
- case KEY_HISTNEXT:
- if (MarkRoutine(CRAZY))
- if (copybuffer != NULL)
- {
- pastelen = copylen;
- pastebuffer = copybuffer;
- debug("histnext\n");
- }
- break;
- case KEY_HISTORY:
- if (MarkRoutine(TRICKY))
- if (copybuffer != NULL)
- {
- pastelen = copylen;
- pastebuffer = copybuffer;
- debug1("history new copylen: %d\n", pastelen);
- }
- break;
- case KEY_PASTE:
- if (copybuffer == NULL)
- {
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "Nothing happens.");
- else
- #endif
- Msg(0, "empty buffer");
- copylen = 0;
- break;
- }
- pastelen = copylen;
- pastebuffer = copybuffer;
- break;
- case KEY_WRITE_BUFFER:
- if (copybuffer == NULL)
- {
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "Nothing happens.");
- else
- #endif
- Msg(0, "empty buffer");
- copylen = 0;
- break;
- }
- WriteFile(DUMP_EXCHANGE);
- break;
- case KEY_READ_BUFFER:
- ReadFile();
- break;
- case KEY_REMOVE_BUFFERS:
- KillBuffers();
- break;
- #endif /* COPY_PASTE */
- case KEY_VBELL:
- if (visual_bell)
- {
- visual_bell = 0;
- Msg(0, "switched to audible bell");
- }
- else
- {
- visual_bell = 1;
- Msg(0, "switched to visual bell");
- }
- break;
- default:
- break;
- }
- }
- else
- ESCseen = 1;
- --*pilen;
- s++;
- break;
- }
- else if (*polen < obuf_size)
- {
- *p++ = *s;
- ++*polen;
- }
- }
- return (s);
- }
-
- /* Send a terminal report as if it were typed. */
- void
- Report(wp, fmt, n1, n2)
- struct win *wp;
- char *fmt;
- int n1, n2;
- {
- register int n, len;
- char rbuf[40];
-
- sprintf(rbuf, fmt, n1, n2);
- len = strlen(rbuf);
-
- for (n = 0; n < MAXWIN; n++)
- {
- if (wp == wtab[n])
- {
- if ((unsigned)(inlen[n] + len) <= sizeof *inbuf)
- {
- bcopy(rbuf, inbuf[n] + inlen[n], len);
- if (inlen[n] == 0)
- inbuf_ct++;
- inlen[n] += len;
- }
- break;
- }
- }/* for */
- }
-
- void
- SwitchWindow(n)
- int n;
- {
- debug1("SwitchWindow %d\n", n);
- if (!wtab[n])
- {
- ShowWindows();
- return;
- }
- if (wtab[n] == fore)
- {
- Msg(0, "This IS window %d.", n);
- return;
- }
- SetForeWindow(n);
- if (!Detached && !in_ovl)
- Activate(fore->norefresh);
- }
-
- static void SetForeWindow(n)
- int n;
- {
- /*
- * If we come from another window, make it inactive.
- */
- if (fore)
- fore->active = 0;
- ForeNum = n;
- fore = wtab[n];
- if (!Detached && !in_ovl)
- fore->active = 1;
- /*
- * Place the window at the head of the most-recently-used list.
- */
- if ((n = WinList) != ForeNum)
- {
- /*
- * we had a bug here. we sometimes ran into n = -1; and crashed.
- * (this is not the perfect fix. "if (...) break;" inserted. jw.)
- */
- while (wtab[n]->WinLink != ForeNum)
- {
- if (wtab[n]->WinLink == -1)
- break;
- n = wtab[n]->WinLink;
- }
- wtab[n]->WinLink = fore->WinLink;
- fore->WinLink = WinList;
- WinList = ForeNum;
- }
- }
-
- static int NextWindow()
- {
- register struct win **pp;
-
- for (pp = wtab + ForeNum + 1; pp != wtab + ForeNum; ++pp)
- {
- if (pp == wtab + MAXWIN)
- pp = wtab;
- if (*pp)
- break;
- }
- return pp - wtab;
- }
-
- static int PreviousWindow()
- {
- register struct win **pp;
-
- for (pp = wtab + ForeNum - 1; pp != wtab + ForeNum; --pp)
- {
- if (pp < wtab)
- pp = wtab + MAXWIN - 1;
- if (*pp)
- break;
- }
- return pp - wtab;
- }
-
- static int MoreWindows()
- {
- if (fore->WinLink != -1)
- return 1;
- #ifdef NETHACK
- if (nethackflag)
- Msg(0, "You cannot escape from window %d!", ForeNum);
- else
- #endif
- Msg(0, "No other window.");
- return 0;
- }
-
- static void FreeWindow(wp)
- struct win *wp;
- {
- #ifdef UTMPOK
- RemoveUtmp(wp);
- #endif
- #ifdef SUIDROOT
- (void) chmod(wp->tty, 0666);
- (void) chown(wp->tty, 0, 0);
- #endif
- close(wp->ptyfd);
- if (wp->logfp != NULL)
- fclose(wp->logfp);
- ChangeWindowSize(wp, 0, 0);
- Free(wp);
- }
-
- int
- MakeWindow(prog, args, aflag, flowflag, StartAt, dir, lflag, histheight, term)
- char *prog, **args, *dir;
- int aflag, flowflag, StartAt, lflag, histheight;
- char *term; /* if term is nonzero we assume it "vt100" or the like.. */
- {
- register struct win **pp, *p;
- register int n, f;
- int tf, tlflag;
- char ebuf[10];
- #ifndef TIOCSWINSZ
- char libuf[20], cobuf[20];
- #endif
- char tebuf[25];
-
- pp = wtab + StartAt;
- do
- {
- if (*pp == 0)
- break;
- if (++pp == wtab + MAXWIN)
- pp = wtab;
- } while (pp != wtab + StartAt);
- if (*pp)
- {
- Msg(0, "No more windows.");
- return -1;
- }
-
- if (((tlflag = lflag) == -1) && ((tlflag = loginflag) == -1))
- tlflag = LOGINDEFAULT;
-
- #ifdef USRLIMIT
- /*
- * Count current number of users, if logging windows in.
- */
- if (tlflag == 1 && CountUsers() >= USRLIMIT)
- {
- Msg(0, "User limit reached. Window will not be logged in.");
- tlflag = 0;
- }
- #endif
- n = pp - wtab;
- debug1("Makewin creating %d\n", n);
- if ((f = OpenPTY()) == -1)
- {
- Msg(0, "No more PTYs.");
- return -1;
- }
- #ifdef SYSV
- (void) fcntl(f, F_SETFL, O_NDELAY);
- #else
- (void) fcntl(f, F_SETFL, FNDELAY);
- #endif
- #ifdef TIOCPKT
- {
- # ifdef sgi
- /*
- * on IRIX 3.3, regardless of stream head's read mode (RNORM/RMSGN/RMSGD)
- * we loose data in TIOCPKT mode if our buffer is too small (IOSIZE)
- * to hold the whole packet at first read().
- * (Marc Boucher)
- */
- int flag = 0;
- # else /* sgi */
- int flag = 1;
- # endif /* sgi */
-
- if (ioctl(f, TIOCPKT, &flag))
- {
- Msg(errno, "TIOCPKT ioctl");
- close(f);
- return -1;
- }
- }
- #endif
- if ((p = (struct win *) malloc(sizeof(struct win))) == 0)
- {
- close(f);
- Msg_nomem;
- return -1;
- }
- bzero((char *) p, (int) sizeof(struct win));
- p->ptyfd = f;
- p->aflag = aflag;
- if (flowflag < 0)
- flowflag = default_flow;
- p->flow = flowflag | ((flowflag & FLOW_AUTOFLAG) ? (FLOW_AUTO|FLOW_NOW) : FLOW_AUTO);
- if (!prog)
- prog = Filename(args[0]);
- strncpy(p->cmd, prog, MAXSTR - 1);
- if ((prog = rindex(p->cmd, '|')) != NULL)
- {
- *prog++ = '\0';
- prog += strlen(prog);
- p->akapos = prog - p->cmd;
- p->autoaka = 0;
- }
- else
- p->akapos = 0;
- p->monitor = default_monitor;
- p->norefresh = 0;
- strncpy(p->tty, TtyName, MAXSTR - 1);
- #ifdef SUIDROOT
- (void) chown(TtyName, real_uid, real_gid);
- # ifdef UTMPOK
- (void) chmod(TtyName, tlflag ? TtyMode : (TtyMode & ~022));
- # else
- (void) chmod(TtyName, TtyMode);
- # endif
- #endif
-
- if (histheight < 0)
- histheight = default_histheight;
- if (ChangeWindowSize(p, default_width, default_height))
- {
- FreeWindow(p);
- return -1;
- }
- ChangeScrollback(p, histheight, default_width);
- ResetScreen(p);
- debug("forking...\n");
- switch (p->wpid = fork())
- {
- case -1:
- Msg(errno, "fork");
- FreeWindow(p);
- return -1;
- case 0:
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- #ifdef BSDJOBS
- signal(SIGTTIN, SIG_DFL);
- signal(SIGTTOU, SIG_DFL);
- #endif
- setuid(real_uid);
- setgid(real_gid);
- if (dir && chdir(dir) == -1)
- {
- SendErrorMsg("Cannot chdir to %s: %s", dir, sys_errlist[errno]);
- eexit(1);
- }
-
- freetty();
- if ((tf = open(TtyName, O_RDWR)) == -1)
- {
- SendErrorMsg("Cannot open %s: %s", TtyName, sys_errlist[errno]);
- eexit(1);
- }
- #ifdef SVR4
- if (ioctl(tf, I_PUSH, "ptem"))
- {
- SendErrorMsg("Cannot I_PUSH ptem %s %s", TtyName, sys_errlist[errno]);
- eexit(1);
- }
- if (ioctl(tf, I_PUSH, "ldterm"))
- {
- SendErrorMsg("Cannot I_PUSH ldterm %s %s", TtyName, sys_errlist[errno]);
- eexit(1);
- }
- if (ioctl(tf, I_PUSH, "ttcompat"))
- {
- SendErrorMsg("Cannot I_PUSH ttcompat %s %s", TtyName, sys_errlist[errno]);
- eexit(1);
- }
- #endif
- (void) dup2(tf, 0);
- (void) dup2(tf, 1);
- (void) dup2(tf, 2);
- #ifdef DEBUG
- dfp = stderr;
- #endif
- closeallfiles();
- fgtty();
- #ifdef TIOCSWINSZ
- glwz.ws_col = p->width;
- glwz.ws_row = p->height;
- (void) ioctl(0, TIOCSWINSZ, &glwz);
- #else
- sprintf(libuf, "LINES=%d", p->height);
- sprintf(cobuf, "COLUMNS=%d", p->width);
- NewEnv[4] = libuf;
- NewEnv[5] = cobuf;
- #endif
- SetTTY(0, &OldMode);
- if (aflag)
- NewEnv[2] = MakeTermcap(1);
- else
- NewEnv[2] = Termcap;
- if (term && *term && strcmp(screenterm, term) &&
- (strlen(term) < 20))
- {
- char *s1, *s2, tl;
-
- sprintf(tebuf, "TERM=%s", term);
- debug2("Makewindow %d with %s\n", n, tebuf);
- tl = strlen(term);
- NewEnv[1] = tebuf;
- if (s1 = index(Termcap, '|'))
- {
- if (s2 = index(++s1, '|'))
- {
- if (strlen(Termcap) - (s2 - s1) + tl < 1024)
- {
- bcopy(s2, s1 + tl, strlen(s2) + 1);
- bcopy(term, s1, tl);
- }
- }
- }
- }
- sprintf(ebuf, "WINDOW=%d", n);
- NewEnv[3] = ebuf;
-
- execvpe(*args, args, NewEnv);
- SendErrorMsg("Cannot exec %s: %s", *args, sys_errlist[errno]);
- exit(1);
- } /* end fork switch */
- /*
- * Place the newly created window at the head of the most-recently-used list.
- */
- *pp = p;
- p->WinLink = WinList;
- WinList = n;
- HasWindow = 1;
- #ifdef UTMPOK
- debug1("MakeWindow will %slog in.\n", tlflag?"":"not ");
- if (tlflag == 1)
- SetUtmp(p, n);
- else
- p->slot = (slot_t) -1;
- #endif
- SetForeWindow(n);
- Activate(0);
- return n;
- }
-
- static void execvpe(prog, args, env)
- char *prog, **args, **env;
- {
- register char *path, *p;
- char buf[1024];
- char *shargs[MAXARGS + 1];
- register int i, eaccess = 0;
-
- if (prog[0] == '/')
- path = "";
- else if ((path = getenv("PATH")) == 0)
- path = DefaultPath;
- do
- {
- p = buf;
- while (*path && *path != ':')
- *p++ = *path++;
- if (p > buf)
- *p++ = '/';
- strcpy(p, prog);
- if (*path)
- ++path;
- execve(buf, args, env);
- switch (errno)
- {
- case ENOEXEC:
- shargs[0] = DefaultShell;
- shargs[1] = buf;
- for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i)
- ;
- execve(DefaultShell, shargs, env);
- return;
- case EACCES:
- eaccess = 1;
- break;
- case ENOMEM:
- case E2BIG:
- case ETXTBSY:
- return;
- }
- } while (*path);
- if (eaccess)
- errno = EACCES;
- }
-
-
- static void LogToggle()
- {
- char buf[1024];
-
- sprintf(buf, "screenlog.%d", ForeNum);
- if (fore->logfp != NULL)
- {
- Msg(0, "Logfile \"%s\" closed.", buf);
- fclose(fore->logfp);
- fore->logfp = NULL;
- return;
- }
- if ((fore->logfp = secfopen(buf, "a")) == NULL)
- {
- Msg(errno, "Error opening logfile \"%s\"", buf);
- return;
- }
- Msg(0, "%s logfile \"%s\"", ftell(fore->logfp) ? "Appending to" : "Creating", buf);
- }
-
- #ifdef NOREUID
- static int UserPID;
- static sig_t (*Usersigcld)__P(SIGPROTOARG);
- #endif
- static int UserSTAT;
-
- int UserContext()
- {
- #ifdef NOREUID
- if (eff_uid == real_uid)
- return(1);
- # ifdef SYSV
- Usersigcld = signal(SIGCLD, SIG_DFL);
- # else
- Usersigcld = signal(SIGCHLD, SIG_DFL);
- # endif
- debug("UserContext: forking.\n");
- switch (UserPID = fork())
- {
- case -1:
- Msg(errno, "fork");
- return -1;
- case 0:
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- # ifdef BSDJOBS
- signal(SIGTTIN, SIG_DFL);
- signal(SIGTTOU, SIG_DFL);
- # endif
- setuid(real_uid);
- setgid(real_gid);
- return 1;
- default:
- return 0;
- }
- #else
- setreuid(eff_uid, real_uid);
- setregid(eff_gid, real_gid);
- return 1;
- #endif
- }
-
- void
- UserReturn(val)
- int val;
- {
- #if defined(NOREUID)
- if (eff_uid == real_uid)
- UserSTAT = val;
- else
- exit(val);
- #else
- setreuid(real_uid, eff_uid);
- setregid(real_gid, eff_gid);
- UserSTAT = val;
- #endif
- }
-
- int UserStatus()
- {
- #ifdef NOREUID
- int i;
- # ifdef BSDWAIT
- union wait wstat;
- # else
- int wstat;
- # endif
-
- if (eff_uid == real_uid)
- return UserSTAT;
- if (UserPID < 0)
- return -1;
- while ((errno = 0, i = wait(&wstat)) != UserPID)
- if (i < 0 && errno != EINTR)
- break;
- # ifdef SYSV
- (void) signal(SIGCLD, Usersigcld);
- # else
- (void) signal(SIGCHLD, Usersigcld);
- # endif
- if (i == -1)
- return -1;
- return (WEXITSTATUS(wstat));
- #else
- return UserSTAT;
- #endif
- }
-
- static void ShowWindows()
- {
- char buf[1024];
- register char *s;
- register struct win **pp, *p;
- register int i, OtherNum = fore->WinLink;
- register char *cmd;
-
- for (i = 0, s = buf, pp = wtab; pp < wtab + MAXWIN; ++i, ++pp)
- {
- if ((p = *pp) == 0)
- continue;
-
- if (p->akapos)
- {
- if (*(p->cmd + p->akapos) && *(p->cmd + p->akapos - 1) != ':')
- cmd = p->cmd + p->akapos;
- else
- cmd = p->cmd + strlen(p->cmd) + 1;
- }
- else
- cmd = p->cmd;
- if (s - buf + 5 + strlen(cmd) > fore->width - 1)
- break;
- if (s > buf)
- {
- *s++ = ' ';
- *s++ = ' ';
- }
- *s++ = i + '0';
- if (i == ForeNum)
- *s++ = '*';
- else if (i == OtherNum)
- *s++ = '-';
- if (p->monitor == MON_DONE)
- *s++ = '@';
- if (p->bell == BELL_DONE)
- *s++ = '!';
- #ifdef UTMPOK
- if (p->slot != (slot_t) 0 && p->slot != (slot_t) -1)
- *s++ = '$';
- #endif
- if (p->logfp != NULL)
- {
- strcpy(s, "(L)");
- s += 3;
- }
- *s++ = ' ';
- strcpy(s, cmd);
- s += strlen(s);
- if (i == ForeNum)
- {
- /*
- * this is usually done by Activate(), but when looking
- * on your current window, you may get annoyed, as there is still
- * that temporal '!' and '@' displayed.
- * So we remove that after displaying it once.
- */
- p->bell = BELL_OFF;
- if (p->monitor != MON_OFF)
- p->monitor = MON_ON;
- }
- }
- *s++ = ' ';
- *s = '\0';
- Msg(0, "%s", buf);
- }
-
- static void ShowTime()
- {
- char buf[512];
- struct tm *tp;
- time_t now;
-
- (void) time(&now);
- tp = localtime(&now);
- sprintf(buf, "%2d:%02.2d:%02.2d %s", tp->tm_hour, tp->tm_min, tp->tm_sec,
- HostName);
- {
- static int loads = 0;
- double loadav[3];
- int n;
-
- if (loads >= 0) /* If it failed, don't try again. */
- {
- loads = getloadavg(loadav, 3);
- for (n = 0; n < loads; n++)
- {
- char *p = buf + strlen(buf);
- sprintf(p, " %2.2f", loadav[n]);
- }
- }
- }
- Msg(0, "%s", buf);
- }
-
- static void ShowInfo()
- {
- char buf[512], *p;
- register struct win *wp = fore;
- register int i;
-
- sprintf(buf, "(%d,%d)/(%d,%d)+%d %c%sflow %cins %corg %cwrap %capp %clog %cmon %cr",
- wp->x + 1, wp->y + 1, wp->width, wp->height,
- wp->histheight,
- (wp->flow & FLOW_NOW) ? '+' : '-',
- (wp->flow & FLOW_AUTOFLAG) ? "" : ((wp->flow & FLOW_AUTO) ? "(+)" : "(-)"),
- wp->insert ? '+' : '-', wp->origin ? '+' : '-',
- wp->wrap ? '+' : '-', wp->keypad ? '+' : '-',
- (wp->logfp != NULL) ? '+' : '-',
- (wp->monitor != MON_OFF) ? '+' : '-',
- wp->norefresh ? '-' : '+');
- if (ISO2022)
- {
- p = buf + strlen(buf);
- sprintf(p, " G%1d [", wp->LocalCharset);
- for (i = 0; i < 4; i++)
- p[i + 5] = wp->charsets[i] ? wp->charsets[i] : 'B';
- p[9] = ']';
- p[10] = '\0';
- }
- Msg(0, "%s", buf);
- }
-
- #if defined(sequent) || defined(_SEQUENT_) || defined(SVR4)
-
- static int OpenPTY()
- {
- char *m, *s;
- register int f;
- # ifdef SVR4
- char *ptsname();
- sig_t (*sigcld)();
-
- if ((f = open("/dev/ptmx", O_RDWR)) == -1)
- return(-1);
-
- /*
- * SIGCLD set to SIG_DFL for grantpt() because it fork()s and
- * exec()s pt_chmod
- */
- sigcld = signal(SIGCLD, SIG_DFL);
-
- if ((m = ptsname(f)) == NULL || unlockpt(f) || grantpt(f))
- {
- signal(SIGCLD, sigcld);
- close(f);
- return(-1);
- }
- signal(SIGCLD, sigcld);
- strncpy(TtyName, m, sizeof TtyName);
- # else /* SVR4 */
- if ((f = getpseudotty(&s, &m)) < 0)
- return(-1);
- strncpy(PtyName, m, sizeof PtyName);
- strncpy(TtyName, s, sizeof TtyName);
- # endif /* SVR4 */
- # ifdef POSIX
- tcflush(f, TCIOFLUSH);
- # else
- (void) ioctl(f, TIOCFLUSH, (char *) 0);
- # endif
- # ifdef LOCKPTY
- (void) ioctl(f, TIOCEXCL, (char *) 0);
- # endif
- return (f);
- }
-
- #else /* defined(sequent) || defined(_SEQUENT_) || defined(SVR4) */
- # ifdef MIPS
-
- static int OpenPTY()
- {
- register char *p, *l, *d;
- register f, tf;
- register my_minor;
- struct stat buf;
-
- strcpy(PtyName, PtyProto);
- for (p = PtyName; *p != 'X'; ++p)
- ;
- for (l = PTY_FIRST_CHARS; *p = *l; ++l)
- {
- for (d = PTY_SECOND_CHARS; p[1] = *d; ++d)
- {
- if ((f = open(PtyName, O_RDWR)) != -1)
- {
- fstat(f, &buf);
- my_minor = minor(buf.st_rdev);
- sprintf(TtyName, "/dev/ttyq%d", my_minor);
- if ((tf = open(TtyName, O_RDWR)) != -1)
- {
- close(tf);
- #ifdef LOCKPTY
- (void) ioctl(f, TIOCEXCL, (char *)0);
- #endif
- return f;
- }
- close(f);
- }
- }
- }
- return -1;
- }
-
- # else /* MIPS */
- # ifdef sgi
-
- static int OpenPTY()
- {
- register f;
- register my_minor;
- struct stat buf;
-
- strcpy(PtyName, "/dev/ptc");
- f = open(PtyName, O_RDWR|O_NDELAY);
- if (f >= 0)
- {
- if (fstat(f, &buf) < 0)
- {
- close(f);
- return -1;
- }
- my_minor = minor(buf.st_rdev);
- sprintf(TtyName, "/dev/ttyq%d", my_minor);
- }
- return f;
- }
-
- # else /* sgi */
- # ifdef _AIX /* RS6000 */
-
- static int OpenPTY()
- {
- register int i, f, tf;
-
- strcpy (PtyName, "/dev/ptc");
- if ((f = open (PtyName, O_RDWR)) != -1)
- {
- strcpy (TtyName, ttyname (f));
- strcpy (PtyName, TtyName);
- PtyName [7] = 'c';
- #ifdef LOCKPTY
- if (ioctl (f, TIOCEXCL, (char *) 0) == -1)
- return -1;
- #endif
- if ((tf = open (TtyName, O_RDWR)) != -1)
- {
- close (tf);
- return f;
- }
- close (f);
- }
- return -1;
- }
-
- # else /* _AIX, RS6000 */
-
- static int OpenPTY()
- {
- register char *p, *q, *l, *d;
- register int f, tf;
-
- # if !defined(hpux)
- debug("Hello, You are none of: sequent, _SEQUENT_, SVR4, MIPS, sgi, AIX\n");
- debug(" This OpenPTY() is for hpux, ... and for you?\n");
- # endif
- strcpy(PtyName, PtyProto);
- strcpy(TtyName, TtyProto);
- for (p = PtyName; *p != 'X'; ++p)
- ;
- for (q = TtyName; *q != 'X'; ++q)
- ;
- for (l = PTY_FIRST_CHARS; (*p = *l) != '\0'; ++l)
- {
- for (d = PTY_SECOND_CHARS; (p[1] = *d) != '\0'; ++d)
- {
- if ((f = open(PtyName, O_RDWR)) != -1)
- {
- q[0] = *l;
- q[1] = *d;
- if ((tf = open(TtyName, O_RDWR)) != -1)
- {
- /* close tf, thus we also get rid of an unwanted
- * controlling terminal!
- */
- close(tf);
- #ifdef LOCKPTY
- (void) ioctl(f, TIOCEXCL, (char *) 0);
- #endif
- return f;
- }
- close(f);
- }
- }
- }
- return -1;
- }
-
- # endif /* _AIX, RS6000 */
- # endif /* sgi */
- # endif /* MIPS */
- #endif
-
- void
- SetTTY(fd, mp)
- int fd;
- struct mode *mp;
- {
- errno = 0;
- #ifdef POSIX
- tcsetattr(fd, TCSADRAIN, &mp->tio);
- # ifdef hpux
- ioctl(fd, TIOCSLTC, &mp->m_ltchars);
- # endif
- #else
- # ifdef TERMIO
- ioctl(fd, TCSETA, &mp->tio);
- # else
- /* ioctl(fd, TIOCSETP, &mp->m_ttyb); */
- ioctl(fd, TIOCSETC, &mp->m_tchars);
- ioctl(fd, TIOCSLTC, &mp->m_ltchars);
- ioctl(fd, TIOCLSET, &mp->m_lmode);
- ioctl(fd, TIOCSETD, &mp->m_ldisc);
- ioctl(fd, TIOCSETP, &mp->m_ttyb);
- # endif
- #endif
- if (errno)
- Msg(0, "SetTTY: ioctl failed");
- }
-
- void
- GetTTY(fd, mp)
- int fd;
- struct mode *mp;
- {
- errno = 0;
- #ifdef POSIX
- tcgetattr(fd, &mp->tio);
- # ifdef hpux
- ioctl(fd, TIOCGLTC, &mp->m_ltchars);
- # endif
- #else
- # ifdef TERMIO
- ioctl(fd, TCGETA, &mp->tio);
- # else
- ioctl(fd, TIOCGETP, &mp->m_ttyb);
- ioctl(fd, TIOCGETC, &mp->m_tchars);
- ioctl(fd, TIOCGLTC, &mp->m_ltchars);
- ioctl(fd, TIOCLGET, &mp->m_lmode);
- ioctl(fd, TIOCGETD, &mp->m_ldisc);
- # endif
- #endif
- if (errno)
- Msg(0, "GetTTY: ioctl failed");
- }
-
- void
- SetMode(op, np)
- struct mode *op, *np;
- {
- *np = *op;
-
- #if defined(TERMIO) || defined(POSIX)
- np->tio.c_iflag &= ~ICRNL;
- # ifdef ONLCR
- np->tio.c_oflag &= ~ONLCR;
- # endif
- np->tio.c_lflag &= ~(ICANON | ECHO);
-
- /*
- * Unfortunately, the master process never will get SIGINT if the real
- * terminal is different from the one on which it was originaly started
- * (process group membership has not been restored or the new tty could not
- * be made controlling again). In my solution, it is the attacher who
- * receives SIGINT (because it is always correctly associated with the real
- * tty) and forwards it to the master [kill(MasterPid, SIGINT)].
- * Marc Boucher (marc@CAM.ORG)
- */
- np->tio.c_lflag |= ISIG;
- /*
- * careful, careful catche monkey..
- * never set VMIN and VTIME to zero, if you want blocking io.
- */
- np->tio.c_cc[VMIN] = 1;
- np->tio.c_cc[VTIME] = 0;
- #ifdef VSTART
- startc = op->tio.c_cc[VSTART];
- #endif
- #ifdef VSTOP
- stopc = op->tio.c_cc[VSTOP];
- #endif
- if (iflag)
- intrc = op->tio.c_cc[VINTR];
- else
- intrc = np->tio.c_cc[VINTR] = 0377;
- np->tio.c_cc[VQUIT] = 0377;
- if (flow == 0)
- {
- np->tio.c_cc[VINTR] = 0377;
- #ifdef VSTART
- np->tio.c_cc[VSTART] = 0377;
- #endif
- #ifdef VSTOP
- np->tio.c_cc[VSTOP] = 0377;
- #endif
- np->tio.c_iflag &= ~IXON;
- }
- #ifdef VDISCARD
- np->tio.c_cc[VDISCARD] = 0377;
- #endif
- #ifdef VSUSP
- np->tio.c_cc[VSUSP] = 0377;
- #endif
- # ifdef hpux
- np->m_ltchars.t_suspc = 0377;
- np->m_ltchars.t_dsuspc = 0377;
- np->m_ltchars.t_flushc = 0377;
- np->m_ltchars.t_lnextc = 0377;
- # else
- # ifdef VDSUSP
- np->tio.c_cc[VDSUSP] = 0377;
- # endif
- # endif
- #else
- startc = op->m_tchars.t_startc;
- stopc = op->m_tchars.t_stopc;
- if (iflag)
- intrc = op->m_tchars.t_intrc;
- else
- intrc = np->m_tchars.t_intrc = -1;
- np->m_ttyb.sg_flags &= ~(CRMOD | ECHO);
- np->m_ttyb.sg_flags |= CBREAK;
- np->m_tchars.t_quitc = -1;
- if (flow == 0)
- {
- np->m_tchars.t_intrc = -1;
- np->m_tchars.t_startc = -1;
- np->m_tchars.t_stopc = -1;
- }
- np->m_ltchars.t_suspc = -1;
- np->m_ltchars.t_dsuspc = -1;
- np->m_ltchars.t_flushc = -1;
- np->m_ltchars.t_lnextc = -1;
- #endif /* defined(TERMIO) || defined(POSIX) */
- }
-
- void
- SetFlow(on)
- int on;
- {
- if (flow == on)
- return;
- #if defined(TERMIO) || defined(POSIX)
- if (on)
- {
- NewMode.tio.c_cc[VINTR] = intrc;
- #ifdef VSTART
- NewMode.tio.c_cc[VSTART] = startc;
- #endif
- #ifdef VSTOP
- NewMode.tio.c_cc[VSTOP] = stopc;
- #endif
- NewMode.tio.c_iflag |= IXON;
- }
- else
- {
- NewMode.tio.c_cc[VINTR] = 0377;
- #ifdef VSTART
- NewMode.tio.c_cc[VSTART] = 0377;
- #endif
- #ifdef VSTOP
- NewMode.tio.c_cc[VSTOP] = 0377;
- #endif
- NewMode.tio.c_iflag &= ~IXON;
- }
- # ifdef POSIX
- if (tcsetattr(0, TCSADRAIN, &NewMode.tio))
- # else
- if (ioctl(0, TCSETA, &NewMode.tio) != 0)
- # endif
- debug1("SetFlow: ioctl errno %d\n", errno);
- #else
- if (on)
- {
- NewMode.m_tchars.t_intrc = intrc;
- NewMode.m_tchars.t_startc = startc;
- NewMode.m_tchars.t_stopc = stopc;
- }
- else
- {
- NewMode.m_tchars.t_intrc = -1;
- NewMode.m_tchars.t_startc = -1;
- NewMode.m_tchars.t_stopc = -1;
- }
- if (ioctl(0, TIOCSETC, &NewMode.m_tchars) != 0)
- debug1("SetFlow: ioctl errno %d\n", errno);
- #endif /* defined(TERMIO) || defined(POSIX) */
- flow = on;
- }
-
- /* we return 1 if we could attach one, or 0 if none */
- static int Attach(how)
- int how;
- {
- int lasts;
- struct msg m;
- struct stat st;
- char *s;
-
- if (how == MSG_WINCH)
- {
- bzero((char *) &m, sizeof(m));
- m.type = how;
- if ((lasts = MakeClientSocket(0, SockName)) >= 0)
- {
- write(lasts, &m, sizeof(m));
- close(lasts);
- }
- return 0;
- }
-
- if (how == MSG_CONT)
- {
- if ((lasts = MakeClientSocket(0, SockName)) < 0)
- {
- printf("Sorry, cannot contact session \"%s\" again\r\n",
- SockName);
- sleep(2);
- how = MSG_ATTACH;
- }
- }
-
- if (how != MSG_CONT)
- {
- switch (FindSocket(how, &lasts))
- {
- case 0:
- if (rflag == 2)
- return 0;
- if (quietflag)
- eexit(10);
- if (SockName && *SockName)
- Msg(0, "There is no screen to be %sed matching %s.",
- dflag ? "detach" : "resum", SockName);
- else
- Msg(0, "There is no screen to be %sed.",
- dflag ? "detach" : "resum");
- /* NOTREACHED */
- case 1:
- break;
- default:
- Msg(0, "Type \"screen [-d] -r [pid.]tty.host\" to resume one of them.");
- /* NOTREACHED */
- }
- /*
- * Go in UserContext. Advantage is, you can kill your attacher
- * when things go wrong. Any disadvantages? jw.
- */
- setuid(real_uid);
- setgid(real_gid);
-
- SockName = SockNamePtr;
- MasterPid = 0;
- while (*SockName)
- {
- if (*SockName > '9' || *SockName < '0')
- break;
- MasterPid = 10 * MasterPid + *SockName - '0';
- SockName++;
- }
- SockName = SockNamePtr;
- debug1("Attach decided, it is '%s'\n", SockPath);
- debug1("Attach found MasterPid == %d\n", MasterPid);
- if (stat(SockPath, &st) == -1)
- Msg(errno, "stat %s", SockPath);
- if ((st.st_mode & 0700) != (dflag ? 0700 : 0600))
- Msg(0, "That screen is %sdetached.", dflag ? "already " : "not ");
- #ifdef REMOTE_DETACH
- if (dflag &&
- (how == MSG_ATTACH || how == MSG_DETACH || how == MSG_POW_DETACH))
- {
- strcpy(m.m.detach.tty, attach_tty);
- debug1("attach_tty is %s\n", attach_tty);
- m.m.detach.dpid = getpid();
- # ifdef POW_DETACH
- if (dflag == 2)
- m.type = MSG_POW_DETACH;
- else
- # endif
- m.type = MSG_DETACH;
- if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m))
- Msg(errno, "write");
- close(lasts);
- if (how != MSG_ATTACH)
- return 0; /* we detached it. jw. */
- sleep(1); /* we dont want to overrun our poor backend. jw. */
- if ((lasts = MakeClientSocket(0, SockName)) == -1)
- Msg(0, "Cannot contact screen again. Shit.");
- }
- #endif
- }
- m.type = how;
- strcpy(m.m.attach.tty, attach_tty);
- debug1("attach_tty is %s\n", attach_tty);
- s = getenv("TERM");
- if (s)
- {
- if (strlen(s) >= MAXPATH - 5)
- Msg(0, "$TERM too long - sorry.");
- sprintf(m.m.attach.envterm, "TERM=%s", s);
- }
- else
- *m.m.attach.envterm = '\0';
- debug1("attach: sending %d bytes... ", sizeof m);
-
- m.m.attach.apid = getpid();
- m.m.attach.adaptflag = adaptflag;
- m.m.attach.lines = m.m.attach.columns = 0;
- if (s = getenv("LINES"))
- m.m.attach.lines = atoi(s);
- if (s = getenv("COLUMNS"))
- m.m.attach.columns = atoi(s);
-
- #ifdef PASSWORD
- if (how == MSG_ATTACH || how == MSG_CONT)
- trysend(lasts, &m, m.m.attach.password);
- else
- #endif
- {
- if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m))
- Msg(errno, "write");
- close(lasts);
- }
- debug1("Attach(%d): sent\n", m.type);
- Suspended = 0;
- rflag = 0;
- return 1;
- }
-
-
- #ifdef PASSWORD
-
- static trysendstat;
-
- static sig_t trysendok(SIGDEFARG)
- {
- trysendstat = 1;
- }
-
- static sig_t trysendfail(SIGDEFARG)
- {
- trysendstat = -1;
- # ifdef SYSV
- signal(SIG_PW_FAIL, trysendfail);
- # endif /* SYSV */
- }
-
- static char screenpw[9];
-
- static void trysend(fd, m, pwto)
- int fd;
- struct msg *m;
- char *pwto;
- {
- char *npw = NULL;
- sig_t (*sighup)();
- sig_t (*sigusr1)();
- int tries;
-
- sigusr1 = signal(SIG_PW_OK, trysendok);
- sighup = signal(SIG_PW_FAIL, trysendfail);
- for (tries = 0; ; )
- {
- strcpy(pwto, screenpw);
- trysendstat = 0;
- if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m))
- Msg(errno, "write");
- close(fd);
- while (trysendstat == 0)
- pause();
- if (trysendstat > 0)
- {
- signal(SIG_PW_OK, sigusr1);
- signal(SIG_PW_FAIL, sighup);
- return;
- }
- if (++tries > 1 || (npw = getpass("Screen Password:")) == 0 || *npw == 0)
- Msg(0, "Password incorrect");
- strncpy(screenpw, npw, 8);
- if ((fd = MakeClientSocket(0, SockName)) == -1)
- Msg(0, "Cannot contact screen again. Shit.");
- }
- }
- #endif /* PASSWORD */
-
-
- /*
- * Unfortunatelly this is also the SIGHUP handler, so we have to
- * check, if the backend is already detached.
- */
-
- static sig_t AttacherFinit(SIGDEFARG)
- {
- struct stat statb;
- struct msg m;
- int s;
-
- debug("AttacherFinit();\n");
- signal(SIGHUP, SIG_IGN);
- /* Check if signal comes from backend */
- if (SockName)
- {
- strcpy(SockNamePtr, SockName);
- if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600)
- {
- debug("Detaching backend!\n");
- bzero((char *) &m, sizeof(m));
- strcpy(m.m.detach.tty, attach_tty);
- debug1("attach_tty is %s\n", attach_tty);
- m.m.detach.dpid = getpid();
- m.type = MSG_HANGUP;
- if ((s = MakeClientSocket(0, SockName)) >= 0)
- {
- write(s, &m, sizeof(m));
- close(s);
- }
- }
- }
- exit(0);
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
-
- #ifdef POW_DETACH
- static sig_t AttacherFinitBye(SIGDEFARG)
- {
- int ppid;
- debug("AttacherFintBye()\n");
- freetty();
- setuid(real_uid);
- setgid(real_gid);
- /* we don't want to disturb init (even if we were root), eh? jw */
- if ((ppid = getppid()) > 1)
- Kill(ppid, SIGHUP); /* carefully say good bye. jw. */
- exit(0);
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
- #endif
-
- static SuspendPlease;
-
- static sig_t SigStop(SIGDEFARG)
- {
- debug("SigStop()\n");
- SuspendPlease = 1;
- #ifndef SIGVOID
- return((sig_t) 0);
- #endif
- }
-
- #ifdef LOCK
- static LockPlease;
-
- static sig_t DoLock(SIGDEFARG)
- {
- debug("DoLock()\n");
- LockPlease = 1;
- # ifdef SYSV
- signal(SIG_LOCK, DoLock);
- # endif
- # ifndef SIGVOID
- return((sig_t) 0);
- # endif
- }
- #endif
-
- #if defined(SIGWINCH) && defined(TIOCGWINSZ)
- static SigWinchPlease;
-
- static sig_t SigAttWinch(SIGDEFARG)
- {
- debug("SigAttWinch()\n");
- SigWinchPlease = 1;
- # ifndef SIGVOID
- return((sig_t) 0);
- # endif
- }
- #endif
-
- static void Attacher()
- {
- /*
- * permanent in UserContext. Advantage is, you can kill your attacher
- * when things go wrong. Any disadvantages? jw.
- */
- setuid(real_uid); /* XXX: already done in Attach() */
- setgid(real_gid); /* XXX: already done in Attach() */
-
- signal(SIGHUP, AttacherFinit);
- signal(SIG_BYE, AttacherFinit);
- #ifdef POW_DETACH
- signal(SIG_POWER_BYE, AttacherFinitBye);
- #endif
- #ifdef LOCK
- signal(SIG_LOCK, DoLock);
- #endif
- signal(SIGINT, AttacherSigInt);
- #ifdef BSDJOBS
- signal(SIG_STOP, SigStop);
- #endif
- #if defined(SIGWINCH) && defined(TIOCGWINSZ)
- signal(SIGWINCH, SigAttWinch);
- #endif
- #ifdef DEBUG
- # ifdef SYSV
- signal(SIGCLD, FEChld);
- # else
- signal(SIGCHLD, FEChld);
- # endif
- #endif
- debug("attacher: going for a nap.\n");
- dflag = 0;
- while (1)
- {
- pause();
- debug("attacher: huh! a signal!\n");
- #ifdef DEBUG
- if (FEpanic)
- {
- printf("\n\rSuddenly the Dungeon collapses!! - You die...\n\r");
- SetTTY(0, &OldMode);
- eexit(1);
- }
- #endif
- #ifdef BSDJOBS
- if (SuspendPlease)
- {
- SuspendPlease = 0;
- signal(SIGTSTP, SIG_DFL);
- debug("attacher: killing myself SIGTSTP\n");
- kill(getpid(), SIGTSTP);
-
- debug1("attacher: continuing from stop(%d)\n", Suspended);
- signal(SIG_STOP, SigStop);
- (void) Attach(MSG_CONT);
- }
- #endif
- #ifdef LOCK
- if (LockPlease)
- {
- LockPlease = 0;
- LockTerminal();
- # ifdef SYSV
- signal(SIG_LOCK, DoLock);
- # endif
- (void) Attach(MSG_CONT);
- }
- #endif /* LOCK */
- #if defined(SIGWINCH) && defined(TIOCGWINSZ)
- if (SigWinchPlease)
- {
- SigWinchPlease = 0;
- # ifdef SYSV
- signal(SIGWINCH, SigAttWinch);
- # endif
- (void) Attach(MSG_WINCH);
- }
- #endif /* SIGWINCH */
- }
- }
-
- #ifdef LOCK
-
- /* ADDED by Rainer Pruy 10/15/87 */
- /* POLISHED by mls. 03/10/91 */
-
- static char LockEnd[] = "Welcome back to screen !!\n";
-
- static void LockTerminal()
- {
- char *prg;
- int sig, pid;
- sig_t (*sigs[NSIG])__P(SIGPROTOARG);
-
- for (sig = 1; sig < NSIG; sig++)
- {
- sigs[sig] = signal(sig, SIG_IGN);
- }
- SetTTY(0, &OldMode);
- printf("\n");
-
- prg = getenv("LOCKPRG");
- if (prg && strcmp(prg, "builtin") && !access(prg, X_OK))
- {
- # ifdef SYSV
- signal(SIGCLD, SIG_DFL);
- # else /* SYSV */
- signal(SIGCHLD, SIG_DFL);
- # endif /* SYSV */
- debug1("lockterminal: '%s' seems executable, execl it!\n", prg);
- if ((pid = fork()) == 0)
- {
- /* Child */
- setuid(real_uid); /* this should be done already */
- setgid(real_gid);
- closeallfiles(); /* important: /etc/shadow may be open */
- execl(prg, "SCREEN-LOCK", NULL);
- exit(errno);
- }
- if (pid == -1)
- {
- #ifdef NETHACK
- if (nethackflag)
- Msg(errno, "Cannot fork terminal - lock failed");
- else
- #endif
- Msg(errno, "Cannot lock terminal - fork failed");
- }
- else
- {
- #ifdef BSDWAIT
- union wait wstat;
- #else
- int wstat;
- #endif
- int wret;
-
- #ifdef hpux
- signal(SIGCLD, SIG_DFL);
- #endif
- errno = 0;
- while (((wret = wait((int *) &wstat)) != pid) ||
- ((wret == -1) && (errno == EINTR))
- )
- errno = 0;
-
- if (errno)
- {
- perror("Lock");
- sleep(2);
- }
- else if (WTERMSIG(wstat) != 0)
- {
- fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg,
- WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : "");
- sleep(2);
- }
- else if (WEXITSTATUS(wstat))
- {
- debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat));
- }
- else
- printf(LockEnd);
- }
- }
- else
- {
- if (prg)
- {
- debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg);
- }
- else
- {
- debug("lockterminal: using buitin.\n");
- }
- screen_builtin_lck();
- }
- /* reset signals */
- for (sig = 1; sig < NSIG; sig++)
- {
- if (sigs[sig] != (sig_t(*) ()) - 1)
- signal(sig, sigs[sig]);
- }
- } /* LockTerminal */
-
- /* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */
- void
- screen_builtin_lck()
- {
- char fullname[100], *cp1, message[BUFSIZ];
- char c, *pass, mypass[9];
- #ifdef SHADOWPW
- struct spwd *sss = NULL;
- #endif
- int t;
-
- #ifdef undef
- /* get password entry */
- if ((ppp = getpwuid(real_uid)) == NULL)
- {
- fprintf(stderr, "screen_builtin_lck: No passwd entry.\007\n");
- sleep(2);
- return;
- }
- if (!isatty(0))
- {
- fprintf(stderr, "screen_builtin_lck: Not a tty.\007\n");
- sleep(2);
- return;
- }
- #endif
- pass = ppp->pw_passwd;
- realpw:
- for (t = 0; t < 13; t++)
- {
- c = pass[t];
- if (!(c == '.' || c == '/' ||
- (c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z')))
- break;
- }
- if (t < 13)
- {
- debug("builtin_lock: ppp->pw_passwd bad, has it a shadow?\n");
- #ifdef SHADOWPW
- setspent(); /* rewind shadow file */
- if ((sss == NULL) && (sss = getspnam(ppp->pw_name)))
- {
- pass = sss->sp_pwdp;
- goto realpw;
- }
- #endif /* SHADOWPW */
- if (pass = getpass("Key: "))
- {
- strncpy(mypass, pass, 8);
- mypass[8] = 0;
- if (*mypass == 0)
- return;
- if (pass = getpass("Again: "))
- {
- if (strcmp(mypass, pass))
- {
- fprintf(stderr, "Passwords don't match.\007\n");
- sleep(2);
- return;
- }
- }
- }
- if (pass == 0)
- {
- fprintf(stderr, "Getpass error.\007\n");
- sleep(2);
- return;
- }
- pass = 0;
- }
-
- debug("screen_builtin_lck looking in gcos field\n");
- strcpy(fullname, ppp->pw_gecos);
- if ((cp1 = index(fullname, ',')) != NULL)
- *cp1 = '\0';
- if ((cp1 = index(fullname, '&')) != NULL)
- {
- sprintf(cp1, "%s", ppp->pw_name);
- *cp1 = islower(*cp1) ? toupper(*cp1) : *cp1;
- }
-
- sprintf(message, "Screen used by %s <%s>.\nPassword:\007",
- fullname, ppp->pw_name);
-
- /* loop here to wait for correct password */
- for (;;)
- {
- debug("screen_builtin_lck awaiting password\n");
- if ((cp1 = getpass(message)) == NULL)
- {
- AttacherFinit(SIGARG);
- /* NOTREACHED */
- }
- if (pass)
- {
- if (!strcmp(crypt(cp1, pass), pass))
- break;
- }
- else
- {
- if (!strcmp(cp1, mypass))
- break;
- }
- debug("screen_builtin_lck: NO!!!!!\n");
- }
- debug("password ok.\n");
- }
-
- #endif /* LOCK */
-
- /*
- * Detach now has the following modes:
- * D_DETACH SIG_BYE detach backend and exit attacher
- * D_STOP SIG_STOP stop attacher (and detach backend)
- * D_REMOTE SIG_BYE remote detach -- reattach to new attacher
- * D_POWER SIG_POWER_BYE power detach -- attacher kills his parent
- * D_REMOTE_POWER SIG_POWER_BYE remote power detach -- both
- * D_LOCK SIG_LOCK lock the attacher
- * (jw)
- * we always remove our utmp slots. (even when "lock" or "stop")
- * Note: Take extra care here, we may be called by unterrupt!
- */
- void
- Detach(mode)
- int mode;
- {
- int sign = 0;
- #ifdef UTMPOK
- register int n;
- #endif
-
- if (Detached)
- return;
- debug1("Detach(%d)\n", mode);
- if (fore && status)
- RemoveStatus();
- signal(SIGHUP, SIG_IGN);
- SetTTY(0, &OldMode);
- FinitTerm();
- switch (mode)
- {
- case D_DETACH:
- printf("\n[detached]\n");
- sign = SIG_BYE;
- break;
- #ifdef BSDJOBS
- case D_STOP:
- (void) fflush(stdout);
- sign = SIG_STOP;
- break;
- #endif
- #ifdef REMOTE_DETACH
- case D_REMOTE:
- printf("\n[remote detached]\n");
- sign = SIG_BYE;
- break;
- #endif
- #ifdef POW_DETACH
- case D_POWER:
- printf("\n[power detached]\n");
- if (PowDetachString)
- printf("%s\n", PowDetachString);
- sign = SIG_POWER_BYE;
- break;
- #ifdef REMOTE_DETACH
- case D_REMOTE_POWER:
- printf("\n[remote power detached]\n");
- if (PowDetachString)
- printf("%s\n", PowDetachString);
- sign = SIG_POWER_BYE;
- break;
- #endif
- #endif
- case D_LOCK:
- ClearDisplay();
- sign = SIG_LOCK;
- /* tell attacher to lock terminal with a lockprg. */
- break;
- }
- #ifdef UTMPOK
- for (n = WinList; n != -1; n = wtab[n]->WinLink)
- if (wtab[n]->slot != (slot_t) -1)
- {
- RemoveUtmp(wtab[n]);
- /*
- * Set the slot to 0 to get the window
- * logged in again.
- */
- wtab[n]->slot = (slot_t) 0;
- }
- RestoreLoginSlot();
- #endif
- freetty();
- (void) chmod(SockPath, /* S_IFSOCK | */ 0600); /* Flag detached-ness */
- /*
- * tell father to father what to do. We do that after we
- * freed the tty, thus getty feels more comfortable on hpux
- * if it was a power detach.
- */
- Kill(AttacherPid, sign);
- debug2("Detach: Signal %d to Attacher(%d)!\n", sign, AttacherPid);
- if (mode != D_LOCK && mode != D_STOP)
- AttacherPid = 0;
-
- Detached = 1;
- Suspended = (mode == D_STOP) ? 1 : 0;
- if (fore)
- fore->active = 0;
- debug("Detach returns, we are successfully detached.\n");
- }
-
- void
- Kill(pid, sig)
- int pid, sig;
- {
- if (pid < 2)
- return;
- (void) kill(pid, sig);
- }
-
- static int IsSymbol(e, s)
- register char *e, *s;
- {
- register char *p;
- register int n;
-
- for (p = e; *p && *p != '='; ++p)
- ;
- if (*p)
- {
- *p = '\0';
- n = strcmp(e, s);
- *p = '=';
- return n == 0;
- }
- return 0;
- }
-
- static void MakeNewEnv()
- {
- register char **op, **np;
- static char buf[MAXSTR];
-
- for (op = environ; *op; ++op)
- ;
- NewEnv = np = (char **) malloc((unsigned) (op - environ + 6 + 1) * sizeof(char **));
- if (!NewEnv)
- Msg_nomem;
- if (strlen(SockName) > MAXSTR - 5)
- SockName = "?";
- sprintf(buf, "STY=%s", SockName);
- *np++ = buf; /* NewEnv[0] */
- *np++ = Term; /* NewEnv[1] */
- #ifdef TIOCSWINSZ
- np += 2; /* room for TERMCAP and WINDOW */
- #else
- np += 4; /* room for TERMCAP WINDOW LINES COLUMNS */
- #endif
-
- for (op = environ; *op; ++op)
- {
- if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP")
- && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW")
- && !IsSymbol(*op, "SCREENCAP")
- #ifndef TIOCGWINSZ
- && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS")
- #endif
- )
- *np++ = *op;
- }
- *np = 0;
- }
-
- void
- #ifdef USEVARARGS
- /*VARARGS2*/
- # if defined(__STDC__)
- Msg(int err, char *fmt, ...)
- # else
- Msg(err, fmt, va_alist)
- int err;
- char *fmt;
- va_dcl
- # endif
- {
- static va_list ap = 0;
- #else
- /*VARARGS2*/
- Msg(err, fmt, p1, p2, p3, p4, p5, p6)
- int err;
- char *fmt;
- unsigned long p1, p2, p3, p4, p5, p6;
- {
- #endif
- char buf[MAXPATH*2];
- char *p = buf;
-
- if (Detached)
- return;
- #ifdef USEVARARGS
- # if defined(__STDC__)
- va_start(ap, fmt);
- # else
- va_start(ap);
- # endif
- (void) vsprintf(p, fmt, ap);
- va_end(ap);
- #else
- sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
- #endif
- if (err)
- {
- p += strlen(p);
- if (err > 0 && err < sys_nerr)
- sprintf(p, ": %s", sys_errlist[err]);
- else
- sprintf(p, ": Error %d", err);
- }
- if (HasWindow)
- {
- debug1("Msg('%s');\n", p);
- MakeStatus(buf);
- }
- else
- {
- printf("%s\r\n", buf);
- if (DeadlyMsg)
- {
- debug1("Msg('%s') screen is not up, exiting..\n", buf);
- Kill(AttacherPid, SIG_BYE);
- eexit(1);
- }
- else
- debug1("Harmless; Msg('%s');\n", buf);
- }
- DeadlyMsg = 1;
- }
-
- char *Filename(s)
- char *s;
- {
- register char *p;
-
- if (s == NULL)
- return s;
- p = s + strlen(s) - 1;
- while (p >= s && *p != '/')
- --p;
- return ++p;
- }
-
- /*
- * '^' is allowed as an escape mechanism for control characters. jw.
- */
- static char *MakeWinMsg(s, n)
- register char *s;
- int n;
- {
- static char buf[MAXSTR];
- register char *p = buf;
- register int ctrl;
-
- ctrl = 0;
- for (; *s && p < buf + MAXSTR - 1; s++, p++)
- if (ctrl)
- {
- ctrl = 0;
- if (*s == '^' || *s < 64)
- *p = *s;
- else
- *p = *s - 64;
- }
- else
- {
- switch (*s)
- {
- case '%':
- *p = n + '0';
- break;
- case '~':
- *p = BELL;
- break;
- case '^':
- ctrl = 1;
- *p-- = '^';
- break;
- default:
- *p = *s;
- break;
- }
- }
- *p = '\0';
- return buf;
- }
-
-