~ubuntu-branches/ubuntu/dapper/screen/dapper-updates

« back to all changes in this revision

Viewing changes to window.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathaniel McCallum
  • Date: 2004-09-03 15:15:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040903151533-px02yqlrchs4fv2t
Tags: upstream-4.0.2
ImportĀ upstreamĀ versionĀ 4.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1993-2002
 
2
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
 
3
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
 
4
 * Copyright (c) 1987 Oliver Laumann
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program (see the file COPYING); if not, write to the
 
18
 * Free Software Foundation, Inc.,
 
19
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 
20
 *
 
21
 ****************************************************************
 
22
 */
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <signal.h>
 
27
#include <fcntl.h>
 
28
#ifndef sun
 
29
# include <sys/ioctl.h>
 
30
#endif
 
31
 
 
32
#include "config.h"
 
33
 
 
34
#include "screen.h"
 
35
#include "extern.h"
 
36
#include "logfile.h"    /* logfopen() */
 
37
 
 
38
extern struct display *displays, *display;
 
39
extern struct win *windows, *fore, *wtab[], *console_window;
 
40
extern char *ShellArgs[];
 
41
extern char *ShellProg;
 
42
extern char screenterm[];
 
43
extern char *screenlogfile;
 
44
extern char HostName[];
 
45
extern int TtyMode;
 
46
extern int SilenceWait;
 
47
extern int real_uid, real_gid, eff_uid, eff_gid;
 
48
extern char Termcap[];
 
49
extern char **NewEnv;
 
50
extern int visual_bell, maxwin;
 
51
extern struct event logflushev;
 
52
extern int log_flush, logtstamp_after;
 
53
extern int ZombieKey_destroy, ZombieKey_resurrect;
 
54
extern struct layer *flayer;
 
55
extern int maxusercount;
 
56
extern int pty_preopen;
 
57
#ifdef ZMODEM
 
58
extern int zmodem_mode;
 
59
extern struct mchar mchar_blank;
 
60
extern char *zmodem_sendcmd;
 
61
extern char *zmodem_recvcmd;
 
62
#endif
 
63
 
 
64
#if defined(TIOCSWINSZ) || defined(TIOCGWINSZ)
 
65
extern struct winsize glwz;
 
66
#endif
 
67
 
 
68
#ifdef O_NOCTTY
 
69
extern int separate_sids;
 
70
#endif
 
71
 
 
72
static void WinProcess __P((char **, int *));
 
73
static void WinRedisplayLine __P((int, int, int, int));
 
74
static void WinClearLine __P((int, int, int, int));
 
75
static int  WinRewrite __P((int, int, int, struct mchar *, int));
 
76
static int  WinResize __P((int, int));
 
77
static void WinRestore __P((void));
 
78
static int  DoAutolf __P((char *, int *, int));
 
79
static void ZombieProcess __P((char **, int *));
 
80
static void win_readev_fn __P((struct event *, char *));
 
81
static void win_writeev_fn __P((struct event *, char *));
 
82
static int  muchpending __P((struct win *, struct event *));
 
83
#ifdef COPY_PASTE
 
84
static void paste_slowev_fn __P((struct event *, char *));
 
85
#endif
 
86
#ifdef PSEUDOS
 
87
static void pseu_readev_fn __P((struct event *, char *));
 
88
static void pseu_writeev_fn __P((struct event *, char *));
 
89
#endif
 
90
static void win_silenceev_fn __P((struct event *, char *));
 
91
 
 
92
static int  OpenDevice __P((char **, int, int *, char **));
 
93
static int  ForkWindow __P((struct win *, char **, char *));
 
94
#ifdef ZMODEM
 
95
static void zmodem_found __P((struct win *, int, char *, int));
 
96
static void zmodem_fin __P((char *, int, char *));
 
97
static int  zmodem_parse __P((struct win *, char *, int));
 
98
#endif
 
99
 
 
100
 
 
101
 
 
102
int VerboseCreate = 0;          /* XXX move this to user.h */
 
103
 
 
104
char DefaultShell[] = "/bin/sh";
 
105
static char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin";
 
106
 
 
107
/* keep this in sync with the structure definition in window.h */
 
108
struct NewWindow nwin_undef   = 
 
109
{
 
110
  -1,           /* StartAt */
 
111
  (char *)0,    /* aka */
 
112
  (char **)0,   /* args */
 
113
  (char *)0,    /* dir */
 
114
  (char *)0,    /* term */
 
115
  -1,           /* aflag */
 
116
  -1,           /* flowflag */
 
117
  -1,           /* lflag */
 
118
  -1,           /* histheight */
 
119
  -1,           /* monitor */
 
120
  -1,           /* wlock */
 
121
  -1,           /* silence */
 
122
  -1,           /* wrap */
 
123
  -1,           /* logging */
 
124
  -1,           /* slowpaste */
 
125
  -1,           /* gr */
 
126
  -1,           /* c1 */
 
127
  -1,           /* bce */
 
128
  -1,           /* encoding */
 
129
  (char *)0,    /* hstatus */
 
130
  (char *)0     /* charset */
 
131
};
 
132
 
 
133
struct NewWindow nwin_default = 
 
134
 
135
  0,            /* StartAt */
 
136
  0,            /* aka */
 
137
  ShellArgs,    /* args */
 
138
  0,            /* dir */
 
139
  screenterm,   /* term */
 
140
  0,            /* aflag */
 
141
  1*FLOW_NOW,   /* flowflag */
 
142
  LOGINDEFAULT, /* lflag */
 
143
  DEFAULTHISTHEIGHT,    /* histheight */
 
144
  MON_OFF,      /* monitor */
 
145
  WLOCK_OFF,    /* wlock */
 
146
  0,            /* silence */
 
147
  1,            /* wrap */
 
148
  0,            /* logging */
 
149
  0,            /* slowpaste */
 
150
  0,            /* gr */
 
151
  1,            /* c1 */
 
152
  0,            /* bce */
 
153
  0,            /* encoding */
 
154
  (char *)0,    /* hstatus */
 
155
  (char *)0     /* charset */
 
156
};
 
157
 
 
158
struct NewWindow nwin_options;
 
159
 
 
160
static int const_IOSIZE = IOSIZE;
 
161
static int const_one = 1;
 
162
 
 
163
void
 
164
nwin_compose(def, new, res)
 
165
struct NewWindow *def, *new, *res;
 
166
{
 
167
#define COMPOSE(x) res->x = new->x != nwin_undef.x ? new->x : def->x
 
168
  COMPOSE(StartAt);
 
169
  COMPOSE(aka);
 
170
  COMPOSE(args);
 
171
  COMPOSE(dir);
 
172
  COMPOSE(term);
 
173
  COMPOSE(aflag);
 
174
  COMPOSE(flowflag);
 
175
  COMPOSE(lflag);
 
176
  COMPOSE(histheight);
 
177
  COMPOSE(monitor);
 
178
  COMPOSE(wlock);
 
179
  COMPOSE(silence);
 
180
  COMPOSE(wrap);
 
181
  COMPOSE(Lflag);
 
182
  COMPOSE(slow);
 
183
  COMPOSE(gr);
 
184
  COMPOSE(c1);
 
185
  COMPOSE(bce);
 
186
  COMPOSE(encoding);
 
187
  COMPOSE(hstatus);
 
188
  COMPOSE(charset);
 
189
#undef COMPOSE
 
190
}
 
191
 
 
192
/*****************************************************************
 
193
 *
 
194
 *  The window layer functions
 
195
 */
 
196
 
 
197
struct LayFuncs WinLf =
 
198
{
 
199
  WinProcess,
 
200
  0,
 
201
  WinRedisplayLine,
 
202
  WinClearLine,
 
203
  WinRewrite,
 
204
  WinResize,
 
205
  WinRestore
 
206
};
 
207
 
 
208
static int
 
209
DoAutolf(buf, lenp, fr)
 
210
char *buf;
 
211
int *lenp;
 
212
int fr;
 
213
{
 
214
  char *p;
 
215
  int len = *lenp;
 
216
  int trunc = 0;
 
217
 
 
218
  for (p = buf; len > 0; p++, len--)
 
219
    {
 
220
      if (*p != '\r')
 
221
        continue;
 
222
      if (fr-- <= 0)
 
223
        {
 
224
          trunc++;
 
225
          len--;
 
226
        }
 
227
      if (len == 0)
 
228
        break;
 
229
      bcopy(p, p + 1, len++);
 
230
      p[1] = '\n';
 
231
    }
 
232
  *lenp = p - buf;
 
233
  return trunc;
 
234
}
 
235
 
 
236
static void
 
237
WinProcess(bufpp, lenp)
 
238
char **bufpp;
 
239
int *lenp;
 
240
{
 
241
  int l2 = 0, f, *ilen, l = *lenp, trunc;
 
242
  char *ibuf;
 
243
 
 
244
  debug1("WinProcess: %d bytes\n", *lenp);
 
245
  fore = (struct win *)flayer->l_data;
 
246
 
 
247
  if (fore->w_ptyfd < 0)        /* zombie? */
 
248
    {
 
249
      ZombieProcess(bufpp, lenp);
 
250
      return;
 
251
    }
 
252
#ifdef MULTIUSER
 
253
 /* a pending writelock is this:
 
254
  * fore->w_wlock == WLOCK_AUTO, fore->w_wlockuse = NULL
 
255
  * The user who wants to use this window next, will get the lock, if he can.
 
256
  */
 
257
 if (display && fore->w_wlock == WLOCK_AUTO &&
 
258
     !fore->w_wlockuser && !AclCheckPermWin(D_user, ACL_WRITE, fore))
 
259
   {
 
260
     fore->w_wlockuser = D_user;
 
261
     debug2("window %d: pending writelock grabbed by user %s\n",
 
262
            fore->w_number, fore->w_wlockuser->u_name);
 
263
   }
 
264
 /* if w_wlock is set, only one user may write, else we check acls */
 
265
  if (display && ((fore->w_wlock == WLOCK_OFF) ? 
 
266
      AclCheckPermWin(D_user, ACL_WRITE, fore) :
 
267
      (D_user != fore->w_wlockuser)))
 
268
    {
 
269
      debug2("window %d, user %s: ", fore->w_number, D_user->u_name);
 
270
      debug2("writelock %d (wlockuser %s)\n", fore->w_wlock,
 
271
             fore->w_wlockuser ? fore->w_wlockuser->u_name : "NULL");
 
272
      /* XXX FIXME only display !*/
 
273
      WBell(fore, visual_bell);
 
274
      *bufpp += *lenp;
 
275
      *lenp = 0;
 
276
      return;
 
277
    }
 
278
#endif /* MULTIUSER */
 
279
 
 
280
#ifdef BUILTIN_TELNET
 
281
  if (fore->w_type == W_TYPE_TELNET && TelIsline(fore) && *bufpp != fore->w_telbuf)
 
282
    {
 
283
      TelProcessLine(bufpp, lenp);
 
284
      return;
 
285
    }
 
286
#endif
 
287
 
 
288
#ifdef PSEUDOS
 
289
  if (W_UWP(fore))
 
290
    {
 
291
      /* we send the user input to our pseudowin */
 
292
      ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen;
 
293
      f = sizeof(fore->w_pwin->p_inbuf) - *ilen;
 
294
    }
 
295
  else
 
296
#endif /* PSEUDOS */
 
297
    {
 
298
      /* we send the user input to the window */
 
299
      ibuf = fore->w_inbuf; ilen = &fore->w_inlen;
 
300
      f = sizeof(fore->w_inbuf) - *ilen;
 
301
    }
 
302
 
 
303
  if (l > f)
 
304
    l = f;
 
305
#ifdef BUILTIN_TELNET
 
306
  while (l > 0)
 
307
#else
 
308
  if (l > 0)
 
309
#endif
 
310
    {
 
311
      l2 = l;
 
312
      bcopy(*bufpp, ibuf + *ilen, l2);
 
313
      if (fore->w_autolf && (trunc = DoAutolf(ibuf + *ilen, &l2, f - l2)))
 
314
        l -= trunc;
 
315
#ifdef BUILTIN_TELNET
 
316
      if (fore->w_type == W_TYPE_TELNET && (trunc = DoTelnet(ibuf + *ilen, &l2, f - l2)))
 
317
        {
 
318
          l -= trunc;
 
319
          if (fore->w_autolf)
 
320
            continue;           /* need exact value */
 
321
        }
 
322
#endif
 
323
      *ilen += l2;
 
324
      *bufpp += l;
 
325
      *lenp -= l;
 
326
      return;
 
327
    }
 
328
}
 
