~ubuntu-branches/debian/stretch/screen/stretch

« back to all changes in this revision

Viewing changes to .pc/62cherry-pick-8ffd5f46-fix-caption-hardstatus-color-rendering.patch/screen.c

  • Committer: Package Import Robot
  • Author(s): Axel Beckert
  • Date: 2015-06-17 21:57:18 UTC
  • mfrom: (7.1.5 experimental)
  • Revision ID: package-import@ubuntu.com-20150617215718-mmj4dpghyl5a0ipy
Tags: 4.3.0-2
* Upload to unstable again.
* Re-add debian/dirs with /etc/tmpfiles.d/ and add a comment why screen
  ships an empty directory.
  + Fixes regression introduced in 4.2.1-4: If systemd is not installed
    and screen is either setuid or neither setuid nor setgid,
    /var/lib/dpkg/info/screen.postinst bailed out with "16:
    /var/lib/dpkg/info/screen.postinst: cannot create
    /etc/tmpfiles.d/screen-cleanup.conf: Directory nonexistent".
  + See comment in debian/dirs for more detailed reasoning.
* No more ship /lib/systemd/system/screen-cleanup.service in the package
  but link it to /dev/null in postinst and remove the link again in
  postrm. (LP: #1462692)
* Add fixed bugs reported in Ubuntu to previous changelog entry.
* Apply wrap-and-sort.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2010
2
 
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3
 
 *      Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
4
 
 * Copyright (c) 2008, 2009
5
 
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
6
 
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
7
 
 *      Micah Cowan (micah@cowan.name)
8
 
 *      Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
9
 
 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
10
 
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
11
 
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
12
 
 * Copyright (c) 1987 Oliver Laumann
13
 
#ifdef HAVE_BRAILLE
14
 
 * Modified by:
15
 
 *      Authors:  Hadi Bargi Rangin  bargi@dots.physics.orst.edu
16
 
 *                Bill Barry         barryb@dots.physics.orst.edu
17
 
 *                Randy Lundquist    randyl@dots.physics.orst.edu
18
 
 *
19
 
 * Modifications Copyright (c) 1995 by
20
 
 * Science Access Project, Oregon State University.
21
 
#endif
22
 
 *
23
 
 * This program is free software; you can redistribute it and/or modify
24
 
 * it under the terms of the GNU General Public License as published by
25
 
 * the Free Software Foundation; either version 3, or (at your option)
26
 
 * any later version.
27
 
 *
28
 
 * This program is distributed in the hope that it will be useful,
29
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31
 
 * GNU General Public License for more details.
32
 
 *
33
 
 * You should have received a copy of the GNU General Public License
34
 
 * along with this program (see the file COPYING); if not, see
35
 
 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
36
 
 * 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
37
 
 *
38
 
 ****************************************************************
39
 
 */
40
 
 
41
 
#include <sys/types.h>
42
 
#include <ctype.h>
43
 
 
44
 
#include <fcntl.h>
45
 
 
46
 
#ifdef sgi
47
 
# include <sys/sysmacros.h>
48
 
#endif
49
 
 
50
 
#include <sys/stat.h>
51
 
#ifndef sun
52
 
# include <sys/ioctl.h>
53
 
#endif
54
 
 
55
 
#ifndef SIGINT
56
 
# include <signal.h>
57
 
#endif
58
 
 
59
 
#include "config.h"
60
 
 
61
 
#ifdef HAVE_STROPTS_H
62
 
# include <sys/stropts.h>
63
 
#endif
64
 
 
65
 
#if defined(SYSV) && !defined(ISC)
66
 
# include <sys/utsname.h>
67
 
#endif
68
 
 
69
 
#if defined(sequent) || defined(SVR4)
70
 
# include <sys/resource.h>
71
 
#endif /* sequent || SVR4 */
72
 
 
73
 
#ifdef ISC
74
 
# include <sys/tty.h>
75
 
# include <sys/sioctl.h>
76
 
# include <sys/pty.h>
77
 
#endif /* ISC */
78
 
 
79
 
#if (defined(AUX) || defined(_AUX_SOURCE)) && defined(POSIX)
80
 
# include <compat.h>
81
 
#endif
82
 
#if defined(USE_LOCALE) || defined(ENCODINGS)
83
 
# include <locale.h>
84
 
#endif
85
 
#if defined(HAVE_NL_LANGINFO) && defined(ENCODINGS)
86
 
# include <langinfo.h>
87
 
#endif
88
 
 
89
 
#include "screen.h"
90
 
#ifdef HAVE_BRAILLE
91
 
# include "braille.h"
92
 
#endif
93
 
 
94
 
#include "patchlevel.h"
95
 
 
96
 
/*
97
 
 *  At the moment we only need the real password if the
98
 
 *  builtin lock is used. Therefore disable SHADOWPW if
99
 
 *  we do not really need it (kind of security thing).
100
 
 */
101
 
#ifndef LOCK
102
 
# undef SHADOWPW
103
 
#endif
104
 
 
105
 
#include <pwd.h>
106
 
#ifdef SHADOWPW
107
 
# include <shadow.h>
108
 
#endif /* SHADOWPW */
109
 
 
110
 
#include "logfile.h"    /* islogfile, logfflush */
111
 
 
112
 
#ifdef DEBUG
113
 
FILE *dfp;
114
 
#endif
115
 
 
116
 
 
117
 
extern char Term[], screenterm[], **environ, Termcap[];
118
 
int force_vt = 1;
119
 
int VBellWait, MsgWait, MsgMinWait, SilenceWait;
120
 
 
121
 
extern struct acluser *users;
122
 
extern struct display *displays, *display; 
123
 
 
124
 
extern struct LayFuncs MarkLf;
125
 
 
126
 
 
127
 
extern int visual_bell;
128
 
#ifdef COPY_PASTE
129
 
extern unsigned char mark_key_tab[];
130
 
#endif
131
 
extern char version[];
132
 
extern char DefaultShell[];
133
 
#ifdef ZMODEM
134
 
extern char *zmodem_sendcmd;
135
 
extern char *zmodem_recvcmd;
136
 
#endif
137
 
extern struct layout *layout_last;
138
 
 
139
 
 
140
 
char *ShellProg;
141
 
char *ShellArgs[2];
142
 
 
143
 
extern struct NewWindow nwin_undef, nwin_default, nwin_options;
144
 
struct backtick;
145
 
 
146
 
static struct passwd *getpwbyname __P((char *, struct passwd *));
147
 
static void  SigChldHandler __P((void));
148
 
static sigret_t SigChld __P(SIGPROTOARG);
149
 
static sigret_t SigInt __P(SIGPROTOARG);
150
 
static sigret_t CoreDump __P(SIGPROTOARG);
151
 
static sigret_t FinitHandler __P(SIGPROTOARG);
152
 
static void  DoWait __P((void));
153
 
static void  serv_read_fn __P((struct event *, char *));
154
 
static void  serv_select_fn __P((struct event *, char *));
155
 
static void  logflush_fn __P((struct event *, char *));
156
 
static void  backtick_filter __P((struct backtick *));
157
 
static void  backtick_fn __P((struct event *, char *));
158
 
static char *runbacktick __P((struct backtick *, int *, time_t));
159
 
static int   IsSymbol __P((char *, char *));
160
 
static char *ParseChar __P((char *, char *));
161
 
static int   ParseEscape __P((char *));
162
 
static char *pad_expand __P((char *, char *, int, int));
163
 
#ifdef DEBUG
164
 
static void  fds __P((void));
165
 
#endif
166
 
 
167
 
int nversion;   /* numerical version, used for secondary DA */
168
 
 
169
 
/* the attacher */
170
 
struct passwd *ppp;
171
 
char *attach_tty;
172
 
int attach_fd = -1;
173
 
char *attach_term;
174
 
char *LoginName;
175
 
struct mode attach_Mode;
176
 
 
177
 
char SockPath[MAXPATHLEN + 2 * MAXSTR];
178
 
char *SockName;                 /* SockName is pointer in SockPath */
179
 
char *SockMatch = NULL;         /* session id command line argument */
180
 
int ServerSocket = -1;
181
 
struct event serv_read;
182
 
struct event serv_select;
183
 
struct event logflushev;
184
 
 
185
 
char **NewEnv = NULL;
186
 
 
187
 
char *RcFileName = NULL;
188
 
char *home;
189
 
 
190
 
char *screenlogfile;                    /* filename layout */
191
 
int log_flush = 10;                     /* flush interval in seconds */
192
 
int logtstamp_on = 0;                   /* tstamp disabled */
193
 
char *logtstamp_string;                 /* stamp layout */
194
 
int logtstamp_after = 120;              /* first tstamp after 120s */
195
 
char *hardcopydir = NULL;
196
 
char *BellString;
197
 
char *VisualBellString;
198
 
char *ActivityString;
199
 
#ifdef COPY_PASTE
200
 
char *BufferFile;
201
 
#endif
202
 
#ifdef POW_DETACH
203
 
char *PowDetachString;
204
 
#endif
205
 
char *hstatusstring;
206
 
char *captionstring;
207
 
char *timestring;
208
 
char *wliststr;
209
 
char *wlisttit;
210
 
int auto_detach = 1;
211
 
int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag;
212
 
int cmdflag;
213
 
int queryflag = -1;
214
 
int adaptflag;
215
 
 
216
 
#ifdef MULTIUSER
217
 
char *multi;
218
 
char *multi_home;
219
 
int multi_uid;
220
 
int own_uid;
221
 
int multiattach;
222
 
int tty_mode;
223
 
int tty_oldmode = -1;
224
 
#endif
225
 
 
226
 
char HostName[MAXSTR];
227
 
int MasterPid, PanicPid;
228
 
int real_uid, real_gid, eff_uid, eff_gid;
229
 
int default_startup;
230
 
int ZombieKey_destroy, ZombieKey_resurrect, ZombieKey_onerror;
231
 
char *preselect = NULL;         /* only used in Attach() */
232
 
 
233
 
#ifdef UTF8
234
 
char *screenencodings;
235
 
#endif
236
 
 
237
 
#ifdef DW_CHARS
238
 
int cjkwidth;
239
 
#endif
240
 
 
241
 
#ifdef NETHACK
242
 
int nethackflag = 0;
243
 
#endif
244
 
int maxwin;
245
 
 
246
 
 
247
 
struct layer *flayer;
248
 
struct win *fore;
249
 
struct win *windows;
250
 
struct win *console_window;
251
 
#ifdef BUILTIN_TELNET
252
 
int af;
253
 
#endif
254
 
 
255
 
/*
256
 
 * Do this last
257
 
 */
258
 
#include "extern.h"
259
 
 
260
 
char strnomem[] = "Out of memory.";
261
 
 
262
 
 
263
 
static int InterruptPlease;
264
 
static int GotSigChld;
265
 
 
266
 
static int 
267
 
lf_secreopen(name, wantfd, l)
268
 
char *name;
269
 
int wantfd;
270
 
struct logfile *l;
271
 
{
272
 
  int got_fd;
273
 
 
274
 
  close(wantfd);
275
 
  if (((got_fd = secopen(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) ||
276
 
      lf_move_fd(got_fd, wantfd) < 0)
277
 
    {
278
 
      logfclose(l);
279
 
      debug1("lf_secreopen: failed for %s\n", name);
280
 
      return -1;
281
 
    }
282
 
  l->st->st_ino = l->st->st_dev = 0;
283
 
  debug2("lf_secreopen: %d = %s\n", wantfd, name);
284
 
  return 0;
285
 
}
286
 
 
287
 
/********************************************************************/
288
 
/********************************************************************/
289
 
/********************************************************************/
290
 
 
291
 
 
292
 
static struct passwd *
293
 
getpwbyname(name, ppp)
294
 
char *name;
295
 
struct passwd *ppp;
296
 
{
297
 
  int n;
298
 
#ifdef SHADOWPW
299
 
  struct spwd *sss = NULL;
300
 
  static char *spw = NULL;
301
 
#endif
302
 
 
303
 
  if (!ppp && !(ppp = getpwnam(name)))
304
 
    return NULL;
305
 
 
306
 
  /* Do password sanity check..., allow ##user for SUN_C2 security */
307
 
#ifdef SHADOWPW
308
 
pw_try_again:
309
 
#endif
310
 
  n = 0;
311
 
  if (ppp->pw_passwd[0] == '#' && ppp->pw_passwd[1] == '#' &&
312
 
      strcmp(ppp->pw_passwd + 2, ppp->pw_name) == 0)
313
 
    n = 13;
314
 
  for (; n < 13; n++)
315
 
    {
316
 
      char c = ppp->pw_passwd[n];
317
 
      if (!(c == '.' || c == '/' || c == '$' ||
318
 
            (c >= '0' && c <= '9') || 
319
 
            (c >= 'a' && c <= 'z') || 
320
 
            (c >= 'A' && c <= 'Z'))) 
321
 
        break;
322
 
    }
323
 
 
324
 
#ifdef SHADOWPW
325
 
  /* try to determine real password */
326
 
  if (n < 13 && sss == 0)
327
 
    {
328
 
      sss = getspnam(ppp->pw_name);
329
 
      if (sss)
330
 
        {
331
 
          if (spw)
332
 
            free(spw);
333
 
          ppp->pw_passwd = spw = SaveStr(sss->sp_pwdp);
334
 
          endspent();   /* this should delete all buffers ... */
335
 
          goto pw_try_again;
336
 
        }
337
 
      endspent();       /* this should delete all buffers ... */
338
 
    }
339
 
#endif
340
 
  if (n < 13)
341
 
    ppp->pw_passwd = 0;
342
 
#ifdef linux
343
 
  if (ppp->pw_passwd && strlen(ppp->pw_passwd) == 13 + 11)
344
 
    ppp->pw_passwd[13] = 0;     /* beware of linux's long passwords */
345
 
#endif
346
 
 
347
 
  return ppp;
348
 
}
349
 
 
350
 
static char *
351
 
locale_name(void)
352
 
{
353
 
  static char *s;
354
 
 
355
 
  if (!s)
356
 
    {
357
 
      s = getenv("LC_ALL");
358
 
      if (s == NULL)
359
 
        s = getenv("LC_CTYPE");
360
 
      if (s == NULL)
361
 
        s = getenv("LANG");
362
 
    }
363
 
  return s;
364
 
}
365
 
 
366
 
int
367
 
main(ac, av)
368
 
int ac;
369
 
char **av;
370
 
{
371
 
  register int n;
372
 
  char *ap;
373
 
  char *av0;
374
 
  char socknamebuf[2 * MAXSTR];
375
 
  int mflag = 0;
376
 
  char *myname = (ac == 0) ? "screen" : av[0];
377
 
  char *SockDir;
378
 
  struct stat st;
379
 
#ifdef _MODE_T                  /* (jw) */
380
 
  mode_t oumask;
381
 
#else
382
 
  int oumask;
383
 
#endif
384
 
#if defined(SYSV) && !defined(ISC)
385
 
  struct utsname utsnam;
386
 
#endif
387
 
  struct NewWindow nwin;
388
 
  int detached = 0;             /* start up detached */
389
 
#ifdef MULTIUSER
390
 
  char *sockp;
391
 
#endif
392
 
  char *sty = 0;
393
 
 
394
 
#if (defined(AUX) || defined(_AUX_SOURCE)) && defined(POSIX)
395
 
  setcompat(COMPAT_POSIX|COMPAT_BSDPROT); /* turn on seteuid support */
396
 
#endif
397
 
#if defined(sun) && defined(SVR4)
398
 
  {
399
 
    /* Solaris' login blocks SIGHUP! This is _very bad_ */
400
 
    sigset_t sset;
401
 
    sigemptyset(&sset);
402
 
    sigprocmask(SIG_SETMASK, &sset, 0);
403
 
  }
404
 
#endif
405
 
 
406
 
  /*
407
 
   *  First, close all unused descriptors
408
 
   *  (otherwise, we might have problems with the select() call)
409
 
   */
410
 
  closeallfiles(0);
411
 
#ifdef DEBUG
412
 
  opendebug(1, 0);
413
 
#endif
414
 
  snprintf(version, 59, "%d.%.2d.%.2d%s (%s%s) %s", REV, VERS,
415
 
          PATCHLEVEL, STATE, ORIGIN, GIT_REV, DATE);
416
 
  nversion = REV * 10000 + VERS * 100 + PATCHLEVEL;
417
 
  debug2("-- screen debug started %s (%s)\n", *av, version);
418
 
#ifdef POSIX
419
 
  debug("POSIX\n");
420
 
#endif
421
 
#ifdef TERMIO
422
 
  debug("TERMIO\n");
423
 
#endif
424
 
#ifdef SYSV
425
 
  debug("SYSV\n");
426
 
#endif
427
 
#ifdef SYSVSIGS
428
 
  debug("SYSVSIGS\n");
429
 
#endif
430
 
#ifdef NAMEDPIPE
431
 
  debug("NAMEDPIPE\n");
432
 
#endif
433
 
#if defined(SIGWINCH) && defined(TIOCGWINSZ)
434
 
  debug("Window size changing enabled\n");
435
 
#endif
436
 
#ifdef HAVE_SETREUID
437
 
  debug("SETREUID\n");
438
 
#endif
439
 
#ifdef HAVE_SETEUID
440
 
  debug("SETEUID\n");
441
 
#endif
442
 
#ifdef hpux
443
 
  debug("hpux\n");
444
 
#endif
445
 
#ifdef USEBCOPY
446
 
  debug("USEBCOPY\n");
447
 
#endif
448
 
#ifdef UTMPOK
449
 
  debug("UTMPOK\n");
450
 
#endif
451
 
#ifdef LOADAV
452
 
  debug("LOADAV\n");
453
 
#endif
454
 
#ifdef NETHACK
455
 
  debug("NETHACK\n");
456
 
#endif
457
 
#ifdef TERMINFO
458
 
  debug("TERMINFO\n");
459
 
#endif
460
 
#ifdef SHADOWPW
461
 
  debug("SHADOWPW\n");
462
 
#endif
463
 
#ifdef NAME_MAX
464
 
  debug1("NAME_MAX = %d\n", NAME_MAX);
465
 
#endif
466
 
 
467
 
  BellString = SaveStr("Bell in window %n");
468
 
  VisualBellString = SaveStr("   Wuff,  Wuff!!  ");
469
 
  ActivityString = SaveStr("Activity in window %n");
470
 
  screenlogfile = SaveStr("screenlog.%n");
471
 
  logtstamp_string = SaveStr("-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n");
472
 
  hstatusstring = SaveStr("%h");
473
 
  captionstring = SaveStr("%4n %t");
474
 
  timestring = SaveStr("%c:%s %M %d %H%? %l%?");
475
 
  wlisttit = SaveStr(" Num Name%=Flags");
476
 
  wliststr = SaveStr("%4n %t%=%f");
477
 
#ifdef COPY_PASTE
478
 
  BufferFile = SaveStr(DEFAULT_BUFFERFILE);
479
 
#endif
480
 
  ShellProg = NULL;
481
 
#ifdef POW_DETACH
482
 
  PowDetachString = 0;
483
 
#endif
484
 
  default_startup = (ac > 1) ? 0 : 1;
485
 
  adaptflag = 0;
486
 
  VBellWait = VBELLWAIT * 1000;
487
 
  MsgWait = MSGWAIT * 1000;
488
 
  MsgMinWait = MSGMINWAIT * 1000;
489
 
  SilenceWait = SILENCEWAIT;
490
 
#ifdef HAVE_BRAILLE
491
 
  InitBraille();
492
 
#endif
493
 
#ifdef ZMODEM
494
 
  zmodem_sendcmd = SaveStr("!!! sz -vv -b ");
495
 
  zmodem_recvcmd = SaveStr("!!! rz -vv -b -E");
496
 
#endif
497
 
 
498
 
#ifdef COPY_PASTE
499
 
  CompileKeys((char *)0, 0, mark_key_tab);
500
 
#endif
501
 
#ifdef UTF8
502
 
  InitBuiltinTabs();
503
 
  screenencodings = SaveStr(SCREENENCODINGS);
504
 
#endif
505
 
#ifdef DW_CHARS
506
 
  cjkwidth = 0;
507
 
#endif
508
 
  nwin = nwin_undef;
509
 
  nwin_options = nwin_undef;
510
 
  strcpy(screenterm, "screen");
511
 
#ifdef BUILTIN_TELNET
512
 
  af = AF_UNSPEC;
513
 
#endif
514
 
 
515
 
  logreopen_register(lf_secreopen);
516
 
 
517
 
  av0 = *av;
518
 
  /* if this is a login screen, assume -RR */
519
 
  if (*av0 == '-')
520
 
    {
521
 
      rflag = 4;
522
 
#ifdef MULTI
523
 
      xflag = 1;
524
 
#else
525
 
      dflag = 1;
526
 
#endif
527
 
      ShellProg = SaveStr(DefaultShell); /* to prevent nasty circles */
528
 
    }
529
 
  while (ac > 0)
530
 
    {
531
 
      ap = *++av;
532
 
      if (--ac > 0 && *ap == '-')
533
 
        {
534
 
          if (ap[1] == '-' && ap[2] == 0)
535
 
            {
536
 
              av++;
537
 
              ac--;
538
 
              break;
539
 
            }
540
 
          if (ap[1] == '-' && !strcmp(ap, "--version"))
541
 
            Panic(0, "Screen version %s", version);
542
 
          if (ap[1] == '-' && !strcmp(ap, "--help"))
543
 
            exit_with_usage(myname, NULL, NULL);
544
 
          while (ap && *ap && *++ap)
545
 
            {
546
 
              switch (*ap)
547
 
                {
548
 
#ifdef BUILTIN_TELNET
549
 
               case '4':
550
 
                 af = AF_INET;
551
 
                 break;
552
 
               case '6':
553
 
                 af = AF_INET6;
554
 
                 break;
555
 
#endif
556
 
                case 'a':
557
 
                  nwin_options.aflag = 1;
558
 
                  break;
559
 
                case 'A':
560
 
                  adaptflag = 1;
561
 
                  break;
562
 
                case 'p': /* preselect */
563
 
                  if (*++ap)
564
 
                    preselect = ap;
565
 
                  else
566
 
                    {
567
 
                      if (!--ac)
568
 
                        exit_with_usage(myname, "Specify a window to preselect with -p", NULL);
569
 
                      preselect = *++av;
570
 
                    }
571
 
                  ap = NULL;
572
 
                  break;
573
 
#ifdef HAVE_BRAILLE
574
 
                case 'B':
575
 
                  bd.bd_start_braille = 1;
576
 
                  break;
577
 
#endif
578
 
                case 'c':
579
 
                  if (*++ap)
580
 
                    RcFileName = ap;
581
 
                  else
582
 
                    {
583
 
                      if (--ac == 0)
584
 
                        exit_with_usage(myname, "Specify an alternate rc-filename with -c", NULL);
585
 
                      RcFileName = *++av;
586
 
                    }
587
 
                  ap = NULL;
588
 
                  break;
589
 
                case 'e':
590
 
                  if (!*++ap)
591
 
                    {
592
 
                      if (--ac == 0)
593
 
                        exit_with_usage(myname, "Specify command characters with -e", NULL);
594
 
                      ap = *++av;
595
 
                    }
596
 
                  if (ParseEscape(ap))
597
 
                    Panic(0, "Two characters are required with -e option, not '%s'.", ap);
598
 
                  ap = NULL;
599
 
                  break;
600
 
                case 'f':
601
 
                  ap++;
602
 
                  switch (*ap++)
603
 
                    {
604
 
                    case 'n':
605
 
                    case '0':
606
 
                      nwin_options.flowflag = FLOW_NOW * 0;
607
 
                      break;
608
 
                    case '\0':
609
 
                      ap--;
610
 
                      /* FALLTHROUGH */
611
 
                    case 'y':
612
 
                    case '1':
613
 
                      nwin_options.flowflag = FLOW_NOW * 1;
614
 
                      break;
615
 
                    case 'a':
616
 
                      nwin_options.flowflag = FLOW_AUTOFLAG;
617
 
                      break;
618
 
                    default:
619
 
                      exit_with_usage(myname, "Unknown flow option -%s", --ap);
620
 
                    }
621
 
                  break;
622
 
                case 'h':
623
 
                  if (--ac == 0)
624
 
                    exit_with_usage(myname, NULL, NULL);
625
 
                  nwin_options.histheight = atoi(*++av);
626
 
                  if (nwin_options.histheight < 0)
627
 
                    exit_with_usage(myname, "-h: %s: negative scrollback size?", *av);
628
 
                  break;
629
 
                case 'i':
630
 
                  iflag = 1;
631
 
                  break;
632
 
                case 't': /* title, the former AkA == -k */
633
 
                  if (--ac == 0)
634
 
                    exit_with_usage(myname, "Specify a new window-name with -t", NULL);
635
 
                  nwin_options.aka = *++av;
636
 
                  break;
637
 
                case 'l':
638
 
                  ap++;
639
 
                  switch (*ap++)
640
 
                    {
641
 
                    case 'n':
642
 
                    case '0':
643
 
                      nwin_options.lflag = 0;
644
 
                      break;
645
 
                    case '\0':
646
 
                      ap--;
647
 
                      /* FALLTHROUGH */
648
 
                    case 'y':
649
 
                    case '1':
650
 
                      nwin_options.lflag = 1;
651
 
                      break;
652
 
                    case 'a':
653
 
                      nwin_options.lflag = 3;
654
 
                      break;
655
 
                    case 's':   /* -ls */
656
 
                    case 'i':   /* -list */
657
 
                      lsflag = 1;
658
 
                      if (ac > 1 && !SockMatch)
659
 
                        {
660
 
                          SockMatch = *++av;
661
 
                          ac--;
662
 
                        }
663
 
                      ap = NULL;
664
 
                      break;
665
 
                    default:
666
 
                      exit_with_usage(myname, "%s: Unknown suboption to -l", --ap);
667
 
                    }
668
 
                  break;
669
 
                case 'w':
670
 
                  if (strcmp(ap+1, "ipe"))
671
 
                    exit_with_usage(myname, "Unknown option %s", --ap);
672
 
                  lsflag = 1;
673
 
                  wipeflag = 1;
674
 
                  if (ac > 1 && !SockMatch)
675
 
                    {
676
 
                      SockMatch = *++av;
677
 
                      ac--;
678
 
                    }
679
 
                  break;
680
 
                case 'L':
681
 
                  nwin_options.Lflag = 1;
682
 
                  break;
683
 
                case 'm':
684
 
                  mflag = 1;
685
 
                  break;
686
 
                case 'O':               /* to be (or not to be?) deleted. jw. */
687
 
                  force_vt = 0;
688
 
                  break;
689
 
                case 'T':
690
 
                  if (--ac == 0)
691
 
                    exit_with_usage(myname, "Specify terminal-type with -T", NULL);
692
 
                  if (strlen(*++av) < 20)
693
 
                    strcpy(screenterm, *av);
694
 
                  else
695
 
                    Panic(0, "-T: terminal name too long. (max. 20 char)");
696
 
                  nwin_options.term = screenterm;
697
 
                  break;
698
 
                case 'q':
699
 
                  quietflag = 1;
700
 
                  break;
701
 
                case 'Q':
702
 
                  queryflag = 1;
703
 
                  cmdflag = 1;
704
 
                  break;
705
 
                case 'r':
706
 
                case 'R':
707
 
#ifdef MULTI
708
 
                case 'x':
709
 
#endif
710
 
                  if (ac > 1 && *av[1] != '-' && !SockMatch)
711
 
                    {
712
 
                      SockMatch = *++av;
713
 
                      ac--;
714
 
                      debug2("rflag=%d, SockMatch=%s\n", dflag, SockMatch);
715
 
                    }
716
 
#ifdef MULTI
717
 
                  if (*ap == 'x')
718
 
                    xflag = 1;
719
 
#endif
720
 
                  if (rflag)
721
 
                    rflag = 2;
722
 
                  rflag += (*ap == 'R') ? 2 : 1;
723
 
                  break;
724
 
#ifdef REMOTE_DETACH
725
 
                case 'd':
726
 
                  dflag = 1;
727
 
                  /* FALLTHROUGH */
728
 
                case 'D':
729
 
                  if (!dflag)
730
 
                    dflag = 2;
731
 
                  if (ac == 2)
732
 
                    {
733
 
                      if (*av[1] != '-' && !SockMatch)
734
 
                        {
735
 
                          SockMatch = *++av;
736
 
                          ac--;
737
 
                          debug2("dflag=%d, SockMatch=%s\n", dflag, SockMatch);
738
 
                        }
739
 
                    }
740
 
                  break;
741
 
#endif
742
 
                case 's':
743
 
                  if (--ac == 0)
744
 
                    exit_with_usage(myname, "Specify shell with -s", NULL);
745
 
                  if (ShellProg)
746
 
                    free(ShellProg);
747
 
                  ShellProg = SaveStr(*++av);
748
 
                  debug1("ShellProg: '%s'\n", ShellProg);
749
 
                  break;
750
 
                case 'S':
751
 
                  if (!SockMatch)
752
 
                    {
753
 
                      if (--ac == 0)
754
 
                        exit_with_usage(myname, "Specify session-name with -S", NULL);
755
 
                      SockMatch = *++av;
756
 
                    }
757
 
                  if (!*SockMatch)
758
 
                    exit_with_usage(myname, "Empty session-name?", NULL);
759
 
                  break;
760
 
                case 'X':
761
 
                  cmdflag = 1;
762
 
                  break;
763
 
                case 'v':
764
 
                  Panic(0, "Screen version %s", version);
765
 
                  /* NOTREACHED */
766
 
#ifdef UTF8
767
 
                case 'U':
768
 
                  nwin_options.encoding = nwin_options.encoding == -1 ? UTF8 : 0;
769
 
                  break;
770
 
#endif
771
 
                default:
772
 
                  exit_with_usage(myname, "Unknown option %s", --ap);
773
 
                }
774
 
            }
775
 
        }
776
 
      else
777
 
        break;
778
 
    }
779
 
 
780
 
  real_uid = getuid();
781
 
  real_gid = getgid();
782
 
  eff_uid = geteuid();
783
 
  eff_gid = getegid();
784
 
 
785
 
#ifdef SIGBUS /* OOPS, linux has no bus errors! */
786
 
  signal(SIGBUS, CoreDump);
787
 
#endif /* SIGBUS */
788
 
  signal(SIGSEGV, CoreDump);
789
 
 
790
 
 
791
 
#ifdef USE_LOCALE
792
 
  setlocale(LC_ALL, "");
793
 
#endif
794
 
#ifdef ENCODINGS
795
 
  if (nwin_options.encoding == -1)
796
 
    {
797
 
      /* ask locale if we should start in UTF-8 mode */
798
 
# ifdef HAVE_NL_LANGINFO
799
 
#  ifndef USE_LOCALE
800
 
      setlocale(LC_CTYPE, "");
801
 
#  endif
802
 
      nwin_options.encoding = FindEncoding(nl_langinfo(CODESET));
803
 
      debug1("locale says encoding = %d\n", nwin_options.encoding);
804
 
# else
805
 
#  ifdef UTF8
806
 
      char *s;
807
 
      if ((s = locale_name()) && InStr(s, "UTF-8"))
808
 
        nwin_options.encoding = UTF8;
809
 
#  endif
810
 
      debug1("environment says encoding=%d\n", nwin_options.encoding);
811
 
#endif
812
 
    }
813
 
# ifdef DW_CHARS
814
 
  {
815
 
    char *s;
816
 
    if ((s = locale_name()))
817
 
    {
818
 
      if(!strncmp(s, "zh_", 3) || !strncmp(s, "ja_", 3) || !strncmp(s, "ko_", 3))
819
 
      {
820
 
        cjkwidth = 1;
821
 
      }
822
 
    }
823
 
  }
824
 
#endif
825
 
#endif
826
 
  if (nwin_options.aka)
827
 
    {
828
 
#ifdef ENCODINGS
829
 
      if (nwin_options.encoding > 0)
830
 
        {
831
 
          size_t len = strlen(nwin_options.aka);
832
 
          size_t newsz;
833
 
          char *newbuf = malloc(3 * len);
834
 
          if (!newbuf)
835
 
            Panic(0, "%s", strnomem);
836
 
          newsz = RecodeBuf((unsigned char *)nwin_options.aka, len,
837
 
                            nwin_options.encoding, 0, (unsigned char *)newbuf);
838
 
          newbuf[newsz] = '\0';
839
 
          nwin_options.aka = newbuf;
840
 
        }
841
 
      else
842
 
#endif
843
 
        {
844
 
          /* If we just use the original value from av,
845
 
             subsequent shelltitle invocations will attempt to free
846
 
             space we don't own... */
847
 
          nwin_options.aka = SaveStr(nwin_options.aka);
848
 
        }
849
 
    }
850
 
  
851
 
  if (SockMatch && strlen(SockMatch) >= MAXSTR)
852
 
    Panic(0, "Ridiculously long socketname - try again.");
853
 
  if (cmdflag && !rflag && !dflag && !xflag)
854
 
    xflag = 1;
855
 
  if (!cmdflag && dflag && mflag && !(rflag || xflag))
856
 
    detached = 1;
857
 
  nwin = nwin_options;
858
 
#ifdef ENCODINGS
859
 
  nwin.encoding = nwin_undef.encoding;  /* let screenrc overwrite it */
860
 
#endif
861
 
  if (ac)
862
 
    nwin.args = av;
863
 
 
864
 
  /* make the write() calls return -1 on all errors */
865
 
#ifdef SIGXFSZ
866
 
  /*
867
 
   * Ronald F. Guilmette, Oct 29 '94, bug-gnu-utils@prep.ai.mit.edu:
868
 
   * It appears that in System V Release 4, UNIX, if you are writing
869
 
   * an output file and you exceed the currently set file size limit,
870
 
   * you _don't_ just get the call to `write' returning with a
871
 
   * failure code.  Rather, you get a signal called `SIGXFSZ' which,
872
 
   * if neither handled nor ignored, will cause your program to crash
873
 
   * with a core dump.
874
 
   */
875
 
  signal(SIGXFSZ, SIG_IGN);
876
 
#endif /* SIGXFSZ */
877
 
 
878
 
#ifdef SIGPIPE
879
 
  signal(SIGPIPE, SIG_IGN);
880
 
#endif
881
 
 
882
 
  if (!ShellProg)
883
 
    {
884
 
      register char *sh;
885
 
 
886
 
      sh = getenv("SHELL");
887
 
      ShellProg = SaveStr(sh ? sh : DefaultShell);
888
 
    }
889
 
  ShellArgs[0] = ShellProg;
890
 
  home = getenv("HOME");
891
 
  if (!mflag && !SockMatch)
892
 
    {
893
 
      sty = getenv("STY");
894
 
      if (sty && *sty == 0)
895
 
        sty = 0;
896
 
    }
897
 
 
898
 
#ifdef NETHACK
899
 
  if (!(nethackflag = (getenv("NETHACKOPTIONS") != NULL)))
900
 
    {
901
 
      char nethackrc[MAXPATHLEN];
902
 
 
903
 
      if (home && (strlen(home) < (MAXPATHLEN - 20)))
904
 
        {
905
 
          sprintf(nethackrc,"%s/.nethackrc", home);
906
 
          nethackflag = !access(nethackrc, F_OK);
907
 
        }
908
 
    }
909
 
#endif
910
 
 
911
 
#ifdef MULTIUSER
912
 
  own_uid = multi_uid = real_uid;
913
 
  if (SockMatch && (sockp = index(SockMatch, '/')))
914
 
    {
915
 
      *sockp = 0;
916
 
      multi = SockMatch;
917
 
      SockMatch = sockp + 1;
918
 
      if (*multi)
919
 
        {
920
 
          struct passwd *mppp;
921
 
          if ((mppp = getpwnam(multi)) == (struct passwd *)0)
922
 
            Panic(0, "Cannot identify account '%s'.", multi);
923
 
          multi_uid = mppp->pw_uid;
924
 
          multi_home = SaveStr(mppp->pw_dir);
925
 
          if (strlen(multi_home) > MAXPATHLEN - 10)
926
 
            Panic(0, "home directory path too long");
927
 
# ifdef MULTI
928
 
          /* always fake multi attach mode */
929
 
          if (rflag || lsflag)
930
 
            xflag = 1;
931
 
# endif /* MULTI */
932
 
          detached = 0;
933
 
          multiattach = 1;
934
 
        }
935
 
      /* Special case: effective user is multiuser. */
936
 
      if (eff_uid && (multi_uid != eff_uid))
937
 
        Panic(0, "Must run suid root for multiuser support.");
938
 
    }
939
 
  if (SockMatch && *SockMatch == 0)
940
 
    SockMatch = 0;
941
 
#endif /* MULTIUSER */
942
 
 
943
 
  if ((LoginName = getlogin()) && LoginName[0] != '\0')
944
 
    {
945
 
      if ((ppp = getpwnam(LoginName)) != (struct passwd *) 0)
946
 
        if ((int)ppp->pw_uid != real_uid)
947
 
          ppp = (struct passwd *) 0;
948
 
    }
949
 
  if (ppp == 0)
950
 
    {
951
 
      if ((ppp = getpwuid(real_uid)) == 0)
952
 
        {
953
 
          Panic(0, "getpwuid() can't identify your account!");
954
 
          exit(1);
955
 
        }
956
 
      LoginName = ppp->pw_name;
957
 
    }
958
 
  LoginName = SaveStr(LoginName);
959
 
 
960
 
  ppp = getpwbyname(LoginName, ppp);
961
 
 
962
 
#if !defined(SOCKDIR) && defined(MULTIUSER)
963
 
  if (multi && !multiattach)
964
 
    {
965
 
      if (home && strcmp(home, ppp->pw_dir))
966
 
        Panic(0, "$HOME must match passwd entry for multiuser screens.");
967
 
    }
968
 
#endif
969
 
 
970
 
#define SET_GUID() do \
971
 
  { \
972
 
    setgid(real_gid); \
973
 
    setuid(real_uid); \
974
 
    eff_uid = real_uid; \
975
 
    eff_gid = real_gid; \
976
 
  } while (0)
977
 
 
978
 
#define SET_TTYNAME(fatal) do \
979
 
  { \
980
 
    if (!(attach_tty = ttyname(0))) \
981
 
      { \
982
 
        if (fatal) \
983
 
          Panic(0, "Must be connected to a terminal."); \
984
 
        else \
985
 
          attach_tty = ""; \
986
 
      } \
987
 
    else \
988
 
      { \
989
 
        if (stat(attach_tty, &st)) \
990
 
          Panic(errno, "Cannot access '%s'", attach_tty); \
991
 
        if (CheckTtyname(attach_tty)) \
992
 
          Panic(0, "Bad tty '%s'", attach_tty); \
993
 
      } \
994
 
    if (strlen(attach_tty) >= MAXPATHLEN) \
995
 
      Panic(0, "TtyName too long - sorry."); \
996
 
  } while (0)
997
 
 
998
 
  if (home == 0 || *home == '\0')
999
 
    home = ppp->pw_dir;
1000
 
  if (strlen(LoginName) > MAXLOGINLEN)
1001
 
    Panic(0, "LoginName too long - sorry.");
1002
 
#ifdef MULTIUSER
1003
 
  if (multi && strlen(multi) > MAXLOGINLEN)
1004
 
    Panic(0, "Screen owner name too long - sorry.");
1005
 
#endif
1006
 
  if (strlen(home) > MAXPATHLEN - 25)
1007
 
    Panic(0, "$HOME too long - sorry.");
1008
 
 
1009
 
  attach_tty = "";
1010
 
  if (!detached && !lsflag && !cmdflag && !(dflag && !mflag && !rflag && !xflag) && !(sty && !SockMatch && !mflag && !rflag && !xflag))
1011
 
    {
1012
 
#ifndef NAMEDPIPE
1013
 
      int fl;
1014
 
#endif
1015
 
 
1016
 
      /* ttyname implies isatty */
1017
 
      SET_TTYNAME(1);
1018
 
#ifdef MULTIUSER
1019
 
      tty_mode = (int)st.st_mode & 0777;
1020
 
#endif
1021
 
 
1022
 
#ifndef NAMEDPIPE
1023
 
      fl = fcntl(0, F_GETFL, 0);
1024
 
      if (fl != -1 && (fl & (O_RDWR|O_RDONLY|O_WRONLY)) == O_RDWR)
1025
 
        attach_fd = 0;
1026
 
#endif
1027
 
      if (attach_fd == -1)
1028
 
        {
1029
 
          if ((n = secopen(attach_tty, O_RDWR | O_NONBLOCK, 0)) < 0)
1030
 
            Panic(0, "Cannot open your terminal '%s' - please check.", attach_tty);
1031
 
          close(n);
1032
 
        }
1033
 
      debug2("attach_tty is %s, attach_fd is %d\n", attach_tty, attach_fd);
1034
 
 
1035
 
      if ((attach_term = getenv("TERM")) == 0 || *attach_term == 0)
1036
 
        Panic(0, "Please set a terminal type.");
1037
 
      if (strlen(attach_term) > sizeof(D_termname) - 1)
1038
 
        Panic(0, "$TERM too long - sorry.");
1039
 
      GetTTY(0, &attach_Mode);
1040
 
#ifdef DEBUGGGGGGGGGGGGGGG
1041
 
      DebugTTY(&attach_Mode);
1042
 
#endif /* DEBUG */
1043
 
    }
1044
 
 
1045
 
#ifdef _MODE_T
1046
 
  oumask = umask(0);            /* well, unsigned never fails? jw. */
1047
 
#else
1048
 
  if ((oumask = (int)umask(0)) == -1)
1049
 
    Panic(errno, "Cannot change umask to zero");
1050
 
#endif
1051
 
  SockDir = getenv("SCREENDIR");
1052
 
  if (SockDir)
1053
 
    {
1054
 
      if (strlen(SockDir) >= MAXPATHLEN - 1)
1055
 
        Panic(0, "Ridiculously long $SCREENDIR - try again.");
1056
 
#ifdef MULTIUSER
1057
 
      if (multi)
1058
 
        Panic(0, "No $SCREENDIR with multi screens, please.");
1059
 
#endif
1060
 
    }
1061
 
#ifdef MULTIUSER
1062
 
  if (multiattach)
1063
 
    {
1064
 
# ifndef SOCKDIR
1065
 
      sprintf(SockPath, "%s/.screen", multi_home);
1066
 
      SockDir = SockPath;
1067
 
# else
1068
 
      SockDir = SOCKDIR;
1069
 
      sprintf(SockPath, "%s/S-%s", SockDir, multi);
1070
 
# endif
1071
 
    }
1072
 
  else
1073
 
#endif
1074
 
    {
1075
 
#ifndef SOCKDIR
1076
 
      if (SockDir == 0)
1077
 
        {
1078
 
          sprintf(SockPath, "%s/.screen", home);
1079
 
          SockDir = SockPath;
1080
 
        }
1081
 
#endif
1082
 
      if (SockDir)
1083
 
        {
1084
 
          if (access(SockDir, F_OK))
1085
 
            {
1086
 
              debug1("SockDir '%s' missing ...\n", SockDir);
1087
 
              if (UserContext() > 0)
1088
 
                {
1089
 
                  if (mkdir(SockDir, 0700))
1090
 
                    UserReturn(0);
1091
 
                  UserReturn(1);
1092
 
                }
1093
 
              if (UserStatus() <= 0)
1094
 
                Panic(0, "Cannot make directory '%s'.", SockDir);
1095
 
            }
1096
 
          if (SockDir != SockPath)
1097
 
            strcpy(SockPath, SockDir);
1098
 
        }
1099
 
#ifdef SOCKDIR
1100
 
      else
1101
 
        {
1102
 
          SockDir = SOCKDIR;
1103
 
          if (stat(SockDir, &st))
1104
 
            {
1105
 
              n = (eff_uid == 0 && (real_uid || eff_gid == real_gid)) ? 0755 :
1106
 
                  (eff_gid != real_gid) ? 0775 :
1107
 
#ifdef S_ISVTX
1108
 
                  0777|S_ISVTX;
1109
 
#else
1110
 
                  0777;
1111
 
#endif
1112
 
              if (mkdir(SockDir, n) == -1)
1113
 
                Panic(errno, "Cannot make directory '%s'", SockDir);
1114
 
            }
1115
 
          else
1116
 
            {
1117
 
              if (!S_ISDIR(st.st_mode))
1118
 
                Panic(0, "'%s' must be a directory.", SockDir);
1119
 
              if (eff_uid == 0 && real_uid && (int)st.st_uid != eff_uid)
1120
 
                Panic(0, "Directory '%s' must be owned by root.", SockDir);
1121
 
              n = (eff_uid == 0 && (real_uid || (st.st_mode & 0775) != 0775)) ? 0755 :
1122
 
                  (eff_gid == (int)st.st_gid && eff_gid != real_gid) ? 0775 :
1123
 
                  0777;
1124
 
              if (((int)st.st_mode & 0777) != n)
1125
 
                Panic(0, "Directory '%s' must have mode %03o.", SockDir, n);
1126
 
            }
1127
 
          sprintf(SockPath, "%s/S-%s", SockDir, LoginName);
1128
 
          if (access(SockPath, F_OK))
1129
 
            {
1130
 
              if (mkdir(SockPath, 0700) == -1 && errno != EEXIST)
1131
 
                Panic(errno, "Cannot make directory '%s'", SockPath);
1132
 
              (void) chown(SockPath, real_uid, real_gid);
1133
 
            }
1134
 
        }
1135
 
#endif
1136
 
    }
1137
 
 
1138
 
  if (stat(SockPath, &st) == -1)
1139
 
    Panic(errno, "Cannot access %s", SockPath);
1140
 
  else
1141
 
  if (!S_ISDIR(st.st_mode))
1142
 
    Panic(0, "%s is not a directory.", SockPath);
1143
 
#ifdef MULTIUSER
1144
 
  if (multi)
1145
 
    {
1146
 
      if ((int)st.st_uid != multi_uid)
1147
 
        Panic(0, "%s is not the owner of %s.", multi, SockPath);
1148
 
    }
1149
 
  else
1150
 
#endif
1151
 
    {
1152
 
      if ((int)st.st_uid != real_uid)
1153
 
        Panic(0, "You are not the owner of %s.", SockPath);
1154
 
    }
1155
 
  if ((st.st_mode & 0777) != 0700)
1156
 
    Panic(0, "Directory %s must have mode 700.", SockPath);
1157
 
  if (SockMatch && index(SockMatch, '/'))
1158
 
    Panic(0, "Bad session name '%s'", SockMatch);
1159
 
  SockName = SockPath + strlen(SockPath) + 1;
1160
 
  *SockName = 0;
1161
 
  (void) umask(oumask);
1162
 
  debug2("SockPath: %s  SockMatch: %s\n", SockPath, SockMatch ? SockMatch : "NULL");
1163
 
 
1164
 
#if defined(SYSV) && !defined(ISC)
1165
 
  if (uname(&utsnam) == -1)
1166
 
    Panic(errno, "uname");
1167
 
  strncpy(HostName, utsnam.nodename, sizeof(utsnam.nodename) < MAXSTR ? sizeof(utsnam.nodename) : MAXSTR - 1);
1168
 
  HostName[sizeof(utsnam.nodename) < MAXSTR ? sizeof(utsnam.nodename) : MAXSTR - 1] = '\0';
1169
 
#else
1170
 
  (void) gethostname(HostName, MAXSTR);
1171
 
  HostName[MAXSTR - 1] = '\0';
1172
 
#endif
1173
 
  if ((ap = index(HostName, '.')) != NULL)
1174
 
    *ap = '\0';
1175
 
 
1176
 
  if (lsflag)
1177
 
    {
1178
 
      int i, fo, oth;
1179
 
 
1180
 
#ifdef MULTIUSER
1181
 
      if (multi)
1182
 
        real_uid = multi_uid;
1183
 
#endif
1184
 
      SET_GUID();
1185
 
      i = FindSocket((int *)NULL, &fo, &oth, SockMatch);
1186
 
      if (quietflag) {
1187
 
        if (rflag)
1188
 
          exit(10 + i);
1189
 
        else
1190
 
          exit(9 + (fo || oth ? 1 : 0) + fo);
1191
 
      }
1192
 
      if (fo == 0)
1193
 
        Panic(0, "No Sockets found in %s.\n", SockPath);
1194
 
      Panic(0, "%d Socket%s in %s.\n", fo, fo > 1 ? "s" : "", SockPath);
1195
 
      /* NOTREACHED */
1196
 
    }
1197
 
  signal(SIG_BYE, AttacherFinit);       /* prevent races */
1198
 
  if (cmdflag)
1199
 
    {
1200
 
      /* attach_tty is not mandatory */
1201
 
      SET_TTYNAME(0);
1202
 
      if (!*av)
1203
 
        Panic(0, "Please specify a command.");
1204
 
      SET_GUID();
1205
 
      SendCmdMessage(sty, SockMatch, av, queryflag >= 0);
1206
 
      exit(0);
1207
 
    }
1208
 
  else if (rflag || xflag)
1209
 
    {
1210
 
      debug("screen -r: - is there anybody out there?\n");
1211
 
      if (Attach(MSG_ATTACH))
1212
 
        {
1213
 
          Attacher();
1214
 
          /* NOTREACHED */
1215
 
        }
1216
 
#ifdef MULTIUSER
1217
 
      if (multiattach)
1218
 
        Panic(0, "Can't create sessions of other users.");
1219
 
#endif
1220
 
      debug("screen -r: backend not responding -- still crying\n");
1221
 
    }
1222
 
  else if (dflag && !mflag)
1223
 
    {
1224
 
      SET_TTYNAME(0);
1225
 
      Attach(MSG_DETACH);
1226
 
      Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : ""));
1227
 
      eexit(0);
1228
 
      /* NOTREACHED */
1229
 
    }
1230
 
  if (!SockMatch && !mflag && sty)
1231
 
    {
1232
 
      /* attach_tty is not mandatory */
1233
 
      SET_TTYNAME(0);
1234
 
      SET_GUID();
1235
 
      nwin_options.args = av;
1236
 
      SendCreateMsg(sty, &nwin);
1237
 
      exit(0);
1238
 
      /* NOTREACHED */
1239
 
    }
1240
 
  nwin_compose(&nwin_default, &nwin_options, &nwin_default);
1241
 
 
1242
 
  if (!detached || dflag != 2)
1243
 
    MasterPid = fork();
1244
 
  else
1245
 
    MasterPid = 0;
1246
 
 
1247
 
  switch (MasterPid)
1248
 
    {
1249
 
    case -1:
1250
 
      Panic(errno, "fork");
1251
 
      /* NOTREACHED */
1252
 
    case 0:
1253
 
      break;
1254
 
    default:
1255
 
      if (detached)
1256
 
        exit(0);
1257
 
      if (SockMatch)
1258
 
        sprintf(socknamebuf, "%d.%s", MasterPid, SockMatch);
1259
 
      else
1260
 
        sprintf(socknamebuf, "%d.%s.%s", MasterPid, stripdev(attach_tty), HostName);
1261
 
      for (ap = socknamebuf; *ap; ap++)
1262
 
        if (*ap == '/')
1263
 
          *ap = '-';
1264
 
#ifdef NAME_MAX
1265
 
      if (strlen(socknamebuf) > NAME_MAX)
1266
 
        socknamebuf[NAME_MAX] = 0;
1267
 
#endif
1268
 
      sprintf(SockPath + strlen(SockPath), "/%s", socknamebuf);
1269
 
      SET_GUID();
1270
 
      Attacher();
1271
 
      /* NOTREACHED */
1272
 
    }
1273
 
 
1274
 
  if (!detached)
1275
 
    PanicPid = getppid();
1276
 
 
1277
 
  if (DefaultEsc == -1)
1278
 
    DefaultEsc = Ctrl('a');
1279
 
  if (DefaultMetaEsc == -1)
1280
 
    DefaultMetaEsc = 'a';
1281
 
 
1282
 
  ap = av0 + strlen(av0) - 1;
1283
 
  while (ap >= av0)
1284
 
    {
1285
 
      if (!strncmp("screen", ap, 6))
1286
 
        {
1287
 
          strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */
1288
 
          break;
1289
 
        }
1290
 
      ap--;
1291
 
    }
1292
 
  if (ap < av0)
1293
 
    *av0 = 'S';
1294
 
 
1295
 
#ifdef DEBUG
1296
 
  {
1297
 
    char buf[256];
1298
 
 
1299
 
    if (dfp && dfp != stderr)
1300
 
      fclose(dfp);
1301
 
    sprintf(buf, "%s/SCREEN.%d", DEBUGDIR, (int)getpid());
1302
 
    if ((dfp = fopen(buf, "w")) == NULL)
1303
 
      dfp = stderr;
1304
 
    else
1305
 
      (void) chmod(buf, 0666);
1306
 
  }
1307
 
#endif
1308
 
  if (!detached)
1309
 
    {
1310
 
      if (attach_fd == -1)
1311
 
        {
1312
 
          if ((n = secopen(attach_tty, O_RDWR, 0)) < 0)
1313
 
            Panic(0, "Cannot reopen '%s' - please check.", attach_tty);
1314
 
        }
1315
 
      else
1316
 
        n = dup(attach_fd);
1317
 
    }
1318
 
  else
1319
 
    n = -1;
1320
 
  freopen("/dev/null", "r", stdin);
1321
 
  freopen("/dev/null", "w", stdout);
1322
 
 
1323
 
#ifdef DEBUG
1324
 
  if (dfp != stderr)
1325
 
#endif
1326
 
  freopen("/dev/null", "w", stderr);
1327
 
  debug("-- screen.back debug started\n");
1328
 
 
1329
 
  /* 
1330
 
   * This guarantees that the session owner is listed, even when we
1331
 
   * start detached. From now on we should not refer to 'LoginName'
1332
 
   * any more, use users->u_name instead.
1333
 
   */
1334
 
  if (UserAdd(LoginName, (char *)0, (struct acluser **)0) < 0)
1335
 
    Panic(0, "Could not create user info");
1336
 
  if (!detached)
1337
 
    {
1338
 
      if (MakeDisplay(LoginName, attach_tty, attach_term, n, getppid(), &attach_Mode) == 0)
1339
 
        Panic(0, "Could not alloc display");
1340
 
      PanicPid = 0;
1341
 
#ifdef ENCODINGS
1342
 
      D_encoding = nwin_options.encoding > 0 ? nwin_options.encoding : 0;
1343
 
      debug1("D_encoding = %d\n", D_encoding);
1344
 
#endif
1345
 
    }
1346
 
 
1347
 
  if (SockMatch)
1348
 
    {
1349
 
      /* user started us with -S option */
1350
 
      sprintf(socknamebuf, "%d.%s", (int)getpid(), SockMatch);
1351
 
    }
1352
 
  else
1353
 
    {
1354
 
      sprintf(socknamebuf, "%d.%s.%s", (int)getpid(), stripdev(attach_tty),
1355
 
              HostName);
1356
 
    }
1357
 
  for (ap = socknamebuf; *ap; ap++)
1358
 
    if (*ap == '/')
1359
 
      *ap = '-';
1360
 
#ifdef NAME_MAX
1361
 
  if (strlen(socknamebuf) > NAME_MAX)
1362
 
    {
1363
 
      debug2("Socketname %s truncated to %d chars\n", socknamebuf, NAME_MAX);
1364
 
      socknamebuf[NAME_MAX] = 0;
1365
 
    }
1366
 
#endif
1367
 
  sprintf(SockPath + strlen(SockPath), "/%s", socknamebuf);
1368
 
  
1369
 
  ServerSocket = MakeServerSocket();
1370
 
  InitKeytab();
1371
 
#ifdef ETCSCREENRC
1372
 
# ifdef ALLOW_SYSSCREENRC
1373
 
  if ((ap = getenv("SYSSCREENRC")))
1374
 
    (void)StartRc(ap, 0);
1375
 
  else
1376
 
# endif
1377
 
    (void)StartRc(ETCSCREENRC, 0);
1378
 
#endif
1379
 
  (void)StartRc(RcFileName, 0);
1380
 
# ifdef UTMPOK
1381
 
#  ifndef UTNOKEEP
1382
 
  InitUtmp(); 
1383
 
#  endif /* UTNOKEEP */
1384
 
# endif /* UTMPOK */
1385
 
  if (display)
1386
 
    {
1387
 
      if (InitTermcap(0, 0))
1388
 
        {
1389
 
          debug("Could not init termcap - exiting\n");
1390
 
          fcntl(D_userfd, F_SETFL, 0);  /* Flush sets FNBLOCK */
1391
 
          freetty();
1392
 
          if (D_userpid)
1393
 
            Kill(D_userpid, SIG_BYE);
1394
 
          eexit(1);
1395
 
        }
1396
 
      MakeDefaultCanvas();
1397
 
      InitTerm(0);
1398
 
#ifdef UTMPOK
1399
 
      RemoveLoginSlot();
1400
 
#endif
1401
 
    }
1402
 
  else
1403
 
    MakeTermcap(1);
1404
 
#ifdef LOADAV
1405
 
  InitLoadav();
1406
 
#endif /* LOADAV */
1407
 
  MakeNewEnv();
1408
 
  signal(SIGHUP, SigHup);
1409
 
  signal(SIGINT, FinitHandler);
1410
 
  signal(SIGQUIT, FinitHandler);
1411
 
  signal(SIGTERM, FinitHandler);
1412
 
#ifdef BSDJOBS
1413
 
  signal(SIGTTIN, SIG_IGN);
1414
 
  signal(SIGTTOU, SIG_IGN);
1415
 
#endif
1416
 
 
1417
 
  if (display)
1418
 
    {
1419
 
      brktty(D_userfd);
1420
 
      SetMode(&D_OldMode, &D_NewMode, D_flow, iflag);
1421
 
      /* Note: SetMode must be called _before_ FinishRc. */
1422
 
      SetTTY(D_userfd, &D_NewMode);
1423
 
      if (fcntl(D_userfd, F_SETFL, FNBLOCK))
1424
 
        Msg(errno, "Warning: NBLOCK fcntl failed");
1425
 
    }
1426
 
  else
1427
 
    brktty(-1);         /* just try */
1428
 
  signal(SIGCHLD, SigChld);
1429
 
#ifdef ETCSCREENRC
1430
 
# ifdef ALLOW_SYSSCREENRC
1431
 
  if ((ap = getenv("SYSSCREENRC")))
1432
 
    FinishRc(ap);
1433
 
  else
1434
 
# endif
1435
 
    FinishRc(ETCSCREENRC);
1436
 
#endif
1437
 
  FinishRc(RcFileName);
1438
 
 
1439
 
  debug2("UID %d  EUID %d\n", (int)getuid(), (int)geteuid());
1440
 
  if (windows == NULL)
1441
 
    {
1442
 
      debug("We open one default window, as screenrc did not specify one.\n");
1443
 
      if (MakeWindow(&nwin) == -1)
1444
 
        {
1445
 
          fd_set rfd;
1446
 
          struct timeval tv = { MsgWait/1000, 1000*(MsgWait%1000) };
1447
 
          FD_SET(0, &rfd);
1448
 
 
1449
 
          Msg(0, "Sorry, could not find a PTY or TTY.");
1450
 
          // allow user to exit early by pressing any key.
1451
 
          select(1, &rfd, NULL, NULL, &tv);
1452
 
          Finit(0);
1453
 
          /* NOTREACHED */
1454
 
        }
1455
 
    }
1456
 
  else if (ac) /* Screen was invoked with a command */
1457
 
    {
1458
 
      MakeWindow(&nwin);
1459
 
    }
1460
 
 
1461
 
#ifdef HAVE_BRAILLE
1462
 
  StartBraille();
1463
 
#endif
1464
 
  
1465
 
  if (display && default_startup)
1466
 
    display_copyright();
1467
 
  signal(SIGINT, SigInt);
1468
 
  if (rflag && (rflag & 1) == 0 && !quietflag)
1469
 
    {
1470
 
      Msg(0, "New screen...");
1471
 
      rflag = 0;
1472
 
    }
1473
 
 
1474
 
  serv_read.type = EV_READ;
1475
 
  serv_read.fd = ServerSocket;
1476
 
  serv_read.handler = serv_read_fn;
1477
 
  evenq(&serv_read);
1478
 
 
1479
 
  serv_select.pri = -10;
1480
 
  serv_select.type = EV_ALWAYS;
1481
 
  serv_select.handler = serv_select_fn;
1482
 
  evenq(&serv_select);
1483
 
 
1484
 
  logflushev.type = EV_TIMEOUT;
1485
 
  logflushev.handler = logflush_fn;
1486
 
 
1487
 
  sched();
1488
 
  /* NOTREACHED */
1489
 
  return 0;
1490
 
}
1491
 
 
1492
 
void
1493
 
WindowDied(p, wstat, wstat_valid)
1494
 
struct win *p;
1495
 
#ifdef BSDWAIT
1496
 
  union wait wstat;
1497
 
#else
1498
 
  int wstat;
1499
 
#endif
1500
 
int wstat_valid;
1501
 
{
1502
 
  int killit = 0;
1503
 
 
1504
 
  if (p->w_destroyev.data == (char *)p)
1505
 
    {
1506
 
      wstat = p->w_exitstatus;
1507
 
      wstat_valid = 1;
1508
 
      evdeq(&p->w_destroyev);
1509
 
      p->w_destroyev.data = 0;
1510
 
    }
1511
 
 
1512
 
#if defined(BSDJOBS) && !defined(BSDWAIT)
1513
 
  if (!wstat_valid && p->w_pid > 0)
1514
 
    {
1515
 
      /* EOF on file descriptor. The process is probably also dead.
1516
 
       * try a waitpid */
1517
 
      if (waitpid(p->w_pid, &wstat, WNOHANG | WUNTRACED) == p->w_pid)
1518
 
        {
1519
 
          p->w_pid = 0;
1520
 
          wstat_valid = 1;
1521
 
        }
1522
 
    }
1523
 
#endif
1524
 
  if (ZombieKey_destroy && ZombieKey_onerror && wstat_valid &&
1525
 
      WIFEXITED(wstat) && WEXITSTATUS(wstat) == 0)
1526
 
        killit = 1;
1527
 
 
1528
 
  if (ZombieKey_destroy && !killit)
1529
 
    {
1530
 
      char buf[100], *s, reason[100];
1531
 
      time_t now;
1532
 
 
1533
 
      if (wstat_valid) {
1534
 
        if (WIFEXITED(wstat))
1535
 
          if (WEXITSTATUS(wstat))
1536
 
            sprintf(reason, "terminated with exit status %d", WEXITSTATUS(wstat));
1537
 
          else
1538
 
            sprintf(reason, "terminated normally");
1539
 
        else if (WIFSIGNALED(wstat))
1540
 
          sprintf(reason, "terminated with signal %d%s", WTERMSIG(wstat),
1541
 
#ifdef WCOREDUMP
1542
 
                          WCOREDUMP(wstat) ? " (core file generated)" : "");
1543
 
#else
1544
 
                          "");
1545
 
#endif
1546
 
      } else
1547
 
        sprintf(reason, "detached from window");
1548
 
 
1549
 
      (void) time(&now);
1550
 
      s = ctime(&now);
1551
 
      if (s && *s)
1552
 
        s[strlen(s) - 1] = '\0';
1553
 
      debug3("window %d (%s) going into zombie state fd %d",
1554
 
             p->w_number, p->w_title, p->w_ptyfd);
1555
 
#ifdef UTMPOK
1556
 
      if (p->w_slot != (slot_t)0 && p->w_slot != (slot_t)-1)
1557
 
        {
1558
 
          RemoveUtmp(p);
1559
 
          p->w_slot = 0;        /* "detached" */
1560
 
        }
1561
 
#endif
1562
 
      CloseDevice(p);
1563
 
 
1564
 
      p->w_deadpid = p->w_pid;
1565
 
      p->w_pid = 0;
1566
 
      ResetWindow(p);
1567
 
      /* p->w_y = p->w_bot; */
1568
 
      p->w_y = MFindUsedLine(p, p->w_bot, 1);
1569
 
      sprintf(buf, "\n\r=== Command %s (%s) ===", reason, s ? s : "?");
1570
 
      WriteString(p, buf, strlen(buf));
1571
 
      WindowChanged(p, 'f');
1572
 
    }
1573
 
  else
1574
 
    KillWindow(p);
1575
 
#ifdef UTMPOK
1576
 
  CarefulUtmp();
1577
 
#endif
1578
 
}
1579
 
 
1580
 
