summaryrefslogtreecommitdiff
path: root/window.c
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2011-10-04 22:01:30 +0200
committerAxel Beckert <abe@deuxchevaux.org>2011-10-04 22:01:30 +0200
commited169177fbfd1fedb0750f3ba18737aba5596451 (patch)
tree4410859c72a75d3ca453521b881d0d40456e2749 /window.c
parent168c94858d20f79247aad40daf2c54cd54182565 (diff)
downloadscreen-ed169177fbfd1fedb0750f3ba18737aba5596451.tar.gz
Imported Upstream version 4.0.3+git201108019upstream/4.0.3+git201108019
Diffstat (limited to 'window.c')
-rw-r--r--window.c2179
1 files changed, 0 insertions, 2179 deletions
diff --git a/window.c b/window.c
deleted file mode 100644
index 3b60ae0..0000000
--- a/window.c
+++ /dev/null
@@ -1,2179 +0,0 @@
-/* Copyright (c) 1993-2002
- * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
- * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
- * Copyright (c) 1987 Oliver Laumann
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program (see the file COPYING); if not, write to the
- * Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- ****************************************************************
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <fcntl.h>
-#ifndef sun
-# include <sys/ioctl.h>
-#endif
-
-#include "config.h"
-
-#include "screen.h"
-#include "extern.h"
-#include "logfile.h" /* logfopen() */
-
-extern struct display *displays, *display;
-extern struct win *windows, *fore, *wtab[], *console_window;
-extern char *ShellArgs[];
-extern char *ShellProg;
-extern char screenterm[];
-extern char *screenlogfile;
-extern char HostName[];
-extern int TtyMode;
-extern int SilenceWait;
-extern int real_uid, real_gid, eff_uid, eff_gid;
-extern char Termcap[];
-extern char **NewEnv;
-extern int visual_bell, maxwin;
-extern struct event logflushev;
-extern int log_flush, logtstamp_after;
-extern int ZombieKey_destroy, ZombieKey_resurrect;
-extern struct layer *flayer;
-extern int maxusercount;
-extern int pty_preopen;
-#ifdef ZMODEM
-extern int zmodem_mode;
-extern struct mchar mchar_blank;
-extern char *zmodem_sendcmd;
-extern char *zmodem_recvcmd;
-#endif
-
-#if defined(TIOCSWINSZ) || defined(TIOCGWINSZ)
-extern struct winsize glwz;
-#endif
-
-#ifdef O_NOCTTY
-extern int separate_sids;
-#endif
-
-static void WinProcess __P((char **, int *));
-static void WinRedisplayLine __P((int, int, int, int));
-static void WinClearLine __P((int, int, int, int));
-static int WinRewrite __P((int, int, int, struct mchar *, int));
-static int WinResize __P((int, int));
-static void WinRestore __P((void));
-static int DoAutolf __P((char *, int *, int));
-static void ZombieProcess __P((char **, int *));
-static void win_readev_fn __P((struct event *, char *));
-static void win_writeev_fn __P((struct event *, char *));
-static int muchpending __P((struct win *, struct event *));
-#ifdef COPY_PASTE
-static void paste_slowev_fn __P((struct event *, char *));
-#endif
-#ifdef PSEUDOS
-static void pseu_readev_fn __P((struct event *, char *));
-static void pseu_writeev_fn __P((struct event *, char *));
-#endif
-static void win_silenceev_fn __P((struct event *, char *));
-
-static int OpenDevice __P((char **, int, int *, char **));
-static int ForkWindow __P((struct win *, char **, char *));
-#ifdef ZMODEM
-static void zmodem_found __P((struct win *, int, char *, int));
-static void zmodem_fin __P((char *, int, char *));
-static int zmodem_parse __P((struct win *, char *, int));
-#endif
-
-
-
-int VerboseCreate = 0; /* XXX move this to user.h */
-
-char DefaultShell[] = "/bin/sh";
-static char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin";
-
-/* keep this in sync with the structure definition in window.h */
-struct NewWindow nwin_undef =
-{
- -1, /* StartAt */
- (char *)0, /* aka */
- (char **)0, /* args */
- (char *)0, /* dir */
- (char *)0, /* term */
- -1, /* aflag */
- -1, /* flowflag */
- -1, /* lflag */
- -1, /* histheight */
- -1, /* monitor */
- -1, /* wlock */
- -1, /* silence */
- -1, /* wrap */
- -1, /* logging */
- -1, /* slowpaste */
- -1, /* gr */
- -1, /* c1 */
- -1, /* bce */
- -1, /* encoding */
- (char *)0, /* hstatus */
- (char *)0 /* charset */
-};
-
-struct NewWindow nwin_default =
-{
- 0, /* StartAt */
- 0, /* aka */
- ShellArgs, /* args */
- 0, /* dir */
- screenterm, /* term */
- 0, /* aflag */
- 1*FLOW_NOW, /* flowflag */
- LOGINDEFAULT, /* lflag */
- DEFAULTHISTHEIGHT, /* histheight */
- MON_OFF, /* monitor */
- WLOCK_OFF, /* wlock */
- 0, /* silence */
- 1, /* wrap */
- 0, /* logging */
- 0, /* slowpaste */
- 0, /* gr */
- 1, /* c1 */
- 0, /* bce */
- 0, /* encoding */
- (char *)0, /* hstatus */
- (char *)0 /* charset */
-};
-
-struct NewWindow nwin_options;
-
-static int const_IOSIZE = IOSIZE;
-static int const_one = 1;
-
-void
-nwin_compose(def, new, res)
-struct NewWindow *def, *new, *res;
-{
-#define COMPOSE(x) res->x = new->x != nwin_undef.x ? new->x : def->x
- COMPOSE(StartAt);
- COMPOSE(aka);
- COMPOSE(args);
- COMPOSE(dir);
- COMPOSE(term);
- COMPOSE(aflag);
- COMPOSE(flowflag);
- COMPOSE(lflag);
- COMPOSE(histheight);
- COMPOSE(monitor);
- COMPOSE(wlock);
- COMPOSE(silence);
- COMPOSE(wrap);
- COMPOSE(Lflag);
- COMPOSE(slow);
- COMPOSE(gr);
- COMPOSE(c1);
- COMPOSE(bce);
- COMPOSE(encoding);
- COMPOSE(hstatus);
- COMPOSE(charset);
-#undef COMPOSE
-}
-
-/*****************************************************************
- *
- * The window layer functions
- */
-
-struct LayFuncs WinLf =
-{
- WinProcess,
- 0,
- WinRedisplayLine,
- WinClearLine,
- WinRewrite,
- WinResize,
- WinRestore
-};
-
-static int
-DoAutolf(buf, lenp, fr)
-char *buf;
-int *lenp;
-int fr;
-{
- char *p;
- int len = *lenp;
- int trunc = 0;
-
- for (p = buf; len > 0; p++, len--)
- {
- if (*p != '\r')
- continue;
- if (fr-- <= 0)
- {
- trunc++;
- len--;
- }
- if (len == 0)
- break;
- bcopy(p, p + 1, len++);
- p[1] = '\n';
- }
- *lenp = p - buf;
- return trunc;
-}
-
-static void
-WinProcess(bufpp, lenp)
-char **bufpp;
-int *lenp;
-{
- int l2 = 0, f, *ilen, l = *lenp, trunc;
- char *ibuf;
-
- debug1("WinProcess: %d bytes\n", *lenp);
- fore = (struct win *)flayer->l_data;
-
- if (fore->w_ptyfd < 0) /* zombie? */
- {
- ZombieProcess(bufpp, lenp);
- return;
- }
-#ifdef MULTIUSER
- /* a pending writelock is this:
- * fore->w_wlock == WLOCK_AUTO, fore->w_wlockuse = NULL
- * The user who wants to use this window next, will get the lock, if he can.
- */
- if (display && fore->w_wlock == WLOCK_AUTO &&
- !fore->w_wlockuser && !AclCheckPermWin(D_user, ACL_WRITE, fore))
- {
- fore->w_wlockuser = D_user;
- debug2("window %d: pending writelock grabbed by user %s\n",
- fore->w_number, fore->w_wlockuser->u_name);
- }
- /* if w_wlock is set, only one user may write, else we check acls */
- if (display && ((fore->w_wlock == WLOCK_OFF) ?
- AclCheckPermWin(D_user, ACL_WRITE, fore) :
- (D_user != fore->w_wlockuser)))
- {
- debug2("window %d, user %s: ", fore->w_number, D_user->u_name);
- debug2("writelock %d (wlockuser %s)\n", fore->w_wlock,
- fore->w_wlockuser ? fore->w_wlockuser->u_name : "NULL");
- /* XXX FIXME only display !*/
- WBell(fore, visual_bell);
- *bufpp += *lenp;
- *lenp = 0;
- return;
- }
-#endif /* MULTIUSER */
-
-#ifdef BUILTIN_TELNET
- if (fore->w_type == W_TYPE_TELNET && TelIsline(fore) && *bufpp != fore->w_telbuf)
- {
- TelProcessLine(bufpp, lenp);
- return;
- }
-#endif
-
-#ifdef PSEUDOS
- if (W_UWP(fore))
- {
- /* we send the user input to our pseudowin */
- ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen;
- f = sizeof(fore->w_pwin->p_inbuf) - *ilen;
- }
- else
-#endif /* PSEUDOS */
- {
- /* we send the user input to the window */
- ibuf = fore->w_inbuf; ilen = &fore->w_inlen;
- f = sizeof(fore->w_inbuf) - *ilen;
- }
-
- if (l > f)
- l = f;
-#ifdef BUILTIN_TELNET
- while (l > 0)
-#else
- if (l > 0)
-#endif
- {
- l2 = l;
- bcopy(*bufpp, ibuf + *ilen, l2);
- if (fore->w_autolf && (trunc = DoAutolf(ibuf + *ilen, &l2, f - l2)))
- l -= trunc;
-#ifdef BUILTIN_TELNET
- if (fore->w_type == W_TYPE_TELNET && (trunc = DoTelnet(ibuf + *ilen, &l2, f - l2)))
- {
- l -= trunc;
- if (fore->w_autolf)
- continue; /* need exact value */
- }
-#endif
- *ilen += l2;
- *bufpp += l;
- *lenp -= l;
- return;
- }
-}
-
-static void
-ZombieProcess(bufpp, lenp)
-char **bufpp;
-int *lenp;
-{
- int l = *lenp;
- char *buf = *bufpp, b1[10], b2[10];
-
- debug1("ZombieProcess: %d bytes\n", *lenp);
- fore = (struct win *)flayer->l_data;
-
- ASSERT(fore->w_ptyfd < 0);
- *bufpp += *lenp;
- *lenp = 0;
- for (; l-- > 0; buf++)
- {
- if (*(unsigned char *)buf == ZombieKey_destroy)
- {
- debug1("Turning undead: %d\n", fore->w_number);
- KillWindow(fore);
- return;
- }
- if (*(unsigned char *)buf == ZombieKey_resurrect)
- {
- debug1("Resurrecting Zombie: %d\n", fore->w_number);
- WriteString(fore, "\r\n", 2);
- RemakeWindow(fore);
- return;
- }
- }
- b1[AddXChar(b1, ZombieKey_destroy)] = '\0';
- b2[AddXChar(b2, ZombieKey_resurrect)] = '\0';
- Msg(0, "Press %s to destroy or %s to resurrect window", b1, b2);
-}
-
-static void
-WinRedisplayLine(y, from, to, isblank)
-int y, from, to, isblank;
-{
- debug3("WinRedisplayLine %d %d %d\n", y, from, to);
- if (y < 0)
- return;
- fore = (struct win *)flayer->l_data;
- if (from == 0 && y > 0 && fore->w_mlines[y - 1].image[fore->w_width] == 0)
- LCDisplayLineWrap(&fore->w_layer, &fore->w_mlines[y], y, from, to, isblank);
- else
- LCDisplayLine(&fore->w_layer, &fore->w_mlines[y], y, from, to, isblank);
-}
-
-static int
-WinRewrite(y, x1, x2, rend, doit)
-int y, x1, x2, doit;
-struct mchar *rend;
-{
- register int cost, dx;
- register unsigned char *p, *i;
-#ifdef FONT
- register unsigned char *f;
-#endif
-#ifdef COLOR
- register unsigned char *c;
-# ifdef COLORS256
- register unsigned char *cx;
-# endif
-#endif
-
- debug3("WinRewrite %d, %d-%d\n", y, x1, x2);
- fore = (struct win *)flayer->l_data;
- dx = x2 - x1 + 1;
- if (doit)
- {
- i = fore->w_mlines[y].image + x1;
- while (dx-- > 0)
- PUTCHAR(*i++);
- return 0;
- }
- p = fore->w_mlines[y].attr + x1;
-#ifdef FONT
- f = fore->w_mlines[y].font + x1;
-# ifdef DW_CHARS
- if (is_dw_font(rend->font))
- return EXPENSIVE;
-# endif
-# ifdef UTF8
- if (fore->w_encoding && fore->w_encoding != UTF8 && D_encoding == UTF8 && ContainsSpecialDeffont(fore->w_mlines + y, x1, x2, fore->w_encoding))
- return EXPENSIVE;
-# endif
-#endif
-#ifdef COLOR
- c = fore->w_mlines[y].color + x1;
-# ifdef COLORS256
- cx = fore->w_mlines[y].colorx + x1;
-# endif
-#endif
-
- cost = dx = x2 - x1 + 1;
- while(dx-- > 0)
- {
- if (*p++ != rend->attr)
- return EXPENSIVE;
-#ifdef FONT
- if (*f++ != rend->font)
- return EXPENSIVE;
-#endif
-#ifdef COLOR
- if (*c++ != rend->color)
- return EXPENSIVE;
-# ifdef COLORS256
- if (*cx++ != rend->colorx)
- return EXPENSIVE;
-# endif
-#endif
- }
- return cost;
-}
-
-static void
-WinClearLine(y, xs, xe, bce)
-int y, xs, xe, bce;
-{
- fore = (struct win *)flayer->l_data;
- debug3("WinClearLine %d %d-%d\n", y, xs, xe);
- LClearLine(flayer, y, xs, xe, bce, &fore->w_mlines[y]);
-}
-
-static int
-WinResize(wi, he)
-int wi, he;
-{
- fore = (struct win *)flayer->l_data;
- ChangeWindowSize(fore, wi, he, fore->w_histheight);
- return 0;
-}
-
-static void
-WinRestore()
-{
- struct canvas *cv;
- fore = (struct win *)flayer->l_data;
- debug1("WinRestore: win %x\n", fore);
- for (cv = flayer->l_cvlist; cv; cv = cv->c_next)
- {
- display = cv->c_display;
- if (cv != D_forecv)
- continue;
- /* ChangeScrollRegion(fore->w_top, fore->w_bot); */
- KeypadMode(fore->w_keypad);
- CursorkeysMode(fore->w_cursorkeys);
- SetFlow(fore->w_flow & FLOW_NOW);
- InsertMode(fore->w_insert);
- ReverseVideo(fore->w_revvid);
- CursorVisibility(fore->w_curinv ? -1 : fore->w_curvvis);
- MouseMode(fore->w_mouse);
- }
-}
-
-/*****************************************************************/
-
-
-/*
- * DoStartLog constructs a path for the "want to be logfile" in buf and
- * attempts logfopen.
- *
- * returns 0 on success.
- */
-int
-DoStartLog(w, buf, bufsize)
-struct win *w;
-char *buf;
-int bufsize;
-{
- int n;
- if (!w || !buf)
- return -1;
-
- strncpy(buf, MakeWinMsg(screenlogfile, w, '%'), bufsize - 1);
- buf[bufsize - 1] = 0;
-
- debug2("DoStartLog: win %d, file %s\n", w->w_number, buf);
-
- if (w->w_log != NULL)
- logfclose(w->w_log);
-
- if ((w->w_log = logfopen(buf, islogfile(buf) ? NULL : secfopen(buf, "a"))) == NULL)
- return -2;
- if (!logflushev.queued)
- {
- n = log_flush ? log_flush : (logtstamp_after + 4) / 5;
- if (n)
- {
- SetTimeout(&logflushev, n * 1000);
- evenq(&logflushev);
- }
- }
- return 0;
-}
-
-/*
- * Umask & wlock are set for the user of the display,
- * The display d (if specified) switches to that window.
- */
-int
-MakeWindow(newwin)
-struct NewWindow *newwin;
-{
- register struct win **pp, *p;
- register int n, i;
- int f = -1;
- struct NewWindow nwin;
- int type, startat;
- char *TtyName;
-#ifdef MULTIUSER
- extern struct acluser *users;
-#endif
-
- debug1("NewWindow: StartAt %d\n", newwin->StartAt);
- debug1("NewWindow: aka %s\n", newwin->aka?newwin->aka:"NULL");
- debug1("NewWindow: dir %s\n", newwin->dir?newwin->dir:"NULL");
- debug1("NewWindow: term %s\n", newwin->term?newwin->term:"NULL");
-
- nwin_compose(&nwin_default, newwin, &nwin);
- debug1("NWin: aka %s\n", nwin.aka ? nwin.aka : "NULL");
- debug1("NWin: wlock %d\n", nwin.wlock);
- debug1("NWin: Lflag %d\n", nwin.Lflag);
-
- startat = nwin.StartAt < maxwin ? nwin.StartAt : 0;
- pp = wtab + startat;
-
- do
- {
- if (*pp == 0)
- break;
- if (++pp == wtab + maxwin)
- pp = wtab;
- }
- while (pp != wtab + startat);
- if (*pp)
- {
- Msg(0, "No more windows.");
- return -1;
- }
-
-#if defined(USRLIMIT) && defined(UTMPOK)
- /*
- * Count current number of users, if logging windows in.
- */
- if (nwin.lflag && CountUsers() >= USRLIMIT)
- {
- Msg(0, "User limit reached. Window will not be logged in.");
- nwin.lflag = 0;
- }
-#endif
- n = pp - wtab;
- debug1("Makewin creating %d\n", n);
-
- if ((f = OpenDevice(nwin.args, nwin.lflag, &type, &TtyName)) < 0)
- return -1;
-
- if ((p = (struct win *)malloc(sizeof(struct win))) == 0)
- {
- close(f);
- Msg(0, strnomem);
- return -1;
- }
- bzero((char *)p, (int)sizeof(struct win));
-
-#ifdef UTMPOK
- if (type != W_TYPE_PTY)
- nwin.lflag = 0;
-#endif
-
- p->w_type = type;
-
- /* save the command line so that zombies can be resurrected */
- for (i = 0; nwin.args[i] && i < MAXARGS - 1; i++)
- p->w_cmdargs[i] = SaveStr(nwin.args[i]);
- p->w_cmdargs[i] = 0;
- if (nwin.dir)
- p->w_dir = SaveStr(nwin.dir);
- if (nwin.term)
- p->w_term = SaveStr(nwin.term);
-
- p->w_number = n;
-#ifdef MULTIUSER
- /*
- * This is dangerous: without a display we use creators umask
- * This is intended to be usefull for detached startup.
- * But is still better than default bits with a NULL user.
- */
- if (NewWindowAcl(p, display ? D_user : users))
- {
- free((char *)p);
- close(f);
- Msg(0, strnomem);
- return -1;
- }
-#endif
- p->w_layer.l_next = 0;
- p->w_layer.l_bottom = &p->w_layer;
- p->w_layer.l_layfn = &WinLf;
- p->w_layer.l_data = (char *)p;
- p->w_savelayer = &p->w_layer;
- p->w_pdisplay = 0;
- p->w_lastdisp = 0;
-
-#ifdef MULTIUSER
- if (display && !AclCheckPermWin(D_user, ACL_WRITE, p))
- p->w_wlockuser = D_user;
- p->w_wlock = nwin.wlock;
-#endif
- p->w_ptyfd = f;
- p->w_aflag = nwin.aflag;
- p->w_flow = nwin.flowflag | ((nwin.flowflag & FLOW_AUTOFLAG) ? (FLOW_AUTO|FLOW_NOW) : FLOW_AUTO);
- if (!nwin.aka)
- nwin.aka = Filename(nwin.args[0]);
- strncpy(p->w_akabuf, nwin.aka, sizeof(p->w_akabuf) - 1);
- if ((nwin.aka = rindex(p->w_akabuf, '|')) != NULL)
- {
- p->w_autoaka = 0;
- *nwin.aka++ = 0;
- p->w_title = nwin.aka;
- p->w_akachange = nwin.aka + strlen(nwin.aka);
- }
- else
- p->w_title = p->w_akachange = p->w_akabuf;
- if (nwin.hstatus)
- p->w_hstatus = SaveStr(nwin.hstatus);
- p->w_monitor = nwin.monitor;
-#ifdef MULTIUSER
- if (p->w_monitor == MON_ON)
- {
- /* always tell all users */
- for (i = 0; i < maxusercount; i++)
- ACLBYTE(p->w_mon_notify, i) |= ACLBIT(i);
- }
-#endif
- /*
- * defsilence by Lloyd Zusman (zusman_lloyd@jpmorgan.com)
- */
- p->w_silence = nwin.silence;
- p->w_silencewait = SilenceWait;
-#ifdef MULTIUSER
- if (p->w_silence == SILENCE_ON)
- {
- /* always tell all users */
- for (i = 0; i < maxusercount; i++)
- ACLBYTE(p->w_lio_notify, i) |= ACLBIT(i);
- }
-#endif
-#ifdef COPY_PASTE
- p->w_slowpaste = nwin.slow;
-#else
- nwin.histheight = 0;
-#endif
-
- p->w_norefresh = 0;
- strncpy(p->w_tty, TtyName, MAXSTR - 1);
-
-#if 0
- /* XXX Fixme display resize */
- if (ChangeWindowSize(p, display ? D_defwidth : 80,
- display ? D_defheight : 24,
- nwin.histheight))
- {
- FreeWindow(p);
- return -1;
- }
-#else
- if (ChangeWindowSize(p, display ? D_forecv->c_xe - D_forecv->c_xs + 1: 80,
- display ? D_forecv->c_ye - D_forecv->c_ys + 1 : 24,
- nwin.histheight))
- {
- FreeWindow(p);
- return -1;
- }
-#endif
-
- p->w_encoding = nwin.encoding;
- ResetWindow(p); /* sets w_wrap, w_c1, w_gr, w_bce */
-
-#ifdef FONT
- if (nwin.charset)
- SetCharsets(p, nwin.charset);
-#endif
-
- if (VerboseCreate)
- {
- struct display *d = display; /* WriteString zaps display */
-
- WriteString(p, ":screen (", 9);
- WriteString(p, p->w_title, strlen(p->w_title));
- WriteString(p, "):", 2);
- for (f = 0; p->w_cmdargs[f]; f++)
- {
- WriteString(p, " ", 1);
- WriteString(p, p->w_cmdargs[f], strlen(p->w_cmdargs[f]));
- }
- WriteString(p, "\r\n", 2);
- display = d;
- }
-
- p->w_pid = 0;
-#ifdef PSEUDOS
- p->w_pwin = 0;
-#endif
-
-#ifdef BUILTIN_TELNET
- if (type == W_TYPE_TELNET)
- {
- if (TelConnect(p))
- {
- FreeWindow(p);
- return -1;
- }
- }
- else
-#endif
- if (type == W_TYPE_PTY)
- {
- p->w_pid = ForkWindow(p, nwin.args, TtyName);
- if (p->w_pid < 0)
- {
- FreeWindow(p);
- return -1;
- }
- }
-
- /*
- * Place the new window at the head of the most-recently-used list.
- */
- if (display && D_fore)
- D_other = D_fore;
- *pp = p;
- p->w_next = windows;
- windows = p;
- p->w_lflag = nwin.lflag;
-#ifdef UTMPOK
- p->w_slot = (slot_t)-1;
-# ifdef LOGOUTOK
- debug1("MakeWindow will %slog in.\n", nwin.lflag?"":"not ");
- if (nwin.lflag & 1)
-# else /* LOGOUTOK */
- debug1("MakeWindow will log in, LOGOUTOK undefined in config.h%s.\n",
- nwin.lflag?"":" (although lflag=0)");
-# endif /* LOGOUTOK */
- {
- p->w_slot = (slot_t)0;
- if (display || (p->w_lflag & 2))
- SetUtmp(p);
- }
-# ifdef CAREFULUTMP
- CarefulUtmp(); /* If all 've been zombies, we've had no slot */
-# endif
-#endif /* UTMPOK */
-
- if (nwin.Lflag)
- {
- char buf[1024];
- DoStartLog(p, buf, sizeof(buf));
- }
-
- p->w_readev.fd = p->w_writeev.fd = p->w_ptyfd;
- p->w_readev.type = EV_READ;
- p->w_writeev.type = EV_WRITE;
- p->w_readev.data = p->w_writeev.data = (char *)p;
- p->w_readev.handler = win_readev_fn;
- p->w_writeev.handler = win_writeev_fn;
- p->w_writeev.condpos = &p->w_inlen;
- evenq(&p->w_readev);
- evenq(&p->w_writeev);
-#ifdef COPY_PASTE
- p->w_paster.pa_slowev.type = EV_TIMEOUT;
- p->w_paster.pa_slowev.data = (char *)&p->w_paster;
- p->w_paster.pa_slowev.handler = paste_slowev_fn;
-#endif
- p->w_silenceev.type = EV_TIMEOUT;
- p->w_silenceev.data = (char *)p;
- p->w_silenceev.handler = win_silenceev_fn;
- if (p->w_silence > 0)
- {
- debug("New window has silence enabled.\n");
- SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
- evenq(&p->w_silenceev);
- }
-
- SetForeWindow(p);
- Activate(p->w_norefresh);
- WindowChanged((struct win*)0, 'w');
- WindowChanged((struct win*)0, 'W');
- WindowChanged((struct win*)0, 0);
- return n;
-}
-
-/*
- * Resurrect a window from Zombie state.
- * The command vector is therefore stored in the window structure.
- * Note: The terminaltype defaults to screenterm again, the current
- * working directory is lost.
- */
-int
-RemakeWindow(p)
-struct win *p;
-{
- char *TtyName;
- int lflag, f;
-
- lflag = nwin_default.lflag;
- if ((f = OpenDevice(p->w_cmdargs, lflag, &p->w_type, &TtyName)) < 0)
- return -1;
-
- strncpy(p->w_tty, *TtyName ? TtyName : p->w_title, MAXSTR - 1);
- p->w_ptyfd = f;
- p->w_readev.fd = f;
- p->w_writeev.fd = f;
- evenq(&p->w_readev);
- evenq(&p->w_writeev);
-
- if (VerboseCreate)
- {
- struct display *d = display; /* WriteString zaps display */
-
- WriteString(p, ":screen (", 9);
- WriteString(p, p->w_title, strlen(p->w_title));
- WriteString(p, "):", 2);
- for (f = 0; p->w_cmdargs[f]; f++)
- {
- WriteString(p, " ", 1);
- WriteString(p, p->w_cmdargs[f], strlen(p->w_cmdargs[f]));
- }
- WriteString(p, "\r\n", 2);
- display = d;
- }
-
- p->w_pid = 0;
-#ifdef BUILTIN_TELNET
- if (p->w_type == W_TYPE_TELNET)
- {
- if (TelConnect(p))
- return -1;
- }
- else
-#endif
- if (p->w_type == W_TYPE_PTY)
- {
- p->w_pid = ForkWindow(p, p->w_cmdargs, TtyName);
- if (p->w_pid < 0)
- return -1;
- }
-
-#ifdef UTMPOK
- if (p->w_slot == (slot_t)0 && (display || (p->w_lflag & 2)))
- SetUtmp(p);
-# ifdef CAREFULUTMP
- CarefulUtmp(); /* If all 've been zombies, we've had no slot */
-# endif
-#endif
- WindowChanged(p, 'f');
- return p->w_number;
-}
-
-void
-CloseDevice(wp)
-struct win *wp;
-{
- if (wp->w_ptyfd < 0)
- return;
- if (wp->w_type == W_TYPE_PTY)
- {
- /* pty 4 SALE */
- (void)chmod(wp->w_tty, 0666);
- (void)chown(wp->w_tty, 0, 0);
- }
- close(wp->w_ptyfd);
- wp->w_ptyfd = -1;
- wp->w_tty[0] = 0;
- evdeq(&wp->w_readev);
- evdeq(&wp->w_writeev);
-#ifdef BUILTIN_TELNET
- evdeq(&wp->w_telconnev);
-#endif
- wp->w_readev.fd = wp->w_writeev.fd = -1;
-}
-
-void
-FreeWindow(wp)
-struct win *wp;
-{
- struct display *d;
- int i;
- struct canvas *cv, *ncv;
- struct layer *l;
-
- debug1("FreeWindow %d\n", wp ? wp->w_number: -1);
-#ifdef PSEUDOS
- if (wp->w_pwin)
- FreePseudowin(wp);
-#endif
-#ifdef UTMPOK
- RemoveUtmp(wp);
-#endif
- CloseDevice(wp);
-
- if (wp == console_window)
- {
- TtyGrabConsole(-1, -1, "free");
- console_window = 0;
- }
- if (wp->w_log != NULL)
- logfclose(wp->w_log);
- ChangeWindowSize(wp, 0, 0, 0);
-
- if (wp->w_hstatus)
- free(wp->w_hstatus);
- for (i = 0; wp->w_cmdargs[i]; i++)
- free(wp->w_cmdargs[i]);
- if (wp->w_dir)
- free(wp->w_dir);
- if (wp->w_term)
- free(wp->w_term);
- for (d = displays; d; d = d->d_next)
- {
- if (d->d_other == wp)
- d->d_other = d->d_fore && d->d_fore->w_next != wp ? d->d_fore->w_next : wp->w_next;
- if (d->d_fore == wp)
- d->d_fore = NULL;
- for (cv = d->d_cvlist; cv; cv = cv->c_next)
- {
- for (l = cv->c_layer; l; l = l->l_next)
- if (l->l_layfn == &WinLf)
- break;
- if (!l)
- continue;
- if ((struct win *)l->l_data != wp)
- continue;
- if (cv->c_layer == wp->w_savelayer)
- wp->w_savelayer = 0;
- KillLayerChain(cv->c_layer);
- }
- }
- if (wp->w_savelayer)
- KillLayerChain(wp->w_savelayer);
- for (cv = wp->w_layer.l_cvlist; cv; cv = ncv)
- {
- ncv = cv->c_lnext;
- cv->c_layer = &cv->c_blank;
- cv->c_blank.l_cvlist = cv;
- cv->c_lnext = 0;
- cv->c_xoff = cv->c_xs;
- cv->c_yoff = cv->c_ys;
- RethinkViewportOffsets(cv);
- }
- wp->w_layer.l_cvlist = 0;
- if (flayer == &wp->w_layer)
- flayer = 0;
-
-#ifdef MULTIUSER
- FreeWindowAcl(wp);
-#endif /* MULTIUSER */
- evdeq(&wp->w_readev); /* just in case */
- evdeq(&wp->w_writeev); /* just in case */
- evdeq(&wp->w_silenceev);
-#ifdef COPY_PASTE
- FreePaster(&wp->w_paster);
-#endif
- free((char *)wp);
-}
-
-static int
-OpenDevice(args, lflag, typep, namep)
-char **args;
-int lflag;
-int *typep;
-char **namep;
-{
- char *arg = args[0];
- struct stat st;
- int f;
-
- if (!arg)
- return -1;
-#ifdef BUILTIN_TELNET
- if (strcmp(arg, "//telnet") == 0)
- {
- f = TelOpen(args + 1);
- lflag = 0;
- *typep = W_TYPE_TELNET;
- *namep = "telnet";
- }
- else
-#endif
- if ((stat(arg, &st)) == 0 && S_ISCHR(st.st_mode))
- {
- if (access(arg, R_OK | W_OK) == -1)
- {
- Msg(errno, "Cannot access line '%s' for R/W", arg);
- return -1;
- }
- debug("OpenDevice: OpenTTY\n");
- if ((f = OpenTTY(arg, args[1])) < 0)
- return -1;
- lflag = 0;
- *typep = W_TYPE_PLAIN;
- *namep = arg;
- }
- else
- {
- *typep = W_TYPE_PTY;
- f = OpenPTY(namep);
- if (f == -1)
- {
- Msg(0, "No more PTYs.");
- return -1;
- }
-#ifdef TIOCPKT
- {
- int flag = 1;
- if (ioctl(f, TIOCPKT, (char *)&flag))
- {
- Msg(errno, "TIOCPKT ioctl");
- close(f);
- return -1;
- }
- }
-#endif /* TIOCPKT */
- }
- debug1("fcntl(%d, F_SETFL, FNBLOCK)\n", f);
- (void) fcntl(f, F_SETFL, FNBLOCK);
-#ifdef linux
- /*
- * Tenebreux (zeus@ns.acadiacom.net) has Linux 1.3.70 where select
- * gets confused in the following condition:
- * Open a pty-master side, request a flush on it, then set packet
- * mode and call select(). Select will return a possible read, where
- * the one byte response to the flush can be found. Select will
- * thereafter return a possible read, which yields I/O error.
- *
- * If we request another flush *after* switching into packet mode,
- * this I/O error does not occur. We receive a single response byte
- * although we send two flush requests now.
- *
- * Maybe we should not flush at all.
- *
- * 10.5.96 jw.
- */
- if (*typep == W_TYPE_PTY || *typep == W_TYPE_PLAIN)
- tcflush(f, TCIOFLUSH);
-#endif
-
- if (*typep != W_TYPE_PTY)
- return f;
-
-#ifndef PTYROFS
-#ifdef PTYGROUP
- if (chown(*namep, real_uid, PTYGROUP) && !eff_uid)
-#else
- if (chown(*namep, real_uid, real_gid) && !eff_uid)
-#endif
- {
- Msg(errno, "chown tty");
- close(f);
- return -1;
- }
-#ifdef UTMPOK
- if (chmod(*namep, lflag ? TtyMode : (TtyMode & ~022)) && !eff_uid)
-#else
- if (chmod(*namep, TtyMode) && !eff_uid)
-#endif
- {
- Msg(errno, "chmod tty");
- close(f);
- return -1;
- }
-#endif
- return f;
-}
-
-/*
- * Fields w_width, w_height, aflag, number (and w_tty)
- * are read from struct win *win. No fields written.
- * If pwin is nonzero, filedescriptors are distributed
- * between win->w_tty and open(ttyn)
- *
- */
-static int
-ForkWindow(win, args, ttyn)
-struct win *win;
-char **args, *ttyn;
-{
- int pid;
- char tebuf[25];
- char ebuf[10];
- char shellbuf[7 + MAXPATHLEN];
- char *proc;
-#ifndef TIOCSWINSZ
- char libuf[20], cobuf[20];
-#endif
- int newfd;
- int w = win->w_width;
- int h = win->w_height;
-#ifdef PSEUDOS
- int i, pat, wfdused;
- struct pseudowin *pwin = win->w_pwin;
-#endif
- int slave = -1;
-
-#ifdef O_NOCTTY
- if (pty_preopen)
- {
- debug("pre-opening slave...\n");
- if ((slave = open(ttyn, O_RDWR|O_NOCTTY)) == -1)
- {
- Msg(errno, "ttyn");
- return -1;
- }
- }
-#endif
- debug("forking...\n");
- proc = *args;
- if (proc == 0)
- {
- args = ShellArgs;
- proc = *args;
- }
- fflush(stdout);
- fflush(stderr);
- switch (pid = fork())
- {
- case -1:
- Msg(errno, "fork");
- break;
- case 0:
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
-#ifdef BSDJOBS
- signal(SIGTTIN, SIG_DFL);
- signal(SIGTTOU, SIG_DFL);
-#endif
-#ifdef SIGPIPE
- signal(SIGPIPE, SIG_DFL);
-#endif
-#ifdef SIGXFSZ
- signal(SIGXFSZ, SIG_DFL);
-#endif
-
- displays = 0; /* beware of Panic() */
- if (setgid(real_gid) || setuid(real_uid))
- Panic(errno, "Setuid/gid");
- eff_uid = real_uid;
- eff_gid = real_gid;
-#ifdef PSEUDOS
- if (!pwin) /* ignore directory if pseudo */
-#endif
- if (win->w_dir && *win->w_dir && chdir(win->w_dir))
- Panic(errno, "Cannot chdir to %s", win->w_dir);
-
- if (display)
- {
- brktty(D_userfd);
- freetty();
- }
- else
- brktty(-1);
-#ifdef DEBUG
- if (dfp && dfp != stderr)
- fclose(dfp);
-#endif
- if (slave != -1)
- {
- close(0);
- dup(slave);
- close(slave);
- closeallfiles(win->w_ptyfd);
- slave = dup(0);
- }
- else
- closeallfiles(win->w_ptyfd);
-#ifdef DEBUG
- if (dfp) /* do not produce child debug, when debug is "off" */
- {
- char buf[256];
-
- sprintf(buf, "%s/screen.child", DEBUGDIR);
- if ((dfp = fopen(buf, "a")) == 0)
- dfp = stderr;
- else
- (void) chmod(buf, 0666);
- }
- debug1("=== ForkWindow: pid %d\n", (int)getpid());
-#endif
- /* Close the three /dev/null descriptors */
- close(0);
- close(1);
- close(2);
- newfd = -1;
- /*
- * distribute filedescriptors between the ttys
- */
-#ifdef PSEUDOS
- pat = pwin ? pwin->p_fdpat :
- ((F_PFRONT<<(F_PSHIFT*2)) | (F_PFRONT<<F_PSHIFT) | F_PFRONT);
- debug1("Using window pattern 0x%x\n", pat);
- wfdused = 0;
- for(i = 0; i < 3; i++)
- {
- if (pat & F_PFRONT << F_PSHIFT * i)
- {
- if (newfd < 0)
- {
-# ifdef O_NOCTTY
- if (separate_sids)
- newfd = open(ttyn, O_RDWR);
- else
- newfd = open(ttyn, O_RDWR|O_NOCTTY);
-# else
- newfd = open(ttyn, O_RDWR);
-# endif
- if (newfd < 0)
- Panic(errno, "Cannot open %s", ttyn);
- }
- else
- dup(newfd);
- }
- else
- {
- dup(win->w_ptyfd);
- wfdused = 1;
- }
- }
- if (wfdused)
- {
- /*
- * the pseudo window process should not be surprised with a
- * nonblocking filedescriptor. Poor Backend!
- */
- debug1("Clearing NBLOCK on window-fd(%d)\n", win->w_ptyfd);
- if (fcntl(win->w_ptyfd, F_SETFL, 0))
- Msg(errno, "Warning: clear NBLOCK fcntl failed");
- }
-#else /* PSEUDOS */
-# ifdef O_NOCTTY
- if (separate_sids)
- newfd = open(ttyn, O_RDWR);
- else
- newfd = open(ttyn, O_RDWR|O_NOCTTY);
-# else
- newfd = open(ttyn, O_RDWR);
-# endif
- if (newfd != 0)
- Panic(errno, "Cannot open %s", ttyn);
- dup(0);
- dup(0);
-#endif /* PSEUDOS */
- close(win->w_ptyfd);
- if (slave != -1)
- close(slave);
- if (newfd >= 0)
- {
- struct mode fakemode, *modep;
- InitPTY(newfd);
- if (fgtty(newfd))
- Msg(errno, "fgtty");
- if (display)
- {
- debug("ForkWindow: using display tty mode for new child.\n");
- modep = &D_OldMode;
- }
- else
- {
- debug("No display - creating tty setting\n");
- modep = &fakemode;
- InitTTY(modep, 0);
-#ifdef DEBUG
- DebugTTY(modep);
-#endif
- }
- /* We only want echo if the users input goes to the pseudo
- * and the pseudo's stdout is not send to the window.
- */
-#ifdef PSEUDOS
- if (pwin && (!(pat & F_UWP) || (pat & F_PBACK << F_PSHIFT)))
- {
- debug1("clearing echo on pseudywin fd (pat %x)\n", pat);
-# if defined(POSIX) || defined(TERMIO)
- modep->tio.c_lflag &= ~ECHO;
- modep->tio.c_iflag &= ~ICRNL;
-# else
- modep->m_ttyb.sg_flags &= ~ECHO;
-# endif
- }
-#endif
- SetTTY(newfd, modep);
-#ifdef TIOCSWINSZ
- glwz.ws_col = w;
- glwz.ws_row = h;
- (void) ioctl(newfd, TIOCSWINSZ, (char *)&glwz);
-#endif
- /* Always turn off nonblocking mode */
- (void)fcntl(newfd, F_SETFL, 0);
- }
-#ifndef TIOCSWINSZ
- sprintf(libuf, "LINES=%d", h);
- sprintf(cobuf, "COLUMNS=%d", w);
- NewEnv[5] = libuf;
- NewEnv[6] = cobuf;
-#endif
-#ifdef MAPKEYS
- NewEnv[2] = MakeTermcap(display == 0 || win->w_aflag);
-#else
- if (win->w_aflag)
- NewEnv[2] = MakeTermcap(1);
- else
- NewEnv[2] = Termcap;
-#endif
- strcpy(shellbuf, "SHELL=");
- strncpy(shellbuf + 6, ShellProg + (*ShellProg == '-'), sizeof(shellbuf) - 7);
- shellbuf[sizeof(shellbuf) - 1] = 0;
- NewEnv[4] = shellbuf;
- debug1("ForkWindow: NewEnv[4] = '%s'\n", shellbuf);
- if (win->w_term && *win->w_term && strcmp(screenterm, win->w_term) &&
- (strlen(win->w_term) < 20))
- {
- char *s1, *s2, tl;
-
- sprintf(tebuf, "TERM=%s", win->w_term);
- debug2("Makewindow %d with %s\n", win->w_number, tebuf);
- tl = strlen(win->w_term);
- NewEnv[1] = tebuf;
- if ((s1 = index(NewEnv[2], '|')))
- {
- if ((s2 = index(++s1, '|')))
- {
- if (strlen(NewEnv[2]) - (s2 - s1) + tl < 1024)
- {
- bcopy(s2, s1 + tl, strlen(s2) + 1);
- bcopy(win->w_term, s1, tl);
- }
- }
- }
- }
- sprintf(ebuf, "WINDOW=%d", win->w_number);
- NewEnv[3] = ebuf;
-
- if (*proc == '-')
- proc++;
- if (!*proc)
- proc = DefaultShell;
- debug1("calling execvpe %s\n", proc);
- execvpe(proc, args, NewEnv);
- debug1("exec error: %d\n", errno);
- Panic(errno, "Cannot exec '%s'", proc);
- default:
- break;
- }
- if (slave != -1)
- close(slave);
- return pid;
-}
-
-void
-execvpe(prog, args, env)
-char *prog, **args, **env;
-{
- register char *path = NULL, *p;
- char buf[1024];
- char *shargs[MAXARGS + 1];
- register int i, eaccess = 0;
-
- if (rindex(prog, '/'))
- path = "";
- if (!path && !(path = getenv("PATH")))
- path = DefaultPath;
- do
- {
- for (p = buf; *path && *path != ':'; path++)
- if (p - buf < (int)sizeof(buf) - 2)
- *p++ = *path;
- if (p > buf)
- *p++ = '/';
- if (p - buf + strlen(prog) >= sizeof(buf) - 1)
- continue;
- strcpy(p, prog);
- execve(buf, args, env);
- switch (errno)
- {
- case ENOEXEC:
- shargs[0] = DefaultShell;
- shargs[1] = buf;
- for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i)
- ;
- execve(DefaultShell, shargs, env);
- return;
- case EACCES:
- eaccess = 1;
- break;
- case ENOMEM:
- case E2BIG:
- case ETXTBSY:
- return;
- }
- } while (*path++);
- if (eaccess)
- errno = EACCES;
-}
-
-#ifdef PSEUDOS
-
-int
-winexec(av)
-char **av;
-{
- char **pp;
- char *p, *s, *t;
- int i, r = 0, l = 0;
- struct win *w;
- extern struct display *display;
- extern struct win *windows;
- struct pseudowin *pwin;
- int type;
-
- if ((w = display ? fore : windows) == NULL)
- return -1;
- if (!*av || w->w_pwin)
- {
- Msg(0, "Filter running: %s", w->w_pwin ? w->w_pwin->p_cmd : "(none)");
- return -1;
- }
- if (w->w_ptyfd < 0)
- {
- Msg(0, "You feel dead inside.");
- return -1;
- }
- if (!(pwin = (struct pseudowin *)malloc(sizeof(struct pseudowin))))
- {
- Msg(0, strnomem);
- return -1;
- }
- bzero((char *)pwin, (int)sizeof(*pwin));
-
- /* allow ^a:!!./ttytest as a short form for ^a:exec !.. ./ttytest */
- for (s = *av; *s == ' '; s++)
- ;
- for (p = s; *p == ':' || *p == '.' || *p == '!'; p++)
- ;
- if (*p != '|')
- while (*p && p > s && p[-1] == '.')
- p--;
- if (*p == '|')
- {
- l = F_UWP;
- p++;
- }
- if (*p)
- av[0] = p;
- else
- av++;
-
- t = pwin->p_cmd;
- for (i = 0; i < 3; i++)
- {
- *t = (s < p) ? *s++ : '.';
- switch (*t++)
- {
- case '.':
- case '|':
- l |= F_PFRONT << (i * F_PSHIFT);
- break;
- case '!':
- l |= F_PBACK << (i * F_PSHIFT);
- break;
- case ':':
- l |= F_PBOTH << (i * F_PSHIFT);
- break;
- }
- }
-
- if (l & F_UWP)
- {
- *t++ = '|';
- if ((l & F_PMASK) == F_PFRONT)
- {
- *pwin->p_cmd = '!';
- l ^= F_PFRONT | F_PBACK;
- }
- }
- if (!(l & F_PBACK))
- l |= F_UWP;
- *t++ = ' ';
- pwin->p_fdpat = l;
- debug1("winexec: '%#x'\n", pwin->p_fdpat);
-
- l = MAXSTR - 4;
- for (pp = av; *pp; pp++)
- {
- p = *pp;
- while (*p && l-- > 0)
- *t++ = *p++;
- if (l <= 0)
- break;
- *t++ = ' ';
- }
- *--t = '\0';
- debug1("%s\n", pwin->p_cmd);
-
- if ((pwin->p_ptyfd = OpenDevice(av, 0, &type, &t)) < 0)
- {
- free((char *)pwin);
- return -1;
- }
- strncpy(pwin->p_tty, t, MAXSTR - 1);
- w->w_pwin = pwin;
- if (type != W_TYPE_PTY)
- {
- FreePseudowin(w);
- Msg(0, "Cannot only use commands as pseudo win.");
- return -1;
- }
- if (!(pwin->p_fdpat & F_PFRONT))
- evdeq(&w->w_readev);
-#ifdef TIOCPKT
- {
- int flag = 0;
-
- if (ioctl(pwin->p_ptyfd, TIOCPKT, (char *)&flag))
- {
- Msg(errno, "TIOCPKT pwin ioctl");
- FreePseudowin(w);
- return -1;
- }
- if (w->w_type == W_TYPE_PTY && !(pwin->p_fdpat & F_PFRONT))
- {
- if (ioctl(w->w_ptyfd, TIOCPKT, (char *)&flag))
- {
- Msg(errno, "TIOCPKT win ioctl");
- FreePseudowin(w);
- return -1;
- }
- }
- }
-#endif /* TIOCPKT */
-
- pwin->p_readev.fd = pwin->p_writeev.fd = pwin->p_ptyfd;
- pwin->p_readev.type = EV_READ;
- pwin->p_writeev.type = EV_WRITE;
- pwin->p_readev.data = pwin->p_writeev.data = (char *)w;
- pwin->p_readev.handler = pseu_readev_fn;
- pwin->p_writeev.handler = pseu_writeev_fn;
- pwin->p_writeev.condpos = &pwin->p_inlen;
- if (pwin->p_fdpat & (F_PFRONT << F_PSHIFT * 2 | F_PFRONT << F_PSHIFT))
- evenq(&pwin->p_readev);
- evenq(&pwin->p_writeev);
- r = pwin->p_pid = ForkWindow(w, av, t);
- if (r < 0)
- FreePseudowin(w);
- return r;
-}
-
-void
-FreePseudowin(w)
-struct win *w;
-{
- struct pseudowin *pwin = w->w_pwin;
-
- ASSERT(pwin);
- if (fcntl(w->w_ptyfd, F_SETFL, FNBLOCK))
- Msg(errno, "Warning: FreePseudowin: NBLOCK fcntl failed");
-#ifdef TIOCPKT
- if (w->w_type == W_TYPE_PTY && !(pwin->p_fdpat & F_PFRONT))
- {
- int flag = 1;
- if (ioctl(w->w_ptyfd, TIOCPKT, (char *)&flag))
- Msg(errno, "Warning: FreePseudowin: TIOCPKT win ioctl");
- }
-#endif
- /* should be able to use CloseDevice() here */
- (void)chmod(pwin->p_tty, 0666);
- (void)chown(pwin->p_tty, 0, 0);
- if (pwin->p_ptyfd >= 0)
- close(pwin->p_ptyfd);
- evdeq(&pwin->p_readev);
- evdeq(&pwin->p_writeev);
- if (w->w_readev.condneg == &pwin->p_inlen)
- w->w_readev.condpos = w->w_readev.condneg = 0;
- evenq(&w->w_readev);
- free((char *)pwin);
- w->w_pwin = NULL;
-}
-
-#endif /* PSEUDOS */
-
-
-#ifdef MULTIUSER
-/*
- * returns 0, if the lock really has been released
- */
-int
-ReleaseAutoWritelock(dis, w)
-struct display *dis;
-struct win *w;
-{
- debug2("ReleaseAutoWritelock: user %s, window %d\n",
- dis->d_user->u_name, w->w_number);
-
- /* release auto writelock when user has no other display here */
- if (w->w_wlock == WLOCK_AUTO && w->w_wlockuser == dis->d_user)
- {
- struct display *d;
-
- for (d = displays; d; d = d->d_next)
- if (( d != dis) && (d->d_fore == w) && (d->d_user == dis->d_user))
- break;
- debug3("%s %s autolock on win %d\n",
- dis->d_user->u_name, d ? "keeps" : "releases", w->w_number);
- if (!d)
- {
- w->w_wlockuser = NULL;
- return 0;
- }
- }
- return 1;
-}
-
-/*
- * returns 0, if the lock really could be obtained
- */
-int
-ObtainAutoWritelock(d, w)
-struct display *d;
-struct win *w;
-{
- if ((w->w_wlock == WLOCK_AUTO) &&
- !AclCheckPermWin(d->d_user, ACL_WRITE, w) &&
- !w->w_wlockuser)
- {
- debug2("%s obtained auto writelock for exported window %d\n",
- d->d_user->u_name, w->w_number);
- w->w_wlockuser = d->d_user;
- return 0;
- }
- return 1;
-}
-
-#endif /* MULTIUSER */
-
-
-
-/********************************************************************/
-
-#ifdef COPY_PASTE
-static void
-paste_slowev_fn(ev, data)
-struct event *ev;
-char *data;
-{
- struct paster *pa = (struct paster *)data;
- struct win *p;
-
- int l = 1;
- flayer = pa->pa_pastelayer;
- if (!flayer)
- pa->pa_pastelen = 0;
- if (!pa->pa_pastelen)
- return;
- p = Layer2Window(flayer);
- DoProcess(p, &pa->pa_pasteptr, &l, pa);
- pa->pa_pastelen -= 1 - l;
- if (pa->pa_pastelen > 0)
- {
- SetTimeout(&pa->pa_slowev, p->w_slowpaste);
- evenq(&pa->pa_slowev);
- }
-}
-#endif
-
-
-static int
-muchpending(p, ev)
-struct win *p;
-struct event *ev;
-{
- struct canvas *cv;
- for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext)
- {
- display = cv->c_display;
- if (D_status == STATUS_ON_WIN && !D_status_bell)
- {
- /* wait 'til status is gone */
- debug("BLOCKING because of status\n");
- ev->condpos = &const_one;
- ev->condneg = &D_status;
- return 1;
- }
- debug2("muchpending %s %d: ", D_usertty, D_blocked);
- debug3("%d %d %d\n", D_obufp - D_obuf, D_obufmax, D_blocked_fuzz);
- if (D_blocked)
- continue;
- if (D_obufp - D_obuf > D_obufmax + D_blocked_fuzz)
- {
- if (D_nonblock == 0)
- {
- debug1("obuf is full, stopping output to display %s\n", D_usertty);
- D_blocked = 1;
- continue;
- }
- debug("BLOCKING because of full obuf\n");
- ev->condpos = &D_obuffree;
- ev->condneg = &D_obuflenmax;
- if (D_nonblock > 0 && !D_blockedev.queued)
- {
- debug1("created timeout of %g secs\n", D_nonblock/1000.);
- SetTimeout(&D_blockedev, D_nonblock);
- evenq(&D_blockedev);
- }
- return 1;
- }
- }
- return 0;
-}
-
-static void
-win_readev_fn(ev, data)
-struct event *ev;
-char *data;
-{
- struct win *p = (struct win *)data;
- char buf[IOSIZE], *bp;
- int size, len;
-#ifdef PSEUDOS
- int wtop;
-#endif
-
- bp = buf;
- size = IOSIZE;
-
-#ifdef PSEUDOS
- wtop = p->w_pwin && W_WTOP(p);
- if (wtop)
- {
- ASSERT(sizeof(p->w_pwin->p_inbuf) == IOSIZE);
- size = IOSIZE - p->w_pwin->p_inlen;
- if (size <= 0)
- {
- ev->condpos = &const_IOSIZE;
- ev->condneg = &p->w_pwin->p_inlen;
- return;
- }
- }
-#endif
- if (p->w_layer.l_cvlist && muchpending(p, ev))
- return;
-#ifdef ZMODEM
- if (!p->w_zdisplay)
-#endif
- if (p->w_blocked)
- {
- ev->condpos = &const_one;
- ev->condneg = &p->w_blocked;
- return;
- }
- if (ev->condpos)
- ev->condpos = ev->condneg = 0;
-
- if ((len = p->w_outlen))
- {
- p->w_outlen = 0;
- WriteString(p, p->w_outbuf, len);
- return;
- }
-
- debug1("going to read from window fd %d\n", ev->fd);
- if ((len = read(ev->fd, buf, size)) < 0)
- {
- if (errno == EINTR || errno == EAGAIN)
- return;
-#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
- if (errno == EWOULDBLOCK)
- return;
-#endif
- debug2("Window %d: read error (errno %d) - killing window\n", p->w_number, errno);
- WindowDied(p);
- return;
- }
- if (len == 0)
- {
- debug1("Window %d: EOF - killing window\n", p->w_number);
- WindowDied(p);
- return;
- }
- debug1(" -> %d bytes\n", len);
-#ifdef TIOCPKT
- if (p->w_type == W_TYPE_PTY)
- {
- if (buf[0])
- {
- debug1("PAKET %x\n", buf[0]);
- if (buf[0] & TIOCPKT_NOSTOP)
- WNewAutoFlow(p, 0);
- if (buf[0] & TIOCPKT_DOSTOP)
- WNewAutoFlow(p, 1);
- }
- bp++;
- len--;
- }
-#endif
-#ifdef BUILTIN_TELNET
- if (p->w_type == W_TYPE_TELNET)
- len = TelIn(p, bp, len, buf + sizeof(buf) - (bp + len));
-#endif
- if (len == 0)
- return;
-#ifdef ZMODEM
- if (zmodem_mode && zmodem_parse(p, bp, len))
- return;
-#endif
-#ifdef PSEUDOS
- if (wtop)
- {
- debug("sending input to pwin\n");
- bcopy(bp, p->w_pwin->p_inbuf + p->w_pwin->p_inlen, len);
- p->w_pwin->p_inlen += len;
- }
-#endif
- WriteString(p, bp, len);
- return;
-}
-
-
-static void
-win_writeev_fn(ev, data)
-struct event *ev;
-char *data;
-{
- struct win *p = (struct win *)data;
- int len;
- if (p->w_inlen)
- {
- debug2("writing %d bytes to win %d\n", p->w_inlen, p->w_number);
- if ((len = write(ev->fd, p->w_inbuf, p->w_inlen)) <= 0)
- len = p->w_inlen; /* dead window */
- if ((p->w_inlen -= len))
- bcopy(p->w_inbuf + len, p->w_inbuf, p->w_inlen);
- }
-#ifdef COPY_PASTE
- if (p->w_paster.pa_pastelen && !p->w_slowpaste)
- {
- struct paster *pa = &p->w_paster;
- flayer = pa->pa_pastelayer;
- if (flayer)
- DoProcess(p, &pa->pa_pasteptr, &pa->pa_pastelen, pa);
- }
-#endif
- return;
-}
-
-
-
-#ifdef PSEUDOS
-
-static void
-pseu_readev_fn(ev, data)
-struct event *ev;
-char *data;
-{
- struct win *p = (struct win *)data;
- char buf[IOSIZE];
- int size, ptow, len;
-
- size = IOSIZE;
-
- ptow = W_PTOW(p);
- if (ptow)
- {
- ASSERT(sizeof(p->w_inbuf) == IOSIZE);
- size = IOSIZE - p->w_inlen;
- if (size <= 0)
- {
- ev->condpos = &const_IOSIZE;
- ev->condneg = &p->w_inlen;
- return;
- }
- }
- if (p->w_layer.l_cvlist && muchpending(p, ev))
- return;
- if (p->w_blocked)
- {
- ev->condpos = &const_one;
- ev->condneg = &p->w_blocked;
- return;
- }
- if (ev->condpos)
- ev->condpos = ev->condneg = 0;
-
- if ((len = p->w_outlen))
- {
- p->w_outlen = 0;
- WriteString(p, p->w_outbuf, len);
- return;
- }
-
- if ((len = read(ev->fd, buf, size)) <= 0)
- {
- if (errno == EINTR || errno == EAGAIN)
- return;
-#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
- if (errno == EWOULDBLOCK)
- return;
-#endif
- debug2("Window %d: pseudowin read error (errno %d) -- removing pseudowin\n", p->w_number, len ? errno : 0);
- FreePseudowin(p);
- return;
- }
- /* no packet mode on pseudos! */
- if (ptow)
- {
- bcopy(buf, p->w_inbuf + p->w_inlen, len);
- p->w_inlen += len;
- }
- WriteString(p, buf, len);
- return;
-}
-
-static void
-pseu_writeev_fn(ev, data)
-struct event *ev;
-char *data;
-{
- struct win *p = (struct win *)data;
- struct pseudowin *pw = p->w_pwin;
- int len;
-
- ASSERT(pw);
- if (pw->p_inlen == 0)
- return;
- if ((len = write(ev->fd, pw->p_inbuf, pw->p_inlen)) <= 0)
- len = pw->p_inlen; /* dead pseudo */
- if ((p->w_pwin->p_inlen -= len))
- bcopy(p->w_pwin->p_inbuf + len, p->w_pwin->p_inbuf, p->w_pwin->p_inlen);
-}
-
-
-#endif /* PSEUDOS */
-
-static void
-win_silenceev_fn(ev, data)
-struct event *ev;
-char *data;
-{
- struct win *p = (struct win *)data;
- struct canvas *cv;
- debug1("FOUND silence win %d\n", p->w_number);
- for (display = displays; display; display = display->d_next)
- {
- for (cv = D_cvlist; cv; cv = cv->c_next)
- if (cv->c_layer->l_bottom == &p->w_layer)
- break;
- if (cv)
- continue; /* user already sees window */
-#ifdef MULTIUSER
- if (!(ACLBYTE(p->w_lio_notify, D_user->u_id) & ACLBIT(D_user->u_id)))
- continue;
-#endif
- Msg(0, "Window %d: silence for %d seconds", p->w_number, p->w_silencewait);
- }
-}
-
-#ifdef ZMODEM
-
-static int
-zmodem_parse(p, bp, len)
-struct win *p;
-char *bp;
-int len;
-{
- int i;
- char *b2 = bp;
- for (i = 0; i < len; i++, b2++)
- {
- if (p->w_zauto == 0)
- {
- for (; i < len; i++, b2++)
- if (*b2 == 030)
- break;
- if (i == len)
- break;
- if (i > 1 && b2[-1] == '*' && b2[-2] == '*')
- p->w_zauto = 3;
- continue;
- }
- if (p->w_zauto > 5 || *b2 == "**\030B00"[p->w_zauto] || (p->w_zauto == 5 && *b2 == '1') || (p->w_zauto == 5 && p->w_zdisplay && *b2 == '8'))
- {
- if (++p->w_zauto < 6)
- continue;
- if (p->w_zauto == 6)
- p->w_zauto = 0;
- if (!p->w_zdisplay)
- {
- if (i > 6)
- WriteString(p, bp, i + 1 - 6);
- WriteString(p, "\r\n", 2);
- zmodem_found(p, *b2 == '1', b2 + 1, len - i - 1);
- return 1;
- }
- else if (p->w_zauto == 7 || *b2 == '8')
- {
- int se = p->w_zdisplay->d_blocked == 2 ? 'O' : '\212';
- for (; i < len; i++, b2++)
- if (*b2 == se)
- break;
- if (i < len)
- {
- zmodem_abort(p, 0);
- D_blocked = 0;
- D_readev.condpos = D_readev.condneg = 0;
- while (len-- > 0)
- AddChar(*bp++);
- Flush();
- Activate(D_fore ? D_fore->w_norefresh : 0);
- return 1;
- }
- p->w_zauto = 6;
- }
- }
- else
- p->w_zauto = *b2 == '*' ? (p->w_zauto == 2 ? 2 : 1) : 0;
- }
- if (p->w_zauto == 0 && bp[len - 1] == '*')
- p->w_zauto = len > 1 && bp[len - 2] == '*' ? 2 : 1;
- if (p->w_zdisplay)
- {
- display = p->w_zdisplay;
- while (len-- > 0)
- AddChar(*bp++);
- return 1;
- }
- return 0;
-}
-
-static void
-zmodem_fin(buf, len, data)
-char *buf;
-int len;
-char *data;
-{
- char *s;
- int n;
-
- if (len)
- RcLine(buf, strlen(buf) + 1);
- else
- {
- s = "\030\030\030\030\030\030\030\030\030\030";
- n = strlen(s);
- LayProcess(&s, &n);
- }
-}
-
-static void
-zmodem_found(p, send, bp, len)
-struct win *p;
-int send;
-char *bp;
-int len;
-{
- char *s;
- int i, n;
- extern int zmodem_mode;
-
- /* check for abort sequence */
- n = 0;
- for (i = 0; i < len ; i++)
- if (bp[i] != 030)
- n = 0;
- else if (++n > 4)
- return;
- if (zmodem_mode == 3 || (zmodem_mode == 1 && p->w_type != W_TYPE_PLAIN))
- {
- struct display *d, *olddisplay;
-
- olddisplay = display;
- d = p->w_lastdisp;
- if (!d || d->d_fore != p)
- for (d = displays; d; d = d->d_next)
- if (d->d_fore == p)
- break;
- if (!d && p->w_layer.l_cvlist)
- d = p->w_layer.l_cvlist->c_display;
- if (!d)
- d = displays;
- if (!d)
- return;
- display = d;
- RemoveStatus();
- p->w_zdisplay = display;
- D_blocked = 2 + send;
- flayer = &p->w_layer;
- ZmodemPage();
- display = d;
- evdeq(&D_blockedev);
- D_readev.condpos = &const_IOSIZE;
- D_readev.condneg = &p->w_inlen;
- ClearAll();
- GotoPos(0, 0);
- SetRendition(&mchar_blank);
- AddStr("Zmodem active\r\n\r\n");
- AddStr(send ? "**\030B01" : "**\030B00");
- while (len-- > 0)
- AddChar(*bp++);
- display = olddisplay;
- return;
- }
- flayer = &p->w_layer;
- Input(":", 100, INP_COOKED, zmodem_fin, NULL);
- s = send ? zmodem_sendcmd : zmodem_recvcmd;
- n = strlen(s);
- LayProcess(&s, &n);
-}
-
-void
-zmodem_abort(p, d)
-struct win *p;
-struct display *d;
-{
- struct display *olddisplay = display;
- struct layer *oldflayer = flayer;
- if (p)
- {
- if (p->w_savelayer && p->w_savelayer->l_next)
- {
- if (oldflayer == p->w_savelayer)
- oldflayer = flayer->l_next;
- flayer = p->w_savelayer;
- ExitOverlayPage();
- }
- p->w_zdisplay = 0;
- p->w_zauto = 0;
- LRefreshAll(&p->w_layer, 0);
- }
- if (d)
- {
- display = d;
- D_blocked = 0;
- D_readev.condpos = D_readev.condneg = 0;
- Activate(D_fore ? D_fore->w_norefresh : 0);
- }
- display = olddisplay;
- flayer = oldflayer;
-}
-
-#endif