329
 
 
330
static void
 
331
ZombieProcess(bufpp, lenp)
 
332
char **bufpp;
 
333
int *lenp;
 
334
{
 
335
  int l = *lenp;
 
336
  char *buf = *bufpp, b1[10], b2[10];
 
337
 
 
338
  debug1("ZombieProcess: %d bytes\n", *lenp);
 
339
  fore = (struct win *)flayer->l_data;
 
340
 
 
341
  ASSERT(fore->w_ptyfd < 0);
 
342
  *bufpp += *lenp;
 
343
  *lenp = 0;
 
344
  for (; l-- > 0; buf++)
 
345
    {
 
346
      if (*(unsigned char *)buf == ZombieKey_destroy)
 
347
        {
 
348
          debug1("Turning undead: %d\n", fore->w_number);
 
349
          KillWindow(fore);
 
350
          return;
 
351
        }
 
352
      if (*(unsigned char *)buf == ZombieKey_resurrect)
 
353
        {
 
354
          debug1("Resurrecting Zombie: %d\n", fore->w_number);
 
355
          WriteString(fore, "\r\n", 2);
 
356
          RemakeWindow(fore);
 
357
          return;
 
358
        }
 
359
    }
 
360
  b1[AddXChar(b1, ZombieKey_destroy)] = '\0';
 
361
  b2[AddXChar(b2, ZombieKey_resurrect)] = '\0';
 
362
  Msg(0, "Press %s to destroy or %s to resurrect window", b1, b2);
 
363
}
 
364
 
 
365
static void
 
366
WinRedisplayLine(y, from, to, isblank)
 
367
int y, from, to, isblank;
 
368
{
 
369
  debug3("WinRedisplayLine %d %d %d\n", y, from, to);
 
370
  if (y < 0)
 
371
    return;
 
372
  fore = (struct win *)flayer->l_data;
 
373
  if (from == 0 && y > 0 && fore->w_mlines[y - 1].image[fore->w_width] == 0)
 
374
    LCDisplayLineWrap(&fore->w_layer, &fore->w_mlines[y], y, from, to, isblank);
 
375
  else
 
376
    LCDisplayLine(&fore->w_layer, &fore->w_mlines[y], y, from, to, isblank);
 
377
}
 
378
 
 
379
static int
 
380
WinRewrite(y, x1, x2, rend, doit)
 
381
int y, x1, x2, doit;
 
382
struct mchar *rend;
 
383
{
 
384
  register int cost, dx;
 
385
  register unsigned char *p, *i;
 
386
#ifdef FONT
 
387
  register unsigned char *f;
 
388
#endif
 
389
#ifdef COLOR
 
390
  register unsigned char *c;
 
391
# ifdef COLORS256
 
392
  register unsigned char *cx;
 
393
# endif
 
394
#endif
 
395
 
 
396
  debug3("WinRewrite %d, %d-%d\n", y, x1, x2);
 
397
  fore = (struct win *)flayer->l_data;
 
398
  dx = x2 - x1 + 1;
 
399
  if (doit)
 
400
    {
 
401
      i = fore->w_mlines[y].image + x1;
 
402
      while (dx-- > 0)
 
403
        PUTCHAR(*i++);
 
404
      return 0;
 
405
    }
 
406
  p = fore->w_mlines[y].attr + x1;
 
407
#ifdef FONT
 
408
  f = fore->w_mlines[y].font + x1;
 
409
# ifdef DW_CHARS
 
410
  if (is_dw_font(rend->font))
 
411
    return EXPENSIVE;
 
412
# endif
 
413
# ifdef UTF8
 
414
  if (fore->w_encoding && fore->w_encoding != UTF8 && D_encoding == UTF8 && ContainsSpecialDeffont(fore->w_mlines + y, x1, x2, fore->w_encoding))
 
415
    return EXPENSIVE;
 
416
# endif
 
417
#endif
 
418
#ifdef COLOR
 
419
  c = fore->w_mlines[y].color + x1;
 
420
# ifdef COLORS256
 
421
  cx = fore->w_mlines[y].colorx + x1;
 
422
# endif
 
423
#endif
 
424
 
 
425
  cost = dx = x2 - x1 + 1;
 
426
  while(dx-- > 0)
 
427
    {
 
428
      if (*p++ != rend->attr)
 
429
        return EXPENSIVE;
 
430
#ifdef FONT
 
431
      if (*f++ != rend->font)
 
432
        return EXPENSIVE;
 
433
#endif
 
434
#ifdef COLOR
 
435
      if (*c++ != rend->color)
 
436
        return EXPENSIVE;
 
437
# ifdef COLORS256
 
438
      if (*cx++ != rend->colorx)
 
439
        return EXPENSIVE;
 
440
# endif
 
441
#endif
 
442
    }
 
443
  return cost;
 
444
}
 
445
 
 
446
static void
 
447
WinClearLine(y, xs, xe, bce)
 
448
int y, xs, xe, bce;
 
449
{
 
450
  fore = (struct win *)flayer->l_data;
 
451
  debug3("WinClearLine %d %d-%d\n", y, xs, xe);
 
452
  LClearLine(flayer, y, xs, xe, bce, &fore->w_mlines[y]);
 
453
}
 
454
 
 
455
static int
 
456
WinResize(wi, he)
 
457
int wi, he;
 
458
{
 
459
  fore = (struct win *)flayer->l_data;
 
460
  ChangeWindowSize(fore, wi, he, fore->w_histheight);
 
461
  return 0;
 
462
}
 
463
 
 
464
static void
 
465
WinRestore()
 
466
{
 
467
  struct canvas *cv;
 
468
  fore = (struct win *)flayer->l_data;
 
469
  debug1("WinRestore: win %x\n", fore);
 
470
  for (cv = flayer->l_cvlist; cv; cv = cv->c_next)
 
471
    {
 
472
      display = cv->c_display;
 
473
      if (cv != D_forecv)
 
474
        continue;
 
475
      /* ChangeScrollRegion(fore->w_top, fore->w_bot); */
 
476
      KeypadMode(fore->w_keypad);
 
477
      CursorkeysMode(fore->w_cursorkeys);
 
478
      SetFlow(fore->w_flow & FLOW_NOW);
 
479
      InsertMode(fore->w_insert);
 
480
      ReverseVideo(fore->w_revvid);
 
481
      CursorVisibility(fore->w_curinv ? -1 : fore->w_curvvis);
 
482
      MouseMode(fore->w_mouse);
 
483
    }
 
484
}
 
485
 
 
486
/*****************************************************************/
 
487
 
 
488
 
 
489
/*
 
490
 * DoStartLog constructs a path for the "want to be logfile" in buf and
 
491
 * attempts logfopen.
 
492
 *
 
493
 * returns 0 on success.
 
494
 */
 
495
int
 
496
DoStartLog(w, buf, bufsize)
 
497
struct win *w;
 
498
char *buf;
 
499
int bufsize;
 
500
{
 
501
  int n;
 
502
  if (!w || !buf)
 
503
    return -1;
 
504
 
 
505
  strncpy(buf, MakeWinMsg(screenlogfile, w, '%'), bufsize - 1);
 
506
  buf[bufsize - 1] = 0;
 
507
 
 
508
  debug2("DoStartLog: win %d, file %s\n", w->w_number, buf);
 
509
 
 
510
  if (w->w_log != NULL)
 
511
    logfclose(w->w_log);
 
512
 
 
513
  if ((w->w_log = logfopen(buf, islogfile(buf) ? NULL : secfopen(buf, "a"))) == NULL)
 
514
    return -2;
 
515
  if (!logflushev.queued)
 
516
    {
 
517
      n = log_flush ? log_flush : (logtstamp_after + 4) / 5;
 
518
      if (n)
 
519
        {
 
520
          SetTimeout(&logflushev, n * 1000);
 
521
          evenq(&logflushev);
 
522
        }
 
523
    }
 
524
  return 0;
 
525
}
 
526
 
 
527
/*
 
528
 * Umask & wlock are set for the user of the display,
 
529
 * The display d (if specified) switches to that window.
 
530
 */
 
531
int
 
532
MakeWindow(newwin)
 
533
struct NewWindow *newwin;
 
