~dannf/ubuntu/saucy/screen/lp1213278-from-debian

« back to all changes in this revision

Viewing changes to socket.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1993-2002
 
2
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
 
3
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
 
4
 * Copyright (c) 1987 Oliver Laumann
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program (see the file COPYING); if not, write to the
 
18
 * Free Software Foundation, Inc.,
 
19
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 
20
 *
 
21
 ****************************************************************
 
22
 */
 
23
 
 
24
#include "config.h"
 
25
#include <sys/types.h>
 
26
#include <sys/stat.h>
 
27
#include <fcntl.h>
 
28
#if !defined(NAMEDPIPE)
 
29
#include <sys/socket.h>
 
30
#include <sys/un.h>
 
31
#endif
 
32
 
 
33
#ifndef SIGINT
 
34
# include <signal.h>
 
35
#endif
 
36
 
 
37
#include "screen.h"
 
38
 
 
39
#ifdef HAVE_DIRENT_H
 
40
# include <dirent.h>
 
41
#else
 
42
# include <sys/dir.h>
 
43
# define dirent direct
 
44
#endif
 
45
 
 
46
#include "extern.h"
 
47
 
 
48
static int   CheckPid __P((int));
 
49
static void  ExecCreate __P((struct msg *));
 
50
static void  DoCommandMsg __P((struct msg *));
 
51
#if defined(_SEQUENT_) && !defined(NAMEDPIPE)
 
52
# define connect sconnect       /* _SEQUENT_ has braindamaged connect */
 
53
static int   sconnect __P((int, struct sockaddr *, int));
 
54
#endif
 
55
static void  FinishAttach __P((struct msg *));
 
56
static void  AskPassword __P((struct msg *));
 
57
 
 
58
 
 
59
extern char *RcFileName, *extra_incap, *extra_outcap;
 
60
extern int ServerSocket, real_uid, real_gid, eff_uid, eff_gid;
 
61
extern int dflag, iflag, rflag, lsflag, quietflag, wipeflag, xflag;
 
62
extern char *attach_tty, *LoginName, HostName[];
 
63
extern struct display *display, *displays;
 
64
extern struct win *fore, *wtab[], *console_window, *windows;
 
65
extern struct layer *flayer;
 
66
extern struct NewWindow nwin_undef;
 
67
#ifdef MULTIUSER
 
68
extern char *multi;
 
69
#endif
 
70
 
 
71
extern char *getenv();
 
72
 
 
73
extern char SockPath[];
 
74
extern struct event serv_read;
 
75
extern char *rc_name;
 
76
extern struct comm comms[];
 
77
 
 
78
#ifdef MULTIUSER
 
79
# define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0))
 
80
#else
 
81
# define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0))
 
82
#endif
 
83
 
 
84
 
 
85
/*
 
86
 *  Socket directory manager
 
87
 *
 
88
 *  fdp: pointer to store the first good socket.
 
89
 *  nfoundp: pointer to store the number of sockets found matching.
 
90
 *  notherp: pointer to store the number of sockets not matching.
 
91
 *  match: string to match socket name.
 
92
 *
 
93
 *  The socket directory must be in SockPath!
 
94
 *  The global variables LoginName, multi, rflag, xflag, dflag,
 
95
 *  quietflag, SockPath are used.
 
96
 *
 
97
 *  The first good socket is stored in fdp and its name is
 
98
 *  appended to SockPath.
 
99
 *  If none exists or fdp is NULL SockPath is not changed.
 
100
 *
 
101
 *  Returns: number of good sockets.
 
102
 *    
 
103
 */
 
104
 
 
105
int
 
106
FindSocket(fdp, nfoundp, notherp, match)
 
107
int *fdp;
 
108
int *nfoundp, *notherp;
 
109
char *match;
 