static void
1581
 
SigChldHandler()
1582
 
{
1583
 
  struct stat st;
1584
 
#ifdef DEBUG
1585
 
  fds();
1586
 
#endif
1587
 
  while (GotSigChld)
1588
 
    {
1589
 
      GotSigChld = 0;
1590
 
      DoWait();
1591
 
#ifdef SYSVSIGS
1592
 
      signal(SIGCHLD, SigChld);
1593
 
#endif
1594
 
    }
1595
 
  if (stat(SockPath, &st) == -1)
1596
 
    {
1597
 
      debug1("SigChldHandler: Yuck! cannot stat '%s'\n", SockPath);
1598
 
      if (!RecoverSocket())
1599
 
        {
1600
 
          debug("SCREEN cannot recover from corrupt Socket, bye\n");
1601
 
          Finit(1);
1602
 
        }
1603
 
      else
1604
 
        debug1("'%s' reconstructed\n", SockPath);
1605
 
    }
1606
 
  else
1607
 
    debug2("SigChldHandler: stat '%s' o.k. (%03o)\n", SockPath, (int)st.st_mode);
1608
 
}
1609
 
 
1610
 
static sigret_t
1611
 
SigChld SIGDEFARG
1612
 
{
1613
 
  debug("SigChld()\n");
1614
 
  GotSigChld = 1;
1615
 
  SIGRETURN;
1616
 
}
1617
 
 
1618
 