534
{
 
535
  register struct win **pp, *p;
 
536
  register int n, i;
 
537
  int f = -1;
 
538
  struct NewWindow nwin;
 
539
  int type, startat;
 
540
  char *TtyName;
 
541
#ifdef MULTIUSER
 
542
  extern struct acluser *users;
 
543
#endif
 
544
 
 
545
  debug1("NewWindow: StartAt %d\n", newwin->StartAt);
 
546
  debug1("NewWindow: aka     %s\n", newwin->aka?newwin->aka:"NULL");
 
547
  debug1("NewWindow: dir     %s\n", newwin->dir?newwin->dir:"NULL");
 
548
  debug1("NewWindow: term    %s\n", newwin->term?newwin->term:"NULL");
 
549
 
 
550
  nwin_compose(&nwin_default, newwin, &nwin);
 
551
  debug1("NWin: aka     %s\n", nwin.aka ? nwin.aka : "NULL");
 
552
  debug1("NWin: wlock   %d\n", nwin.wlock);
 
553
  debug1("NWin: Lflag   %d\n", nwin.Lflag);
 
554
 
 
555
  startat = nwin.StartAt < maxwin ? nwin.StartAt : 0;
 
556
  pp = wtab + startat;
 
557
 
 
558
  do
 
559
    {
 
560
      if (*pp == 0)
 
561
        break;
 
562
      if (++pp == wtab + maxwin)
 
563
        pp = wtab;
 
564
    }
 
565
  while (pp != wtab + startat);
 
566
  if (*pp)
 
567
    {
 
568
      Msg(0, "No more windows.");
 
569
      return -1;
 
570
    }
 
571
 
 
572
#if defined(USRLIMIT) && defined(UTMPOK)
 
573
  /*
 
574
   * Count current number of users, if logging windows in.
 
575
   */
 
576
  if (nwin.lflag && CountUsers() >= USRLIMIT)
 
577
    {
 
578
      Msg(0, "User limit reached.  Window will not be logged in.");
 
579
      nwin.lflag = 0;
 
580
    }
 
581
#endif
 
582
  n = pp - wtab;
 
583
  debug1("Makewin creating %d\n", n);
 
584
 
 
585
  if ((f = OpenDevice(nwin.args, nwin.lflag, &type, &TtyName)) < 0)
 
586
    return -1;
 
587
 
 
588
  if ((p = (struct win *)malloc(sizeof(struct win))) == 0)
 
589
    {
 
590
      close(f);
 
591
      Msg(0, strnomem);
 
592
      return -1;
 
593
    }
 
594
  bzero((char *)p, (int)sizeof(struct win));
 
595
 
 
596
#ifdef UTMPOK
 
597
  if (type != W_TYPE_PTY)
 
598
    nwin.lflag = 0;
 
599
#endif
 
600
 
 
601
  p->w_type = type;
 
602
 
 
603
  /* save the command line so that zombies can be resurrected */
 
604
  for (i = 0; nwin.args[i] && i < MAXARGS - 1; i++)
 
605
    p->w_cmdargs[i] = SaveStr(nwin.args[i]);
 
606
  p->w_cmdargs[i] = 0;
 
607
  if (nwin.dir)
 
608
    p->w_dir = SaveStr(nwin.dir);
 
609
  if (nwin.term)
 
610
    p->w_term = SaveStr(nwin.term);
 
611
 
 
612
  p->w_number = n;
 
613
#ifdef MULTIUSER
 
614
  /*
 
615
   * This is dangerous: without a display we use creators umask
 
616
   * This is intended to be usefull for detached startup.
 
617
   * But is still better than default bits with a NULL user.
 
618
   */
 
619
  if (NewWindowAcl(p, display ? D_user : users))
 
620
    {
 
621
      free((char *)p);
 
622
      close(f);
 
623
      Msg(0, strnomem);
 
624
      return -1;
 
625
    }
 
626
#endif
 
627
  p->w_layer.l_next = 0;
 
628
  p->w_layer.l_bottom = &p->w_layer;
 
629
  p->w_layer.l_layfn = &WinLf;
 
630
  p->w_layer.l_data = (char *)p;
 
631
  p->w_savelayer = &p->w_layer;
 
632
  p->w_pdisplay = 0;
 
633
  p->w_lastdisp = 0;
 
634
 
 
635
#ifdef MULTIUSER
 
636
  if (display && !AclCheckPermWin(D_user, ACL_WRITE, p))
 
637
    p->w_wlockuser = D_user;
 
638
  p->w_wlock = nwin.wlock;
 
639
#endif
 
640
  p->w_ptyfd = f;
 
641
  p->w_aflag = nwin.aflag;
 
642
  p->w_flow = nwin.flowflag | ((nwin.flowflag & FLOW_AUTOFLAG) ? (FLOW_AUTO|FLOW_NOW) : FLOW_AUTO);
 
643
  if (!nwin.aka)
 
644
    nwin.aka = Filename(nwin.args[0]);
 
645
  strncpy(p->w_akabuf, nwin.aka, sizeof(p->w_akabuf) - 1);
 
646
  if ((nwin.aka = rindex(p->w_akabuf, '|')) != NULL)
 
647
    {
 
648
      p->w_autoaka = 0;
 
649
      *nwin.aka++ = 0;
 
650
      p->w_title = nwin.aka;
 
651
      p->w_akachange = nwin.aka + strlen(nwin.aka);
 
652
    }
 
653
  else
 
654
    p->w_title = p->w_akachange = p->w_akabuf;
 
655
  if (nwin.hstatus)
 
656
    p->w_hstatus = SaveStr(nwin.hstatus);
 
657
  p->w_monitor = nwin.monitor;
 
658
#ifdef MULTIUSER
 
659
  if (p->w_monitor == MON_ON)
 
660
    {
 
661
      /* always tell all users */
 
662
      for (i = 0; i < maxusercount; i++)
 
663
        ACLBYTE(p->w_mon_notify, i) |= ACLBIT(i);
 
664
    }
 
665
#endif
 
666
  /*
 
667
   * defsilence by Lloyd Zusman (zusman_lloyd@jpmorgan.com)
 
668
   */
 
669
  p->w_silence = nwin.silence;
 
670
  p->w_silencewait = SilenceWait;
 
671
#ifdef MULTIUSER
 
672
  if (p->w_silence == SILENCE_ON)
 
673
    {
 
674
      /* always tell all users */
 
675
      for (i = 0; i < maxusercount; i++)
 
676
        ACLBYTE(p->w_lio_notify, i) |= ACLBIT(i);
 
677
    }
 
678
#endif
 
679
#ifdef COPY_PASTE
 
680
  p->w_slowpaste = nwin.slow;
 
681
#else
 
682
  nwin.histheight = 0;
 
683
#endif
 
684
 
 
685
  p->w_norefresh = 0;
 
686
  strncpy(p->w_tty, TtyName, MAXSTR - 1);
 
687
 
 
688
#if 0
 
689
  /* XXX Fixme display resize */
 
690
  if (ChangeWindowSize(p, display ? D_defwidth : 80,
 
691
                       display ? D_defheight : 24, 
 
692
                       nwin.histheight))
 
693
    {
 
694
      FreeWindow(p);
 
695
      return -1;
 
696
    }
 
697
#else
 
698
  if (ChangeWindowSize(p, display ? D_forecv->c_xe - D_forecv->c_xs + 1: 80,
 
699
                       display ? D_forecv->c_ye - D_forecv->c_ys + 1 : 24, 
 
700
                       nwin.histheight))
 
701
    {
 
702
      FreeWindow(p);
 
703
      return -1;
 
704
    }
 
705
#endif
 
706
 
 
707
  p->w_encoding = nwin.encoding;
 
708
  ResetWindow(p);       /* sets w_wrap, w_c1, w_gr, w_bce */
 
709
 
 
710
#ifdef FONT
 
711
  if (nwin.charset)
 
712
    SetCharsets(p, nwin.charset);
 
713
#endif
 
714
 
 
715
  if (VerboseCreate)
 
716
    {
 
717
      struct display *d = display; /* WriteString zaps display */
 
718
 
 
719
      WriteString(p, ":screen (", 9);
 
720
      WriteString(p, p->w_title, strlen(p->w_title));
 
721
      WriteString(p, "):", 2);
 
722
      for (f = 0; p->w_cmdargs[f]; f++)
 
723
        {
 
724
          WriteString(p, " ", 1);
 
725
          WriteString(p, p->w_cmdargs[f], strlen(p->w_cmdargs[f]));
 
726
        }
 
727
      WriteString(p, "\r\n", 2);
 
728
      display = d;
 
729
    }
 
730
 
 
731
  p->w_pid = 0;
 
732
#ifdef PSEUDOS
 
733
  p->w_pwin = 0;
 
734
#endif
 
735
 
 
736
#ifdef BUILTIN_TELNET
 
737
  if (type == W_TYPE_TELNET)
 
738
    {
 
739
      if (TelConnect(p))
 
740
        {
 
741
          FreeWindow(p);
 
742
          return -1;
 
743
        }
 
744
    }
 
745
  else
 
746
#endif
 
747
  if (type == W_TYPE_PTY)
 
748
    {
 
749
      p->w_pid = ForkWindow(p, nwin.args, TtyName);
 
750
      if (p->w_pid < 0)
 
751
        {
 
752
          FreeWindow(p);
 
753
          return -1;
 
754
        }
 
755
    }
 
756
 
 
757
  /*
 
758
   * Place the new window at the head of the most-recently-used list.
 
759
   */
 
760
  if (display && D_fore)
 
761
    D_other = D_fore;
 
762
  *pp = p;
 
763
  p->w_next = windows;
 
764
  windows = p;
 
765
  p->w_lflag = nwin.lflag;
 
766
#ifdef UTMPOK
 
767
  p->w_slot = (slot_t)-1;
 
768
# ifdef LOGOUTOK
 
769
  debug1("MakeWindow will %slog in.\n", nwin.lflag?"":"not ");
 
770
  if (nwin.lflag & 1)
 
771
# else /* LOGOUTOK */
 
772
  debug1("MakeWindow will log in, LOGOUTOK undefined in config.h%s.\n",
 
773
         nwin.lflag?"":" (although lflag=0)");
 
774
# endif /* LOGOUTOK */
 
775
    {
 
776
      p->w_slot = (slot_t)0;
 
777
      if (display || (p->w_lflag & 2))
 
778
        SetUtmp(p);
 
779
    }
 
780
# ifdef CAREFULUTMP
 
781
  CarefulUtmp();        /* If all 've been zombies, we've had no slot */
 
782
# endif
 
783
#endif /* UTMPOK */
 
784
 
 
785
  if (nwin.Lflag)
 
786
    {
 
787
      char buf[1024];
 
788
      DoStartLog(p, buf, sizeof(buf));
 
789
    }
 
790
 
 
791
  p->w_readev.fd = p->w_writeev.fd = p->w_ptyfd;
 
792
  p->w_readev.type = EV_READ;
 
793
  p->w_writeev.type = EV_WRITE;
 
794
  p->w_readev.data = p->w_writeev.data = (char *)p;
 
795
  p->w_readev.handler = win_readev_fn;
 
796
  p->w_writeev.handler = win_writeev_fn;
 
797
  p->w_writeev.condpos = &p->w_inlen;
 
798
  evenq(&p->w_readev);
 
799
  evenq(&p->w_writeev);
 
800
#ifdef COPY_PASTE
 
801
  p->w_paster.pa_slowev.type = EV_TIMEOUT;
 
802
  p->w_paster.pa_slowev.data = (char *)&p->w_paster;
 
803
  p->w_paster.pa_slowev.handler = paste_slowev_fn;
 
804
#endif
 
805
  p->w_silenceev.type = EV_TIMEOUT;
 
806
  p->w_silenceev.data = (char *)p;
 
807
  p->w_silenceev.handler = win_silenceev_fn;
 
808
  if (p->w_silence > 0)
 
809
    {
 
810
      debug("New window has silence enabled.\n");
 
811
      SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
 
812
      evenq(&p->w_silenceev);
 
813
    }
 
814
 
 
815
  SetForeWindow(p);
 
816
  Activate(p->w_norefresh);
 
817
  WindowChanged((struct win*)0, 'w');
 
818
  WindowChanged((struct win*)0, 'W');
 
819
  WindowChanged((struct win*)0, 0);
 
820
  return n;
 
821
}
 
822
 
 
823
/*
 
824
 * Resurrect a window from Zombie state.
 
825
 * The command vector is therefore stored in the window structure.
 
826
 * Note: The terminaltype defaults to screenterm again, the current
 
827
 * working directory is lost.
 
828
 */
 
