home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-07-25 | 94.9 KB | 4,408 lines |
- Newsgroups: comp.sources.unix
- From: mlschroe@immd4.informatik.uni-erlangen.de (Michael Schroeder)
- Subject: v26i305: screen-3.5 - screen manager with VT100/ANSI terminal emulation, V3.5, Part06/10
- Sender: unix-sources-moderator@gw.home.vix.com
- Approved: vixie@gw.home.vix.com
-
- Submitted-By: mlschroe@immd4.informatik.uni-erlangen.de (Michael Schroeder)
- Posting-Number: Volume 26, Issue 305
- Archive-Name: screen-3.5/part06
-
- #! /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 6 (of 10)."
- # Contents: ansi.c screen.c
- # Wrapped by vixie@gw.home.vix.com on Sun Jul 25 12:57:21 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'ansi.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ansi.c'\"
- else
- echo shar: Extracting \"'ansi.c'\" \(39996 characters\)
- sed "s/^X//" >'ansi.c' <<'END_OF_FILE'
- X/* Copyright (c) 1993
- X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
- X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
- X * Copyright (c) 1987 Oliver Laumann
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2, or (at your option)
- X * any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program (see the file COPYING); if not, write to the
- X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X ****************************************************************
- X */
- X
- X#include "rcs.h"
- XRCS_ID("$Id: ansi.c,v 1.12 1993/07/21 15:42:44 mlschroe Exp $ FAU")
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <fcntl.h>
- X#ifndef sun /* we want to know about TIOCPKT. */
- X# include <sys/ioctl.h>
- X#endif
- X#include "config.h"
- X#include "screen.h"
- X#include "extern.h"
- X
- Xextern char *getenv(), *tgetstr(), *tgoto();
- X#ifndef __STDC__
- Xextern char *malloc();
- X#endif
- X
- Xextern struct win *windows; /* linked list of all windows */
- Xextern struct win *fore;
- Xextern struct display *display, *displays;
- X
- Xextern int force_vt;
- Xextern int all_norefresh; /* => display */
- Xextern char Esc, MetaEsc; /* => display */
- Xextern time_t Now;
- X
- Xint maxwidth; /* maximum of all widths so far */
- X
- Xint Z0width, Z1width; /* widths for Z0/Z1 switching */
- X
- Xstatic struct win *curr; /* window we are working on */
- Xstatic int rows, cols; /* window size of the curr window */
- X
- Xint default_wrap = 1; /* default: wrap on */
- Xint default_monitor = 0;
- X
- Xint visual_bell = 0;
- Xint use_hardstatus = 1;
- X
- Xchar *blank; /* line filled with spaces */
- Xchar *null; /* line filled with '\0' */
- Xchar *OldImage, *OldAttr, *OldFont; /* temporary buffers */
- X
- Xstatic void WinProcess __P((char **, int *));
- Xstatic void WinRedisplayLine __P((int, int, int, int));
- Xstatic void WinClearLine __P((int, int, int));
- Xstatic int WinRewrite __P((int, int, int, int));
- Xstatic void WinSetCursor __P((void));
- Xstatic int WinResize __P((int, int));
- Xstatic void WinRestore __P((void));
- Xstatic int Special __P((int));
- Xstatic void DoESC __P((int, int ));
- Xstatic void DoCSI __P((int, int ));
- Xstatic void SetChar __P((int));
- Xstatic void StartString __P((enum string_t));
- Xstatic void SaveChar __P((int ));
- Xstatic void PrintChar __P((int ));
- Xstatic void PrintFlush __P((void));
- Xstatic void DesignateCharset __P((int, int ));
- Xstatic void MapCharset __P((int));
- Xstatic void SaveCursor __P((void));
- Xstatic void RestoreCursor __P((void));
- Xstatic void BackSpace __P((void));
- Xstatic void Return __P((void));
- Xstatic void LineFeed __P((int));
- Xstatic void ReverseLineFeed __P((void));
- Xstatic void InsertAChar __P((int));
- Xstatic void InsertChar __P((int));
- Xstatic void DeleteChar __P((int));
- Xstatic void DeleteLine __P((int));
- Xstatic void InsertLine __P((int));
- Xstatic void ScrollUpMap __P((int));
- Xstatic void ScrollDownMap __P((int));
- Xstatic void Scroll __P((char *, int, int, char *));
- Xstatic void ForwardTab __P((void));
- Xstatic void BackwardTab __P((void));
- Xstatic void ClearScreen __P((void));
- Xstatic void ClearFromBOS __P((void));
- Xstatic void ClearToEOS __P((void));
- Xstatic void ClearFullLine __P((void));
- Xstatic void ClearToEOL __P((void));
- Xstatic void ClearFromBOL __P((void));
- Xstatic void ClearInLine __P((int, int, int));
- Xstatic void CursorRight __P((int));
- Xstatic void CursorUp __P((int));
- Xstatic void CursorDown __P((int));
- Xstatic void CursorLeft __P((int));
- Xstatic void ASetMode __P((int));
- Xstatic void SelectRendition __P((void));
- Xstatic void RestorePosAttrFont __P((void));
- Xstatic void FillWithEs __P((void));
- Xstatic void UpdateLine __P((char *, char *, char *, int, int, int ));
- Xstatic void FindAKA __P((void));
- Xstatic void Report __P((char *, int, int));
- X
- X
- X/*
- X * The window layer functions
- X */
- X
- Xstruct LayFuncs WinLf =
- X{
- X WinProcess,
- X 0,
- X WinRedisplayLine,
- X WinClearLine,
- X WinRewrite,
- X WinSetCursor,
- X WinResize,
- X WinRestore
- X};
- X
- Xstatic void
- XWinProcess(bufpp, lenp)
- Xchar **bufpp;
- Xint *lenp;
- X{
- X int f, *ilen, l = *lenp;
- X char *ibuf;
- X
- X fore = d_fore;
- X#ifdef MULTIUSER
- X /* if w_wlock is set, only one user may write, else we check acls */
- X if ((fore->w_wlock == WLOCK_OFF) ?
- X AclCheckPermWin(d_user, ACL_WRITE, fore) :
- X (d_user != fore->w_wlockuser))
- X {
- X SetCurr(fore);
- X Special('\007');
- X *bufpp += *lenp;
- X *lenp = 0;
- X return;
- X }
- X#endif /* MULTIUSER */
- X#ifdef PSEUDOS
- X if (W_UWP(fore))
- X {
- X /* we send the user input to our pseudowin */
- X ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen;
- X f = sizeof(fore->w_pwin->p_inbuf) - *ilen;
- X }
- X else
- X#endif /* PSEUDOS */
- X {
- X /* we send the user input to the window */
- X ibuf = fore->w_inbuf; ilen = &fore->w_inlen;
- X f = sizeof(fore->w_inbuf) - *ilen;
- X }
- X if (l > f)
- X {
- X debug1("Yuck! pty buffer full (%d chars missing). lets beep\n", l - f);
- X SetCurr(fore);
- X Special('\007');
- X l = f;
- X }
- X if (l > 0)
- X {
- X bcopy(*bufpp, ibuf + *ilen, l);
- X *ilen += l;
- X }
- X *bufpp += *lenp;
- X *lenp = 0;
- X}
- X
- Xstatic void
- XWinRedisplayLine(y, from, to, isblank)
- Xint y, from, to, isblank;
- X{
- X if (y < 0)
- X return;
- X fore = d_fore;
- X DisplayLine(isblank ? blank: null, null, null, fore->w_image[y],
- X fore->w_attr[y], fore->w_font[y], y, from, to);
- X}
- X
- Xstatic int
- XWinRewrite(y, x1, x2, doit)
- Xint y, x1, x2, doit;
- X{
- X register int cost, dx;
- X register char *p, *f, *i;
- X
- X fore = d_fore;
- X dx = x2 - x1;
- X if (doit)
- X {
- X i = fore->w_image[y] + x1;
- X while (dx-- > 0)
- X PUTCHAR(*i++);
- X return(0);
- X }
- X p = fore->w_attr[y] + x1;
- X f = fore->w_font[y] + x1;
- X
- X cost = dx = x2 - x1;
- X if (d_insert)
- X cost += d_EIcost + d_IMcost;
- X while(dx-- > 0)
- X {
- X if (*p++ != d_attr || *f++ != d_font)
- X return EXPENSIVE;
- X }
- X return cost;
- X}
- X
- Xstatic void
- XWinClearLine(y, xs, xe)
- Xint y, xs, xe;
- X{
- X fore = d_fore;
- X DisplayLine(fore->w_image[y], fore->w_attr[y], fore->w_font[y],
- X blank, null, null, y, xs, xe);
- X}
- X
- Xstatic void
- XWinSetCursor()
- X{
- X fore = d_fore;
- X GotoPos(fore->w_x, fore->w_y);
- X}
- X
- Xstatic int
- XWinResize(wi, he)
- Xint wi, he;
- X{
- X fore = d_fore;
- X if (fore)
- X ChangeWindowSize(fore, wi, he);
- X return 0;
- X}
- X
- Xstatic void
- XWinRestore()
- X{
- X fore = d_fore;
- X ChangeScrollRegion(fore->w_top, fore->w_bot);
- X KeypadMode(fore->w_keypad);
- X CursorkeysMode(fore->w_cursorkeys);
- X SetFlow(fore->w_flow & FLOW_NOW);
- X InsertMode(fore->w_insert);
- X fore->w_active = 1;
- X}
- X
- X/*
- X * Activate - make fore window active
- X * norefresh = -1 forces a refresh, disregard all_norefresh then.
- X */
- Xvoid
- XActivate(norefresh)
- Xint norefresh;
- X{
- X debug1("Activate(%d)\n", norefresh);
- X if (display == 0)
- X return;
- X RemoveStatus();
- X fore = d_fore;
- X if (fore)
- X {
- X ASSERT(fore->w_display == display);
- X fore->w_active = d_layfn == &WinLf;
- X if (fore->w_monitor != MON_OFF)
- X fore->w_monitor = MON_ON;
- X fore->w_bell = BELL_OFF;
- X if (ResizeDisplay(fore->w_width, fore->w_height))
- X {
- X debug2("Cannot resize from (%d,%d)", d_width, d_height);
- X debug2(" to (%d,%d) -> resize window\n", fore->w_width, fore->w_height);
- X DoResize(d_width, d_height);
- X }
- X }
- X Redisplay(norefresh + all_norefresh);
- X}
- X
- Xvoid
- XResetWindow(p)
- Xregister struct win *p;
- X{
- X register int i;
- X
- X p->w_wrap = default_wrap;
- X p->w_origin = 0;
- X p->w_insert = 0;
- X p->w_vbwait = 0;
- X p->w_keypad = 0;
- X p->w_cursorkeys = 0;
- X p->w_top = 0;
- X p->w_bot = p->w_height - 1;
- X p->w_saved = 0;
- X p->w_Attr = 0;
- X p->w_Font = 0;
- X p->w_x = p->w_y = 0;
- X p->w_state = LIT;
- X p->w_StringType = NONE;
- X p->w_ss = 0;
- X p->w_Charset = G0;
- X bzero(p->w_tabs, p->w_width);
- X for (i = 8; i < p->w_width; i += 8)
- X p->w_tabs[i] = 1;
- X for (i = G0; i <= G3; i++)
- X p->w_charsets[i] = ASCII;
- X}
- X
- X
- X/*
- X * Here comes the vt100 emulator
- X */
- Xvoid
- XWriteString(wp, buf, len)
- Xstruct win *wp;
- Xregister char *buf;
- Xregister int len;
- X{
- X register int c;
- X
- X if (!len)
- X return;
- X if (wp->w_logfp != NULL)
- X if ((int)fwrite(buf, len, 1, wp->w_logfp) < 1)
- X {
- X Msg(errno, "Error writing logfile");
- X fclose(wp->w_logfp);
- X wp->w_logfp = NULL;
- X }
- X /*
- X * SetCurr() here may prevent output, as it may set display = 0
- X */
- X SetCurr(wp);
- X if (display)
- X {
- X if (d_status && !(use_hardstatus && HS))
- X RemoveStatus();
- X }
- X else
- X {
- X if (curr->w_tstamp.seconds)
- X curr->w_tstamp.lastio = Now;
- X
- X if (curr->w_monitor == MON_ON || curr->w_monitor == MON_DONE)
- X {
- X debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell);
- X curr->w_monitor = MON_FOUND;
- X }
- X }
- X do
- X {
- X if (curr->w_Attr && curr->w_attr[curr->w_y] == null)
- X {
- X if ((curr->w_attr[curr->w_y] = (char *)malloc(curr->w_width + 1)) == 0)
- X {
- X curr->w_attr[curr->w_y] = null;
- X curr->w_Attr = 0;
- X Msg(0, "Warning: no space for attr - turned off");
- X }
- X else
- X bzero(curr->w_attr[curr->w_y], curr->w_width + 1);
- X }
- X if (curr->w_Font && curr->w_font[curr->w_y] == null)
- X {
- X if ((curr->w_font[curr->w_y] = (char *)malloc(curr->w_width + 1)) == 0)
- X {
- X curr->w_font[curr->w_y] = null;
- X curr->w_Font = curr->w_charsets[curr->w_ss ? curr->w_ss : curr->w_Charset] = 0;
- X Msg(0, "Warning: no space for font - turned off");
- X }
- X else
- X bzero(curr->w_font[curr->w_y], curr->w_width + 1);
- X }
- X
- X c = (unsigned char)*buf++;
- X if (c == '\177')
- X continue;
- X
- X /* The next part is only for speedup */
- X if (curr->w_state == LIT &&
- X c >= ' ' && ((c & 0x80) == 0 || display == 0 || !CB8) &&
- X !curr->w_insert && !curr->w_ss)
- X {
- X register int currx;
- X register char *imp, *atp, *fop, at, fo;
- X
- X currx = curr->w_x;
- X imp = curr->w_image[curr->w_y] + currx;
- X atp = curr->w_attr[curr->w_y] + currx;
- X fop = curr->w_font[curr->w_y] + currx;
- X at = curr->w_Attr;
- X fo = curr->w_Font;
- X if (display)
- X {
- X if (d_x != currx || d_y != curr->w_y)
- X GotoPos(currx, curr->w_y);
- X if (at != d_attr)
- X SetAttr(at);
- X if (fo != d_font)
- X SetFont(fo);
- X if (d_insert)
- X InsertMode(0);
- X }
- X while (currx < cols - 1)
- X {
- X if (display)
- X AddChar(d_font != '0' ? c : d_c0_tab[c]);
- X *imp++ = c;
- X *atp++ = at;
- X *fop++ = fo;
- X currx++;
- Xskip: if (--len == 0)
- X break;
- X c = (unsigned char)*buf++;
- X if (c == '\177')
- X goto skip;
- X if (c < ' ' || ((c & 0x80) && display && CB8))
- X break;
- X }
- X curr->w_x = currx;
- X if (display)
- X d_x = currx;
- X if (len == 0)
- X break;
- X }
- X /* end of speedup code */
- X
- X if ((c & 0x80) && display && CB8)
- X {
- X FILE *logfp = wp->w_logfp;
- X char *cb8 = CB8;
- X
- X wp->w_logfp = NULL; /* a little hack */
- X CB8 = NULL; /* dito */
- X WriteString(wp, cb8, (int)strlen(cb8));
- X wp->w_logfp = logfp;
- X CB8 = cb8;
- X c &= 0x7f;
- X }
- X tryagain:
- X switch (curr->w_state)
- X {
- X case PRIN:
- X switch (c)
- X {
- X case '\033':
- X curr->w_state = PRINESC;
- X break;
- X default:
- X PrintChar(c);
- X }
- X break;
- X case PRINESC:
- X switch (c)
- X {
- X case '[':
- X curr->w_state = PRINCSI;
- X break;
- X default:
- X PrintChar('\033');
- X PrintChar(c);
- X curr->w_state = PRIN;
- X }
- X break;
- X case PRINCSI:
- X switch (c)
- X {
- X case '4':
- X curr->w_state = PRIN4;
- X break;
- X default:
- X PrintChar('\033');
- X PrintChar('[');
- X PrintChar(c);
- X curr->w_state = PRIN;
- X }
- X break;
- X case PRIN4:
- X switch (c)
- X {
- X case 'i':
- X curr->w_state = LIT;
- X PrintFlush();
- X break;
- X default:
- X PrintChar('\033');
- X PrintChar('[');
- X PrintChar('4');
- X PrintChar(c);
- X curr->w_state = PRIN;
- X }
- X break;
- X case STRESC:
- X switch (c)
- X {
- X case '\\':
- X curr->w_state = LIT;
- X *(curr->w_stringp) = '\0';
- X switch (curr->w_StringType)
- X {
- X case GM:
- X {
- X struct display *old = display;
- X for (display = displays; display; display = display->_d_next)
- X if (display != old)
- X MakeStatus(curr->w_string);
- X display = old;
- X }
- X /*FALLTHROUGH*/
- X case PM:
- X if (!display)
- X break;
- X MakeStatus(curr->w_string);
- X if (d_status && !(use_hardstatus && HS) && len > 1)
- X {
- X curr->w_outlen = len - 1;
- X bcopy(buf, curr->w_outbuf, curr->w_outlen);
- X return;
- X }
- X break;
- X case DCS:
- X if (display)
- X AddStr(curr->w_string);
- X break;
- X case AKA:
- X if (curr->w_aka == curr->w_akabuf && !*curr->w_string)
- X break;
- X ChangeAKA(curr, curr->w_string, 20);
- X if (!*curr->w_string)
- X curr->w_autoaka = curr->w_y + 1;
- X break;
- X default:
- X break;
- X }
- X break;
- X default:
- X curr->w_state = ASTR;
- X SaveChar('\033');
- X SaveChar(c);
- X }
- X break;
- X case ASTR:
- X switch (c)
- X {
- X case '\0':
- X break;
- X case '\033':
- X curr->w_state = STRESC;
- X break;
- X default:
- X SaveChar(c);
- X }
- X break;
- X case ESC:
- X switch (c)
- X {
- X case '[':
- X curr->w_NumArgs = 0;
- X curr->w_intermediate = 0;
- X bzero((char *) curr->w_args, MAXARGS * sizeof(int));
- X curr->w_state = CSI;
- X break;
- X case ']':
- X StartString(OSC);
- X break;
- X case '_':
- X StartString(APC);
- X break;
- X case 'P':
- X StartString(DCS);
- X break;
- X case '^':
- X StartString(PM);
- X break;
- X case '!':
- X StartString(GM);
- X break;
- X case '"':
- X case 'k':
- X StartString(AKA);
- X break;
- X default:
- X if (Special(c))
- X break;
- X debug1("not special. c = %x\n", c);
- X if (c >= ' ' && c <= '/')
- X curr->w_intermediate = curr->w_intermediate ? -1 : c;
- X else if (c >= '0' && c <= '~')
- X {
- X DoESC(c, curr->w_intermediate);
- X curr->w_state = LIT;
- X }
- X else
- X {
- X curr->w_state = LIT;
- X goto tryagain;
- X }
- X }
- X break;
- X case CSI:
- X switch (c)
- X {
- X case '0':
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X if (curr->w_NumArgs < MAXARGS)
- X {
- X curr->w_args[curr->w_NumArgs] =
- X 10 * curr->w_args[curr->w_NumArgs] + c - '0';
- X }
- X break;
- X case ';':
- X case ':':
- X curr->w_NumArgs++;
- X break;
- X default:
- X if (Special(c))
- X break;
- X if (c >= '@' && c <= '~')
- X {
- X curr->w_NumArgs++;
- X DoCSI(c, curr->w_intermediate);
- X if (curr->w_state != PRIN)
- X curr->w_state = LIT;
- X }
- X else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
- X curr->w_intermediate = curr->w_intermediate ? -1 : c;
- X else
- X {
- X curr->w_state = LIT;
- X goto tryagain;
- X }
- X }
- X break;
- X case LIT:
- X default:
- X if (c < ' ')
- X {
- X if (c == '\033')
- X {
- X curr->w_intermediate = 0;
- X curr->w_state = ESC;
- X if (display && d_lp_missing && (CIC || IC || IM))
- X UpdateLine(blank, null, null, d_bot, cols - 2, cols - 1);
- X if (curr->w_autoaka < 0)
- X curr->w_autoaka = 0;
- X }
- X else
- X Special(c);
- X break;
- X }
- X if (display)
- X {
- X if (d_attr != curr->w_Attr)
- X SetAttr(curr->w_Attr);
- X if (d_font != curr->w_Font)
- X SetFont(curr->w_Font);
- X }
- X if (curr->w_x < cols - 1)
- X {
- X if (curr->w_insert)
- X InsertAChar(c);
- X else
- X {
- X if (display)
- X PUTCHAR(c);
- X SetChar(c);
- X curr->w_x++;
- X }
- X }
- X else if (curr->w_x == cols - 1)
- X {
- X if (display && curr->w_wrap && (CLP || !force_vt || COP))
- X {
- X RAW_PUTCHAR(c); /* don't care about d_insert */
- X SetChar(c);
- X if (AM && !CLP)
- X LineFeed(0); /* terminal auto-wrapped */
- X else
- X curr->w_x++;
- X }
- X else
- X {
- X if (display)
- X {
- X if (CLP || curr->w_y != d_bot)
- X {
- X RAW_PUTCHAR(c);
- X GotoPos(curr->w_x, curr->w_y);
- X }
- X else
- X CheckLP(c);
- X }
- X SetChar(c);
- X if (curr->w_wrap)
- X curr->w_x++;
- X }
- X }
- X else /* curr->w_x > cols - 1 */
- X {
- X SetChar(0); /* we wrapped */
- X if (curr->w_insert)
- X {
- X LineFeed(2); /* cr+lf, handle LP */
- X InsertAChar(c);
- X }
- X else
- X {
- X LineFeed(display == 0 || AM ? 0 : 2);
- X if (display)
- X PUTCHAR(c);
- X SetChar(c);
- X curr->w_x = 1;
- X }
- X }
- X if (curr->w_ss)
- X {
- X SetFont(curr->w_Font = curr->w_charsets[curr->w_Charset]);
- X curr->w_ss = 0;
- X }
- X break;
- X }
- X }
- X while (--len);
- X curr->w_outlen = 0;
- X if (curr->w_state == PRIN)
- X PrintFlush();
- X}
- X
- Xstatic int
- XSpecial(c)
- Xregister int c;
- X{
- X switch (c)
- X {
- X case '\b':
- X BackSpace();
- X return 1;
- X case '\r':
- X Return();
- X return 1;
- X case '\n':
- X if (curr->w_autoaka)
- X FindAKA();
- X LineFeed(1);
- X return 1;
- X case '\007':
- X if (display == 0)
- X curr->w_bell = BELL_ON;
- X else
- X {
- X if (!visual_bell)
- X PutStr(BL);
- X else
- X {
- X if (!VB)
- X curr->w_bell = BELL_VISUAL;
- X else
- X PutStr(VB);
- X }
- X }
- X return 1;
- X case '\t':
- X ForwardTab();
- X return 1;
- X case '\017': /* SI */
- X MapCharset(G0);
- X return 1;
- X case '\016': /* SO */
- X MapCharset(G1);
- X return 1;
- X }
- X return 0;
- X}
- X
- Xstatic void
- XDoESC(c, intermediate)
- Xint c, intermediate;
- X{
- X debug2("DoESC: %x - inter = %x\n", c, intermediate);
- X switch (intermediate)
- X {
- X case 0:
- X switch (c)
- X {
- X case 'E':
- X LineFeed(2);
- X break;
- X case 'D':
- X LineFeed(1);
- X break;
- X case 'M':
- X ReverseLineFeed();
- X break;
- X case 'H':
- X curr->w_tabs[curr->w_x] = 1;
- X break;
- X case 'Z': /* jph: Identify as VT100 */
- X Report("\033[?%d;%dc", 1, 2);
- X break;
- X case '7':
- X SaveCursor();
- X break;
- X case '8':
- X RestoreCursor();
- X break;
- X case 'c':
- X ClearScreen();
- X ResetWindow(curr);
- X SetAttrFont(0, ASCII);
- X InsertMode(0);
- X KeypadMode(0);
- X CursorkeysMode(0);
- X ChangeScrollRegion(0, rows - 1);
- X break;
- X case '=':
- X KeypadMode(curr->w_keypad = 1);
- X#ifndef TIOCPKT
- X NewAutoFlow(curr, 0);
- X#endif /* !TIOCPKT */
- X break;
- X case '>':
- X KeypadMode(curr->w_keypad = 0);
- X#ifndef TIOCPKT
- X NewAutoFlow(curr, 1);
- X#endif /* !TIOCPKT */
- X break;
- X case 'n': /* LS2 */
- X MapCharset(G2);
- X break;
- X case 'o': /* LS3 */
- X MapCharset(G3);
- X break;
- X case 'N': /* SS2 */
- X if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2])
- X curr->w_Font = curr->w_charsets[curr->w_ss = G2];
- X else
- X curr->w_ss = 0;
- X break;
- X case 'O': /* SS3 */
- X if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3])
- X curr->w_Font = curr->w_charsets[curr->w_ss = G3];
- X else
- X curr->w_ss = 0;
- X break;
- X }
- X break;
- X case '#':
- X switch (c)
- X {
- X case '8':
- X FillWithEs();
- X break;
- X }
- X break;
- X case '(':
- X DesignateCharset(c, G0);
- X break;
- X case ')':
- X DesignateCharset(c, G1);
- X break;
- X case '*':
- X DesignateCharset(c, G2);
- X break;
- X case '+':
- X DesignateCharset(c, G3);
- X break;
- X }
- X}
- X
- Xstatic void
- XDoCSI(c, intermediate)
- Xint c, intermediate;
- X{
- X register int i, a1 = curr->w_args[0], a2 = curr->w_args[1];
- X
- X if (curr->w_NumArgs > MAXARGS)
- X curr->w_NumArgs = MAXARGS;
- X switch (intermediate)
- X {
- X case 0:
- X switch (c)
- X {
- X case 'H':
- X case 'f':
- X if (a1 < 1)
- X a1 = 1;
- X if (curr->w_origin)
- X a1 += curr->w_top;
- X if (a1 > rows)
- X a1 = rows;
- X if (a2 < 1)
- X a2 = 1;
- X if (a2 > cols)
- X a2 = cols;
- X GotoPos(--a2, --a1);
- X curr->w_x = a2;
- X curr->w_y = a1;
- X if (curr->w_autoaka)
- X curr->w_autoaka = a1 + 1;
- X break;
- X case 'J':
- X if (a1 < 0 || a1 > 2)
- X a1 = 0;
- X switch (a1)
- X {
- X case 0:
- X ClearToEOS();
- X break;
- X case 1:
- X ClearFromBOS();
- X break;
- X case 2:
- X ClearScreen();
- X GotoPos(curr->w_x, curr->w_y);
- X break;
- X }
- X break;
- X case 'K':
- X if (a1 < 0 || a1 > 2)
- X a1 %= 3;
- X switch (a1)
- X {
- X case 0:
- X ClearToEOL();
- X break;
- X case 1:
- X ClearFromBOL();
- X break;
- X case 2:
- X ClearFullLine();
- X break;
- X }
- X break;
- X case 'A':
- X CursorUp(a1 ? a1 : 1);
- X break;
- X case 'B':
- X CursorDown(a1 ? a1 : 1);
- X break;
- X case 'C':
- X CursorRight(a1 ? a1 : 1);
- X break;
- X case 'D':
- X CursorLeft(a1 ? a1 : 1);
- X break;
- X case 'm':
- X SelectRendition();
- X break;
- X case 'g':
- X if (a1 == 0)
- X curr->w_tabs[curr->w_x] = 0;
- X else if (a1 == 3)
- X bzero(curr->w_tabs, cols);
- X break;
- X case 'r':
- X if (!a1)
- X a1 = 1;
- X if (!a2)
- X a2 = rows;
- X if (a1 < 1 || a2 > rows || a1 >= a2)
- X break;
- X curr->w_top = a1 - 1;
- X curr->w_bot = a2 - 1;
- X ChangeScrollRegion(curr->w_top, curr->w_bot);
- X if (curr->w_origin)
- X {
- X GotoPos(0, curr->w_top);
- X curr->w_y = curr->w_top;
- X curr->w_x = 0;
- X }
- X else
- X {
- X GotoPos(0, 0);
- X curr->w_y = curr->w_x = 0;
- X }
- X break;
- X case 's':
- X SaveCursor();
- X break;
- X case 't':
- X if (a1 != 8)
- X break;
- X a1 = curr->w_args[2];
- X if (a1 < 1)
- X a1 = curr->w_width;
- X if (a2 < 1)
- X a2 = curr->w_height;
- X if (display && CWS == NULL)
- X {
- X a2 = curr->w_height;
- X if (CZ0 == NULL || (a1 != Z0width && a1 != Z1width))
- X a1 = curr->w_width;
- X }
- X if (a1 == curr->w_width && a2 == curr->w_height)
- X break;
- X ChangeWindowSize(curr, a1, a2);
- X SetCurr(curr);
- X if (display)
- X Activate(0);
- X break;
- X case 'u':
- X RestoreCursor();
- X break;
- X case 'I':
- X if (!a1)
- X a1 = 1;
- X while (a1--)
- X ForwardTab();
- X break;
- X case 'Z':
- X if (!a1)
- X a1 = 1;
- X while (a1--)
- X BackwardTab();
- X break;
- X case 'L':
- X InsertLine(a1 ? a1 : 1);
- X break;
- X case 'M':
- X DeleteLine(a1 ? a1 : 1);
- X break;
- X case 'P':
- X DeleteChar(a1 ? a1 : 1);
- X break;
- X case '@':
- X InsertChar(a1 ? a1 : 1);
- X break;
- X case 'h':
- X ASetMode(1);
- X break;
- X case 'l':
- X ASetMode(0);
- X break;
- X case 'i':
- X if (display && PO && a1 == 5)
- X {
- X curr->w_stringp = curr->w_string;
- X curr->w_state = PRIN;
- X }
- X break;
- X case 'n':
- X if (a1 == 6) /* Report cursor position */
- X Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1);
- X break;
- X case 'c': /* Identify as VT100 */
- X Report("\033[?%d;%dc", 1, 2);
- X break;
- X }
- X break;
- X case '?':
- X debug2("\\E[?%d%c\n",a1,c);
- X if (c != 'h' && c != 'l')
- X break;
- X i = (c == 'h');
- X switch (a1)
- X {
- X case 1:
- X CursorkeysMode(curr->w_cursorkeys = i);
- X#ifndef TIOCPKT
- X NewAutoFlow(curr, !i);
- X#endif /* !TIOCPKT */
- X break;
- X case 3:
- X i = (i ? Z0width : Z1width);
- X if (curr->w_width != i && (display == 0 || (CZ0 || CWS)))
- X {
- X ChangeWindowSize(curr, i, curr->w_height);
- X SetCurr(curr); /* update rows/cols */
- X if (display)
- X Activate(0);
- X }
- X break;
- X case 5:
- X if (i)
- X curr->w_vbwait = 1;
- X else
- X {
- X if (display && curr->w_vbwait)
- X PutStr(VB);
- X curr->w_vbwait = 0;
- X }
- X break;
- X case 6:
- X if ((curr->w_origin = i) != 0)
- X {
- X curr->w_y = curr->w_top;
- X curr->w_x = 0;
- X }
- X else
- X curr->w_y = curr->w_x = 0;
- X if (display)
- X GotoPos(curr->w_x, curr->w_y);
- X break;
- X case 7:
- X curr->w_wrap = i;
- X break;
- X case 35:
- X debug1("Cursor %svisible\n", i ? "in" : "");
- X curr->w_cursor_invisible = i;
- X break;
- X }
- X break;
- X }
- X}
- X
- X
- Xstatic void
- XSetChar(c)
- Xregister int c;
- X{
- X register struct win *p = curr;
- X
- X p->w_image[p->w_y][p->w_x] = c;
- X p->w_attr[p->w_y][p->w_x] = p->w_Attr;
- X p->w_font[p->w_y][p->w_x] = p->w_Font;
- X}
- X
- Xstatic void
- XStartString(type)
- Xenum string_t type;
- X{
- X curr->w_StringType = type;
- X curr->w_stringp = curr->w_string;
- X curr->w_state = ASTR;
- X}
- X
- Xstatic void
- XSaveChar(c)
- Xint c;
- X{
- X if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
- X curr->w_state = LIT;
- X else
- X *(curr->w_stringp)++ = c;
- X}
- X
- Xstatic void
- XPrintChar(c)
- Xint c;
- X{
- X if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
- X PrintFlush();
- X *(curr->w_stringp)++ = c;
- X}
- X
- Xstatic void
- XPrintFlush()
- X{
- X if (display && curr->w_stringp > curr->w_string)
- X {
- X PutStr(PO);
- X AddStrn(curr->w_string, curr->w_stringp - curr->w_string);
- X PutStr(PF);
- X Flush();
- X }
- X curr->w_stringp = curr->w_string;
- X}
- X
- X
- Xvoid
- XNewAutoFlow(win, on)
- Xstruct win *win;
- Xint on;
- X{
- X debug1("NewAutoFlow: %d\n", on);
- X SetCurr(win);
- X if (win->w_flow & FLOW_AUTOFLAG)
- X win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on;
- X else
- X win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on;
- X if (display)
- X SetFlow(win->w_flow & FLOW_NOW);
- X}
- X
- Xstatic void
- XDesignateCharset(c, n)
- Xint c, n;
- X{
- X curr->w_ss = 0;
- X if (c == 'B')
- X c = ASCII;
- X if (curr->w_charsets[n] != c)
- X {
- X curr->w_charsets[n] = c;
- X if (curr->w_Charset == n)
- X SetFont(curr->w_Font = c);
- X }
- X}
- X
- Xstatic void
- XMapCharset(n)
- Xint n;
- X{
- X curr->w_ss = 0;
- X if (curr->w_Charset != n)
- X {
- X curr->w_Charset = n;
- X SetFont(curr->w_Font = curr->w_charsets[n]);
- X }
- X}
- X
- Xstatic void
- XSaveCursor()
- X{
- X curr->w_saved = 1;
- X curr->w_Saved_x = curr->w_x;
- X curr->w_Saved_y = curr->w_y;
- X curr->w_SavedAttr = curr->w_Attr;
- X curr->w_SavedCharset = curr->w_Charset;
- X bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets,
- X 4 * sizeof(int));
- X}
- X
- Xstatic void
- XRestoreCursor()
- X{
- X if (curr->w_saved)
- X {
- X GotoPos(curr->w_Saved_x, curr->w_Saved_y);
- X curr->w_x = curr->w_Saved_x;
- X curr->w_y = curr->w_Saved_y;
- X curr->w_Attr = curr->w_SavedAttr;
- X SetAttr(curr->w_Attr);
- X bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets,
- X 4 * sizeof(int));
- X curr->w_Charset = curr->w_SavedCharset;
- X curr->w_ss = 0;
- X SetFont(curr->w_Font = curr->w_charsets[curr->w_Charset]);
- X }
- X}
- X
- Xstatic void
- XBackSpace()
- X{
- X if (curr->w_x > 0)
- X {
- X curr->w_x--;
- X }
- X else if (curr->w_wrap && curr->w_y > 0)
- X {
- X curr->w_x = cols - 1;
- X curr->w_y--;
- X }
- X if (display)
- X GotoPos(curr->w_x, curr->w_y);
- X}
- X
- Xstatic void
- XReturn()
- X{
- X if (curr->w_x > 0)
- X {
- X curr->w_x = 0;
- X if (display)
- X GotoPos(curr->w_x, curr->w_y);
- X }
- X}
- X
- Xstatic void
- XLineFeed(out_mode)
- Xint out_mode;
- X{
- X /* out_mode: 0=cr+lf no-output, 1=lf, 2=cr+lf */
- X if (out_mode != 1)
- X curr->w_x = 0;
- X if (curr->w_y != curr->w_bot) /* Don't scroll */
- X {
- X if (curr->w_y < rows-1)
- X curr->w_y++;
- X if (out_mode && display)
- X GotoPos(curr->w_x, curr->w_y);
- X return;
- X }
- X ScrollUpMap(1);
- X if (curr->w_autoaka > 1)
- X curr->w_autoaka--;
- X if (out_mode && display)
- X {
- X ScrollRegion(curr->w_top, curr->w_bot, 1);
- X GotoPos(curr->w_x, curr->w_y);
- X }
- X}
- X
- Xstatic void
- XReverseLineFeed()
- X{
- X if (curr->w_y == curr->w_top)
- X {
- X ScrollDownMap(1);
- X if (!display)
- X return;
- X ScrollRegion(curr->w_top, curr->w_bot, -1);
- X GotoPos(curr->w_x, curr->w_y);
- X }
- X else if (curr->w_y > 0)
- X CursorUp(1);
- X}
- X
- Xstatic void
- XInsertAChar(c)
- Xint c;
- X{
- X register int y = curr->w_y, x = curr->w_x;
- X
- X if (x == cols)
- X x--;
- X bcopy(curr->w_image[y], OldImage, cols);
- X bcopy(curr->w_attr[y], OldAttr, cols);
- X bcopy(curr->w_font[y], OldFont, cols);
- X bcopy(curr->w_image[y] + x, curr->w_image[y] + x + 1, cols - x - 1);
- X bcopy(curr->w_attr[y] + x, curr->w_attr[y] + x + 1, cols - x - 1);
- X bcopy(curr->w_font[y] + x, curr->w_font[y] + x + 1, cols - x - 1);
- X SetChar(c);
- X curr->w_x = x + 1;
- X if (!display)
- X return;
- X if (CIC || IC || IM)
- X {
- X InsertMode(curr->w_insert);
- X INSERTCHAR(c);
- X if (y == d_bot)
- X d_lp_missing = 0;
- X }
- X else
- X UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
- X}
- X
- Xstatic void
- XInsertChar(n)
- Xint n;
- X{
- X register int i, y = curr->w_y, x = curr->w_x;
- X
- X if (n <= 0)
- X return;
- X /* Hack to be compatible with the old screen versions */
- X if (curr->w_insert)
- X return;
- X if (x == cols)
- X x--;
- X bcopy(curr->w_image[y], OldImage, cols);
- X bcopy(curr->w_attr[y], OldAttr, cols);
- X bcopy(curr->w_font[y], OldFont, cols);
- X if (n > cols - x)
- X n = cols - x;
- X bcopy(curr->w_image[y] + x, curr->w_image[y] + x + n, cols - x - n);
- X bcopy(curr->w_attr[y] + x, curr->w_attr[y] + x + n, cols - x - n);
- X bcopy(curr->w_font[y] + x, curr->w_font[y] + x + n, cols - x - n);
- X ClearInLine(y, x, x + n - 1);
- X if (!display)
- X return;
- X if (IC || CIC || IM)
- X {
- X if (y == d_bot)
- X d_lp_missing = 0;
- X if (!d_insert)
- X {
- X if (n == 1 && IC)
- X {
- X PutStr(IC);
- X return;
- X }
- X if (CIC)
- X {
- X CPutStr(CIC, n);
- X return;
- X }
- X }
- X InsertMode(1);
- X for (i = n; i--; )
- X INSERTCHAR(' ');
- X GotoPos(x, y);
- X }
- X else
- X UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
- X}
- X
- Xstatic void
- XDeleteChar(n)
- Xint n;
- X{
- X register int i, y = curr->w_y, x = curr->w_x;
- X
- X if (x == cols)
- X x--;
- X bcopy(curr->w_image[y], OldImage, cols);
- X bcopy(curr->w_attr[y], OldAttr, cols);
- X bcopy(curr->w_font[y], OldFont, cols);
- X if (n > cols - x)
- X n = cols - x;
- X bcopy(curr->w_image[y] + x + n, curr->w_image[y] + x, cols - x - n);
- X bcopy(curr->w_attr[y] + x + n, curr->w_attr[y] + x, cols - x - n);
- X bcopy(curr->w_font[y] + x + n, curr->w_font[y] + x, cols - x - n);
- X ClearInLine(y, cols - n, cols - 1);
- X if (!display)
- X return;
- X if (CDC && !(n == 1 && DC))
- X {
- X CPutStr(CDC, n);
- X if (d_lp_missing && y == d_bot)
- X {
- X FixLP(cols - 1 - n, y);
- X GotoPos(x, y);
- X }
- X }
- X else if (DC)
- X {
- X for (i = n; i; i--)
- X PutStr(DC);
- X if (d_lp_missing && y == d_bot)
- X {
- X FixLP(cols - 1 - n, y);
- X GotoPos(x, y);
- X }
- X }
- X else
- X UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
- X}
- X
- Xstatic void
- XDeleteLine(n)
- Xint n;
- X{
- X register int old = curr->w_top;
- X
- X if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
- X return;
- X if (n > curr->w_bot - curr->w_y + 1)
- X n = curr->w_bot - curr->w_y + 1;
- X curr->w_top = curr->w_y;
- X ScrollUpMap(n);
- X curr->w_top = old;
- X if (!display)
- X return;
- X ScrollRegion(curr->w_y, curr->w_bot, n);
- X GotoPos(curr->w_x, curr->w_y);
- X}
- X
- Xstatic void
- XInsertLine(n)
- Xint n;
- X{
- X register int old = curr->w_top;
- X
- X if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
- X return;
- X if (n > curr->w_bot - curr->w_y + 1)
- X n = curr->w_bot - curr->w_y + 1;
- X curr->w_top = curr->w_y;
- X ScrollDownMap(n);
- X curr->w_top = old;
- X if (!display)
- X return;
- X ScrollRegion(curr->w_y, curr->w_bot, -n);
- X GotoPos(curr->w_x, curr->w_y);
- X}
- X
- X
- Xstatic void
- XScrollUpMap(n)
- Xint n;
- X{
- X char tmp[256 * sizeof(char *)];
- X register int i, cnt1, cnt2;
- X register char **ppi, **ppa, **ppf;
- X#ifdef COPY_PASTE
- X register int ii;
- X#endif
- X
- X i = curr->w_top + n;
- X cnt1 = n * sizeof(char *);
- X cnt2 = (curr->w_bot - i + 1) * sizeof(char *);
- X ppi = curr->w_image + i;
- X ppa = curr->w_attr + i;
- X ppf = curr->w_font + i;
- X#ifdef COPY_PASTE
- X for(ii = curr->w_top; ii < i; ii++)
- X AddLineToHist(curr, &curr->w_image[ii], &curr->w_attr[ii], &curr->w_font[ii]);
- X#endif
- X for (i = n; i; --i)
- X {
- X bclear(*--ppi, cols + 1);
- X bzero(*--ppa, cols + 1);
- X bzero(*--ppf, cols + 1);
- X }
- X Scroll((char *) ppi, cnt1, cnt2, tmp);
- X Scroll((char *) ppa, cnt1, cnt2, tmp);
- X Scroll((char *) ppf, cnt1, cnt2, tmp);
- X}
- X
- Xstatic void
- XScrollDownMap(n)
- Xint n;
- X{
- X char tmp[256 * sizeof(char *)];
- X register int i, cnt1, cnt2;
- X register char **ppi, **ppa, **ppf;
- X
- X i = curr->w_top;
- X cnt1 = (curr->w_bot - i - n + 1) * sizeof(char *);
- X cnt2 = n * sizeof(char *);
- X Scroll((char *) (ppi = curr->w_image + i), cnt1, cnt2, tmp);
- X Scroll((char *) (ppa = curr->w_attr + i), cnt1, cnt2, tmp);
- X Scroll((char *) (ppf = curr->w_font + i), cnt1, cnt2, tmp);
- X for (i = n; i; --i)
- X {
- X bclear(*ppi++, cols + 1);
- X bzero(*ppa++, cols + 1);
- X bzero(*ppf++, cols + 1);
- X }
- X}
- X
- Xstatic void
- XScroll(cp, cnt1, cnt2, tmp)
- Xchar *cp, *tmp;
- Xint cnt1, cnt2;
- X{
- X if (!cnt1 || !cnt2)
- X return;
- X if (cnt1 <= cnt2)
- X {
- X bcopy(cp, tmp, cnt1);
- X bcopy(cp + cnt1, cp, cnt2);
- X bcopy(tmp, cp + cnt2, cnt1);
- X }
- X else
- X {
- X bcopy(cp + cnt1, tmp, cnt2);
- X bcopy(cp, cp + cnt2, cnt1);
- X bcopy(tmp, cp, cnt2);
- X }
- X}
- X
- Xstatic void
- XForwardTab()
- X{
- X register int x = curr->w_x;
- X
- X if (x == cols)
- X {
- X LineFeed(2);
- X x = 0;
- X }
- X if (curr->w_tabs[x] && x < cols - 1)
- X x++;
- X while (x < cols - 1 && !curr->w_tabs[x])
- X x++;
- X GotoPos(x, curr->w_y);
- X curr->w_x = x;
- X}
- X
- Xstatic void
- XBackwardTab()
- X{
- X register int x = curr->w_x;
- X
- X if (curr->w_tabs[x] && x > 0)
- X x--;
- X while (x > 0 && !curr->w_tabs[x])
- X x--;
- X GotoPos(x, curr->w_y);
- X curr->w_x = x;
- X}
- X
- Xstatic void
- XClearScreen()
- X{
- X register int i;
- X register char **ppi = curr->w_image, **ppa = curr->w_attr, **ppf = curr->w_font;
- X
- X for (i = 0; i < rows; ++i)
- X {
- X#ifdef COPY_PASTE
- X AddLineToHist(curr, ppi, ppa, ppf);
- X#endif
- X bclear(*ppi++, cols + 1);
- X bzero(*ppa++, cols + 1);
- X bzero(*ppf++, cols + 1);
- X }
- X if (display)
- X ClearDisplay();
- X}
- X
- Xstatic void
- XClearFromBOS()
- X{
- X register int n, y = curr->w_y, x = curr->w_x;
- X
- X if (display)
- X Clear(0, 0, x, y);
- X for (n = 0; n < y; ++n)
- X ClearInLine(n, 0, cols - 1);
- X ClearInLine(y, 0, x);
- X RestorePosAttrFont();
- X}
- X
- Xstatic void
- XClearToEOS()
- X{
- X register int n, y = curr->w_y, x = curr->w_x;
- X
- X if (x == 0 && y == 0)
- X {
- X ClearScreen();
- X return;
- X }
- X if (display)
- X Clear(x, y, d_width - 1, d_height - 1);
- X ClearInLine(y, x, cols - 1);
- X for (n = y + 1; n < rows; n++)
- X ClearInLine(n, 0, cols - 1);
- X RestorePosAttrFont();
- X}
- X
- Xstatic void
- XClearFullLine()
- X{
- X register int y = curr->w_y;
- X
- X if (display)
- X Clear(0, y, d_width - 1, y);
- X ClearInLine(y, 0, cols - 1);
- X RestorePosAttrFont();
- X}
- X
- Xstatic void
- XClearToEOL()
- X{
- X register int y = curr->w_y, x = curr->w_x;
- X
- X if (display)
- X Clear(x, y, d_width - 1, y);
- X ClearInLine(y, x, cols - 1);
- X RestorePosAttrFont();
- X}
- X
- Xstatic void
- XClearFromBOL()
- X{
- X register int y = curr->w_y, x = curr->w_x;
- X
- X if (display)
- X Clear(0, y, x, y);
- X ClearInLine(y, 0, x);
- X RestorePosAttrFont();
- X}
- X
- Xstatic void
- XClearInLine(y, x1, x2)
- Xint y, x1, x2;
- X{
- X register int n;
- X
- X if (x1 == cols)
- X x1--;
- X if (x2 == cols - 1)
- X x2++;
- X if ((n = x2 - x1 + 1) != 0)
- X {
- X bclear(curr->w_image[y] + x1, n);
- X bzero(curr->w_attr[y] + x1, n);
- X bzero(curr->w_font[y] + x1, n);
- X }
- X}
- X
- Xstatic void
- XCursorRight(n)
- Xregister int n;
- X{
- X register int x = curr->w_x;
- X
- X if (x == cols)
- X {
- X LineFeed(2);
- X x = 0;
- X }
- X if ((curr->w_x += n) >= cols)
- X curr->w_x = cols - 1;
- X GotoPos(curr->w_x, curr->w_y);
- X}
- X
- Xstatic void
- XCursorUp(n)
- Xregister int n;
- X{
- X if (curr->w_y < curr->w_top) /* if above scrolling rgn, */
- X {
- X if ((curr->w_y -= n) < 0) /* ignore its limits */
- X curr->w_y = 0;
- X }
- X else
- X if ((curr->w_y -= n) < curr->w_top)
- X curr->w_y = curr->w_top;
- X GotoPos(curr->w_x, curr->w_y);
- X}
- X
- Xstatic void
- XCursorDown(n)
- Xregister int n;
- X{
- X if (curr->w_y > curr->w_bot) /* if below scrolling rgn, */
- X {
- X if ((curr->w_y += n) > rows - 1) /* ignore its limits */
- X curr->w_y = rows - 1;
- X }
- X else
- X if ((curr->w_y += n) > curr->w_bot)
- X curr->w_y = curr->w_bot;
- X GotoPos(curr->w_x, curr->w_y);
- X}
- X
- Xstatic void
- XCursorLeft(n)
- Xregister int n;
- X{
- X if ((curr->w_x -= n) < 0)
- X curr->w_x = 0;
- X GotoPos(curr->w_x, curr->w_y);
- X}
- X
- Xstatic void
- XASetMode(on)
- Xint on;
- X{
- X register int i;
- X
- X for (i = 0; i < curr->w_NumArgs; ++i)
- X {
- X switch (curr->w_args[i])
- X {
- X case 4:
- X curr->w_insert = on;
- X InsertMode(on);
- X break;
- X }
- X }
- X}
- X
- Xstatic char rendlist[] =
- X{
- X (1 << NATTR), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0,
- X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- X 0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV
- X};
- X
- Xstatic void
- XSelectRendition()
- X{
- X register int j, i = 0, a = curr->w_Attr;
- X
- X do
- X {
- X j = curr->w_args[i];
- X if (j < 0 || j >= (sizeof(rendlist)/sizeof(*rendlist)))
- X continue;
- X j = rendlist[j];
- X if (j & (1 << NATTR))
- X a &= j;
- X else
- X a |= j;
- X }
- X while (++i < curr->w_NumArgs);
- X SetAttr(curr->w_Attr = a);
- X}
- X
- Xstatic void
- XFillWithEs()
- X{
- X register int i;
- X register char *p, *ep;
- X
- X curr->w_y = curr->w_x = 0;
- X for (i = 0; i < rows; ++i)
- X {
- X bzero(curr->w_attr[i], cols);
- X bzero(curr->w_font[i], cols);
- X p = curr->w_image[i];
- X ep = p + cols;
- X while (p < ep)
- X *p++ = 'E';
- X }
- X if (display)
- X Redisplay(0);
- X}
- X
- X
- Xstatic void
- XUpdateLine(os, oa, of, y, from, to)
- Xint from, to, y;
- Xchar *os, *oa, *of;
- X{
- X ASSERT(display);
- X DisplayLine(os, oa, of, curr->w_image[y], curr->w_attr[y],
- X curr->w_font[y], y, from, to);
- X RestorePosAttrFont();
- X}
- X
- Xvoid
- XCheckLP(n_ch)
- Xchar n_ch;
- X{
- X register int y, x;
- X register char n_at, n_fo, o_ch, o_at, o_fo;
- X
- X ASSERT(display);
- X x = cols - 1;
- X y = d_bot;
- X o_ch = curr->w_image[y][x];
- X o_at = curr->w_attr[y][x];
- X o_fo = curr->w_font[y][x];
- X
- X n_at = curr->w_Attr;
- X n_fo = curr->w_Font;
- X
- X d_lp_image = n_ch;
- X d_lp_attr = n_at;
- X d_lp_font = n_fo;
- X d_lp_missing = 0;
- X if (n_ch == o_ch && n_at == o_at && n_fo == o_fo)
- X return;
- X if (n_ch != ' ' || n_at || n_fo)
- X d_lp_missing = 1;
- X if (o_ch != ' ' || o_at || o_fo)
- X {
- X if (DC)
- X PutStr(DC);
- X else if (CDC)
- X CPutStr(CDC, 1);
- X else if (CE)
- X PutStr(CE);
- X else
- X d_lp_missing = 1;
- X }
- X}
- X
- X/*
- X * Ugly autoaka hack support:
- X * ChangeAKA() sets a new aka
- X * FindAKA() searches for an autoaka match
- X */
- X
- Xvoid
- XChangeAKA(p, s, l)
- Xstruct win *p;
- Xchar *s;
- Xint l;
- X{
- X if (l > 20)
- X l = 20;
- X strncpy(p->w_akachange, s, l);
- X p->w_akachange[l] = 0;
- X p->w_aka = p->w_akachange;
- X if (p->w_akachange != p->w_akabuf)
- X if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':')
- X p->w_aka = p->w_akabuf + strlen(p->w_akabuf) + 1;
- X}
- X
- Xstatic void
- XFindAKA()
- X{
- X register char *cp, *line;
- X register struct win *wp = curr;
- X register int len = strlen(wp->w_akabuf);
- X int y;
- X
- X y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y;
- X cols = wp->w_width;
- X try_line:
- X cp = line = wp->w_image[y];
- X if (wp->w_autoaka > 0 && *wp->w_akabuf != '\0')
- X {
- X for (;;)
- X {
- X if (cp - line >= cols - len)
- X {
- X if (++y == wp->w_autoaka && y < rows)
- X goto try_line;
- X return;
- X }
- X if (strncmp(cp, wp->w_akabuf, len) == 0)
- X break;
- X cp++;
- X }
- X cp += len;
- X }
- X for (len = cols - (cp - line); len && *cp == ' '; len--, cp++)
- X ;
- X if (len)
- X {
- X if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^'))
- X wp->w_autoaka = -1;
- X else
- X wp->w_autoaka = 0;
- X line = cp;
- X while (len && *cp != ' ')
- X {
- X if (*cp++ == '/')
- X line = cp;
- X len--;
- X }
- X ChangeAKA(wp, line, cp - line);
- X }
- X else
- X wp->w_autoaka = 0;
- X}
- X
- Xvoid
- XMakeBlankLine(p, n)
- Xregister char *p;
- Xregister int n;
- X{
- X while (n--)
- X *p++ = ' ';
- X}
- X
- Xvoid
- XSetCurr(wp)
- Xstruct win *wp;
- X{
- X curr = wp;
- X if (curr == 0)
- X return;
- X cols = curr->w_width;
- X rows = curr->w_height;
- X display = curr->w_active ? curr->w_display : 0;
- X}
- X
- Xstatic void
- XRestorePosAttrFont()
- X{
- X GotoPos(curr->w_x, curr->w_y);
- X SetAttr(curr->w_Attr);
- X SetFont(curr->w_Font);
- X}
- X
- X/* Send a terminal report as if it were typed. */
- Xstatic void
- XReport(fmt, n1, n2)
- Xchar *fmt;
- Xint n1, n2;
- X{
- X register int len;
- X char rbuf[40];
- X
- X sprintf(rbuf, fmt, n1, n2);
- X len = strlen(rbuf);
- X
- X if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf))
- X {
- X bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len);
- X curr->w_inlen += len;
- X }
- X}
- X
- X#ifdef COPY_PASTE
- Xvoid
- XAddLineToHist(wp, pi, pa, pf)
- Xstruct win *wp;
- Xchar **pi, **pa, **pf;
- X{
- X register char *q, *o;
- X
- X if (wp->w_histheight == 0)
- X return;
- X q = *pi; *pi = wp->w_ihist[wp->w_histidx]; wp->w_ihist[wp->w_histidx] = q;
- X q = *pa; o = wp->w_ahist[wp->w_histidx]; wp->w_ahist[wp->w_histidx] = q;
- X if (o != null)
- X free(o);
- X
- X q = *pf; o = wp->w_fhist[wp->w_histidx]; wp->w_fhist[wp->w_histidx] = q;
- X if (o != null)
- X free(o);
- X *pa = *pf = null;
- X if (++wp->w_histidx >= wp->w_histheight)
- X wp->w_histidx = 0;
- X}
- X#endif
- END_OF_FILE
- if test 39996 -ne `wc -c <'ansi.c'`; then
- echo shar: \"'ansi.c'\" unpacked with wrong size!
- fi
- # end of 'ansi.c'
- fi
- if test -f 'screen.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'screen.c'\"
- else
- echo shar: Extracting \"'screen.c'\" \(50777 characters\)
- sed "s/^X//" >'screen.c' <<'END_OF_FILE'
- X/* Copyright (c) 1993
- X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
- X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
- X * Copyright (c) 1987 Oliver Laumann
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2, or (at your option)
- X * any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program (see the file COPYING); if not, write to the
- X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X ****************************************************************
- X */
- X
- X#include "rcs.h"
- XRCS_ID("$Id: screen.c,v 1.9 1993/07/09 12:07:49 jnweiger Exp $ FAU")
- X
- X
- X#include <ctype.h>
- X#ifdef __sgi
- X# include <stdio.h> /* needed before pwd.h to avoid ansi compiler whining */
- X#endif /* __sgi */
- X#include <pwd.h>
- X#include <fcntl.h>
- X#ifdef sgi
- X# include <sys/sysmacros.h>
- X#endif /* sgi */
- X#if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX)
- X# include <time.h>
- X#endif
- X#include <sys/time.h>
- X#if defined(M_XENIX) || defined(M_UNIX)
- X#include <sys/select.h> /* for timeval */
- X#endif
- X#include <sys/types.h>
- X#ifdef ISC
- X# include <sys/bsdtypes.h>
- X#endif
- X#include <sys/stat.h>
- X#ifndef sgi
- X# include <sys/file.h>
- X#endif /* sgi */
- X#ifndef sun
- X# include <sys/ioctl.h>
- X#endif /* sun */
- X
- X#include <signal.h>
- X
- X#include "config.h"
- X
- X#ifdef SHADOWPW
- X# include <shadow.h>
- X#endif /* SHADOWPW */
- X
- X#ifdef SVR4
- X# include <sys/stropts.h>
- X#endif
- X
- X#ifdef SYSV
- X# include <sys/utsname.h>
- X#endif
- X
- X#if defined(sequent) || defined(SVR4)
- X# include <sys/resource.h>
- X#endif /* sequent || SVR4 */
- X
- X#ifdef ISC
- X# include <sys/tty.h>
- X# include <sys/sioctl.h>
- X# include <sys/pty.h>
- X#endif /* ISC */
- X
- X#include "screen.h"
- X
- X#include "patchlevel.h"
- X
- X#if defined(xelos) || defined(m68k) || defined(M_XENIX)
- X struct passwd *getpwuid __P((uid_t));
- X struct passwd *getpwnam __P((char *));
- X#endif
- X
- X#ifdef USEVARARGS
- X# if defined(__STDC__)
- X# include <stdarg.h>
- X# else
- X# include <varargs.h>
- X# endif
- X#endif
- X
- X#if defined(_SEQUENT_)
- X/* for the FD.. stuff */
- X# include <sys/select.h>
- X#endif /* _SEQUENT_ */
- X
- X#ifndef FD_SET
- Xtypedef struct fd_set
- X{
- X int fd_bits[1];
- X} fd_set;
- X# define FD_ZERO(fd) ((fd)->fd_bits[0] = 0)
- X# define FD_SET(b, fd) ((fd)->fd_bits[0] |= 1 << (b))
- X# define FD_ISSET(b, fd) ((fd)->fd_bits[0] & 1 << (b))
- X# define FD_SETSIZE 32
- X#endif
- X
- X
- X#ifdef DEBUG
- XFILE *dfp;
- X#endif
- X
- X
- Xextern char *blank, *null, Term[], screenterm[], **environ, Termcap[];
- Xint force_vt = 1, assume_LP = 0;
- Xint VBellWait, MsgWait, MsgMinWait, SilenceWait;
- X
- Xextern struct display *displays, *display;
- Xextern struct layer BlankLayer;
- X
- X/* tty.c */
- Xextern int intrc;
- X
- X
- Xextern int use_hardstatus;
- X#ifdef COPY_PASTE
- Xextern char mark_key_tab[];
- X#endif
- Xextern char version[];
- Xextern char DefaultShell[];
- X
- X
- Xchar *ShellProg;
- Xchar *ShellArgs[2];
- X
- Xextern struct NewWindow nwin_undef, nwin_default, nwin_options;
- X
- Xstatic char *MakeWinMsg __P((char *, int));
- Xstatic void SigChldHandler __P((void));
- Xstatic sig_t SigChld __P(SIGPROTOARG);
- Xstatic sig_t SigInt __P(SIGPROTOARG);
- Xstatic sig_t CoreDump __P((int));
- Xstatic void DoWait __P((void));
- X
- X
- X#ifdef PASSWORD
- Xextern char Password[];
- X#endif
- X
- X
- X/* the attacher */
- Xstruct passwd *ppp;
- Xchar *attach_tty;
- Xchar *attach_term;
- Xchar *LoginName;
- Xstruct mode attach_Mode;
- X
- X
- X#ifdef SOCKDIR
- Xchar *SockDir = SOCKDIR;
- X#else
- Xchar *SockDir = ".iscreen";
- X#endif
- Xextern char SockPath[], *SockNamePtr, *SockName;
- Xint ServerSocket = -1;
- Xchar **NewEnv = NULL;
- X
- Xchar *RcFileName = NULL;
- Xextern char Esc;
- Xchar *home;
- X
- Xchar *screenlogdir = NULL;
- Xchar *hardcopydir = NULL;
- Xchar *BellString;
- Xchar *VisualBellString;
- Xchar *ActivityString;
- X#ifdef COPY_PASTE
- Xchar *BufferFile;
- X#endif
- X#ifdef POW_DETACH
- Xchar *PowDetachString;
- X#endif
- Xint auto_detach = 1;
- Xint iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag;
- Xint adaptflag;
- X
- Xtime_t Now;
- X
- X#ifdef MULTIUSER
- Xchar *multi;
- Xchar *multi_home;
- Xint multi_uid;
- Xint own_uid;
- Xint multiattach;
- Xint tty_mode;
- Xint tty_oldmode = -1;
- X#endif
- X
- Xchar HostName[MAXSTR];
- Xint MasterPid;
- Xint real_uid, real_gid, eff_uid, eff_gid;
- Xint default_startup;
- Xint slowpaste;
- X
- X#ifdef NETHACK
- Xint nethackflag = 0;
- X#endif
- X
- X
- Xstruct win *fore = NULL;
- Xstruct win *windows = NULL;
- Xstruct win *console_window;
- X
- X
- X/*
- X * Do this last
- X */
- X#include "extern.h"
- X
- X/*
- X * XXX: Missing system header files.
- X */
- X#ifdef USEVARARGS
- X# ifndef VPRNT_DECLARED
- Xint vsprintf __P((char *, char *, va_list));
- X# endif /* VPRNT_DECLARED */
- X#endif
- X#ifndef SELECT_DECLARED
- Xint select __P((int, fd_set *, fd_set *, fd_set *, const struct timeval *));
- X#endif
- X
- X#ifdef NETHACK
- Xchar strnomem[] = "Who was that Maude person anyway?";
- X#else
- Xchar strnomem[] = "Out of memory.";
- X#endif
- X
- X
- Xstatic int InterruptPlease = 0;
- Xstatic int GotSigChld;
- X
- X
- Xstatic void
- Xmkfdsets(rp, wp)
- Xfd_set *rp, *wp;
- X{
- X register struct win *p;
- X
- X FD_ZERO(rp);
- X FD_ZERO(wp);
- X for (display = displays; display; display = display->_d_next)
- X {
- X if (d_obufp != d_obuf)
- X FD_SET(d_userfd, wp);
- X
- X FD_SET(d_userfd, rp); /* Do that always */
- X
- X /* read from terminal if there is room in the destination buffer
- X *
- X * Removed, so we can always input a command sequence
- X *
- X * if (d_fore == 0)
- X * continue;
- X * if (W_UWP(d_fore))
- X * {
- X * check pseudowin buffer
- X * if (d_fore->w_pwin->p_inlen < sizeof(d_fore->w_pwin->p_inbuf))
- X * FD_SET(d_userfd, rp);
- X * }
- X * else
- X * {
- X * check window buffer
- X * if (d_fore->w_inlen < sizeof(d_fore->w_inbuf))
- X * FD_SET(d_userfd, rp);
- X * }
- X */
- X }
- X for (p = windows; p; p = p->w_next)
- X {
- X#ifdef COPY_PASTE
- X if (p->w_pastelen)
- X {
- X /* paste to win/pseudo */
- X# ifdef PSEUDOS
- X FD_SET(W_UWP(p) ? p->w_pwin->p_ptyfd : p->w_ptyfd, wp);
- X# else
- X FD_SET(p->w_ptyfd, wp);
- X# endif
- X }
- X#endif
- X /* query window buffer */
- X if (p->w_inlen > 0)
- X FD_SET(p->w_ptyfd, wp);
- X#ifdef PSEUDOS
- X /* query pseudowin buffer */
- X if (p->w_pwin && p->w_pwin->p_inlen > 0)
- X FD_SET(p->w_pwin->p_ptyfd, wp);
- X#endif
- X
- X display = p->w_display;
- X if (p->w_active && d_status && !d_status_bell && !(use_hardstatus && HS))
- X continue;
- X if (p->w_outlen > 0)
- X continue;
- X if (p->w_lay->l_block)
- X continue;
- X /*
- X * Don't accept input from window or pseudowin if there is to much
- X * output pending on display .
- X */
- X if (p->w_active && (d_obufp - d_obuf) > d_obufmax)
- X {
- X debug1("too much output pending, window %d\n", p->w_number);
- X continue;
- X }
- X#ifdef PSEUDOS
- X if (W_RW(p))
- X {
- X /* Check free space if we stuff window output in pseudo */
- X if (p->w_pwin && W_WTOP(p) && (p->w_pwin->p_inlen >= sizeof(p->w_pwin->p_inbuf)))
- X {
- X debug2("pseudowin %d buffer full (%d bytes)\n", p->w_number, p->w_pwin->p_inlen);
- X }
- X else
- X FD_SET(p->w_ptyfd, rp);
- X }
- X if (W_RP(p))
- X {
- X /* Check free space if we stuff pseudo output in window */
- X if (W_PTOW(p) && p->w_inlen >= sizeof(p->w_inbuf))
- X {
- X debug2("window %d buffer full (%d bytes)\n", p->w_number, p->w_inlen);
- X }
- X else
- X FD_SET(p->w_pwin->p_ptyfd, rp);
- X }
- X#else /* PSEUDOS */
- X FD_SET(p->w_ptyfd, rp);
- X#endif /* PSEUDOS */
- X }
- X FD_SET(ServerSocket, rp);
- X}
- X
- Xvoid
- Xmain(ac, av)
- Xint ac;
- Xchar **av;
- X{
- X register int n, len;
- X register struct win *p;
- X char *ap;
- X char *av0;
- X char socknamebuf[2 * MAXSTR];
- X fd_set r, w;
- X int mflag = 0;
- X struct timeval tv;
- X int nsel;
- X char buf[IOSIZE], *myname = (ac == 0) ? "screen" : av[0];
- X struct stat st;
- X int buflen, tmp;
- X#ifdef _MODE_T /* (jw) */
- X mode_t oumask;
- X#else
- X int oumask;
- X#endif
- X#ifdef SYSV
- X struct utsname utsnam;
- X#endif
- X struct NewWindow nwin;
- X int detached = 0; /* start up detached */
- X struct display *ndisplay;
- X#ifdef MULTIUSER
- X char *sockp;
- X#endif
- X
- X /*
- X * First, close all unused descriptors
- X * (otherwise, we might have problems with the select() call)
- X */
- X closeallfiles(0);
- X#ifdef DEBUG
- X (void) mkdir("/tmp/debug", 0777);
- X if ((dfp = fopen("/tmp/debug/screen.front", "w")) == NULL)
- X dfp = stderr;
- X else
- X (void) chmod("/tmp/debug/screen.front", 0666);
- X#endif
- X sprintf(version, "%d.%.2d.%.2d%s (%s) %s", REV, VERS,
- X PATCHLEVEL, STATE, ORIGIN, DATE);
- X debug2("-- screen debug started %s (%s)\n", *av, version);
- X#ifdef POSIX
- X debug("POSIX\n");
- X#endif
- X#ifdef TERMIO
- X debug("TERMIO\n");
- X#endif
- X#ifdef SYSV
- X debug("SYSV\n");
- X#endif
- X#ifdef SYSVSIGS
- X debug("SYSVSIGS\n");
- X#endif
- X#ifdef NAMEDPIPE
- X debug("NAMEDPIPE\n");
- X#endif
- X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
- X debug("Window changing enabled\n");
- X#endif
- X#ifdef NOREUID
- X debug("NOREUID\n");
- X#endif
- X#ifdef hpux
- X debug("hpux\n");
- X#endif
- X#ifdef USEBCOPY
- X debug("USEBCOPY\n");
- X#endif
- X#ifdef UTMPOK
- X debug("UTMPOK\n");
- X#endif
- X#ifdef LOADAV
- X debug("LOADAV\n");
- X#endif
- X#ifdef NETHACK
- X debug("NETHACK\n");
- X#endif
- X#ifdef TERMINFO
- X debug("TERMINFO\n");
- X#endif
- X#ifdef SHADOWPW
- X debug("SHADOWPW\n");
- X#endif
- X#ifdef NAME_MAX
- X debug1("NAME_MAX = %d\n", NAME_MAX);
- X#endif
- X
- X BellString = SaveStr("Bell in window %");
- X VisualBellString = SaveStr(" Wuff, Wuff!! ");
- X ActivityString = SaveStr("Activity in window %");
- X#ifdef COPY_PASTE
- X BufferFile = SaveStr(DEFAULT_BUFFERFILE);
- X#endif
- X ShellProg = NULL;
- X#ifdef POW_DETACH
- X PowDetachString = 0;
- X#endif
- X default_startup = (ac > 1) ? 0 : 1;
- X adaptflag = 0;
- X slowpaste = 0;
- X VBellWait = VBELLWAIT;
- X MsgWait = MSGWAIT;
- X MsgMinWait = MSGMINWAIT;
- X SilenceWait = SILENCEWAIT;
- X#ifdef COPY_PASTE
- X CompileKeys((char *)NULL, mark_key_tab);
- X#endif
- X nwin = nwin_undef;
- X nwin_options = nwin_undef;
- X
- X av0 = *av;
- X /* if this is a login screen, assume -R */
- X if (*av0 == '-')
- X {
- X rflag = 2;
- X#ifdef MULTI
- X xflag = 1;
- X#endif
- X ShellProg = SaveStr(DefaultShell); /* to prevent nasty circles */
- X }
- X while (ac > 0)
- X {
- X ap = *++av;
- X if (--ac > 0 && *ap == '-')
- X {
- X switch (ap[1])
- X {
- X case 'a':
- X nwin_options.aflag = 1;
- X break;
- X case 'A':
- X adaptflag = 1;
- X break;
- X case 'c':
- X if (ap[2])
- X RcFileName = ap + 2;
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X RcFileName = *++av;
- X }
- X break;
- X case 'e':
- X if (ap[2])
- X ap += 2;
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X ap = *++av;
- X }
- X if (ParseEscape(ap))
- X Panic(0, "Two characters are required with -e option.");
- X break;
- X case 'f':
- X switch (ap[2])
- X {
- X case 'n':
- X case '0':
- X nwin_options.flowflag = FLOW_NOW * 0;
- X break;
- X case 'y':
- X case '1':
- X case '\0':
- X nwin_options.flowflag = FLOW_NOW * 1;
- X break;
- X case 'a':
- X nwin_options.flowflag = FLOW_AUTOFLAG;
- X break;
- X default:
- X exit_with_usage(myname);
- X }
- X break;
- X case 'h':
- X if (ap[2])
- X nwin_options.histheight = atoi(ap + 2);
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X nwin_options.histheight = atoi(*++av);
- X }
- X if (nwin_options.histheight < 0)
- X exit_with_usage(myname);
- X break;
- X case 'i':
- X iflag = 1;
- X break;
- X case 't': /* title is a synonym for AkA */
- X case 'k':
- X if (ap[2])
- X nwin_options.aka = ap + 2;
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X nwin_options.aka = *++av;
- X }
- X break;
- X case 'l':
- X switch (ap[2])
- X {
- X case 'n':
- X case '0':
- X nwin_options.lflag = 0;
- X break;
- X case 'y':
- X case '1':
- X case '\0':
- X nwin_options.lflag = 1;
- X break;
- X case 's':
- X case 'i':
- X lsflag = 1;
- X if (ac > 1)
- X {
- X SockName = *++av;
- X ac--;
- X }
- X break;
- X default:
- X exit_with_usage(myname);
- X }
- X break;
- X case 'w':
- X lsflag = 1;
- X wipeflag = 1;
- X break;
- X case 'L':
- X assume_LP = 1;
- X break;
- X case 'm':
- X mflag = 1;
- X break;
- X case 'O':
- X force_vt = 0;
- X break;
- X case 'T':
- X if (ap[2])
- X {
- X if (strlen(ap+2) < 20)
- X strcpy(screenterm, ap + 2);
- X }
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X if (strlen(*++av) < 20)
- X strcpy(screenterm, *av);
- X }
- X nwin_options.term = screenterm;
- X break;
- X case 'q':
- X quietflag = 1;
- X break;
- X case 'r':
- X case 'R':
- X#ifdef MULTI
- X case 'x':
- X#endif
- X if (ap[2])
- X {
- X SockName = ap + 2;
- X if (ac != 1)
- X exit_with_usage(myname);
- X }
- X else if (ac > 1 && *av[1] != '-')
- X {
- X SockName = *++av;
- X ac--;
- X }
- X#ifdef MULTI
- X if (ap[1] == 'x')
- X xflag = 1;
- X else
- X#endif
- X rflag = (ap[1] == 'r') ? 1 : 2;
- X break;
- X#ifdef REMOTE_DETACH
- X case 'd':
- X dflag = 1;
- X /* FALLTHROUGH */
- X case 'D':
- X if (!dflag)
- X dflag = 2;
- X if (ap[2])
- X SockName = ap + 2;
- X if (ac == 2)
- X {
- X if (*av[1] != '-')
- X {
- X SockName = *++av;
- X ac--;
- X }
- X }
- X break;
- X#endif
- X case 's':
- X if (ap[2])
- X {
- X if (ShellProg)
- X free(ShellProg);
- X ShellProg = SaveStr(ap + 2);
- X }
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X if (ShellProg)
- X free(ShellProg);
- X ShellProg = SaveStr(*++av);
- X }
- X debug1("ShellProg: '%s'\n", ShellProg);
- X break;
- X case 'S':
- X if (ap[2])
- X SockName = ap + 2;
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X SockName = *++av;
- X if (!*SockName)
- X exit_with_usage(myname);
- X }
- X break;
- X case 'v':
- X Panic(0, "Screen version %s", version);
- X /* NOTREACHED */
- X default:
- X exit_with_usage(myname);
- X }
- X }
- X else
- X break;
- X }
- X if (dflag && mflag && SockName && !(rflag || xflag))
- X detached = 1;
- X nwin = nwin_options;
- X if (ac)
- X nwin.args = av;
- X real_uid = getuid();
- X real_gid = getgid();
- X eff_uid = geteuid();
- X eff_gid = getegid();
- X if (eff_uid != real_uid)
- X {
- X /* if running with s-bit, we must install a special signal
- X * handler routine that resets the s-bit, so that we get a
- X * core file anyway.
- X */
- X#ifdef SIGBUS /* OOPS, linux has no bus errors ??? */
- X signal(SIGBUS, CoreDump);
- X#endif /* SIGBUS */
- X signal(SIGSEGV, CoreDump);
- X }
- X if (!ShellProg)
- X {
- X register char *sh;
- X
- X sh = getenv("SHELL");
- X ShellProg = SaveStr(sh ? sh : DefaultShell);
- X }
- X ShellArgs[0] = ShellProg;
- X#ifdef NETHACK
- X nethackflag = (getenv("NETHACKOPTIONS") != NULL);
- X#endif
- X#ifdef MULTIUSER
- X own_uid = multi_uid = real_uid;
- X if (SockName && (sockp = index(SockName, '/')))
- X {
- X if (eff_uid)
- X Panic(0, "Must run suid root for multi support.");
- X *sockp = 0;
- X multi = SockName;
- X SockName = sockp + 1;
- X if (*multi)
- X {
- X struct passwd *mppp;
- X if ((mppp = getpwnam(multi)) == (struct passwd *) 0)
- X Panic(0, "Cannot identify account '%s'.", multi);
- X multi_uid = mppp->pw_uid;
- X multi_home = SaveStr(mppp->pw_dir);
- X#ifdef MULTI
- X if (rflag || lsflag)
- X {
- X xflag = 1;
- X rflag = 0;
- X }
- X#endif
- X detached = 0;
- X multiattach = 1;
- X }
- X }
- X if (SockName && *SockName == 0)
- X SockName = 0;
- X#endif
- X if ((LoginName = getlogin()) && LoginName[0] != '\0')
- X {
- X if ((ppp = getpwnam(LoginName)) != (struct passwd *) 0)
- X if (ppp->pw_uid != real_uid)
- X ppp = (struct passwd *) 0;
- X }
- X if (ppp == 0)
- X {
- X if ((ppp = getpwuid(real_uid)) == 0)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Panic(0, "An alarm sounds through the dungeon...\nWarning, the kops are coming.");
- X else
- X#endif
- X Panic(0, "getpwuid() can't identify your account!");
- X exit(1);
- X }
- X LoginName = ppp->pw_name;
- X }
- X home = getenv("HOME"); /* may or may not return a result. jw. */
- X#if !defined(SOCKDIR) && defined(MULTIUSER)
- X if (multi && !multiattach)
- X {
- X if (home && strcmp(home, ppp->pw_dir))
- X Panic(0, "$HOME must match passwd entry for multi screens");
- X }
- X#endif
- X if (home == 0 || *home == '\0')
- X home = ppp->pw_dir;
- X if (strlen(LoginName) > 20)
- X Panic(0, "LoginName too long - sorry.");
- X if (strlen(home) > MAXPATHLEN - 25)
- X Panic(0, "$HOME too long - sorry.");
- X#ifdef PASSWORD
- X strcpy(Password, ppp->pw_passwd);
- X#endif
- X
- X if (!detached && !lsflag)
- X {
- X /* ttyname implies isatty */
- X if (!(attach_tty = ttyname(0)))
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Panic(0, "You must play from a terminal.");
- X else
- X#endif
- X Panic(0, "Must be connected to a terminal.");
- X exit(1);
- X }
- X if (strlen(attach_tty) >= MAXPATHLEN)
- X Panic(0, "TtyName too long - sorry.");
- X if (stat(attach_tty, &st))
- X Panic(errno, "Cannot access '%s'", attach_tty);
- X#ifdef MULTIUSER
- X tty_mode = st.st_mode & 0777;
- X#endif
- X if ((n = secopen(attach_tty, O_RDWR, 0)) < 0)
- X Panic(0, "Cannot open '%s' - please check.", attach_tty);
- X close(n);
- X debug1("attach_tty is %s\n", attach_tty);
- X if ((attach_term = getenv("TERM")) == 0)
- X Panic(0, "Please set a terminal type.");
- X if (strlen(attach_term) > sizeof(d_termname) - 1)
- X Panic(0, "$TERM too long - sorry.");
- X GetTTY(0, &attach_Mode);
- X#ifdef DEBUGGGGGGGGGGGGGGG
- X DebugTTY(&attach_Mode);
- X#endif /* DEBUG */
- X }
- X
- X#ifdef _MODE_T
- X oumask = umask(0); /* well, unsigned never fails? jw. */
- X#else
- X if ((oumask = umask(0)) == -1)
- X Panic(errno, "Cannot change umask to zero");
- X#endif
- X if ((SockDir = getenv("ISCREENDIR")) == NULL)
- X SockDir = getenv("SCREENDIR");
- X if (SockDir)
- X {
- X if (strlen(SockDir) >= MAXPATHLEN - 1)
- X Panic(0, "Ridiculously long $(I)SCREENDIR - try again.");
- X#ifdef MULTIUSER
- X if (multi)
- X Panic(0, "No $(I)SCREENDIR with multi screens, please.");
- X#endif
- X }
- X#ifdef MULTIUSER
- X if (multiattach)
- X {
- X# ifndef SOCKDIR
- X sprintf(SockPath, "%s/.iscreen", multi_home);
- X SockDir = SockPath;
- X# else
- X SockDir = SOCKDIR;
- X sprintf(SockPath, "%s/S-%s", SockDir, multi);
- X# endif
- X }
- X else
- X#endif
- X {
- X#ifndef SOCKDIR
- X if (SockDir == 0)
- X {
- X sprintf(SockPath, "%s/.iscreen", home);
- X SockDir = SockPath;
- X }
- X#endif
- X if (SockDir)
- X {
- X if (access(SockDir, F_OK))
- X {
- X debug1("SockDir '%s' missing ...\n", SockDir);
- X if (UserContext() > 0)
- X {
- X if (mkdir(SockDir, 0700))
- X UserReturn(0);
- X UserReturn(1);
- X }
- X if (UserStatus() <= 0)
- X Panic(0, "Cannot make directory '%s'.", SockDir);
- X }
- X if (SockDir != SockPath)
- X strcpy(SockPath, SockDir);
- X }
- X#ifdef SOCKDIR
- X else
- X {
- X SockDir = SOCKDIR;
- X if (stat(SockDir, &st))
- X {
- X if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1)
- X Panic(errno, "Cannot make directory '%s'", SockDir);
- X }
- X else
- X {
- X n = eff_uid ? 0777 : 0755;
- X if ((st.st_mode & 0777) != n)
- X Panic(0, "Directory '%s' must have mode %03o.", SockDir, n);
- X }
- X sprintf(SockPath, "%s/S-%s", SockDir, LoginName);
- X if (access(SockPath, F_OK))
- X {
- X if (mkdir(SockPath, 0700) == -1)
- X Panic(errno, "Cannot make directory '%s'", SockPath);
- X (void) chown(SockPath, real_uid, real_gid);
- X }
- X }
- X#endif
- X }
- X
- X if (stat(SockPath, &st) == -1)
- X {
- X Panic(errno, "Cannot access %s", SockPath);
- X }
- X else
- X {
- X#ifdef _POSIX_SOURCE
- X if (S_ISDIR(st.st_mode) == 0)
- X#else
- X if ((st.st_mode & S_IFMT) != S_IFDIR)
- X#endif
- X Panic(0, "%s is not a directory.", SockPath);
- X#ifdef MULTIUSER
- X if (multi)
- X {
- X if (st.st_uid != multi_uid)
- X Panic(0, "%s is not the owner of %s.", multi, SockPath);
- X }
- X else
- X#endif
- X {
- X if (st.st_uid != real_uid)
- X Panic(0, "You are not the owner of %s.", SockPath);
- X }
- X if ((st.st_mode & 0777) != 0700)
- X Panic(0, "Directory %s must have mode 700.", SockPath);
- X }
- X strcat(SockPath, "/");
- X SockNamePtr = SockPath + strlen(SockPath);
- X (void) umask(oumask);
- X debug2("SockPath: %s SockName: %s\n", SockPath, SockName ? SockName : "NULL");
- X
- X#if defined(SYSV) && !defined(ISC)
- X if (uname(&utsnam) == -1)
- X Panic(0, "uname() failed, errno = %d.", errno);
- X else
- X {
- X strncpy(HostName, utsnam.nodename, MAXSTR);
- X HostName[(sizeof(utsnam.nodename) <= MAXSTR) ?
- X sizeof(utsnam.nodename) : MAXSTR] = '\0';
- X }
- X#else
- X (void) gethostname(HostName, MAXSTR);
- X#endif
- X HostName[MAXSTR - 1] = '\0';
- X if ((ap = index(HostName, '.')) != NULL)
- X *ap = '\0';
- X
- X if (lsflag)
- X {
- X int i;
- X
- X#ifdef MULTIUSER
- X if (multi)
- X real_uid = multi_uid;
- X setuid(real_uid);
- X setgid(real_gid);
- X eff_uid = real_uid;
- X eff_gid = real_gid;
- X#endif
- X i = FindSocket(0, (int *)NULL);
- X /* MakeClientSocket appended the last (Sock)Name there: */
- X *SockNamePtr = '\0';
- X if (i == 0)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Panic(0, "This room is empty (%s).\n", SockPath);
- X else
- X#endif /* NETHACK */
- X Panic(0, "No Sockets found in %s.\n", SockPath);
- X }
- X Panic(0, "%d Socket%s in %s.\n", i, i > 1 ? "s" : "", SockPath);
- X /* NOTREACHED */
- X }
- X signal(SIG_BYE, AttacherFinit); /* prevent races */
- X if (rflag || xflag)
- X {
- X debug("screen -r: - is there anybody out there?\n");
- X#ifdef SHADOWPW
- X setspent(); /* open shadow file while we are still root */
- X#endif /* SHADOWPW */
- X if (Attach(MSG_ATTACH))
- X {
- X Attacher();
- X /* NOTREACHED */
- X }
- X debug("screen -r: backend not responding -- still crying\n");
- X }
- X else if (dflag && !mflag)
- X {
- X (void) Attach(MSG_DETACH);
- X Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : ""));
- X eexit(0);
- X /* NOTREACHED */
- X }
- X if (!SockName && !mflag)
- X {
- X register char *sty;
- X int s;
- X
- X if ((sty = getenv("STY")) != 0 && *sty != '\0')
- X {
- X setuid(real_uid);
- X setgid(real_gid);
- X eff_uid = real_uid;
- X eff_gid = real_gid;
- X if ((s = MakeClientSocket(1, sty)) > 0)
- X {
- X nwin_options.args = av;
- X SendCreateMsg(s, &nwin);
- X close(s);
- X }
- X exit(0);
- X /* NOTREACHED */
- X }
- X }
- X nwin_compose(&nwin_default, &nwin_options, &nwin_default);
- X if (SockName && !*SockName)
- X SockName = NULL;
- X switch (MasterPid = fork())
- X {
- X case -1:
- X Panic(errno, "fork");
- X /* NOTREACHED */
- X#ifdef FORKDEBUG
- X default:
- X break;
- X case 0:
- X MasterPid = getppid();
- X#else
- X case 0:
- X break;
- X default:
- X#endif
- X if (detached)
- X exit(0);
- X if (SockName)
- X {
- X /* user started us with -S option */
- X sprintf(socknamebuf, "%d.%s", MasterPid, SockName);
- X }
- X else
- X {
- X sprintf(socknamebuf, "%d.%s.%s", MasterPid, stripdev(attach_tty),
- X HostName);
- X }
- X for (ap = socknamebuf; *ap; ap++)
- X if (*ap == '/')
- X *ap = '-';
- X SockName = socknamebuf;
- X#ifdef SHADOWPW
- X setspent(); /* open shadow file while we are still root */
- X#endif /* SHADOWPW */
- X setuid(real_uid);
- X setgid(real_gid);
- X eff_uid = real_uid;
- X eff_gid = real_gid;
- X Attacher();
- X /* NOTREACHED */
- X }
- X
- X ap = av0 + strlen(av0) - 1;
- X while (ap >= av0)
- X {
- X if (!strncmp("screen", ap, 6))
- X {
- X strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */
- X break;
- X }
- X ap--;
- X }
- X if (ap < av0)
- X *av0 = 'S';
- X
- X#ifdef DEBUG
- X if (dfp != stderr)
- X fclose(dfp);
- X if ((dfp = fopen("/tmp/debug/screen.back", "w")) == NULL)
- X dfp = stderr;
- X else
- X (void) chmod("/tmp/debug/screen.back", 0666);
- X#endif
- X if (!detached)
- X n = dup(0);
- X else
- X n = -1;
- X freopen("/dev/null", "r", stdin);
- X freopen("/dev/null", "w", stdout);
- X#ifdef DEBUG
- X if (dfp != stderr)
- X#endif
- X freopen("/dev/null", "w", stderr);
- X debug("-- screen.back debug started\n");
- X
- X if (!detached)
- X {
- X#ifdef FORKDEBUG
- X if (MakeDisplay(LoginName, attach_tty, attach_term, n, MasterPid, &attach_Mode) == 0)
- X#else
- X if (MakeDisplay(LoginName, attach_tty, attach_term, n, getppid(), &attach_Mode) == 0)
- X#endif
- X Panic(0, "Could not alloc display");
- X }
- X
- X if (SockName)
- X {
- X /* user started us with -S option */
- X sprintf(socknamebuf, "%d.%s", getpid(), SockName);
- X }
- X else
- X {
- X sprintf(socknamebuf, "%d.%s.%s", getpid(), stripdev(attach_tty),
- X HostName);
- X }
- X for (ap = socknamebuf; *ap; ap++)
- X if (*ap == '/')
- X *ap = '-';
- X SockName = socknamebuf;
- X ServerSocket = MakeServerSocket();
- X#ifdef ETCSCREENRC
- X if ((ap = getenv("SYSSCREENRC")) == NULL)
- X StartRc(ETCSCREENRC);
- X else
- X StartRc(ap);
- X#endif
- X StartRc(RcFileName);
- X# ifdef UTMPOK
- X# ifndef UTNOKEEP
- X InitUtmp();
- X# endif /* UTNOKEEP */
- X# endif /* UTMPOK */
- X if (display)
- X {
- X if (InitTermcap(0, 0))
- X {
- X debug("Could not init termcap - exiting\n");
- X fcntl(d_userfd, F_SETFL, 0); /* Flush sets NDELAY */
- X freetty();
- X if (d_userpid)
- X Kill(d_userpid, SIG_BYE);
- X eexit(1);
- X }
- X InitTerm(0);
- X#ifdef UTMPOK
- X RemoveLoginSlot();
- X#endif
- X }
- X else
- X {
- X MakeTermcap(1);
- X }
- X#ifdef LOADAV
- X InitLoadav();
- X#endif /* LOADAV */
- X MakeNewEnv();
- X signal(SIGHUP, SigHup);
- X signal(SIGINT, Finit);
- X signal(SIGQUIT, Finit);
- X signal(SIGTERM, Finit);
- X#ifdef BSDJOBS
- X signal(SIGTTIN, SIG_IGN);
- X signal(SIGTTOU, SIG_IGN);
- X#endif
- X InitKeytab();
- X if (display)
- X {
- X brktty(d_userfd);
- X SetMode(&d_OldMode, &d_NewMode);
- X /* Note: SetMode must be called _before_ FinishRc. */
- X SetTTY(d_userfd, &d_NewMode);
- X if (fcntl(d_userfd, F_SETFL, FNDELAY))
- X Msg(errno, "Warning: NDELAY fcntl failed");
- X }
- X else
- X brktty(-1); /* just try */
- X#ifdef ETCSCREENRC
- X if ((ap = getenv("SYSSCREENRC")) == NULL)
- X FinishRc(ETCSCREENRC);
- X else
- X FinishRc(ap);
- X#endif
- X FinishRc(RcFileName);
- X
- X debug2("UID %d EUID %d\n", getuid(), geteuid());
- X if (windows == NULL)
- X {
- X debug("We open one default window, as screenrc did not specify one.\n");
- X if (MakeWindow(&nwin) == -1)
- X {
- X AddStr("Sorry, could not find a PTY.");
- X sleep(2);
- X Finit(0);
- X /* NOTREACHED */
- X }
- X }
- X if (default_startup)
- X display_copyright();
- X signal(SIGCHLD, SigChld);
- X signal(SIGINT, SigInt);
- X tv.tv_usec = 0;
- X if (rflag == 2)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "I can't seem to find a... Hey, wait a minute! Here comes a screen now.");
- X else
- X#endif
- X Msg(0, "New screen...");
- X rflag = 0;
- X }
- X
- X Now = time((time_t *)0);
- X
- X for (;;)
- X {
- X tv.tv_sec = 0;
- X /*
- X * check for silence
- X */
- X for (p = windows; p; p = p->w_next)
- X {
- X int time_left;
- X
- X if (p->w_tstamp.seconds == 0)
- X continue;
- X debug1("checking silence win %d\n", p->w_number);
- X time_left = p->w_tstamp.lastio + p->w_tstamp.seconds - Now;
- X if (time_left > 0)
- X {
- X if (tv.tv_sec == 0 || time_left < tv.tv_sec)
- X tv.tv_sec = time_left;
- X }
- X else
- X {
- X for (display = displays; display; display = display->_d_next)
- X if (p != d_fore)
- X Msg(0, "Window %d: silence for %d seconds",
- X p->w_number, p->w_tstamp.seconds);
- X p->w_tstamp.lastio = Now;
- X }
- X }
- X
- X /*
- X * check to see if message line should be removed
- X */
- X for (display = displays; display; display = display->_d_next)
- X {
- X int time_left;
- X
- X if (d_status == 0)
- X continue;
- X debug("checking status...\n");
- X time_left = d_status_time + (d_status_bell?VBellWait:MsgWait) - Now;
- X if (time_left > 0)
- X {
- X if (tv.tv_sec == 0 || time_left < tv.tv_sec)
- X tv.tv_sec = time_left;
- X debug(" not yet.\n");
- X }
- X else
- X {
- X debug(" removing now.\n");
- X RemoveStatus();
- X }
- X }
- X /*
- X * check for I/O on all available I/O descriptors
- X */
- X#ifdef DEBUG
- X if (tv.tv_sec)
- X debug1("select timeout %d seconds\n", tv.tv_sec);
- X#endif
- X mkfdsets(&r, &w);
- X if (GotSigChld && !tv.tv_sec)
- X {
- X SigChldHandler();
- X continue;
- X }
- X if ((nsel = select(FD_SETSIZE, &r, &w, (fd_set *)0, tv.tv_sec ? &tv : (struct timeval *) 0)) < 0)
- X {
- X debug1("Bad select - errno %d\n", errno);
- X if (errno != EINTR)
- X Panic(errno, "select");
- X errno = 0;
- X nsel = 0;
- X }
- X#ifdef SELECT_BROKEN
- X /*
- X * Sequents select emulation counts an descriptor which is
- X * readable and writeable only as one. waaaaa.
- X */
- X if (nsel)
- X nsel = 2 * FD_SETSIZE;
- X#endif
- X if (GotSigChld && !tv.tv_sec)
- X {
- X SigChldHandler();
- X continue;
- X }
- X if (InterruptPlease)
- X {
- X debug("Backend received interrupt\n");
- X if (fore)
- X {
- X char ibuf;
- X ibuf = intrc;
- X#ifdef PSEUDOS
- X write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd,
- X &ibuf, 1);
- X debug1("Backend wrote interrupt to %d", fore->w_number);
- X debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : "");
- X#else
- X write(fore->w_ptyfd, &ibuf, 1);
- X debug1("Backend wrote interrupt to %d\n", fore->w_number);
- X#endif
- X }
- X InterruptPlease = 0;
- X }
- X
- X /*
- X * Process a client connect attempt and message
- X */
- X if (nsel && FD_ISSET(ServerSocket, &r))
- X {
- X nsel--;
- X debug("Knock - knock!\n");
- X ReceiveMsg();
- X continue;
- X }
- X
- X /*
- X * Write the (already processed) user input to the window
- X * descriptors first. We do not want to choke, if he types fast.
- X */
- X if (nsel)
- X {
- X for (p = windows; p; p = p->w_next)
- X {
- X int pastefd = -1;
- X#ifdef COPY_PASTE
- X if (p->w_pastelen)
- X {
- X /*
- X * Write the copybuffer contents first, if any.
- X */
- X#ifdef PSEUDOS
- X pastefd = W_UWP(p) ? p->w_pwin->p_ptyfd : p->w_ptyfd;
- X#else
- X pastefd = p->w_ptyfd;
- X#endif
- X if (FD_ISSET(pastefd, &w))
- X {
- X debug1("writing pastebuffer (%d)\n", p->w_pastelen);
- X len = write(pastefd, p->w_pastebuffer,
- X (slowpaste > 0) ? 1 :
- X (p->w_pastelen > IOSIZE ?
- X IOSIZE : p->w_pastelen));
- X if (len < 0) /* Problems... window is dead */
- X p->w_pastelen = 0;
- X if (len > 0)
- X {
- X p->w_pastebuffer += len;
- X p->w_pastelen -= len;
- X }
- X debug1("%d bytes pasted\n", len);
- X if (slowpaste > 0)
- X {
- X struct timeval t;
- X
- X debug1("slowpaste %d\n", slowpaste);
- X t.tv_sec = (long) (slowpaste / 1000);
- X t.tv_usec = (long) ((slowpaste % 1000) * 1000);
- X select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
- X }
- X if (--nsel == 0)
- X break;
- X if (p->w_pastelen == 0)
- X pastefd = -1;
- X }
- X }
- X#endif
- X
- X#ifdef PSEUDOS
- X if (p->w_pwin && p->w_pwin->p_inlen > 0)
- X {
- X /* stuff w_pwin->p_inbuf into pseudowin */
- X tmp = p->w_pwin->p_ptyfd;
- X if (tmp != pastefd && FD_ISSET(tmp, &w))
- X {
- X if ((len = write(tmp, p->w_pwin->p_inbuf,
- X p->w_pwin->p_inlen)) > 0)
- X {
- X if ((p->w_pwin->p_inlen -= len))
- X bcopy(p->w_pwin->p_inbuf + len, p->w_pwin->p_inbuf,
- X p->w_pwin->p_inlen);
- X }
- X if (--nsel == 0)
- X break;
- X }
- X }
- X#endif
- X if (p->w_inlen > 0)
- X {
- X /* stuff w_inbuf buffer into window */
- X tmp = p->w_ptyfd;
- X if (tmp != pastefd && FD_ISSET(tmp, &w))
- X {
- X if ((len = write(tmp, p->w_inbuf, p->w_inlen)) > 0)
- X {
- X if ((p->w_inlen -= len))
- X bcopy(p->w_inbuf + len, p->w_inbuf, p->w_inlen);
- X }
- X if (--nsel == 0)
- X break;
- X }
- X }
- X }
- X }
- X
- X Now = time((time_t *)0);
- X
- X if (nsel)
- X {
- X for (display = displays; display; display = ndisplay)
- X {
- X int maxlen;
- X
- X ndisplay = display->_d_next;
- X /*
- X * stuff d_obuf into user's tty
- X */
- X if (FD_ISSET(d_userfd, &w))
- X {
- X int size = OUTPUT_BLOCK_SIZE;
- X
- X len = d_obufp - d_obuf;
- X if (len < size)
- X size = len;
- X ASSERT(len >= 0);
- X size = write(d_userfd, d_obuf, size);
- X if (size >= 0)
- X {
- X len -= size;
- X if (len)
- X {
- X bcopy(d_obuf + size, d_obuf, len);
- X debug2("ASYNC: wrote %d - remaining %d\n", size, len);
- X }
- X d_obufp -= size;
- X d_obuffree += size;
- X }
- X else
- X {
- X if (errno != EINTR)
- X# ifdef EWOULDBLOCK
- X if (errno != EWOULDBLOCK)
- X# endif
- X Msg(errno, "Error writing output to display");
- X }
- X if (--nsel == 0)
- X break;
- X }
- X /*
- X * O.k. All streams are fed, now look what comes back
- X * to us. First of all: user input.
- X */
- X if (! FD_ISSET(d_userfd, &r))
- X continue;
- X if (d_status && !(use_hardstatus && HS))
- X RemoveStatus();
- X if (d_fore == 0)
- X maxlen = IOSIZE;
- X else
- X {
- X#ifdef PSEUDOS
- X if (W_UWP(d_fore))
- X maxlen = sizeof(d_fore->w_pwin->p_inbuf) - d_fore->w_pwin->p_inlen;
- X else
- X#endif
- X maxlen = sizeof(d_fore->w_inbuf) - d_fore->w_inlen;
- X }
- X if (maxlen > IOSIZE)
- X maxlen = IOSIZE;
- X if (maxlen <= 0)
- X maxlen = 1; /* Allow one char for command keys */
- X if (d_ESCseen)
- X {
- X if (maxlen == 1)
- X maxlen = 2; /* Allow one char for command keys */
- X buf[0] = Esc;
- X buflen = read(d_userfd, buf + 1, maxlen - 1) + 1;
- X d_ESCseen = 0;
- X }
- X else
- X buflen = read(d_userfd, buf, maxlen);
- X if (buflen < 0)
- X {
- X if (errno == EINTR)
- X continue;
- X debug1("Read error: %d - SigHup()ing!\n", errno);
- X SigHup(SIGARG);
- X sleep(1);
- X }
- X else if (buflen == 0)
- X {
- X debug("Found EOF - SigHup()ing!\n");
- X SigHup(SIGARG);
- X sleep(1);
- X }
- X else
- X {
- X /* This refills inbuf or p_inbuf */
- X ProcessInput(buf, buflen);
- X }
- X if (--nsel == 0)
- X break;
- X }
- X }
- X
- X /*
- X * Read and process the output from the window descriptors
- X */
- X for (p = windows; p; p = p->w_next)
- X {
- X if (p->w_lay->l_block)
- X continue;
- X display = p->w_display;
- X if (p->w_outlen)
- X WriteString(p, p->w_outbuf, p->w_outlen);
- X else
- X {
- X#ifdef PSEUDOS
- X /* gather pseudowin output */
- X if (W_RP(p) && nsel && FD_ISSET(p->w_pwin->p_ptyfd, &r))
- X {
- X nsel--;
- X n = 0;
- X if (W_PTOW(p))
- X {
- X /* Window wants a copy of the pseudowin output */
- X tmp = sizeof(p->w_inbuf) - p->w_inlen;
- X ASSERT(tmp > 0);
- X n++;
- X }
- X else
- X tmp = IOSIZE;
- X if ((len = read(p->w_pwin->p_ptyfd, buf, tmp)) <= 0)
- X {
- X if (errno != EINTR)
- X#ifdef EWOULDBLOCK
- X if (errno != EWOULDBLOCK)
- X#endif
- X {
- X debug2("Window %d: pseudowin read error (errno %d) -- removing pseudowin\n", p->w_number, len ? errno : 0);
- X FreePseudowin(p);
- X }
- X }
- X/* HERE WE ASSUME THAT THERE IS NO PACKET MODE ON PSEUDOWINS */
- X else
- X {
- X if (n)
- X {
- X bcopy(buf, p->w_inbuf + p->w_inlen, len);
- X p->w_inlen += len;
- X }
- X WriteString(p, buf, len);
- X }
- X }
- X#endif /* PSEUDOS */
- X /* gather window output */
- X if (nsel && FD_ISSET(p->w_ptyfd, &r))
- X {
- X nsel--;
- X#ifdef PSEUDOS
- X n = 0;
- X ASSERT(W_RW(p));
- X if (p->w_pwin && W_WTOP(p))
- X {
- X /* Pseudowin wants a copy of the window output */
- X tmp = sizeof(p->w_pwin->p_inbuf) - p->w_pwin->p_inlen;
- X ASSERT(tmp > 0);
- X n++;
- X }
- X else
- X#endif
- X tmp = IOSIZE;
- X if ((len = read(p->w_ptyfd, buf, tmp)) <= 0)
- X {
- X if (errno == EINTR)
- X continue;
- X#ifdef EWOULDBLOCK
- X if (errno == EWOULDBLOCK)
- X continue;
- X#endif
- X debug2("Window %d: read error (errno %d) - killing window\n", p->w_number, len ? errno : 0);
- X KillWindow(p);
- X nsel = 0; /* KillWindow may change window order */
- X break; /* so we just break */
- X }
- X#ifdef TIOCPKT
- X if ((p->w_t.flags & TTY_FLAG_PLAIN) == 0)
- X {
- X if (buf[0])
- X {
- X debug1("PAKET %x\n", buf[0]);
- X if (buf[0] & TIOCPKT_NOSTOP)
- X NewAutoFlow(p, 0);
- X if (buf[0] & TIOCPKT_DOSTOP)
- X NewAutoFlow(p, 1);
- X }
- X if (len > 1)
- X {
- X#ifdef PSEUDOS
- X if (n)
- X {
- X bcopy(buf + 1,
- X p->w_pwin->p_inbuf + p->w_pwin->p_inlen,
- X len - 1);
- X p->w_pwin->p_inlen += len - 1;
- X }
- X#endif
- X WriteString(p, buf + 1, len - 1);
- X }
- X }
- X else
- X#endif /* TIOCPKT */
- X {
- X if (len > 0)
- X {
- X#ifdef PSEUDOS
- X if (n)
- X {
- X bcopy(buf, p->w_pwin->p_inbuf + p->w_pwin->p_inlen,
- X len);
- X p->w_pwin->p_inlen += len;
- X }
- X#endif
- X WriteString(p, buf, len);
- X }
- X }
- X }
- X }
- X if (p->w_bell == BELL_ON)
- X {
- X p->w_bell = BELL_MSG;
- X for (display = displays; display; display = display->_d_next)
- X Msg(0, MakeWinMsg(BellString, p->w_number));
- X if (p->w_monitor == MON_FOUND)
- X p->w_monitor = MON_DONE;
- X }
- X else if (p->w_bell == BELL_VISUAL)
- X {
- X if (display && !d_status_bell)
- X {
- X /*
- X * Stop the '!' appearing in the ^A^W display if it is an
- X * active at the time of the bell. (Tim MacKenzie)
- X */
- X p->w_bell = BELL_OFF;
- X Msg(0, VisualBellString);
- X if (d_status)
- X d_status_bell = 1;
- X }
- X }
- X if (p->w_monitor == MON_FOUND)
- X {
- X p->w_monitor = MON_MSG;
- X for (display = displays; display; display = display->_d_next)
- X Msg(0, MakeWinMsg(ActivityString, p->w_number));
- X }
- X }
- X#if defined(DEBUG) && !defined(_SEQUENT_)
- X if (nsel)
- X debug1("*** Left over nsel: %d\n", nsel);
- X#endif
- X }
- X /* NOTREACHED */
- X}
- X
- Xstatic void
- XSigChldHandler()
- X{
- X struct stat st;
- X while (GotSigChld)
- X {
- X GotSigChld = 0;
- X DoWait();
- X#ifdef SYSVSIGS
- X signal(SIGCHLD, SigChld);
- X#endif
- X }
- X if (stat(SockPath, &st) == -1)
- X {
- X debug1("SigChldHandler: Yuck! cannot stat '%s'\n", SockPath);
- X if (!RecoverSocket())
- X {
- X debug("SCREEN cannot recover from corrupt Socket, bye\n");
- X Finit(1);
- X }
- X else
- X debug1("'%s' reconstructed\n", SockPath);
- X }
- X else
- X debug2("SigChldHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode);
- X}
- X
- Xstatic sig_t
- XSigChld(SIGDEFARG)
- X{
- X debug("SigChld()\n");
- X GotSigChld = 1;
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- Xsig_t
- XSigHup(SIGDEFARG)
- X{
- X if (display == 0)
- X return;
- X debug("SigHup()\n");
- X if (d_userfd >= 0)
- X {
- X close(d_userfd);
- X d_userfd = -1;
- X }
- X if (auto_detach || displays->_d_next)
- X Detach(D_DETACH);
- X else
- X Finit(0);
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- X/*
- X * the backend's Interrupt handler
- X * we cannot d_insert the intrc directly, as we never know
- X * if fore is valid.
- X */
- Xstatic sig_t
- XSigInt(SIGDEFARG)
- X{
- X#if HAZARDOUS
- X char buf[1];
- X
- X debug("SigInt()\n");
- X *buf = (char) intrc;
- X if (fore)
- X fore->w_inlen = 0;
- X if (fore)
- X write(fore->w_ptyfd, buf, 1);
- X#else
- X signal(SIGINT, SigInt);
- X debug("SigInt() careful\n");
- X InterruptPlease = 1;
- X#endif
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- Xstatic sig_t
- XCoreDump(sig)
- Xint sig;
- X{
- X struct display *disp;
- X char buf[80];
- X
- X#ifdef SYSVSIGS
- X signal(sig, SIG_IGN);
- X#endif /* SYSV */
- X setgid(getgid());
- X setuid(getuid());
- X unlink("core");
- X sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sig,
- X#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
- X ""
- X#else /* SHADOWPW && !DEBUG */
- X " (core dumped)"
- X#endif /* SHADOWPW && !DEBUG */
- X );
- X for (disp = displays; disp; disp = disp->_d_next)
- X {
- X fcntl(disp->_d_userfd, F_SETFL, 0);
- X write(disp->_d_userfd, buf, strlen(buf));
- X Kill(disp->_d_userpid, SIG_BYE);
- X }
- X#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
- X eexit(sig);
- X#else /* SHADOWPW && !DEBUG */
- X abort();
- X#endif /* SHADOWPW && !DEBUG */
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- Xstatic void
- XDoWait()
- X{
- X register int pid;
- X struct win *p, *next;
- X#ifdef BSDWAIT
- X union wait wstat;
- X#else
- X int wstat;
- X#endif
- X
- X#ifdef BSDJOBS
- X# ifndef BSDWAIT
- X while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0)
- X# else
- X# ifdef USE_WAIT2
- X /*
- X * From: rouilj@sni-usa.com (John Rouillard)
- X * note that WUNTRACED is not documented to work, but it is defined in
- X * /usr/include/sys/wait.h, so it may work
- X */
- X while ((pid = wait2(&wstat, WNOHANG | WUNTRACED )) > 0)
- X# else /* USE_WAIT2 */
- X while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0)
- X# endif /* USE_WAIT2 */
- X# endif
- X#else /* BSDJOBS */
- X while ((pid = wait(&wstat)) < 0)
- X if (errno != EINTR)
- X break;
- X if (pid > 0)
- X#endif /* BSDJOBS */
- X {
- X for (p = windows; p; p = next)
- X {
- X next = p->w_next;
- X if (pid == p->w_pid)
- X {
- X#ifdef BSDJOBS
- X if (WIFSTOPPED(wstat))
- X {
- X debug3("Window %d pid %d: WIFSTOPPED (sig %d)\n", p->w_number, p->w_pid, WSTOPSIG(wstat));
- X#ifdef SIGTTIN
- X if (WSTOPSIG(wstat) == SIGTTIN)
- X {
- X Msg(0, "Suspended (tty input)");
- X continue;
- X }
- X#endif
- X#ifdef SIGTTOU
- X if (WSTOPSIG(wstat) == SIGTTOU)
- X {
- X Msg(0, "Suspended (tty output)");
- X continue;
- X }
- X#endif
- X /* Try to restart process */
- X# ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "You regain consciousness.");
- X else
- X# endif /* NETHACK */
- X Msg(0, "Child has been stopped, restarting.");
- X if (killpg(p->w_pid, SIGCONT))
- X kill(p->w_pid, SIGCONT);
- X }
- X else
- X#endif
- X KillWindow(p);
- X break;
- X }
- X#ifdef PSEUDOS
- X if (p->w_pwin && pid == p->w_pwin->p_pid)
- X {
- X debug2("pseudo of win Nr %d died. pid == %d\n", p->w_number, p->w_pwin->p_pid);
- X FreePseudowin(p);
- X break;
- X }
- X#endif
- X }
- X if (p == 0)
- X {
- X debug1("pid %d not found - hope that's ok\n", pid);
- X }
- X }
- X}
- X
- X
- Xsig_t
- XFinit(i)
- Xint i;
- X{
- X struct win *p, *next;
- X
- X signal(SIGCHLD, SIG_IGN);
- X signal(SIGHUP, SIG_IGN);
- X debug1("Finit(%d);\n", i);
- X for (p = windows; p; p = next)
- X {
- X next = p->w_next;
- X FreeWindow(p);
- X }
- X if (ServerSocket != -1)
- X {
- X debug1("we unlink(%s)\n", SockPath);
- X#ifndef NOREUID
- X setreuid(eff_uid, real_uid);
- X setregid(eff_gid, real_gid);
- X#endif
- X (void) unlink(SockPath);
- X#ifndef NOREUID
- X setreuid(real_uid, eff_uid);
- X setregid(real_gid, eff_gid);
- X#endif
- X }
- X for (display = displays; display; display = display->_d_next)
- X {
- X if (d_status)
- X RemoveStatus();
- X FinitTerm();
- X#ifdef UTMPOK
- X RestoreLoginSlot();
- X#endif
- X AddStr("[screen is terminating]\r\n");
- X Flush();
- X SetTTY(d_userfd, &d_OldMode);
- X fcntl(d_userfd, F_SETFL, 0);
- X freetty();
- X Kill(d_userpid, SIG_BYE);
- X }
- X /*
- X * we _cannot_ call eexit(i) here,
- X * instead of playing with the Socket above. Sigh.
- X */
- X exit(i);
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- Xvoid
- Xeexit(e)
- Xint e;
- X{
- X if (ServerSocket != -1)
- X {
- X debug1("we unlink(%s)\n", SockPath);
- X setuid(real_uid);
- X setgid(real_gid);
- X (void) unlink(SockPath);
- X }
- X exit(e);
- X}
- X
- X
- X/*
- X * Detach now has the following modes:
- X * D_DETACH SIG_BYE detach backend and exit attacher
- X * D_STOP SIG_STOP stop attacher (and detach backend)
- X * D_REMOTE SIG_BYE remote detach -- reattach to new attacher
- X * D_POWER SIG_POWER_BYE power detach -- attacher kills his parent
- X * D_REMOTE_POWER SIG_POWER_BYE remote power detach -- both
- X * D_LOCK SIG_LOCK lock the attacher
- X * (jw)
- X * we always remove our utmp slots. (even when "lock" or "stop")
- X * Note: Take extra care here, we may be called by interrupt!
- X */
- Xvoid
- XDetach(mode)
- Xint mode;
- X{
- X int sign = 0, pid;
- X#ifdef UTMPOK
- X struct win *p;
- X#endif
- X
- X if (display == 0)
- X return;
- X signal(SIGHUP, SIG_IGN);
- X debug1("Detach(%d)\n", mode);
- X if (d_status)
- X RemoveStatus();
- X FinitTerm();
- X switch (mode)
- X {
- X case D_DETACH:
- X AddStr("[detached]\r\n");
- X sign = SIG_BYE;
- X break;
- X#ifdef BSDJOBS
- X case D_STOP:
- X sign = SIG_STOP;
- X break;
- X#endif
- X#ifdef REMOTE_DETACH
- X case D_REMOTE:
- X AddStr("[remote detached]\r\n");
- X sign = SIG_BYE;
- X break;
- X#endif
- X#ifdef POW_DETACH
- X case D_POWER:
- X AddStr("[power detached]\r\n");
- X if (PowDetachString)
- X {
- X AddStr(expand_vars(PowDetachString));
- X AddStr("\r\n");
- X }
- X sign = SIG_POWER_BYE;
- X break;
- X#ifdef REMOTE_DETACH
- X case D_REMOTE_POWER:
- X AddStr("[remote power detached]\r\n");
- X if (PowDetachString)
- X {
- X AddStr(expand_vars(PowDetachString));
- X AddStr("\r\n");
- X }
- X sign = SIG_POWER_BYE;
- X break;
- X#endif
- X#endif
- X case D_LOCK:
- X ClearDisplay();
- X sign = SIG_LOCK;
- X /* tell attacher to lock terminal with a lockprg. */
- X break;
- X }
- X#ifdef UTMPOK
- X if (displays->_d_next == 0)
- X {
- X for (p = windows; p; p = p->w_next)
- X if (p->w_slot != (slot_t) -1)
- X {
- X RemoveUtmp(p);
- X /*
- X * Set the slot to 0 to get the window
- X * logged in again.
- X */
- X p->w_slot = (slot_t) 0;
- X }
- X if (console_window)
- X {
- X if (TtyGrabConsole(console_window->w_ptyfd, 0, "detach"))
- X {
- X debug("could not release console - killing window\n");
- X KillWindow(console_window);
- X display = displays;
- X }
- X }
- X }
- X RestoreLoginSlot();
- X#endif
- X if (d_fore)
- X {
- X d_fore->w_active = 0;
- X d_fore->w_display = 0;
- X d_lay = &BlankLayer;
- X d_layfn = d_lay->l_layfn;
- X }
- X while (d_lay != &BlankLayer)
- X ExitOverlayPage();
- X if (d_userfd >= 0)
- X {
- X Flush();
- X SetTTY(d_userfd, &d_OldMode);
- X fcntl(d_userfd, F_SETFL, 0);
- X }
- X freetty();
- X pid = d_userpid;
- X debug2("display: %#x displays: %#x\n", (unsigned int)display, (unsigned int)displays);
- X FreeDisplay();
- X if (displays == 0)
- X /* Flag detached-ness */
- X (void) chsock();
- X /*
- X * tell father to father what to do. We do that after we
- X * freed the tty, thus getty feels more comfortable on hpux
- X * if it was a power detach.
- X */
- X Kill(pid, sign);
- X debug2("Detach: Signal %d to Attacher(%d)!\n", sign, pid);
- X debug("Detach returns, we are successfully detached.\n");
- X signal(SIGHUP, SigHup);
- X}
- X
- Xstatic int
- XIsSymbol(e, s)
- Xregister char *e, *s;
- X{
- X register int l;
- X
- X l = strlen(s);
- X return strncmp(e, s, l) == 0 && e[l] == '=';
- X}
- X
- Xvoid
- XMakeNewEnv()
- X{
- X register char **op, **np;
- X static char stybuf[MAXSTR];
- X
- X for (op = environ; *op; ++op)
- X ;
- X if (NewEnv)
- X free(NewEnv);
- X NewEnv = np = (char **) malloc((unsigned) (op - environ + 7 + 1) * sizeof(char **));
- X if (!NewEnv)
- X Panic(0, strnomem);
- X SockName = SockNamePtr;
- X if (strlen(SockNamePtr) > MAXSTR - 5)
- X SockName = "?";
- X sprintf(stybuf, "STY=%s", SockNamePtr);
- X *np++ = stybuf; /* NewEnv[0] */
- X *np++ = Term; /* NewEnv[1] */
- X np++; /* room for SHELL */
- X#ifdef TIOCSWINSZ
- X np += 2; /* room for TERMCAP and WINDOW */
- X#else
- X np += 4; /* room for TERMCAP WINDOW LINES COLUMNS */
- X#endif
- X
- X for (op = environ; *op; ++op)
- X {
- X if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP")
- X && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW")
- X && !IsSymbol(*op, "SCREENCAP") && !IsSymbol(*op, "SHELL")
- X && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS")
- X )
- X *np++ = *op;
- X }
- X *np = 0;
- X}
- X
- Xvoid
- X#ifdef USEVARARGS
- X/*VARARGS2*/
- X# if defined(__STDC__)
- XMsg(int err, char *fmt, ...)
- X# else /* __STDC__ */
- XMsg(err, fmt, va_alist)
- Xint err;
- Xchar *fmt;
- Xva_dcl
- X# endif /* __STDC__ */
- X{
- X static va_list ap;
- X#else /* USEVARARRGS */
- X/*VARARGS2*/
- XMsg(err, fmt, p1, p2, p3, p4, p5, p6)
- Xint err;
- Xchar *fmt;
- Xunsigned long p1, p2, p3, p4, p5, p6;
- X{
- X#endif /* USEVARARRGS */
- X char buf[MAXPATHLEN*2];
- X char *p = buf;
- X
- X#ifdef USEVARARGS
- X# if defined(__STDC__)
- X va_start(ap, fmt);
- X# else /* __STDC__ */
- X va_start(ap);
- X# endif /* __STDC__ */
- X (void) vsprintf(p, fmt, ap);
- X va_end(ap);
- X#else /* USEVARARRGS */
- X sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
- X#endif /* USEVARARRGS */
- X if (err)
- X {
- 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 debug2("Msg('%s') (%#x);\n", buf, (unsigned int)display);
- X if (display)
- X MakeStatus(buf);
- X else if (displays)
- X {
- X for (display = displays; display; display = display->_d_next)
- X MakeStatus(buf);
- X }
- X else
- X printf("%s\r\n", buf);
- X}
- X
- Xvoid
- X#ifdef USEVARARGS
- X/*VARARGS2*/
- X# if defined(__STDC__)
- XPanic(int err, char *fmt, ...)
- X# else /* __STDC__ */
- XPanic(err, fmt, va_alist)
- Xint err;
- Xchar *fmt;
- Xva_dcl
- X# endif /* __STDC__ */
- X{
- X static va_list ap;
- X#else /* USEVARARRGS */
- X/*VARARGS2*/
- XPanic(err, fmt, p1, p2, p3, p4, p5, p6)
- Xint err;
- Xchar *fmt;
- Xunsigned long p1, p2, p3, p4, p5, p6;
- X{
- X#endif /* USEVARARRGS */
- X char buf[MAXPATHLEN*2];
- X char *p = buf;
- X
- X#ifdef USEVARARGS
- X# if defined(__STDC__)
- X va_start(ap, fmt);
- X# else /* __STDC__ */
- X va_start(ap);
- X# endif /* __STDC__ */
- X (void) vsprintf(p, fmt, ap);
- X va_end(ap);
- X#else /* USEVARARRGS */
- X sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
- X#endif /* USEVARARRGS */
- X if (err)
- X {
- 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 debug1("Panic('%s');\n", buf);
- X if (displays == 0)
- X printf("%s\r\n", buf);
- X else
- X for (display = displays; display; display = display->_d_next)
- X {
- X if (d_status)
- X RemoveStatus();
- X FinitTerm();
- X Flush();
- X#ifdef UTMPOK
- X RestoreLoginSlot();
- X#endif
- X SetTTY(d_userfd, &d_OldMode);
- X fcntl(d_userfd, F_SETFL, 0);
- X write(d_userfd, buf, strlen(buf));
- X write(d_userfd, "\n", 1);
- X freetty();
- X if (d_userpid)
- X Kill(d_userpid, SIG_BYE);
- X }
- X#ifdef MULTIUSER
- X if (tty_oldmode >= 0)
- X {
- X# ifdef NOREUID
- X setuid(eff_uid);
- X# else
- X setreuid(real_uid, eff_uid);
- X# endif
- X debug1("Panic: changing back modes from %s\n", attach_tty);
- X chmod(attach_tty, tty_oldmode);
- X }
- X#endif
- X eexit(1);
- X}
- X
- X
- X/*
- X * '^' is allowed as an escape mechanism for control characters. jw.
- X */
- Xstatic char *
- XMakeWinMsg(s, n)
- Xregister char *s;
- Xint n;
- X{
- X static char buf[MAXSTR];
- X register char *p = buf;
- X register int ctrl;
- X
- X ctrl = 0;
- X for (; *s && p < buf + MAXSTR - 1; s++, p++)
- X if (ctrl)
- X {
- X ctrl = 0;
- X if (*s == '^' || *s < 64)
- X *p = *s;
- X else
- X *p = *s - 64;
- X }
- X else
- X {
- X switch (*s)
- X {
- X case '%':
- X sprintf(p, "%d", n);
- X p += strlen(p) - 1;
- X break;
- X case '~':
- X *p = BELL;
- X break;
- X case '^':
- X ctrl = 1;
- X *p-- = '^';
- X break;
- X default:
- X *p = *s;
- X break;
- X }
- X }
- X *p = '\0';
- X return buf;
- X}
- X
- Xvoid
- XDisplaySleep(n)
- Xint n;
- X{
- X char buf;
- X fd_set r;
- X struct timeval t;
- X
- X if (!display)
- X {
- X debug("DisplaySleep has no display sigh\n");
- X sleep(n);
- X return;
- X }
- X t.tv_usec = 0;
- X t.tv_sec = n;
- X FD_ZERO(&r);
- X FD_SET(d_userfd, &r);
- X if (select(FD_SETSIZE, &r, (fd_set *)0, (fd_set *)0, &t) > 0)
- X {
- X debug("display activity stopped sleep\n");
- X read(d_userfd, &buf, 1);
- X }
- X debug1("DisplaySleep(%d) ending\n", n);
- X}
- END_OF_FILE
- if test 50777 -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 6 \(of 10\).
- cp /dev/null ark6isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 10 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-