110
{
 
111
  DIR *dirp;
 
112
  struct dirent *dp;
 
113
  struct stat st;
 
114
  int mode;
 
115
  int sdirlen;
 
116
  int  matchlen = 0;
 
117
  char *name, *n;
 
118
  int firsts = -1, sockfd;
 
119
  char *firstn = NULL;
 
120
  int nfound = 0, ngood = 0, ndead = 0, nwipe = 0, npriv = 0;
 
121
  struct sent
 
122
    {
 
123
      struct sent *next;
 
124
      int mode;
 
125
      char *name;
 
126
    } *slist, **slisttail, *sent, *nsent;
 
127
          
 
128
  if (match)
 
129
    {
 
130
      matchlen = strlen(match);
 
131
#ifdef NAME_MAX
 
132
      if (matchlen > NAME_MAX)
 
133
        matchlen = NAME_MAX;
 
134
#endif
 
135
    }
 
136
 
 
137
  /*
 
138
   * SockPath contains the socket directory.
 
139
   * At the end of FindSocket the socket name will be appended to it.
 
140
   * Thus FindSocket() can only be called once!
 
141
   */
 
142
  sdirlen = strlen(SockPath);
 
143
 
 
144
#ifdef USE_SETEUID
 
145
  xseteuid(real_uid);
 
146
  xsetegid(real_gid);
 
147
#endif
 
148
 
 
149
  if ((dirp = opendir(SockPath)) == 0)
 
150
    Panic(errno, "Cannot opendir %s", SockPath);
 
151
 
 
152
  slist = 0;
 
153
  slisttail = &slist;
 
154
  while ((dp = readdir(dirp)))
 
155
    {
 
156
      name = dp->d_name;
 
157
      debug1("- %s\n",  name);
 
158
      if (*name == 0 || *name == '.' || strlen(name) > 2*MAXSTR)
 
159
        continue;
 
160
      if (matchlen)
 
161
        {
 
162
          n = name;
 
163
          /* if we don't want to match digits. Skip them */
 
164
          if ((*match <= '0' || *match > '9') && (*n > '0' && *n <= '9'))
 
165
            {
 
166
              while (*n >= '0' && *n <= '9')
 
167
                n++;
 
168
              if (*n == '.')
 
169
                n++;
 
170
            }
 
171
          /* the tty prefix is optional */
 
172
          if (strncmp(match, "tty", 3) && strncmp(n, "tty", 3) == 0)
 
173
            n += 3;
 
174
          if (strncmp(match, n, matchlen))
 
175
            continue;
 
176
          debug1("  -> matched %s\n", match);
 
177
        }
 
178
      sprintf(SockPath + sdirlen, "/%s", name);
 
179
 
 
180
      debug1("stat %s\n", SockPath);
 
181
      errno = 0;
 
182
      debug2("uid = %d, gid = %d\n", getuid(), getgid());
 
183
      debug2("euid = %d, egid = %d\n", geteuid(), getegid());
 
184
      if (stat(SockPath, &st))
 
185
        {
 
186
          debug1("errno = %d\n", errno);
 
187
          continue;
 
188
        }
 
189
 
 
190
#ifndef SOCK_NOT_IN_FS
 
191
# ifdef NAMEDPIPE
 
192
#  ifdef S_ISFIFO
 
193
      debug("S_ISFIFO?\n");
 
194
      if (!S_ISFIFO(st.st_mode))
 
195
        continue;
 
196
#  endif
 
197
# else
 
198
#  ifdef S_ISSOCK
 
199
      debug("S_ISSOCK?\n");
 
200
      if (!S_ISSOCK(st.st_mode))
 
201
        continue;
 
202
#  endif
 
203
# endif
 
204
#endif
 
205
 
 
206
      debug2("st.st_uid = %d, real_uid = %d\n", st.st_uid, real_uid);
 
207
      if ((int)st.st_uid != real_uid)
 
208
        continue;
 
209
      mode = (int)st.st_mode & 0777;
 
210
      debug1("  has mode 0%03o\n", mode);
 
211
#ifdef MULTIUSER 
 
212
      if (multi && ((mode & 0677) != 0601))
 
213
        {
 
214
          debug("  is not a MULTI-USER session");
 
215
          if (strcmp(multi, LoginName))
 
216
            {
 
217
              debug(" and we are in a foreign directory.\n");
 
218
              mode = -4;
 
219
            }
 
220
          else
 
221
            {
 
222
              debug(", but it is our own session.\n");
 
223
            }
 
224
        }
 
225
#endif
 
226
      debug("  store it.\n");
 
227
      if ((sent = (struct sent *)malloc(sizeof(struct sent))) == 0)
 
228
        continue;
 
229
      sent->next = 0;
 
230
      sent->name = SaveStr(name);
 
231
      sent->mode = mode;
 
232
      *slisttail = sent;
 
233
      slisttail = &sent->next;
 
234
      nfound++;
 
235
      sockfd = MakeClientSocket(0);
 
236
#ifdef USE_SETEUID
 
237
      /* MakeClientSocket sets ids back to eff */
 
238
      xseteuid(real_uid);
 
239
      xsetegid(real_gid);
 
240
#endif
 
241
      if (sockfd == -1)
 
242
        {
 
243
          debug2("  MakeClientSocket failed, unreachable? %d %d\n",
 
244
                 matchlen, wipeflag);
 
245
          sent->mode = -3;
 
246
#ifndef SOCKDIR_IS_LOCAL_TO_HOST
 
247
          /* Unreachable - it is dead if we detect that it's local
 
248
           * or we specified a match
 
249
           */
 
250
          n = name + strlen(name) - 1;
 
251
          while (n != name && *n != '.')
 
252
            n--;
 
253
          if (matchlen == 0  && !(*n == '.' && n[1] && strncmp(HostName, n + 1, strlen(n + 1)) == 0))
 
254
            {
 
255
              npriv++;          /* a good socket that was not for us */
 
256
              continue;
 
257
            }
 
258
#endif
 
259
          ndead++;
 
260
          sent->mode = -1;
 
261
          if (wipeflag)
 
262
            {
 
263
              if (unlink(SockPath) == 0)
 
264
                {
 
265
                  sent->mode = -2;
 
266
                  nwipe++;
 
267
                }
 
268
            }
 
269
          continue;
 
270
        }
 
271
 
 
272
      mode &= 0776;
 
273
      /* Shall we connect ? */
 
274
      debug2("  connecting: mode=%03o, rflag=%d, ", mode, rflag);
 
275
      debug2("xflag=%d, dflag=%d ?\n", xflag, dflag);
 
276
 
 
277
      /*
 
278
       * mode 600: socket is detached.
 
279
       * mode 700: socket is attached.
 
280
       * xflag implies rflag here.
 
281
       *
 
282
       * fail, when socket mode mode is not 600 or 700
 
283
       * fail, when we want to detach w/o reattach, but it already is detached.
 
284
       * fail, when we only want to attach, but mode 700 and not xflag.
 
285
       * fail, if none of dflag, rflag, xflag is set.
 
286
       */
 
287
      if ((mode != 0700 && mode != 0600) ||
 
288
          (dflag && !rflag && !xflag && mode == 0600) ||
 
289
          (!dflag && rflag && mode == 0700 && !xflag) ||
 
290
          (!dflag && !rflag && !xflag))
 
291
        {
 
292
          close(sockfd);
 
293
          debug("  no!\n");
 
294
          npriv++;              /* a good socket that was not for us */
 
295
          continue;
 
296
        }
 
297
      ngood++;
 
298
      if (fdp && firsts == -1)
 
299
        {
 
300
          firsts = sockfd;
 
301
          firstn = sent->name;
 
302
          debug("  taken.\n");
 
303
        }
 
304
      else
 
305
        {
 
306
          debug("  discarded.\n");
 
307
          close(sockfd);
 
308
        } 
 
309
    }
 
310
  (void)closedir(dirp);
 
311
  if (nfound && (lsflag || ngood != 1) && !quietflag)
 
312
    {
 
313
      switch(ngood)
 
314
        {
 
315
        case 0:
 
316
          Msg(0, nfound > 1 ? "There are screens on:" : "There is a screen on:");
 
317
          break;
 
318
        case 1:
 
319
          Msg(0, nfound > 1 ? "There are several screens on:" : "There is a suitable screen on:");
 
320
          break;
 
321
        default:
 
322
          Msg(0, "There are several suitable screens on:");
 
323
          break;
 
324
        }
 
325
      for (sent = slist; sent; sent = sent->next)
 
326
        {
 
327
          switch (sent->mode)
 
328
            {
 
329
            case 0700:
 
330
              printf("\t%s\t(Attached)\n", sent->name);
 
331
              break;
 
332
            case 0600:
 
333
              printf("\t%s\t(Detached)\n", sent->name);
 
334
              break;
 
335
#ifdef MULTIUSER
 
336
            case 0701:
 
337
              printf("\t%s\t(Multi, attached)\n", sent->name);
 
338
              break;
 
339
            case 0601:
 
340
              printf("\t%s\t(Multi, detached)\n", sent->name);
 
341
              break;
 
342
#endif
 
343
            case -1:
 
344
              /* No trigraphs here! */
 
345
              printf("\t%s\t(Dead ?%c?)\n", sent->name, '?');
 
346
              break;
 
347
            case -2:
 
348
              printf("\t%s\t(Removed)\n", sent->name);
 
349
              break;
 
350
            case -3:
 
351
              printf("\t%s\t(Remote or dead)\n", sent->name);
 
352
              break;
 
353
            case -4:
 
354
              printf("\t%s\t(Private)\n", sent->name);
 
355
              break;
 
356
            }
 
357
        }
 
358
    }
 
359
  if (ndead && !quietflag)
 
360
    {
 
361
      char *m = "Remove dead screens with 'screen -wipe'.";
 
362
      if (wipeflag)
 
363
        Msg(0, "%d socket%s wiped out.", nwipe, nwipe > 1 ? "s" : "");
 
364
      else
 
365
        Msg(0, m, ndead > 1 ? "s" : "", ndead > 1 ? "" : "es"); /* other args for nethack */
 
366
    }
 
367
  if (firsts != -1)
 
368
    {
 
369
      sprintf(SockPath + sdirlen, "/%s", firstn);
 
370
      *fdp = firsts;
 
371
    }
 
372
  else
 
373
    SockPath[sdirlen] = 0;
 
374
  for (sent = slist; sent; sent = nsent)
 
375
    {
 
376
      nsent = sent->next;
 
377
      free(sent->name);
 
378
      free((char *)sent);
 
379
    }
 
380
#ifdef USE_SETEUID
 
381
  xseteuid(eff_uid);
 
382
  xsetegid(eff_gid);
 
383
#endif
 
384
  if (notherp)
 
385
    *notherp = npriv;
 
386
  if (nfoundp)
 
387
    *nfoundp = nfound - nwipe;
 
388
  return ngood;
 
389
}
 
