home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / screen-3.2 / part06 < prev    next >
Text File  |  1992-02-09  |  57KB  |  2,517 lines

  1. Newsgroups: comp.sources.misc
  2. From: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  3. Subject:  v28i023:  screen-3.2 - multiple windows on an ASCII terminal, v3.2, Part06/11
  4. Message-ID: <1992Feb9.223654.6728@sparky.imd.sterling.com>
  5. X-Md4-Signature: b9ad9b52526f30cb86ba88c5eb712017
  6. Date: Sun, 9 Feb 1992 22:36:54 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  10. Posting-number: Volume 28, Issue 23
  11. Archive-name: screen-3.2/part06
  12. Environment: UNIX
  13.  
  14. #!/bin/sh
  15. # do not concatenate these parts, unpack them in order with /bin/sh
  16. # file screen3.2/screen.c continued
  17. #
  18. if test ! -r _shar_seq_.tmp; then
  19.     echo 'Please unpack part 1 first!'
  20.     exit 1
  21. fi
  22. (read Scheck
  23.  if test "$Scheck" != 6; then
  24.     echo Please unpack part "$Scheck" next!
  25.     exit 1
  26.  else
  27.     exit 0
  28.  fi
  29. ) < _shar_seq_.tmp || exit 1
  30. if test ! -f _shar_wnt_.tmp; then
  31.     echo 'x - still skipping screen3.2/screen.c'
  32. else
  33. echo 'x - continuing file screen3.2/screen.c'
  34. sed 's/^X//' << 'SHAR_EOF' >> 'screen3.2/screen.c' &&
  35. X          switch (ap[2])
  36. X        {
  37. X        case 'n':
  38. X        case '0':
  39. X          default_flow = FLOW_NOW * 0;
  40. X          break;
  41. X        case 'y':
  42. X        case '1':
  43. X        case '\0':
  44. X          default_flow = FLOW_NOW * 1;
  45. X          break;
  46. X        case 'a':
  47. X          default_flow = FLOW_AUTOFLAG;
  48. X          break;
  49. X        default:
  50. X          exit_with_usage(myname);
  51. X        }
  52. X          break;
  53. X            case 'h':
  54. X          if (ap[2])
  55. X        default_histheight = atoi(ap + 2);
  56. X          else
  57. X        {
  58. X          if (--ac == 0)
  59. X            exit_with_usage(myname);
  60. X          default_histheight = atoi(*++av);
  61. X        }
  62. X          if (default_histheight < 0)
  63. X        default_histheight = 0;
  64. X          break;
  65. X        case 'i':
  66. X          iflag = 1;
  67. X          break;
  68. X        case 't': /* title is a synonym for AkA */
  69. X        case 'k':
  70. X          if (ap[2])
  71. X        aka = ap + 2;
  72. X          else
  73. X        {
  74. X          if (--ac == 0)
  75. X            exit_with_usage(myname);
  76. X          aka = *++av;
  77. X        }
  78. X          break;
  79. X        case 'l':
  80. X          switch (ap[2])
  81. X        {
  82. X        case 'n':
  83. X        case '0':
  84. X          loginflag = 0;
  85. X          break;
  86. X        case 'y':
  87. X        case '1':
  88. X        case '\0':
  89. X          loginflag = 1;
  90. X          break;
  91. X        case 's':
  92. X        case 'i':
  93. X          lsflag = 1;
  94. X          break;
  95. X        default:
  96. X          exit_with_usage(myname);
  97. X        }
  98. X          break;
  99. X        case 'w':
  100. X          lsflag = 1;
  101. X          wipeflag = 1;
  102. X          break;
  103. X        case 'L':
  104. X          assume_LP = 1;
  105. X          break;
  106. X        case 'm':
  107. X          mflag = 1;
  108. X          break;
  109. X        case 'O':
  110. X          force_vt = 0;
  111. X          break;
  112. X        case 'T':
  113. X              if (ap[2])
  114. X        {
  115. X          if (strlen(ap+2) < 20)
  116. X                    strcpy(screenterm, ap + 2);
  117. X        }
  118. X              else
  119. X                {
  120. X                  if (--ac == 0)
  121. X                    exit_with_usage(myname);
  122. X          if (strlen(*++av) < 20)
  123. X                    strcpy(screenterm, *av);
  124. X                }
  125. X              break;
  126. X        case 'q':
  127. X          quietflag = 1;
  128. X          break;
  129. X        case 'r':
  130. X        case 'R':
  131. X          if (ap[2])
  132. X        {
  133. X          SockName = ap + 2;
  134. X          if (ac != 1)
  135. X            exit_with_usage(myname);
  136. X        }
  137. X          else if (ac > 1 && *av[1] != '-')
  138. X        {
  139. X          SockName = *++av;
  140. X          ac--;
  141. X        }
  142. X          rflag = (ap[1] == 'r') ? 1 : 2;
  143. X          break;
  144. #ifdef REMOTE_DETACH
  145. X        case 'd':
  146. X          dflag = 1;
  147. X          /* FALLTHRU */
  148. X        case 'D':
  149. X          if (!dflag)
  150. X        dflag = 2;
  151. X          if (ap[2])
  152. X        SockName = ap + 2;
  153. X          if (ac == 2)
  154. X        {
  155. X          if (*av[1] != '-')
  156. X            {
  157. X              SockName = *++av;
  158. X              ac--;
  159. X            }
  160. X        }
  161. X          break;
  162. #endif
  163. X        case 's':
  164. X          if (ap[2])
  165. X        ShellProg = ap + 2;
  166. X          else
  167. X        {
  168. X          if (--ac == 0)
  169. X            exit_with_usage(myname);
  170. X          ShellProg = *++av;
  171. X        }
  172. X          break;
  173. X        default:
  174. X          exit_with_usage(myname);
  175. X        }
  176. X    }
  177. X      else
  178. X    break;
  179. X    }
  180. X  real_uid = getuid();
  181. X  real_gid = getgid();
  182. X  eff_uid = geteuid();
  183. X  eff_gid = getegid();
  184. X  if (eff_uid != real_uid)
  185. X    {        
  186. X      /* if running with s-bit, we must install a special signal
  187. X       * handler routine that resets the s-bit, so that we get a
  188. X       * core file anyway.
  189. X       */
  190. X      signal(SIGBUS, CoreDump);
  191. X      signal(SIGSEGV, CoreDump);
  192. X    }
  193. X  if (!ShellProg && (ShellProg = getenv("SHELL")) == 0)
  194. X    ShellProg = DefaultShell;
  195. X  ShellArgs[0] = ShellProg;
  196. #ifdef NETHACK
  197. X  nethackflag = (getenv("NETHACKOPTIONS") != NULL);
  198. #endif
  199. X  home = getenv("HOME");    /* may or may not return a result. jw. */
  200. X  if ((LoginName = getlogin()) && LoginName[0] != '\0')
  201. X    {
  202. X      if ((ppp = getpwnam(LoginName)) != (struct passwd *) 0)
  203. X    if (ppp->pw_uid != real_uid)
  204. X      ppp = (struct passwd *) 0;
  205. X    }
  206. X  if (ppp == 0)
  207. X    {
  208. X      if ((ppp = getpwuid(real_uid)) == 0)
  209. X        {
  210. #ifdef NETHACK
  211. X          if (nethackflag)
  212. X        Msg(0, "An alarm sounds through the dungeon...\nWarning, the kops are coming.");
  213. X      else
  214. #endif
  215. X      Msg(0, "getpwuid() can't identify your account!");
  216. X      exit(1);
  217. X        }
  218. X      LoginName = ppp->pw_name;
  219. X    }
  220. X  if (home == 0 || *home == '\0')
  221. X    home = ppp->pw_dir;
  222. X  if (strlen(LoginName) > 20)
  223. X    Msg(0, "LoginName too long - sorry.");
  224. X  if (strlen(home) > MAXPATH - 25)
  225. X    Msg(0, "$HOME too long - sorry.");
  226. #ifdef PASSWORD
  227. X  strcpy(Password, ppp->pw_passwd);
  228. #endif
  229. X
  230. X  /* ttyname implies isatty */
  231. X  if (!(attach_tty = ttyname(0)))
  232. X    {
  233. #ifdef NETHACK
  234. X      if (nethackflag)
  235. X    Msg(0, "You must play from a terminal.");
  236. X      else
  237. #endif
  238. X      Msg(0, "Must be connected to a terminal.");
  239. X      exit(1);
  240. X    }
  241. X  if (strlen(attach_tty) >= MAXPATH)
  242. X    Msg(0, "TtyName too long - sorry.");
  243. X  if ((n = secopen(attach_tty, O_RDWR, 0)) < 0)
  244. X    Msg(0, "Cannot open '%s' - please check.", attach_tty);
  245. X  close(n);
  246. X    
  247. X  debug1("attach_tty is %s\n", attach_tty);
  248. X  
  249. #ifdef _MODE_T
  250. X  oumask = umask(0);        /* well, unsigned never fails? jw. */
  251. #else
  252. X  if ((oumask = umask(0)) == -1)
  253. X    Msg(errno, "Cannot change umask to zero");
  254. #endif
  255. X  if ((SockDir = getenv("ISCREENDIR")) == NULL)
  256. X    SockDir = getenv("SCREENDIR");
  257. X  if (SockDir && strlen(SockDir) >= MAXPATH - 1)
  258. X    Msg(0, "ridiculous long $(I)SCREENDIR - try again.");
  259. #ifndef SOCKDIR
  260. X  if (SockDir == 0)
  261. X    {
  262. X      sprintf(SockPath, "%s/.iscreen", home);
  263. X      SockDir = SockPath;
  264. X    }
  265. #endif
  266. X  if (SockDir)
  267. X    {
  268. X      if (access(SockDir, F_OK))
  269. X    {
  270. X      if (UserContext() > 0)
  271. X        {
  272. X          if (mkdir(SockDir, 0700))
  273. X        UserReturn(0);
  274. X          UserReturn(1);
  275. X        }
  276. X      if (UserStatus() <= 0)
  277. X        Msg(0, "Cannot make directory '%s'", SockDir);
  278. X    }
  279. X      if (SockDir != SockPath)
  280. X        strcpy(SockPath, SockDir);
  281. X    }
  282. #ifdef SOCKDIR
  283. X  else
  284. X    {
  285. X      SockDir = SOCKDIR;
  286. X      if (stat(SockDir, &st))
  287. X    {
  288. X      if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1)
  289. X        Msg(errno, "Cannot make directory '%s'", SockDir);
  290. X    }
  291. X      else
  292. X    {
  293. X          n = eff_uid ? 0777 : 0755;
  294. X      if ((st.st_mode & 0777) != n)
  295. X        Msg(0, "Directory '%s' must have mode %03o.", SockDir, n);
  296. X    }
  297. X      sprintf(SockPath, "%s/S-%s", SockDir, LoginName);
  298. X      if (access(SockPath, F_OK))
  299. X    {
  300. X      if (mkdir(SockPath, 0700) == -1)
  301. X        Msg(errno, "Cannot make directory '%s'", SockPath);
  302. X      (void) chown(SockPath, real_uid, real_gid);
  303. X    }
  304. X    }
  305. #endif
  306. X  if (stat(SockPath, &st) == -1)
  307. X    {
  308. X      Msg(errno, "Cannot access %s", SockPath);
  309. X    }
  310. X  else
  311. X    {
  312. #ifdef _POSIX_SOURCE
  313. X      if (S_ISDIR(st.st_mode) == 0)
  314. #else
  315. X      if ((st.st_mode & S_IFMT) != S_IFDIR)
  316. #endif
  317. X    Msg(0, "%s is not a directory.", SockPath);
  318. X      if (st.st_uid != real_uid)
  319. X    Msg(0, "You are not the owner of %s.", SockPath);
  320. X      if ((st.st_mode & 0777) != 0700)
  321. X    Msg(0, "Directory %s must have mode 700.", SockPath);
  322. X    }
  323. X  strcat(SockPath, "/");
  324. X  SockNamePtr = SockPath + strlen(SockPath);
  325. X  (void) umask(oumask);
  326. #if defined(SYSV) && !defined(ISC)
  327. X  if (uname(&utsnam) == -1)
  328. X    Msg(0, "uname() failed, errno = %d", errno);
  329. X  else
  330. X    {
  331. X      strncpy(HostName, utsnam.nodename, MAXSTR);
  332. X      HostName[(sizeof(utsnam.nodename) <= MAXSTR) ? 
  333. X               sizeof(utsnam.nodename) : MAXSTR] = '\0';
  334. X    }
  335. #else
  336. X  (void) gethostname(HostName, MAXSTR);
  337. #endif
  338. X  HostName[MAXSTR - 1] = '\0';
  339. X  if ((ap = index(HostName, '.')) != NULL)
  340. X    *ap = '\0';
  341. X  GetTTY(0, &OldMode);
  342. #ifdef POSIX
  343. X  ospeed = (short) cfgetospeed(&OldMode.tio);
  344. #else
  345. # ifndef TERMIO
  346. X  ospeed = (short) OldMode.m_ttyb.sg_ospeed;
  347. # endif
  348. #endif
  349. X  debug1("...setting extern short ospeed = %d\n", ospeed);
  350. X
  351. X  if (lsflag)
  352. X    {
  353. X      int i;
  354. X      i = FindSocket(0, (int *)NULL);
  355. X      /* MakeClientSocket appended the last (Sock)Name there: */
  356. X      *SockNamePtr = '\0';
  357. X      if (i == 0)
  358. X    {
  359. #ifdef NETHACK
  360. X          if (nethackflag)
  361. X        Msg(0, "This room is empty (%s)\n", SockPath);
  362. X          else
  363. #endif /* NETHACK */
  364. X          Msg(0, "No Sockets found in %s\n", SockPath);
  365. X        }
  366. X      else
  367. X        Msg(0, "%d Socket%s in %s.\n", i, i > 1 ? "s" : "", SockPath);
  368. X        /* NOTREACHED */
  369. X    }
  370. X  if (rflag)
  371. X    {
  372. X      debug("screen -r: - is there anybody out there?\n");
  373. #ifdef SHADOWPW
  374. X      setspent();  /* open shadow file while we are still root */
  375. #endif /* SHADOWPW */
  376. X      if (Attach(MSG_ATTACH))
  377. X    {
  378. X      Attacher();
  379. X      /* NOTREACHED */
  380. X    }
  381. X      debug("screen -r: backend not responding -- still crying\n");
  382. X    }
  383. X  else if (dflag)
  384. X    {
  385. X      (void) Attach(MSG_DETACH);
  386. X      DeadlyMsg = 0;
  387. X      Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : ""));
  388. X      eexit(0);
  389. X      /* NOTREACHED */
  390. X    }
  391. X  if (!mflag && (SockName = getenv("STY")) != 0 && *SockName != '\0')
  392. X    {
  393. X      setuid(real_uid);
  394. X      setgid(real_gid);
  395. X      s = MakeClientSocket(1, SockName);
  396. X      if (ac == 0)
  397. X    {
  398. X      ac = 1;
  399. X      av = ShellArgs;
  400. X    }
  401. X      av[ac] = aka;
  402. X      SendCreateMsg(s, ac, av, allflag, default_flow, loginflag, default_histheight,
  403. X            screenterm);
  404. X      close(s);
  405. X      exit(0);
  406. X    }
  407. #if defined(BSDJOBS) && !(defined(POSIX) || defined(SYSV))
  408. X  if ((DevTty = open("/dev/tty", O_RDWR | O_NDELAY)) == -1)
  409. X    Msg(errno, "/dev/tty");
  410. #endif
  411. X  switch (MasterPid = fork())
  412. X    {
  413. X    case -1:
  414. X      Msg(errno, "fork");
  415. X      /* NOTREACHED */
  416. X    case 0:
  417. X      break;
  418. X    default:
  419. X      sprintf(socknamebuf, "%d.%s.%s", MasterPid, stripdev(attach_tty),
  420. X          HostName);
  421. X      for (ap = socknamebuf; *ap; ap++)
  422. X    if (*ap == '/')
  423. X      *ap = '-';
  424. X      SockName = socknamebuf;
  425. #ifdef SHADOWPW
  426. X      setspent();  /* open shadow file while we are still root */
  427. #endif /* SHADOWPW */
  428. X      Attacher();
  429. X      /* NOTREACHED */
  430. X    }
  431. #ifdef DEBUG
  432. X  if (dfp != stderr)
  433. X    fclose(dfp);
  434. X  if ((dfp = fopen("/tmp/debug/screen.back", "w")) == NULL)
  435. X    dfp = stderr;
  436. X  else
  437. X    (void) chmod("/tmp/debug/screen.back", 0666);
  438. #endif
  439. X  debug("-- screen.back debug started\n");
  440. X  ap = av0 + strlen(av0) - 1;
  441. X  while (ap >= av0)
  442. X    {
  443. X      if (!strncmp("screen", ap, 6))
  444. X    {
  445. X      strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */
  446. X      break;
  447. X    }
  448. X      ap--;
  449. X    }
  450. X  if (ap < av0)
  451. X    *av0 = 'S';
  452. X
  453. X  AttacherPid = getppid();
  454. X  sprintf(socknamebuf, "%d.%s.%s", getpid(), stripdev(attach_tty), HostName);
  455. X  for (ap = socknamebuf; *ap; ap++)
  456. X    if (*ap == '/')
  457. X      *ap = '-';
  458. X  SockName = socknamebuf;
  459. X  ServerSocket = s = MakeServerSocket();
  460. #ifdef ETCSCREENRC
  461. X  if ((ap = getenv("SYSSCREENRC")) == NULL)
  462. X    StartRc(ETCSCREENRC);
  463. X  else
  464. X    StartRc(ap);
  465. #endif
  466. X  StartRc(RcFileName);
  467. X  InitTermcap();
  468. X  InitTerm(0);
  469. X  MakeNewEnv();
  470. X  strcpy(display_tty, attach_tty);
  471. #ifdef UTMPOK
  472. # ifdef apollo
  473. X  ReInitUtmp();
  474. # else
  475. X  InitUtmp();
  476. # endif /* apollo */
  477. #endif
  478. #ifdef LOADAV
  479. # ifdef NeXT
  480. X  InitNeXTLoadAvg(); /* NeXT load average */
  481. # else
  482. X  InitKmem();
  483. # endif /* !NeXT */
  484. #endif /* LOADAV */
  485. X  signal(SIGHUP, SigHup);
  486. X  signal(SIGINT, Finit);
  487. X  signal(SIGQUIT, Finit);
  488. X  signal(SIGTERM, Finit);
  489. #ifdef BSDJOBS
  490. X  signal(SIGTTIN, SIG_IGN);
  491. X  signal(SIGTTOU, SIG_IGN);
  492. #endif
  493. X  InitKeytab();
  494. #ifdef ETCSCREENRC
  495. X  if ((ap = getenv("SYSSCREENRC")) == NULL)
  496. X    FinishRc(ETCSCREENRC);
  497. X  else
  498. X    FinishRc(ap);
  499. #endif
  500. X  FinishRc(RcFileName);
  501. X
  502. X  /* Note: SetMode must be called _after_ FinishRc (flow is set there).
  503. X   */
  504. X  SetMode(&OldMode, &NewMode);
  505. X  SetTTY(0, &NewMode);
  506. X  if (loginflag == -1)
  507. X      loginflag = LOGINDEFAULT;
  508. X  if (ac == 0)
  509. X    {
  510. X      ac = 1;
  511. X      av = ShellArgs;
  512. X      if (!aka)
  513. X    aka = shellaka;
  514. X    }
  515. X  if (!HasWindow)
  516. X    {
  517. X      debug("We open one default window, as screenrc did not specify one.\n");
  518. X      if (MakeWindow(aka, av, allflag, default_flow, 0, (char *)0, loginflag, -1, (char *)0) == -1)
  519. X    {
  520. X      Finit(1);
  521. X      /* NOTREACHED */
  522. X    }
  523. X    }
  524. X  if (default_startup)
  525. X    display_copyright();
  526. #ifdef SYSV
  527. X  signal(SIGCLD, SigChld);
  528. #else
  529. X  signal(SIGCHLD, SigChld);
  530. #endif
  531. X  signal(SIGINT, SigInt);
  532. X  tv.tv_usec = 0;
  533. X  if (rflag == 2)
  534. X    {
  535. #ifdef NETHACK
  536. X      if (nethackflag)
  537. X        Msg(0, "I can't seem to find a... Hey, wait a minute!  Here comes a screen now.");
  538. X      else
  539. #endif
  540. X      Msg(0, "New screen...");
  541. X      rflag = 0;
  542. X    }
  543. X  brktty();
  544. X  for (;;)
  545. X    {
  546. X      /*
  547. X       * check to see if message line should be removed
  548. X       */
  549. X      if (status)
  550. X    {
  551. X      int time_left;
  552. X
  553. X      debug("checking status...\n");
  554. X      time_left = TimeDisplayed + (BellDisplayed ? VBellWait : MsgWait) - time((time_t *)0);
  555. X      if (time_left > 0)
  556. X        {
  557. X          tv.tv_sec = time_left;
  558. X          debug(" not yet.\n");
  559. X        }
  560. X      else
  561. X        {
  562. X          debug(" removing now.\n");
  563. X          RemoveStatus();
  564. X        }
  565. X    }
  566. X      /*
  567. X       * check for I/O on all available I/O descriptors
  568. X       */
  569. X      FD_ZERO(&r);
  570. X      FD_ZERO(&w);
  571. X      FD_ZERO(&e);
  572. X      if (inbuf_ct > 0)
  573. X    for (n = 0; n < MAXWIN; n++)
  574. #ifdef COPY_PASTE        /* wrong here? jw. */
  575. X      if (inlen[n] > 0 || (pastelen > 0 && n == ForeNum))
  576. #else
  577. X      if (inlen[n] > 0)
  578. #endif
  579. X        FD_SET(wtab[n]->ptyfd, &w);
  580. X      if (!Detached)
  581. X    FD_SET(0, &r);
  582. X      for (n = WinList; n != -1; n = p->WinLink)
  583. X    {
  584. X      p = wtab[n];
  585. X      if (p->active && status && !BellDisplayed && !HS)
  586. X        continue;
  587. X      if (p->outlen > 0)
  588. X        continue;
  589. X      if (in_ovl && ovl_blockfore && n == ForeNum)
  590. X        continue;
  591. X      FD_SET(p->ptyfd, &r);
  592. X    }
  593. X      FD_SET(s, &r);
  594. X      (void) fflush(stdout);
  595. X      if (GotSignal && !status)
  596. X    {
  597. X      SigHandler();
  598. X      continue;
  599. X    }
  600. X      if ((nsel = select(FD_SETSIZE, &r, &w, &e, (status) ? &tv : (struct timeval *) 0)) < 0)
  601. X    {
  602. X      debug1("Bad select - errno %d\n", errno);
  603. X      if (errno != EINTR)
  604. X        {
  605. X          perror("select");
  606. X          Finit(1);
  607. X        }
  608. X      else
  609. X        {
  610. X          errno = 0;
  611. X          if ((!GotSignal || status) && !InterruptPlease)
  612. X            continue;
  613. X        }
  614. X    }
  615. X      if (InterruptPlease)
  616. X    {
  617. X      char buf[1];
  618. X
  619. X      debug("Backend received interrupt\n");
  620. X      *buf = intrc;
  621. X      write(wtab[ForeNum]->ptyfd, buf, 1);
  622. X      debug1("Backend wrote interrupt to %d\n", ForeNum);
  623. X      InterruptPlease = 0;
  624. X
  625. X      continue;
  626. X    }
  627. X      if (GotSignal && !status)
  628. X    {
  629. X      SigHandler();
  630. X      continue;
  631. X    }
  632. X      /* Process a client connect attempt and message */
  633. X      if (nsel && FD_ISSET(s, &r))
  634. X    {
  635. X          nsel--;
  636. X      if (!HS)
  637. X        RemoveStatus();
  638. X      if (in_ovl)
  639. X        {
  640. X          SetOvlCurr();
  641. X          (*ovl_process)(0, 0); /* We have to abort first!! */
  642. X          CheckScreenSize(1); /* Change fore */
  643. X          DeadlyMsg = 0;
  644. #ifdef NETHACK
  645. X              if (nethackflag)
  646. X            Msg(0, "KAABLAMM!!!  You triggered a land mine!");
  647. X              else
  648. #endif
  649. X          Msg(0, "Aborted because of window change or message.");
  650. X        }
  651. X      else
  652. X        CheckScreenSize(1); /* Change fore */
  653. X      ReceiveMsg(s);
  654. X      continue;
  655. X    }
  656. X      /*
  657. X       * Write the stored user input to the window descriptors first.
  658. X       * We do not want to choke, if he types fast.
  659. X       */
  660. X      if (nsel && inbuf_ct > 0)
  661. X    {
  662. X      for (n = 0; n < MAXWIN ; n++)
  663. X        {
  664. X          if (inlen[n] <= 0)
  665. X        continue;
  666. X          tmp = wtab[n]->ptyfd;
  667. X              if (FD_ISSET(tmp, &w))
  668. X                {
  669. X          if ((len = write(tmp, inbuf[n], inlen[n])) > 0)
  670. X            {
  671. X              if ((inlen[n] -= len) == 0)
  672. X              inbuf_ct--;
  673. X              bcopy(inbuf[n] + len, inbuf[n], inlen[n]);
  674. X            }
  675. X          if (--nsel == 0)
  676. X            break;
  677. X        }
  678. X        }
  679. X    }
  680. X      /* Read, process, and store the user input */
  681. X      if (nsel && FD_ISSET(0, &r))
  682. X    {
  683. X          nsel--;
  684. X      if (!HS)
  685. X        RemoveStatus();
  686. X      if (ESCseen)
  687. X        {
  688. X          buf[0] = Esc;
  689. X          buflen = read(0, buf + 1, IOSIZE - 1) + 1;
  690. X          ESCseen = 0;
  691. X        }
  692. X      else
  693. X        buflen = read(0, buf, IOSIZE);
  694. X      if (buflen < 0)
  695. X        {
  696. X          debug1("Read error: %d - SigHup()ing!\n", errno);
  697. X          SigHup(SIGARG);
  698. X          continue;
  699. X        }
  700. X      if (buflen == 0)
  701. X        {
  702. X          debug("Found EOF - SigHup()ing!\n");
  703. X          SigHup(SIGARG);
  704. X          continue;
  705. X        }
  706. X      bufp = buf;
  707. X          if (in_ovl)
  708. X        {
  709. X          SetOvlCurr();
  710. X          (*ovl_process)(&bufp, &buflen);
  711. X        }
  712. X      while (buflen > 0)
  713. X        {
  714. X          n = ForeNum;
  715. X          len = inlen[n];
  716. X          bufp = ProcessInput(bufp, &buflen, inbuf[n], &inlen[n],
  717. X                  sizeof *inbuf);
  718. X          if (inlen[n] > 0 && len == 0)
  719. X        inbuf_ct++;
  720. X        }
  721. X      if (inbuf_ct > 0)
  722. X        continue;
  723. X    }
  724. X      if (GotSignal && !status)
  725. X    {
  726. X      SigHandler();
  727. X      continue;
  728. X    }
  729. #ifdef COPY_PASTE
  730. X      /* Write the copybuffer contents first, if any. jw. */
  731. X      if (pastelen > 0)
  732. X    {
  733. X      n = ForeNum;
  734. X      debug1("writing pastebuffer (%d)\n", pastelen);
  735. X      tmp = wtab[n]->ptyfd;
  736. X      if (            /* FD_ISSET(tmp, &w) && */
  737. X          (len = write(tmp, pastebuffer,
  738. X               pastelen > IOSIZE ? IOSIZE : pastelen)) > 0)
  739. X        {
  740. X          pastebuffer += len;
  741. X          pastelen -= len;
  742. X          debug1("%d bytes pasted\n", len);
  743. X          if (slowpaste > 0)
  744. X        {
  745. X          struct timeval t;
  746. X
  747. X                  debug1("slowpaste %d\n", slowpaste);
  748. X          t.tv_usec = (long) (slowpaste * 1000);
  749. X          t.tv_sec = 0;
  750. X          select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
  751. X        }
  752. X          else
  753. X            continue;
  754. X        }
  755. X      /* 
  756. X       * We could not paste? Let's see if the pty did echo the lot.
  757. X       * Then continue by processing some pty output.
  758. X       */
  759. X    }
  760. #endif
  761. X      if (GotSignal && !status)
  762. X    {
  763. X      SigHandler();
  764. X      continue;
  765. X    }
  766. X      /* Read and process the output from the window descriptors */
  767. X      for (n = WinList; n != -1; n = p->WinLink)
  768. X    {
  769. X      p = wtab[n];
  770. X      if (in_ovl && ovl_blockfore && n == ForeNum)
  771. X        continue;
  772. X      if (p->outlen)
  773. X        WriteString(p, p->outbuf, p->outlen);
  774. X      else if (nsel && FD_ISSET(p->ptyfd, &r))
  775. X        {
  776. X          nsel--;
  777. X          if ((len = read(p->ptyfd, buf, IOSIZE)) == -1)
  778. X        {
  779. #ifdef EWOULDBLOCK
  780. X          if (errno == EWOULDBLOCK)
  781. X            len = 0;
  782. #endif
  783. X        }
  784. #if defined(TIOCPKT) && !defined(sgi)
  785. X          if (buf[0])
  786. X        {
  787. X          debug1("PAKET %x\n", buf[0]);
  788. X          if (buf[0] & TIOCPKT_NOSTOP)
  789. X            {
  790. X              NewAutoFlow(p, 0);
  791. X            }
  792. X          if (buf[0] & TIOCPKT_DOSTOP)
  793. X            {
  794. X              NewAutoFlow(p, 1);
  795. X            }
  796. X        }
  797. X          if (len > 1)
  798. X        WriteString(p, buf + 1, len - 1);
  799. #else /* TIOCPKT && !sgi */
  800. X          if (len > 0)
  801. X        WriteString(p, buf, len);
  802. #endif /* TIOCPKT && !sgi */
  803. X        }
  804. X      if (p->bell == BELL_ON)
  805. X        {
  806. X          p->bell = BELL_DONE;
  807. X          Msg(0, MakeWinMsg(BellString, n));
  808. X          if (p->monitor == MON_FOUND)
  809. X        p->monitor = MON_DONE;
  810. X        }
  811. X      else if (p->bell == BELL_VISUAL)
  812. X        {
  813. X          if (!BellDisplayed)
  814. X        {
  815. X          p->bell = BELL_DONE;
  816. X          Msg(0, VisualBellString);
  817. X          BellDisplayed = 1;
  818. X        }
  819. X        }
  820. X      else if (p->monitor == MON_FOUND)
  821. X        {
  822. X          p->monitor = MON_DONE;
  823. X          Msg(0, MakeWinMsg(ActivityString, n));
  824. X        }
  825. X    }
  826. X      if (GotSignal && !status)
  827. X    SigHandler();
  828. #ifdef DEBUG
  829. X      if (nsel)
  830. X    debug1("Left over nsel: %d\n", nsel);
  831. #endif
  832. X    }
  833. X  /* NOTREACHED */
  834. }
  835. X
  836. static void SigHandler()
  837. {
  838. X  struct stat st;
  839. X  while (GotSignal)
  840. X    {
  841. X      GotSignal = 0;
  842. X      DoWait();
  843. #ifdef SYSV
  844. X      signal(SIGCLD, SigChld);
  845. #endif
  846. X    }
  847. X  if (stat(SockPath, &st) == -1)
  848. X    {
  849. X      debug1("SigHandler: Yuck! cannot stat '%s'\n", SockPath);
  850. X      if (!RecoverSocket())
  851. X    {
  852. X      debug("SCREEN cannot recover from corrupt Socket, bye\n");
  853. X      Finit(1);
  854. X    }
  855. X      else
  856. X    debug1("'%s' reconstructed\n", SockPath);
  857. X    }
  858. X  else
  859. X    debug2("SigHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode);
  860. }
  861. X
  862. #ifdef DEBUG
  863. int FEpanic;
  864. X
  865. sig_t FEChld(SIGDEFARG)
  866. {
  867. X  FEpanic=1;
  868. #ifndef SIGVOID
  869. X  return((sig_t) 0);
  870. #endif
  871. }
  872. #endif
  873. X
  874. static sig_t SigChld(SIGDEFARG)
  875. {
  876. X  debug("SigChld()\n");
  877. X  GotSignal = 1;
  878. #ifndef SIGVOID
  879. X  return((sig_t) 0);
  880. #endif
  881. }
  882. X
  883. sig_t SigHup(SIGDEFARG)
  884. {
  885. X  debug("SigHup()\n");
  886. X  if (auto_detach)
  887. X    Detach(D_DETACH);
  888. X  else
  889. X    Finit(0);
  890. #ifndef SIGVOID
  891. X  return((sig_t) 0);
  892. #endif
  893. }
  894. X
  895. /*
  896. X * the frontend's Interrupt handler
  897. X * we forward SIGINT to the backend
  898. X */
  899. static sig_t 
  900. AttacherSigInt(SIGDEFARG)
  901. {
  902. X  Kill(MasterPid, SIGINT);
  903. X  signal(SIGINT, AttacherSigInt);
  904. # ifndef SIGVOID
  905. X  return (sig_t) 0;
  906. # endif
  907. }
  908. X
  909. X
  910. /* 
  911. X * the backend's Interrupt handler
  912. X * we cannot insert the intrc directly, as we never know
  913. X * if fore and ForeNum are valid.
  914. X */
  915. static sig_t SigInt(SIGDEFARG)
  916. {
  917. #if HAZARDOUS
  918. X  char buf[1];
  919. X
  920. X  debug("SigInt()\n");
  921. X  *buf = (char) intrc;
  922. X  inlen[ForeNum] = 0;
  923. X  if (fore && !in_ovl)
  924. X    write(fore->ptyfd, buf, 1);
  925. #else
  926. X  debug("SigInt() careful\n");
  927. X  InterruptPlease = 1;
  928. X  signal(SIGINT, SigInt);
  929. #endif
  930. #ifndef SIGVOID
  931. X  return((sig_t) 0);
  932. #endif
  933. }
  934. X
  935. static sig_t CoreDump(sig)
  936. int sig;
  937. {
  938. X  setgid(getgid());
  939. X  setuid(getuid());
  940. X  unlink("core");
  941. X  fprintf(stderr, "\r\n[screen caught signal %d.%s]\r\n", sig,
  942. #ifdef SHADOWPW
  943. X          ""
  944. #else /* SHADOWPW */
  945. X          " (core dumped)"
  946. #endif /* SHADOWPW */
  947. X          );
  948. X  fflush(stderr);
  949. X  Kill(AttacherPid, SIG_BYE);
  950. #ifdef SHADOWPW
  951. X  eexit(sig);
  952. #else /* SHADOWPW */
  953. X  abort();
  954. #endif /* SHADOWPW */
  955. #ifndef SIGVOID
  956. X  return((sig_t) 0);
  957. #endif
  958. }
  959. X
  960. static void DoWait()
  961. {
  962. X  register int n, next, pid;
  963. #ifdef BSDWAIT
  964. X  union wait wstat;
  965. #else
  966. X  int wstat;
  967. #endif
  968. X
  969. #ifdef BSDJOBS
  970. # ifndef BSDWAIT
  971. X  while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0)
  972. # else
  973. X  while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0)
  974. # endif
  975. #else    /* BSDJOBS */
  976. X  while ((pid = wait(&wstat)) < 0)
  977. X    if (errno != EINTR)
  978. X      break;
  979. X  if (pid >= 0)
  980. #endif    /* BSDJOBS */
  981. X    {
  982. X      for (n = WinList; n != -1; n = next)
  983. X    {
  984. X      next = wtab[n]->WinLink;
  985. X      if (pid == wtab[n]->wpid)
  986. X        {
  987. #ifdef BSDJOBS
  988. X          if (WIFSTOPPED(wstat))
  989. X        {
  990. # ifdef NETHACK    
  991. X                  if (nethackflag)
  992. X            Msg(0, "You regain consciousness.");
  993. X          else
  994. # endif /* NETHACK */
  995. X          Msg(0, "Child has been stopped, restarting.");
  996. X          debug1("WIFSTOPPED: %d SIGCONT\n", wtab[n]->wpid);
  997. X          if (killpg(wtab[n]->wpid, SIGCONT))
  998. X            kill(wtab[n]->wpid, SIGCONT);
  999. X        }
  1000. X          else
  1001. #endif
  1002. X        KillWindow(n);
  1003. X        }
  1004. X    }
  1005. X    }
  1006. }
  1007. X
  1008. void KillWindow(n)
  1009. int n;
  1010. {
  1011. X  register int i;
  1012. X  /*
  1013. X   * Remove window from linked list.
  1014. X   */
  1015. X  if (n == WinList)    /* WinList = ForeNum */
  1016. X    {
  1017. X      RemoveStatus();
  1018. X      WinList = fore->WinLink;
  1019. X      fore = 0;
  1020. X    }
  1021. X  else
  1022. X    {
  1023. X      i = WinList;
  1024. X      while (wtab[i]->WinLink != n)
  1025. X    i = wtab[i]->WinLink;
  1026. X      wtab[i]->WinLink = wtab[n]->WinLink;
  1027. X    }
  1028. X  FreeWindow(wtab[n]);
  1029. X  wtab[n] = 0;
  1030. X  if (inlen[n] > 0)
  1031. X    {
  1032. X      inlen[n] = 0;
  1033. X      inbuf_ct--;
  1034. X    }
  1035. X  /*
  1036. X   * If the foreground window disappeared check the head of the linked list
  1037. X   * of windows for the most recently used window. If no window is alive at
  1038. X   * all, exit.
  1039. X   */
  1040. X  if (WinList == -1)
  1041. X    Finit(0);
  1042. X  if (!fore)
  1043. X    SwitchWindow(WinList);
  1044. }
  1045. X
  1046. static sig_t Finit(i)
  1047. int i;
  1048. {
  1049. X  register int n, next;
  1050. X
  1051. #ifdef SYSV
  1052. X  signal(SIGCLD, SIG_IGN);
  1053. #else
  1054. X  signal(SIGCHLD, SIG_IGN);
  1055. #endif
  1056. X  signal(SIGHUP, SIG_IGN);
  1057. X  debug1("Finit(%d);\n", i);
  1058. X  for (n = WinList; n != -1; n = next)
  1059. X    {
  1060. X      next = wtab[n]->WinLink;
  1061. X      FreeWindow(wtab[n]);
  1062. X    }
  1063. X  FinitTerm();
  1064. X  SetTTY(0, &OldMode);
  1065. #ifdef UTMPOK
  1066. X  RestoreLoginSlot();
  1067. #endif
  1068. X  printf("\n[screen is terminating]\n");
  1069. X  freetty();
  1070. X  if (ServerSocket != -1)
  1071. X    {
  1072. X      debug1("we unlink(%s)\n", SockPath);
  1073. X      (void) unlink(SockPath);
  1074. X    }
  1075. X  Kill(AttacherPid, SIG_BYE);
  1076. X  exit(i);
  1077. #ifndef SIGVOID
  1078. X  return((sig_t) 0);
  1079. #endif
  1080. }
  1081. X
  1082. void
  1083. eexit(e)
  1084. int e;
  1085. {
  1086. X  if (ServerSocket != -1)
  1087. X    {
  1088. X      debug1("we unlink(%s)\n", SockPath);
  1089. X      (void) unlink(SockPath);
  1090. X    }
  1091. X  exit(e);
  1092. }
  1093. X
  1094. static void InitKeytab()
  1095. {
  1096. X  register unsigned int i;
  1097. X
  1098. X  for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++)
  1099. X    ktab[i].type = KEY_IGNORE;
  1100. X
  1101. X  ktab['h'].type = ktab[Ctrl('h')].type = KEY_HARDCOPY;
  1102. #ifdef BSDJOBS
  1103. X  ktab['z'].type = ktab[Ctrl('z')].type = KEY_SUSPEND;
  1104. #endif
  1105. X  ktab['c'].type = ktab[Ctrl('c')].type = KEY_SHELL;
  1106. X  ktab[' '].type = ktab[Ctrl(' ')].type =
  1107. X    ktab['n'].type = ktab[Ctrl('n')].type = KEY_NEXT;
  1108. X  ktab['-'].type = ktab['p'].type = ktab[Ctrl('p')].type = KEY_PREV;
  1109. X  ktab['k'].type = ktab[Ctrl('k')].type = KEY_KILL;
  1110. X  ktab['l'].type = ktab[Ctrl('l')].type = KEY_REDISPLAY;
  1111. X  ktab['w'].type = ktab[Ctrl('w')].type = KEY_WINDOWS;
  1112. X  ktab['v'].type = ktab[Ctrl('v')].type = KEY_VERSION;
  1113. X  ktab['q'].type = ktab[Ctrl('q')].type = KEY_XON;
  1114. X  ktab['s'].type = ktab[Ctrl('s')].type = KEY_XOFF;
  1115. X  ktab['t'].type = ktab[Ctrl('t')].type = KEY_TIME;
  1116. X  ktab['i'].type = ktab[Ctrl('i')].type = KEY_INFO;
  1117. X  ktab['m'].type = ktab[Ctrl('m')].type = KEY_LASTMSG;
  1118. X  ktab['A'].type = KEY_AKA, ktab['A'].args = NULL;
  1119. X  ktab['L'].type = KEY_LOGIN;
  1120. X  ktab[','].type = KEY_LICENSE;
  1121. X  ktab['W'].type = KEY_WIDTH;
  1122. X  ktab['.'].type = KEY_TERMCAP;
  1123. X  ktab[Ctrl('\\')].type = KEY_QUIT;
  1124. X  ktab['d'].type = ktab[Ctrl('d')].type = KEY_DETACH;
  1125. X  ktab['r'].type = ktab[Ctrl('r')].type = KEY_WRAP;
  1126. X  ktab['f'].type = ktab[Ctrl('f')].type = KEY_FLOW;
  1127. X  ktab['C'].type = KEY_CLEAR;
  1128. X  ktab['Z'].type = KEY_RESET;
  1129. X  ktab['H'].type = KEY_LOGTOGGLE;
  1130. X  if (Esc != MetaEsc)
  1131. X    ktab[Esc].type = KEY_OTHER;
  1132. X  else
  1133. X    ktab[Esc].type = KEY_IGNORE;
  1134. X  ktab['M'].type = KEY_MONITOR;
  1135. X  ktab['?'].type = KEY_HELP;
  1136. X  for (i = 0; i <= 9; i++)
  1137. X    ktab['0' + i].type = (enum keytype) (i + (int)KEY_0);
  1138. X  ktab[Ctrl('G')].type = KEY_VBELL;
  1139. X  ktab[':'].type = KEY_COLON;
  1140. #ifdef COPY_PASTE
  1141. X  ktab['['].type = ktab[Ctrl('[')].type = KEY_COPY;
  1142. X  ktab[']'].type = ktab[Ctrl(']')].type = KEY_PASTE;
  1143. X  ktab['{'].type = KEY_HISTORY;
  1144. X  ktab['}'].type = KEY_HISTNEXT;
  1145. X  ktab['>'].type = KEY_WRITE_BUFFER;
  1146. X  ktab['<'].type = KEY_READ_BUFFER;
  1147. X  ktab['='].type = KEY_REMOVE_BUFFERS;
  1148. #endif
  1149. #ifdef POW_DETACH
  1150. X  ktab['D'].type = KEY_POW_DETACH;
  1151. #endif
  1152. #ifdef LOCK
  1153. X  ktab['x'].type = ktab[Ctrl('x')].type = KEY_LOCK;
  1154. #endif
  1155. }
  1156. X
  1157. /*
  1158. X * this is a braindamaged hack: if (obuf == NULL) then we provided
  1159. X * a key_type as a second char in ibuf. not a key.
  1160. X */
  1161. char *ProcessInput(ibuf, pilen, obuf, polen, obuf_size)
  1162. char *ibuf, *obuf;
  1163. register int *pilen, *polen, obuf_size;
  1164. {
  1165. X  register int n;
  1166. X  register enum keytype k;
  1167. X  register char *s, *p;
  1168. X  char buf[2];
  1169. X  int newwidth;
  1170. X
  1171. X  if (!obuf)
  1172. X    obuf_size = 0;
  1173. X
  1174. X  for (s = ibuf, p = obuf + *polen; *pilen > 0; --*pilen, s++)
  1175. X    {
  1176. X      if (*s == Esc)
  1177. X    {
  1178. X      debug2("'%c %c ", s[0], s[1]);
  1179. X      debug2("%c %c' ", s[2], s[3]);
  1180. X      if (*pilen > 1)
  1181. X        {
  1182. X          --*pilen;
  1183. X          s++;
  1184. #if defined(GOULD_NP1)
  1185. X          k = (obuf)?(ktab[*s].type):(enum keytype)(int)(*s);
  1186. #else
  1187. X          k = (obuf)?(ktab[*s].type):(enum keytype)(*s);
  1188. #endif
  1189. X          debug2("Processinput C-A %02x '%c' ", k, k);
  1190. X          debug1("%s\n", (obuf)?"std":"NOOBUF");
  1191. X          if (*s == MetaEsc)
  1192. X        {
  1193. X          if (*polen < obuf_size)
  1194. X            {
  1195. X              *p++ = Esc;
  1196. X              ++*polen;
  1197. X            }
  1198. X        }
  1199. X          else if ((int)k >= (int)KEY_0 && (int)k <= (int)KEY_9)
  1200. X        SwitchWindow((int)k - (int)KEY_0);
  1201. X          else
  1202. X        switch (k)
  1203. X          {
  1204. X          case KEY_TERMCAP:
  1205. X            WriteFile(DUMP_TERMCAP);
  1206. X            break;
  1207. X          case KEY_HARDCOPY:
  1208. X            WriteFile(DUMP_HARDCOPY);
  1209. X            break;
  1210. X          case KEY_LOGTOGGLE:
  1211. X            LogToggle();
  1212. X            break;
  1213. #ifdef BSDJOBS
  1214. X          case KEY_SUSPEND:
  1215. X            *pilen = 0;
  1216. X            Detach(D_STOP);
  1217. X            break;
  1218. #endif
  1219. X          case KEY_SHELL:
  1220. X            debug("calling MakeWindow with shell\n");
  1221. X            MakeWindow(shellaka, ShellArgs, allflag, default_flow,
  1222. X                   0, (char *) 0, loginflag, -1, (char *)0);
  1223. X            break;
  1224. X          case KEY_NEXT:
  1225. X            if (MoreWindows())
  1226. X              SwitchWindow(NextWindow());
  1227. X            break;
  1228. X          case KEY_PREV:
  1229. X            if (MoreWindows())
  1230. X              SwitchWindow(PreviousWindow());
  1231. X            break;
  1232. X          case KEY_KILL:
  1233. X            KillWindow(n = ForeNum);
  1234. #ifdef NETHACK
  1235. X                  if (nethackflag)
  1236. X              Msg(0, "You destroy poor window %d", n);
  1237. #endif
  1238. X            break;
  1239. X          case KEY_QUIT:
  1240. X            Finit(0);
  1241. X            /* NOTREACHED */
  1242. X          case KEY_DETACH:
  1243. X            *pilen = 0;
  1244. X            Detach(D_DETACH);
  1245. X            break;
  1246. #ifdef POW_DETACH
  1247. X          case KEY_POW_DETACH:
  1248. X            *pilen = 0;
  1249. X            if (obuf)
  1250. X              {
  1251. X            buf[0] = *s;
  1252. X            buf[1] = '\0';
  1253. X            Msg(0, buf);
  1254. X            read(0, buf, 1);
  1255. X            if (*buf != *s)
  1256. X              {
  1257. X                write(1, "\007", 1);
  1258. X                RemoveStatus();
  1259. #ifdef NETHACK
  1260. X                if (nethackflag)
  1261. X                   Msg(0, "The blast of disintegration whizzes by you!");
  1262. #endif
  1263. X                break;
  1264. X              }
  1265. X              }
  1266. X            Detach(D_POWER); /* detach and kill Attacher's
  1267. X                      * parent     */
  1268. X            break;
  1269. #endif
  1270. X          case KEY_REDISPLAY:
  1271. X            Activate(0);
  1272. X            break;
  1273. X          case KEY_WINDOWS:
  1274. X            ShowWindows();
  1275. X            break;
  1276. X          case KEY_VERSION:
  1277. X            Msg(0, "screen %d.%.2d.%.2d%s (%s) %s", REV, VERS,
  1278. X                PATCHLEVEL, STATE, ORIGIN, DATE);
  1279. X            break;
  1280. X          case KEY_TIME:
  1281. X            ShowTime();
  1282. X            break;
  1283. X          case KEY_INFO:
  1284. X            ShowInfo();
  1285. X            break;
  1286. X          case KEY_OTHER:
  1287. X            if (MoreWindows())
  1288. X              SwitchWindow(fore->WinLink);
  1289. X            break;
  1290. X          case KEY_XON:
  1291. X            if (*polen < obuf_size)
  1292. X              {
  1293. X            *p++ = Ctrl('q');
  1294. X            ++*polen;
  1295. X              }
  1296. X            break;
  1297. X          case KEY_XOFF:
  1298. X            if (*polen < obuf_size)
  1299. X              {
  1300. X            *p++ = Ctrl('s');
  1301. X            ++*polen;
  1302. X              }
  1303. X            break;
  1304. #ifdef LOCK
  1305. X          case KEY_LOCK:
  1306. X            Detach(D_LOCK); /* do it micha's way */
  1307. X            break;
  1308. #endif
  1309. X          case KEY_WIDTH:
  1310. X            if (Z0 || WS)
  1311. X              {
  1312. X            if (fore->width == Z0width)
  1313. X              newwidth = Z1width;
  1314. X            else if (fore->width == Z1width)
  1315. X              newwidth = Z0width;
  1316. X            else if (fore->width > (Z0width+Z1width)/2)
  1317. X              newwidth = Z0width;
  1318. X            else
  1319. X              newwidth = Z1width;
  1320. X            ChangeWindowSize(fore, newwidth, fore->height);
  1321. X            Activate(fore->norefresh);
  1322. X              }
  1323. X            else
  1324. X              Msg(0, "Your termcap does not specify how to change the terminal's width.");
  1325. X            break;
  1326. X          case KEY_LOGIN:
  1327. X            SlotToggle(0);
  1328. X            break;
  1329. X          case KEY_AKA:
  1330. X            if (!ktab[*s].args)
  1331. X              InputAKA();
  1332. X            else
  1333. X              strncpy(fore->cmd + fore->akapos, ktab[*s].args[0], 20);
  1334. X            break;
  1335. X          case KEY_COLON:
  1336. X            InputColon();
  1337. X            break;
  1338. X          case KEY_LASTMSG:
  1339. X            Msg(0, "%s", LastMsg);
  1340. X            break;
  1341. X          case KEY_SET:
  1342. X            DoSet(ktab[*s].args);
  1343. X            break;
  1344. X          case KEY_SCREEN:
  1345. X            debug3("KEY_SCREEN DoSc(, ktab[%d].args(='%s','%s')...)\n",
  1346. X               *s, ktab[*s].args[0], ktab[*s].args[1]);
  1347. X            DoScreen("key", ktab[*s].args);
  1348. X            break;
  1349. X          case KEY_CREATE:
  1350. X            debug2("KEY_CREATE MaWi(0, ktab[%d].args(='%s')...)\n",
  1351. X               *s, ktab[*s].args);
  1352. X            MakeWindow((char *) 0, ktab[*s].args, allflag, default_flow, 0, (char *) 0, loginflag, -1, (char *)0);
  1353. X            break;
  1354. X          case KEY_WRAP:
  1355. X            fore->wrap = !fore->wrap;
  1356. X            Msg(0, "%cwrap", fore->wrap ? '+' : '-');
  1357. X            break;
  1358. X          case KEY_FLOW:
  1359. X            if (fore->flow & FLOW_AUTOFLAG)
  1360. X              fore->flow = (fore->flow & FLOW_AUTO) | FLOW_NOW;
  1361. X            else if (fore->flow & FLOW_NOW)
  1362. X              fore->flow &= ~FLOW_NOW;
  1363. X            else
  1364. X              fore->flow = fore->flow ? FLOW_AUTOFLAG|FLOW_AUTO|FLOW_NOW : FLOW_AUTOFLAG;
  1365. X            SetFlow(fore->flow & FLOW_NOW);
  1366. X            Msg(0, "%cflow%s", (fore->flow & FLOW_NOW) ? '+' : '-',
  1367. X            (fore->flow & FLOW_AUTOFLAG) ? "(auto)" : "");
  1368. X            break;
  1369. X          case KEY_CLEAR:
  1370. X            if (fore->state == LIT)
  1371. X              WriteString(fore, "\033[H\033[J", 6);
  1372. X            break;
  1373. X          case KEY_RESET:
  1374. X            if (fore->state == LIT)
  1375. X              WriteString(fore, "\033c", 2);
  1376. X            break;
  1377. X          case KEY_MONITOR:
  1378. X            if (fore->monitor == MON_OFF)
  1379. X              {
  1380. X            fore->monitor = MON_ON;
  1381. X            Msg(0,
  1382. X                "Window %d is now being monitored for all activity.",
  1383. X                ForeNum);
  1384. X              }
  1385. X            else
  1386. X              {
  1387. X            fore->monitor = MON_OFF;
  1388. X            Msg(0,
  1389. X                "Window %d is no longer being monitored for activity.",
  1390. X                ForeNum);
  1391. X              }
  1392. X            break;
  1393. X          case KEY_HELP:
  1394. X            display_help();
  1395. X            break;
  1396. X          case KEY_LICENSE:
  1397. X            display_copyright();
  1398. X            break;
  1399. #ifdef COPY_PASTE
  1400. X          case KEY_COPY:
  1401. X            (void) MarkRoutine(PLAIN);
  1402. X            break;
  1403. X          case KEY_HISTNEXT:
  1404. X            if (MarkRoutine(CRAZY))
  1405. X              if (copybuffer != NULL)
  1406. X                {
  1407. X                pastelen = copylen;
  1408. X                pastebuffer = copybuffer;
  1409. X              debug("histnext\n");
  1410. X                }
  1411. X            break;
  1412. X          case KEY_HISTORY:
  1413. X            if (MarkRoutine(TRICKY))
  1414. X              if (copybuffer != NULL)
  1415. X            {
  1416. X              pastelen = copylen;
  1417. X              pastebuffer = copybuffer;
  1418. X              debug1("history new copylen: %d\n", pastelen);
  1419. X            }
  1420. X            break;
  1421. X          case KEY_PASTE:
  1422. X            if (copybuffer == NULL)
  1423. X              {
  1424. #ifdef NETHACK
  1425. X                  if (nethackflag)
  1426. X              Msg(0, "Nothing happens.");
  1427. X                  else
  1428. #endif
  1429. X            Msg(0, "empty buffer");
  1430. X            copylen = 0;
  1431. X            break;
  1432. X              }
  1433. X            pastelen = copylen;
  1434. X            pastebuffer = copybuffer;
  1435. X            break;
  1436. X          case KEY_WRITE_BUFFER:
  1437. X            if (copybuffer == NULL)
  1438. X              {
  1439. #ifdef NETHACK
  1440. X                  if (nethackflag)
  1441. X              Msg(0, "Nothing happens.");
  1442. X                  else
  1443. #endif
  1444. X            Msg(0, "empty buffer");
  1445. X            copylen = 0;
  1446. X            break;
  1447. X              }
  1448. X            WriteFile(DUMP_EXCHANGE);
  1449. X            break;
  1450. X          case KEY_READ_BUFFER:
  1451. X            ReadFile();
  1452. X            break;
  1453. X          case KEY_REMOVE_BUFFERS:
  1454. X            KillBuffers();
  1455. X            break;
  1456. #endif                /* COPY_PASTE */
  1457. X          case KEY_VBELL:
  1458. X            if (visual_bell)
  1459. X              {
  1460. X            visual_bell = 0;
  1461. X            Msg(0, "switched to audible bell");
  1462. X              }
  1463. X            else
  1464. X              {
  1465. X            visual_bell = 1;
  1466. X            Msg(0, "switched to visual bell");
  1467. X              }
  1468. X            break;
  1469. X           default:
  1470. X            break;
  1471. X          }
  1472. X        }
  1473. X      else
  1474. X        ESCseen = 1;
  1475. X      --*pilen;
  1476. X      s++;
  1477. X      break;
  1478. X    }
  1479. X      else if (*polen < obuf_size)
  1480. X    {
  1481. X      *p++ = *s;
  1482. X      ++*polen;
  1483. X    }
  1484. X    }
  1485. X  return (s);
  1486. }
  1487. X
  1488. /* Send a terminal report as if it were typed. */ 
  1489. void
  1490. Report(wp, fmt, n1, n2)
  1491. struct win *wp;
  1492. char *fmt;
  1493. int n1, n2;
  1494. {
  1495. X  register int n, len;
  1496. X  char rbuf[40];
  1497. X
  1498. X  sprintf(rbuf, fmt, n1, n2);
  1499. X  len = strlen(rbuf);
  1500. X
  1501. X  for (n = 0; n < MAXWIN; n++)
  1502. X    {
  1503. X      if (wp == wtab[n])
  1504. X    {
  1505. X      if ((unsigned)(inlen[n] + len) <= sizeof *inbuf)
  1506. X        {
  1507. X          bcopy(rbuf, inbuf[n] + inlen[n], len);
  1508. X          if (inlen[n] == 0)
  1509. X        inbuf_ct++;
  1510. X          inlen[n] += len;
  1511. X        }
  1512. X      break;
  1513. X    }
  1514. X    }/* for */
  1515. }
  1516. X
  1517. void
  1518. SwitchWindow(n)
  1519. int n;
  1520. {
  1521. X  debug1("SwitchWindow %d\n", n);
  1522. X  if (!wtab[n])
  1523. X    {
  1524. X      ShowWindows();
  1525. X      return;
  1526. X    }
  1527. X  if (wtab[n] == fore)
  1528. X    {
  1529. X      Msg(0, "This IS window %d.", n);
  1530. X      return;
  1531. X    }
  1532. X  SetForeWindow(n);
  1533. X  if (!Detached && !in_ovl)
  1534. X    Activate(fore->norefresh);
  1535. }
  1536. X
  1537. static void SetForeWindow(n)
  1538. int n;
  1539. {
  1540. X  /*
  1541. X   * If we come from another window, make it inactive.
  1542. X   */
  1543. X  if (fore)
  1544. X    fore->active = 0;
  1545. X  ForeNum = n;
  1546. X  fore = wtab[n];
  1547. X  if (!Detached && !in_ovl)
  1548. X    fore->active = 1;
  1549. X  /*
  1550. X   * Place the window at the head of the most-recently-used list.
  1551. X   */
  1552. X  if ((n = WinList) != ForeNum)
  1553. X    {
  1554. X      /*
  1555. X       * we had a bug here. we sometimes ran into n = -1; and crashed.
  1556. X       * (this is not the perfect fix. "if (...) break;" inserted. jw.)
  1557. X       */
  1558. X      while (wtab[n]->WinLink != ForeNum)
  1559. X    {
  1560. X      if (wtab[n]->WinLink == -1)
  1561. X        break;
  1562. X      n = wtab[n]->WinLink;
  1563. X    }
  1564. X      wtab[n]->WinLink = fore->WinLink;
  1565. X      fore->WinLink = WinList;
  1566. X      WinList = ForeNum;
  1567. X    }
  1568. }
  1569. X
  1570. static int NextWindow()
  1571. {
  1572. X  register struct win **pp;
  1573. X
  1574. X  for (pp = wtab + ForeNum + 1; pp != wtab + ForeNum; ++pp)
  1575. X    {
  1576. X      if (pp == wtab + MAXWIN)
  1577. X    pp = wtab;
  1578. X      if (*pp)
  1579. X    break;
  1580. X    }
  1581. X  return pp - wtab;
  1582. }
  1583. X
  1584. static int PreviousWindow()
  1585. {
  1586. X  register struct win **pp;
  1587. X
  1588. X  for (pp = wtab + ForeNum - 1; pp != wtab + ForeNum; --pp)
  1589. X    {
  1590. X      if (pp < wtab)
  1591. X    pp = wtab + MAXWIN - 1;
  1592. X      if (*pp)
  1593. X    break;
  1594. X    }
  1595. X  return pp - wtab;
  1596. }
  1597. X
  1598. static int MoreWindows()
  1599. {
  1600. X  if (fore->WinLink != -1)
  1601. X    return 1;
  1602. #ifdef NETHACK
  1603. X  if (nethackflag)
  1604. X    Msg(0, "You cannot escape from window %d!", ForeNum);
  1605. X  else
  1606. #endif
  1607. X  Msg(0, "No other window.");
  1608. X  return 0;
  1609. }
  1610. X
  1611. static void FreeWindow(wp)
  1612. struct win *wp;
  1613. {
  1614. #ifdef UTMPOK
  1615. X  RemoveUtmp(wp);
  1616. #endif
  1617. #ifdef SUIDROOT
  1618. X  (void) chmod(wp->tty, 0666);
  1619. X  (void) chown(wp->tty, 0, 0);
  1620. #endif
  1621. X  close(wp->ptyfd);
  1622. X  if (wp->logfp != NULL)
  1623. X    fclose(wp->logfp);
  1624. X  ChangeWindowSize(wp, 0, 0);
  1625. X  Free(wp);
  1626. }
  1627. X
  1628. int
  1629. MakeWindow(prog, args, aflag, flowflag, StartAt, dir, lflag, histheight, term)
  1630. char *prog, **args, *dir;
  1631. int aflag, flowflag, StartAt, lflag, histheight;
  1632. char *term; /* if term is nonzero we assume it "vt100" or the like.. */
  1633. {
  1634. X  register struct win **pp, *p;
  1635. X  register int n, f;
  1636. X  int tf, tlflag;
  1637. X  char ebuf[10];
  1638. #ifndef TIOCSWINSZ
  1639. X  char libuf[20], cobuf[20];
  1640. #endif
  1641. X  char tebuf[25];
  1642. X
  1643. X  pp = wtab + StartAt;
  1644. X  do
  1645. X    {
  1646. X      if (*pp == 0)
  1647. X    break;
  1648. X      if (++pp == wtab + MAXWIN)
  1649. X    pp = wtab;
  1650. X    } while (pp != wtab + StartAt);
  1651. X  if (*pp)
  1652. X    {
  1653. X      Msg(0, "No more windows.");
  1654. X      return -1;
  1655. X    }
  1656. X
  1657. X   if (((tlflag = lflag) == -1) && ((tlflag = loginflag) == -1))
  1658. X    tlflag = LOGINDEFAULT;
  1659. X
  1660. #ifdef USRLIMIT
  1661. X  /*
  1662. X   * Count current number of users, if logging windows in.
  1663. X   */
  1664. X  if (tlflag == 1 && CountUsers() >= USRLIMIT)
  1665. X    {
  1666. X      Msg(0, "User limit reached.  Window will not be logged in.");
  1667. X      tlflag = 0;
  1668. X    }
  1669. #endif
  1670. X  n = pp - wtab;
  1671. X  debug1("Makewin creating %d\n", n);
  1672. X  if ((f = OpenPTY()) == -1)
  1673. X    {
  1674. X      Msg(0, "No more PTYs.");
  1675. X      return -1;
  1676. X    }
  1677. #ifdef SYSV
  1678. X  (void) fcntl(f, F_SETFL, O_NDELAY);
  1679. #else
  1680. X  (void) fcntl(f, F_SETFL, FNDELAY);
  1681. #endif
  1682. #ifdef TIOCPKT
  1683. X    {
  1684. # ifdef sgi
  1685. X      /*
  1686. X       * on IRIX 3.3, regardless of stream head's read mode (RNORM/RMSGN/RMSGD)
  1687. X       * we loose data in TIOCPKT mode if our buffer is too small (IOSIZE)
  1688. X       * to hold the whole packet at first read().
  1689. X       * (Marc Boucher)
  1690. X       */
  1691. X      int flag = 0;
  1692. # else /* sgi */
  1693. X      int flag = 1;
  1694. # endif /* sgi */
  1695. X
  1696. X      if (ioctl(f, TIOCPKT, &flag))
  1697. X    {
  1698. X      Msg(errno, "TIOCPKT ioctl");
  1699. X      close(f);
  1700. X      return -1;
  1701. X    }
  1702. X    }
  1703. #endif
  1704. X  if ((p = (struct win *) malloc(sizeof(struct win))) == 0)
  1705. X    {
  1706. X      close(f);
  1707. X      Msg_nomem;
  1708. X      return -1;
  1709. X    }
  1710. X  bzero((char *) p, (int) sizeof(struct win));
  1711. X  p->ptyfd = f;
  1712. X  p->aflag = aflag;
  1713. X  if (flowflag < 0)
  1714. X    flowflag = default_flow;
  1715. X  p->flow = flowflag | ((flowflag & FLOW_AUTOFLAG) ? (FLOW_AUTO|FLOW_NOW) : FLOW_AUTO);
  1716. X  if (!prog)
  1717. X    prog = Filename(args[0]);
  1718. X  strncpy(p->cmd, prog, MAXSTR - 1);
  1719. X  if ((prog = rindex(p->cmd, '|')) != NULL)
  1720. X    {
  1721. X      *prog++ = '\0';
  1722. X      prog += strlen(prog);
  1723. X      p->akapos = prog - p->cmd;
  1724. X      p->autoaka = 0;
  1725. X    }
  1726. X  else
  1727. X    p->akapos = 0;
  1728. X  p->monitor = default_monitor;
  1729. X  p->norefresh = 0;
  1730. X  strncpy(p->tty, TtyName, MAXSTR - 1);
  1731. #ifdef SUIDROOT
  1732. X  (void) chown(TtyName, real_uid, real_gid);
  1733. # ifdef UTMPOK
  1734. X  (void) chmod(TtyName, tlflag ? TtyMode : (TtyMode & ~022));
  1735. # else
  1736. X  (void) chmod(TtyName, TtyMode);
  1737. # endif
  1738. #endif
  1739. X
  1740. X  if (histheight < 0)
  1741. X    histheight = default_histheight;
  1742. X  if (ChangeWindowSize(p, default_width, default_height))
  1743. X    {
  1744. X      FreeWindow(p);
  1745. X      return -1;
  1746. X    }
  1747. X  ChangeScrollback(p, histheight, default_width);
  1748. X  ResetScreen(p);
  1749. X  debug("forking...\n");
  1750. X  switch (p->wpid = fork())
  1751. X    {
  1752. X    case -1:
  1753. X      Msg(errno, "fork");
  1754. X      FreeWindow(p);
  1755. X      return -1;
  1756. X    case 0:
  1757. X      signal(SIGHUP, SIG_DFL);
  1758. X      signal(SIGINT, SIG_DFL);
  1759. X      signal(SIGQUIT, SIG_DFL);
  1760. X      signal(SIGTERM, SIG_DFL);
  1761. #ifdef BSDJOBS
  1762. X      signal(SIGTTIN, SIG_DFL);
  1763. X      signal(SIGTTOU, SIG_DFL);
  1764. #endif
  1765. X      setuid(real_uid);
  1766. X      setgid(real_gid);
  1767. X      if (dir && chdir(dir) == -1)
  1768. X    {
  1769. X      SendErrorMsg("Cannot chdir to %s: %s", dir, sys_errlist[errno]);
  1770. X      eexit(1);
  1771. X    }
  1772. X
  1773. X      freetty();
  1774. X      if ((tf = open(TtyName, O_RDWR)) == -1)
  1775. X    {
  1776. X      SendErrorMsg("Cannot open %s: %s", TtyName, sys_errlist[errno]);
  1777. X      eexit(1);
  1778. X    }
  1779. #ifdef SVR4
  1780. X      if (ioctl(tf, I_PUSH, "ptem"))
  1781. X    {
  1782. X      SendErrorMsg("Cannot I_PUSH ptem %s %s", TtyName, sys_errlist[errno]);
  1783. X      eexit(1);
  1784. X    }
  1785. X      if (ioctl(tf, I_PUSH, "ldterm"))
  1786. X    {
  1787. X      SendErrorMsg("Cannot I_PUSH ldterm %s %s", TtyName, sys_errlist[errno]);
  1788. X      eexit(1);
  1789. X    }
  1790. X      if (ioctl(tf, I_PUSH, "ttcompat"))
  1791. X    {
  1792. X      SendErrorMsg("Cannot I_PUSH ttcompat %s %s", TtyName, sys_errlist[errno]);
  1793. X      eexit(1);
  1794. X    }
  1795. #endif
  1796. X      (void) dup2(tf, 0);
  1797. X      (void) dup2(tf, 1);
  1798. X      (void) dup2(tf, 2);
  1799. #ifdef DEBUG
  1800. X      dfp = stderr;
  1801. #endif
  1802. X      closeallfiles();
  1803. X      fgtty();
  1804. #ifdef TIOCSWINSZ
  1805. X      glwz.ws_col = p->width;
  1806. X      glwz.ws_row = p->height;
  1807. X      (void) ioctl(0, TIOCSWINSZ, &glwz);
  1808. #else
  1809. X      sprintf(libuf, "LINES=%d", p->height);
  1810. X      sprintf(cobuf, "COLUMNS=%d", p->width);
  1811. X      NewEnv[4] = libuf;
  1812. X      NewEnv[5] = cobuf;
  1813. #endif
  1814. X      SetTTY(0, &OldMode);
  1815. X      if (aflag)
  1816. X        NewEnv[2] = MakeTermcap(1);
  1817. X      else
  1818. X        NewEnv[2] = Termcap;
  1819. X      if (term && *term && strcmp(screenterm, term) &&
  1820. X      (strlen(term) < 20))
  1821. X    {
  1822. X          char *s1, *s2, tl;
  1823. X
  1824. X      sprintf(tebuf, "TERM=%s", term);
  1825. X      debug2("Makewindow %d with %s\n", n, tebuf);
  1826. X          tl = strlen(term);
  1827. X      NewEnv[1] = tebuf;
  1828. X          if (s1 = index(Termcap, '|'))
  1829. X        {
  1830. X          if (s2 = index(++s1, '|'))
  1831. X        {
  1832. X          if (strlen(Termcap) - (s2 - s1) + tl < 1024)
  1833. X            {
  1834. X              bcopy(s2, s1 + tl, strlen(s2) + 1);
  1835. X              bcopy(term, s1, tl);
  1836. X            }
  1837. X        }
  1838. X            }
  1839. X    }
  1840. X      sprintf(ebuf, "WINDOW=%d", n);
  1841. X      NewEnv[3] = ebuf;
  1842. X
  1843. X      execvpe(*args, args, NewEnv);
  1844. X      SendErrorMsg("Cannot exec %s: %s", *args, sys_errlist[errno]);
  1845. X      exit(1);
  1846. X    } /* end fork switch */
  1847. X  /*
  1848. X   * Place the newly created window at the head of the most-recently-used list.
  1849. X   */
  1850. X  *pp = p;
  1851. X  p->WinLink = WinList;
  1852. X  WinList = n;
  1853. X  HasWindow = 1;
  1854. #ifdef UTMPOK
  1855. X  debug1("MakeWindow will %slog in.\n", tlflag?"":"not ");
  1856. X  if (tlflag == 1)
  1857. X    SetUtmp(p, n);
  1858. X  else
  1859. X    p->slot = (slot_t) -1;
  1860. #endif
  1861. X  SetForeWindow(n);
  1862. X  Activate(0);
  1863. X  return n;
  1864. }
  1865. X
  1866. static void execvpe(prog, args, env)
  1867. char *prog, **args, **env;
  1868. {
  1869. X  register char *path, *p;
  1870. X  char buf[1024];
  1871. X  char *shargs[MAXARGS + 1];
  1872. X  register int i, eaccess = 0;
  1873. X
  1874. X  if (prog[0] == '/')
  1875. X    path = "";
  1876. X  else if ((path = getenv("PATH")) == 0)
  1877. X    path = DefaultPath;
  1878. X  do
  1879. X    {
  1880. X      p = buf;
  1881. X      while (*path && *path != ':')
  1882. X    *p++ = *path++;
  1883. X      if (p > buf)
  1884. X    *p++ = '/';
  1885. X      strcpy(p, prog);
  1886. X      if (*path)
  1887. X    ++path;
  1888. X      execve(buf, args, env);
  1889. X      switch (errno)
  1890. X    {
  1891. X    case ENOEXEC:
  1892. X      shargs[0] = DefaultShell;
  1893. X      shargs[1] = buf;
  1894. X      for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i)
  1895. X        ;
  1896. X      execve(DefaultShell, shargs, env);
  1897. X      return;
  1898. X    case EACCES:
  1899. X      eaccess = 1;
  1900. X      break;
  1901. X    case ENOMEM:
  1902. X    case E2BIG:
  1903. X    case ETXTBSY:
  1904. X      return;
  1905. X    }
  1906. X    } while (*path);
  1907. X  if (eaccess)
  1908. X    errno = EACCES;
  1909. }
  1910. X
  1911. X
  1912. static void LogToggle()
  1913. {
  1914. X  char buf[1024];
  1915. X
  1916. X  sprintf(buf, "screenlog.%d", ForeNum);
  1917. X  if (fore->logfp != NULL)
  1918. X    {
  1919. X      Msg(0, "Logfile \"%s\" closed.", buf);
  1920. X      fclose(fore->logfp);
  1921. X      fore->logfp = NULL;
  1922. X      return;
  1923. X    }
  1924. X  if ((fore->logfp = secfopen(buf, "a")) == NULL)
  1925. X    {
  1926. X      Msg(errno, "Error opening logfile \"%s\"", buf);
  1927. X      return;
  1928. X    }
  1929. X  Msg(0, "%s logfile \"%s\"", ftell(fore->logfp) ? "Appending to" : "Creating", buf);
  1930. }
  1931. X
  1932. #ifdef NOREUID
  1933. static int UserPID;
  1934. static sig_t (*Usersigcld)__P(SIGPROTOARG);
  1935. #endif
  1936. static int UserSTAT;
  1937. X
  1938. int UserContext()
  1939. {
  1940. #ifdef NOREUID
  1941. X  if (eff_uid == real_uid)
  1942. X    return(1);
  1943. # ifdef SYSV
  1944. X  Usersigcld = signal(SIGCLD, SIG_DFL);
  1945. # else
  1946. X  Usersigcld = signal(SIGCHLD, SIG_DFL);
  1947. # endif
  1948. X  debug("UserContext: forking.\n");
  1949. X  switch (UserPID = fork())
  1950. X    {
  1951. X    case -1:
  1952. X      Msg(errno, "fork");
  1953. X      return -1;
  1954. X    case 0:
  1955. X      signal(SIGHUP, SIG_DFL);
  1956. X      signal(SIGINT, SIG_IGN);
  1957. X      signal(SIGQUIT, SIG_DFL);
  1958. X      signal(SIGTERM, SIG_DFL);
  1959. # ifdef BSDJOBS
  1960. X      signal(SIGTTIN, SIG_DFL);
  1961. X      signal(SIGTTOU, SIG_DFL);
  1962. # endif
  1963. X      setuid(real_uid);
  1964. X      setgid(real_gid);
  1965. X      return 1;
  1966. X    default:
  1967. X      return 0;
  1968. X    }
  1969. #else
  1970. X  setreuid(eff_uid, real_uid);
  1971. X  setregid(eff_gid, real_gid);
  1972. X  return 1;
  1973. #endif
  1974. }
  1975. X
  1976. void
  1977. UserReturn(val)
  1978. int val;
  1979. {
  1980. #if defined(NOREUID)
  1981. X  if (eff_uid == real_uid)
  1982. X    UserSTAT = val;
  1983. X  else
  1984. X    exit(val);
  1985. #else
  1986. X  setreuid(real_uid, eff_uid);
  1987. X  setregid(real_gid, eff_gid);
  1988. X  UserSTAT = val;
  1989. #endif
  1990. }
  1991. X
  1992. int UserStatus()
  1993. {
  1994. #ifdef NOREUID
  1995. X  int i;
  1996. # ifdef BSDWAIT
  1997. X  union wait wstat;
  1998. # else
  1999. X  int wstat;
  2000. # endif
  2001. X
  2002. X  if (eff_uid == real_uid)
  2003. X    return UserSTAT;
  2004. X  if (UserPID < 0)
  2005. X    return -1;
  2006. X  while ((errno = 0, i = wait(&wstat)) != UserPID)
  2007. X    if (i < 0 && errno != EINTR)
  2008. X      break;
  2009. # ifdef SYSV
  2010. X  (void) signal(SIGCLD, Usersigcld);
  2011. # else
  2012. X  (void) signal(SIGCHLD, Usersigcld);
  2013. # endif
  2014. X  if (i == -1)
  2015. X    return -1;
  2016. X  return (WEXITSTATUS(wstat));
  2017. #else
  2018. X  return UserSTAT;
  2019. #endif
  2020. }
  2021. X
  2022. static void ShowWindows()
  2023. {
  2024. X  char buf[1024];
  2025. X  register char *s;
  2026. X  register struct win **pp, *p;
  2027. X  register int i, OtherNum = fore->WinLink;
  2028. X  register char *cmd;
  2029. X
  2030. X  for (i = 0, s = buf, pp = wtab; pp < wtab + MAXWIN; ++i, ++pp)
  2031. X    {
  2032. X      if ((p = *pp) == 0)
  2033. X    continue;
  2034. X
  2035. X      if (p->akapos)
  2036. X    {
  2037. X      if (*(p->cmd + p->akapos) && *(p->cmd + p->akapos - 1) != ':')
  2038. X        cmd = p->cmd + p->akapos;
  2039. X      else
  2040. X        cmd = p->cmd + strlen(p->cmd) + 1;
  2041. X    }
  2042. X      else
  2043. X    cmd = p->cmd;
  2044. X      if (s - buf + 5 + strlen(cmd) > fore->width - 1)
  2045. X    break;
  2046. X      if (s > buf)
  2047. X    {
  2048. X      *s++ = ' ';
  2049. X      *s++ = ' ';
  2050. X    }
  2051. X      *s++ = i + '0';
  2052. X      if (i == ForeNum)
  2053. X    *s++ = '*';
  2054. X      else if (i == OtherNum)
  2055. X    *s++ = '-';
  2056. X      if (p->monitor == MON_DONE)
  2057. X    *s++ = '@';
  2058. X      if (p->bell == BELL_DONE)
  2059. X    *s++ = '!';
  2060. #ifdef UTMPOK
  2061. X      if (p->slot != (slot_t) 0 && p->slot != (slot_t) -1)
  2062. X    *s++ = '$';
  2063. #endif
  2064. X      if (p->logfp != NULL)
  2065. X    {
  2066. X      strcpy(s, "(L)");
  2067. X      s += 3;
  2068. X    }
  2069. X      *s++ = ' ';
  2070. X      strcpy(s, cmd);
  2071. X      s += strlen(s);
  2072. X      if (i == ForeNum)
  2073. X    {
  2074. X      /* 
  2075. X       * this is usually done by Activate(), but when looking
  2076. X       * on your current window, you may get annoyed, as there is still
  2077. X       * that temporal '!' and '@' displayed.
  2078. X       * So we remove that after displaying it once.
  2079. X       */
  2080. X      p->bell = BELL_OFF;
  2081. X      if (p->monitor != MON_OFF)
  2082. X        p->monitor = MON_ON;
  2083. X    }
  2084. X    }
  2085. X  *s++ = ' ';
  2086. X  *s = '\0';
  2087. X  Msg(0, "%s", buf);
  2088. }
  2089. X
  2090. #ifdef LOADAV_3LONGS
  2091. extern long loadav[3];
  2092. #else
  2093. # ifdef LOADAV_4LONGS
  2094. extern long loadav[4];
  2095. # else
  2096. #  ifdef LOADAV_NEXT
  2097. extern float loadav;
  2098. #  else
  2099. extern double loadav[3];
  2100. #  endif
  2101. # endif
  2102. #endif
  2103. extern avenrun;
  2104. X
  2105. static void ShowTime()
  2106. {
  2107. X  char buf[512];
  2108. #ifdef LOADAV
  2109. X  char *p;
  2110. #endif
  2111. X  struct tm *tp;
  2112. X  time_t now;
  2113. X
  2114. X  (void) time(&now);
  2115. X  tp = localtime(&now);
  2116. X  sprintf(buf, "%2d:%02.2d:%02.2d %s", tp->tm_hour, tp->tm_min, tp->tm_sec,
  2117. X      HostName);
  2118. #ifdef LOADAV
  2119. X  if (avenrun && GetAvenrun())
  2120. X    {
  2121. X      p = buf + strlen(buf);
  2122. # ifdef LOADAV_3LONGS
  2123. X      sprintf(p, " %2.2f %2.2f %2.2f", (double) loadav[0] / FSCALE,
  2124. X          (double) loadav[1] / FSCALE, (double) loadav[2] / FSCALE);
  2125. # else
  2126. #  ifdef LOADAV_4LONGS
  2127. X      sprintf(p, " %2.2f %2.2f %2.2f %2.2f", (double) loadav[0] / 100,
  2128. X          (double) loadav[1] / 100, (double) loadav[2] / 100,
  2129. X          (double) loadav[3] / 100);
  2130. #  else
  2131. #   ifdef LOADAV_NEXT
  2132. X      sprintf(p, " %2.2f", loadav);
  2133. #   else
  2134. #    ifdef apollo
  2135. X      sprintf(p, " %2.2f %2.2f %2.2f", loadav[0]/65536.0, loadav[1]/65536.0,
  2136. X          loadav[2]/65536.0);
  2137. #    else
  2138. X      sprintf(p, " %2.2f %2.2f %2.2f", loadav[0], loadav[1], loadav[2]);
  2139. #    endif /* apollo */
  2140. #   endif /* LOADAV_NEXT */
  2141. #  endif /* LOADAV_4LONGS */
  2142. # endif /* LOADAV_3LONGS */
  2143. X    }
  2144. #endif /* LOADAV */
  2145. X  Msg(0, "%s", buf);
  2146. }
  2147. X
  2148. static void ShowInfo()
  2149. {
  2150. X  char buf[512], *p;
  2151. X  register struct win *wp = fore;
  2152. X  register int i;
  2153. X
  2154. X  sprintf(buf, "(%d,%d)/(%d,%d)+%d %c%sflow %cins %corg %cwrap %capp %clog %cmon %cr",
  2155. X      wp->x + 1, wp->y + 1, wp->width, wp->height,
  2156. X      wp->histheight,
  2157. X      (wp->flow & FLOW_NOW) ? '+' : '-',
  2158. X      (wp->flow & FLOW_AUTOFLAG) ? "" : ((wp->flow & FLOW_AUTO) ? "(+)" : "(-)"),
  2159. X      wp->insert ? '+' : '-', wp->origin ? '+' : '-',
  2160. X      wp->wrap ? '+' : '-', wp->keypad ? '+' : '-',
  2161. X      (wp->logfp != NULL) ? '+' : '-',
  2162. X      (wp->monitor != MON_OFF) ? '+' : '-',
  2163. X      wp->norefresh ? '-' : '+');
  2164. X  if (ISO2022)
  2165. X    {
  2166. X      p = buf + strlen(buf);
  2167. X      sprintf(p, " G%1d [", wp->LocalCharset);
  2168. X      for (i = 0; i < 4; i++)
  2169. X    p[i + 5] = wp->charsets[i] ? wp->charsets[i] : 'B';
  2170. X      p[9] = ']';
  2171. X      p[10] = '\0';
  2172. X    }
  2173. X  Msg(0, "%s", buf);
  2174. }
  2175. X
  2176. #if defined(sequent) || defined(_SEQUENT_) || defined(SVR4)
  2177. X
  2178. static int OpenPTY()
  2179. {
  2180. X  char *m, *s;
  2181. X  register int f;
  2182. # ifdef SVR4
  2183. X  char *ptsname();
  2184. X  sig_t (*sigcld)();
  2185. X
  2186. X  if ((f = open("/dev/ptmx", O_RDWR)) == -1)
  2187. X    return(-1);
  2188. X
  2189. X  /*
  2190. X   * SIGCLD set to SIG_DFL for grantpt() because it fork()s and
  2191. X   * exec()s pt_chmod
  2192. X   */
  2193. X  sigcld = signal(SIGCLD, SIG_DFL);
  2194. X       
  2195. X  if ((m = ptsname(f)) == NULL || unlockpt(f) || grantpt(f))
  2196. X    {
  2197. X      signal(SIGCLD, sigcld);
  2198. X      close(f);
  2199. X      return(-1);
  2200. X    } 
  2201. X  signal(SIGCLD, sigcld);
  2202. X  strncpy(TtyName, m, sizeof TtyName);
  2203. # else /* SVR4 */
  2204. X  if ((f = getpseudotty(&s, &m)) < 0)
  2205. X    return(-1);
  2206. X  strncpy(PtyName, m, sizeof PtyName);
  2207. X  strncpy(TtyName, s, sizeof TtyName);
  2208. # endif /* SVR4 */
  2209. # ifdef POSIX
  2210. X  tcflush(f, TCIOFLUSH);
  2211. # else
  2212. X  (void) ioctl(f, TIOCFLUSH, (char *) 0);
  2213. # endif
  2214. # ifdef LOCKPTY
  2215. X  (void) ioctl(f, TIOCEXCL, (char *) 0);
  2216. # endif
  2217. X  return (f);
  2218. }
  2219. X
  2220. #else /* defined(sequent) || defined(_SEQUENT_) || defined(SVR4) */
  2221. # ifdef MIPS
  2222. X
  2223. static int OpenPTY()
  2224. {
  2225. X  register char *p, *l, *d;
  2226. X  register f, tf;
  2227. X  register my_minor;
  2228. X  struct stat buf;
  2229. X   
  2230. X  strcpy(PtyName, PtyProto);
  2231. X  for (p = PtyName; *p != 'X'; ++p)
  2232. X    ;
  2233. X  for (l = "zyxwvutsrqp"; *p = *l; ++l)
  2234. X    {
  2235. X      for (d = "0123456789abcdef"; p[1] = *d; ++d)
  2236. X    {
  2237. X      if ((f = open(PtyName, O_RDWR)) != -1)
  2238. X        {
  2239. X          fstat(f, &buf);
  2240. X          my_minor = minor(buf.st_rdev);
  2241. X          sprintf(TtyName, "/dev/ttyq%d", my_minor);
  2242. X          if ((tf = open(TtyName, O_RDWR)) != -1)
  2243. X        {
  2244. X          close(tf);
  2245. #ifdef LOCKPTY
  2246. X          (void) ioctl(f, TIOCEXCL, (char *)0);
  2247. #endif
  2248. X          return f;
  2249. X        }
  2250. X          close(f);
  2251. X        }
  2252. X    }
  2253. X    }
  2254. X  return -1;
  2255. }
  2256. X
  2257. # else  /* MIPS */
  2258. #  ifdef sgi
  2259. X
  2260. static int OpenPTY()
  2261. {
  2262. X  register f;
  2263. X  register my_minor;
  2264. X  struct stat buf;
  2265. X   
  2266. X  strcpy(PtyName, "/dev/ptc");
  2267. X  f = open(PtyName, O_RDWR|O_NDELAY);
  2268. X  if (f >= 0)
  2269. X    {
  2270. X      if (fstat(f, &buf) < 0)
  2271. X    {
  2272. X      close(f);
  2273. X      return -1;
  2274. X    }
  2275. X      my_minor = minor(buf.st_rdev);
  2276. X      sprintf(TtyName, "/dev/ttyq%d", my_minor);
  2277. X    }
  2278. X  return f;
  2279. }
  2280. X
  2281. #  else /* sgi */
  2282. #   ifdef _AIX /* RS6000 */
  2283. X
  2284. static int OpenPTY()
  2285. {
  2286. X  register int i, f, tf;
  2287. X
  2288. X  for (i = 0; i < 256; i++)
  2289. X    {
  2290. X      sprintf(PtyName, "/dev/ptc/%d", i);
  2291. X      if ((f = open(PtyName, O_RDWR)) != -1)
  2292. X    {
  2293. X      sprintf(TtyName, "/dev/pts/%d", i);
  2294. X      if ((tf = open(TtyName, O_RDWR)) != -1)
  2295. X        {
  2296. X          close(tf);
  2297. #ifdef LOCKPTY
  2298. X          (void) ioctl(f, TIOCEXCL, (char *) 0);
  2299. #endif
  2300. X          return f;
  2301. X        }
  2302. X      close(f);
  2303. X    }
  2304. X    }
  2305. X  return -1;
  2306. }
  2307. X
  2308. #   else /* _AIX, RS6000 */
  2309. X
  2310. static int OpenPTY()
  2311. {
  2312. X  register char *p, *q, *l, *d;
  2313. X  register int f, tf;
  2314. X
  2315. #    if !defined(hpux)
  2316. X  debug("Hello, You are none of: sequent, _SEQUENT_, SVR4, MIPS, sgi, AIX\n");
  2317. X  debug("       This OpenPTY() is for hpux, ... and for you?\n");
  2318. #    endif
  2319. X  strcpy(PtyName, PtyProto);
  2320. X  strcpy(TtyName, TtyProto);
  2321. X  for (p = PtyName; *p != 'X'; ++p)
  2322. X    ;
  2323. X  for (q = TtyName; *q != 'X'; ++q)
  2324. X    ;
  2325. #ifdef sequent
  2326. X  /* why ask for sequent in #else (not sequent) section? jw. */
  2327. X  for (l = "p"; (*p = *l) != '\0'; ++l)
  2328. X    {                /* } */
  2329. X      for (d = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; (p[1] = *d) != '\0'; ++d)
  2330. X    {            /* } */
  2331. #else
  2332. # ifdef hpux
  2333. X  for (l = "pqrstuvw"; (*p = *l) != '\0'; ++l)
  2334. # else
  2335. X  for (l = "qpr"; (*p = *l) != '\0'; ++l)
  2336. #endif
  2337. X    {
  2338. X      for (d = "0123456789abcdef"; (p[1] = *d) != '\0'; ++d)
  2339. X    {
  2340. #endif
  2341. X      if ((f = open(PtyName, O_RDWR)) != -1)
  2342. X        {
  2343. X          q[0] = *l;
  2344. X          q[1] = *d;
  2345. X          if ((tf = open(TtyName, O_RDWR)) != -1)
  2346. X        {
  2347. X          /* close tf, thus we also get rid of an unwanted
  2348. X           * controlling terminal! 
  2349. X           */
  2350. X          close(tf);
  2351. #ifdef LOCKPTY
  2352. X          (void) ioctl(f, TIOCEXCL, (char *) 0);
  2353. #endif
  2354. X          return f;
  2355. X        }
  2356. X          close(f);
  2357. X        }
  2358. X    }
  2359. X    }
  2360. X  return -1;
  2361. }
  2362. X
  2363. #   endif /* _AIX, RS6000 */
  2364. #  endif /* sgi */
  2365. # endif /* MIPS */
  2366. #endif
  2367. X
  2368. void 
  2369. SetTTY(fd, mp)
  2370. int fd;
  2371. struct mode *mp;
  2372. {
  2373. X  errno = 0;
  2374. #ifdef POSIX
  2375. X  tcsetattr(fd, TCSADRAIN, &mp->tio);
  2376. # ifdef hpux
  2377. X  ioctl(fd, TIOCSLTC, &mp->m_ltchars);
  2378. # endif
  2379. #else
  2380. # ifdef TERMIO
  2381. X  ioctl(fd, TCSETA, &mp->tio);
  2382. # else
  2383. X  /* ioctl(fd, TIOCSETP, &mp->m_ttyb); */
  2384. X  ioctl(fd, TIOCSETC, &mp->m_tchars);
  2385. X  ioctl(fd, TIOCSLTC, &mp->m_ltchars);
  2386. X  ioctl(fd, TIOCLSET, &mp->m_lmode);
  2387. X  ioctl(fd, TIOCSETD, &mp->m_ldisc);
  2388. X  ioctl(fd, TIOCSETP, &mp->m_ttyb);
  2389. # endif
  2390. #endif
  2391. X  if (errno)
  2392. X    Msg(0, "SetTTY: ioctl failed");
  2393. }
  2394. X
  2395. void
  2396. GetTTY(fd, mp)
  2397. int fd;
  2398. struct mode *mp;
  2399. {
  2400. X  errno = 0;
  2401. #ifdef POSIX
  2402. X  tcgetattr(fd, &mp->tio);
  2403. # ifdef hpux
  2404. X  ioctl(fd, TIOCGLTC, &mp->m_ltchars);
  2405. # endif
  2406. #else
  2407. # ifdef TERMIO
  2408. X  ioctl(fd, TCGETA, &mp->tio);
  2409. # else
  2410. X  ioctl(fd, TIOCGETP, &mp->m_ttyb);
  2411. X  ioctl(fd, TIOCGETC, &mp->m_tchars);
  2412. X  ioctl(fd, TIOCGLTC, &mp->m_ltchars);
  2413. X  ioctl(fd, TIOCLGET, &mp->m_lmode);
  2414. X  ioctl(fd, TIOCGETD, &mp->m_ldisc);
  2415. # endif
  2416. #endif
  2417. X  if (errno)
  2418. X    Msg(0, "GetTTY: ioctl failed");
  2419. }
  2420. X
  2421. void
  2422. SetMode(op, np)
  2423. struct mode *op, *np;
  2424. {
  2425. X  *np = *op;
  2426. X
  2427. #if defined(TERMIO) || defined(POSIX)
  2428. X  np->tio.c_iflag &= ~ICRNL;
  2429. # ifdef ONLCR
  2430. X  np->tio.c_oflag &= ~ONLCR;
  2431. # endif
  2432. X  np->tio.c_lflag &= ~(ICANON | ECHO);
  2433. X
  2434. X  /*
  2435. X   * Unfortunately, the master process never will get SIGINT if the real
  2436. X   * terminal is different from the one on which it was originaly started
  2437. X   * (process group membership has not been restored or the new tty could not
  2438. X   * be made controlling again). In my solution, it is the attacher who
  2439. X   * receives SIGINT (because it is always correctly associated with the real
  2440. X   * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. 
  2441. X   * Marc Boucher (marc@CAM.ORG)
  2442. X   */
  2443. X  np->tio.c_lflag |= ISIG;
  2444. X  /* 
  2445. X   * careful, careful catche monkey..
  2446. X   * never set VMIN and VTIME to zero, if you want blocking io.
  2447. X   */
  2448. X  np->tio.c_cc[VMIN] = 1;
  2449. X  np->tio.c_cc[VTIME] = 0;
  2450. #ifdef VSTART
  2451. X  startc = op->tio.c_cc[VSTART];
  2452. #endif
  2453. #ifdef VSTOP
  2454. X  stopc = op->tio.c_cc[VSTOP];
  2455. #endif
  2456. X  if (iflag)
  2457. X    intrc = op->tio.c_cc[VINTR];
  2458. X  else
  2459. X    intrc = np->tio.c_cc[VINTR] = 0377;
  2460. X  np->tio.c_cc[VQUIT] = 0377;
  2461. X  if (flow == 0)
  2462. X    {
  2463. X      np->tio.c_cc[VINTR] = 0377;
  2464. #ifdef VSTART
  2465. X      np->tio.c_cc[VSTART] = 0377;
  2466. #endif
  2467. #ifdef VSTOP
  2468. X      np->tio.c_cc[VSTOP] = 0377;
  2469. #endif
  2470. X      np->tio.c_iflag &= ~IXON;
  2471. X    }
  2472. #ifdef VDISCARD
  2473. X  np->tio.c_cc[VDISCARD] = 0377;
  2474. #endif
  2475. #ifdef VSUSP
  2476. X  np->tio.c_cc[VSUSP] = 0377;
  2477. #endif
  2478. # ifdef hpux
  2479. X  np->m_ltchars.t_suspc = 0377;
  2480. X  np->m_ltchars.t_dsuspc = 0377;
  2481. X  np->m_ltchars.t_flushc = 0377;
  2482. X  np->m_ltchars.t_lnextc = 0377;
  2483. # else
  2484. #  ifdef VDSUSP
  2485. X  np->tio.c_cc[VDSUSP] = 0377;
  2486. #  endif
  2487. # endif
  2488. #else
  2489. X  startc = op->m_tchars.t_startc;
  2490. X  stopc = op->m_tchars.t_stopc;
  2491. X  if (iflag)
  2492. X    intrc = op->m_tchars.t_intrc;
  2493. X  else
  2494. X    intrc = np->m_tchars.t_intrc = -1;
  2495. X  np->m_ttyb.sg_flags &= ~(CRMOD | ECHO);
  2496. X  np->m_ttyb.sg_flags |= CBREAK;
  2497. X  np->m_tchars.t_quitc = -1;
  2498. X  if (flow == 0)
  2499. X    {
  2500. X      np->m_tchars.t_intrc = -1;
  2501. X      np->m_tchars.t_startc = -1;
  2502. X      np->m_tchars.t_stopc = -1;
  2503. X    }
  2504. X  np->m_ltchars.t_suspc = -1;
  2505. X  np->m_ltchars.t_dsuspc = -1;
  2506. X  np->m_ltchars.t_flushc = -1;
  2507. X  np->m_ltchars.t_lnextc = -1;
  2508. #endif                /* defined(TERMIO) || defined(POSIX) */
  2509. SHAR_EOF
  2510. true || echo 'restore of screen3.2/screen.c failed'
  2511. fi
  2512. echo 'End of  part 6'
  2513. echo 'File screen3.2/screen.c is continued in part 7'
  2514. echo 7 > _shar_seq_.tmp
  2515. exit 0
  2516. exit 0 # Just in case...
  2517.