sigret_t
1619
 
SigHup SIGDEFARG
1620
 
{
1621
 
  /* Hangup all displays */
1622
 
  while ((display = displays) != 0)
1623
 
    Hangup();
1624
 
  SIGRETURN;
1625
 
}
1626
 
 
1627
 
/* 
1628
 
 * the backend's Interrupt handler
1629
 
 * we cannot insert the intrc directly, as we never know
1630
 
 * if fore is valid.
1631
 
 */
1632
 
static sigret_t
1633
 
SigInt SIGDEFARG
1634
 
{
1635
 
#if HAZARDOUS
1636
 
  char ibuf;
1637
 
 
1638
 
  debug("SigInt()\n");
1639
 
  if (fore && displays)
1640
 
    {
1641
 
# if defined(TERMIO) || defined(POSIX)
1642
 
      ibuf = displays->d_OldMode.tio.c_cc[VINTR];
1643
 
# else
1644
 
      ibuf = displays->d_OldMode.m_tchars.t_intrc;
1645
 
# endif
1646
 
      fore->w_inlen = 0;
1647
 
      write(fore->w_ptyfd, &ibuf, 1);
1648
 
    }
1649
 
#else
1650
 
  signal(SIGINT, SigInt);
1651
 
  debug("SigInt() careful\n");
1652
 
  InterruptPlease = 1;
1653
 
#endif
1654
 
  SIGRETURN;
1655
 
}
1656
 
 
1657
 