829
int
 
830
RemakeWindow(p)
 
831
struct win *p;
 
832
{
 
833
  char *TtyName;
 
834
  int lflag, f;
 
835
 
 
836
  lflag = nwin_default.lflag;
 
837
  if ((f = OpenDevice(p->w_cmdargs, lflag, &p->w_type, &TtyName)) < 0)
 
838
    return -1;
 
839
 
 
840
  strncpy(p->w_tty, *TtyName ? TtyName : p->w_title, MAXSTR - 1);
 
841
  p->w_ptyfd = f;
 
842
  p->w_readev.fd = f;
 
843
  p->w_writeev.fd = f;
 
844
  evenq(&p->w_readev);
 
845
  evenq(&p->w_writeev);
 
846
 
 
847
  if (VerboseCreate)
 
848
    {
 
849
      struct display *d = display; /* WriteString zaps display */
 
850
 
 
851
      WriteString(p, ":screen (", 9);
 
852
      WriteString(p, p->w_title, strlen(p->w_title));
 
853
      WriteString(p, "):", 2);
 
854
      for (f = 0; p->w_cmdargs[f]; f++)
 
855
        {
 
856
          WriteString(p, " ", 1);
 
857
          WriteString(p, p->w_cmdargs[f], strlen(p->w_cmdargs[f]));
 
858
        }
 
859
      WriteString(p, "\r\n", 2);
 
860
      display = d;
 
861
    }
 
862
 
 
863
  p->w_pid = 0;
 
864
#ifdef BUILTIN_TELNET
 
865
  if (p->w_type == W_TYPE_TELNET)
 
866
    {
 
867
      if (TelConnect(p))
 
868
        return -1;
 
869
    }
 
870
  else
 
871
#endif
 
872
  if (p->w_type == W_TYPE_PTY)
 
873
    {
 
874
      p->w_pid = ForkWindow(p, p->w_cmdargs, TtyName);
 
875
      if (p->w_pid < 0)
 
876
        return -1;
 
877
    }
 
878
 
 
879
#ifdef UTMPOK
 
880
  if (p->w_slot == (slot_t)0 && (display || (p->w_lflag & 2)))
 
881
    SetUtmp(p);
 
882
# ifdef CAREFULUTMP
 
883
  CarefulUtmp();        /* If all 've been zombies, we've had no slot */
 
884
# endif
 
885
#endif
 
886
  WindowChanged(p, 'f');
 
887
  return p->w_number;
 
888
}
 
889
 
 
890
void
 
891
CloseDevice(wp)
 
892
struct win *wp;
 
893
{
 
894
  if (wp->w_ptyfd < 0)
 
895
    return;
 
896
  if (wp->w_type == W_TYPE_PTY)
 
897
    {
 
898
      /* pty 4 SALE */
 
899
      (void)chmod(wp->w_tty, 0666);
 
900
      (void)chown(wp->w_tty, 0, 0);
 
901
    }
 
902
  close(wp->w_ptyfd);
 
903
  wp->w_ptyfd = -1;
 
904
  wp->w_tty[0] = 0;
 
905
  evdeq(&wp->w_readev);
 
906
  evdeq(&wp->w_writeev);
 
907
#ifdef BUILTIN_TELNET
 
908
  evdeq(&wp->w_telconnev);
 
909
#endif
 
910
  wp->w_readev.fd = wp->w_writeev.fd = -1;
 
911
}
 
912
 
 
913
void
 
914
FreeWindow(wp)
 
915
struct win *wp;
 
916
{
 
917
  struct display *d;
 
918
  int i;
 
919
  struct canvas *cv, *ncv;
 
920
  struct layer *l;
 
921
 
 
922
  debug1("FreeWindow %d\n", wp ? wp->w_number: -1);
 
923
#ifdef PSEUDOS
 
924
  if (wp->w_pwin)
 
925
    FreePseudowin(wp);
 
926
#endif
 
927
#ifdef UTMPOK
 
928
  RemoveUtmp(wp);
 
929
#endif
 
930
  CloseDevice(wp);
 
931
 
 
932
  if (wp == console_window)
 
933
    {
 
934
      TtyGrabConsole(-1, -1, "free");
 
935
      console_window = 0;
 
936
    }
 
937
  if (wp->w_log != NULL)
 
938
    logfclose(wp->w_log);
 
939
  ChangeWindowSize(wp, 0, 0, 0);
 
940
 
 
941
  if (wp->w_hstatus)
 
942
    free(wp->w_hstatus);
 
943
  for (i = 0; wp->w_cmdargs[i]; i++)
 
944
    free(wp->w_cmdargs[i]);
 
945
  if (wp->w_dir)
 
946
    free(wp->w_dir);
 
947
  if (wp->w_term)
 
948
    free(wp->w_term);
 
949
  for (d = displays; d; d = d->d_next)
 
950
    {
 
951
      if (d->d_other == wp)
 
952
        d->d_other = d->d_fore && d->d_fore->w_next != wp ? d->d_fore->w_next : wp->w_next;
 
953
      if (d->d_fore == wp)
 
954
        d->d_fore = NULL;
 
955
      for (cv = d->d_cvlist; cv; cv = cv->c_next)
 
956
        {
 
957
          for (l = cv->c_layer; l; l = l->l_next)
 
958
            if (l->l_layfn == &WinLf)
 
959
              break;
 
960
          if (!l)
 
961
            continue;
 
962
          if ((struct win *)l->l_data != wp)
 
963
            continue;
 
964
          if (cv->c_layer == wp->w_savelayer)
 
965
            wp->w_savelayer = 0;
 
966
          KillLayerChain(cv->c_layer);
 
967
        }
 
968
    }
 
969
  if (wp->w_savelayer)
 
970
    KillLayerChain(wp->w_savelayer);
 
971
  for (cv = wp->w_layer.l_cvlist; cv; cv = ncv)
 
972
    {
 
973
      ncv = cv->c_lnext;
 
974
      cv->c_layer = &cv->c_blank;
 
975
      cv->c_blank.l_cvlist = cv;
 
976
      cv->c_lnext = 0;
 
977
      cv->c_xoff = cv->c_xs;
 
978
      cv->c_yoff = cv->c_ys;
 
979
      RethinkViewportOffsets(cv);
 
980
    }
 
981
  wp->w_layer.l_cvlist = 0;
 
982
  if (flayer == &wp->w_layer)
 
983
    flayer = 0;
 
984
 
 
985
#ifdef MULTIUSER
 
986
  FreeWindowAcl(wp);
 
987
#endif /* MULTIUSER */
 
988
  evdeq(&wp->w_readev);         /* just in case */
 
989
  evdeq(&wp->w_writeev);        /* just in case */
 
990
  evdeq(&wp->w_silenceev);
 
991
#ifdef COPY_PASTE
 
992
  FreePaster(&wp->w_paster);
 
993
#endif
 
994
  free((char *)wp);
 
995
}
 
996
 
 
997
static int
 
998
OpenDevice(args, lflag, typep, namep)
 
999
char **args;
 
1000
int lflag;
 
1001
int *typep;
 
1002
char **namep;
 
1003
{
 
1004
  char *arg = args[0];
 
1005
  struct stat st;
 
1006
  int f;
 
1007
 
 
1008
  if (!arg)
 
1009
    return -1;
 
1010
#ifdef BUILTIN_TELNET
 
1011
  if (strcmp(arg, "//telnet") == 0)
 
1012
    {
 
1013
      f = TelOpen(args + 1);
 
1014
      lflag = 0;
 
1015
      *typep = W_TYPE_TELNET;
 
1016
      *namep = "telnet";
 
1017
    }
 
1018
  else
 
1019
#endif
 
1020
  if ((stat(arg, &st)) == 0 && S_ISCHR(st.st_mode))
 
1021
    {
 
1022
      if (access(arg, R_OK | W_OK) == -1)
 
1023
        {
 
1024
          Msg(errno, "Cannot access line '%s' for R/W", arg);
 
1025
          return -1;
 
1026
        }
 
1027
      debug("OpenDevice: OpenTTY\n");
 
1028
      if ((f = OpenTTY(arg, args[1])) < 0)
 
1029
        return -1;
 
1030
      lflag = 0;
 
1031
      *typep = W_TYPE_PLAIN;
 
1032
      *namep = arg;
 
1033
    }
 
1034
  else
 
1035
    {
 
1036
      *typep = W_TYPE_PTY;
 
1037
      f = OpenPTY(namep);
 
1038
      if (f == -1)
 
1039
        {
 
1040
          Msg(0, "No more PTYs.");
 
1041
          return -1;
 
1042
        }
 
1043
#ifdef TIOCPKT
 
1044
      {
 
1045
        int flag = 1;
 
1046
        if (ioctl(f, TIOCPKT, (char *)&flag))
 
1047
          {
 
1048
            Msg(errno, "TIOCPKT ioctl");
 
1049
            close(f);
 
1050
            return -1;
 
1051
          }
 
1052
      }
 
1053
#endif /* TIOCPKT */
 
1054
    }
 
1055
  debug1("fcntl(%d, F_SETFL, FNBLOCK)\n", f);
 
1056
  (void) fcntl(f, F_SETFL, FNBLOCK);
 
1057
#ifdef linux
 
1058
  /*
 
1059
   * Tenebreux (zeus@ns.acadiacom.net) has Linux 1.3.70 where select
 
1060
   * gets confused in the following condition:
 
1061
   * Open a pty-master side, request a flush on it, then set packet
 
1062
   * mode and call select(). Select will return a possible read, where
 
1063
   * the one byte response to the flush can be found. Select will
 
1064
   * thereafter return a possible read, which yields I/O error.
 
1065
   *
 
1066
   * If we request another flush *after* switching into packet mode,
 
1067
   * this I/O error does not occur. We receive a single response byte
 
1068
   * although we send two flush requests now.
 
1069
   *
 
1070
   * Maybe we should not flush at all.
 
1071
   *
 
1072
   * 10.5.96 jw.
 
1073
   */
 
1074
  if (*typep == W_TYPE_PTY || *typep == W_TYPE_PLAIN)
 
1075
    tcflush(f, TCIOFLUSH);
 
1076
#endif
 
1077
 
 
1078
  if (*typep != W_TYPE_PTY)
 
1079
    return f;
 
1080
 
 
1081
#ifndef PTYROFS
 
1082
#ifdef PTYGROUP
 
1083
  if (chown(*namep, real_uid, PTYGROUP) && !eff_uid)
 
1084
#else
 
1085
  if (chown(*namep, real_uid, real_gid) && !eff_uid)
 
1086
#endif
 
1087
    {
 
1088
      Msg(errno, "chown tty");
 
1089
      close(f);
 
1090
      return -1;
 
1091
    }
 
1092
#ifdef UTMPOK
 
1093
  if (chmod(*namep, lflag ? TtyMode : (TtyMode & ~022)) && !eff_uid)
 
1094
#else
 
1095
  if (chmod(*namep, TtyMode) && !eff_uid)
 
1096
#endif
 
1097
    {
 
1098
      Msg(errno, "chmod tty");
 
1099
      close(f);
 
1100
      return -1;
 
1101
    }
 
1102
#endif
 
1103
  return f;
 
1104
}
 