390
  
 
391
 
 
392
/*
 
393
**
 
394
**        Socket/pipe create routines
 
395
**
 
396
*/
 
397
 
 
398
#ifdef NAMEDPIPE
 
399
 
 
400
int
 
401
MakeServerSocket()
 
402
{
 
403
  register int s;
 
404
  struct stat st;
 
405
 
 
406
# ifdef USE_SETEUID
 
407
  xseteuid(real_uid);
 
408
  xsetegid(real_gid);
 
409
# endif
 
410
  if ((s = open(SockPath, O_WRONLY | O_NONBLOCK)) >= 0)
 
411
    {
 
412
      debug("huii, my fifo already exists??\n");
 
413
      if (quietflag)
 
414
        {
 
415
          Kill(D_userpid, SIG_BYE);
 
416
          eexit(11);
 
417
        }
 
418
      Msg(0, "There is already a screen running on %s.", Filename(SockPath));
 
419
      if (stat(SockPath, &st) == -1)
 
420
        Panic(errno, "stat");
 
421
      if ((int)st.st_uid != real_uid)
 
422
        Panic(0, "Unfortunatelly you are not its owner.");
 
423
      if ((st.st_mode & 0700) == 0600)
 
424
        Panic(0, "To resume it, use \"screen -r\"");
 
425
      else
 
426
        Panic(0, "It is not detached.");
 
427
      /* NOTREACHED */
 
428
    }
 
429
# ifdef USE_SETEUID
 
430
  (void) unlink(SockPath);
 
431
  if (mkfifo(SockPath, SOCKMODE))
 
432
    Panic(0, "mkfifo %s failed", SockPath);
 
433
#  ifdef BROKEN_PIPE
 
434
  if ((s = open(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0)
 
435
#  else
 
436
  if ((s = open(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0)
 
437
#  endif
 
438
    Panic(errno, "open fifo %s", SockPath);
 
439
  xseteuid(eff_uid);
 
440
  xsetegid(eff_gid);
 
441
  return s;
 
442
# else /* !USE_SETEUID */
 
443
  if (UserContext() > 0)
 
444
    {
 
445
      (void) unlink(SockPath);
 
446
      UserReturn(mkfifo(SockPath, SOCKMODE));
 
447
    }
 
448
  if (UserStatus())
 
449
    Panic(0, "mkfifo %s failed", SockPath);
 
450
#  ifdef BROKEN_PIPE
 
451
  if ((s = secopen(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0)
 
452
#  else
 
453
  if ((s = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0)
 
454
#  endif
 
455
    Panic(errno, "open fifo %s", SockPath);
 
456
  return s;
 
457
# endif /* !USE_SETEUID */
 
458
}
 
459
 
 
460
 
 
461
int
 
462
MakeClientSocket(err)
 
463
int err;
 
464
{
 
465
  register int s = 0;
 
466
 
 
467
  if ((s = secopen(SockPath, O_WRONLY | O_NONBLOCK, 0)) >= 0)
 
468
    {
 
469
      (void) fcntl(s, F_SETFL, 0);
 
470
      return s;
 
471
    }
 
472
  if (err)
 
473
    Msg(errno, "%s", SockPath);
 
474
  debug2("MakeClientSocket() open %s failed (%d)\n", SockPath, errno);
 
475
  return -1;
 
476
}
 
477
 
 
478
 
 
479
#else   /* NAMEDPIPE */
 
480
 
 
481
 
 
482
int
 
483
MakeServerSocket()
 
484
{
 
485
  register int s;
 
486
  struct sockaddr_un a;
 
487
  struct stat st;
 
488
 
 
489
  if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
 
490
    Panic(errno, "socket");
 
491
  a.sun_family = AF_UNIX;
 
492
  strncpy(a.sun_path, SockPath, sizeof(a.sun_path));
 
493
  a.sun_path[sizeof(a.sun_path) - 1] = 0;
 
494
# ifdef USE_SETEUID
 
495
  xseteuid(real_uid);
 
496
  xsetegid(real_gid);
 
497
# endif
 
498
  if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) != -1)
 
499
    {
 
500
      debug("oooooh! socket already is alive!\n");
 
501
      if (quietflag)
 
502
        { 
 
503
          Kill(D_userpid, SIG_BYE);
 
504
          /* 
 
505
           * oh, well. nobody receives that return code. papa 
 
506
           * dies by signal.
 
507
           */
 
508
          eexit(11);
 
509
        }
 
510
      Msg(0, "There is already a screen running on %s.", Filename(SockPath));
 
511
      if (stat(SockPath, &st) == -1)
 
512
        Panic(errno, "stat");
 
513
      if (st.st_uid != real_uid)
 
514
        Panic(0, "Unfortunatelly you are not its owner.");
 
515
      if ((st.st_mode & 0700) == 0600)
 
516
        Panic(0, "To resume it, use \"screen -r\"");
 
517
      else
 
518
        Panic(0, "It is not detached.");
 
519
      /* NOTREACHED */
 
520
    }
 
521
#if defined(m88k) || defined(sysV68)
 
522
  close(s);     /* we get bind: Invalid argument if this is not done */
 
523
  if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
 
524
    Panic(errno, "reopen socket");
 
525
#endif
 
526
  (void) unlink(SockPath);
 
527
  if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
 
528
    Panic(errno, "bind (%s)", SockPath);
 
529
#ifdef SOCK_NOT_IN_FS
 
530
    {
 
531
      int f;
 
532
      if ((f = secopen(SockPath, O_RDWR | O_CREAT, SOCKMODE)) < 0)
 
533
        Panic(errno, "shadow socket open");
 
534
      close(f);
 
535
    }
 
536
#else
 
537
  chmod(SockPath, SOCKMODE);
 
538
# ifndef USE_SETEUID
 
539
  chown(SockPath, real_uid, real_gid);
 
540
# endif
 
541
#endif /* SOCK_NOT_IN_FS */
 
542
  if (listen(s, 5) == -1)
 
543
    Panic(errno, "listen");
 
544
# ifdef F_SETOWN
 
545
  fcntl(s, F_SETOWN, getpid());
 
546
  debug1("Serversocket owned by %d\n", fcntl(s, F_GETOWN, 0));
 
547
# endif /* F_SETOWN */
 
548
# ifdef USE_SETEUID
 
549
  xseteuid(eff_uid);
 
550
  xsetegid(eff_gid);
 
551
# endif
 
552
  return s;
 
553
}
 
554
 
 
555
int
 
556
MakeClientSocket(err)
 
557
int err;
 
558
{
 
559
  register int s;
 
560
  struct sockaddr_un a;
 
561
 
 
562
  if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
 
563
    Panic(errno, "socket");
 
564
  a.sun_family = AF_UNIX;
 
565
  strncpy(a.sun_path, SockPath, sizeof(a.sun_path));
 
566
  a.sun_path[sizeof(a.sun_path) - 1] = 0;
 
567
# ifdef USE_SETEUID
 
568
  xseteuid(real_uid);
 
569
  xsetegid(real_gid);
 
570
# else
 
571
  if (access(SockPath, W_OK))
 
572
    {
 
573
      if (err)
 
574
        Msg(errno, "%s", SockPath);
 
575
      debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno);
 
576
      close(s);
 
577
      return -1;
 
578
    }
 
579
# endif
 
580
  if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) == -1)
 
581
    {
 
582
      if (err)
 
583
        Msg(errno, "%s: connect", SockPath);
 
584
      debug("MakeClientSocket: connect failed.\n");
 
585
      close(s);
 
586
      s = -1;
 
587
    }
 
588
# ifdef USE_SETEUID
 
589
  xseteuid(eff_uid);
 
590
  xsetegid(eff_gid);
 
591
# endif
 
592
  return s;
 
593
}
 
594
#endif /* NAMEDPIPE */
 
595
 
 
596
 
 
597
/*
 
598
**
 
599
**       Message send and receive routines
 
600
**
 
601
*/
 
602
 
 
603
void
 
604
SendCreateMsg(sty, nwin)
 
605
char *sty;
 
606
struct NewWindow *nwin;
 
607
{
 
608
  int s;
 
609
  struct msg m;
 
610
  register char *p;
 
611
  register int len, n;
 
612
  char **av = nwin->args;
 
613
 
 
614
#ifdef NAME_MAX
 
615
  if (strlen(sty) > NAME_MAX)
 
616
    sty[NAME_MAX] = 0;
 
617
#endif
 
618
  if (strlen(sty) > 2 * MAXSTR - 1)
 
619
    sty[2 * MAXSTR - 1] = 0;
 
620
  sprintf(SockPath + strlen(SockPath), "/%s", sty);
 
621
  if ((s = MakeClientSocket(1)) == -1)
 
622
    exit(1);
 
623
  debug1("SendCreateMsg() to '%s'\n", SockPath);
 
624
  bzero((char *)&m, sizeof(m));
 
625
  m.type = MSG_CREATE;
 
626
  strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1);
 
627
  m.m_tty[sizeof(m.m_tty) - 1] = 0;
 
628
  p = m.m.create.line;
 
629
  n = 0;
 
630
  if (nwin->args != nwin_undef.args)
 
631
    for (av = nwin->args; *av && n < MAXARGS - 1; ++av, ++n)
 
632
      {
 
633
        len = strlen(*av) + 1;
 
634
        if (p + len >= m.m.create.line + sizeof(m.m.create.line) - 1)
 
635
          break;
 
636
        strcpy(p, *av);
 
637
        p += len;
 
638
      }
 
639
  if (nwin->aka != nwin_undef.aka && p + strlen(nwin->aka) + 1 < m.m.create.line + sizeof(m.m.create.line))
 
640
    strcpy(p, nwin->aka);
 
641
  else
 
642
    *p = '\0';
 
643
  m.m.create.nargs = n;
 
644
  m.m.create.aflag = nwin->aflag;
 
645
  m.m.create.flowflag = nwin->flowflag;
 
646
  m.m.create.lflag = nwin->lflag;
 
647
  m.m.create.hheight = nwin->histheight;
 
648
  if (getcwd(m.m.create.dir, sizeof(m.m.create.dir)) == 0)
 
649
    {
 
650
      Msg(errno, "getcwd");
 
651
      return;
 
652
    }
 
653
  if (nwin->term != nwin_undef.term)
 
654
    strncpy(m.m.create.screenterm, nwin->term, 19);
 
655
  m.m.create.screenterm[19] = '\0';
 
656
  m.protocol_revision = MSG_REVISION;
 
657
  debug1("SendCreateMsg writing '%s'\n", m.m.create.line);
 
658
  if (write(s, (char *) &m, sizeof m) != sizeof m)
 
659
    Msg(errno, "write");
 
660
  close(s);
 
661
}
 
662
 
 
663
int
 
664
SendErrorMsg(tty, buf)
 
665
char *tty, *buf;
 
666
{
 
667
  int s;
 
668
  struct msg m;
 
669
 
 
670
  strncpy(m.m.message, buf, sizeof(m.m.message) - 1);
 
671
  m.m.message[sizeof(m.m.message) - 1] = 0;
 
672
  s = MakeClientSocket(0);
 
673
  if (s < 0)
 
674
    return -1;
 
675
  m.type = MSG_ERROR;
 
676
  strncpy(m.m_tty, tty, sizeof(m.m_tty) - 1);
 
677
  m.m_tty[sizeof(m.m_tty) - 1] = 0;
 
678
  m.protocol_revision = MSG_REVISION;
 
679
  debug1("SendErrorMsg(): writing to '%s'\n", SockPath);
 
680
  (void) write(s, (char *) &m, sizeof m);
 
681
  close(s);
 
682
  return 0;
 
683
}
 
684
 
 
685
static void
 
686
ExecCreate(mp)
 
687
struct msg *mp;
 
688
{
 
689
  struct NewWindow nwin;
 
690
  char *args[MAXARGS];
 
691
  register int n;
 
692
  register char **pp = args, *p = mp->m.create.line;
 
693
 
 
694
  nwin = nwin_undef;
 
695
  n = mp->m.create.nargs;
 
696
  if (n > MAXARGS - 1)
 
697
    n = MAXARGS - 1;
 
698
  /* ugly hack alert... should be done by the frontend! */
 
699
  if (n)
 
700
    {
 
701
      int l, num;
 
702
      char buf[20];
 
703
 
 
704
      l = strlen(p);
 
705
      if (IsNumColon(p, 10, buf, sizeof(buf)))
 
706
        {
 
707
          if (*buf)
 
708
            nwin.aka = buf;
 
709
          num = atoi(p);
 
710
          if (num < 0 || num > MAXWIN - 1)
 
711
            num = 0;
 
712
          nwin.StartAt = num;
 
713
          p += l + 1;
 
714
          n--;
 
715
        }
 
716
    }
 
717
  for (; n > 0; n--)
 
718
    {
 
719
      *pp++ = p;
 
720
      p += strlen(p) + 1;
 
721
    }
 
722
  *pp = 0;
 
723
  if (*p)
 
724
    nwin.aka = p;
 
725
  if (*args)
 
726
    nwin.args = args;
 
727
  nwin.aflag = mp->m.create.aflag;
 
728
  nwin.flowflag = mp->m.create.flowflag;
 
729
  if (*mp->m.create.dir)
 
730
    nwin.dir = mp->m.create.dir;
 
731
  nwin.lflag = mp->m.create.lflag;
 
732
  nwin.histheight = mp->m.create.hheight;
 
733
  if (*mp->m.create.screenterm)
 
734
    nwin.term =  mp->m.create.screenterm;
 
735
  MakeWindow(&nwin);
 
736
}
 
737
 
 
738
static int
 
739
CheckPid(pid)
 
740
int pid;
 
741
{
 
742
  debug1("Checking pid %d\n", pid);
 
743
  if (pid < 2)
 
744
    return -1;
 
745
  if (eff_uid == real_uid)
 
746
    return kill(pid, 0);
 
747
  if (UserContext() > 0)
 
748
    UserReturn(kill(pid, 0));
 
749
  return UserStatus();
 
750
}
 
751
 
 
752
#ifdef hpux
 
753
/*
 
754
 * From: "F. K. Bruner" <napalm@ugcs.caltech.edu>
 
755
 * From: "Dan Egnor" <egnor@oracorp.com> Tue Aug 10 06:56:45 1993
 
756
 * The problem is that under HPUX (and possibly other systems too) there are
 
757
 * two equivalent device files for each pty/tty device:
 
758
 * /dev/ttyxx == /dev/pty/ttyxx
 
759
 * /dev/ptyxx == /dev/ptym/ptyxx
 
760
 * I didn't look into the exact specifics, but I've run across this problem
 
761
 * before: Even if you open /dev/ttyxx as fds 0 1 & 2 for a process, if that
 
762
 * process calls the system to determine its tty, it'll get /dev/pty/ttyxx.
 
763
 *
 
764
 * Earlier versions seemed to work -- wonder what they did.
 
765
 */
 
766
static int
 
767
ttycmp(s1, s2)
 
768
char *s1, *s2;
 
769
{
 
770
  if (strlen(s1) > 5) s1 += strlen(s1) - 5;
 
771
  if (strlen(s2) > 5) s2 += strlen(s2) - 5;
 
772
  return strcmp(s1, s2);
 
773
}
 
774
# define TTYCMP(a, b) ttycmp(a, b)
 
775
#else
 
776
# define TTYCMP(a, b) strcmp(a, b)
 
777
#endif
 
778
 
 
779
void
 
780
ReceiveMsg()
 
781
{
 
782
  int left, len, i;
 
783
  static struct msg m;
 
784
  char *p;
 
785
  int ns = ServerSocket;
 
786
  struct mode Mode;
 
787
  struct win *wi;
 
788
#ifdef REMOTE_DETACH
 
789
  struct display *next;
 
790
#endif
 
791
  struct display *olddisplays = displays;
 
792
 
 
793
#ifdef NAMEDPIPE
 
794
  debug("Ha, there was someone knocking on my fifo??\n");
 
795
  if (fcntl(ServerSocket, F_SETFL, 0) == -1)
 
796
    Panic(errno, "BLOCK fcntl");
 
797
#else
 
798
  struct sockaddr_un a;
 
799
 
 
800
  len = sizeof(a);
 
801
  debug("Ha, there was someone knocking on my socket??\n");
 
802
  if ((ns = accept(ns, (struct sockaddr *) &a, &len)) < 0)
 
803
    {
 
804
      Msg(errno, "accept");
 
805
      return;
 
806
    }
 
807
#endif                          /* NAMEDPIPE */
 
808
 
 
809
  p = (char *) &m;
 
810
  left = sizeof(m);
 
811
  while (left > 0)
 
812
    {
 
813
      len = read(ns, p, left);
 
814
      if (len < 0 && errno == EINTR)
 
815
        continue;
 
816
      if (len <= 0)
 
817
        break;
 
818
      p += len;
 
819
      left -= len;
 
820
    }
 
821
 
 
822
#ifdef NAMEDPIPE
 
823
# ifndef BROKEN_PIPE
 
824
  /* Reopen pipe to prevent EOFs at the select() call */
 
825
  close(ServerSocket);
 
826
  if ((ServerSocket = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0)
 
827
    Panic(errno, "reopen fifo %s", SockPath);
 
828
  evdeq(&serv_read);
 
829
  serv_read.fd = ServerSocket;
 
830
  evenq(&serv_read);
 
831
# endif
 
832
#else
 
833
  close(ns);
 
834
#endif
 
835
 
 
836
  if (len < 0)
 
837
    {
 
838
      Msg(errno, "read");
 
839
      return;
 
840
    }
 
841
  if (left > 0)
 
842
    {
 
843
      if (left != sizeof(m))
 
844
        Msg(0, "Message %d of %d bytes too small", left, (int)sizeof(m));
 
845
      else
 
846
        debug("No data on socket.\n");
 
847
      return;
 
848
    }
 
849
  if (m.protocol_revision != MSG_REVISION)
 
850
    {
 
851
      Msg(0, "Invalid message (magic 0x%08x).", m.protocol_revision);
 
852
      return;
 
853
    }
 
854
 
 
855
  debug2("*** RecMsg: type %d tty %s\n", m.type, m.m_tty);
 
856
  for (display = displays; display; display = display->d_next)
 
857
    if (TTYCMP(D_usertty, m.m_tty) == 0)
 
858
      break;
 
859
  debug2("display: %s display %sfound\n", m.m_tty, display ? "" : "not ");
 
860
  wi = 0;
 
861
  if (!display)
 
862
    {
 
863
      for (wi = windows; wi; wi = wi->w_next)
 
864
        if (!TTYCMP(m.m_tty, wi->w_tty))
 
865
          {
 
866
            /* XXX: hmmm, rework this? */
 
867
            display = wi->w_layer.l_cvlist ? wi->w_layer.l_cvlist->c_display : 0;
 
868
            debug2("but window %s %sfound.\n", m.m_tty, display ? "" : 
 
869
                   "(backfacing)");
 
870
            break;
 
871
          }
 
872
    }
 
873
 
 
874
  /* Remove the status to prevent garbage on the screen */
 
875
  if (display && D_status)
 
876
    RemoveStatus();
 
877
 
 
878
  if (display && !D_tcinited && m.type != MSG_HANGUP)
 
879
    return;             /* ignore messages for bad displays */
 
880
 
 
881
  switch (m.type)
 
882
    {
 
883
    case MSG_WINCH:
 
884
      if (display)
 
885
        CheckScreenSize(1); /* Change fore */
 
886
      break;
 
887
    case MSG_CREATE:
 
888
      /*
 
889
       * the window that issued the create message need not be an active
 
890
       * window. Then we create the window without having a display.
 
891
       * Resulting in another inactive window.
 
892
       * 
 
893
       * Currently we enforce that at least one display exists. But why?
 
894
       * jw.
 
895
       */
 
896
      if (displays)
 
897
        ExecCreate(&m);
 
898
      break;
 
899
    case MSG_CONT:
 
900
        if (display && D_userpid != 0 && kill(D_userpid, 0) == 0)
 
901
          break;                /* Intruder Alert */
 
902
      debug2("RecMsg: apid=%d,was %d\n", m.m.attach.apid, display ? D_userpid : 0);
 
903
      /* FALLTHROUGH */
 
904
 
 
905
    case MSG_ATTACH:
 
906
      if (CheckPid(m.m.attach.apid))
 
907
        {
 
908
          Msg(0, "Attach attempt with bad pid(%d)!", m.m.attach.apid);
 
909
          break;
 
910
        }
 
911
      if ((i = secopen(m.m_tty, O_RDWR | O_NONBLOCK, 0)) < 0)
 
912
        {
 
913
          Msg(errno, "Attach: Could not open %s!", m.m_tty);
 
914
          Kill(m.m.attach.apid, SIG_BYE);
 
915
          break;
 
916
        }
 
917
# ifdef MULTIUSER
 
918
      Kill(m.m.attach.apid, SIGCONT);
 
919
# endif
 
920
 
 
921
#if defined(ultrix) || defined(pyr) || defined(NeXT)
 
922
      brktty(i);        /* for some strange reason this must be done */
 
923
#endif
 
924
 
 
925
      if (display || wi)
 
926
        {
 
927
          write(i, "Attaching from inside of screen?\n", 33);
 
928
          close(i);
 
929
          Kill(m.m.attach.apid, SIG_BYE);
 
930
          Msg(0, "Attach msg ignored: coming from inside.");
 
931
          break;
 
932
        }
 
933
 
 
934
#ifdef MULTIUSER
 
935
      if (strcmp(m.m.attach.auser, LoginName))
 
936
        if (*FindUserPtr(m.m.attach.auser) == 0)
 
937
          {
 
938
              write(i, "Access to session denied.\n", 26);
 
939
              close(i);
 
940
              Kill(m.m.attach.apid, SIG_BYE);
 
941
              Msg(0, "Attach: access denied for user %s.", m.m.attach.auser);
 
942
              break;
 
943
          }
 
944
#endif
 
945
 
 
946
      debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", m.m.attach.apid, m.m_tty);
 
947
#ifndef MULTI
 
948
      if (displays)
 
949
        {
 
950
          write(i, "Screen session in use.\n", 23);
 
951
          close(i);
 
952
          Kill(m.m.attach.apid, SIG_BYE);
 
953
          break;
 
954
        }
 
955
#endif
 
956
 
 
957
      /* create new display */
 
958
      GetTTY(i, &Mode);
 
959
      if (MakeDisplay(m.m.attach.auser, m.m_tty, m.m.attach.envterm, i, m.m.attach.apid, &Mode) == 0)
 
960
        {
 
961
          write(i, "Could not make display.\n", 24);
 
962
          close(i);
 
963
          Msg(0, "Attach: could not make display for user %s", m.m.attach.auser);
 
964
          Kill(m.m.attach.apid, SIG_BYE);
 
965
          break;
 
966
        }
 
967
#ifdef ENCODINGS
 
968
# ifdef UTF8
 
969
      D_encoding = m.m.attach.encoding == 1 ? UTF8 : m.m.attach.encoding ? m.m.attach.encoding - 1 : 0;
 
970
# else
 
971
      D_encoding = m.m.attach.encoding ? m.m.attach.encoding - 1 : 0;
 
972
# endif
 
973
      if (D_encoding < 0 || !EncodingName(D_encoding))
 
974
        D_encoding = 0;
 
975
#endif
 
976
      /* turn off iflag on a multi-attach... */
 
977
      if (iflag && olddisplays)
 
978
        {
 
979
          iflag = 0;
 
980
#if defined(TERMIO) || defined(POSIX)
 
981
          olddisplays->d_NewMode.tio.c_cc[VINTR] = VDISABLE;
 
982
          olddisplays->d_NewMode.tio.c_lflag &= ~ISIG;
 
983
#else /* TERMIO || POSIX */
 
984
          olddisplays->d_NewMode.m_tchars.t_intrc = -1;
 
985
#endif /* TERMIO || POSIX */
 
986
          SetTTY(olddisplays->d_userfd, &olddisplays->d_NewMode);
 
987
        }
 
988
      SetMode(&D_OldMode, &D_NewMode, D_flow, iflag);
 
989
      SetTTY(D_userfd, &D_NewMode);
 
990
      if (fcntl(D_userfd, F_SETFL, FNBLOCK))
 
991
        Msg(errno, "Warning: NBLOCK fcntl failed");
 
992
 
 
993
#ifdef PASSWORD
 
994
      if (D_user->u_password && *D_user->u_password)
 
995
        AskPassword(&m);
 
996
      else
 
997
#endif
 
998
        FinishAttach(&m);
 
999
      break;
 
1000
    case MSG_ERROR:
 
1001
      Msg(0, "%s", m.m.message);
 
1002
      break;
 
1003
    case MSG_HANGUP:
 
1004
      if (!wi)          /* ignore hangups from inside */
 
1005
        Hangup();
 
1006
      break;
 
1007
#ifdef REMOTE_DETACH
 
1008
    case MSG_DETACH:
 
1009
# ifdef POW_DETACH
 
1010
    case MSG_POW_DETACH:
 
1011
# endif                         /* POW_DETACH */
 
1012
      for (display = displays; display; display = next)
 
1013
        {
 
1014
          next = display->d_next;
 
1015
# ifdef POW_DETACH
 
1016
          if (m.type == MSG_POW_DETACH)
 
1017
            Detach(D_REMOTE_POWER);
 
1018
          else
 
1019
# endif                         /* POW_DETACH */
 
1020
          if (m.type == MSG_DETACH)
 
1021
            Detach(D_REMOTE);
 
1022
        }
 
1023
      break;
 
1024
#endif
 
1025
    case MSG_COMMAND:
 
1026
      DoCommandMsg(&m);
 
1027
      break;
 
1028
    default:
 
1029
      Msg(0, "Invalid message (type %d).", m.type);
 
1030
    }
 
1031
}
 
1032
 
 
1033
#if defined(_SEQUENT_) && !defined(NAMEDPIPE)
 
1034
#undef connect
 
1035
/*
 
1036
 *  sequent_ptx socket emulation must have mode 000 on the socket!
 
1037
 */
 
1038
static int
 
1039
sconnect(s, sapp, len)
 
1040
int s, len;
 
1041
struct sockaddr *sapp;
 
1042
{
 
1043
  register struct sockaddr_un *sap;
 
1044
  struct stat st;
 
1045
  int x;
 
1046
 
 
1047
  sap = (struct sockaddr_un *)sapp;
 
1048
  if (stat(sap->sun_path, &st))
 
1049
    return -1;
 
1050
  chmod(sap->sun_path, 0);
 
1051
  x = connect(s, (struct sockaddr *) sap, len);
 
1052
  chmod(sap->sun_path, st.st_mode);
 
1053
  return x;
 
1054
}
 
1055
#endif
 
1056
 
 
1057
 
 
1058
/*
 
1059
 * Set the mode bits of the socket to the current status
 
1060
 */
 
1061
int
 
1062
chsock()
 
1063
{
 
1064
  int r, euid = geteuid();
 
1065
  if (euid != real_uid)
 
1066
    {
 
1067
      if (UserContext() <= 0)
 
1068
        return UserStatus();
 
1069
    }
 
1070
  r = chmod(SockPath, SOCKMODE);
 
1071
  /* 
 
1072
   * Sockets usually reside in the /tmp/ area, where sysadmin scripts
 
1073
   * may be happy to remove old files. We manually prevent the socket
 
1074
   * from becoming old. (chmod does not touch mtime).
 
1075
   */
 
1076
  (void)utimes(SockPath, NULL);
 
1077
 
 
1078
  if (euid != real_uid)
 
1079
    UserReturn(r);
 
1080
  return r;
 
1081
}
 
1082
 
 
1083
/*
 
1084
 * Try to recreate the socket/pipe
 
1085
 */
 
1086
int
 
1087
RecoverSocket()
 
1088
{
 
1089
  close(ServerSocket);
 
1090
  if ((int)geteuid() != real_uid)
 
1091
    {
 
1092
      if (UserContext() > 0)
 
1093
        UserReturn(unlink(SockPath));
 
1094
      (void)UserStatus();
 
1095
    }
 
1096
  else
 
1097
    (void) unlink(SockPath);
 
1098
 
 
1099
  if ((ServerSocket = MakeServerSocket()) < 0)
 
1100
    return 0;
 
1101
  evdeq(&serv_read);
 
1102
  serv_read.fd = ServerSocket;
 
1103
  evenq(&serv_read);
 
1104
  return 1;
 
1105
}
 
1106
 
 
1107
 
 
1108
static void
 
1109
FinishAttach(m)
 
1110
struct msg *m;
 
1111
{
 
1112
  char *p;
 
1113
  int pid;
 
1114
  int noshowwin;
 
1115
  struct win *wi;
 
1116
 
 
1117
  ASSERT(display);
 
1118
  pid = D_userpid;
 
1119
 
 
1120
#if defined(pyr) || defined(xelos) || defined(sequent)
 
1121
  /*
 
1122
   * Kludge for systems with braindamaged termcap routines,
 
1123
   * which evaluate $TERMCAP, regardless weather it describes
 
1124
   * the correct terminal type or not.
 
1125
   */
 
1126
  debug("unsetenv(TERMCAP) in case of a different terminal");
 
1127
  unsetenv("TERMCAP");
 
1128
#endif
 
1129
 
 
1130
  /*
 
1131
   * We reboot our Terminal Emulator. Forget all we knew about
 
1132
   * the old terminal, reread the termcap entries in .screenrc
 
1133
   * (and nothing more from .screenrc is read. Mainly because
 
1134
   * I did not check, weather a full reinit is safe. jw) 
 
1135
   * and /etc/screenrc, and initialise anew.
 
1136
   */
 
1137
  if (extra_outcap)
 
1138
    free(extra_outcap);
 
1139
  if (extra_incap)
 
1140
    free(extra_incap);
 
1141
  extra_incap = extra_outcap = 0;
 
1142
  debug2("Message says size (%dx%d)\n", m->m.attach.columns, m->m.attach.lines);
 
1143
#ifdef ETCSCREENRC
 
1144
# ifdef ALLOW_SYSSCREENRC
 
1145
  if ((p = getenv("SYSSCREENRC")))
 
1146
    StartRc(p);
 
1147
  else
 
1148
# endif
 
1149
    StartRc(ETCSCREENRC);
 
1150
#endif
 
1151
  StartRc(RcFileName);
 
1152
  if (InitTermcap(m->m.attach.columns, m->m.attach.lines))
 
1153
    {
 
1154
      FreeDisplay();
 
1155
      Kill(pid, SIG_BYE);
 
1156
      return;
 
1157
    }
 
1158
  MakeDefaultCanvas();
 
1159
  InitTerm(m->m.attach.adaptflag);      /* write init string on fd */
 
1160
  if (displays->d_next == 0)
 
1161
    (void) chsock();
 
1162
  signal(SIGHUP, SigHup);
 
1163
  if (m->m.attach.esc != -1 && m->m.attach.meta_esc != -1)
 
1164
    {
 
1165
      D_user->u_Esc = m->m.attach.esc;
 
1166
      D_user->u_MetaEsc = m->m.attach.meta_esc;
 
1167
    }
 
1168
 
 
1169
#ifdef UTMPOK
 
1170
  /*
 
1171
   * we set the Utmp slots again, if we were detached normally
 
1172
   * and if we were detached by ^Z.
 
1173
   * don't log zomies back in!
 
1174
   */
 
1175
  RemoveLoginSlot();
 
1176
  if (displays->d_next == 0)
 
1177
    for (wi = windows; wi; wi = wi->w_next)
 
1178
      if (wi->w_ptyfd >= 0 && wi->w_slot != (slot_t) -1)
 
1179
        SetUtmp(wi);
 
1180
#endif
 
1181
 
 
1182
  D_fore = NULL;
 
1183
  /*
 
1184
   * there may be a window that we remember from last detach:
 
1185
   */
 
1186
  debug1("D_user->u_detachwin = %d\n", D_user->u_detachwin);
 
1187
  if (D_user->u_detachwin >= 0) 
 
1188
    fore = wtab[D_user->u_detachwin];
 
1189
  else
 
1190
    fore = 0;
 
1191
 
 
1192
  /* Wayne wants us to restore the other window too. */
 
1193
  if (D_user->u_detachotherwin >= 0)
 
1194
    D_other = wtab[D_user->u_detachotherwin];
 
1195
 
 
1196
  noshowwin = 0;
 
1197
  if (*m->m.attach.preselect)
 
1198
    {
 
1199
      if (!strcmp(m->m.attach.preselect, "="))
 
1200
        fore = 0;
 
1201
      else if (!strcmp(m->m.attach.preselect, "-"))
 
1202
        {
 
1203
          fore = 0;
 
1204
          noshowwin = 1;
 
1205
        }
 
1206
      else
 
1207
        fore = FindNiceWindow(fore, m->m.attach.preselect);
 
1208
    }
 
1209
  else
 
1210
    fore = FindNiceWindow(fore, 0);
 
1211
  if (fore)
 
1212
    SetForeWindow(fore);
 
1213
  else if (!noshowwin)
 
1214
    {
 
1215
#ifdef MULTIUSER
 
1216
      if (!AclCheckPermCmd(D_user, ACL_EXEC, &comms[RC_WINDOWLIST]))
 
1217
#endif
 
1218
        {
 
1219
          flayer = D_forecv->c_layer;
 
1220
          display_wlist(1, WLIST_NUM);
 
1221
          noshowwin = 1;
 
1222
        }
 
1223
    }
 
1224
  Activate(0);
 
1225
  ResetIdle();
 
1226
  if (!D_fore && !noshowwin)
 
1227
    ShowWindows(-1);
 
1228
  if (displays->d_next == 0 && console_window)
 
1229
    {
 
1230
      if (TtyGrabConsole(console_window->w_ptyfd, 1, "reattach") == 0)
 
1231
        Msg(0, "console %s is on window %d", HostName, console_window->w_number);
 
1232
    }
 
1233
  debug("activated...\n");
 
1234
 
 
1235
# if defined(DEBUG) && defined(SIG_NODEBUG)
 
1236
  if (!dfp)
 
1237
    {
 
1238
      sleep(1);
 
1239
      debug1("Attacher %d must not debug, as we have debug off.\n", pid);
 
1240
      kill(pid, SIG_NODEBUG);
 
1241
    }
 
1242
# endif /* SIG_NODEBUG */
 
1243
}
 
1244
 
 
1245
 
 
1246
#ifdef PASSWORD
 
1247
static void PasswordProcessInput __P((char *, int));
 
1248
 
 
1249
struct pwdata {
 
1250
  int l;
 
1251
  char buf[20 + 1];
 
1252
  struct msg m;
 
1253
};
 
1254
 
 
1255
static void
 
1256
AskPassword(m)
 
1257
struct msg *m;
 
1258
{
 
1259
  struct pwdata *pwdata;
 
1260
  ASSERT(display);
 
1261
  pwdata = (struct pwdata *)malloc(sizeof(struct pwdata));
 
1262
  if (!pwdata)
 
1263
    Panic(0, strnomem);
 
1264
  pwdata->l = 0;
 
1265
  pwdata->m = *m;
 
1266
  D_processinputdata = (char *)pwdata;
 
1267
  D_processinput = PasswordProcessInput;
 
1268
  AddStr("Screen password: ");
 
1269
}
 
1270
 
 
1271
static void
 
1272
PasswordProcessInput(ibuf, ilen)
 
1273
char *ibuf;
 
1274
int ilen;
 
1275
{
 
1276
  struct pwdata *pwdata;
 
1277
  int c, l;
 
1278
  char *up;
 
1279
  int pid = D_userpid;
 
1280
 
 
1281
  pwdata = (struct pwdata *)D_processinputdata;
 
1282
  l = pwdata->l;
 
1283
  while (ilen-- > 0)
 
1284
    {
 
1285
      c = *(unsigned char *)ibuf++;
 
1286
      if (c == '\r' || c == '\n')
 
1287
        {
 
1288
          up = D_user->u_password;
 
1289
          pwdata->buf[l] = 0;
 
1290
          if (strncmp(crypt(pwdata->buf, up), up, strlen(up)))
 
1291
            {
 
1292
              /* uh oh, user failed */
 
1293
              bzero(pwdata->buf, sizeof(pwdata->buf));
 
1294
              AddStr("\r\nPassword incorrect.\r\n");
 
1295
              D_processinputdata = 0;   /* otherwise freed by FreeDis */
 
1296
              FreeDisplay();
 
1297
              Msg(0, "Illegal reattach attempt from terminal %s.", pwdata->m.m_tty);
 
1298
              free(pwdata);
 
1299
              Kill(pid, SIG_BYE);
 
1300
              return;
 
1301
            }
 
1302
          /* great, pw matched, all is fine */
 
1303
          bzero(pwdata->buf, sizeof(pwdata->buf));
 
1304
          AddStr("\r\n");
 
1305
          D_processinputdata = 0;
 
1306
          D_processinput = ProcessInput;
 
1307
          FinishAttach(&pwdata->m);
 
1308
          free(pwdata);
 
1309
          return;
 
1310
        }
 
1311
      if (c == Ctrl('c'))
 
1312
        {
 
1313
          AddStr("\r\n");
 
1314
          FreeDisplay();
 
1315
          Kill(pid, SIG_BYE);
 
1316
          return;
 
1317
        }
 
1318
      if (c == '\b' || c == 0177)
 
1319
        {
 
1320
          if (l > 0)
 
1321
            l--;
 
1322
          continue;
 
1323
        }
 
1324
      if (c == Ctrl('u'))
 
1325
        {
 
1326
          l = 0;
 
1327
          continue;
 
1328
        }
 
1329
      if (l < (int)sizeof(pwdata->buf) - 1)
 
1330
        pwdata->buf[l++] = c;
 
1331
    }
 
1332
  pwdata->l = l;
 
1333
}
 
1334
#endif
 
1335
 
 
1336
static void
 
1337
DoCommandMsg(mp)
 
1338
struct msg *mp;
 
1339
{
 
1340
  char *args[MAXARGS];
 
1341
  int argl[MAXARGS];
 
1342
  int n, *lp;
 
1343
  register char **pp = args, *p = mp->m.command.cmd;
 
1344
  struct acluser *user;
 
1345
#ifdef MULTIUSER
 
1346
  extern struct acluser *EffectiveAclUser;      /* acls.c */
 
1347
#else
 
1348
  extern struct acluser *users;                 /* acls.c */
 
1349
#endif
 
1350
 
 
1351
  lp = argl;
 
1352
  n = mp->m.command.nargs;
 
1353
  if (n > MAXARGS - 1)
 
1354
    n = MAXARGS - 1;
 
1355
  for (; n > 0; n--)
 
1356
    {
 
1357
      *pp++ = p;
 
1358
      *lp = strlen(p);
 
1359
      p += *lp++ + 1;
 
1360
    }
 
1361
  *pp = 0;
 
1362
#ifdef MULTIUSER
 
1363
  user = *FindUserPtr(mp->m.attach.auser);
 
1364
  if (user == 0)
 
1365
    {
 
1366
      Msg(0, "Unknown user %s tried to send a command!", mp->m.attach.auser);
 
1367
      return;
 
1368
    }
 
1369
#else
 
1370
  user = users;
 
1371
#endif
 
1372
#ifdef PASSWORD
 
1373
  if (user->u_password && *user->u_password)
 
1374
    {
 
1375
      Msg(0, "User %s has a password, cannot use -X option.", mp->m.attach.auser);
 
1376
      return;
 
1377
    }
 
1378
#endif
 
1379
  if (!display)
 
1380
    for (display = displays; display; display = display->d_next)
 
1381
      if (D_user == user)
 
1382
        break;
 
1383
  for (fore = windows; fore; fore = fore->w_next)
 
1384
    if (!TTYCMP(mp->m_tty, fore->w_tty))
 
1385
      {
 
1386
        if (!display)
 
1387
          display = fore->w_layer.l_cvlist ? fore->w_layer.l_cvlist->c_display : 0;
 
1388
        break;
 
1389
      }
 
1390
  if (!display)
 
1391
    display = displays;         /* sigh */
 
1392
  if (*mp->m.command.preselect)
 
1393
    {
 
1394
      int i = -1;
 
1395
      if (strcmp(mp->m.command.preselect, "-"))
 
1396
        i = WindowByNoN(mp->m.command.preselect);
 
1397
      fore = i >= 0 ? wtab[i] : 0;
 
1398
    }
 
1399
  else if (!fore)
 
1400
    {
 
1401
      if (display && D_user == user)
 
1402
        fore = Layer2Window(display->d_forecv->c_layer);
 
1403
      if (!fore)
 
1404
        {
 
1405
          fore = user->u_detachwin >= 0 ? wtab[user->u_detachwin] : 0;
 
1406
          fore = FindNiceWindow(fore, 0);
 
1407
        }
 
1408
    }
 
1409
#ifdef MULTIUSER
 
1410
  EffectiveAclUser = user;
 
1411
#endif
 
1412
  if (*args)
 
1413
    {
 
1414
      char *oldrcname = rc_name;
 
1415
      rc_name = "-X";
 
1416
      debug3("Running command on display %x window %x (%d)\n", display, fore, fore ? fore->w_number : -1);
 
1417
      flayer = fore ? &fore->w_layer : 0;
 
1418
      if (fore && fore->w_savelayer && (fore->w_blocked || fore->w_savelayer->l_cvlist == 0))
 
1419
        flayer = fore->w_savelayer;
 
1420
      DoCommand(args, argl);
 
1421
      rc_name = oldrcname;
 
1422
    }
 
1423
#ifdef MULTIUSER
 
1424
  EffectiveAclUser = 0;
 
1425
#endif
 
1426
}