static sigret_t
1658
 
CoreDump SIGDEFARG
1659
 
{
1660
 
  /* if running with s-bit, we must reset the s-bit, so that we get a
1661
 
   * core file anyway.
1662
 
   */
1663
 
 
1664
 
  struct display *disp;
1665
 
  char buf[80];
1666
 
 
1667
 
  char *dump_msg = " (core dumped)";
1668
 
 
1669
 
  int running_w_s_bit = getuid() != geteuid();
1670
 
#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
1671
 
  if (running_w_s_bit)
1672
 
    dump_msg = "";
1673
 
#endif
1674
 
 
1675
 
#if defined(SYSVSIGS) && defined(SIGHASARG)
1676
 
  signal(sigsig, SIG_IGN);
1677
 
#endif
1678
 
  setgid(getgid());
1679
 
  setuid(getuid());
1680
 
  unlink("core");
1681
 
 
1682
 
#ifdef SIGHASARG
1683
 
  sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sigsig, dump_msg);
1684
 
#else
1685
 
  sprintf(buf, "\r\n[screen caught a fatal signal.%s]\r\n", dump_msg);
1686
 
#endif
1687
 
 
1688
 
  for (disp = displays; disp; disp = disp->d_next)
1689
 
    {
1690
 
      if (disp->d_nonblock < -1 || disp->d_nonblock > 1000000)
1691
 
        continue;
1692
 
      fcntl(disp->d_userfd, F_SETFL, 0);
1693
 
      SetTTY(disp->d_userfd, &D_OldMode);
1694
 
      write(disp->d_userfd, buf, strlen(buf));
1695
 
      Kill(disp->d_userpid, SIG_BYE);
1696
 
    }
1697
 
 
1698
 
  if (running_w_s_bit)
1699
 
    {
1700
 
#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
1701
 
      Kill(getpid(), SIGKILL);
1702
 
      eexit(11);
1703
 
#else /* SHADOWPW && !DEBUG */
1704
 
      abort();
1705
 
#endif /* SHADOWPW  && !DEBUG */
1706
 
    }
1707
 
  else
1708
 
    abort();
1709
 
  SIGRETURN;
1710
 
}
1711
 
 
1712
 
static void
1713
 
DoWait()
1714
 
{
1715
 
  register int pid;
1716
 
  struct win *p, *next;
1717
 
#ifdef BSDWAIT
1718
 
  union wait wstat;
1719
 
#else
1720
 
  int wstat;
1721
 
#endif
1722
 
 
1723
 
#ifdef BSDJOBS
1724
 
# ifndef BSDWAIT
1725
 
  while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0)