1105
 
 
1106
/*
 
1107
 * Fields w_width, w_height, aflag, number (and w_tty)
 
1108
 * are read from struct win *win. No fields written.
 
1109
 * If pwin is nonzero, filedescriptors are distributed
 
1110
 * between win->w_tty and open(ttyn)
 
1111
 *
 
1112
 */
 
1113
static int
 
1114
ForkWindow(win, args, ttyn)
 
1115
struct win *win;
 
1116
char **args, *ttyn;
 
1117
{
 
1118
  int pid;
 
1119
  char tebuf[25];
 
1120
  char ebuf[10];
 
1121
  char shellbuf[7 + MAXPATHLEN];
 
1122
  char *proc;
 
1123
#ifndef TIOCSWINSZ
 
1124
  char libuf[20], cobuf[20];
 
1125
#endif
 
1126
  int newfd;
 
1127
  int w = win->w_width;
 
1128
  int h = win->w_height;
 
1129
#ifdef PSEUDOS
 
1130
  int i, pat, wfdused;
 
1131
  struct pseudowin *pwin = win->w_pwin;
 
1132
#endif
 
1133
  int slave = -1;
 
1134
 
 
1135
#ifdef O_NOCTTY
 
1136
  if (pty_preopen)
 
1137
    {
 
1138
      debug("pre-opening slave...\n");
 
1139
      if ((slave = open(ttyn, O_RDWR|O_NOCTTY)) == -1)
 
1140
        {
 
1141
          Msg(errno, "ttyn");
 
1142
          return -1;
 
1143
        }
 
1144
    }
 
1145
#endif
 
1146
  debug("forking...\n");
 
1147
  proc = *args;
 
1148
  if (proc == 0)
 
1149
    {
 
1150
      args = ShellArgs;
 
1151
      proc = *args;
 
1152
    }
 
1153
  fflush(stdout);
 
1154
  fflush(stderr);
 
1155
  switch (pid = fork())
 
1156
    {
 
1157
    case -1:
 
1158
      Msg(errno, "fork");
 
1159
      break;
 
1160
    case 0:
 
1161
      signal(SIGHUP, SIG_DFL);
 
1162
      signal(SIGINT, SIG_DFL);
 
1163
      signal(SIGQUIT, SIG_DFL);
 
1164
      signal(SIGTERM, SIG_DFL);
 
1165
#ifdef BSDJOBS
 
1166
      signal(SIGTTIN, SIG_DFL);
 
1167
      signal(SIGTTOU, SIG_DFL);
 
1168
#endif
 
1169
#ifdef SIGPIPE
 
1170
      signal(SIGPIPE, SIG_DFL);
 
1171
#endif
 
1172
#ifdef SIGXFSZ
 
1173
      signal(SIGXFSZ, SIG_DFL);
 
1174
#endif
 
1175
 
 
1176
      displays = 0;             /* beware of Panic() */
 
1177
      if (setgid(real_gid) || setuid(real_uid))
 
1178
        Panic(errno, "Setuid/gid");
 
1179
      eff_uid = real_uid;
 
1180
      eff_gid = real_gid;
 
1181
#ifdef PSEUDOS
 
1182
      if (!pwin)        /* ignore directory if pseudo */
 
1183
#endif
 
1184
        if (win->w_dir && *win->w_dir && chdir(win->w_dir))
 
1185
          Panic(errno, "Cannot chdir to %s", win->w_dir);
 
1186
 
 
1187
      if (display)
 
1188
        {
 
1189
          brktty(D_userfd);
 
1190
          freetty();
 
1191
        }
 
1192
      else
 
1193
        brktty(-1);
 
1194
#ifdef DEBUG
 
1195
      if (dfp && dfp != stderr)
 
1196
        fclose(dfp);
 
1197
#endif
 
1198
      if (slave != -1)
 
1199
        {
 
1200
          close(0);
 
1201
          dup(slave);
 
1202
          close(slave);
 
1203
          closeallfiles(win->w_ptyfd);
 
1204
          slave = dup(0);
 
1205
        }
 
1206
      else
 
1207
        closeallfiles(win->w_ptyfd);
 
1208
#ifdef DEBUG
 
1209
      if (dfp)  /* do not produce child debug, when debug is "off" */
 
1210
        {
 
1211
          char buf[256];
 
1212
 
 
1213
          sprintf(buf, "%s/screen.child", DEBUGDIR);
 
1214
          if ((dfp = fopen(buf, "a")) == 0)
 
1215
            dfp = stderr;
 
1216
          else
 
1217
            (void) chmod(buf, 0666);
 
1218
        }
 
1219
      debug1("=== ForkWindow: pid %d\n", (int)getpid());
 
1220
#endif
 
1221
      /* Close the three /dev/null descriptors */
 
1222
      close(0);
 
1223
      close(1);
 
1224
      close(2);
 
1225
      newfd = -1;
 
1226
      /*
 
1227
       * distribute filedescriptors between the ttys
 
1228
       */
 
1229
#ifdef PSEUDOS
 
1230
      pat = pwin ? pwin->p_fdpat : 
 
1231
                   ((F_PFRONT<<(F_PSHIFT*2)) | (F_PFRONT<<F_PSHIFT) | F_PFRONT);
 
1232
      debug1("Using window pattern 0x%x\n", pat);
 
1233
      wfdused = 0;
 
1234
      for(i = 0; i < 3; i++)
 
1235
        {
 
1236
          if (pat & F_PFRONT << F_PSHIFT * i)
 
1237
            {
 
1238
              if (newfd < 0)
 
1239
                {
 
1240
# ifdef O_NOCTTY
 
1241
                  if (separate_sids)
 
1242
                    newfd = open(ttyn, O_RDWR);
 
1243
                  else
 
1244
                    newfd = open(ttyn, O_RDWR|O_NOCTTY);
 
1245
# else
 
1246
                  newfd = open(ttyn, O_RDWR);
 
1247
# endif
 
1248
                  if (newfd < 0)
 
1249
                    Panic(errno, "Cannot open %s", ttyn);
 
1250
                }
 
1251
              else
 
1252
                dup(newfd);
 
1253
            }
 
1254
          else
 
1255
            {
 
1256
              dup(win->w_ptyfd);
 
1257
              wfdused = 1;
 
1258
            }
 
1259
        }
 
1260
      if (wfdused)
 
1261
        {
 
1262
            /*
 
1263
             * the pseudo window process should not be surprised with a
 
1264
             * nonblocking filedescriptor. Poor Backend!
 
1265
             */
 
1266
            debug1("Clearing NBLOCK on window-fd(%d)\n", win->w_ptyfd);
 
1267
            if (fcntl(win->w_ptyfd, F_SETFL, 0))
 
1268
              Msg(errno, "Warning: clear NBLOCK fcntl failed");
 
1269
        }
 
1270
#else /* PSEUDOS */
 
1271
# ifdef O_NOCTTY
 
1272
      if (separate_sids)
 
1273
        newfd = open(ttyn, O_RDWR);
 
1274
      else
 
1275
        newfd = open(ttyn, O_RDWR|O_NOCTTY);
 
1276
# else
 
1277
      newfd = open(ttyn, O_RDWR);
 
1278
# endif
 
1279
      if (newfd != 0)
 
1280
        Panic(errno, "Cannot open %s", ttyn);
 
1281
      dup(0);
 
1282
      dup(0);
 
1283
#endif /* PSEUDOS */
 
1284
      close(win->w_ptyfd);
 
1285
      if (slave != -1)
 
1286
        close(slave);
 
1287
      if (newfd >= 0)
 
1288
        {
 
1289
          struct mode fakemode, *modep;
 
1290
          InitPTY(newfd);
 
1291
          if (fgtty(newfd))
 
1292
            Msg(errno, "fgtty");
 
1293
          if (display)
 
1294
            {
 
1295
              debug("ForkWindow: using display tty mode for new child.\n");
 
1296
              modep = &D_OldMode;
 
1297
            }
 
1298
          else
 
1299
            {
 
1300
              debug("No display - creating tty setting\n");
 
1301
              modep = &fakemode;
 
1302
              InitTTY(modep, 0);
 
1303
#ifdef DEBUG
 
1304
              DebugTTY(modep);
 
1305
#endif
 
1306
            }
 
1307
          /* We only want echo if the users input goes to the pseudo
 
1308
           * and the pseudo's stdout is not send to the window.
 
1309
           */
 
1310
#ifdef PSEUDOS
 
1311
          if (pwin && (!(pat & F_UWP) || (pat & F_PBACK << F_PSHIFT)))
 
1312
            {
 
1313
              debug1("clearing echo on pseudywin fd (pat %x)\n", pat);
 
1314
# if defined(POSIX) || defined(TERMIO)
 
1315
              modep->tio.c_lflag &= ~ECHO;
 
1316
              modep->tio.c_iflag &= ~ICRNL;
 
1317
# else
 
1318
              modep->m_ttyb.sg_flags &= ~ECHO;
 
1319
# endif
 
1320
            }
 
1321
#endif
 
1322
          SetTTY(newfd, modep);
 
1323
#ifdef TIOCSWINSZ
 
1324
          glwz.ws_col = w;
 
1325
          glwz.ws_row = h;
 
1326
          (void) ioctl(newfd, TIOCSWINSZ, (char *)&glwz);
 
1327
#endif
 
1328
          /* Always turn off nonblocking mode */
 
1329
          (void)fcntl(newfd, F_SETFL, 0);
 
1330
        }
 
1331
#ifndef TIOCSWINSZ
 
1332
      sprintf(libuf, "LINES=%d", h);
 
1333
      sprintf(cobuf, "COLUMNS=%d", w);
 
1334
      NewEnv[5] = libuf;
 
1335
      NewEnv[6] = cobuf;
 
1336
#endif
 
1337
#ifdef MAPKEYS
 
1338
      NewEnv[2] = MakeTermcap(display == 0 || win->w_aflag);
 
1339
#else
 
1340
      if (win->w_aflag)
 
1341
        NewEnv[2] = MakeTermcap(1);
 
1342
      else
 
1343
        NewEnv[2] = Termcap;
 
1344
#endif
 
1345
      strcpy(shellbuf, "SHELL=");
 
1346
      strncpy(shellbuf + 6, ShellProg + (*ShellProg == '-'), sizeof(shellbuf) - 7);
 
1347
      shellbuf[sizeof(shellbuf) - 1] = 0;
 
1348
      NewEnv[4] = shellbuf;
 
1349
      debug1("ForkWindow: NewEnv[4] = '%s'\n", shellbuf);
 
1350
      if (win->w_term && *win->w_term && strcmp(screenterm, win->w_term) &&
 
1351
          (strlen(win->w_term) < 20))
 
1352
        {
 
1353
          char *s1, *s2, tl;
 
1354
 
 
1355
          sprintf(tebuf, "TERM=%s", win->w_term);
 
1356
          debug2("Makewindow %d with %s\n", win->w_number, tebuf);
 
1357
          tl = strlen(win->w_term);
 
1358
          NewEnv[1] = tebuf;
 
1359
          if ((s1 = index(NewEnv[2], '|')))
 
1360
            {
 
1361
              if ((s2 = index(++s1, '|')))
 
1362
                {
 
1363
                  if (strlen(NewEnv[2]) - (s2 - s1) + tl < 1024)
 
1364
                    {
 
1365
                      bcopy(s2, s1 + tl, strlen(s2) + 1);
 
1366
                      bcopy(win->w_term, s1, tl);
 
1367
                    }
 
1368
                }
 
1369
            }
 
1370
        }
 
1371
      sprintf(ebuf, "WINDOW=%d", win->w_number);
 
1372
      NewEnv[3] = ebuf;
 
1373
 
 
1374
      if (*proc == '-')
 
1375
        proc++;
 
1376
      if (!*proc)
 
1377
        proc = DefaultShell;
 
1378
      debug1("calling execvpe %s\n", proc);
 
1379
      execvpe(proc, args, NewEnv);
 
1380
      debug1("exec error: %d\n", errno);
 
1381
      Panic(errno, "Cannot exec '%s'", proc);
 
1382
    default:
 
1383
      break;
 
1384
    }
 
1385
  if (slave != -1)
 
1386
    close(slave);
 
1387
  return pid;
 
1388
}
 
