summaryrefslogtreecommitdiff
path: root/window.c
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2011-09-03 14:05:25 +0200
committerAxel Beckert <abe@deuxchevaux.org>2011-09-03 14:05:25 +0200
commit9d943c7539f59f42ba8f8052497dc541fe5f0167 (patch)
treec8725127bf7a68d3d7fe57adca45c204b25adf21 /window.c
parent0e9a09d7718f02726b12924f7ddb05a992202aa3 (diff)
downloadscreen-9d943c7539f59f42ba8f8052497dc541fe5f0167.tar.gz
Imported Upstream version 4.0.2upstream/4.0.2
Diffstat (limited to 'window.c')
-rw-r--r--window.c410
1 files changed, 323 insertions, 87 deletions
diff --git a/window.c b/window.c
index 789debe..3b60ae0 100644
--- a/window.c
+++ b/window.c
@@ -21,9 +21,6 @@
****************************************************************
*/
-#include "rcs.h"
-RCS_ID("$Id: window.c,v 1.20 1994/05/31 12:33:24 mlschroe Exp $ FAU")
-
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
@@ -50,21 +47,24 @@ extern int SilenceWait;
extern int real_uid, real_gid, eff_uid, eff_gid;
extern char Termcap[];
extern char **NewEnv;
-extern int visual_bell;
+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 _IBMR2
-extern int aixhack;
-#endif
-
#ifdef O_NOCTTY
extern int separate_sids;
#endif
@@ -91,7 +91,12 @@ 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 *));
-static void execvpe __P((char *, 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 */
@@ -133,7 +138,7 @@ struct NewWindow nwin_default =
0, /* dir */
screenterm, /* term */
0, /* aflag */
- 1*FLOW_NOW, /* flowflag */
+ 1*FLOW_NOW, /* flowflag */
LOGINDEFAULT, /* lflag */
DEFAULTHISTHEIGHT, /* histheight */
MON_OFF, /* monitor */
@@ -183,7 +188,7 @@ struct NewWindow *def, *new, *res;
COMPOSE(charset);
#undef COMPOSE
}
-
+
/*****************************************************************
*
* The window layer functions
@@ -235,7 +240,7 @@ int *lenp;
{
int l2 = 0, f, *ilen, l = *lenp, trunc;
char *ibuf;
-
+
debug1("WinProcess: %d bytes\n", *lenp);
fore = (struct win *)flayer->l_data;
@@ -482,12 +487,12 @@ WinRestore()
/*
- * DoStartLog constructs a path for the "want to be logfile" in buf and
+ * DoStartLog constructs a path for the "want to be logfile" in buf and
* attempts logfopen.
*
* returns 0 on success.
*/
-int
+int
DoStartLog(w, buf, bufsize)
struct win *w;
char *buf;
@@ -519,8 +524,8 @@ int bufsize;
return 0;
}
-/*
- * Umask & wlock are set for the user of the display,
+/*
+ * Umask & wlock are set for the user of the display,
* The display d (if specified) switches to that window.
*/
int
@@ -531,7 +536,7 @@ struct NewWindow *newwin;
register int n, i;
int f = -1;
struct NewWindow nwin;
- int type;
+ int type, startat;
char *TtyName;
#ifdef MULTIUSER
extern struct acluser *users;
@@ -547,16 +552,17 @@ struct NewWindow *newwin;
debug1("NWin: wlock %d\n", nwin.wlock);
debug1("NWin: Lflag %d\n", nwin.Lflag);
- pp = wtab + nwin.StartAt;
+ startat = nwin.StartAt < maxwin ? nwin.StartAt : 0;
+ pp = wtab + startat;
do
{
if (*pp == 0)
break;
- if (++pp == wtab + MAXWIN)
+ if (++pp == wtab + maxwin)
pp = wtab;
}
- while (pp != wtab + nwin.StartAt);
+ while (pp != wtab + startat);
if (*pp)
{
Msg(0, "No more windows.");
@@ -605,8 +611,8 @@ struct NewWindow *newwin;
p->w_number = n;
#ifdef MULTIUSER
- /*
- * This is dangerous: without a display we use creators umask
+ /*
+ * 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.
*/
@@ -624,6 +630,7 @@ struct NewWindow *newwin;
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))
@@ -635,7 +642,7 @@ struct NewWindow *newwin;
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, MAXSTR - 1);
+ strncpy(p->w_akabuf, nwin.aka, sizeof(p->w_akabuf) - 1);
if ((nwin.aka = rindex(p->w_akabuf, '|')) != NULL)
{
p->w_autoaka = 0;
@@ -814,9 +821,9 @@ struct NewWindow *newwin;
}
/*
- * Resurrect a window from Zombie state.
+ * 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
+ * Note: The terminaltype defaults to screenterm again, the current
* working directory is lost.
*/
int
@@ -972,6 +979,8 @@ struct win *wp;
RethinkViewportOffsets(cv);
}
wp->w_layer.l_cvlist = 0;
+ if (flayer == &wp->w_layer)
+ flayer = 0;
#ifdef MULTIUSER
FreeWindowAcl(wp);
@@ -1012,7 +1021,7 @@ char **namep;
{
if (access(arg, R_OK | W_OK) == -1)
{
- Msg(errno, "Cannot access line '%s' for R/W", arg);
+ Msg(errno, "Cannot access line '%s' for R/W", arg);
return -1;
}
debug("OpenDevice: OpenTTY\n");
@@ -1069,6 +1078,7 @@ char **namep;
if (*typep != W_TYPE_PTY)
return f;
+#ifndef PTYROFS
#ifdef PTYGROUP
if (chown(*namep, real_uid, PTYGROUP) && !eff_uid)
#else
@@ -1089,17 +1099,18 @@ char **namep;
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
+ * If pwin is nonzero, filedescriptors are distributed
* between win->w_tty and open(ttyn)
*
*/
-static int
+static int
ForkWindow(win, args, ttyn)
struct win *win;
char **args, *ttyn;
@@ -1119,24 +1130,19 @@ char **args, *ttyn;
int i, pat, wfdused;
struct pseudowin *pwin = win->w_pwin;
#endif
-#if (defined(sun) || defined(_IBMR2)) && defined(O_NOCTTY)
- int slave;
-#endif
+ int slave = -1;
-#if defined(sun) && defined(O_NOCTTY)
- /* sun's utmp_update program opens the salve side, thus corrupting
- * pty semantics */
- debug("pre-opening slave...\n");
- if ((slave = open(ttyn, O_RDWR|O_NOCTTY)) == -1)
+#ifdef O_NOCTTY
+ if (pty_preopen)
{
- Msg(errno, "ttyn");
- return -1;
+ debug("pre-opening slave...\n");
+ if ((slave = open(ttyn, O_RDWR|O_NOCTTY)) == -1)
+ {
+ Msg(errno, "ttyn");
+ return -1;
+ }
}
#endif
-#if defined(_IBMR2) && defined(O_NOCTTY)
- slave = aixhack;
- aixhack = -1;
-#endif
debug("forking...\n");
proc = *args;
if (proc == 0)
@@ -1189,20 +1195,21 @@ char **args, *ttyn;
if (dfp && dfp != stderr)
fclose(dfp);
#endif
-#if (defined(sun) || defined(_IBMR2)) && defined(O_NOCTTY)
- close(0);
- dup(slave);
- close(slave);
- closeallfiles(win->w_ptyfd);
- slave = dup(0);
-#else
- closeallfiles(win->w_ptyfd);
-#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;
@@ -1216,12 +1223,13 @@ char **args, *ttyn;
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++)
{
@@ -1251,8 +1259,8 @@ char **args, *ttyn;
}
if (wfdused)
{
- /*
- * the pseudo window process should not be surprised with a
+ /*
+ * 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);
@@ -1274,9 +1282,8 @@ char **args, *ttyn;
dup(0);
#endif /* PSEUDOS */
close(win->w_ptyfd);
-#if (defined(sun) || defined(_IBMR2)) && defined(O_NOCTTY)
- close(slave);
-#endif
+ if (slave != -1)
+ close(slave);
if (newfd >= 0)
{
struct mode fakemode, *modep;
@@ -1375,13 +1382,12 @@ char **args, *ttyn;
default:
break;
}
-#if (defined(sun) || defined(_IBMR2)) && defined(O_NOCTTY)
- close(slave);
-#endif
+ if (slave != -1)
+ close(slave);
return pid;
}
-static void
+void
execvpe(prog, args, env)
char *prog, **args, **env;
{
@@ -1397,7 +1403,7 @@ char *prog, **args, **env;
do
{
for (p = buf; *path && *path != ':'; path++)
- if (p - buf < sizeof(buf) - 2)
+ if (p - buf < (int)sizeof(buf) - 2)
*p++ = *path;
if (p > buf)
*p++ = '/';
@@ -1441,7 +1447,7 @@ char **av;
extern struct win *windows;
struct pseudowin *pwin;
int type;
-
+
if ((w = display ? fore : windows) == NULL)
return -1;
if (!*av || w->w_pwin)
@@ -1474,7 +1480,7 @@ char **av;
l = F_UWP;
p++;
}
- if (*p)
+ if (*p)
av[0] = p;
else
av++;
@@ -1497,7 +1503,7 @@ char **av;
break;
}
}
-
+
if (l & F_UWP)
{
*t++ = '|';
@@ -1512,7 +1518,7 @@ char **av;
*t++ = ' ';
pwin->p_fdpat = l;
debug1("winexec: '%#x'\n", pwin->p_fdpat);
-
+
l = MAXSTR - 4;
for (pp = av; *pp; pp++)
{
@@ -1525,7 +1531,7 @@ char **av;
}
*--t = '\0';
debug1("%s\n", pwin->p_cmd);
-
+
if ((pwin->p_ptyfd = OpenDevice(av, 0, &type, &t)) < 0)
{
free((char *)pwin);
@@ -1539,19 +1545,30 @@ char **av;
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 ioctl");
+ 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;
@@ -1559,10 +1576,11 @@ char **av;
pwin->p_readev.handler = pseu_readev_fn;
pwin->p_writeev.handler = pseu_writeev_fn;
pwin->p_writeev.condpos = &pwin->p_inlen;
- evenq(&pwin->p_readev);
+ if (pwin->p_fdpat & (F_PFRONT << F_PSHIFT * 2 | F_PFRONT << F_PSHIFT))
+ evenq(&pwin->p_readev);
evenq(&pwin->p_writeev);
- pwin->p_pid = ForkWindow(w, av, t);
- if ((r = pwin->p_pid) < 0)
+ r = pwin->p_pid = ForkWindow(w, av, t);
+ if (r < 0)
FreePseudowin(w);
return r;
}
@@ -1576,6 +1594,14 @@ struct win *w;
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);
@@ -1585,6 +1611,7 @@ struct win *w;
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;
}
@@ -1593,15 +1620,15 @@ struct win *w;
#ifdef MULTIUSER
-/*
- * returns 0, if the lock really has been released
+/*
+ * 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",
+ 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 */
@@ -1623,8 +1650,8 @@ struct win *w;
return 1;
}
-/*
- * returns 0, if the lock really could be obtained
+/*
+ * returns 0, if the lock really could be obtained
*/
int
ObtainAutoWritelock(d, w)
@@ -1693,11 +1720,27 @@ struct event *ev;
ev->condneg = &D_status;
return 1;
}
- if (D_obufp - D_obuf > D_obufmax)
+ 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;
}
}
@@ -1715,7 +1758,7 @@ char *data;
#ifdef PSEUDOS
int wtop;
#endif
-
+
bp = buf;
size = IOSIZE;
@@ -1735,12 +1778,15 @@ char *data;
#endif
if (p->w_layer.l_cvlist && muchpending(p, ev))
return;
- if (p->w_blocked)
- {
- ev->condpos = &const_one;
- ev->condneg = &p->w_blocked;
- 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;
@@ -1792,9 +1838,14 @@ char *data;
#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;
}
@@ -1926,7 +1977,7 @@ char *data;
{
struct win *p = (struct win *)data;
struct canvas *cv;
- debug1("FOUND silence win %d\n", p->w_number);
+ 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)
@@ -1941,3 +1992,188 @@ char *data;
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