1726
 
# else
1727
 
# ifdef USE_WAIT2
1728
 
  /* 
1729
 
   * From: rouilj@sni-usa.com (John Rouillard) 
1730
 
   * note that WUNTRACED is not documented to work, but it is defined in
1731
 
   * /usr/include/sys/wait.h, so it may work 
1732
 
   */
1733
 
  while ((pid = wait2(&wstat, WNOHANG | WUNTRACED )) > 0)
1734
 
#  else /* USE_WAIT2 */
1735
 
  while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0)
1736
 
#  endif /* USE_WAIT2 */
1737
 
# endif
1738
 
#else   /* BSDJOBS */
1739
 
  while ((pid = wait(&wstat)) < 0)
1740
 
    if (errno != EINTR)
1741
 
      break;
1742
 
  if (pid > 0)
1743
 
#endif  /* BSDJOBS */
1744
 
    {
1745
 
      for (p = windows; p; p = next)
1746
 
        {
1747
 
          next = p->w_next;
1748
 
          if (  (p->w_pid     && pid == p->w_pid) ||
1749
 
                (p->w_deadpid && pid == p->w_deadpid) )
1750
 
            {
1751
 
              /* child has ceased to exist */
1752
 
              p->w_pid = 0;
1753
 
                
1754
 
#ifdef BSDJOBS
1755
 
              if (WIFSTOPPED(wstat))
1756
 
                {
1757
 
                  debug3("Window %d pid %d: WIFSTOPPED (sig %d)\n", p->w_number, pid, WSTOPSIG(wstat));
1758
 
#ifdef SIGTTIN
1759
 
                  if (WSTOPSIG(wstat) == SIGTTIN)
1760
 
                    {
1761
 
                      Msg(0, "Suspended (tty input)");
1762
 
                      continue;
1763
 
                    }
1764
 
#endif
1765
 
#ifdef SIGTTOU
1766
 
                  if (WSTOPSIG(wstat) == SIGTTOU)
1767
 
                    {
1768
 
                      Msg(0, "Suspended (tty output)");
1769
 
                      continue;
1770
 
                    }
1771
 
#endif
1772
 
                  /* Try to restart process */
1773
 
                  Msg(0, "Child has been stopped, restarting.");
1774
 
                  if (killpg(pid, SIGCONT))
1775
 
                    kill(pid, SIGCONT);
1776
 
                }
1777
 
              else
1778
 
#endif
1779
 
                {
1780
 
                  /* Screen will detect the window has died when the window's
1781
 
                   * file descriptor signals EOF (which it will do when the process in
1782
 
                   * the window terminates). So do this in a timeout of 10 seconds.
1783
 
                   * (not doing this at all might also work)
1784
 
                   * See #27061 for more details.
1785
 
                   */
1786
 
                  p->w_destroyev.data = (char *)p;
1787
 
                  p->w_exitstatus = wstat;
1788
 
                  SetTimeout(&p->w_destroyev, 10 * 1000);
1789
 
                  evenq(&p->w_destroyev);
1790
 
                }
1791
 
              break;
1792
 
            }
1793
 
#ifdef PSEUDOS
1794
 
          if (p->w_pwin && pid == p->w_pwin->p_pid)
1795
 
            {
1796
 
              debug2("pseudo of win Nr %d died. pid == %d\n", p->w_number, p->w_pwin->p_pid);
1797
 
              FreePseudowin(p);
1798
 
              break;
1799
 
            }
1800
 
#endif
1801
 
        }
1802
 
      if (p == 0)
1803
 
        {
1804
 
          debug1("pid %d not found - hope that's ok\n", pid);
1805
 
        }
1806
 
    }
1807
 
}
1808
 
 
1809
 
 
1810
 
static sigret_t
1811
 
FinitHandler SIGDEFARG
1812
 
{
1813
 
#ifdef SIGHASARG
1814
 
  debug1("FinitHandler called, sig %d.\n", sigsig);
1815
 
#else
1816
 
  debug("FinitHandler called.\n");
1817
 
#endif
1818
 
  Finit(1);
1819
 
  SIGRETURN;
1820
 
}
1821
 
 
1822
 
void
1823
 
Finit(i)
1824
 
int i;
1825
 
{
1826
 
  signal(SIGCHLD, SIG_DFL);
1827
 
  signal(SIGHUP, SIG_IGN);
1828
 
  debug1("Finit(%d);\n", i);
1829
 
  while (windows)
1830
 
    {
1831
 
      struct win *p = windows;
1832
 
      windows = windows->w_next;
1833
 
      FreeWindow(p);
1834
 
    }
1835
 
  if (ServerSocket != -1)
1836
 
    {
1837
 
      debug1("we unlink(%s)\n", SockPath);
1838
 
#ifdef USE_SETEUID
1839
 
      xseteuid(real_uid);
1840
 
      xsetegid(real_gid);
1841
 
#endif
1842
 
      (void) unlink(SockPath);
1843
 
#ifdef USE_SETEUID
1844
 
      xseteuid(eff_uid);
1845
 
      xsetegid(eff_gid);
1846
 
#endif
1847
 
    }
1848
 
  for (display = displays; display; display = display->d_next)
1849
 
    {
1850
 
      if (D_status)
1851
 
        RemoveStatus();
1852
 
      FinitTerm();
1853
 
#ifdef UTMPOK
1854
 
      RestoreLoginSlot();
1855
 
#endif
1856
 
      AddStr("[screen is terminating]\r\n");
1857
 
      Flush(3);
1858
 
      SetTTY(D_userfd, &D_OldMode);
1859
 
      fcntl(D_userfd, F_SETFL, 0);
1860
 
      freetty();
1861
 
      Kill(D_userpid, SIG_BYE);
1862
 
    }
1863
 
  /*
1864
 
   * we _cannot_ call eexit(i) here, 
1865
 
   * instead of playing with the Socket above. Sigh.
1866
 
   */
1867
 
  exit(i);
1868
 
}
1869
 
 
1870
 
void
1871
 
eexit(e)
1872
 
int e;
1873
 
{
1874
 
  debug("eexit\n");
1875
 
  if (ServerSocket != -1)
1876
 
    {
1877
 
      debug1("we unlink(%s)\n", SockPath);
1878
 
      setgid(real_gid);
1879
 
      setuid(real_uid);
1880
 
      (void) unlink(SockPath);
1881
 
    }
1882
 
  exit(e);
1883
 
}
1884
 
 
1885
 
void
1886
 
Hangup()
1887
 
{
1888
 
  if (display == 0)
1889
 
    return;
1890
 
  debug1("Hangup %x\n", display);
1891
 
  if (D_userfd >= 0)
1892
 
    {
1893
 
      close(D_userfd);
1894
 
      D_userfd = -1;
1895
 
    }
1896
 
  if (auto_detach || displays->d_next)
1897
 
    Detach(D_HANGUP);
1898
 
  else
1899
 
    Finit(0);
1900
 
}
1901
 
 
1902
 
/*
1903
 
 * Detach now has the following modes:
1904
 
 *D_DETACH       SIG_BYE        detach backend and exit attacher
1905
 
 *D_HANGUP       SIG_BYE        detach backend and exit attacher
1906
 
 *D_STOP         SIG_STOP       stop attacher (and detach backend)
1907
 
 *D_REMOTE       SIG_BYE        remote detach -- reattach to new attacher
1908
 
 *D_POWER        SIG_POWER_BYE  power detach -- attacher kills his parent
1909
 
 *D_REMOTE_POWER SIG_POWER_BYE  remote power detach -- both
1910
 
 *D_LOCK         SIG_LOCK       lock the attacher
1911
 
 * (jw)
1912
 
 * we always remove our utmp slots. (even when "lock" or "stop")
1913
 
 * Note: Take extra care here, we may be called by interrupt!
1914
 
 */
1915
 
void
1916
 
Detach(mode)
1917
 
int mode;
1918
 
{
1919
 
  int sign = 0, pid;
1920
 
  struct canvas *cv;
1921
 
  struct win *p;
1922
 
 
1923
 
  if (display == 0)
1924
 
    return;
1925
 
 
1926
 
#define AddStrSock(msg) do { \
1927
 
    if (SockName) \
1928
 
      { \
1929
 
        AddStr("[" msg " from "); \
1930
 
        AddStr(SockName); \
1931
 
        AddStr("]\r\n"); \
1932
 
      } \
1933
 
    else \
1934
 
      AddStr("[" msg "]\r\n"); \
1935
 
  } while (0)
1936
 
 
1937
 
  signal(SIGHUP, SIG_IGN);
1938
 
  debug1("Detach(%d)\n", mode);
1939
 
  if (D_status)
1940
 
    RemoveStatus();
1941
 
  FinitTerm();
1942
 
  if (!display)
1943
 
    return;
1944
 
  switch (mode)
1945
 
    {
1946
 
    case D_HANGUP:
1947
 
      sign = SIG_BYE;
1948
 
      break;
1949
 
    case D_DETACH:
1950
 
      AddStrSock("detached");
1951
 
      sign = SIG_BYE;
1952
 
      break;
1953
 
#ifdef BSDJOBS
1954
 
    case D_STOP:
1955
 
      sign = SIG_STOP;
1956
 
      break;
1957
 
#endif
1958
 
#ifdef REMOTE_DETACH
1959
 
    case D_REMOTE:
1960
 
      AddStrSock("remote detached");
1961
 
      sign = SIG_BYE;
1962
 
      break;
1963
 
#endif
1964
 
#ifdef POW_DETACH
1965
 
    case D_POWER:
1966
 
      AddStrSock("power detached");
1967
 
      if (PowDetachString)
1968
 
        {
1969
 
          AddStr(PowDetachString);
1970
 
          AddStr("\r\n");
1971
 
        }
1972
 
      sign = SIG_POWER_BYE;
1973
 
      break;
1974
 
#ifdef REMOTE_DETACH
1975
 
    case D_REMOTE_POWER:
1976
 
      AddStrSock("remote power detached");
1977
 
      if (PowDetachString)
1978
 
        {
1979
 
          AddStr(PowDetachString);
1980
 
          AddStr("\r\n");
1981
 
        }
1982
 
      sign = SIG_POWER_BYE;
1983
 
      break;
1984
 
#endif
1985
 
#endif
1986
 
    case D_LOCK:
1987
 
      ClearAll();
1988
 
      sign = SIG_LOCK;
1989
 
      /* tell attacher to lock terminal with a lockprg. */
1990
 
      break;
1991
 
    }
1992
 
#ifdef UTMPOK
1993
 
  if (displays->d_next == 0)
1994
 
    {
1995
 
      for (p = windows; p; p = p->w_next)
1996
 
        {
1997
 
          if (p->w_slot != (slot_t) -1 && !(p->w_lflag & 2))
1998
 
            {
1999
 
              RemoveUtmp(p);
2000
 
              /*
2001
 
               * Set the slot to 0 to get the window
2002
 
               * logged in again.
2003
 
               */
2004
 
              p->w_slot = (slot_t) 0;
2005
 
            }
2006
 
        }
2007
 
    }
2008
 
  if (mode != D_HANGUP)
2009
 
    RestoreLoginSlot();
2010
 
#endif
2011
 
  if (displays->d_next == 0 && console_window)
2012
 
    {
2013
 
      if (TtyGrabConsole(console_window->w_ptyfd, 0, "detach"))
2014
 
        {
2015
 
          debug("could not release console - killing window\n");
2016
 
          KillWindow(console_window);
2017
 
          display = displays;           /* restore display */
2018
 
        }
2019
 
    }
2020
 
  if (D_fore)
2021
 
    {
2022
 
#ifdef MULTIUSER
2023
 
      ReleaseAutoWritelock(display, D_fore);
2024
 
#endif
2025
 
      D_user->u_detachwin = D_fore->w_number;
2026
 
      D_user->u_detachotherwin = D_other ? D_other->w_number : -1;
2027
 
    }
2028
 
  AutosaveLayout(D_layout);
2029
 
  layout_last = D_layout;
2030
 
  for (cv = D_cvlist; cv; cv = cv->c_next)
2031
 
    {
2032
 
      p = Layer2Window(cv->c_layer);
2033
 
      SetCanvasWindow(cv, 0);
2034
 
      if (p)
2035
 
        WindowChanged(p, 'u');
2036
 
    }
2037
 
 
2038
 
  pid = D_userpid;
2039
 
  debug2("display: %#x displays: %#x\n", (unsigned int)display, (unsigned int)displays);
2040
 
  FreeDisplay();
2041
 
  if (displays == 0)
2042
 
    /* Flag detached-ness */
2043
 
    (void) chsock();
2044
 
  /*
2045
 
   * tell father what to do. We do that after we
2046
 
   * freed the tty, thus getty feels more comfortable on hpux
2047
 
   * if it was a power detach.
2048
 
   */
2049
 
  Kill(pid, sign);
2050
 
  debug2("Detach: Signal %d to Attacher(%d)!\n", sign, pid);
2051
 
  debug("Detach returns, we are successfully detached.\n");
2052
 
  signal(SIGHUP, SigHup);
2053
 
#undef AddStrSock
2054
 
}
2055
 
 
2056
 
static int
2057
 
IsSymbol(e, s)
2058
 
char *e, *s;
2059
 
{
2060
 
  register int l;
2061
 
 
2062
 
  l = strlen(s);
2063
 
  return strncmp(e, s, l) == 0 && e[l] == '=';
2064
 
}
2065
 
 
2066
 
void
2067
 
MakeNewEnv()
2068
 
{
2069
 
  register char **op, **np;
2070
 
  static char stybuf[MAXSTR];
2071
 
 
2072
 
  for (op = environ; *op; ++op)
2073
 
    ;
2074
 
  if (NewEnv)
2075
 
    free((char *)NewEnv);
2076
 
  NewEnv = np = (char **) malloc((unsigned) (op - environ + 7 + 1) * sizeof(char **));
2077
 
  if (!NewEnv)
2078
 
    Panic(0, "%s", strnomem);
2079
 
  sprintf(stybuf, "STY=%s", strlen(SockName) <= MAXSTR - 5 ? SockName : "?");
2080
 
  *np++ = stybuf;                       /* NewEnv[0] */
2081
 
  *np++ = Term;                 /* NewEnv[1] */
2082
 
  np++;         /* room for SHELL */
2083
 
#ifdef TIOCSWINSZ
2084
 
  np += 2;      /* room for TERMCAP and WINDOW */
2085
 
#else
2086
 
  np += 4;      /* room for TERMCAP WINDOW LINES COLUMNS */
2087
 
#endif
2088
 
 
2089
 
  for (op = environ; *op; ++op)
2090
 
    {
2091
 
      if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP")
2092
 
          && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW")
2093
 
          && !IsSymbol(*op, "SCREENCAP") && !IsSymbol(*op, "SHELL")
2094
 
          && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS")
2095
 
         )
2096
 
        *np++ = *op;
2097
 
    }
2098
 
  *np = 0;
2099
 
}
2100
 
 
2101
 
#if defined(USEVARARGS) && defined(__STDC__)
2102
 
  #define DEFINE_VARARGS_FN(fnname)     void fnname (int err, const char *fmt, VA_DOTS)
2103
 
#else
2104
 
  #define DEFINE_VARARGS_FN(fnname)     void fnname(err, fmt, VA_DOTS) \
2105
 
  int err;      \
2106
 
  const char *fmt;      \
2107
 
  VA_DECL
2108
 
#endif
2109
 
 
2110
 
#define PROCESS_MESSAGE(B) do { \
2111
 
    char *p = B;        \
2112
 
    VA_LIST(ap) \
2113
 
    VA_START(ap, fmt);  \
2114
 
    fmt = DoNLS(fmt);   \
2115
 
    (void)vsnprintf(p, sizeof(B) - 100, fmt, VA_ARGS(ap));      \
2116
 
    VA_END(ap); \
2117
 
    if (err)    \
2118
 
      { \
2119
 
        p += strlen(p); \
2120
 
        *p++ = ':';     \
2121
 
        *p++ = ' ';     \
2122
 
        strncpy(p, strerror(err), B + sizeof(B) - p - 1);       \
2123
 
        B[sizeof(B) - 1] = 0;   \
2124
 
      } \
2125
 
  } while (0)
2126
 
 
2127
 
DEFINE_VARARGS_FN(Msg)
2128
 
{
2129
 
  char buf[MAXPATHLEN*2];
2130
 
  PROCESS_MESSAGE(buf);
2131
 
 
2132
 
  debug2("Msg('%s') (%#x);\n", buf, (unsigned int)display);
2133
 
 
2134
 
  if (display && displays)
2135
 
    MakeStatus(buf);
2136
 
  else if (displays)
2137
 
    {
2138
 
      for (display = displays; display; display = display->d_next)
2139
 
        MakeStatus(buf);
2140
 
    }
2141
 
  else if (display)
2142
 
    {
2143
 
      /* no displays but a display - must have forked.
2144
 
       * send message to backend!
2145
 
       */
2146
 
      char *tty = D_usertty;
2147
 
      struct display *olddisplay = display;
2148
 
      display = 0;      /* only send once */
2149
 
      SendErrorMsg(tty, buf);
2150
 
      display = olddisplay;
2151
 
    }
2152
 
  else
2153
 
    printf("%s\r\n", buf);
2154
 
 
2155
 
  if (queryflag >= 0)
2156
 
    write(queryflag, buf, strlen(buf));
2157
 
}
2158
 
 
2159
 
/*
2160
 
 * Call FinitTerm for all displays, write a message to each and call eexit();
2161
 
 */
2162
 