1389
 
 
1390
void
 
1391
execvpe(prog, args, env)
 
1392
char *prog, **args, **env;
 
1393
{
 
1394
  register char *path = NULL, *p;
 
1395
  char buf[1024];
 
1396
  char *shargs[MAXARGS + 1];
 
1397
  register int i, eaccess = 0;
 
1398
 
 
1399
  if (rindex(prog, '/'))
 
1400
    path = "";
 
1401
  if (!path && !(path = getenv("PATH")))
 
1402
    path = DefaultPath;
 
1403
  do
 
1404
    {
 
1405
      for (p = buf; *path && *path != ':'; path++)
 
1406
        if (p - buf < (int)sizeof(buf) - 2)
 
1407
          *p++ = *path;
 
1408
      if (p > buf)
 
1409
        *p++ = '/';
 
1410
      if (p - buf + strlen(prog) >= sizeof(buf) - 1)
 
1411
        continue;
 
1412
      strcpy(p, prog);
 
1413
      execve(buf, args, env);
 
1414
      switch (errno)
 
1415
        {
 
1416
        case ENOEXEC:
 
1417
          shargs[0] = DefaultShell;
 
1418
          shargs[1] = buf;
 
1419
          for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i)
 
1420
            ;
 
1421
          execve(DefaultShell, shargs, env);
 
1422
          return;
 
1423
        case EACCES:
 
1424
          eaccess = 1;
 
1425
          break;
 
1426
        case ENOMEM:
 
1427
        case E2BIG:
 
1428
        case ETXTBSY:
 
1429
          return;
 
1430
        }
 
1431
    } while (*path++);
 
1432
  if (eaccess)
 
1433
    errno = EACCES;
 
1434
}
 
1435
 
 
1436
#ifdef PSEUDOS
 
1437
 
 
1438
int
 
1439
winexec(av)
 
1440
char **av;
 
1441
{
 
1442
  char **pp;
 
1443
  char *p, *s, *t;
 
1444
  int i, r = 0, l = 0;
 
1445
  struct win *w;
 
1446
  extern struct display *display;
 
1447
  extern struct win *windows;
 
1448
  struct pseudowin *pwin;
 
1449
  int type;
 
1450
 
 
1451
  if ((w = display ? fore : windows) == NULL)
 
1452
    return -1;
 
1453
  if (!*av || w->w_pwin)
 
1454
    {
 
1455
      Msg(0, "Filter running: %s", w->w_pwin ? w->w_pwin->p_cmd : "(none)");
 
1456
      return -1;
 
1457
    }
 
1458
  if (w->w_ptyfd < 0)
 
1459
    {
 
1460
      Msg(0, "You feel dead inside.");
 
1461
      return -1;
 
1462
    }
 
1463
  if (!(pwin = (struct pseudowin *)malloc(sizeof(struct pseudowin))))
 
1464
    {
 
1465
      Msg(0, strnomem);
 
1466
      return -1;
 
1467
    }
 
1468
  bzero((char *)pwin, (int)sizeof(*pwin));
 
1469
 
 
1470
  /* allow ^a:!!./ttytest as a short form for ^a:exec !.. ./ttytest */
 
1471
  for (s = *av; *s == ' '; s++)
 
1472
    ;
 
1473
  for (p = s; *p == ':' || *p == '.' || *p == '!'; p++)
 
1474
    ;
 
1475
  if (*p != '|')
 
1476
    while (*p && p > s && p[-1] == '.')
 
1477
      p--;
 
1478
  if (*p == '|')
 
1479
    {
 
1480
      l = F_UWP;
 
1481
      p++;
 
1482
    }
 
1483
  if (*p)
 
1484
    av[0] = p;
 
1485
  else
 
1486
    av++;
 
1487
 
 
1488
  t = pwin->p_cmd;
 
1489
  for (i = 0; i < 3; i++)
 
1490
    {
 
1491
      *t = (s < p) ? *s++ : '.';
 
1492
      switch (*t++)
 
1493
        {
 
1494
        case '.':
 
1495
        case '|':
 
1496
          l |= F_PFRONT << (i * F_PSHIFT);
 
1497
          break;
 
1498
        case '!':
 
1499
          l |= F_PBACK << (i * F_PSHIFT);
 
1500
          break;
 
1501
        case ':':
 
1502
          l |= F_PBOTH << (i * F_PSHIFT);
 
1503
          break;
 
1504
        }
 
1505
    }
 
1506
 
 
1507
  if (l & F_UWP)
 
1508
    {
 
1509
      *t++ = '|';
 
1510
      if ((l & F_PMASK) == F_PFRONT)
 
1511
        {
 
1512
          *pwin->p_cmd = '!';
 
1513
          l ^= F_PFRONT | F_PBACK;
 
1514
        }
 
1515
    }
 
1516
  if (!(l & F_PBACK))
 
1517
    l |= F_UWP;
 
1518
  *t++ = ' ';
 
1519
  pwin->p_fdpat = l;
 
1520
  debug1("winexec: '%#x'\n", pwin->p_fdpat);
 
1521
 
 
1522
  l = MAXSTR - 4;
 
1523
  for (pp = av; *pp; pp++)
 
1524
    {
 
1525
      p = *pp;
 
1526
      while (*p && l-- > 0)
 
1527
        *t++ = *p++;
 
1528
      if (l <= 0)
 
1529
        break;
 
1530
      *t++ = ' ';
 
1531
    }
 
1532
  *--t = '\0';
 
1533
  debug1("%s\n", pwin->p_cmd);
 
1534
 
 
1535
  if ((pwin->p_ptyfd = OpenDevice(av, 0, &type, &t)) < 0)
 
1536
    {
 
1537
      free((char *)pwin);
 
1538
      return -1;
 
1539
    }
 
1540
  strncpy(pwin->p_tty, t, MAXSTR - 1);
 
1541
  w->w_pwin = pwin;
 
1542
  if (type != W_TYPE_PTY)
 
1543
    {
 
1544
      FreePseudowin(w);
 
1545
      Msg(0, "Cannot only use commands as pseudo win.");
 
1546
      return -1;
 
1547
    }
 
1548
  if (!(pwin->p_fdpat & F_PFRONT))
 
1549
    evdeq(&w->w_readev);
 
1550
#ifdef TIOCPKT
 
1551
  {
 
1552
    int flag = 0;
 
1553
 
 
1554
    if (ioctl(pwin->p_ptyfd, TIOCPKT, (char *)&flag))
 
1555
      {
 
1556
        Msg(errno, "TIOCPKT pwin ioctl");
 
1557
        FreePseudowin(w);
 
1558
        return -1;
 
1559
      }
 
1560
    if (w->w_type == W_TYPE_PTY && !(pwin->p_fdpat & F_PFRONT))
 
1561
      {
 
1562
        if (ioctl(w->w_ptyfd, TIOCPKT, (char *)&flag))
 
1563
          {
 
1564
            Msg(errno, "TIOCPKT win ioctl");
 
1565
            FreePseudowin(w);
 
1566
            return -1;
 
1567
          }
 
1568
      }
 
1569
  }
 
1570
#endif /* TIOCPKT */
 
1571
 
 
1572
  pwin->p_readev.fd = pwin->p_writeev.fd = pwin->p_ptyfd;
 
1573
  pwin->p_readev.type = EV_READ;
 
1574
  pwin->p_writeev.type = EV_WRITE;
 
1575
  pwin->p_readev.data = pwin->p_writeev.data = (char *)w;
 
1576
  pwin->p_readev.handler = pseu_readev_fn;
 
1577
  pwin->p_writeev.handler = pseu_writeev_fn;
 
1578
  pwin->p_writeev.condpos = &pwin->p_inlen;
 
1579
  if (pwin->p_fdpat & (F_PFRONT << F_PSHIFT * 2 | F_PFRONT << F_PSHIFT))
 
1580
    evenq(&pwin->p_readev);
 
1581
  evenq(&pwin->p_writeev);
 
1582
  r = pwin->p_pid = ForkWindow(w, av, t);
 
1583
  if (r < 0)
 
1584
    FreePseudowin(w);
 
1585
  return r;
 
1586
}
 
1587
 
 
1588
void
 
1589
FreePseudowin(w)
 
1590
struct win *w;
 
1591
{
 
1592
  struct pseudowin *pwin = w->w_pwin;
 
1593
 
 
1594
  ASSERT(pwin);
 
1595
  if (fcntl(w->w_ptyfd, F_SETFL, FNBLOCK))
 
1596
    Msg(errno, "Warning: FreePseudowin: NBLOCK fcntl failed");
 
1597
#ifdef TIOCPKT
 
1598
  if (w->w_type == W_TYPE_PTY && !(pwin->p_fdpat & F_PFRONT))
 
1599
    {
 
1600
      int flag = 1;
 
1601
      if (ioctl(w->w_ptyfd, TIOCPKT, (char *)&flag))
 
1602
        Msg(errno, "Warning: FreePseudowin: TIOCPKT win ioctl");
 
1603
    }
 
1604
#endif
 
1605
  /* should be able to use CloseDevice() here */
 
1606
  (void)chmod(pwin->p_tty, 0666);
 
1607
  (void)chown(pwin->p_tty, 0, 0);
 
1608
  if (pwin->p_ptyfd >= 0)
 
1609
    close(pwin->p_ptyfd);
 
1610
  evdeq(&pwin->p_readev);
 
1611
  evdeq(&pwin->p_writeev);
 
1612
  if (w->w_readev.condneg == &pwin->p_inlen)
 
1613
    w->w_readev.condpos = w->w_readev.condneg = 0;
 
1614
  evenq(&w->w_readev);
 
1615
  free((char *)pwin);
 
1616
  w->w_pwin = NULL;
 
1617
}
 