DEFINE_VARARGS_FN(Panic)
2163
 
{
2164
 
  char buf[MAXPATHLEN*2];
2165
 
  PROCESS_MESSAGE(buf);
2166
 
 
2167
 
  debug3("Panic('%s'); display=%x displays=%x\n", buf, display, displays);
2168
 
  if (displays == 0 && display == 0)
2169
 
    {
2170
 
      printf("%s\r\n", buf);
2171
 
      if (PanicPid)
2172
 
        Kill(PanicPid, SIG_BYE);
2173
 
    }
2174
 
  else if (displays == 0)
2175
 
    {
2176
 
      /* no displays but a display - must have forked.
2177
 
       * send message to backend!
2178
 
       */
2179
 
      char *tty = D_usertty;
2180
 
      display = 0;
2181
 
      SendErrorMsg(tty, buf);
2182
 
      sleep(2);
2183
 
      _exit(1);
2184
 
    }
2185
 
  else
2186
 
    for (display = displays; display; display = display->d_next)
2187
 
      {
2188
 
        if (D_status)
2189
 
          RemoveStatus();
2190
 
        FinitTerm();
2191
 
        Flush(3);
2192
 
#ifdef UTMPOK
2193
 
        RestoreLoginSlot();
2194
 
#endif
2195
 
        SetTTY(D_userfd, &D_OldMode);
2196
 
        fcntl(D_userfd, F_SETFL, 0);
2197
 
        write(D_userfd, buf, strlen(buf));
2198
 
        write(D_userfd, "\n", 1);
2199
 
        freetty();
2200
 
        if (D_userpid)
2201
 
          Kill(D_userpid, SIG_BYE);
2202
 
      }
2203
 
#ifdef MULTIUSER
2204
 
  if (tty_oldmode >= 0)
2205
 
    {
2206
 
# ifdef USE_SETEUID
2207
 
      if (setuid(own_uid))
2208
 
        xseteuid(own_uid);      /* may be a loop. sigh. */
2209
 
# else
2210
 
      setuid(own_uid);
2211
 
# endif
2212
 
      debug1("Panic: changing back modes from %s\n", attach_tty);
2213
 
      chmod(attach_tty, tty_oldmode);
2214
 
    }
2215
 
#endif
2216
 
  eexit(1);
2217
 
}
2218
 
 
2219
 
DEFINE_VARARGS_FN(QueryMsg)
2220
 
{
2221
 
  char buf[MAXPATHLEN*2];
2222
 
 
2223
 
  if (queryflag < 0)
2224
 
    return;
2225
 
 
2226
 
  PROCESS_MESSAGE(buf);
2227
 
  write(queryflag, buf, strlen(buf));
2228
 
}
2229
 
 
2230
 
DEFINE_VARARGS_FN(Dummy)
2231
 
{}
2232
 
 
2233
 
#undef PROCESS_MESSAGE
2234
 
#undef DEFINE_VARARGS_FN
2235
 
 
2236
 
/*
2237
 
 * '^' is allowed as an escape mechanism for control characters. jw.
2238
 
 * 
2239
 
 * Added time insertion using ideas/code from /\ndy Jones
2240
 
 *   (andy@lingua.cltr.uq.OZ.AU) - thanks a lot!
2241
 
 *
2242
 
 */
2243
 
 
2244
 
#ifndef USE_LOCALE
2245
 
static const char days[]   = "SunMonTueWedThuFriSat";
2246
 
static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
2247
 
#endif
2248
 
 
2249
 
static char winmsg_buf[MAXSTR];
2250
 
#define MAX_WINMSG_REND 256     /* rendition changes */
2251
 
static int winmsg_rend[MAX_WINMSG_REND];
2252
 
static int winmsg_rendpos[MAX_WINMSG_REND];
2253
 
static int winmsg_numrend;
2254
 
 
2255
 
static char *
2256
 
pad_expand(buf, p, numpad, padlen)
2257
 
char *buf;
2258
 
char *p;
2259
 
int numpad;
2260
 
int padlen;
2261
 
{
2262
 
  char *pn, *pn2;
2263
 
  int i, r;
2264
 
 
2265
 
  padlen = padlen - (p - buf);  /* space for rent */
2266
 
  if (padlen < 0)
2267
 
    padlen = 0;
2268
 
  pn2 = pn = p + padlen;
2269
 
  r = winmsg_numrend;
2270
 
  while (p >= buf)
2271
 
    {
2272
 
      if (r && *p != 127 && p - buf == winmsg_rendpos[r - 1])
2273
 
        {
2274
 
          winmsg_rendpos[--r] = pn - buf;
2275
 
          continue;
2276
 
        }
2277
 
      *pn-- = *p;
2278
 
      if (*p-- == 127)
2279
 
        {
2280
 
          pn[1] = ' ';
2281
 
          i = numpad > 0 ? (padlen + numpad - 1) / numpad : 0;
2282
 
          padlen -= i;
2283
 
          while (i-- > 0)
2284
 
            *pn-- = ' ';
2285
 
          numpad--;
2286
 
          if (r && p - buf == winmsg_rendpos[r - 1])
2287
 
            winmsg_rendpos[--r] = pn - buf;
2288
 
        }
2289
 
    }
2290
 
  return pn2;
2291
 
}
2292
 
 
2293
 
struct backtick {
2294
 
  struct backtick *next;
2295
 
  int num;
2296
 
  int tick;
2297
 
  int lifespan;
2298
 
  time_t bestbefore;
2299
 
  char result[MAXSTR];
2300
 
  char **cmdv;
2301
 
  struct event ev;
2302
 
  char *buf;
2303
 
  int bufi;
2304
 
};
2305
 
 
2306
 
struct backtick *backticks;
2307
 
 
2308
 
static void
2309
 
backtick_filter(bt)
2310
 
struct backtick *bt;
2311
 
{
2312
 
  char *p, *q;
2313
 
  int c;
2314
 
 
2315
 
  for (p = q = bt->result; (c = (unsigned char)*p++) != 0;)
2316
 
    {
2317
 
      if (c == '\t')
2318
 
        c = ' ';
2319
 
      if (c >= ' ' || c == '\005')
2320
 
        *q++ = c;
2321
 
    }
2322
 
  *q = 0;
2323
 
}
2324
 
 
2325
 
static void
2326
 
backtick_fn(ev, data)
2327
 
struct event *ev;
2328
 
char *data;
2329
 
{
2330
 
  struct backtick *bt;
2331
 
  int i, j, k, l;
2332
 
 
2333
 
  bt = (struct backtick *)data;
2334
 
  debug1("backtick_fn for #%d\n", bt->num);
2335
 
  i = bt->bufi;
2336
 
  l = read(ev->fd, bt->buf + i, MAXSTR - i);
2337
 
  if (l <= 0)
2338
 
    {
2339
 
      debug1("EOF on backtick #%d\n", bt->num);
2340
 
      evdeq(ev);
2341
 
      close(ev->fd);
2342
 
      ev->fd = -1;
2343
 
      return;
2344
 
    }
2345
 
  debug1("read %d bytes\n", l);
2346
 
  i += l;
2347
 
  for (j = 0; j < l; j++)
2348
 
    if (bt->buf[i - j - 1] == '\n')
2349
 
      break;
2350
 
  if (j < l)
2351
 
    {
2352
 
      for (k = i - j - 2; k >= 0; k--)
2353
 
        if (bt->buf[k] == '\n')
2354
 
          break;
2355
 
      k++;
2356
 
      bcopy(bt->buf + k, bt->result, i - j - k);
2357
 
      bt->result[i - j - k - 1] = 0;
2358
 
      backtick_filter(bt);
2359
 
      WindowChanged(0, '`');
2360
 
    }
2361
 
  if (j == l && i == MAXSTR)
2362
 
    {
2363
 
      j = MAXSTR/2;
2364
 
      l = j + 1;
2365
 
    }
2366
 
  if (j < l)
2367
 
    {
2368
 
      if (j)
2369
 
        bcopy(bt->buf + i - j, bt->buf, j);
2370
 
      i = j;
2371
 
    }
2372
 
  bt->bufi = i;
2373
 
}
2374
 
 
2375
 
void
2376
 
setbacktick(num, lifespan, tick, cmdv)
2377
 
int num;
2378
 
int lifespan;
2379
 
int tick;
2380
 
char **cmdv;
2381
 
{
2382
 
  struct backtick **btp, *bt;
2383
 
  char **v;
2384
 
 
2385
 
  debug1("setbacktick called for backtick #%d\n", num);
2386
 
  for (btp = &backticks; (bt = *btp) != 0; btp = &bt->next)
2387
 
    if (bt->num == num)
2388
 
      break;
2389
 
  if (!bt && !cmdv)
2390
 
    return;
2391
 
  if (bt)
2392
 
    {
2393
 
      for (v = bt->cmdv; *v; v++)
2394
 
        free(*v);
2395
 
      free(bt->cmdv);
2396
 
      if (bt->buf)
2397
 
        free(bt->buf);
2398
 
      if (bt->ev.fd >= 0)
2399
 
        close(bt->ev.fd);
2400
 
      evdeq(&bt->ev);
2401
 
    }
2402
 
  if (bt && !cmdv)
2403
 
    {
2404
 
      *btp = bt->next;
2405
 
      free(bt);
2406
 
      return;
2407
 
    }
2408
 
  if (!bt)
2409
 
    {
2410
 
      bt = (struct backtick *)malloc(sizeof *bt);
2411
 
      if (!bt)
2412
 
        {
2413
 
          Msg(0, "%s", strnomem);
2414
 
          return;
2415
 
        }
2416
 
      bzero(bt, sizeof(*bt));
2417
 
      bt->next = 0;
2418
 
      *btp = bt;
2419
 
    }
2420
 
  bt->num = num;
2421
 
  bt->tick = tick;
2422
 
  bt->lifespan = lifespan;
2423
 
  bt->bestbefore = 0;
2424
 
  bt->result[0] = 0;
2425
 
  bt->buf = 0;
2426
 
  bt->bufi = 0;
2427
 
  bt->cmdv = cmdv;
2428
 
  bt->ev.fd = -1;
2429
 
  if (bt->tick == 0 && bt->lifespan == 0)
2430
 
    {
2431
 
      debug("setbacktick: continuous mode\n");
2432
 
      bt->buf = (char *)malloc(MAXSTR);
2433
 
      if (bt->buf == 0)
2434
 
        {
2435
 
          Msg(0, "%s", strnomem);
2436
 
          setbacktick(num, 0, 0, (char **)0);
2437
 
          return;
2438
 
        }
2439
 
      bt->ev.type = EV_READ;
2440
 
      bt->ev.fd = readpipe(bt->cmdv);
2441
 
      bt->ev.handler = backtick_fn;
2442
 
      bt->ev.data = (char *)bt;
2443
 
      if (bt->ev.fd >= 0)
2444
 
        evenq(&bt->ev);
2445
 
    }
2446
 
}
2447
 
 
2448
 
static char *
2449
 
runbacktick(bt, tickp, now)
2450
 
struct backtick *bt;
2451
 
int *tickp;
2452
 
time_t now;
2453
 
{
2454
 
  int f, i, l, j;
2455
 
  time_t now2;
2456
 
 
2457
 
  debug1("runbacktick called for backtick #%d\n", bt->num);
2458
 
  if (bt->tick && (!*tickp || bt->tick < *tickp))
2459
 
    *tickp = bt->tick;
2460
 
  if ((bt->lifespan == 0 && bt->tick == 0) || now < bt->bestbefore)
2461
 
    {
2462
 
      debug1("returning old result (%d)\n", bt->lifespan);
2463
 
      return bt->result;
2464
 
    }
2465
 
  f = readpipe(bt->cmdv);
2466
 
  if (f == -1)
2467
 
    return bt->result;
2468
 
  i = 0;
2469
 
  while ((l = read(f, bt->result + i, sizeof(bt->result) - i)) > 0)
2470
 
    {
2471
 
      debug1("runbacktick: read %d bytes\n", l);
2472
 
      i += l;
2473
 
      for (j = 1; j < l; j++)
2474
 
        if (bt->result[i - j - 1] == '\n')
2475
 
          break;
2476
 
      if (j == l && i == sizeof(bt->result))
2477
 
        {
2478
 
          j = sizeof(bt->result) / 2;
2479
 
          l = j + 1;
2480
 
        }
2481
 
      if (j < l)
2482
 
        {
2483
 
          bcopy(bt->result + i - j, bt->result, j);
2484
 
          i = j;
2485
 
        }
2486
 
    }
2487
 
  close(f);
2488
 
  bt->result[sizeof(bt->result) - 1] = '\n';
2489
 
  if (i && bt->result[i - 1] == '\n')
2490
 
    i--;
2491
 
  debug1("runbacktick: finished, %d bytes\n", i);
2492
 
  bt->result[i] = 0;
2493
 
  backtick_filter(bt);
2494
 
  (void)time(&now2);
2495
 
  bt->bestbefore = now2 + bt->lifespan;
2496
 
  return bt->result;
2497
 
}
2498
 
 
2499
 
int
2500
 
AddWinMsgRend(str, r)
2501
 
const char *str;
2502
 
int r;
2503
 
{
2504
 
  if (winmsg_numrend >= MAX_WINMSG_REND || str < winmsg_buf ||
2505
 
      str >= winmsg_buf + MAXSTR)
2506
 
    return -1;
2507
 
 
2508
 
  winmsg_rend[winmsg_numrend] = r;
2509
 
  winmsg_rendpos[winmsg_numrend] = str - winmsg_buf;
2510
 
  winmsg_numrend++;
2511
 
 
2512
 
  return 0;
2513
 
}
2514
 
 
2515
 
char *
2516
 
MakeWinMsgEv(str, win, esc, padlen, ev, rec)
2517
 
char *str;
2518
 
struct win *win;
2519
 
int esc;
2520
 
int padlen;
2521
 
struct event *ev;
2522
 
int rec;
2523
 