1618
 
 
1619
#endif /* PSEUDOS */
 
1620
 
 
1621
 
 
1622
#ifdef MULTIUSER
 
1623
/*
 
1624
 * returns 0, if the lock really has been released
 
1625
 */
 
1626
int
 
1627
ReleaseAutoWritelock(dis, w)
 
1628
struct display *dis;
 
1629
struct win *w;
 
1630
{
 
1631
  debug2("ReleaseAutoWritelock: user %s, window %d\n",
 
1632
         dis->d_user->u_name, w->w_number);
 
1633
 
 
1634
  /* release auto writelock when user has no other display here */
 
1635
  if (w->w_wlock == WLOCK_AUTO && w->w_wlockuser == dis->d_user)
 
1636
    {
 
1637
      struct display *d;
 
1638
 
 
1639
      for (d = displays; d; d = d->d_next)
 
1640
        if (( d != dis) && (d->d_fore == w) && (d->d_user == dis->d_user))
 
1641
          break;
 
1642
      debug3("%s %s autolock on win %d\n", 
 
1643
             dis->d_user->u_name, d ? "keeps" : "releases", w->w_number);
 
1644
      if (!d)
 
1645
        {
 
1646
          w->w_wlockuser = NULL;
 
1647
          return 0;
 
1648
        }
 
1649
    }
 
1650
  return 1;
 
1651
}
 
1652
 
 
1653
/*
 
1654
 * returns 0, if the lock really could be obtained
 
1655
 */
 
1656
int
 
1657
ObtainAutoWritelock(d, w)
 
1658
struct display *d;
 
1659
struct win *w;
 
1660
{
 
1661
  if ((w->w_wlock == WLOCK_AUTO) &&
 
1662
       !AclCheckPermWin(d->d_user, ACL_WRITE, w) &&
 
1663
       !w->w_wlockuser)
 
1664
    {
 
1665
      debug2("%s obtained auto writelock for exported window %d\n",
 
1666
             d->d_user->u_name, w->w_number);
 
1667
      w->w_wlockuser = d->d_user;
 
1668
      return 0;
 
1669
    }
 
1670
  return 1;
 
1671
}
 
1672
 
 
1673
#endif /* MULTIUSER */
 
1674
 
 
1675
 
 
1676
 
 
1677
/********************************************************************/
 
1678
 
 
1679
#ifdef COPY_PASTE
 
1680
static void
 
1681
paste_slowev_fn(ev, data)
 
1682
struct event *ev;
 
1683
char *data;
 
1684
{
 
1685
  struct paster *pa = (struct paster *)data;
 
1686
  struct win *p;
 
1687
 
 
1688
  int l = 1;
 
1689
  flayer = pa->pa_pastelayer;
 
1690
  if (!flayer)
 
1691
    pa->pa_pastelen = 0;
 
1692
  if (!pa->pa_pastelen)
 
1693
    return;
 
1694
  p = Layer2Window(flayer);
 
1695
  DoProcess(p, &pa->pa_pasteptr, &l, pa);
 
1696
  pa->pa_pastelen -= 1 - l;
 
1697
  if (pa->pa_pastelen > 0)
 
1698
    {
 
1699
      SetTimeout(&pa->pa_slowev, p->w_slowpaste);
 
1700
      evenq(&pa->pa_slowev);
 
1701
    }
 
1702
}
 
1703
#endif
 
1704
 
 
1705
 
 
1706
static int
 
1707
muchpending(p, ev)
 
1708
struct win *p;
 
1709
struct event *ev;
 
1710
{
 
1711
  struct canvas *cv;
 
1712
  for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext)
 
1713
    {
 
1714
      display = cv->c_display;
 
1715
      if (D_status == STATUS_ON_WIN && !D_status_bell)
 
1716
        {
 
1717
          /* wait 'til status is gone */
 
1718
          debug("BLOCKING because of status\n");
 
1719
          ev->condpos = &const_one;
 
1720
          ev->condneg = &D_status;
 
1721
          return 1;
 
1722
        }
 
1723
      debug2("muchpending %s %d: ", D_usertty, D_blocked);
 
1724
      debug3("%d %d %d\n", D_obufp - D_obuf, D_obufmax, D_blocked_fuzz);
 
1725
      if (D_blocked)
 
1726
        continue;
 
1727
      if (D_obufp - D_obuf > D_obufmax + D_blocked_fuzz)
 
1728
        {
 
1729
          if (D_nonblock == 0)
 
1730
            {
 
1731
              debug1("obuf is full, stopping output to display %s\n", D_usertty);
 
1732
              D_blocked = 1;
 
1733
              continue;
 
1734
            }
 
1735
          debug("BLOCKING because of full obuf\n");
 
1736
          ev->condpos = &D_obuffree;
 
1737
          ev->condneg = &D_obuflenmax;
 
1738
          if (D_nonblock > 0 && !D_blockedev.queued)
 
1739
            {
 
1740
              debug1("created timeout of %g secs\n", D_nonblock/1000.);
 
1741
              SetTimeout(&D_blockedev, D_nonblock);
 
1742
              evenq(&D_blockedev);
 
1743
            }
 
1744
          return 1;
 
1745
        }
 
1746
    }
 
1747
  return 0;
 
1748
}
 
1749
 
 
1750
static void
 
1751
win_readev_fn(ev, data)
 
1752
struct event *ev;
 
1753
char *data;
 
1754
{
 
1755
  struct win *p = (struct win *)data;
 
1756
  char buf[IOSIZE], *bp;
 
1757
  int size, len;
 
1758
#ifdef PSEUDOS
 
1759
  int wtop;
 
1760
#endif
 
1761
 
 
1762
  bp = buf;
 
1763
  size = IOSIZE;
 
1764
 
 
1765
#ifdef PSEUDOS
 
1766
  wtop = p->w_pwin && W_WTOP(p);
 
1767
  if (wtop)
 
1768
    {
 
1769
      ASSERT(sizeof(p->w_pwin->p_inbuf) == IOSIZE);
 
1770
      size = IOSIZE - p->w_pwin->p_inlen;
 
1771
      if (size <= 0)
 
1772
        {
 
1773
          ev->condpos = &const_IOSIZE;
 
1774
          ev->condneg = &p->w_pwin->p_inlen;
 
1775
          return;
 
1776
        }
 
1777
    }
 
1778
#endif
 
1779
  if (p->w_layer.l_cvlist && muchpending(p, ev))
 
1780
    return;
 
1781
#ifdef ZMODEM
 
1782
  if (!p->w_zdisplay)
 
1783
#endif
 
1784
    if (p->w_blocked)
 
1785
      {
 
1786
        ev->condpos = &const_one;
 
1787
        ev->condneg = &p->w_blocked;
 
1788
        return;
 
1789
      }
 
1790
  if (ev->condpos)
 
1791
    ev->condpos = ev->condneg = 0;
 
1792
 
 
1793
  if ((len = p->w_outlen))
 
1794
    {
 
1795
      p->w_outlen = 0;
 
1796
      WriteString(p, p->w_outbuf, len);
 
1797
      return;
 
1798
    }
 
1799
 
 
1800
  debug1("going to read from window fd %d\n", ev->fd);
 
1801
  if ((len = read(ev->fd, buf, size)) < 0)
 
1802
    {
 
1803
      if (errno == EINTR || errno == EAGAIN)
 
1804
        return;
 
1805
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
 
1806
      if (errno == EWOULDBLOCK)
 
1807
        return;
 
1808
#endif
 
1809
      debug2("Window %d: read error (errno %d) - killing window\n", p->w_number, errno);
 
1810
      WindowDied(p);
 
1811
      return;
 
1812
    }
 
1813
  if (len == 0)
 
1814
    {
 
1815
      debug1("Window %d: EOF - killing window\n", p->w_number);
 
1816
      WindowDied(p);
 
1817
      return;
 
1818
    }
 
1819
  debug1(" -> %d bytes\n", len);
 
1820
#ifdef TIOCPKT
 
1821
  if (p->w_type == W_TYPE_PTY)
 
1822
    {
 
1823
      if (buf[0])
 
1824
        {
 
1825
          debug1("PAKET %x\n", buf[0]);
 
1826
          if (buf[0] & TIOCPKT_NOSTOP)
 
1827
            WNewAutoFlow(p, 0);
 
1828
          if (buf[0] & TIOCPKT_DOSTOP)
 
1829
            WNewAutoFlow(p, 1);
 
1830
        }
 
1831
      bp++;
 
1832
      len--;
 
1833
    }
 
1834
#endif
 
1835
#ifdef BUILTIN_TELNET
 
1836
  if (p->w_type == W_TYPE_TELNET)
 
1837
    len = TelIn(p, bp, len, buf + sizeof(buf) - (bp + len));
 
1838
#endif
 
1839
  if (len == 0)
 
1840
    return;
 
1841
#ifdef ZMODEM
 
1842
  if (zmodem_mode && zmodem_parse(p, bp, len))
 
1843
    return;
 
1844
#endif
 
1845
#ifdef PSEUDOS
 
1846
  if (wtop)
 
1847
    {
 
1848
      debug("sending input to pwin\n");
 
1849
      bcopy(bp, p->w_pwin->p_inbuf + p->w_pwin->p_inlen, len);
 
1850
      p->w_pwin->p_inlen += len;
 
1851
    }
 
1852
#endif
 
1853
  WriteString(p, bp, len);
 
1854
  return;
 
1855
}
 
1856
 
 
1857
 
 
1858
static void
 
1859
win_writeev_fn(ev, data)
 
1860
struct event *ev;
 
1861
char *data;
 
1862
{
 
1863
  struct win *p = (struct win *)data;
 
1864
  int len;
 
1865
  if (p->w_inlen)
 
1866
    {
 
1867
      debug2("writing %d bytes to win %d\n", p->w_inlen, p->w_number);
 
1868
      if ((len = write(ev->fd, p->w_inbuf, p->w_inlen)) <= 0)
 
1869
        len = p->w_inlen;       /* dead window */
 
1870
      if ((p->w_inlen -= len))
 
1871
        bcopy(p->w_inbuf + len, p->w_inbuf, p->w_inlen);
 
1872
    }
 
1873
#ifdef COPY_PASTE
 
1874
  if (p->w_paster.pa_pastelen && !p->w_slowpaste)
 
1875
    {
 
1876
      struct paster *pa = &p->w_paster;
 
1877
      flayer = pa->pa_pastelayer;
 
1878
      if (flayer)
 
1879
        DoProcess(p, &pa->pa_pasteptr, &pa->pa_pastelen, pa);
 
1880
    }
 
1881
#endif
 
1882
  return;
 
1883
}
 
1884
 
 
1885
 
 
1886
 
 
1887
#ifdef PSEUDOS
 
1888
 
 
1889
static void
 
1890
pseu_readev_fn(ev, data)
 
1891
struct event *ev;
 
1892
char *data;
 
1893
{
 
1894
  struct win *p = (struct win *)data;
 
1895
  char buf[IOSIZE];
 
1896
  int size, ptow, len;
 
1897
 
 
1898
  size = IOSIZE;
 
1899
 
 
1900
  ptow = W_PTOW(p);
 
1901
  if (ptow)
 
1902
    {
 
1903
      ASSERT(sizeof(p->w_inbuf) == IOSIZE);
 
1904
      size = IOSIZE - p->w_inlen;
 
1905
      if (size <= 0)
 
1906
        {
 
1907
          ev->condpos = &const_IOSIZE;
 
1908
          ev->condneg = &p->w_inlen;
 
1909
          return;
 
1910
        }
 
1911
    }
 
1912
  if (p->w_layer.l_cvlist && muchpending(p, ev))
 
1913
    return;
 
1914
  if (p->w_blocked)
 
1915
    {
 
1916
      ev->condpos = &const_one;
 
1917
      ev->condneg = &p->w_blocked;
 
1918
      return;
 
1919
    }
 
1920
  if (ev->condpos)
 
1921
    ev->condpos = ev->condneg = 0;
 
1922
 
 
1923
  if ((len = p->w_outlen))
 
1924
    {
 
1925
      p->w_outlen = 0;
 
1926
      WriteString(p, p->w_outbuf, len);
 
1927
      return;
 
1928
    }
 
1929
 
 
1930
  if ((len = read(ev->fd, buf, size)) <= 0)
 
1931
    {
 
1932
      if (errno == EINTR || errno == EAGAIN)
 
1933
        return;
 
1934
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
 
1935
      if (errno == EWOULDBLOCK)
 
1936
        return;
 
1937
#endif
 
1938
      debug2("Window %d: pseudowin read error (errno %d) -- removing pseudowin\n", p->w_number, len ? errno : 0);
 
1939
      FreePseudowin(p);
 
1940
      return;
 
1941
    }
 
1942
  /* no packet mode on pseudos! */
 
1943
  if (ptow)
 
1944
    {
 
1945
      bcopy(buf, p->w_inbuf + p->w_inlen, len);
 
1946
      p->w_inlen += len;
 
1947
    }
 
1948
  WriteString(p, buf, len);
 
1949
  return;
 
1950
}
 
1951
 
 
1952
static void
 
1953
pseu_writeev_fn(ev, data)
 
1954
struct event *ev;
 
1955
char *data;
 
1956
{
 
1957
  struct win *p = (struct win *)data;
 
1958
  struct pseudowin *pw = p->w_pwin;
 
1959
  int len;
 
1960
 
 
1961
  ASSERT(pw);
 
1962
  if (pw->p_inlen == 0)
 
1963
    return;
 
1964
  if ((len = write(ev->fd, pw->p_inbuf, pw->p_inlen)) <= 0)
 
1965
    len = pw->p_inlen;          /* dead pseudo */
 
1966
  if ((p->w_pwin->p_inlen -= len))
 
1967
    bcopy(p->w_pwin->p_inbuf + len, p->w_pwin->p_inbuf, p->w_pwin->p_inlen);
 
1968
}
 
1969
 
 
1970
 
 
1971
#endif /* PSEUDOS */
 
1972
 
 
1973
static void
 
1974
win_silenceev_fn(ev, data)
 
1975
struct event *ev;
 
1976
char *data;
 
1977
{
 
1978
  struct win *p = (struct win *)data;
 
1979
  struct canvas *cv;
 
1980
  debug1("FOUND silence win %d\n", p->w_number);
 
1981
  for (display = displays; display; display = display->d_next)
 
1982
    {
 
1983
      for (cv = D_cvlist; cv; cv = cv->c_next)
 
1984
        if (cv->c_layer->l_bottom == &p->w_layer)
 
1985
          break;
 
1986
      if (cv)
 
1987
        continue;       /* user already sees window */
 
1988
#ifdef MULTIUSER
 
1989
      if (!(ACLBYTE(p->w_lio_notify, D_user->u_id) & ACLBIT(D_user->u_id)))
 
1990
        continue;
 
1991
#endif
 
1992
      Msg(0, "Window %d: silence for %d seconds", p->w_number, p->w_silencewait);
 
1993
    }
 
1994
}
 
1995
 
 
1996
#ifdef ZMODEM
 
1997
 
 
1998
static int
 
1999
zmodem_parse(p, bp, len)
 
2000
struct win *p;
 
2001
char *bp;
 
2002
int len;
 
2003
{
 
2004
  int i;
 
2005
  char *b2 = bp;
 
2006
  for (i = 0; i < len; i++, b2++)
 
2007
    {
 
2008
      if (p->w_zauto == 0)
 
2009
        {
 
2010
          for (; i < len; i++, b2++)
 
2011
            if (*b2 == 030)
 
2012
              break;
 
2013
          if (i == len)
 
2014
            break;
 
2015
          if (i > 1 && b2[-1] == '*' && b2[-2] == '*')
 
2016
            p->w_zauto = 3;
 
2017
          continue;
 
2018
        }
 
2019
      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'))
 
2020
        {
 
2021
          if (++p->w_zauto < 6)
 
2022
            continue;
 
2023
          if (p->w_zauto == 6)
 
2024
            p->w_zauto = 0;
 
2025
          if (!p->w_zdisplay)
 
2026
            {
 
2027
              if (i > 6)
 
2028
                WriteString(p, bp, i + 1 - 6);
 
2029
              WriteString(p, "\r\n", 2);
 
2030
              zmodem_found(p, *b2 == '1', b2 + 1, len - i - 1);
 
2031
              return 1;
 
2032
            }
 
2033
          else if (p->w_zauto == 7 || *b2 == '8')
 
2034
            {
 
2035
              int se = p->w_zdisplay->d_blocked == 2 ? 'O' : '\212';
 
2036
              for (; i < len; i++, b2++)
 
2037
                if (*b2 == se)
 
2038
                  break;
 
2039
              if (i < len)
 
2040
                {
 
2041
                  zmodem_abort(p, 0);
 
2042
                  D_blocked = 0;
 
2043
                  D_readev.condpos = D_readev.condneg = 0;
 
2044
                  while (len-- > 0)
 
2045
                    AddChar(*bp++);
 
2046
                  Flush();
 
2047
                  Activate(D_fore ? D_fore->w_norefresh : 0);
 
2048
                  return 1;
 
2049
                }
 
2050
              p->w_zauto = 6;
 
2051
            }
 
2052
        }
 
2053
      else
 
2054
        p->w_zauto = *b2 == '*' ? (p->w_zauto == 2 ? 2 : 1) : 0;
 
2055
    }
 
2056
  if (p->w_zauto == 0 && bp[len - 1] == '*')
 
2057
    p->w_zauto = len > 1 && bp[len - 2] == '*' ? 2 : 1;
 
2058
  if (p->w_zdisplay)
 
2059
    {
 
2060
      display = p->w_zdisplay;
 
2061
      while (len-- > 0)
 
2062
        AddChar(*bp++);
 
2063
      return 1;
 
2064
    }
 
2065
  return 0;
 
2066
}
 
2067
 
 
2068
static void
 
2069
zmodem_fin(buf, len, data)
 
2070
char *buf;
 
2071
int len;
 
2072
char *data;
 
2073
{
 
2074
  char *s;
 
2075
  int n;
 
2076
 
 
2077
  if (len)
 
2078
    RcLine(buf, strlen(buf) + 1);
 
2079
  else
 
2080
    {
 
2081
      s = "\030\030\030\030\030\030\030\030\030\030";
 
2082
      n = strlen(s);
 
2083
      LayProcess(&s, &n);
 
2084
    }
 
2085
}
 
2086
 
 
2087
static void
 
2088
zmodem_found(p, send, bp, len)
 
2089
struct win *p;
 
2090
int send;
 
2091
char *bp;
 
2092
int len;
 
2093
{
 
2094
  char *s;
 
2095
  int i, n;
 
2096
  extern int zmodem_mode;
 
2097
 
 
2098
  /* check for abort sequence */
 
2099
  n = 0;
 
2100
  for (i = 0; i < len ; i++)
 
2101
    if (bp[i] != 030)
 
2102
      n = 0;
 
2103
    else if (++n > 4)
 
2104
      return;
 
2105
  if (zmodem_mode == 3 || (zmodem_mode == 1 && p->w_type != W_TYPE_PLAIN))
 
2106
    {
 
2107
      struct display *d, *olddisplay;
 
2108
 
 
2109
      olddisplay = display;
 
2110
      d = p->w_lastdisp;
 
2111
      if (!d || d->d_fore != p)
 
2112
        for (d = displays; d; d = d->d_next)
 
2113
          if (d->d_fore == p)
 
2114
            break;
 
2115
      if (!d && p->w_layer.l_cvlist)
 
2116
        d = p->w_layer.l_cvlist->c_display;
 
2117
      if (!d)
 
2118
        d = displays;
 
2119
      if (!d)
 
2120
        return;
 
2121
      display = d;
 
2122
      RemoveStatus();
 
2123
      p->w_zdisplay = display;
 
2124
      D_blocked = 2 + send;
 
2125
      flayer = &p->w_layer;
 
2126
      ZmodemPage();
 
2127
      display = d;
 
2128
      evdeq(&D_blockedev);
 
2129
      D_readev.condpos = &const_IOSIZE;
 
2130
      D_readev.condneg = &p->w_inlen;
 
2131
      ClearAll();
 
2132
      GotoPos(0, 0);
 
2133
      SetRendition(&mchar_blank);
 
2134
      AddStr("Zmodem active\r\n\r\n");
 
2135
      AddStr(send ? "**\030B01" : "**\030B00");
 
2136
      while (len-- > 0)
 
2137
        AddChar(*bp++);
 
2138
      display = olddisplay;
 
2139
      return;
 
2140
    }
 
2141
  flayer = &p->w_layer;
 
2142
  Input(":", 100, INP_COOKED, zmodem_fin, NULL);
 
2143
  s = send ? zmodem_sendcmd : zmodem_recvcmd;
 
2144
  n = strlen(s);
 
2145
  LayProcess(&s, &n);
 
2146
}
 
2147
 
 
2148
void
 
2149
zmodem_abort(p, d)
 
2150
struct win *p;
 
2151
struct display *d;
 
2152
{
 
2153
  struct display *olddisplay = display;
 
2154
  struct layer *oldflayer = flayer;
 
2155
  if (p)
 
2156
    {
 
2157
      if (p->w_savelayer && p->w_savelayer->l_next)
 
2158
        {
 
2159
          if (oldflayer == p->w_savelayer)
 
2160
            oldflayer = flayer->l_next;
 
2161
          flayer = p->w_savelayer;
 
2162
          ExitOverlayPage();
 
2163
        }
 
2164
      p->w_zdisplay = 0;
 
2165
      p->w_zauto = 0;
 
2166
      LRefreshAll(&p->w_layer, 0);
 
2167
    }
 
2168
  if (d)
 
2169
    {
 
2170
      display = d;
 
2171
      D_blocked = 0;
 
2172
      D_readev.condpos = D_readev.condneg = 0;
 
2173
      Activate(D_fore ? D_fore->w_norefresh : 0);
 
2174
    }
 
2175
  display = olddisplay;
 
2176
  flayer = oldflayer;
 
2177
}
 
2178
 
 
2179
#endif