{
2524
 
  static int tick;
2525
 
  char *s = str;
2526
 
  register char *p = winmsg_buf;
2527
 
  register int ctrl;
2528
 
  struct timeval now;
2529
 
  struct tm *tm;
2530
 
  int l, i, r;
2531
 
  int num;
2532
 
  int zeroflg;
2533
 
  int longflg;
2534
 
  int minusflg;
2535
 
  int plusflg;
2536
 
  int qmflag = 0, omflag = 0, qmnumrend = 0;
2537
 
  char *qmpos = 0;
2538
 
  int numpad = 0;
2539
 
  int lastpad = 0;
2540
 
  int truncpos = -1;
2541
 
  int truncper = 0;
2542
 
  int trunclong = 0;
2543
 
  struct backtick *bt = NULL;
2544
 
 
2545
 
  if (winmsg_numrend >= 0)
2546
 
    winmsg_numrend = 0;
2547
 
  else
2548
 
    winmsg_numrend = -winmsg_numrend;
2549
 
    
2550
 
  tick = 0;
2551
 
  tm = 0;
2552
 
  ctrl = 0;
2553
 
  gettimeofday(&now, NULL);
2554
 
  for (; *s && (l = winmsg_buf + MAXSTR - 1 - p) > 0; s++, p++)
2555
 
    {
2556
 
      *p = *s;
2557
 
      if (ctrl)
2558
 
        {
2559
 
          ctrl = 0;
2560
 
          if (*s != '^' && *s >= 64)
2561
 
            *p &= 0x1f;
2562
 
          continue;
2563
 
        }
2564
 
      if (*s != esc)
2565
 
        {
2566
 
          if (esc == '%')
2567
 
            {
2568
 
              switch (*s)
2569
 
                {
2570
 
#if 0
2571
 
                case '~':
2572
 
                  *p = BELL;
2573
 
                  break;
2574
 
#endif
2575
 
                case '^':
2576
 
                  ctrl = 1;
2577
 
                  *p-- = '^';
2578
 
                  break;
2579
 
                default:
2580
 
                  break;
2581
 
                }
2582
 
            }
2583
 
          continue;
2584
 
        }
2585
 
      if (*++s == esc)  /* double escape ? */
2586
 
        continue;
2587
 
      if ((plusflg = *s == '+') != 0)
2588
 
        s++;
2589
 
      if ((minusflg = *s == '-') != 0)
2590
 
        s++;
2591
 
      if ((zeroflg = *s == '0') != 0)
2592
 
        s++;
2593
 
      num = 0;
2594
 
      while(*s >= '0' && *s <= '9')
2595
 
        num = num * 10 + (*s++ - '0');
2596
 
      if ((longflg = *s == 'L') != 0)
2597
 
        s++;
2598
 
      switch (*s)
2599
 
        {
2600
 
        case '?':
2601
 
          p--;
2602
 
          if (qmpos)
2603
 
            {
2604
 
              if ((!qmflag && !omflag) || omflag == 1)
2605
 
                {
2606
 
                  p = qmpos;
2607
 
                  if (qmnumrend < winmsg_numrend)
2608
 
                    winmsg_numrend = qmnumrend;
2609
 
                }
2610
 
              qmpos = 0;
2611
 
              break;
2612
 
            }
2613
 
          qmpos = p;
2614
 
          qmnumrend = winmsg_numrend;
2615
 
          qmflag = omflag = 0;
2616
 
          break;
2617
 
        case ':':
2618
 
          p--;
2619
 
          if (!qmpos)
2620
 
            break;
2621
 
          if (qmflag && omflag != 1)
2622
 
            {
2623
 
              omflag = 1;
2624
 
              qmpos = p;
2625
 
              qmnumrend = winmsg_numrend;
2626
 
            }
2627
 
          else
2628
 
            {
2629
 
              p = qmpos;
2630
 
              if (qmnumrend < winmsg_numrend)
2631
 
                winmsg_numrend = qmnumrend;
2632
 
              omflag = -1;
2633
 
            }
2634
 
          break;
2635
 
        case 'd': case 'D': case 'm': case 'M': case 'y': case 'Y':
2636
 
        case 'a': case 'A': case 's': case 'c': case 'C':
2637
 
          if (l < 4)
2638
 
            break;
2639
 
          if (tm == 0)
2640
 
            {
2641
 
              time_t nowsec = now.tv_sec;
2642
 
              tm = localtime(&nowsec);
2643
 
            }
2644
 
          qmflag = 1;
2645
 
          if (!tick || tick > 3600)
2646
 
            tick = 3600;
2647
 
          switch (*s)
2648
 
            {
2649
 
            case 'd':
2650
 
              sprintf(p, "%02d", tm->tm_mday % 100);
2651
 
              break;
2652
 
            case 'D':
2653
 
#ifdef USE_LOCALE
2654
 
              strftime(p, l, (longflg ? "%A" : "%a"), tm);
2655
 
#else
2656
 
              sprintf(p, "%3.3s", days + 3 * tm->tm_wday);
2657
 
#endif
2658
 
              break;
2659
 
            case 'm':
2660
 
              sprintf(p, "%02d", tm->tm_mon + 1);
2661
 
              break;
2662
 
            case 'M':
2663
 
#ifdef USE_LOCALE
2664
 
              strftime(p, l, (longflg ? "%B" : "%b"), tm);
2665
 
#else
2666
 
              sprintf(p, "%3.3s", months + 3 * tm->tm_mon);
2667
 
#endif
2668
 
              break;
2669
 
            case 'y':
2670
 
              sprintf(p, "%02d", tm->tm_year % 100);
2671
 
              break;
2672
 
            case 'Y':
2673
 
              sprintf(p, "%04d", tm->tm_year + 1900);
2674
 
              break;
2675
 
            case 'a':
2676
 
              sprintf(p, tm->tm_hour >= 12 ? "pm" : "am");
2677
 
              break;
2678
 
            case 'A':
2679
 
              sprintf(p, tm->tm_hour >= 12 ? "PM" : "AM");
2680
 
              break;
2681
 
            case 's':
2682
 
              sprintf(p, "%02d", tm->tm_sec);
2683
 
              tick = 1;
2684
 
              break;
2685
 
            case 'c':
2686
 
              sprintf(p, zeroflg ? "%02d:%02d" : "%2d:%02d", tm->tm_hour, tm->tm_min);
2687
 
              if (!tick || tick > 60)
2688
 
                tick = 60;
2689
 
              break;
2690
 
            case 'C':
2691
 
              sprintf(p, zeroflg ? "%02d:%02d" : "%2d:%02d", (tm->tm_hour + 11) % 12 + 1, tm->tm_min);
2692
 
              if (!tick || tick > 60)
2693
 
                tick = 60;
2694
 
              break;
2695
 
            default:
2696
 
              break;
2697
 
            }
2698
 
          p += strlen(p) - 1;
2699
 
          break;
2700
 
        case 'l':
2701
 
#ifdef LOADAV
2702
 
          *p = 0;
2703
 
          if (l > 20)
2704
 
            AddLoadav(p);
2705
 
          if (*p)
2706
 
            {
2707
 
              qmflag = 1;
2708
 
              p += strlen(p) - 1;
2709
 
            }
2710
 
          else
2711
 
            *p = '?';
2712
 
          if (!tick || tick > 60)
2713
 
            tick = 60;
2714
 
#else
2715
 
          *p = '?';
2716
 
#endif
2717
 
          p += strlen(p) - 1;
2718
 
          break;
2719
 
        case '`':
2720
 
        case 'h':
2721
 
          if (rec >= 10 || (*s == 'h' && (win == 0 || win->w_hstatus == 0 || *win->w_hstatus == 0)))
2722
 
            {
2723
 
              p--;
2724
 
              break;
2725
 
            }
2726
 
          if (*s == '`')
2727
 
            {
2728
 
              for (bt = backticks; bt; bt = bt->next)
2729
 
                if (bt->num == num)
2730
 
                  break;
2731
 
              if (bt == 0)
2732
 
                {
2733
 
                  p--;
2734
 
                  break;
2735
 
                }
2736
 
            }
2737
 
            {
2738
 
              char savebuf[sizeof(winmsg_buf)];
2739
 
              int oldtick = tick;
2740
 
              int oldnumrend = winmsg_numrend;
2741
 
 
2742
 
              *p = 0;
2743
 
              strcpy(savebuf, winmsg_buf);
2744
 
              winmsg_numrend = -winmsg_numrend;
2745
 
              MakeWinMsgEv(*s == 'h' ? win->w_hstatus : runbacktick(bt, &oldtick, now.tv_sec), win, '\005', 0, (struct event *)0, rec + 1);
2746
 
              debug2("oldtick=%d tick=%d\n", oldtick, tick);
2747
 
              if (!tick || oldtick < tick)
2748
 
                tick = oldtick;
2749
 
              if ((int)strlen(winmsg_buf) < l)
2750
 
                strcat(savebuf, winmsg_buf);
2751
 
              strcpy(winmsg_buf, savebuf);
2752
 
              while (oldnumrend < winmsg_numrend)
2753
 
                winmsg_rendpos[oldnumrend++] += p - winmsg_buf;
2754
 
              if (*p)
2755
 
                qmflag = 1;
2756
 
              p += strlen(p) - 1;
2757
 
            }
2758
 
          break;
2759
 
        case 'w':
2760
 
        case 'W':
2761
 
          {
2762
 
            struct win *oldfore = 0;
2763
 
            char *ss;
2764
 
 
2765
 
            if (display)
2766
 
              {
2767
 
                oldfore = D_fore;
2768
 
                D_fore = win;
2769
 
              }
2770
 
            ss = AddWindows(p, l - 1, (*s == 'w' ? 0 : 1) | (longflg ? 0 : 2) | (plusflg ? 4 : 0) | (minusflg ? 8 : 0), win ? win->w_number : -1);
2771
 
            if (display)
2772
 
              D_fore = oldfore;
2773
 
          }
2774
 
          if (*p)
2775
 
            qmflag = 1;
2776
 
          p += strlen(p) - 1;
2777
 
          break;
2778
 
        case 'u':
2779
 
          *p = 0;
2780
 
          if (win)
2781
 
            AddOtherUsers(p, l - 1, win);
2782
 
          if (*p)
2783
 
            qmflag = 1;
2784
 
          p += strlen(p) - 1;
2785
 
          break;
2786
 
        case 'f':
2787
 
          *p = 0;
2788
 
          if (win)
2789
 
            AddWindowFlags(p, l - 1, win);
2790
 
          if (*p)
2791
 
            qmflag = 1;
2792
 
          p += strlen(p) - 1;
2793
 
          break;
2794
 
        case 't':
2795
 
          *p = 0;
2796
 
          if (win && (int)strlen(win->w_title) < l)
2797
 
            {
2798
 
              strcpy(p, win->w_title);
2799
 
              if (*p)
2800
 
                qmflag = 1;
2801
 
            }
2802
 
          p += strlen(p) - 1;
2803
 
          break;
2804
 
        #ifdef ENCODINGS
2805
 
        case 'e':
2806
 
            *p = 0;
2807
 
            D_encoding = nwin_options.encoding > 0 ? nwin_options.encoding : 0;
2808
 
            if (win && win->w_encoding)
2809
 
            {
2810
 
                *p++ = ' ';
2811
 
                strcpy(p, EncodingName(win->w_encoding));
2812
 
            }
2813
 
            p += strlen(p) - 1;
2814
 
            break;
2815
 
        #endif
2816
 
        case '{':
2817
 
          {
2818
 
            char rbuf[128];
2819
 
            s++;
2820
 
            for (i = 0; i < 127; i++)
2821
 
              if (s[i] && s[i] != '}')
2822
 
                rbuf[i] = s[i];
2823
 
              else
2824
 
                break;
2825
 
            if (s[i] == '}' && winmsg_numrend < MAX_WINMSG_REND)
2826
 
              {
2827
 
                r = -1;
2828
 
                rbuf[i] = 0;
2829
 
                debug1("MakeWinMsg attrcolor %s\n", rbuf);
2830
 
                if (i != 1 || rbuf[0] != '-')
2831
 
                  r = ParseAttrColor(rbuf, (char *)0, 0);
2832
 
                if (r != -1 || (i == 1 && rbuf[0] == '-'))
2833
 
                  {
2834
 
                    winmsg_rend[winmsg_numrend] = r;
2835
 
                    winmsg_rendpos[winmsg_numrend] = p - winmsg_buf;
2836
 
                    winmsg_numrend++;
2837
 
                  }
2838
 
              }
2839
 
            s += i;
2840
 
            p--;
2841
 
          }
2842
 
          break;
2843
 
        case 'H':
2844
 
          *p = 0;
2845
 
          if ((int)strlen(HostName) < l)
2846
 
            {
2847
 
              strcpy(p, HostName);
2848
 
              if (*p)
2849
 
                qmflag = 1;
2850
 
            }
2851
 
          p += strlen(p) - 1;
2852
 
          break;
2853
 
        case 'S':
2854
 
          {
2855
 
            char *session_name;
2856
 
            *p = 0;
2857
 
            session_name = strchr(SockName, '.') + 1;
2858
 
            if ((int)strlen(session_name) < l)
2859
 
              {
2860
 
                strcpy(p, session_name);
2861
 
                if (*p)
2862
 
                  qmflag = 1;
2863
 
              }
2864
 
            p += strlen(p) - 1;
2865
 
          }
2866
 
          break;
2867
 
        case 'p':
2868
 
          {
2869
 
            sprintf(p, "%d", (plusflg && display) ? D_userpid : getpid());
2870
 
            p += strlen(p) - 1;
2871
 
          }
2872
 
          break;
2873
 
        case 'F':
2874
 
          p--;
2875
 
          /* small hack */
2876
 
          if (display && ((ev && ev == &D_forecv->c_captev) || (!ev && win && win == D_fore)))
2877
 
            minusflg = !minusflg;
2878
 
          if (minusflg)
2879
 
            qmflag = 1;
2880
 
          break;
2881
 
        case 'P':
2882
 
          p--;
2883
 
#ifdef COPY_PASTE
2884
 
          if (display && ev && ev != &D_hstatusev)      /* Hack */
2885
 
            {
2886
 
              /* Is the layer in the current canvas in copy mode? */
2887
 
              struct canvas *cv = (struct canvas *)ev->data;
2888
 
              if (ev == &cv->c_captev && cv->c_layer->l_layfn == &MarkLf)
2889
 
                qmflag = 1;
2890
 
            }
2891
 
#endif
2892
 
          break;
2893
 
        case 'E':
2894
 
          p--;
2895
 
          if (display && D_ESCseen)
2896
 
            qmflag = 1;
2897
 
          break;
2898
 
        case '>':
2899
 
          truncpos = p - winmsg_buf;
2900
 
          truncper = num > 100 ? 100 : num;
2901
 
          trunclong = longflg;
2902
 
          p--;
2903
 
          break;
2904
 
        case '=':
2905
 
        case '<':
2906
 
          *p = ' ';
2907
 
          if (num || zeroflg || plusflg || longflg || (*s != '='))
2908
 
            {
2909
 
              /* expand all pads */
2910
 
              if (minusflg)
2911
 
                {
2912
 
                  num = (plusflg ? lastpad : padlen) - num;
2913
 
                  if (!plusflg && padlen == 0)
2914
 
                    num = p - winmsg_buf;
2915
 
                  plusflg = 0;
2916
 
                }
2917
 
              else if (!zeroflg)
2918
 
                {
2919
 
                  if (*s != '=' && num == 0 && !plusflg)
2920
 
                    num = 100;
2921
 
                  if (num > 100)
2922
 
                    num = 100;
2923
 
                  if (padlen == 0)
2924
 
                    num = p - winmsg_buf;
2925
 
                  else
2926
 
                    num = (padlen - (plusflg ? lastpad : 0)) * num / 100;
2927
 
                }
2928
 
              if (num < 0)
2929
 
                num = 0;
2930
 
              if (plusflg)
2931
 
                num += lastpad;
2932
 
              if (num > MAXSTR - 1)
2933
 
                num = MAXSTR - 1;
2934
 
              if (numpad)
2935
 
                p = pad_expand(winmsg_buf, p, numpad, num);
2936
 
              numpad = 0;
2937
 
              if (p - winmsg_buf > num && !longflg)
2938
 
                {
2939
 
                  int left, trunc;
2940
 
 
2941
 
                  if (truncpos == -1)
2942
 
                    {
2943
 
                      truncpos = lastpad;
2944
 
                      truncper = 0;
2945
 
                    }
2946
 
                  trunc = lastpad + truncper * (num - lastpad) / 100;
2947
 
                  if (trunc > num)
2948
 
                    trunc = num;
2949
 
                  if (trunc < lastpad)
2950
 
                    trunc = lastpad;
2951
 
                  left = truncpos - trunc;
2952
 
                  if (left > p - winmsg_buf - num)
2953
 
                    left = p - winmsg_buf - num;
2954
 
                  debug1("lastpad = %d, ", lastpad);
2955
 
                  debug3("truncpos = %d, trunc = %d, left = %d\n", truncpos, trunc, left);
2956
 
                  if (left > 0)
2957
 
                    {
2958
 
                      if (left + lastpad > p - winmsg_buf)
2959
 
                        left = p - winmsg_buf - lastpad;
2960
 
                      if (p - winmsg_buf - lastpad - left > 0)
2961
 
                        bcopy(winmsg_buf + lastpad + left, winmsg_buf + lastpad,  p - winmsg_buf - lastpad - left);
2962
 
                      p -= left;
2963
 
                      r = winmsg_numrend;
2964
 
                      while (r && winmsg_rendpos[r - 1] > lastpad)
2965
 
                        {
2966
 
                          r--;
2967
 
                          winmsg_rendpos[r] -= left;
2968
 
                          if (winmsg_rendpos[r] < lastpad)
2969
 
                            winmsg_rendpos[r] = lastpad;
2970
 
                        }
2971
 
                      if (trunclong)
2972
 
                        {
2973
 
                          if (p - winmsg_buf > lastpad)
2974
 
                            winmsg_buf[lastpad] = '.';
2975
 
                          if (p - winmsg_buf > lastpad + 1)
2976
 
                            winmsg_buf[lastpad + 1] = '.';
2977
 
                          if (p - winmsg_buf > lastpad + 2)
2978
 
                            winmsg_buf[lastpad + 2] = '.';
2979
 
                        }
2980
 
                    }
2981
 
                  if (p - winmsg_buf > num)
2982
 
                    {
2983
 
                      p = winmsg_buf + num;
2984
 
                      if (trunclong)
2985
 
                        {
2986
 
                          if (num - 1 >= lastpad)
2987
 
                            p[-1] = '.';
2988
 
                          if (num - 2 >= lastpad)
2989
 
                            p[-2] = '.';
2990
 
                          if (num - 3 >= lastpad)
2991
 
                            p[-3] = '.';
2992
 
                        }
2993
 
                      r = winmsg_numrend;
2994
 
                      while (r && winmsg_rendpos[r - 1] > num)
2995
 
                        winmsg_rendpos[--r] = num;
2996
 
                    }
2997
 
                  truncpos = -1;
2998
 
                  trunclong = 0;
2999
 
                  if (lastpad > p - winmsg_buf)
3000
 
                    lastpad = p - winmsg_buf;
3001
 
                  debug1("lastpad now %d\n", lastpad);
3002
 
                }
3003
 
              if (*s == '=')
3004
 
                {
3005
 
                  while (p - winmsg_buf < num)
3006
 
                    *p++ = ' ';
3007
 
                  lastpad = p - winmsg_buf;
3008
 
                  truncpos = -1;
3009
 
                  trunclong = 0;
3010
 
                  debug1("lastpad2 now %d\n", lastpad);
3011
 
                }
3012
 
              p--;
3013
 
            }
3014
 
          else if (padlen)
3015
 
            {
3016
 
              *p = 127;         /* internal pad representation */
3017
 
              numpad++;
3018
 
            }
3019
 
          break;
3020
 
        case 'n':
3021
 
          s++;
3022
 
          /* FALLTHROUGH */
3023
 
        default:
3024
 
          s--;
3025
 
          if (l > 10 + num)
3026
 
            {
3027
 
              if (num == 0)
3028
 
                num = 1;
3029
 
              if (!win)
3030
 
                sprintf(p, "%*s", num, num > 1 ? "--" : "-");
3031
 
              else
3032
 
                sprintf(p, "%*d", num, win->w_number);
3033
 
              qmflag = 1;
3034
 
              p += strlen(p) - 1;
3035
 
            }
3036
 
          break;
3037
 
        }
3038
 
    }
3039
 
  if (qmpos && !qmflag)
3040
 
    p = qmpos + 1;
3041
 
  *p = '\0';
3042
 
  if (numpad)
3043
 
    {
3044
 
      if (padlen > MAXSTR - 1)
3045
 
        padlen = MAXSTR - 1;
3046
 
      p = pad_expand(winmsg_buf, p, numpad, padlen);
3047
 
    }
3048
 
  if (ev)
3049
 
    {
3050
 
      evdeq(ev);                /* just in case */
3051
 
      ev->timeout.tv_sec = 0;
3052
 
      ev->timeout.tv_usec = 0;
3053
 
    }
3054
 
  if (ev && tick)
3055
 
    {
3056
 
      now.tv_usec = 100000;
3057
 
      if (tick == 1)
3058
 
        now.tv_sec++;
3059
 
      else
3060
 
        now.tv_sec += tick - (now.tv_sec % tick);
3061
 
      ev->timeout = now;
3062
 
      debug2("NEW timeout %d %d\n", ev->timeout.tv_sec, tick);
3063
 
    }
3064
 
  return winmsg_buf;
3065
 
}
3066
 
 
3067
 
char *
3068
 
MakeWinMsg(s, win, esc)
3069
 
char *s;
3070
 
struct win *win;
3071
 
int esc;
3072
 
{
3073
 
  return MakeWinMsgEv(s, win, esc, 0, (struct event *)0, 0);
3074
 
}
3075
 
 
3076
 
void
3077
 
PutWinMsg(s, start, max)
3078
 
char *s;
3079
 
int start, max;
3080
 
{
3081
 
  int i, p, l, r, n;
3082
 
  struct mchar rend;
3083
 
  struct mchar rendstack[MAX_WINMSG_REND];
3084
 
  int rendstackn = 0;
3085
 
 
3086
 
  if (s != winmsg_buf)
3087
 
    {
3088
 
      /* sorry, no fancy coloring available */
3089
 
      debug1("PutWinMsg %s plain\n", s);
3090
 
      l = strlen(s);
3091
 
      if (l > max)
3092
 
        l = max;
3093
 
      l -= start;
3094
 
      s += start;
3095
 
      while (l-- > 0)
3096
 
        PUTCHARLP(*s++);
3097
 
      return;
3098
 
    }
3099
 
  rend = D_rend;
3100
 
  p = 0;
3101
 
  l = strlen(s);
3102
 
  debug2("PutWinMsg %s start attr %x\n", s, rend.attr);
3103
 
  for (i = 0; i < winmsg_numrend && max > 0; i++)
3104
 
    {
3105
 
      if (p > winmsg_rendpos[i] || winmsg_rendpos[i] > l)
3106
 
        break;
3107
 
      if (p < winmsg_rendpos[i])
3108
 
        {
3109
 
          n = winmsg_rendpos[i] - p;
3110
 
          if (n > max)
3111
 
            n = max;
3112
 
          max -= n;
3113
 
          p += n;
3114
 
          while(n-- > 0)
3115
 
            {
3116
 
              if (start-- > 0)
3117
 
                s++;
3118
 
              else
3119
 
                PUTCHARLP(*s++);
3120
 
            }
3121
 
        }
3122
 
      r = winmsg_rend[i];
3123
 
      if (r == -1)
3124
 
        {
3125
 
          if (rendstackn > 0)
3126
 
            rend = rendstack[--rendstackn];
3127
 
        }
3128
 
      else
3129
 
        {
3130
 
          rendstack[rendstackn++] = rend;
3131
 
          ApplyAttrColor(r, &rend);
3132
 
        }
3133
 
      SetRendition(&rend);
3134
 
    }
3135
 
  if (p < l)
3136
 
    {
3137
 
      n = l - p;
3138
 
      if (n > max)
3139
 
        n = max;
3140
 
      while(n-- > 0)
3141
 
        {
3142
 
          if (start-- > 0)
3143
 
            s++;
3144
 
          else
3145
 
            PUTCHARLP(*s++);
3146
 
        }
3147
 
    }
3148
 
}
3149
 
 
3150
 
 
3151
 
#ifdef DEBUG
3152
 
static void
3153
 
fds1(i, j)
3154
 
int i, j;
3155
 
{
3156
 
  while (i < j)
3157
 
    {
3158
 
      debug1("%d ", i);
3159
 
      i++;
3160
 
    }
3161
 
  if ((j = open("/dev/null", 0)) >= 0)
3162
 
    {
3163
 
      fds1(i + 1, j);
3164
 
      close(j);
3165
 
    }
3166
 
  else
3167
 
    {
3168
 
      while (dup(++i) < 0 && errno != EBADF)
3169
 
        debug1("%d ", i);
3170
 
      debug1(" [%d]\n", i);
3171
 
    }
3172
 
}
3173
 
 
3174
 
static void
3175
 
fds()
3176
 
{
3177
 
  debug("fds: ");
3178
 
  fds1(-1, -1);
3179
 
}
3180
 
#endif
3181
 
 
3182
 
static void
3183
 
serv_read_fn(ev, data)
3184
 
struct event *ev;
3185
 
char *data;
3186
 
{
3187
 
  debug("Knock - knock!\n");
3188
 
  ReceiveMsg();
3189
 
}
3190
 
 
3191
 
static void
3192
 
serv_select_fn(ev, data)
3193
 
struct event *ev;
3194
 
char *data;
3195
 
{
3196
 
  struct win *p;
3197
 
 
3198
 
  debug("serv_select_fn called\n");
3199
 
  /* XXX: messages?? */
3200
 
  if (GotSigChld)
3201
 
    {
3202
 
      SigChldHandler();
3203
 
    }
3204
 
  if (InterruptPlease)
3205
 
    {
3206
 
      debug("Backend received interrupt\n");
3207
 
      /* This approach is rather questionable in a multi-display
3208
 
       * environment */
3209
 
      if (fore && displays)
3210
 
        {
3211
 
#if defined(TERMIO) || defined(POSIX)
3212
 
          char ibuf = displays->d_OldMode.tio.c_cc[VINTR];
3213
 
#else
3214
 
          char ibuf = displays->d_OldMode.m_tchars.t_intrc;
3215
 
#endif
3216
 
#ifdef PSEUDOS
3217
 
          write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd, 
3218
 
                &ibuf, 1);
3219
 
          debug1("Backend wrote interrupt to %d", fore->w_number);
3220
 
          debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : "");
3221
 
#else
3222
 
          write(fore->w_ptyfd, &ibuf, 1);
3223
 
          debug1("Backend wrote interrupt to %d\n", fore->w_number);
3224
 
#endif
3225
 
        }
3226
 
      InterruptPlease = 0;
3227
 
    }
3228
 
 
3229
 
  for (p = windows; p; p = p->w_next)
3230
 
    {
3231
 
      if (p->w_bell == BELL_FOUND || p->w_bell == BELL_VISUAL)
3232
 
        {
3233
 
          struct canvas *cv;
3234
 
          int visual = p->w_bell == BELL_VISUAL || visual_bell;
3235
 
          p->w_bell = BELL_ON;
3236
 
          for (display = displays; display; display = display->d_next)
3237
 
            {
3238
 
              for (cv = D_cvlist; cv; cv = cv->c_next)
3239
 
                if (cv->c_layer->l_bottom == &p->w_layer)
3240
 
                  break;
3241
 
              if (cv == 0)
3242
 
                {
3243
 
                  p->w_bell = BELL_DONE;
3244
 
                  Msg(0, "%s", MakeWinMsg(BellString, p, '%'));
3245
 
                }
3246
 
              else if (visual && !D_VB && (!D_status || !D_status_bell))
3247
 
                {
3248
 
                  Msg(0, "%s", VisualBellString);
3249
 
                  if (D_status)
3250
 
                    {
3251
 
                      D_status_bell = 1;
3252
 
                      debug1("using vbell timeout %d\n", VBellWait);
3253
 
                      SetTimeout(&D_statusev, VBellWait );
3254
 
                    }
3255
 
                }
3256
 
            }
3257
 
          /* don't annoy the user with two messages */
3258
 
          if (p->w_monitor == MON_FOUND)
3259
 
            p->w_monitor = MON_DONE;
3260
 
          WindowChanged(p, 'f');
3261
 
        }
3262
 
      if (p->w_monitor == MON_FOUND)
3263
 
        {
3264
 
          struct canvas *cv;
3265
 
          p->w_monitor = MON_ON;
3266
 
          for (display = displays; display; display = display->d_next)
3267
 
            {
3268
 
              for (cv = D_cvlist; cv; cv = cv->c_next)
3269
 
                if (cv->c_layer->l_bottom == &p->w_layer)
3270
 
                  break;
3271
 
              if (cv)
3272
 
                continue;       /* user already sees window */
3273
 
#ifdef MULTIUSER
3274
 
              if (!(ACLBYTE(p->w_mon_notify, D_user->u_id) & ACLBIT(D_user->u_id)))
3275
 
                continue;       /* user doesn't care */
3276
 
#endif
3277
 
              Msg(0, "%s", MakeWinMsg(ActivityString, p, '%'));
3278
 
              p->w_monitor = MON_DONE;
3279
 
            }
3280
 
          WindowChanged(p, 'f');
3281
 
        }
3282
 
      if (p->w_silence == SILENCE_FOUND)
3283
 
        {
3284
 
          /* Unset the flag if the user switched to this window. */
3285
 
          if (p->w_layer.l_cvlist)
3286
 
            {
3287
 
              p->w_silence = SILENCE_ON;
3288
 
              WindowChanged(p, 'f');
3289
 
            }
3290
 
        }
3291
 
    }
3292
 
 
3293
 
  for (display = displays; display; display = display->d_next)
3294
 
    {
3295
 
      struct canvas *cv;
3296
 
      if (D_status == STATUS_ON_WIN)
3297
 
        continue;
3298
 
      /* XXX: should use display functions! */
3299
 
      for (cv = D_cvlist; cv; cv = cv->c_next)
3300
 
        {
3301
 
          int lx, ly;
3302
 
 
3303
 
          /* normalize window, see resize.c */
3304
 
          lx = cv->c_layer->l_x;
3305
 
          ly = cv->c_layer->l_y;
3306
 
          if (lx == cv->c_layer->l_width)
3307
 
            lx--;
3308
 
          if (ly + cv->c_yoff < cv->c_ys)
3309
 
            {
3310
 
              int i, n = cv->c_ys - (ly + cv->c_yoff);
3311
 
              cv->c_yoff = cv->c_ys - ly;
3312
 
              RethinkViewportOffsets(cv);
3313
 
              if (n > cv->c_layer->l_height)
3314
 
                n = cv->c_layer->l_height;
3315
 
              CV_CALL(cv, 
3316
 
                LScrollV(flayer, -n, 0, flayer->l_height - 1, 0);
3317
 
                LayRedisplayLine(-1, -1, -1, 1);
3318
 
                for (i = 0; i < n; i++)
3319
 
                  LayRedisplayLine(i, 0, flayer->l_width - 1, 1);
3320
 
                if (cv == cv->c_display->d_forecv)
3321
 
                  LaySetCursor();
3322
 
              );
3323
 
            }
3324
 
          else if (ly + cv->c_yoff > cv->c_ye)
3325
 
            {
3326
 
              int i, n = ly + cv->c_yoff - cv->c_ye;
3327
 
              cv->c_yoff = cv->c_ye - ly;
3328
 
              RethinkViewportOffsets(cv);
3329
 
              if (n > cv->c_layer->l_height)
3330
 
                n = cv->c_layer->l_height;
3331
 
              CV_CALL(cv, 
3332
 
                LScrollV(flayer, n, 0, cv->c_layer->l_height - 1, 0);
3333
 
                LayRedisplayLine(-1, -1, -1, 1);
3334
 
                for (i = 0; i < n; i++)
3335
 
                  LayRedisplayLine(i + flayer->l_height - n, 0, flayer->l_width - 1, 1);
3336
 
                if (cv == cv->c_display->d_forecv)
3337
 
                  LaySetCursor();
3338
 
              );
3339
 
            }
3340
 
          if (lx + cv->c_xoff < cv->c_xs)
3341
 
            {
3342
 
              int i, n = cv->c_xs - (lx + cv->c_xoff);
3343
 
              if (n < (cv->c_xe - cv->c_xs + 1) / 2)
3344
 
                n = (cv->c_xe - cv->c_xs + 1) / 2;
3345
 
              if (cv->c_xoff + n > cv->c_xs)
3346
 
                n = cv->c_xs - cv->c_xoff;
3347
 
              cv->c_xoff += n;
3348
 
              RethinkViewportOffsets(cv);
3349
 
              if (n > cv->c_layer->l_width)
3350
 
                n = cv->c_layer->l_width;
3351
 
              CV_CALL(cv, 
3352
 
                LayRedisplayLine(-1, -1, -1, 1);
3353
 
                for (i = 0; i < flayer->l_height; i++)
3354
 
                  {
3355
 
                    LScrollH(flayer, -n, i, 0, flayer->l_width - 1, 0, 0);
3356
 
                    LayRedisplayLine(i, 0, n - 1, 1);
3357
 
                  }
3358
 
                if (cv == cv->c_display->d_forecv)
3359
 
                  LaySetCursor();
3360
 
              );
3361
 
            }
3362
 
          else if (lx + cv->c_xoff > cv->c_xe)
3363
 
            {
3364
 
              int i, n = lx + cv->c_xoff - cv->c_xe;
3365
 
              if (n < (cv->c_xe - cv->c_xs + 1) / 2)
3366
 
                n = (cv->c_xe - cv->c_xs + 1) / 2;
3367
 
              if (cv->c_xoff - n + cv->c_layer->l_width - 1 < cv->c_xe)
3368
 
                n = cv->c_xoff + cv->c_layer->l_width - 1 - cv->c_xe;
3369
 
              cv->c_xoff -= n;
3370
 
              RethinkViewportOffsets(cv);
3371
 
              if (n > cv->c_layer->l_width)
3372
 
                n = cv->c_layer->l_width;
3373
 
              CV_CALL(cv, 
3374
 
                LayRedisplayLine(-1, -1, -1, 1);
3375
 
                for (i = 0; i < flayer->l_height; i++)
3376
 
                  {
3377
 
                    LScrollH(flayer, n, i, 0, flayer->l_width - 1, 0, 0);
3378
 
                    LayRedisplayLine(i, flayer->l_width - n, flayer->l_width - 1, 1);
3379
 
                  }
3380
 
                if (cv == cv->c_display->d_forecv)
3381
 
                  LaySetCursor();
3382
 
              );
3383
 
            }
3384
 
        }
3385
 
    }
3386
 
 
3387
 
  for (display = displays; display; display = display->d_next)
3388
 
    {
3389
 
      if (D_status == STATUS_ON_WIN || D_cvlist == 0 || D_cvlist->c_next == 0)
3390
 
        continue;
3391
 
      debug1("serv_select_fn: Restore on cv %#x\n", (int)D_forecv);
3392
 
      CV_CALL(D_forecv, LayRestore();LaySetCursor());
3393
 
    }
3394
 
}
3395
 
 
3396
 
static void
3397
 
logflush_fn(ev, data)
3398
 
struct event *ev;
3399
 
char *data;
3400
 
{
3401
 
  struct win *p;
3402
 
  char *buf;
3403
 
  int n;
3404
 
 
3405
 
  if (!islogfile(NULL))
3406
 
    return;             /* no more logfiles */
3407
 
  logfflush(NULL);
3408
 
  n = log_flush ? log_flush : (logtstamp_after + 4) / 5;
3409
 
  if (n)
3410
 
    {
3411
 
      SetTimeout(ev, n * 1000);
3412
 
      evenq(ev);        /* re-enqueue ourself */
3413
 
    }
3414
 
  if (!logtstamp_on)
3415
 
    return;
3416
 
  /* write fancy time-stamp */
3417
 
  for (p = windows; p; p = p->w_next)
3418
 
    {
3419
 
      if (!p->w_log)
3420
 
        continue;
3421
 
      p->w_logsilence += n;
3422
 
      if (p->w_logsilence < logtstamp_after)
3423
 
        continue;
3424
 
      if (p->w_logsilence - n >= logtstamp_after)
3425
 
        continue;
3426
 
      buf = MakeWinMsg(logtstamp_string, p, '%');
3427
 
      logfwrite(p->w_log, buf, strlen(buf));
3428
 
    }
3429
 
}
3430
 
 
3431
 
/*
3432
 
 * Interprets ^?, ^@ and other ^-control-char notation.
3433
 
 * Interprets \ddd octal notation
3434
 
 * 
3435
 
 * The result is placed in *cp, p is advanced behind the parsed expression and 
3436
 
 * returned. 
3437
 
 */
3438
 
static char *
3439
 
ParseChar(p, cp)
3440
 
char *p, *cp;
3441
 
{
3442
 
  if (*p == 0)
3443
 
    return 0;
3444
 
  if (*p == '^' && p[1])
3445
 
    {
3446
 
      if (*++p == '?')
3447
 
        *cp = '\177';
3448
 
      else if (*p >= '@')
3449
 
        *cp = Ctrl(*p);
3450
 
      else
3451
 
        return 0;
3452
 
      ++p;
3453
 
    }
3454
 
  else if (*p == '\\' && *++p <= '7' && *p >= '0')
3455
 
    {
3456
 
      *cp = 0;
3457
 
      do
3458
 
        *cp = *cp * 8 + *p - '0';
3459
 
      while (*++p <= '7' && *p >= '0');
3460
 
    }
3461
 
  else
3462
 
    *cp = *p++;
3463
 
  return p;
3464
 
}
3465
 
 
3466
 
static int 
3467
 
ParseEscape(p)
3468
 
char *p;
3469
 
{
3470
 
  unsigned char buf[2];
3471
 
 
3472
 
  if (*p == 0)
3473
 
    SetEscape((struct acluser *)0, -1, -1);
3474
 
  else
3475
 
    {
3476
 
      if ((p = ParseChar(p, (char *)buf)) == NULL ||
3477
 
          (p = ParseChar(p, (char *)buf+1)) == NULL || *p)
3478
 
        return -1;
3479
 
      SetEscape((struct acluser *)0, buf[0], buf[1]);
3480
 
    }
3481
 
  return 0;
3482
 
}
3483