home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / screen35 / part06 < prev    next >
Encoding:
Text File  |  1993-07-25  |  94.9 KB  |  4,408 lines

  1. Newsgroups: comp.sources.unix
  2. From: mlschroe@immd4.informatik.uni-erlangen.de (Michael Schroeder)
  3. Subject: v26i305: screen-3.5 - screen manager with VT100/ANSI terminal emulation, V3.5, Part06/10
  4. Sender: unix-sources-moderator@gw.home.vix.com
  5. Approved: vixie@gw.home.vix.com
  6.  
  7. Submitted-By: mlschroe@immd4.informatik.uni-erlangen.de (Michael Schroeder)
  8. Posting-Number: Volume 26, Issue 305
  9. Archive-Name: screen-3.5/part06
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 6 (of 10)."
  18. # Contents:  ansi.c screen.c
  19. # Wrapped by vixie@gw.home.vix.com on Sun Jul 25 12:57:21 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'ansi.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'ansi.c'\"
  23. else
  24. echo shar: Extracting \"'ansi.c'\" \(39996 characters\)
  25. sed "s/^X//" >'ansi.c' <<'END_OF_FILE'
  26. X/* Copyright (c) 1993
  27. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  28. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  29. X * Copyright (c) 1987 Oliver Laumann
  30. X *
  31. X * This program is free software; you can redistribute it and/or modify
  32. X * it under the terms of the GNU General Public License as published by
  33. X * the Free Software Foundation; either version 2, or (at your option)
  34. X * any later version.
  35. X *  
  36. X * This program is distributed in the hope that it will be useful,
  37. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39. X * GNU General Public License for more details.
  40. X *
  41. X * You should have received a copy of the GNU General Public License
  42. X * along with this program (see the file COPYING); if not, write to the
  43. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  44. X *
  45. X ****************************************************************
  46. X */
  47. X
  48. X#include "rcs.h"
  49. XRCS_ID("$Id: ansi.c,v 1.12 1993/07/21 15:42:44 mlschroe Exp $ FAU")
  50. X
  51. X#include <stdio.h>
  52. X#include <sys/types.h>
  53. X#include <fcntl.h>
  54. X#ifndef sun    /* we want to know about TIOCPKT. */
  55. X# include <sys/ioctl.h>
  56. X#endif
  57. X#include "config.h"
  58. X#include "screen.h"
  59. X#include "extern.h"
  60. X
  61. Xextern char *getenv(), *tgetstr(), *tgoto();
  62. X#ifndef __STDC__
  63. Xextern char *malloc();
  64. X#endif
  65. X
  66. Xextern struct win *windows;    /* linked list of all windows */
  67. Xextern struct win *fore;
  68. Xextern struct display *display, *displays;
  69. X
  70. Xextern int  force_vt;
  71. Xextern int  all_norefresh;    /* => display */
  72. Xextern char Esc, MetaEsc;    /* => display */
  73. Xextern time_t Now;
  74. X
  75. Xint maxwidth;            /* maximum of all widths so far */
  76. X
  77. Xint Z0width, Z1width;        /* widths for Z0/Z1 switching */
  78. X
  79. Xstatic struct win *curr;    /* window we are working on */
  80. Xstatic int rows, cols;        /* window size of the curr window */
  81. X
  82. Xint default_wrap = 1;        /* default: wrap on */
  83. Xint default_monitor = 0; 
  84. X
  85. Xint visual_bell = 0;
  86. Xint use_hardstatus = 1;
  87. X
  88. Xchar *blank;            /* line filled with spaces */
  89. Xchar *null;            /* line filled with '\0' */
  90. Xchar *OldImage, *OldAttr, *OldFont;    /* temporary buffers */
  91. X
  92. Xstatic void WinProcess __P((char **, int *));
  93. Xstatic void WinRedisplayLine __P((int, int, int, int));
  94. Xstatic void WinClearLine __P((int, int, int));
  95. Xstatic int  WinRewrite __P((int, int, int, int));
  96. Xstatic void WinSetCursor __P((void));
  97. Xstatic int  WinResize __P((int, int));
  98. Xstatic void WinRestore __P((void));
  99. Xstatic int  Special __P((int));
  100. Xstatic void DoESC __P((int, int ));
  101. Xstatic void DoCSI __P((int, int ));
  102. Xstatic void SetChar __P((int));
  103. Xstatic void StartString __P((enum string_t));
  104. Xstatic void SaveChar __P((int ));
  105. Xstatic void PrintChar __P((int ));
  106. Xstatic void PrintFlush __P((void));
  107. Xstatic void DesignateCharset __P((int, int ));
  108. Xstatic void MapCharset __P((int));
  109. Xstatic void SaveCursor __P((void));
  110. Xstatic void RestoreCursor __P((void));
  111. Xstatic void BackSpace __P((void));
  112. Xstatic void Return __P((void));
  113. Xstatic void LineFeed __P((int));
  114. Xstatic void ReverseLineFeed __P((void));
  115. Xstatic void InsertAChar __P((int));
  116. Xstatic void InsertChar __P((int));
  117. Xstatic void DeleteChar __P((int));
  118. Xstatic void DeleteLine __P((int));
  119. Xstatic void InsertLine __P((int));
  120. Xstatic void ScrollUpMap __P((int));
  121. Xstatic void ScrollDownMap __P((int));
  122. Xstatic void Scroll __P((char *, int, int, char *));
  123. Xstatic void ForwardTab __P((void));
  124. Xstatic void BackwardTab __P((void));
  125. Xstatic void ClearScreen __P((void));
  126. Xstatic void ClearFromBOS __P((void));
  127. Xstatic void ClearToEOS __P((void));
  128. Xstatic void ClearFullLine __P((void));
  129. Xstatic void ClearToEOL __P((void));
  130. Xstatic void ClearFromBOL __P((void));
  131. Xstatic void ClearInLine __P((int, int, int));
  132. Xstatic void CursorRight __P((int));
  133. Xstatic void CursorUp __P((int));
  134. Xstatic void CursorDown __P((int));
  135. Xstatic void CursorLeft __P((int));
  136. Xstatic void ASetMode __P((int));
  137. Xstatic void SelectRendition __P((void));
  138. Xstatic void RestorePosAttrFont __P((void));
  139. Xstatic void FillWithEs __P((void));
  140. Xstatic void UpdateLine __P((char *, char *, char *, int, int, int ));
  141. Xstatic void FindAKA __P((void));
  142. Xstatic void Report __P((char *, int, int));
  143. X
  144. X
  145. X/*
  146. X *  The window layer functions
  147. X */
  148. X
  149. Xstruct LayFuncs WinLf =
  150. X{
  151. X  WinProcess,
  152. X  0,
  153. X  WinRedisplayLine,
  154. X  WinClearLine,
  155. X  WinRewrite,
  156. X  WinSetCursor,
  157. X  WinResize,
  158. X  WinRestore
  159. X};
  160. X
  161. Xstatic void
  162. XWinProcess(bufpp, lenp)
  163. Xchar **bufpp;
  164. Xint *lenp;
  165. X{
  166. X  int f, *ilen, l = *lenp;
  167. X  char *ibuf;
  168. X  
  169. X  fore = d_fore;
  170. X#ifdef MULTIUSER
  171. X  /* if w_wlock is set, only one user may write, else we check acls */
  172. X  if ((fore->w_wlock == WLOCK_OFF) ? 
  173. X      AclCheckPermWin(d_user, ACL_WRITE, fore) :
  174. X      (d_user != fore->w_wlockuser))
  175. X    {
  176. X      SetCurr(fore);
  177. X      Special('\007');
  178. X      *bufpp += *lenp;
  179. X      *lenp = 0;
  180. X      return;
  181. X    }
  182. X#endif /* MULTIUSER */
  183. X#ifdef PSEUDOS
  184. X  if (W_UWP(fore))
  185. X    {
  186. X      /* we send the user input to our pseudowin */
  187. X      ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen;
  188. X      f = sizeof(fore->w_pwin->p_inbuf) - *ilen;
  189. X    }
  190. X  else
  191. X#endif /* PSEUDOS */
  192. X    {
  193. X      /* we send the user input to the window */
  194. X      ibuf = fore->w_inbuf; ilen = &fore->w_inlen;
  195. X      f = sizeof(fore->w_inbuf) - *ilen;
  196. X    }
  197. X  if (l > f)
  198. X    {
  199. X      debug1("Yuck! pty buffer full (%d chars missing). lets beep\n", l - f);
  200. X      SetCurr(fore);
  201. X      Special('\007');
  202. X      l = f;
  203. X    }
  204. X  if (l > 0)
  205. X    {
  206. X      bcopy(*bufpp, ibuf + *ilen, l);
  207. X      *ilen += l;
  208. X    }
  209. X  *bufpp += *lenp;
  210. X  *lenp = 0;
  211. X}
  212. X
  213. Xstatic void
  214. XWinRedisplayLine(y, from, to, isblank)
  215. Xint y, from, to, isblank;
  216. X{
  217. X  if (y < 0)
  218. X    return;
  219. X  fore = d_fore;
  220. X  DisplayLine(isblank ? blank: null, null, null, fore->w_image[y],
  221. X              fore->w_attr[y], fore->w_font[y], y, from, to);
  222. X}
  223. X
  224. Xstatic int
  225. XWinRewrite(y, x1, x2, doit)
  226. Xint y, x1, x2, doit;
  227. X{
  228. X  register int cost, dx;
  229. X  register char *p, *f, *i;
  230. X
  231. X  fore = d_fore;
  232. X  dx = x2 - x1;
  233. X  if (doit)
  234. X    {
  235. X      i = fore->w_image[y] + x1;
  236. X      while (dx-- > 0)
  237. X    PUTCHAR(*i++);
  238. X      return(0);
  239. X    }
  240. X  p = fore->w_attr[y] + x1;
  241. X  f = fore->w_font[y] + x1;
  242. X
  243. X  cost = dx = x2 - x1;
  244. X  if (d_insert)
  245. X    cost += d_EIcost + d_IMcost;
  246. X  while(dx-- > 0)
  247. X    {
  248. X      if (*p++ != d_attr || *f++ != d_font)
  249. X    return EXPENSIVE;
  250. X    }
  251. X  return cost;
  252. X}
  253. X
  254. Xstatic void
  255. XWinClearLine(y, xs, xe)
  256. Xint y, xs, xe;
  257. X{
  258. X  fore = d_fore;
  259. X  DisplayLine(fore->w_image[y], fore->w_attr[y], fore->w_font[y],
  260. X          blank, null, null, y, xs, xe);
  261. X}
  262. X
  263. Xstatic void
  264. XWinSetCursor()
  265. X{
  266. X  fore = d_fore;
  267. X  GotoPos(fore->w_x, fore->w_y);
  268. X}
  269. X
  270. Xstatic int
  271. XWinResize(wi, he)
  272. Xint wi, he;
  273. X{
  274. X  fore = d_fore;
  275. X  if (fore)
  276. X    ChangeWindowSize(fore, wi, he);
  277. X  return 0;
  278. X}
  279. X
  280. Xstatic void
  281. XWinRestore()
  282. X{
  283. X  fore = d_fore;
  284. X  ChangeScrollRegion(fore->w_top, fore->w_bot);
  285. X  KeypadMode(fore->w_keypad);
  286. X  CursorkeysMode(fore->w_cursorkeys);
  287. X  SetFlow(fore->w_flow & FLOW_NOW);
  288. X  InsertMode(fore->w_insert);
  289. X  fore->w_active = 1;
  290. X}
  291. X
  292. X/* 
  293. X *  Activate - make fore window active
  294. X *  norefresh = -1 forces a refresh, disregard all_norefresh then.
  295. X */
  296. Xvoid
  297. XActivate(norefresh)
  298. Xint norefresh;
  299. X{
  300. X  debug1("Activate(%d)\n", norefresh);
  301. X  if (display == 0)
  302. X    return;
  303. X  RemoveStatus();
  304. X  fore = d_fore;
  305. X  if (fore)
  306. X    {
  307. X      ASSERT(fore->w_display == display);
  308. X      fore->w_active = d_layfn == &WinLf;
  309. X      if (fore->w_monitor != MON_OFF)
  310. X    fore->w_monitor = MON_ON;
  311. X      fore->w_bell = BELL_OFF;
  312. X      if (ResizeDisplay(fore->w_width, fore->w_height))
  313. X    {
  314. X      debug2("Cannot resize from (%d,%d)", d_width, d_height);
  315. X      debug2(" to (%d,%d) -> resize window\n", fore->w_width, fore->w_height);
  316. X      DoResize(d_width, d_height);
  317. X    }
  318. X    }
  319. X  Redisplay(norefresh + all_norefresh);
  320. X}
  321. X
  322. Xvoid
  323. XResetWindow(p)
  324. Xregister struct win *p;
  325. X{
  326. X  register int i;
  327. X
  328. X  p->w_wrap = default_wrap;
  329. X  p->w_origin = 0;
  330. X  p->w_insert = 0;
  331. X  p->w_vbwait = 0;
  332. X  p->w_keypad = 0;
  333. X  p->w_cursorkeys = 0;
  334. X  p->w_top = 0;
  335. X  p->w_bot = p->w_height - 1;
  336. X  p->w_saved = 0;
  337. X  p->w_Attr = 0;
  338. X  p->w_Font = 0;
  339. X  p->w_x = p->w_y = 0;
  340. X  p->w_state = LIT;
  341. X  p->w_StringType = NONE;
  342. X  p->w_ss = 0;
  343. X  p->w_Charset = G0;
  344. X  bzero(p->w_tabs, p->w_width);
  345. X  for (i = 8; i < p->w_width; i += 8)
  346. X    p->w_tabs[i] = 1;
  347. X  for (i = G0; i <= G3; i++)
  348. X    p->w_charsets[i] = ASCII;
  349. X}
  350. X
  351. X
  352. X/*
  353. X *  Here comes the vt100 emulator
  354. X */
  355. Xvoid
  356. XWriteString(wp, buf, len)
  357. Xstruct win *wp;
  358. Xregister char *buf;
  359. Xregister int len;
  360. X{
  361. X  register int c;
  362. X
  363. X  if (!len)
  364. X    return;
  365. X  if (wp->w_logfp != NULL)
  366. X    if ((int)fwrite(buf, len, 1, wp->w_logfp) < 1)
  367. X      {
  368. X    Msg(errno, "Error writing logfile");
  369. X    fclose(wp->w_logfp);
  370. X    wp->w_logfp = NULL;
  371. X      }
  372. X  /*
  373. X   * SetCurr() here may prevent output, as it may set display = 0
  374. X   */
  375. X  SetCurr(wp);
  376. X  if (display)
  377. X    {
  378. X      if (d_status && !(use_hardstatus && HS))
  379. X    RemoveStatus();
  380. X    }
  381. X  else
  382. X    {
  383. X      if (curr->w_tstamp.seconds)
  384. X        curr->w_tstamp.lastio = Now;
  385. X
  386. X      if (curr->w_monitor == MON_ON || curr->w_monitor == MON_DONE)
  387. X    {
  388. X          debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell);
  389. X          curr->w_monitor = MON_FOUND;
  390. X    }
  391. X    }
  392. X  do
  393. X    {
  394. X      if (curr->w_Attr && curr->w_attr[curr->w_y] == null)
  395. X    {
  396. X      if ((curr->w_attr[curr->w_y] = (char *)malloc(curr->w_width + 1)) == 0)
  397. X        {
  398. X          curr->w_attr[curr->w_y] = null;
  399. X          curr->w_Attr = 0;
  400. X          Msg(0, "Warning: no space for attr - turned off");
  401. X        }
  402. X      else
  403. X        bzero(curr->w_attr[curr->w_y], curr->w_width + 1);
  404. X    }
  405. X      if (curr->w_Font && curr->w_font[curr->w_y] == null)
  406. X    {
  407. X      if ((curr->w_font[curr->w_y] = (char *)malloc(curr->w_width + 1)) == 0)
  408. X        {
  409. X          curr->w_font[curr->w_y] = null;
  410. X              curr->w_Font = curr->w_charsets[curr->w_ss ? curr->w_ss : curr->w_Charset] = 0;
  411. X          Msg(0, "Warning: no space for font - turned off");
  412. X        }
  413. X      else
  414. X        bzero(curr->w_font[curr->w_y], curr->w_width + 1);
  415. X    }
  416. X
  417. X      c = (unsigned char)*buf++;
  418. X      if (c == '\177')
  419. X    continue;
  420. X
  421. X      /* The next part is only for speedup */
  422. X      if (curr->w_state == LIT &&
  423. X          c >= ' ' && ((c & 0x80) == 0 || display == 0 || !CB8) &&
  424. X          !curr->w_insert && !curr->w_ss)
  425. X    {
  426. X      register int currx;
  427. X      register char *imp, *atp, *fop, at, fo;
  428. X
  429. X      currx = curr->w_x;
  430. X      imp = curr->w_image[curr->w_y] + currx;
  431. X      atp = curr->w_attr[curr->w_y] + currx;
  432. X      fop = curr->w_font[curr->w_y] + currx;
  433. X      at = curr->w_Attr;
  434. X      fo = curr->w_Font;
  435. X      if (display)
  436. X        {
  437. X          if (d_x != currx || d_y != curr->w_y)
  438. X        GotoPos(currx, curr->w_y);
  439. X          if (at != d_attr)
  440. X        SetAttr(at);
  441. X          if (fo != d_font)
  442. X        SetFont(fo);
  443. X          if (d_insert)
  444. X        InsertMode(0);
  445. X        }
  446. X      while (currx < cols - 1)
  447. X        {
  448. X          if (display)
  449. X        AddChar(d_font != '0' ? c : d_c0_tab[c]);
  450. X          *imp++ = c;
  451. X          *atp++ = at;
  452. X          *fop++ = fo;
  453. X          currx++;
  454. Xskip:          if (--len == 0)
  455. X        break;
  456. X              c = (unsigned char)*buf++;
  457. X          if (c == '\177')
  458. X        goto skip;
  459. X          if (c < ' ' || ((c & 0x80) && display && CB8))
  460. X        break;
  461. X        }
  462. X      curr->w_x = currx;
  463. X      if (display)
  464. X        d_x = currx;
  465. X      if (len == 0)
  466. X        break;
  467. X    }
  468. X      /* end of speedup code */
  469. X
  470. X      if ((c & 0x80) && display && CB8)
  471. X    {
  472. X      FILE *logfp = wp->w_logfp;
  473. X      char *cb8 = CB8;
  474. X    
  475. X      wp->w_logfp = NULL;    /* a little hack */
  476. X      CB8 = NULL;        /* dito */
  477. X      WriteString(wp, cb8, (int)strlen(cb8));
  478. X      wp->w_logfp = logfp;
  479. X      CB8 = cb8;
  480. X      c &= 0x7f;
  481. X    }
  482. X    tryagain:
  483. X      switch (curr->w_state)
  484. X    {
  485. X    case PRIN:
  486. X      switch (c)
  487. X        {
  488. X        case '\033':
  489. X          curr->w_state = PRINESC;
  490. X          break;
  491. X        default:
  492. X          PrintChar(c);
  493. X        }
  494. X      break;
  495. X    case PRINESC:
  496. X      switch (c)
  497. X        {
  498. X        case '[':
  499. X          curr->w_state = PRINCSI;
  500. X          break;
  501. X        default:
  502. X          PrintChar('\033');
  503. X          PrintChar(c);
  504. X          curr->w_state = PRIN;
  505. X        }
  506. X      break;
  507. X    case PRINCSI:
  508. X      switch (c)
  509. X        {
  510. X        case '4':
  511. X          curr->w_state = PRIN4;
  512. X          break;
  513. X        default:
  514. X          PrintChar('\033');
  515. X          PrintChar('[');
  516. X          PrintChar(c);
  517. X          curr->w_state = PRIN;
  518. X        }
  519. X      break;
  520. X    case PRIN4:
  521. X      switch (c)
  522. X        {
  523. X        case 'i':
  524. X          curr->w_state = LIT;
  525. X          PrintFlush();
  526. X          break;
  527. X        default:
  528. X          PrintChar('\033');
  529. X          PrintChar('[');
  530. X          PrintChar('4');
  531. X          PrintChar(c);
  532. X          curr->w_state = PRIN;
  533. X        }
  534. X      break;
  535. X    case STRESC:
  536. X      switch (c)
  537. X        {
  538. X        case '\\':
  539. X          curr->w_state = LIT;
  540. X          *(curr->w_stringp) = '\0';
  541. X          switch (curr->w_StringType)
  542. X        {
  543. X        case GM:
  544. X            {
  545. X              struct display *old = display;
  546. X              for (display = displays; display; display = display->_d_next)
  547. X            if (display != old)
  548. X              MakeStatus(curr->w_string);
  549. X              display = old;
  550. X            }
  551. X          /*FALLTHROUGH*/
  552. X        case PM:
  553. X          if (!display)
  554. X            break;
  555. X          MakeStatus(curr->w_string);
  556. X          if (d_status && !(use_hardstatus && HS) && len > 1)
  557. X            {
  558. X              curr->w_outlen = len - 1;
  559. X              bcopy(buf, curr->w_outbuf, curr->w_outlen);
  560. X              return;
  561. X            }
  562. X          break;
  563. X        case DCS:
  564. X          if (display)
  565. X            AddStr(curr->w_string);
  566. X          break;
  567. X        case AKA:
  568. X          if (curr->w_aka == curr->w_akabuf && !*curr->w_string)
  569. X            break;
  570. X          ChangeAKA(curr, curr->w_string, 20);
  571. X          if (!*curr->w_string)
  572. X            curr->w_autoaka = curr->w_y + 1;
  573. X          break;
  574. X        default:
  575. X          break;
  576. X        }
  577. X          break;
  578. X        default:
  579. X          curr->w_state = ASTR;
  580. X          SaveChar('\033');
  581. X          SaveChar(c);
  582. X        }
  583. X      break;
  584. X    case ASTR:
  585. X      switch (c)
  586. X        {
  587. X        case '\0':
  588. X          break;
  589. X        case '\033':
  590. X          curr->w_state = STRESC;
  591. X          break;
  592. X        default:
  593. X          SaveChar(c);
  594. X        }
  595. X      break;
  596. X    case ESC:
  597. X      switch (c)
  598. X        {
  599. X        case '[':
  600. X          curr->w_NumArgs = 0;
  601. X          curr->w_intermediate = 0;
  602. X          bzero((char *) curr->w_args, MAXARGS * sizeof(int));
  603. X          curr->w_state = CSI;
  604. X          break;
  605. X        case ']':
  606. X          StartString(OSC);
  607. X          break;
  608. X        case '_':
  609. X          StartString(APC);
  610. X          break;
  611. X        case 'P':
  612. X          StartString(DCS);
  613. X          break;
  614. X        case '^':
  615. X          StartString(PM);
  616. X          break;
  617. X        case '!':
  618. X          StartString(GM);
  619. X          break;
  620. X        case '"':
  621. X        case 'k':
  622. X          StartString(AKA);
  623. X          break;
  624. X        default:
  625. X          if (Special(c))
  626. X        break;
  627. X          debug1("not special. c = %x\n", c);
  628. X          if (c >= ' ' && c <= '/')
  629. X        curr->w_intermediate = curr->w_intermediate ? -1 : c;
  630. X          else if (c >= '0' && c <= '~')
  631. X        {
  632. X          DoESC(c, curr->w_intermediate);
  633. X          curr->w_state = LIT;
  634. X        }
  635. X          else
  636. X        {
  637. X          curr->w_state = LIT;
  638. X          goto tryagain;
  639. X        }
  640. X        }
  641. X      break;
  642. X    case CSI:
  643. X      switch (c)
  644. X        {
  645. X        case '0':
  646. X        case '1':
  647. X        case '2':
  648. X        case '3':
  649. X        case '4':
  650. X        case '5':
  651. X        case '6':
  652. X        case '7':
  653. X        case '8':
  654. X        case '9':
  655. X          if (curr->w_NumArgs < MAXARGS)
  656. X        {
  657. X          curr->w_args[curr->w_NumArgs] =
  658. X            10 * curr->w_args[curr->w_NumArgs] + c - '0';
  659. X        }
  660. X          break;
  661. X        case ';':
  662. X        case ':':
  663. X          curr->w_NumArgs++;
  664. X          break;
  665. X        default:
  666. X          if (Special(c))
  667. X        break;
  668. X          if (c >= '@' && c <= '~')
  669. X        {
  670. X          curr->w_NumArgs++;
  671. X          DoCSI(c, curr->w_intermediate);
  672. X          if (curr->w_state != PRIN)
  673. X            curr->w_state = LIT;
  674. X        }
  675. X          else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
  676. X        curr->w_intermediate = curr->w_intermediate ? -1 : c;
  677. X          else
  678. X        {
  679. X          curr->w_state = LIT;
  680. X          goto tryagain;
  681. X        }
  682. X        }
  683. X      break;
  684. X    case LIT:
  685. X    default:
  686. X      if (c < ' ')
  687. X        {
  688. X          if (c == '\033')
  689. X        {
  690. X          curr->w_intermediate = 0;
  691. X          curr->w_state = ESC;
  692. X          if (display && d_lp_missing && (CIC || IC || IM))
  693. X            UpdateLine(blank, null, null, d_bot, cols - 2, cols - 1);
  694. X          if (curr->w_autoaka < 0)
  695. X            curr->w_autoaka = 0;
  696. X        }
  697. X          else
  698. X        Special(c);
  699. X          break;
  700. X        }
  701. X      if (display)
  702. X        {
  703. X          if (d_attr != curr->w_Attr)
  704. X        SetAttr(curr->w_Attr);
  705. X          if (d_font != curr->w_Font)
  706. X        SetFont(curr->w_Font);
  707. X        }
  708. X      if (curr->w_x < cols - 1)
  709. X        {
  710. X          if (curr->w_insert)
  711. X        InsertAChar(c);
  712. X          else
  713. X        {
  714. X          if (display)
  715. X            PUTCHAR(c);
  716. X          SetChar(c);
  717. X          curr->w_x++;
  718. X        }
  719. X        }
  720. X      else if (curr->w_x == cols - 1)
  721. X        {
  722. X          if (display && curr->w_wrap && (CLP || !force_vt || COP))
  723. X        {
  724. X          RAW_PUTCHAR(c);    /* don't care about d_insert */
  725. X          SetChar(c);
  726. X          if (AM && !CLP)
  727. X            LineFeed(0);    /* terminal auto-wrapped */
  728. X          else
  729. X            curr->w_x++;
  730. X        }
  731. X          else
  732. X        {
  733. X          if (display)
  734. X            {
  735. X              if (CLP || curr->w_y != d_bot)
  736. X            {
  737. X              RAW_PUTCHAR(c);
  738. X              GotoPos(curr->w_x, curr->w_y);
  739. X            }
  740. X              else
  741. X            CheckLP(c);
  742. X            }
  743. X          SetChar(c);
  744. X          if (curr->w_wrap)
  745. X            curr->w_x++;
  746. X        }
  747. X        }
  748. X      else /* curr->w_x > cols - 1 */
  749. X        {
  750. X              SetChar(0);        /* we wrapped */
  751. X          if (curr->w_insert)
  752. X        {
  753. X          LineFeed(2);        /* cr+lf, handle LP */
  754. X          InsertAChar(c);
  755. X        }
  756. X          else
  757. X        {
  758. X          LineFeed(display == 0 || AM ? 0 : 2);
  759. X          if (display)
  760. X            PUTCHAR(c);
  761. X          SetChar(c);
  762. X          curr->w_x = 1;
  763. X        }
  764. X        }
  765. X      if (curr->w_ss)
  766. X        {
  767. X          SetFont(curr->w_Font = curr->w_charsets[curr->w_Charset]);
  768. X          curr->w_ss = 0;
  769. X        }
  770. X      break;
  771. X    }
  772. X    }
  773. X  while (--len);
  774. X  curr->w_outlen = 0;
  775. X  if (curr->w_state == PRIN)
  776. X    PrintFlush();
  777. X}
  778. X
  779. Xstatic int
  780. XSpecial(c)
  781. Xregister int c;
  782. X{
  783. X  switch (c)
  784. X    {
  785. X    case '\b':
  786. X      BackSpace();
  787. X      return 1;
  788. X    case '\r':
  789. X      Return();
  790. X      return 1;
  791. X    case '\n':
  792. X      if (curr->w_autoaka)
  793. X    FindAKA();
  794. X      LineFeed(1);
  795. X      return 1;
  796. X    case '\007':
  797. X      if (display == 0)
  798. X    curr->w_bell = BELL_ON;
  799. X      else
  800. X    {
  801. X      if (!visual_bell)
  802. X        PutStr(BL);
  803. X      else
  804. X        {
  805. X          if (!VB)
  806. X        curr->w_bell = BELL_VISUAL;
  807. X          else
  808. X        PutStr(VB);
  809. X        }
  810. X    }
  811. X      return 1;
  812. X    case '\t':
  813. X      ForwardTab();
  814. X      return 1;
  815. X    case '\017':        /* SI */
  816. X      MapCharset(G0);
  817. X      return 1;
  818. X    case '\016':        /* SO */
  819. X      MapCharset(G1);
  820. X      return 1;
  821. X    }
  822. X  return 0;
  823. X}
  824. X
  825. Xstatic void
  826. XDoESC(c, intermediate)
  827. Xint c, intermediate;
  828. X{
  829. X  debug2("DoESC: %x - inter = %x\n", c, intermediate);
  830. X  switch (intermediate)
  831. X    {
  832. X    case 0:
  833. X      switch (c)
  834. X    {
  835. X    case 'E':
  836. X      LineFeed(2);
  837. X      break;
  838. X    case 'D':
  839. X      LineFeed(1);
  840. X      break;
  841. X    case 'M':
  842. X      ReverseLineFeed();
  843. X      break;
  844. X    case 'H':
  845. X      curr->w_tabs[curr->w_x] = 1;
  846. X      break;
  847. X    case 'Z':        /* jph: Identify as VT100 */
  848. X      Report("\033[?%d;%dc", 1, 2);
  849. X      break;
  850. X    case '7':
  851. X      SaveCursor();
  852. X      break;
  853. X    case '8':
  854. X      RestoreCursor();
  855. X      break;
  856. X    case 'c':
  857. X      ClearScreen();
  858. X      ResetWindow(curr);
  859. X      SetAttrFont(0, ASCII);
  860. X      InsertMode(0);
  861. X      KeypadMode(0);
  862. X      CursorkeysMode(0);
  863. X      ChangeScrollRegion(0, rows - 1);
  864. X      break;
  865. X    case '=':
  866. X      KeypadMode(curr->w_keypad = 1);
  867. X#ifndef TIOCPKT
  868. X      NewAutoFlow(curr, 0);
  869. X#endif /* !TIOCPKT */
  870. X      break;
  871. X    case '>':
  872. X      KeypadMode(curr->w_keypad = 0);
  873. X#ifndef TIOCPKT
  874. X      NewAutoFlow(curr, 1);
  875. X#endif /* !TIOCPKT */
  876. X      break;
  877. X    case 'n':        /* LS2 */
  878. X      MapCharset(G2);
  879. X      break;
  880. X    case 'o':        /* LS3 */
  881. X      MapCharset(G3);
  882. X      break;
  883. X    case 'N':        /* SS2 */
  884. X      if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2])
  885. X        curr->w_Font = curr->w_charsets[curr->w_ss = G2];
  886. X      else
  887. X        curr->w_ss = 0;
  888. X      break;
  889. X    case 'O':        /* SS3 */
  890. X      if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3])
  891. X        curr->w_Font = curr->w_charsets[curr->w_ss = G3];
  892. X      else
  893. X        curr->w_ss = 0;
  894. X      break;
  895. X    }
  896. X      break;
  897. X    case '#':
  898. X      switch (c)
  899. X    {
  900. X    case '8':
  901. X      FillWithEs();
  902. X      break;
  903. X    }
  904. X      break;
  905. X    case '(':
  906. X      DesignateCharset(c, G0);
  907. X      break;
  908. X    case ')':
  909. X      DesignateCharset(c, G1);
  910. X      break;
  911. X    case '*':
  912. X      DesignateCharset(c, G2);
  913. X      break;
  914. X    case '+':
  915. X      DesignateCharset(c, G3);
  916. X      break;
  917. X    }
  918. X}
  919. X
  920. Xstatic void
  921. XDoCSI(c, intermediate)
  922. Xint c, intermediate;
  923. X{
  924. X  register int i, a1 = curr->w_args[0], a2 = curr->w_args[1];
  925. X
  926. X  if (curr->w_NumArgs > MAXARGS)
  927. X    curr->w_NumArgs = MAXARGS;
  928. X  switch (intermediate)
  929. X    {
  930. X    case 0:
  931. X      switch (c)
  932. X    {
  933. X    case 'H':
  934. X    case 'f':
  935. X      if (a1 < 1)
  936. X        a1 = 1;
  937. X      if (curr->w_origin)
  938. X        a1 += curr->w_top;
  939. X      if (a1 > rows)
  940. X        a1 = rows;
  941. X      if (a2 < 1)
  942. X        a2 = 1;
  943. X      if (a2 > cols)
  944. X        a2 = cols;
  945. X      GotoPos(--a2, --a1);
  946. X      curr->w_x = a2;
  947. X      curr->w_y = a1;
  948. X      if (curr->w_autoaka)
  949. X        curr->w_autoaka = a1 + 1;
  950. X      break;
  951. X    case 'J':
  952. X      if (a1 < 0 || a1 > 2)
  953. X        a1 = 0;
  954. X      switch (a1)
  955. X        {
  956. X        case 0:
  957. X          ClearToEOS();
  958. X          break;
  959. X        case 1:
  960. X          ClearFromBOS();
  961. X          break;
  962. X        case 2:
  963. X          ClearScreen();
  964. X          GotoPos(curr->w_x, curr->w_y);
  965. X          break;
  966. X        }
  967. X      break;
  968. X    case 'K':
  969. X      if (a1 < 0 || a1 > 2)
  970. X        a1 %= 3;
  971. X      switch (a1)
  972. X        {
  973. X        case 0:
  974. X          ClearToEOL();
  975. X          break;
  976. X        case 1:
  977. X          ClearFromBOL();
  978. X          break;
  979. X        case 2:
  980. X          ClearFullLine();
  981. X          break;
  982. X        }
  983. X      break;
  984. X    case 'A':
  985. X      CursorUp(a1 ? a1 : 1);
  986. X      break;
  987. X    case 'B':
  988. X      CursorDown(a1 ? a1 : 1);
  989. X      break;
  990. X    case 'C':
  991. X      CursorRight(a1 ? a1 : 1);
  992. X      break;
  993. X    case 'D':
  994. X      CursorLeft(a1 ? a1 : 1);
  995. X      break;
  996. X    case 'm':
  997. X      SelectRendition();
  998. X      break;
  999. X    case 'g':
  1000. X      if (a1 == 0)
  1001. X        curr->w_tabs[curr->w_x] = 0;
  1002. X      else if (a1 == 3)
  1003. X        bzero(curr->w_tabs, cols);
  1004. X      break;
  1005. X    case 'r':
  1006. X      if (!a1)
  1007. X        a1 = 1;
  1008. X      if (!a2)
  1009. X        a2 = rows;
  1010. X      if (a1 < 1 || a2 > rows || a1 >= a2)
  1011. X        break;
  1012. X      curr->w_top = a1 - 1;
  1013. X      curr->w_bot = a2 - 1;
  1014. X      ChangeScrollRegion(curr->w_top, curr->w_bot);
  1015. X      if (curr->w_origin)
  1016. X        {
  1017. X          GotoPos(0, curr->w_top);
  1018. X          curr->w_y = curr->w_top;
  1019. X          curr->w_x = 0;
  1020. X        }
  1021. X      else
  1022. X        {
  1023. X          GotoPos(0, 0);
  1024. X          curr->w_y = curr->w_x = 0;
  1025. X        }
  1026. X      break;
  1027. X    case 's':
  1028. X      SaveCursor();
  1029. X      break;
  1030. X    case 't':
  1031. X      if (a1 != 8)
  1032. X        break;
  1033. X      a1 = curr->w_args[2];
  1034. X      if (a1 < 1)
  1035. X        a1 = curr->w_width;
  1036. X      if (a2 < 1)
  1037. X        a2 = curr->w_height;
  1038. X      if (display && CWS == NULL)
  1039. X        {
  1040. X          a2 = curr->w_height;
  1041. X          if (CZ0 == NULL || (a1 != Z0width && a1 != Z1width))
  1042. X            a1 = curr->w_width;
  1043. X         }
  1044. X      if (a1 == curr->w_width && a2 == curr->w_height)
  1045. X        break;
  1046. X          ChangeWindowSize(curr, a1, a2);
  1047. X      SetCurr(curr);
  1048. X      if (display)
  1049. X        Activate(0);
  1050. X      break;
  1051. X    case 'u':
  1052. X      RestoreCursor();
  1053. X      break;
  1054. X    case 'I':
  1055. X      if (!a1)
  1056. X        a1 = 1;
  1057. X      while (a1--)
  1058. X        ForwardTab();
  1059. X      break;
  1060. X    case 'Z':
  1061. X      if (!a1)
  1062. X        a1 = 1;
  1063. X      while (a1--)
  1064. X        BackwardTab();
  1065. X      break;
  1066. X    case 'L':
  1067. X      InsertLine(a1 ? a1 : 1);
  1068. X      break;
  1069. X    case 'M':
  1070. X      DeleteLine(a1 ? a1 : 1);
  1071. X      break;
  1072. X    case 'P':
  1073. X      DeleteChar(a1 ? a1 : 1);
  1074. X      break;
  1075. X    case '@':
  1076. X      InsertChar(a1 ? a1 : 1);
  1077. X      break;
  1078. X    case 'h':
  1079. X      ASetMode(1);
  1080. X      break;
  1081. X    case 'l':
  1082. X      ASetMode(0);
  1083. X      break;
  1084. X    case 'i':
  1085. X      if (display && PO && a1 == 5)
  1086. X        {
  1087. X          curr->w_stringp = curr->w_string;
  1088. X          curr->w_state = PRIN;
  1089. X        }
  1090. X      break;
  1091. X    case 'n':
  1092. X      if (a1 == 6)        /* Report cursor position */
  1093. X        Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1);
  1094. X      break;
  1095. X    case 'c':        /* Identify as VT100 */
  1096. X      Report("\033[?%d;%dc", 1, 2);
  1097. X      break;
  1098. X    }
  1099. X      break;
  1100. X    case '?':
  1101. X      debug2("\\E[?%d%c\n",a1,c);
  1102. X      if (c != 'h' && c != 'l')
  1103. X    break;
  1104. X      i = (c == 'h');
  1105. X      switch (a1)
  1106. X    {
  1107. X    case 1:
  1108. X      CursorkeysMode(curr->w_cursorkeys = i);
  1109. X#ifndef TIOCPKT
  1110. X      NewAutoFlow(curr, !i);
  1111. X#endif /* !TIOCPKT */
  1112. X      break;
  1113. X    case 3:
  1114. X      i = (i ? Z0width : Z1width);
  1115. X      if (curr->w_width != i && (display == 0 || (CZ0 || CWS)))
  1116. X        {
  1117. X              ChangeWindowSize(curr, i, curr->w_height);
  1118. X          SetCurr(curr);    /* update rows/cols */
  1119. X          if (display)
  1120. X        Activate(0);
  1121. X        }
  1122. X      break;
  1123. X    case 5:
  1124. X      if (i)
  1125. X        curr->w_vbwait = 1;
  1126. X      else
  1127. X        {
  1128. X          if (display && curr->w_vbwait)
  1129. X        PutStr(VB);
  1130. X          curr->w_vbwait = 0;
  1131. X        }
  1132. X      break;
  1133. X    case 6:
  1134. X      if ((curr->w_origin = i) != 0)
  1135. X        {
  1136. X          curr->w_y = curr->w_top;
  1137. X          curr->w_x = 0;
  1138. X        }
  1139. X      else
  1140. X        curr->w_y = curr->w_x = 0;
  1141. X      if (display)
  1142. X        GotoPos(curr->w_x, curr->w_y);
  1143. X      break;
  1144. X    case 7:
  1145. X      curr->w_wrap = i;
  1146. X      break;
  1147. X    case 35:
  1148. X      debug1("Cursor %svisible\n", i ? "in" : "");
  1149. X      curr->w_cursor_invisible = i;
  1150. X      break;
  1151. X    }
  1152. X      break;
  1153. X    }
  1154. X}
  1155. X
  1156. X
  1157. Xstatic void
  1158. XSetChar(c)
  1159. Xregister int c;
  1160. X{
  1161. X  register struct win *p = curr;
  1162. X
  1163. X  p->w_image[p->w_y][p->w_x] = c;
  1164. X  p->w_attr[p->w_y][p->w_x] = p->w_Attr;
  1165. X  p->w_font[p->w_y][p->w_x] = p->w_Font;
  1166. X}
  1167. X
  1168. Xstatic void
  1169. XStartString(type)
  1170. Xenum string_t type;
  1171. X{
  1172. X  curr->w_StringType = type;
  1173. X  curr->w_stringp = curr->w_string;
  1174. X  curr->w_state = ASTR;
  1175. X}
  1176. X
  1177. Xstatic void
  1178. XSaveChar(c)
  1179. Xint c;
  1180. X{
  1181. X  if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
  1182. X    curr->w_state = LIT;
  1183. X  else
  1184. X    *(curr->w_stringp)++ = c;
  1185. X}
  1186. X
  1187. Xstatic void
  1188. XPrintChar(c)
  1189. Xint c;
  1190. X{
  1191. X  if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
  1192. X    PrintFlush();
  1193. X  *(curr->w_stringp)++ = c;
  1194. X}
  1195. X
  1196. Xstatic void
  1197. XPrintFlush()
  1198. X{
  1199. X  if (display && curr->w_stringp > curr->w_string)
  1200. X    {
  1201. X      PutStr(PO);
  1202. X      AddStrn(curr->w_string, curr->w_stringp - curr->w_string);
  1203. X      PutStr(PF);
  1204. X      Flush();
  1205. X    }
  1206. X  curr->w_stringp = curr->w_string;
  1207. X}
  1208. X
  1209. X
  1210. Xvoid
  1211. XNewAutoFlow(win, on)
  1212. Xstruct win *win;
  1213. Xint on;
  1214. X{
  1215. X  debug1("NewAutoFlow: %d\n", on);
  1216. X  SetCurr(win);
  1217. X  if (win->w_flow & FLOW_AUTOFLAG)
  1218. X    win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on;
  1219. X  else
  1220. X    win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on;
  1221. X  if (display)
  1222. X    SetFlow(win->w_flow & FLOW_NOW);
  1223. X}
  1224. X
  1225. Xstatic void
  1226. XDesignateCharset(c, n)
  1227. Xint c, n;
  1228. X{
  1229. X  curr->w_ss = 0;
  1230. X  if (c == 'B')
  1231. X    c = ASCII;
  1232. X  if (curr->w_charsets[n] != c)
  1233. X    {
  1234. X      curr->w_charsets[n] = c;
  1235. X      if (curr->w_Charset == n)
  1236. X    SetFont(curr->w_Font = c);
  1237. X    }
  1238. X}
  1239. X
  1240. Xstatic void
  1241. XMapCharset(n)
  1242. Xint n;
  1243. X{
  1244. X  curr->w_ss = 0;
  1245. X  if (curr->w_Charset != n)
  1246. X    {
  1247. X      curr->w_Charset = n;
  1248. X      SetFont(curr->w_Font = curr->w_charsets[n]);
  1249. X    }
  1250. X}
  1251. X
  1252. Xstatic void
  1253. XSaveCursor()
  1254. X{
  1255. X  curr->w_saved = 1;
  1256. X  curr->w_Saved_x = curr->w_x;
  1257. X  curr->w_Saved_y = curr->w_y;
  1258. X  curr->w_SavedAttr = curr->w_Attr;
  1259. X  curr->w_SavedCharset = curr->w_Charset;
  1260. X  bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets,
  1261. X    4 * sizeof(int));
  1262. X}
  1263. X
  1264. Xstatic void
  1265. XRestoreCursor()
  1266. X{
  1267. X  if (curr->w_saved)
  1268. X    {
  1269. X      GotoPos(curr->w_Saved_x, curr->w_Saved_y);
  1270. X      curr->w_x = curr->w_Saved_x;
  1271. X      curr->w_y = curr->w_Saved_y;
  1272. X      curr->w_Attr = curr->w_SavedAttr;
  1273. X      SetAttr(curr->w_Attr);
  1274. X      bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets,
  1275. X        4 * sizeof(int));
  1276. X      curr->w_Charset = curr->w_SavedCharset;
  1277. X      curr->w_ss = 0;
  1278. X      SetFont(curr->w_Font = curr->w_charsets[curr->w_Charset]);
  1279. X    }
  1280. X}
  1281. X
  1282. Xstatic void
  1283. XBackSpace()
  1284. X{
  1285. X  if (curr->w_x > 0)
  1286. X    {
  1287. X      curr->w_x--;
  1288. X    }
  1289. X  else if (curr->w_wrap && curr->w_y > 0)
  1290. X    {
  1291. X      curr->w_x = cols - 1;
  1292. X      curr->w_y--;
  1293. X    }
  1294. X  if (display)
  1295. X    GotoPos(curr->w_x, curr->w_y);
  1296. X}
  1297. X
  1298. Xstatic void
  1299. XReturn()
  1300. X{
  1301. X  if (curr->w_x > 0)
  1302. X    {
  1303. X      curr->w_x = 0;
  1304. X      if (display)
  1305. X        GotoPos(curr->w_x, curr->w_y);
  1306. X    }
  1307. X}
  1308. X
  1309. Xstatic void
  1310. XLineFeed(out_mode)
  1311. Xint out_mode;
  1312. X{
  1313. X  /* out_mode: 0=cr+lf no-output, 1=lf, 2=cr+lf */
  1314. X  if (out_mode != 1)
  1315. X    curr->w_x = 0;
  1316. X  if (curr->w_y != curr->w_bot)        /* Don't scroll */
  1317. X    {
  1318. X      if (curr->w_y < rows-1)
  1319. X    curr->w_y++;
  1320. X      if (out_mode && display)
  1321. X    GotoPos(curr->w_x, curr->w_y);
  1322. X      return;
  1323. X    }
  1324. X  ScrollUpMap(1);
  1325. X  if (curr->w_autoaka > 1)
  1326. X    curr->w_autoaka--;
  1327. X  if (out_mode && display)
  1328. X    {
  1329. X      ScrollRegion(curr->w_top, curr->w_bot, 1);
  1330. X      GotoPos(curr->w_x, curr->w_y);
  1331. X    }
  1332. X}
  1333. X
  1334. Xstatic void
  1335. XReverseLineFeed()
  1336. X{
  1337. X  if (curr->w_y == curr->w_top)
  1338. X    {
  1339. X      ScrollDownMap(1);
  1340. X      if (!display)
  1341. X    return;
  1342. X      ScrollRegion(curr->w_top, curr->w_bot, -1);
  1343. X      GotoPos(curr->w_x, curr->w_y);
  1344. X    }
  1345. X  else if (curr->w_y > 0)
  1346. X    CursorUp(1);
  1347. X}
  1348. X
  1349. Xstatic void
  1350. XInsertAChar(c)
  1351. Xint c;
  1352. X{
  1353. X  register int y = curr->w_y, x = curr->w_x;
  1354. X
  1355. X  if (x == cols)
  1356. X    x--;
  1357. X  bcopy(curr->w_image[y], OldImage, cols);
  1358. X  bcopy(curr->w_attr[y], OldAttr, cols);
  1359. X  bcopy(curr->w_font[y], OldFont, cols);
  1360. X  bcopy(curr->w_image[y] + x, curr->w_image[y] + x + 1, cols - x - 1);
  1361. X  bcopy(curr->w_attr[y] + x, curr->w_attr[y] + x + 1, cols - x - 1);
  1362. X  bcopy(curr->w_font[y] + x, curr->w_font[y] + x + 1, cols - x - 1);
  1363. X  SetChar(c);
  1364. X  curr->w_x = x + 1;
  1365. X  if (!display)
  1366. X    return;
  1367. X  if (CIC || IC || IM)
  1368. X    {
  1369. X      InsertMode(curr->w_insert);
  1370. X      INSERTCHAR(c);
  1371. X      if (y == d_bot)
  1372. X    d_lp_missing = 0;
  1373. X    }
  1374. X  else
  1375. X    UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  1376. X}
  1377. X
  1378. Xstatic void
  1379. XInsertChar(n)
  1380. Xint n;
  1381. X{
  1382. X  register int i, y = curr->w_y, x = curr->w_x;
  1383. X
  1384. X  if (n <= 0)
  1385. X    return;
  1386. X  /* Hack to be compatible with the old screen versions */
  1387. X  if (curr->w_insert)
  1388. X    return;
  1389. X  if (x == cols)
  1390. X    x--;
  1391. X  bcopy(curr->w_image[y], OldImage, cols);
  1392. X  bcopy(curr->w_attr[y], OldAttr, cols);
  1393. X  bcopy(curr->w_font[y], OldFont, cols);
  1394. X  if (n > cols - x)
  1395. X    n = cols - x;
  1396. X  bcopy(curr->w_image[y] + x, curr->w_image[y] + x + n, cols - x - n);
  1397. X  bcopy(curr->w_attr[y] + x, curr->w_attr[y] + x + n, cols - x - n);
  1398. X  bcopy(curr->w_font[y] + x, curr->w_font[y] + x + n, cols - x - n);
  1399. X  ClearInLine(y, x, x + n - 1);
  1400. X  if (!display)
  1401. X    return;
  1402. X  if (IC || CIC || IM)
  1403. X    {
  1404. X      if (y == d_bot)
  1405. X    d_lp_missing = 0;
  1406. X      if (!d_insert)
  1407. X    {
  1408. X      if (n == 1 && IC)
  1409. X        {
  1410. X          PutStr(IC);
  1411. X          return;
  1412. X            }
  1413. X      if (CIC)
  1414. X        {
  1415. X          CPutStr(CIC, n);
  1416. X          return;
  1417. X            }
  1418. X    }
  1419. X      InsertMode(1);
  1420. X      for (i = n; i--; )
  1421. X    INSERTCHAR(' ');
  1422. X      GotoPos(x, y);
  1423. X    }
  1424. X  else
  1425. X    UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  1426. X}
  1427. X
  1428. Xstatic void
  1429. XDeleteChar(n)
  1430. Xint n;
  1431. X{
  1432. X  register int i, y = curr->w_y, x = curr->w_x;
  1433. X
  1434. X  if (x == cols)
  1435. X    x--;
  1436. X  bcopy(curr->w_image[y], OldImage, cols);
  1437. X  bcopy(curr->w_attr[y], OldAttr, cols);
  1438. X  bcopy(curr->w_font[y], OldFont, cols);
  1439. X  if (n > cols - x)
  1440. X    n = cols - x;
  1441. X  bcopy(curr->w_image[y] + x + n, curr->w_image[y] + x, cols - x - n);
  1442. X  bcopy(curr->w_attr[y] + x + n, curr->w_attr[y] + x, cols - x - n);
  1443. X  bcopy(curr->w_font[y] + x + n, curr->w_font[y] + x, cols - x - n);
  1444. X  ClearInLine(y, cols - n, cols - 1);
  1445. X  if (!display)
  1446. X    return;
  1447. X  if (CDC && !(n == 1 && DC))
  1448. X    {
  1449. X      CPutStr(CDC, n);
  1450. X      if (d_lp_missing && y == d_bot)
  1451. X    {
  1452. X      FixLP(cols - 1 - n, y);
  1453. X          GotoPos(x, y);
  1454. X    }
  1455. X    }
  1456. X  else if (DC)
  1457. X    {
  1458. X      for (i = n; i; i--)
  1459. X    PutStr(DC);
  1460. X      if (d_lp_missing && y == d_bot)
  1461. X    {
  1462. X      FixLP(cols - 1 - n, y);
  1463. X          GotoPos(x, y);
  1464. X    }
  1465. X    }
  1466. X  else
  1467. X    UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  1468. X}
  1469. X
  1470. Xstatic void
  1471. XDeleteLine(n)
  1472. Xint n;
  1473. X{
  1474. X  register int old = curr->w_top;
  1475. X  
  1476. X  if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
  1477. X    return;
  1478. X  if (n > curr->w_bot - curr->w_y + 1)
  1479. X    n = curr->w_bot - curr->w_y + 1;
  1480. X  curr->w_top = curr->w_y;
  1481. X  ScrollUpMap(n);
  1482. X  curr->w_top = old;
  1483. X  if (!display)
  1484. X    return;
  1485. X  ScrollRegion(curr->w_y, curr->w_bot, n);
  1486. X  GotoPos(curr->w_x, curr->w_y);
  1487. X}
  1488. X
  1489. Xstatic void
  1490. XInsertLine(n)
  1491. Xint n;
  1492. X{
  1493. X  register int old = curr->w_top;
  1494. X
  1495. X  if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
  1496. X    return;
  1497. X  if (n > curr->w_bot - curr->w_y + 1)
  1498. X    n = curr->w_bot - curr->w_y + 1;
  1499. X  curr->w_top = curr->w_y;
  1500. X  ScrollDownMap(n);
  1501. X  curr->w_top = old;
  1502. X  if (!display)
  1503. X    return;
  1504. X  ScrollRegion(curr->w_y, curr->w_bot, -n);
  1505. X  GotoPos(curr->w_x, curr->w_y);
  1506. X}
  1507. X
  1508. X
  1509. Xstatic void
  1510. XScrollUpMap(n)
  1511. Xint n;
  1512. X{
  1513. X  char tmp[256 * sizeof(char *)];
  1514. X  register int i, cnt1, cnt2;
  1515. X  register char **ppi, **ppa, **ppf;
  1516. X#ifdef COPY_PASTE
  1517. X  register int ii;
  1518. X#endif
  1519. X
  1520. X  i = curr->w_top + n;
  1521. X  cnt1 = n * sizeof(char *);
  1522. X  cnt2 = (curr->w_bot - i + 1) * sizeof(char *);
  1523. X  ppi = curr->w_image + i;
  1524. X  ppa = curr->w_attr + i;
  1525. X  ppf = curr->w_font + i;
  1526. X#ifdef COPY_PASTE
  1527. X  for(ii = curr->w_top; ii < i; ii++)
  1528. X     AddLineToHist(curr, &curr->w_image[ii], &curr->w_attr[ii], &curr->w_font[ii]);
  1529. X#endif
  1530. X  for (i = n; i; --i)
  1531. X    {
  1532. X      bclear(*--ppi, cols + 1);
  1533. X      bzero(*--ppa, cols + 1);
  1534. X      bzero(*--ppf, cols + 1);
  1535. X    }
  1536. X  Scroll((char *) ppi, cnt1, cnt2, tmp);
  1537. X  Scroll((char *) ppa, cnt1, cnt2, tmp);
  1538. X  Scroll((char *) ppf, cnt1, cnt2, tmp);
  1539. X}
  1540. X
  1541. Xstatic void
  1542. XScrollDownMap(n)
  1543. Xint n;
  1544. X{
  1545. X  char tmp[256 * sizeof(char *)];
  1546. X  register int i, cnt1, cnt2;
  1547. X  register char **ppi, **ppa, **ppf;
  1548. X
  1549. X  i = curr->w_top;
  1550. X  cnt1 = (curr->w_bot - i - n + 1) * sizeof(char *);
  1551. X  cnt2 = n * sizeof(char *);
  1552. X  Scroll((char *) (ppi = curr->w_image + i), cnt1, cnt2, tmp);
  1553. X  Scroll((char *) (ppa = curr->w_attr + i), cnt1, cnt2, tmp);
  1554. X  Scroll((char *) (ppf = curr->w_font + i), cnt1, cnt2, tmp);
  1555. X  for (i = n; i; --i)
  1556. X    {
  1557. X      bclear(*ppi++, cols + 1);
  1558. X      bzero(*ppa++, cols + 1);
  1559. X      bzero(*ppf++, cols + 1);
  1560. X    }
  1561. X}
  1562. X
  1563. Xstatic void
  1564. XScroll(cp, cnt1, cnt2, tmp)
  1565. Xchar *cp, *tmp;
  1566. Xint cnt1, cnt2;
  1567. X{
  1568. X  if (!cnt1 || !cnt2)
  1569. X    return;
  1570. X  if (cnt1 <= cnt2)
  1571. X    {
  1572. X      bcopy(cp, tmp, cnt1);
  1573. X      bcopy(cp + cnt1, cp, cnt2);
  1574. X      bcopy(tmp, cp + cnt2, cnt1);
  1575. X    }
  1576. X  else
  1577. X    {
  1578. X      bcopy(cp + cnt1, tmp, cnt2);
  1579. X      bcopy(cp, cp + cnt2, cnt1);
  1580. X      bcopy(tmp, cp, cnt2);
  1581. X    }
  1582. X}
  1583. X
  1584. Xstatic void
  1585. XForwardTab()
  1586. X{
  1587. X  register int x = curr->w_x;
  1588. X
  1589. X  if (x == cols)
  1590. X    {
  1591. X      LineFeed(2);
  1592. X      x = 0;
  1593. X    }
  1594. X  if (curr->w_tabs[x] && x < cols - 1)
  1595. X    x++;
  1596. X  while (x < cols - 1 && !curr->w_tabs[x])
  1597. X    x++;
  1598. X  GotoPos(x, curr->w_y);
  1599. X  curr->w_x = x;
  1600. X}
  1601. X
  1602. Xstatic void
  1603. XBackwardTab()
  1604. X{
  1605. X  register int x = curr->w_x;
  1606. X
  1607. X  if (curr->w_tabs[x] && x > 0)
  1608. X    x--;
  1609. X  while (x > 0 && !curr->w_tabs[x])
  1610. X    x--;
  1611. X  GotoPos(x, curr->w_y);
  1612. X  curr->w_x = x;
  1613. X}
  1614. X
  1615. Xstatic void
  1616. XClearScreen()
  1617. X{
  1618. X  register int i;
  1619. X  register char **ppi = curr->w_image, **ppa = curr->w_attr, **ppf = curr->w_font;
  1620. X
  1621. X  for (i = 0; i < rows; ++i)
  1622. X    {
  1623. X#ifdef COPY_PASTE
  1624. X      AddLineToHist(curr, ppi, ppa, ppf);
  1625. X#endif
  1626. X      bclear(*ppi++, cols + 1);
  1627. X      bzero(*ppa++, cols + 1);
  1628. X      bzero(*ppf++, cols + 1);
  1629. X    }
  1630. X  if (display)
  1631. X    ClearDisplay();
  1632. X}
  1633. X
  1634. Xstatic void
  1635. XClearFromBOS()
  1636. X{
  1637. X  register int n, y = curr->w_y, x = curr->w_x;
  1638. X
  1639. X  if (display)
  1640. X    Clear(0, 0, x, y);
  1641. X  for (n = 0; n < y; ++n)
  1642. X    ClearInLine(n, 0, cols - 1);
  1643. X  ClearInLine(y, 0, x);
  1644. X  RestorePosAttrFont();
  1645. X}
  1646. X
  1647. Xstatic void
  1648. XClearToEOS()
  1649. X{
  1650. X  register int n, y = curr->w_y, x = curr->w_x;
  1651. X
  1652. X  if (x == 0 && y == 0)
  1653. X    {
  1654. X      ClearScreen();
  1655. X      return;
  1656. X    }
  1657. X  if (display)
  1658. X    Clear(x, y, d_width - 1, d_height - 1);
  1659. X  ClearInLine(y, x, cols - 1);
  1660. X  for (n = y + 1; n < rows; n++)
  1661. X    ClearInLine(n, 0, cols - 1);
  1662. X  RestorePosAttrFont();
  1663. X}
  1664. X
  1665. Xstatic void
  1666. XClearFullLine()
  1667. X{
  1668. X  register int y = curr->w_y;
  1669. X
  1670. X  if (display)
  1671. X    Clear(0, y, d_width - 1, y);
  1672. X  ClearInLine(y, 0, cols - 1);
  1673. X  RestorePosAttrFont();
  1674. X}
  1675. X
  1676. Xstatic void
  1677. XClearToEOL()
  1678. X{
  1679. X  register int y = curr->w_y, x = curr->w_x;
  1680. X
  1681. X  if (display)
  1682. X    Clear(x, y, d_width - 1, y);
  1683. X  ClearInLine(y, x, cols - 1);
  1684. X  RestorePosAttrFont();
  1685. X}
  1686. X
  1687. Xstatic void
  1688. XClearFromBOL()
  1689. X{
  1690. X  register int y = curr->w_y, x = curr->w_x;
  1691. X
  1692. X  if (display)
  1693. X    Clear(0, y, x, y);
  1694. X  ClearInLine(y, 0, x);
  1695. X  RestorePosAttrFont();
  1696. X}
  1697. X
  1698. Xstatic void
  1699. XClearInLine(y, x1, x2)
  1700. Xint y, x1, x2;
  1701. X{
  1702. X  register int n;
  1703. X
  1704. X  if (x1 == cols)
  1705. X    x1--;
  1706. X  if (x2 == cols - 1)
  1707. X    x2++;
  1708. X  if ((n = x2 - x1 + 1) != 0)
  1709. X    {
  1710. X      bclear(curr->w_image[y] + x1, n);
  1711. X      bzero(curr->w_attr[y] + x1, n);
  1712. X      bzero(curr->w_font[y] + x1, n);
  1713. X    }
  1714. X}
  1715. X
  1716. Xstatic void
  1717. XCursorRight(n)
  1718. Xregister int n;
  1719. X{
  1720. X  register int x = curr->w_x;
  1721. X
  1722. X  if (x == cols)
  1723. X    {
  1724. X      LineFeed(2);
  1725. X      x = 0;
  1726. X    }
  1727. X  if ((curr->w_x += n) >= cols)
  1728. X    curr->w_x = cols - 1;
  1729. X  GotoPos(curr->w_x, curr->w_y);
  1730. X}
  1731. X
  1732. Xstatic void
  1733. XCursorUp(n)
  1734. Xregister int n;
  1735. X{
  1736. X  if (curr->w_y < curr->w_top)        /* if above scrolling rgn, */
  1737. X    {
  1738. X      if ((curr->w_y -= n) < 0)        /* ignore its limits      */
  1739. X         curr->w_y = 0;
  1740. X    }
  1741. X  else
  1742. X    if ((curr->w_y -= n) < curr->w_top)
  1743. X      curr->w_y = curr->w_top;
  1744. X  GotoPos(curr->w_x, curr->w_y);
  1745. X}
  1746. X
  1747. Xstatic void
  1748. XCursorDown(n)
  1749. Xregister int n;
  1750. X{
  1751. X  if (curr->w_y > curr->w_bot)        /* if below scrolling rgn, */
  1752. X    {
  1753. X      if ((curr->w_y += n) > rows - 1)    /* ignore its limits      */
  1754. X        curr->w_y = rows - 1;
  1755. X    }
  1756. X  else
  1757. X    if ((curr->w_y += n) > curr->w_bot)
  1758. X      curr->w_y = curr->w_bot;
  1759. X  GotoPos(curr->w_x, curr->w_y);
  1760. X}
  1761. X
  1762. Xstatic void
  1763. XCursorLeft(n)
  1764. Xregister int n;
  1765. X{
  1766. X  if ((curr->w_x -= n) < 0)
  1767. X    curr->w_x = 0;
  1768. X  GotoPos(curr->w_x, curr->w_y);
  1769. X}
  1770. X
  1771. Xstatic void
  1772. XASetMode(on)
  1773. Xint on;
  1774. X{
  1775. X  register int i;
  1776. X
  1777. X  for (i = 0; i < curr->w_NumArgs; ++i)
  1778. X    {
  1779. X      switch (curr->w_args[i])
  1780. X    {
  1781. X    case 4:
  1782. X      curr->w_insert = on;
  1783. X      InsertMode(on);
  1784. X      break;
  1785. X    }
  1786. X    }
  1787. X}
  1788. X
  1789. Xstatic char rendlist[] =
  1790. X{
  1791. X  (1 << NATTR), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0,
  1792. X  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1793. X  0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV
  1794. X};
  1795. X
  1796. Xstatic void
  1797. XSelectRendition()
  1798. X{
  1799. X  register int j, i = 0, a = curr->w_Attr;
  1800. X
  1801. X  do
  1802. X    {
  1803. X      j = curr->w_args[i];
  1804. X      if (j < 0 || j >= (sizeof(rendlist)/sizeof(*rendlist)))
  1805. X    continue;
  1806. X      j = rendlist[j];
  1807. X      if (j & (1 << NATTR))
  1808. X        a &= j;
  1809. X      else
  1810. X        a |= j;
  1811. X    }
  1812. X  while (++i < curr->w_NumArgs);
  1813. X  SetAttr(curr->w_Attr = a);
  1814. X}
  1815. X
  1816. Xstatic void
  1817. XFillWithEs()
  1818. X{
  1819. X  register int i;
  1820. X  register char *p, *ep;
  1821. X
  1822. X  curr->w_y = curr->w_x = 0;
  1823. X  for (i = 0; i < rows; ++i)
  1824. X    {
  1825. X      bzero(curr->w_attr[i], cols);
  1826. X      bzero(curr->w_font[i], cols);
  1827. X      p = curr->w_image[i];
  1828. X      ep = p + cols;
  1829. X      while (p < ep)
  1830. X    *p++ = 'E';
  1831. X    }
  1832. X  if (display)
  1833. X    Redisplay(0);
  1834. X}
  1835. X
  1836. X
  1837. Xstatic void
  1838. XUpdateLine(os, oa, of, y, from, to)
  1839. Xint from, to, y;
  1840. Xchar *os, *oa, *of;
  1841. X{
  1842. X  ASSERT(display);
  1843. X  DisplayLine(os, oa, of, curr->w_image[y], curr->w_attr[y],
  1844. X          curr->w_font[y], y, from, to);
  1845. X  RestorePosAttrFont();
  1846. X}
  1847. X
  1848. Xvoid
  1849. XCheckLP(n_ch)
  1850. Xchar n_ch;
  1851. X{
  1852. X  register int y, x;
  1853. X  register char n_at, n_fo, o_ch, o_at, o_fo;
  1854. X
  1855. X  ASSERT(display);
  1856. X  x = cols - 1;
  1857. X  y = d_bot;
  1858. X  o_ch = curr->w_image[y][x];
  1859. X  o_at = curr->w_attr[y][x];
  1860. X  o_fo = curr->w_font[y][x];
  1861. X
  1862. X  n_at = curr->w_Attr;
  1863. X  n_fo = curr->w_Font;
  1864. X
  1865. X  d_lp_image = n_ch;
  1866. X  d_lp_attr = n_at;
  1867. X  d_lp_font = n_fo;
  1868. X  d_lp_missing = 0;
  1869. X  if (n_ch == o_ch && n_at == o_at && n_fo == o_fo)
  1870. X    return;
  1871. X  if (n_ch != ' ' || n_at || n_fo)
  1872. X    d_lp_missing = 1;
  1873. X  if (o_ch != ' ' || o_at || o_fo)
  1874. X    {
  1875. X      if (DC)
  1876. X    PutStr(DC);
  1877. X      else if (CDC)
  1878. X    CPutStr(CDC, 1);
  1879. X      else if (CE)
  1880. X    PutStr(CE);
  1881. X      else
  1882. X    d_lp_missing = 1;
  1883. X    }
  1884. X}
  1885. X
  1886. X/*
  1887. X *  Ugly autoaka hack support:
  1888. X *    ChangeAKA() sets a new aka
  1889. X *    FindAKA() searches for an autoaka match
  1890. X */
  1891. X
  1892. Xvoid
  1893. XChangeAKA(p, s, l)
  1894. Xstruct win *p;
  1895. Xchar *s;
  1896. Xint l;
  1897. X{
  1898. X  if (l > 20)
  1899. X    l = 20;
  1900. X  strncpy(p->w_akachange, s, l);
  1901. X  p->w_akachange[l] = 0;
  1902. X  p->w_aka = p->w_akachange;
  1903. X  if (p->w_akachange != p->w_akabuf)
  1904. X    if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':')
  1905. X      p->w_aka = p->w_akabuf + strlen(p->w_akabuf) + 1;
  1906. X}
  1907. X
  1908. Xstatic void
  1909. XFindAKA()
  1910. X{
  1911. X  register char *cp, *line;
  1912. X  register struct win *wp = curr;
  1913. X  register int len = strlen(wp->w_akabuf);
  1914. X  int y;
  1915. X
  1916. X  y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y;
  1917. X  cols = wp->w_width;
  1918. X try_line:
  1919. X  cp = line = wp->w_image[y];
  1920. X  if (wp->w_autoaka > 0 &&  *wp->w_akabuf != '\0')
  1921. X    {
  1922. X      for (;;)
  1923. X    {
  1924. X      if (cp - line >= cols - len)
  1925. X        {
  1926. X          if (++y == wp->w_autoaka && y < rows)
  1927. X        goto try_line;
  1928. X          return;
  1929. X        }
  1930. X      if (strncmp(cp, wp->w_akabuf, len) == 0)
  1931. X        break;
  1932. X      cp++;
  1933. X    }
  1934. X      cp += len;
  1935. X    }
  1936. X  for (len = cols - (cp - line); len && *cp == ' '; len--, cp++)
  1937. X    ;
  1938. X  if (len)
  1939. X    {
  1940. X      if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^'))
  1941. X    wp->w_autoaka = -1;
  1942. X      else
  1943. X    wp->w_autoaka = 0;
  1944. X      line = cp;
  1945. X      while (len && *cp != ' ')
  1946. X    {
  1947. X      if (*cp++ == '/')
  1948. X        line = cp;
  1949. X      len--;
  1950. X    }
  1951. X      ChangeAKA(wp, line, cp - line);
  1952. X    }
  1953. X  else
  1954. X    wp->w_autoaka = 0;
  1955. X}
  1956. X
  1957. Xvoid
  1958. XMakeBlankLine(p, n)
  1959. Xregister char *p;
  1960. Xregister int n;
  1961. X{
  1962. X  while (n--)
  1963. X    *p++ = ' ';
  1964. X}
  1965. X
  1966. Xvoid
  1967. XSetCurr(wp)
  1968. Xstruct win *wp;
  1969. X{
  1970. X  curr = wp;
  1971. X  if (curr == 0)
  1972. X    return;
  1973. X  cols = curr->w_width;
  1974. X  rows = curr->w_height;
  1975. X  display = curr->w_active ? curr->w_display : 0;
  1976. X}
  1977. X
  1978. Xstatic void
  1979. XRestorePosAttrFont()
  1980. X{
  1981. X  GotoPos(curr->w_x, curr->w_y);
  1982. X  SetAttr(curr->w_Attr);
  1983. X  SetFont(curr->w_Font);
  1984. X}
  1985. X
  1986. X/* Send a terminal report as if it were typed. */ 
  1987. Xstatic void
  1988. XReport(fmt, n1, n2)
  1989. Xchar *fmt;
  1990. Xint n1, n2;
  1991. X{
  1992. X  register int len;
  1993. X  char rbuf[40];
  1994. X
  1995. X  sprintf(rbuf, fmt, n1, n2);
  1996. X  len = strlen(rbuf);
  1997. X
  1998. X  if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf))
  1999. X    {
  2000. X      bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len);
  2001. X      curr->w_inlen += len;
  2002. X    }
  2003. X}
  2004. X
  2005. X#ifdef COPY_PASTE
  2006. Xvoid
  2007. XAddLineToHist(wp, pi, pa, pf)
  2008. Xstruct win *wp;
  2009. Xchar **pi, **pa, **pf;
  2010. X{
  2011. X  register char *q, *o;
  2012. X
  2013. X  if (wp->w_histheight == 0)
  2014. X    return;
  2015. X  q = *pi; *pi = wp->w_ihist[wp->w_histidx]; wp->w_ihist[wp->w_histidx] = q;
  2016. X  q = *pa; o = wp->w_ahist[wp->w_histidx]; wp->w_ahist[wp->w_histidx] = q;
  2017. X  if (o != null)
  2018. X    free(o);
  2019. X  q = *pf; o = wp->w_fhist[wp->w_histidx]; wp->w_fhist[wp->w_histidx] = q;
  2020. X  if (o != null)
  2021. X    free(o);
  2022. X  *pa = *pf = null;
  2023. X  if (++wp->w_histidx >= wp->w_histheight)
  2024. X    wp->w_histidx = 0;
  2025. X}
  2026. X#endif
  2027. END_OF_FILE
  2028. if test 39996 -ne `wc -c <'ansi.c'`; then
  2029.     echo shar: \"'ansi.c'\" unpacked with wrong size!
  2030. fi
  2031. # end of 'ansi.c'
  2032. fi
  2033. if test -f 'screen.c' -a "${1}" != "-c" ; then 
  2034.   echo shar: Will not clobber existing file \"'screen.c'\"
  2035. else
  2036. echo shar: Extracting \"'screen.c'\" \(50777 characters\)
  2037. sed "s/^X//" >'screen.c' <<'END_OF_FILE'
  2038. X/* Copyright (c) 1993
  2039. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  2040. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  2041. X * Copyright (c) 1987 Oliver Laumann
  2042. X *
  2043. X * This program is free software; you can redistribute it and/or modify
  2044. X * it under the terms of the GNU General Public License as published by
  2045. X * the Free Software Foundation; either version 2, or (at your option)
  2046. X * any later version.
  2047. X *
  2048. X * This program is distributed in the hope that it will be useful,
  2049. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2050. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2051. X * GNU General Public License for more details.
  2052. X *
  2053. X * You should have received a copy of the GNU General Public License
  2054. X * along with this program (see the file COPYING); if not, write to the
  2055. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2056. X *
  2057. X ****************************************************************
  2058. X */
  2059. X
  2060. X#include "rcs.h"
  2061. XRCS_ID("$Id: screen.c,v 1.9 1993/07/09 12:07:49 jnweiger Exp $ FAU")
  2062. X
  2063. X
  2064. X#include <ctype.h>
  2065. X#ifdef __sgi
  2066. X# include <stdio.h> /* needed before pwd.h to avoid ansi compiler whining */
  2067. X#endif /* __sgi */
  2068. X#include <pwd.h>
  2069. X#include <fcntl.h>
  2070. X#ifdef sgi
  2071. X# include <sys/sysmacros.h>
  2072. X#endif /* sgi */
  2073. X#if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX)
  2074. X# include <time.h>
  2075. X#endif
  2076. X#include <sys/time.h>
  2077. X#if defined(M_XENIX) || defined(M_UNIX)
  2078. X#include <sys/select.h> /* for timeval */
  2079. X#endif
  2080. X#include <sys/types.h>
  2081. X#ifdef ISC
  2082. X# include <sys/bsdtypes.h>
  2083. X#endif
  2084. X#include <sys/stat.h>
  2085. X#ifndef sgi
  2086. X# include <sys/file.h>
  2087. X#endif /* sgi */
  2088. X#ifndef sun
  2089. X# include <sys/ioctl.h>
  2090. X#endif /* sun */
  2091. X
  2092. X#include <signal.h>
  2093. X
  2094. X#include "config.h"
  2095. X
  2096. X#ifdef SHADOWPW
  2097. X# include <shadow.h>
  2098. X#endif /* SHADOWPW */
  2099. X
  2100. X#ifdef SVR4
  2101. X# include <sys/stropts.h>
  2102. X#endif
  2103. X
  2104. X#ifdef SYSV
  2105. X# include <sys/utsname.h>
  2106. X#endif
  2107. X
  2108. X#if defined(sequent) || defined(SVR4)
  2109. X# include <sys/resource.h>
  2110. X#endif /* sequent || SVR4 */
  2111. X
  2112. X#ifdef ISC
  2113. X# include <sys/tty.h>
  2114. X# include <sys/sioctl.h>
  2115. X# include <sys/pty.h>
  2116. X#endif /* ISC */
  2117. X
  2118. X#include "screen.h"
  2119. X
  2120. X#include "patchlevel.h"
  2121. X
  2122. X#if defined(xelos) || defined(m68k) || defined(M_XENIX)
  2123. X struct passwd *getpwuid __P((uid_t));
  2124. X struct passwd *getpwnam __P((char *));
  2125. X#endif
  2126. X
  2127. X#ifdef USEVARARGS
  2128. X# if defined(__STDC__)
  2129. X#  include <stdarg.h>
  2130. X# else
  2131. X#  include <varargs.h>
  2132. X# endif
  2133. X#endif
  2134. X
  2135. X#if defined(_SEQUENT_) 
  2136. X/* for the FD.. stuff */
  2137. X# include <sys/select.h>
  2138. X#endif /* _SEQUENT_ */
  2139. X
  2140. X#ifndef FD_SET
  2141. Xtypedef struct fd_set
  2142. X{
  2143. X  int fd_bits[1];
  2144. X}      fd_set;
  2145. X# define FD_ZERO(fd) ((fd)->fd_bits[0] = 0)
  2146. X# define FD_SET(b, fd) ((fd)->fd_bits[0] |= 1 << (b))
  2147. X# define FD_ISSET(b, fd) ((fd)->fd_bits[0] & 1 << (b))
  2148. X# define FD_SETSIZE 32
  2149. X#endif
  2150. X
  2151. X
  2152. X#ifdef DEBUG
  2153. XFILE *dfp;
  2154. X#endif
  2155. X
  2156. X
  2157. Xextern char *blank, *null, Term[], screenterm[], **environ, Termcap[];
  2158. Xint force_vt = 1, assume_LP = 0;
  2159. Xint VBellWait, MsgWait, MsgMinWait, SilenceWait;
  2160. X
  2161. Xextern struct display *displays, *display; 
  2162. Xextern struct layer BlankLayer;
  2163. X
  2164. X/* tty.c */
  2165. Xextern int intrc;
  2166. X
  2167. X
  2168. Xextern int use_hardstatus;
  2169. X#ifdef COPY_PASTE
  2170. Xextern char mark_key_tab[];
  2171. X#endif
  2172. Xextern char version[];
  2173. Xextern char DefaultShell[];
  2174. X
  2175. X
  2176. Xchar *ShellProg;
  2177. Xchar *ShellArgs[2];
  2178. X
  2179. Xextern struct NewWindow nwin_undef, nwin_default, nwin_options;
  2180. X
  2181. Xstatic char *MakeWinMsg __P((char *, int));
  2182. Xstatic void  SigChldHandler __P((void));
  2183. Xstatic sig_t SigChld __P(SIGPROTOARG);
  2184. Xstatic sig_t SigInt __P(SIGPROTOARG);
  2185. Xstatic sig_t CoreDump __P((int));
  2186. Xstatic void  DoWait __P((void));
  2187. X
  2188. X
  2189. X#ifdef PASSWORD
  2190. Xextern char Password[];
  2191. X#endif
  2192. X
  2193. X
  2194. X/* the attacher */
  2195. Xstruct passwd *ppp;
  2196. Xchar *attach_tty;
  2197. Xchar *attach_term;
  2198. Xchar *LoginName;
  2199. Xstruct mode attach_Mode;
  2200. X
  2201. X
  2202. X#ifdef SOCKDIR
  2203. Xchar *SockDir = SOCKDIR;
  2204. X#else
  2205. Xchar *SockDir = ".iscreen";
  2206. X#endif
  2207. Xextern char SockPath[], *SockNamePtr, *SockName;
  2208. Xint ServerSocket = -1;
  2209. Xchar **NewEnv = NULL;
  2210. X
  2211. Xchar *RcFileName = NULL;
  2212. Xextern char Esc;
  2213. Xchar *home;
  2214. X
  2215. Xchar *screenlogdir = NULL;
  2216. Xchar *hardcopydir = NULL;
  2217. Xchar *BellString;
  2218. Xchar *VisualBellString;
  2219. Xchar *ActivityString;
  2220. X#ifdef COPY_PASTE
  2221. Xchar *BufferFile;
  2222. X#endif
  2223. X#ifdef POW_DETACH
  2224. Xchar *PowDetachString;
  2225. X#endif
  2226. Xint auto_detach = 1;
  2227. Xint iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag;
  2228. Xint adaptflag;
  2229. X
  2230. Xtime_t Now;
  2231. X
  2232. X#ifdef MULTIUSER
  2233. Xchar *multi;
  2234. Xchar *multi_home;
  2235. Xint multi_uid;
  2236. Xint own_uid;
  2237. Xint multiattach;
  2238. Xint tty_mode;
  2239. Xint tty_oldmode = -1;
  2240. X#endif
  2241. X
  2242. Xchar HostName[MAXSTR];
  2243. Xint MasterPid;
  2244. Xint real_uid, real_gid, eff_uid, eff_gid;
  2245. Xint default_startup;
  2246. Xint slowpaste;
  2247. X
  2248. X#ifdef NETHACK
  2249. Xint nethackflag = 0;
  2250. X#endif
  2251. X
  2252. X
  2253. Xstruct win *fore = NULL;
  2254. Xstruct win *windows = NULL;
  2255. Xstruct win *console_window;
  2256. X
  2257. X
  2258. X/*
  2259. X * Do this last
  2260. X */
  2261. X#include "extern.h"
  2262. X
  2263. X/*
  2264. X * XXX: Missing system header files.
  2265. X */
  2266. X#ifdef USEVARARGS
  2267. X# ifndef VPRNT_DECLARED
  2268. Xint vsprintf __P((char *, char *, va_list));
  2269. X# endif /* VPRNT_DECLARED */
  2270. X#endif
  2271. X#ifndef SELECT_DECLARED
  2272. Xint select __P((int, fd_set *, fd_set *, fd_set *, const struct timeval *));
  2273. X#endif
  2274. X
  2275. X#ifdef NETHACK
  2276. Xchar strnomem[] = "Who was that Maude person anyway?";
  2277. X#else
  2278. Xchar strnomem[] = "Out of memory.";
  2279. X#endif
  2280. X
  2281. X
  2282. Xstatic int InterruptPlease = 0;
  2283. Xstatic int GotSigChld;
  2284. X
  2285. X
  2286. Xstatic void
  2287. Xmkfdsets(rp, wp)
  2288. Xfd_set *rp, *wp;
  2289. X{
  2290. X  register struct win *p;
  2291. X
  2292. X  FD_ZERO(rp);
  2293. X  FD_ZERO(wp);
  2294. X  for (display = displays; display; display = display->_d_next)
  2295. X    {
  2296. X      if (d_obufp != d_obuf)
  2297. X    FD_SET(d_userfd, wp);
  2298. X
  2299. X      FD_SET(d_userfd, rp);    /* Do that always */
  2300. X
  2301. X      /* read from terminal if there is room in the destination buffer
  2302. X       *
  2303. X       * Removed, so we can always input a command sequence
  2304. X       *
  2305. X       * if (d_fore == 0)
  2306. X       *   continue;
  2307. X       * if (W_UWP(d_fore))
  2308. X       *   {
  2309. X       *      check pseudowin buffer
  2310. X       *      if (d_fore->w_pwin->p_inlen < sizeof(d_fore->w_pwin->p_inbuf))
  2311. X       *      FD_SET(d_userfd, rp);
  2312. X       *   }
  2313. X       * else
  2314. X       *   {
  2315. X       *     check window buffer
  2316. X       *     if (d_fore->w_inlen < sizeof(d_fore->w_inbuf))
  2317. X       *     FD_SET(d_userfd, rp);
  2318. X       *   }
  2319. X       */
  2320. X    }
  2321. X  for (p = windows; p; p = p->w_next)
  2322. X    {
  2323. X#ifdef COPY_PASTE
  2324. X      if (p->w_pastelen)
  2325. X        {
  2326. X      /* paste to win/pseudo */
  2327. X# ifdef PSEUDOS
  2328. X      FD_SET(W_UWP(p) ? p->w_pwin->p_ptyfd : p->w_ptyfd, wp);
  2329. X# else
  2330. X      FD_SET(p->w_ptyfd, wp);
  2331. X# endif
  2332. X    }
  2333. X#endif
  2334. X      /* query window buffer */
  2335. X      if (p->w_inlen > 0)
  2336. X    FD_SET(p->w_ptyfd, wp);
  2337. X#ifdef PSEUDOS
  2338. X      /* query pseudowin buffer */
  2339. X      if (p->w_pwin && p->w_pwin->p_inlen > 0)
  2340. X        FD_SET(p->w_pwin->p_ptyfd, wp);
  2341. X#endif
  2342. X
  2343. X      display = p->w_display;
  2344. X      if (p->w_active && d_status && !d_status_bell && !(use_hardstatus && HS))
  2345. X    continue;
  2346. X      if (p->w_outlen > 0)
  2347. X    continue;
  2348. X      if (p->w_lay->l_block)
  2349. X    continue;
  2350. X    /* 
  2351. X     * Don't accept input from window or pseudowin if there is to much 
  2352. X     * output pending on display .
  2353. X     */
  2354. X      if (p->w_active && (d_obufp - d_obuf) > d_obufmax)
  2355. X    {
  2356. X      debug1("too much output pending, window %d\n", p->w_number);
  2357. X      continue;  
  2358. X    }
  2359. X#ifdef PSEUDOS
  2360. X      if (W_RW(p))
  2361. X    {
  2362. X      /* Check free space if we stuff window output in pseudo */
  2363. X      if (p->w_pwin && W_WTOP(p) && (p->w_pwin->p_inlen >= sizeof(p->w_pwin->p_inbuf)))
  2364. X        {
  2365. X          debug2("pseudowin %d buffer full (%d bytes)\n", p->w_number, p->w_pwin->p_inlen);
  2366. X        }
  2367. X      else
  2368. X            FD_SET(p->w_ptyfd, rp);
  2369. X    }
  2370. X      if (W_RP(p))
  2371. X    {
  2372. X      /* Check free space if we stuff pseudo output in window */
  2373. X      if (W_PTOW(p) && p->w_inlen >= sizeof(p->w_inbuf))
  2374. X        {
  2375. X          debug2("window %d buffer full (%d bytes)\n", p->w_number, p->w_inlen);
  2376. X        }
  2377. X      else
  2378. X            FD_SET(p->w_pwin->p_ptyfd, rp);
  2379. X    }
  2380. X#else /* PSEUDOS */
  2381. X      FD_SET(p->w_ptyfd, rp);
  2382. X#endif /* PSEUDOS */
  2383. X    }
  2384. X  FD_SET(ServerSocket, rp);
  2385. X}
  2386. X
  2387. Xvoid
  2388. Xmain(ac, av)
  2389. Xint ac;
  2390. Xchar **av;
  2391. X{
  2392. X  register int n, len;
  2393. X  register struct win *p;
  2394. X  char *ap;
  2395. X  char *av0;
  2396. X  char socknamebuf[2 * MAXSTR];
  2397. X  fd_set r, w;
  2398. X  int mflag = 0;
  2399. X  struct timeval tv;
  2400. X  int nsel;
  2401. X  char buf[IOSIZE], *myname = (ac == 0) ? "screen" : av[0];
  2402. X  struct stat st;
  2403. X  int buflen, tmp;
  2404. X#ifdef _MODE_T            /* (jw) */
  2405. X  mode_t oumask;
  2406. X#else
  2407. X  int oumask;
  2408. X#endif
  2409. X#ifdef SYSV
  2410. X  struct utsname utsnam;
  2411. X#endif
  2412. X  struct NewWindow nwin;
  2413. X  int detached = 0;        /* start up detached */
  2414. X  struct display *ndisplay;
  2415. X#ifdef MULTIUSER
  2416. X  char *sockp;
  2417. X#endif
  2418. X
  2419. X  /*
  2420. X   *  First, close all unused descriptors
  2421. X   *  (otherwise, we might have problems with the select() call)
  2422. X   */
  2423. X  closeallfiles(0);
  2424. X#ifdef DEBUG
  2425. X  (void) mkdir("/tmp/debug", 0777);
  2426. X  if ((dfp = fopen("/tmp/debug/screen.front", "w")) == NULL)
  2427. X    dfp = stderr;
  2428. X  else
  2429. X    (void) chmod("/tmp/debug/screen.front", 0666);
  2430. X#endif
  2431. X  sprintf(version, "%d.%.2d.%.2d%s (%s) %s", REV, VERS,
  2432. X      PATCHLEVEL, STATE, ORIGIN, DATE);
  2433. X  debug2("-- screen debug started %s (%s)\n", *av, version);
  2434. X#ifdef POSIX
  2435. X  debug("POSIX\n");
  2436. X#endif
  2437. X#ifdef TERMIO
  2438. X  debug("TERMIO\n");
  2439. X#endif
  2440. X#ifdef SYSV
  2441. X  debug("SYSV\n");
  2442. X#endif
  2443. X#ifdef SYSVSIGS
  2444. X  debug("SYSVSIGS\n");
  2445. X#endif
  2446. X#ifdef NAMEDPIPE
  2447. X  debug("NAMEDPIPE\n");
  2448. X#endif
  2449. X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
  2450. X  debug("Window changing enabled\n");
  2451. X#endif
  2452. X#ifdef NOREUID
  2453. X  debug("NOREUID\n");
  2454. X#endif
  2455. X#ifdef hpux
  2456. X  debug("hpux\n");
  2457. X#endif
  2458. X#ifdef USEBCOPY
  2459. X  debug("USEBCOPY\n");
  2460. X#endif
  2461. X#ifdef UTMPOK
  2462. X  debug("UTMPOK\n");
  2463. X#endif
  2464. X#ifdef LOADAV
  2465. X  debug("LOADAV\n");
  2466. X#endif
  2467. X#ifdef NETHACK
  2468. X  debug("NETHACK\n");
  2469. X#endif
  2470. X#ifdef TERMINFO
  2471. X  debug("TERMINFO\n");
  2472. X#endif
  2473. X#ifdef SHADOWPW
  2474. X  debug("SHADOWPW\n");
  2475. X#endif
  2476. X#ifdef NAME_MAX
  2477. X  debug1("NAME_MAX = %d\n", NAME_MAX);
  2478. X#endif
  2479. X
  2480. X  BellString = SaveStr("Bell in window %");
  2481. X  VisualBellString = SaveStr("   Wuff,  Wuff!!  ");
  2482. X  ActivityString = SaveStr("Activity in window %");
  2483. X#ifdef COPY_PASTE
  2484. X  BufferFile = SaveStr(DEFAULT_BUFFERFILE);
  2485. X#endif
  2486. X  ShellProg = NULL;
  2487. X#ifdef POW_DETACH
  2488. X  PowDetachString = 0;
  2489. X#endif
  2490. X  default_startup = (ac > 1) ? 0 : 1;
  2491. X  adaptflag = 0;
  2492. X  slowpaste = 0;
  2493. X  VBellWait = VBELLWAIT;
  2494. X  MsgWait = MSGWAIT;
  2495. X  MsgMinWait = MSGMINWAIT;
  2496. X  SilenceWait = SILENCEWAIT;
  2497. X#ifdef COPY_PASTE
  2498. X  CompileKeys((char *)NULL, mark_key_tab);
  2499. X#endif
  2500. X  nwin = nwin_undef;
  2501. X  nwin_options = nwin_undef;
  2502. X
  2503. X  av0 = *av;
  2504. X  /* if this is a login screen, assume -R */
  2505. X  if (*av0 == '-')
  2506. X    {
  2507. X      rflag = 2;
  2508. X#ifdef MULTI
  2509. X      xflag = 1;
  2510. X#endif
  2511. X      ShellProg = SaveStr(DefaultShell); /* to prevent nasty circles */
  2512. X    }
  2513. X  while (ac > 0)
  2514. X    {
  2515. X      ap = *++av;
  2516. X      if (--ac > 0 && *ap == '-')
  2517. X    {
  2518. X      switch (ap[1])
  2519. X        {
  2520. X        case 'a':
  2521. X          nwin_options.aflag = 1;
  2522. X          break;
  2523. X        case 'A':
  2524. X          adaptflag = 1;
  2525. X          break;
  2526. X        case 'c':
  2527. X          if (ap[2])
  2528. X        RcFileName = ap + 2;
  2529. X          else
  2530. X        {
  2531. X          if (--ac == 0)
  2532. X            exit_with_usage(myname);
  2533. X          RcFileName = *++av;
  2534. X        }
  2535. X          break;
  2536. X        case 'e':
  2537. X          if (ap[2])
  2538. X        ap += 2;
  2539. X          else
  2540. X        {
  2541. X          if (--ac == 0)
  2542. X            exit_with_usage(myname);
  2543. X          ap = *++av;
  2544. X        }
  2545. X          if (ParseEscape(ap))
  2546. X        Panic(0, "Two characters are required with -e option.");
  2547. X          break;
  2548. X        case 'f':
  2549. X          switch (ap[2])
  2550. X        {
  2551. X        case 'n':
  2552. X        case '0':
  2553. X          nwin_options.flowflag = FLOW_NOW * 0;
  2554. X          break;
  2555. X        case 'y':
  2556. X        case '1':
  2557. X        case '\0':
  2558. X          nwin_options.flowflag = FLOW_NOW * 1;
  2559. X          break;
  2560. X        case 'a':
  2561. X          nwin_options.flowflag = FLOW_AUTOFLAG;
  2562. X          break;
  2563. X        default:
  2564. X          exit_with_usage(myname);
  2565. X        }
  2566. X          break;
  2567. X            case 'h':
  2568. X          if (ap[2])
  2569. X        nwin_options.histheight = atoi(ap + 2);
  2570. X          else
  2571. X        {
  2572. X          if (--ac == 0)
  2573. X            exit_with_usage(myname);
  2574. X          nwin_options.histheight = atoi(*++av);
  2575. X        }
  2576. X          if (nwin_options.histheight < 0)
  2577. X        exit_with_usage(myname);
  2578. X          break;
  2579. X        case 'i':
  2580. X          iflag = 1;
  2581. X          break;
  2582. X        case 't': /* title is a synonym for AkA */
  2583. X        case 'k':
  2584. X          if (ap[2])
  2585. X        nwin_options.aka = ap + 2;
  2586. X          else
  2587. X        {
  2588. X          if (--ac == 0)
  2589. X            exit_with_usage(myname);
  2590. X          nwin_options.aka = *++av;
  2591. X        }
  2592. X          break;
  2593. X        case 'l':
  2594. X          switch (ap[2])
  2595. X        {
  2596. X        case 'n':
  2597. X        case '0':
  2598. X          nwin_options.lflag = 0;
  2599. X          break;
  2600. X        case 'y':
  2601. X        case '1':
  2602. X        case '\0':
  2603. X          nwin_options.lflag = 1;
  2604. X          break;
  2605. X        case 's':
  2606. X        case 'i':
  2607. X          lsflag = 1;
  2608. X          if (ac > 1)
  2609. X            {
  2610. X              SockName = *++av;
  2611. X              ac--;
  2612. X            }
  2613. X          break;
  2614. X        default:
  2615. X          exit_with_usage(myname);
  2616. X        }
  2617. X          break;
  2618. X        case 'w':
  2619. X          lsflag = 1;
  2620. X          wipeflag = 1;
  2621. X          break;
  2622. X        case 'L':
  2623. X          assume_LP = 1;
  2624. X          break;
  2625. X        case 'm':
  2626. X          mflag = 1;
  2627. X          break;
  2628. X        case 'O':
  2629. X          force_vt = 0;
  2630. X          break;
  2631. X        case 'T':
  2632. X              if (ap[2])
  2633. X        {
  2634. X          if (strlen(ap+2) < 20)
  2635. X                    strcpy(screenterm, ap + 2);
  2636. X        }
  2637. X              else
  2638. X                {
  2639. X                  if (--ac == 0)
  2640. X                    exit_with_usage(myname);
  2641. X          if (strlen(*++av) < 20)
  2642. X                    strcpy(screenterm, *av);
  2643. X                }
  2644. X          nwin_options.term = screenterm;
  2645. X              break;
  2646. X        case 'q':
  2647. X          quietflag = 1;
  2648. X          break;
  2649. X        case 'r':
  2650. X        case 'R':
  2651. X#ifdef MULTI
  2652. X        case 'x':
  2653. X#endif
  2654. X          if (ap[2])
  2655. X        {
  2656. X          SockName = ap + 2;
  2657. X          if (ac != 1)
  2658. X            exit_with_usage(myname);
  2659. X        }
  2660. X          else if (ac > 1 && *av[1] != '-')
  2661. X        {
  2662. X          SockName = *++av;
  2663. X          ac--;
  2664. X        }
  2665. X#ifdef MULTI
  2666. X          if (ap[1] == 'x')
  2667. X        xflag = 1;
  2668. X          else
  2669. X#endif
  2670. X            rflag = (ap[1] == 'r') ? 1 : 2;
  2671. X          break;
  2672. X#ifdef REMOTE_DETACH
  2673. X        case 'd':
  2674. X          dflag = 1;
  2675. X          /* FALLTHROUGH */
  2676. X        case 'D':
  2677. X          if (!dflag)
  2678. X        dflag = 2;
  2679. X          if (ap[2])
  2680. X        SockName = ap + 2;
  2681. X          if (ac == 2)
  2682. X        {
  2683. X          if (*av[1] != '-')
  2684. X            {
  2685. X              SockName = *++av;
  2686. X              ac--;
  2687. X            }
  2688. X        }
  2689. X          break;
  2690. X#endif
  2691. X        case 's':
  2692. X          if (ap[2])
  2693. X        {
  2694. X          if (ShellProg)
  2695. X            free(ShellProg);
  2696. X          ShellProg = SaveStr(ap + 2);
  2697. X        }
  2698. X          else
  2699. X        {
  2700. X          if (--ac == 0)
  2701. X            exit_with_usage(myname);
  2702. X          if (ShellProg)
  2703. X            free(ShellProg);
  2704. X          ShellProg = SaveStr(*++av);
  2705. X        }
  2706. X          debug1("ShellProg: '%s'\n", ShellProg);
  2707. X          break;
  2708. X        case 'S':
  2709. X          if (ap[2])
  2710. X        SockName = ap + 2;
  2711. X          else
  2712. X        {
  2713. X          if (--ac == 0)
  2714. X            exit_with_usage(myname);
  2715. X          SockName = *++av;
  2716. X          if (!*SockName)
  2717. X            exit_with_usage(myname);
  2718. X        }
  2719. X          break;
  2720. X        case 'v':
  2721. X          Panic(0, "Screen version %s", version);
  2722. X          /* NOTREACHED */
  2723. X        default:
  2724. X          exit_with_usage(myname);
  2725. X        }
  2726. X    }
  2727. X      else
  2728. X    break;
  2729. X    }
  2730. X  if (dflag && mflag && SockName && !(rflag || xflag))
  2731. X    detached = 1;
  2732. X  nwin = nwin_options;
  2733. X  if (ac)
  2734. X    nwin.args = av;
  2735. X  real_uid = getuid();
  2736. X  real_gid = getgid();
  2737. X  eff_uid = geteuid();
  2738. X  eff_gid = getegid();
  2739. X  if (eff_uid != real_uid)
  2740. X    {        
  2741. X      /* if running with s-bit, we must install a special signal
  2742. X       * handler routine that resets the s-bit, so that we get a
  2743. X       * core file anyway.
  2744. X       */
  2745. X#ifdef SIGBUS /* OOPS, linux has no bus errors ??? */
  2746. X      signal(SIGBUS, CoreDump);
  2747. X#endif /* SIGBUS */
  2748. X      signal(SIGSEGV, CoreDump);
  2749. X    }
  2750. X  if (!ShellProg)
  2751. X    {
  2752. X      register char *sh;
  2753. X
  2754. X      sh = getenv("SHELL");
  2755. X      ShellProg = SaveStr(sh ? sh : DefaultShell);
  2756. X    }
  2757. X  ShellArgs[0] = ShellProg;
  2758. X#ifdef NETHACK
  2759. X  nethackflag = (getenv("NETHACKOPTIONS") != NULL);
  2760. X#endif
  2761. X#ifdef MULTIUSER
  2762. X  own_uid = multi_uid = real_uid;
  2763. X  if (SockName && (sockp = index(SockName, '/')))
  2764. X    {
  2765. X      if (eff_uid)
  2766. X        Panic(0, "Must run suid root for multi support.");
  2767. X      *sockp = 0;
  2768. X      multi = SockName;
  2769. X      SockName = sockp + 1;
  2770. X      if (*multi)
  2771. X    {
  2772. X      struct passwd *mppp;
  2773. X      if ((mppp = getpwnam(multi)) == (struct passwd *) 0)
  2774. X        Panic(0, "Cannot identify account '%s'.", multi);
  2775. X      multi_uid = mppp->pw_uid;
  2776. X      multi_home = SaveStr(mppp->pw_dir);
  2777. X#ifdef MULTI
  2778. X      if (rflag || lsflag)
  2779. X        {
  2780. X          xflag = 1;
  2781. X          rflag = 0;
  2782. X        }
  2783. X#endif
  2784. X      detached = 0;
  2785. X      multiattach = 1;
  2786. X    }
  2787. X    }
  2788. X  if (SockName && *SockName == 0)
  2789. X    SockName = 0;
  2790. X#endif
  2791. X  if ((LoginName = getlogin()) && LoginName[0] != '\0')
  2792. X    {
  2793. X      if ((ppp = getpwnam(LoginName)) != (struct passwd *) 0)
  2794. X    if (ppp->pw_uid != real_uid)
  2795. X      ppp = (struct passwd *) 0;
  2796. X    }
  2797. X  if (ppp == 0)
  2798. X    {
  2799. X      if ((ppp = getpwuid(real_uid)) == 0)
  2800. X        {
  2801. X#ifdef NETHACK
  2802. X          if (nethackflag)
  2803. X        Panic(0, "An alarm sounds through the dungeon...\nWarning, the kops are coming.");
  2804. X      else
  2805. X#endif
  2806. X      Panic(0, "getpwuid() can't identify your account!");
  2807. X      exit(1);
  2808. X        }
  2809. X      LoginName = ppp->pw_name;
  2810. X    }
  2811. X  home = getenv("HOME");    /* may or may not return a result. jw. */
  2812. X#if !defined(SOCKDIR) && defined(MULTIUSER)
  2813. X  if (multi && !multiattach)
  2814. X    {
  2815. X      if (home && strcmp(home, ppp->pw_dir))
  2816. X        Panic(0, "$HOME must match passwd entry for multi screens");
  2817. X    }
  2818. X#endif
  2819. X  if (home == 0 || *home == '\0')
  2820. X    home = ppp->pw_dir;
  2821. X  if (strlen(LoginName) > 20)
  2822. X    Panic(0, "LoginName too long - sorry.");
  2823. X  if (strlen(home) > MAXPATHLEN - 25)
  2824. X    Panic(0, "$HOME too long - sorry.");
  2825. X#ifdef PASSWORD
  2826. X  strcpy(Password, ppp->pw_passwd);
  2827. X#endif
  2828. X
  2829. X  if (!detached && !lsflag)
  2830. X    {
  2831. X      /* ttyname implies isatty */
  2832. X      if (!(attach_tty = ttyname(0)))
  2833. X    {
  2834. X#ifdef NETHACK
  2835. X      if (nethackflag)
  2836. X        Panic(0, "You must play from a terminal.");
  2837. X      else
  2838. X#endif
  2839. X      Panic(0, "Must be connected to a terminal.");
  2840. X      exit(1);
  2841. X    }
  2842. X      if (strlen(attach_tty) >= MAXPATHLEN)
  2843. X    Panic(0, "TtyName too long - sorry.");
  2844. X      if (stat(attach_tty, &st))
  2845. X    Panic(errno, "Cannot access '%s'", attach_tty);
  2846. X#ifdef MULTIUSER
  2847. X      tty_mode = st.st_mode & 0777;
  2848. X#endif
  2849. X      if ((n = secopen(attach_tty, O_RDWR, 0)) < 0)
  2850. X    Panic(0, "Cannot open '%s' - please check.", attach_tty);
  2851. X      close(n);
  2852. X      debug1("attach_tty is %s\n", attach_tty);
  2853. X      if ((attach_term = getenv("TERM")) == 0)
  2854. X    Panic(0, "Please set a terminal type.");
  2855. X      if (strlen(attach_term) > sizeof(d_termname) - 1)
  2856. X    Panic(0, "$TERM too long - sorry.");
  2857. X      GetTTY(0, &attach_Mode);
  2858. X#ifdef DEBUGGGGGGGGGGGGGGG
  2859. X      DebugTTY(&attach_Mode);
  2860. X#endif /* DEBUG */
  2861. X    }
  2862. X  
  2863. X#ifdef _MODE_T
  2864. X  oumask = umask(0);        /* well, unsigned never fails? jw. */
  2865. X#else
  2866. X  if ((oumask = umask(0)) == -1)
  2867. X    Panic(errno, "Cannot change umask to zero");
  2868. X#endif
  2869. X  if ((SockDir = getenv("ISCREENDIR")) == NULL)
  2870. X    SockDir = getenv("SCREENDIR");
  2871. X  if (SockDir)
  2872. X    {
  2873. X      if (strlen(SockDir) >= MAXPATHLEN - 1)
  2874. X    Panic(0, "Ridiculously long $(I)SCREENDIR - try again.");
  2875. X#ifdef MULTIUSER
  2876. X      if (multi)
  2877. X    Panic(0, "No $(I)SCREENDIR with multi screens, please.");
  2878. X#endif
  2879. X    }
  2880. X#ifdef MULTIUSER
  2881. X  if (multiattach)
  2882. X    {
  2883. X# ifndef SOCKDIR
  2884. X      sprintf(SockPath, "%s/.iscreen", multi_home);
  2885. X      SockDir = SockPath;
  2886. X# else
  2887. X      SockDir = SOCKDIR;
  2888. X      sprintf(SockPath, "%s/S-%s", SockDir, multi);
  2889. X# endif
  2890. X    }
  2891. X  else
  2892. X#endif
  2893. X    {
  2894. X#ifndef SOCKDIR
  2895. X      if (SockDir == 0)
  2896. X    {
  2897. X      sprintf(SockPath, "%s/.iscreen", home);
  2898. X      SockDir = SockPath;
  2899. X    }
  2900. X#endif
  2901. X      if (SockDir)
  2902. X    {
  2903. X      if (access(SockDir, F_OK))
  2904. X        {
  2905. X          debug1("SockDir '%s' missing ...\n", SockDir);
  2906. X          if (UserContext() > 0)
  2907. X        {
  2908. X          if (mkdir(SockDir, 0700))
  2909. X            UserReturn(0);
  2910. X          UserReturn(1);
  2911. X        }
  2912. X          if (UserStatus() <= 0)
  2913. X        Panic(0, "Cannot make directory '%s'.", SockDir);
  2914. X        }
  2915. X      if (SockDir != SockPath)
  2916. X        strcpy(SockPath, SockDir);
  2917. X    }
  2918. X#ifdef SOCKDIR
  2919. X      else
  2920. X    {
  2921. X      SockDir = SOCKDIR;
  2922. X      if (stat(SockDir, &st))
  2923. X        {
  2924. X          if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1)
  2925. X        Panic(errno, "Cannot make directory '%s'", SockDir);
  2926. X        }
  2927. X      else
  2928. X        {
  2929. X          n = eff_uid ? 0777 : 0755;
  2930. X          if ((st.st_mode & 0777) != n)
  2931. X        Panic(0, "Directory '%s' must have mode %03o.", SockDir, n);
  2932. X        }
  2933. X      sprintf(SockPath, "%s/S-%s", SockDir, LoginName);
  2934. X      if (access(SockPath, F_OK))
  2935. X        {
  2936. X          if (mkdir(SockPath, 0700) == -1)
  2937. X        Panic(errno, "Cannot make directory '%s'", SockPath);
  2938. X          (void) chown(SockPath, real_uid, real_gid);
  2939. X        }
  2940. X    }
  2941. X#endif
  2942. X    }
  2943. X
  2944. X  if (stat(SockPath, &st) == -1)
  2945. X    {
  2946. X      Panic(errno, "Cannot access %s", SockPath);
  2947. X    }
  2948. X  else
  2949. X    {
  2950. X#ifdef _POSIX_SOURCE
  2951. X      if (S_ISDIR(st.st_mode) == 0)
  2952. X#else
  2953. X      if ((st.st_mode & S_IFMT) != S_IFDIR)
  2954. X#endif
  2955. X    Panic(0, "%s is not a directory.", SockPath);
  2956. X#ifdef MULTIUSER
  2957. X      if (multi)
  2958. X    {
  2959. X      if (st.st_uid != multi_uid)
  2960. X        Panic(0, "%s is not the owner of %s.", multi, SockPath);
  2961. X    }
  2962. X      else
  2963. X#endif
  2964. X    {
  2965. X      if (st.st_uid != real_uid)
  2966. X        Panic(0, "You are not the owner of %s.", SockPath);
  2967. X    }
  2968. X      if ((st.st_mode & 0777) != 0700)
  2969. X    Panic(0, "Directory %s must have mode 700.", SockPath);
  2970. X    }
  2971. X  strcat(SockPath, "/");
  2972. X  SockNamePtr = SockPath + strlen(SockPath);
  2973. X  (void) umask(oumask);
  2974. X  debug2("SockPath: %s  SockName: %s\n", SockPath, SockName ? SockName : "NULL");
  2975. X
  2976. X#if defined(SYSV) && !defined(ISC)
  2977. X  if (uname(&utsnam) == -1)
  2978. X    Panic(0, "uname() failed, errno = %d.", errno);
  2979. X  else
  2980. X    {
  2981. X      strncpy(HostName, utsnam.nodename, MAXSTR);
  2982. X      HostName[(sizeof(utsnam.nodename) <= MAXSTR) ? 
  2983. X               sizeof(utsnam.nodename) : MAXSTR] = '\0';
  2984. X    }
  2985. X#else
  2986. X  (void) gethostname(HostName, MAXSTR);
  2987. X#endif
  2988. X  HostName[MAXSTR - 1] = '\0';
  2989. X  if ((ap = index(HostName, '.')) != NULL)
  2990. X    *ap = '\0';
  2991. X
  2992. X  if (lsflag)
  2993. X    {
  2994. X      int i;
  2995. X
  2996. X#ifdef MULTIUSER
  2997. X      if (multi)
  2998. X    real_uid = multi_uid;
  2999. X      setuid(real_uid);
  3000. X      setgid(real_gid);
  3001. X      eff_uid = real_uid;
  3002. X      eff_gid = real_gid;
  3003. X#endif
  3004. X      i = FindSocket(0, (int *)NULL);
  3005. X      /* MakeClientSocket appended the last (Sock)Name there: */
  3006. X      *SockNamePtr = '\0';
  3007. X      if (i == 0)
  3008. X    {
  3009. X#ifdef NETHACK
  3010. X          if (nethackflag)
  3011. X        Panic(0, "This room is empty (%s).\n", SockPath);
  3012. X          else
  3013. X#endif /* NETHACK */
  3014. X          Panic(0, "No Sockets found in %s.\n", SockPath);
  3015. X        }
  3016. X      Panic(0, "%d Socket%s in %s.\n", i, i > 1 ? "s" : "", SockPath);
  3017. X      /* NOTREACHED */
  3018. X    }
  3019. X  signal(SIG_BYE, AttacherFinit);    /* prevent races */
  3020. X  if (rflag || xflag)
  3021. X    {
  3022. X      debug("screen -r: - is there anybody out there?\n");
  3023. X#ifdef SHADOWPW
  3024. X      setspent();  /* open shadow file while we are still root */
  3025. X#endif /* SHADOWPW */
  3026. X      if (Attach(MSG_ATTACH))
  3027. X    {
  3028. X      Attacher();
  3029. X      /* NOTREACHED */
  3030. X    }
  3031. X      debug("screen -r: backend not responding -- still crying\n");
  3032. X    }
  3033. X  else if (dflag && !mflag)
  3034. X    {
  3035. X      (void) Attach(MSG_DETACH);
  3036. X      Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : ""));
  3037. X      eexit(0);
  3038. X      /* NOTREACHED */
  3039. X    }
  3040. X  if (!SockName && !mflag)
  3041. X    {
  3042. X      register char *sty;
  3043. X      int s;
  3044. X
  3045. X      if ((sty = getenv("STY")) != 0 && *sty != '\0')
  3046. X    {
  3047. X      setuid(real_uid);
  3048. X      setgid(real_gid);
  3049. X      eff_uid = real_uid;
  3050. X      eff_gid = real_gid;
  3051. X      if ((s = MakeClientSocket(1, sty)) > 0)
  3052. X        {
  3053. X          nwin_options.args = av;
  3054. X          SendCreateMsg(s, &nwin);
  3055. X          close(s);
  3056. X        }
  3057. X      exit(0);
  3058. X      /* NOTREACHED */
  3059. X    }
  3060. X    }
  3061. X  nwin_compose(&nwin_default, &nwin_options, &nwin_default);
  3062. X  if (SockName && !*SockName)
  3063. X    SockName = NULL;
  3064. X  switch (MasterPid = fork())
  3065. X    {
  3066. X    case -1:
  3067. X      Panic(errno, "fork");
  3068. X      /* NOTREACHED */
  3069. X#ifdef FORKDEBUG
  3070. X    default:
  3071. X      break;
  3072. X    case 0:
  3073. X      MasterPid = getppid();
  3074. X#else
  3075. X    case 0:
  3076. X      break;
  3077. X    default:
  3078. X#endif
  3079. X      if (detached)
  3080. X        exit(0);
  3081. X      if (SockName)
  3082. X    {
  3083. X      /* user started us with -S option */
  3084. X      sprintf(socknamebuf, "%d.%s", MasterPid, SockName);
  3085. X    }
  3086. X      else
  3087. X    {
  3088. X      sprintf(socknamebuf, "%d.%s.%s", MasterPid, stripdev(attach_tty),
  3089. X          HostName);
  3090. X    }
  3091. X      for (ap = socknamebuf; *ap; ap++)
  3092. X    if (*ap == '/')
  3093. X      *ap = '-';
  3094. X      SockName = socknamebuf;
  3095. X#ifdef SHADOWPW
  3096. X      setspent();  /* open shadow file while we are still root */
  3097. X#endif /* SHADOWPW */
  3098. X      setuid(real_uid);
  3099. X      setgid(real_gid);
  3100. X      eff_uid = real_uid;
  3101. X      eff_gid = real_gid;
  3102. X      Attacher();
  3103. X      /* NOTREACHED */
  3104. X    }
  3105. X
  3106. X  ap = av0 + strlen(av0) - 1;
  3107. X  while (ap >= av0)
  3108. X    {
  3109. X      if (!strncmp("screen", ap, 6))
  3110. X    {
  3111. X      strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */
  3112. X      break;
  3113. X    }
  3114. X      ap--;
  3115. X    }
  3116. X  if (ap < av0)
  3117. X    *av0 = 'S';
  3118. X
  3119. X#ifdef DEBUG
  3120. X  if (dfp != stderr)
  3121. X    fclose(dfp);
  3122. X  if ((dfp = fopen("/tmp/debug/screen.back", "w")) == NULL)
  3123. X    dfp = stderr;
  3124. X  else
  3125. X    (void) chmod("/tmp/debug/screen.back", 0666);
  3126. X#endif
  3127. X  if (!detached)
  3128. X    n = dup(0);
  3129. X  else
  3130. X    n = -1;
  3131. X  freopen("/dev/null", "r", stdin);
  3132. X  freopen("/dev/null", "w", stdout);
  3133. X#ifdef DEBUG
  3134. X  if (dfp != stderr)
  3135. X#endif
  3136. X  freopen("/dev/null", "w", stderr);
  3137. X  debug("-- screen.back debug started\n");
  3138. X
  3139. X  if (!detached)
  3140. X    {
  3141. X#ifdef FORKDEBUG
  3142. X      if (MakeDisplay(LoginName, attach_tty, attach_term, n, MasterPid, &attach_Mode) == 0)
  3143. X#else
  3144. X      if (MakeDisplay(LoginName, attach_tty, attach_term, n, getppid(), &attach_Mode) == 0)
  3145. X#endif
  3146. X    Panic(0, "Could not alloc display");
  3147. X    }
  3148. X
  3149. X  if (SockName)
  3150. X    {
  3151. X      /* user started us with -S option */
  3152. X      sprintf(socknamebuf, "%d.%s", getpid(), SockName);
  3153. X    }
  3154. X  else
  3155. X    {
  3156. X      sprintf(socknamebuf, "%d.%s.%s", getpid(), stripdev(attach_tty),
  3157. X          HostName);
  3158. X    }
  3159. X  for (ap = socknamebuf; *ap; ap++)
  3160. X    if (*ap == '/')
  3161. X      *ap = '-';
  3162. X  SockName = socknamebuf;
  3163. X  ServerSocket = MakeServerSocket();
  3164. X#ifdef ETCSCREENRC
  3165. X  if ((ap = getenv("SYSSCREENRC")) == NULL)
  3166. X    StartRc(ETCSCREENRC);
  3167. X  else
  3168. X    StartRc(ap);
  3169. X#endif
  3170. X  StartRc(RcFileName);
  3171. X# ifdef UTMPOK
  3172. X#  ifndef UTNOKEEP
  3173. X  InitUtmp(); 
  3174. X#  endif /* UTNOKEEP */
  3175. X# endif /* UTMPOK */
  3176. X  if (display)
  3177. X    {
  3178. X      if (InitTermcap(0, 0))
  3179. X    {
  3180. X      debug("Could not init termcap - exiting\n");
  3181. X      fcntl(d_userfd, F_SETFL, 0);    /* Flush sets NDELAY */
  3182. X      freetty();
  3183. X      if (d_userpid)
  3184. X        Kill(d_userpid, SIG_BYE);
  3185. X      eexit(1);
  3186. X    }
  3187. X      InitTerm(0);
  3188. X#ifdef UTMPOK
  3189. X      RemoveLoginSlot();
  3190. X#endif
  3191. X    }
  3192. X  else
  3193. X    {
  3194. X      MakeTermcap(1);
  3195. X    }
  3196. X#ifdef LOADAV
  3197. X  InitLoadav();
  3198. X#endif /* LOADAV */
  3199. X  MakeNewEnv();
  3200. X  signal(SIGHUP, SigHup);
  3201. X  signal(SIGINT, Finit);
  3202. X  signal(SIGQUIT, Finit);
  3203. X  signal(SIGTERM, Finit);
  3204. X#ifdef BSDJOBS
  3205. X  signal(SIGTTIN, SIG_IGN);
  3206. X  signal(SIGTTOU, SIG_IGN);
  3207. X#endif
  3208. X  InitKeytab();
  3209. X  if (display)
  3210. X    {
  3211. X      brktty(d_userfd);
  3212. X      SetMode(&d_OldMode, &d_NewMode);
  3213. X      /* Note: SetMode must be called _before_ FinishRc. */
  3214. X      SetTTY(d_userfd, &d_NewMode);
  3215. X      if (fcntl(d_userfd, F_SETFL, FNDELAY))
  3216. X    Msg(errno, "Warning: NDELAY fcntl failed");
  3217. X    }
  3218. X  else
  3219. X    brktty(-1);        /* just try */
  3220. X#ifdef ETCSCREENRC
  3221. X  if ((ap = getenv("SYSSCREENRC")) == NULL)
  3222. X    FinishRc(ETCSCREENRC);
  3223. X  else
  3224. X    FinishRc(ap);
  3225. X#endif
  3226. X  FinishRc(RcFileName);
  3227. X
  3228. X  debug2("UID %d  EUID %d\n", getuid(), geteuid());
  3229. X  if (windows == NULL)
  3230. X    {
  3231. X      debug("We open one default window, as screenrc did not specify one.\n");
  3232. X      if (MakeWindow(&nwin) == -1)
  3233. X    {
  3234. X      AddStr("Sorry, could not find a PTY.");
  3235. X      sleep(2);
  3236. X      Finit(0);
  3237. X      /* NOTREACHED */
  3238. X    }
  3239. X    }
  3240. X  if (default_startup)
  3241. X    display_copyright();
  3242. X  signal(SIGCHLD, SigChld);
  3243. X  signal(SIGINT, SigInt);
  3244. X  tv.tv_usec = 0;
  3245. X  if (rflag == 2)
  3246. X    {
  3247. X#ifdef NETHACK
  3248. X      if (nethackflag)
  3249. X        Msg(0, "I can't seem to find a... Hey, wait a minute!  Here comes a screen now.");
  3250. X      else
  3251. X#endif
  3252. X      Msg(0, "New screen...");
  3253. X      rflag = 0;
  3254. X    }
  3255. X
  3256. X  Now = time((time_t *)0);
  3257. X
  3258. X  for (;;)
  3259. X    {
  3260. X      tv.tv_sec = 0;
  3261. X      /*
  3262. X       * check for silence
  3263. X       */
  3264. X      for (p = windows; p; p = p->w_next)
  3265. X        {
  3266. X      int time_left;
  3267. X
  3268. X      if (p->w_tstamp.seconds == 0)
  3269. X        continue;
  3270. X      debug1("checking silence win %d\n", p->w_number);
  3271. X      time_left = p->w_tstamp.lastio + p->w_tstamp.seconds - Now;
  3272. X      if (time_left > 0)
  3273. X        {
  3274. X          if (tv.tv_sec == 0 || time_left < tv.tv_sec)
  3275. X            tv.tv_sec = time_left;
  3276. X        }
  3277. X      else
  3278. X        {
  3279. X          for (display = displays; display; display = display->_d_next)
  3280. X            if (p != d_fore)
  3281. X          Msg(0, "Window %d: silence for %d seconds", 
  3282. X              p->w_number, p->w_tstamp.seconds);
  3283. X          p->w_tstamp.lastio = Now;
  3284. X        }
  3285. X    }
  3286. X
  3287. X      /*
  3288. X       * check to see if message line should be removed
  3289. X       */
  3290. X      for (display = displays; display; display = display->_d_next)
  3291. X    {
  3292. X      int time_left;
  3293. X
  3294. X      if (d_status == 0)
  3295. X        continue;
  3296. X      debug("checking status...\n");
  3297. X      time_left = d_status_time + (d_status_bell?VBellWait:MsgWait) - Now;
  3298. X      if (time_left > 0)
  3299. X        {
  3300. X          if (tv.tv_sec == 0 || time_left < tv.tv_sec)
  3301. X            tv.tv_sec = time_left;
  3302. X          debug(" not yet.\n");
  3303. X        }
  3304. X      else
  3305. X        {
  3306. X          debug(" removing now.\n");
  3307. X          RemoveStatus();
  3308. X        }
  3309. X    }
  3310. X      /*
  3311. X       * check for I/O on all available I/O descriptors
  3312. X       */
  3313. X#ifdef DEBUG
  3314. X      if (tv.tv_sec)
  3315. X        debug1("select timeout %d seconds\n", tv.tv_sec);
  3316. X#endif
  3317. X      mkfdsets(&r, &w);
  3318. X      if (GotSigChld && !tv.tv_sec)
  3319. X    {
  3320. X      SigChldHandler();
  3321. X      continue;
  3322. X    }
  3323. X      if ((nsel = select(FD_SETSIZE, &r, &w, (fd_set *)0, tv.tv_sec ? &tv : (struct timeval *) 0)) < 0)
  3324. X    {
  3325. X      debug1("Bad select - errno %d\n", errno);
  3326. X      if (errno != EINTR)
  3327. X        Panic(errno, "select");
  3328. X      errno = 0;
  3329. X      nsel = 0;
  3330. X    }
  3331. X#ifdef SELECT_BROKEN
  3332. X      /* 
  3333. X       * Sequents select emulation counts an descriptor which is
  3334. X       * readable and writeable only as one. waaaaa.
  3335. X       */
  3336. X      if (nsel)
  3337. X    nsel = 2 * FD_SETSIZE;
  3338. X#endif
  3339. X      if (GotSigChld && !tv.tv_sec)
  3340. X    {
  3341. X      SigChldHandler();
  3342. X      continue;
  3343. X    }
  3344. X      if (InterruptPlease)
  3345. X    {
  3346. X      debug("Backend received interrupt\n");
  3347. X      if (fore)
  3348. X        {
  3349. X          char ibuf;
  3350. X          ibuf = intrc;
  3351. X#ifdef PSEUDOS
  3352. X          write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd, 
  3353. X            &ibuf, 1);
  3354. X          debug1("Backend wrote interrupt to %d", fore->w_number);
  3355. X          debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : "");
  3356. X#else
  3357. X          write(fore->w_ptyfd, &ibuf, 1);
  3358. X          debug1("Backend wrote interrupt to %d\n", fore->w_number);
  3359. X#endif
  3360. X        }
  3361. X      InterruptPlease = 0;
  3362. X    }
  3363. X
  3364. X      /*
  3365. X       *   Process a client connect attempt and message
  3366. X       */
  3367. X      if (nsel && FD_ISSET(ServerSocket, &r))
  3368. X    {
  3369. X          nsel--;
  3370. X      debug("Knock - knock!\n");
  3371. X      ReceiveMsg();
  3372. X      continue;
  3373. X    }
  3374. X
  3375. X      /*
  3376. X       * Write the (already processed) user input to the window
  3377. X       * descriptors first. We do not want to choke, if he types fast.
  3378. X       */
  3379. X      if (nsel)
  3380. X    {
  3381. X      for (p = windows; p; p = p->w_next)
  3382. X        {
  3383. X          int pastefd = -1;
  3384. X#ifdef COPY_PASTE
  3385. X          if (p->w_pastelen)
  3386. X        {
  3387. X          /*
  3388. X           *  Write the copybuffer contents first, if any.
  3389. X           */
  3390. X#ifdef PSEUDOS
  3391. X          pastefd = W_UWP(p) ? p->w_pwin->p_ptyfd : p->w_ptyfd;
  3392. X#else
  3393. X          pastefd = p->w_ptyfd;
  3394. X#endif
  3395. X          if (FD_ISSET(pastefd, &w))
  3396. X            {
  3397. X              debug1("writing pastebuffer (%d)\n", p->w_pastelen);
  3398. X              len = write(pastefd, p->w_pastebuffer, 
  3399. X                          (slowpaste > 0) ? 1 :
  3400. X                  (p->w_pastelen > IOSIZE ? 
  3401. X                   IOSIZE : p->w_pastelen));
  3402. X              if (len < 0)    /* Problems... window is dead */
  3403. X            p->w_pastelen = 0;
  3404. X              if (len > 0)
  3405. X            {
  3406. X              p->w_pastebuffer += len;
  3407. X              p->w_pastelen -= len;
  3408. X            }
  3409. X              debug1("%d bytes pasted\n", len);
  3410. X              if (slowpaste > 0)
  3411. X            {
  3412. X              struct timeval t;
  3413. X
  3414. X              debug1("slowpaste %d\n", slowpaste);
  3415. X              t.tv_sec = (long) (slowpaste / 1000);
  3416. X              t.tv_usec = (long) ((slowpaste % 1000) * 1000);
  3417. X              select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
  3418. X            }
  3419. X              if (--nsel == 0)
  3420. X                break;
  3421. X              if (p->w_pastelen == 0)
  3422. X            pastefd = -1;
  3423. X            }
  3424. X        }
  3425. X#endif
  3426. X
  3427. X#ifdef PSEUDOS
  3428. X          if (p->w_pwin && p->w_pwin->p_inlen > 0)
  3429. X            {
  3430. X          /* stuff w_pwin->p_inbuf into pseudowin */
  3431. X          tmp = p->w_pwin->p_ptyfd;
  3432. X          if (tmp != pastefd && FD_ISSET(tmp, &w))
  3433. X            {
  3434. X              if ((len = write(tmp, p->w_pwin->p_inbuf, 
  3435. X                       p->w_pwin->p_inlen)) > 0)
  3436. X                {
  3437. X              if ((p->w_pwin->p_inlen -= len))
  3438. X                bcopy(p->w_pwin->p_inbuf + len, p->w_pwin->p_inbuf,
  3439. X                      p->w_pwin->p_inlen);
  3440. X            }
  3441. X              if (--nsel == 0)
  3442. X                break;
  3443. X            }
  3444. X        }
  3445. X#endif
  3446. X          if (p->w_inlen > 0)
  3447. X        {
  3448. X          /* stuff w_inbuf buffer into window */
  3449. X          tmp = p->w_ptyfd;
  3450. X          if (tmp != pastefd && FD_ISSET(tmp, &w))
  3451. X            {
  3452. X              if ((len = write(tmp, p->w_inbuf, p->w_inlen)) > 0)
  3453. X            {
  3454. X              if ((p->w_inlen -= len))
  3455. X                bcopy(p->w_inbuf + len, p->w_inbuf, p->w_inlen);
  3456. X            }
  3457. X              if (--nsel == 0)
  3458. X            break;
  3459. X            }
  3460. X        }
  3461. X        }
  3462. X    }
  3463. X      
  3464. X      Now = time((time_t *)0);
  3465. X
  3466. X      if (nsel)
  3467. X    {
  3468. X      for (display = displays; display; display = ndisplay)
  3469. X        {
  3470. X          int maxlen;
  3471. X
  3472. X          ndisplay = display->_d_next;
  3473. X          /* 
  3474. X           * stuff d_obuf into user's tty
  3475. X           */
  3476. X          if (FD_ISSET(d_userfd, &w)) 
  3477. X        {
  3478. X          int size = OUTPUT_BLOCK_SIZE;
  3479. X
  3480. X          len = d_obufp - d_obuf;
  3481. X          if (len < size)
  3482. X            size = len;
  3483. X          ASSERT(len >= 0);
  3484. X          size = write(d_userfd, d_obuf, size);
  3485. X          if (size >= 0) 
  3486. X            {
  3487. X              len -= size;
  3488. X              if (len)
  3489. X                {
  3490. X              bcopy(d_obuf + size, d_obuf, len);
  3491. X                  debug2("ASYNC: wrote %d - remaining %d\n", size, len);
  3492. X            }
  3493. X              d_obufp -= size;
  3494. X              d_obuffree += size;
  3495. X            } 
  3496. X          else
  3497. X            {
  3498. X              if (errno != EINTR)
  3499. X# ifdef EWOULDBLOCK
  3500. X            if (errno != EWOULDBLOCK)
  3501. X# endif
  3502. X            Msg(errno, "Error writing output to display");
  3503. X            }
  3504. X          if (--nsel == 0)
  3505. X            break;
  3506. X        }
  3507. X          /*
  3508. X           * O.k. All streams are fed, now look what comes back
  3509. X           * to us. First of all: user input.
  3510. X           */
  3511. X          if (! FD_ISSET(d_userfd, &r))
  3512. X        continue;
  3513. X          if (d_status && !(use_hardstatus && HS))
  3514. X        RemoveStatus();
  3515. X          if (d_fore == 0)
  3516. X        maxlen = IOSIZE;
  3517. X          else
  3518. X        {
  3519. X#ifdef PSEUDOS
  3520. X          if (W_UWP(d_fore))
  3521. X            maxlen = sizeof(d_fore->w_pwin->p_inbuf) - d_fore->w_pwin->p_inlen;
  3522. X          else
  3523. X#endif
  3524. X            maxlen = sizeof(d_fore->w_inbuf) - d_fore->w_inlen;
  3525. X        }
  3526. X          if (maxlen > IOSIZE)
  3527. X        maxlen = IOSIZE;
  3528. X          if (maxlen <= 0)
  3529. X        maxlen = 1;    /* Allow one char for command keys */
  3530. X          if (d_ESCseen)
  3531. X        {
  3532. X          if (maxlen == 1)
  3533. X            maxlen = 2;    /* Allow one char for command keys */
  3534. X          buf[0] = Esc;
  3535. X          buflen = read(d_userfd, buf + 1, maxlen - 1) + 1;
  3536. X          d_ESCseen = 0;
  3537. X        }
  3538. X          else
  3539. X        buflen = read(d_userfd, buf, maxlen);
  3540. X          if (buflen < 0)
  3541. X        {
  3542. X          if (errno == EINTR)
  3543. X            continue;
  3544. X          debug1("Read error: %d - SigHup()ing!\n", errno);
  3545. X          SigHup(SIGARG);
  3546. X          sleep(1);
  3547. X        }
  3548. X          else if (buflen == 0)
  3549. X        {
  3550. X          debug("Found EOF - SigHup()ing!\n");
  3551. X          SigHup(SIGARG);
  3552. X          sleep(1);
  3553. X        }
  3554. X          else
  3555. X        {
  3556. X              /* This refills inbuf or p_inbuf */
  3557. X              ProcessInput(buf, buflen);
  3558. X        }
  3559. X          if (--nsel == 0)
  3560. X        break;
  3561. X        }
  3562. X    }
  3563. X    
  3564. X      /* 
  3565. X       * Read and process the output from the window descriptors 
  3566. X       */ 
  3567. X      for (p = windows; p; p = p->w_next) 
  3568. X    {
  3569. X      if (p->w_lay->l_block)
  3570. X        continue;
  3571. X      display = p->w_display;
  3572. X      if (p->w_outlen)
  3573. X        WriteString(p, p->w_outbuf, p->w_outlen);
  3574. X      else 
  3575. X        {
  3576. X#ifdef PSEUDOS
  3577. X          /* gather pseudowin output */
  3578. X          if (W_RP(p) && nsel && FD_ISSET(p->w_pwin->p_ptyfd, &r))
  3579. X            {
  3580. X          nsel--;
  3581. X          n = 0;
  3582. X          if (W_PTOW(p))
  3583. X            {
  3584. X              /* Window wants a copy of the pseudowin output */
  3585. X              tmp = sizeof(p->w_inbuf) - p->w_inlen;
  3586. X              ASSERT(tmp > 0);
  3587. X              n++;
  3588. X            }
  3589. X          else
  3590. X            tmp = IOSIZE;
  3591. X          if ((len = read(p->w_pwin->p_ptyfd, buf, tmp)) <= 0)
  3592. X            {
  3593. X              if (errno != EINTR)
  3594. X#ifdef EWOULDBLOCK
  3595. X                if (errno != EWOULDBLOCK)
  3596. X#endif
  3597. X              {
  3598. X                debug2("Window %d: pseudowin read error (errno %d) -- removing pseudowin\n", p->w_number, len ? errno : 0);
  3599. X                FreePseudowin(p);
  3600. X              }
  3601. X            }
  3602. X/* HERE WE ASSUME THAT THERE IS NO PACKET MODE ON PSEUDOWINS */
  3603. X          else
  3604. X            {
  3605. X              if (n)
  3606. X            {
  3607. X              bcopy(buf, p->w_inbuf + p->w_inlen, len);
  3608. X              p->w_inlen += len;
  3609. X            }
  3610. X              WriteString(p, buf, len);
  3611. X            }
  3612. X        }
  3613. X#endif /* PSEUDOS */
  3614. X          /* gather window output */
  3615. X          if (nsel && FD_ISSET(p->w_ptyfd, &r))
  3616. X        {
  3617. X          nsel--;
  3618. X#ifdef PSEUDOS
  3619. X          n = 0;
  3620. X          ASSERT(W_RW(p));
  3621. X          if (p->w_pwin && W_WTOP(p))
  3622. X            {
  3623. X              /* Pseudowin wants a copy of the window output */
  3624. X              tmp = sizeof(p->w_pwin->p_inbuf) - p->w_pwin->p_inlen;
  3625. X              ASSERT(tmp > 0);
  3626. X              n++;
  3627. X            }
  3628. X          else
  3629. X#endif
  3630. X            tmp = IOSIZE;
  3631. X          if ((len = read(p->w_ptyfd, buf, tmp)) <= 0)
  3632. X            {
  3633. X              if (errno == EINTR)
  3634. X            continue;
  3635. X#ifdef EWOULDBLOCK
  3636. X              if (errno == EWOULDBLOCK)
  3637. X            continue;
  3638. X#endif
  3639. X              debug2("Window %d: read error (errno %d) - killing window\n", p->w_number, len ? errno : 0);
  3640. X              KillWindow(p);
  3641. X              nsel = 0;    /* KillWindow may change window order */
  3642. X              break;    /* so we just break */
  3643. X            }
  3644. X#ifdef TIOCPKT
  3645. X          if ((p->w_t.flags & TTY_FLAG_PLAIN) == 0)
  3646. X            {
  3647. X              if (buf[0])
  3648. X            {
  3649. X              debug1("PAKET %x\n", buf[0]);
  3650. X              if (buf[0] & TIOCPKT_NOSTOP)
  3651. X                NewAutoFlow(p, 0);
  3652. X              if (buf[0] & TIOCPKT_DOSTOP)
  3653. X                NewAutoFlow(p, 1);
  3654. X            }
  3655. X              if (len > 1)
  3656. X            {
  3657. X#ifdef PSEUDOS
  3658. X              if (n)
  3659. X                {
  3660. X                  bcopy(buf + 1, 
  3661. X                    p->w_pwin->p_inbuf + p->w_pwin->p_inlen,
  3662. X                    len - 1);
  3663. X                  p->w_pwin->p_inlen += len - 1;
  3664. X                }
  3665. X#endif
  3666. X              WriteString(p, buf + 1, len - 1);
  3667. X            }
  3668. X            }
  3669. X          else
  3670. X#endif /* TIOCPKT */
  3671. X            {
  3672. X              if (len > 0)
  3673. X            {
  3674. X#ifdef PSEUDOS
  3675. X              if (n)
  3676. X                {
  3677. X                  bcopy(buf, p->w_pwin->p_inbuf + p->w_pwin->p_inlen,
  3678. X                    len);
  3679. X                  p->w_pwin->p_inlen += len;
  3680. X                }
  3681. X#endif
  3682. X              WriteString(p, buf, len);
  3683. X            }
  3684. X            }
  3685. X        }
  3686. X        }
  3687. X      if (p->w_bell == BELL_ON)
  3688. X        {
  3689. X          p->w_bell = BELL_MSG;
  3690. X          for (display = displays; display; display = display->_d_next)
  3691. X            Msg(0, MakeWinMsg(BellString, p->w_number));
  3692. X          if (p->w_monitor == MON_FOUND)
  3693. X        p->w_monitor = MON_DONE;
  3694. X        }
  3695. X      else if (p->w_bell == BELL_VISUAL)
  3696. X        {
  3697. X          if (display && !d_status_bell)
  3698. X        {
  3699. X          /*
  3700. X           * Stop the '!' appearing in the ^A^W display if it is an 
  3701. X           * active at the time of the bell. (Tim MacKenzie)
  3702. X           */
  3703. X          p->w_bell = BELL_OFF; 
  3704. X          Msg(0, VisualBellString);
  3705. X          if (d_status)
  3706. X            d_status_bell = 1;
  3707. X        }
  3708. X        }
  3709. X      if (p->w_monitor == MON_FOUND)
  3710. X        {
  3711. X          p->w_monitor = MON_MSG;
  3712. X          for (display = displays; display; display = display->_d_next)
  3713. X            Msg(0, MakeWinMsg(ActivityString, p->w_number));
  3714. X        }
  3715. X    }
  3716. X#if defined(DEBUG) && !defined(_SEQUENT_)
  3717. X      if (nsel)
  3718. X    debug1("*** Left over nsel: %d\n", nsel);
  3719. X#endif
  3720. X    }
  3721. X  /* NOTREACHED */
  3722. X}
  3723. X
  3724. Xstatic void
  3725. XSigChldHandler()
  3726. X{
  3727. X  struct stat st;
  3728. X  while (GotSigChld)
  3729. X    {
  3730. X      GotSigChld = 0;
  3731. X      DoWait();
  3732. X#ifdef SYSVSIGS
  3733. X      signal(SIGCHLD, SigChld);
  3734. X#endif
  3735. X    }
  3736. X  if (stat(SockPath, &st) == -1)
  3737. X    {
  3738. X      debug1("SigChldHandler: Yuck! cannot stat '%s'\n", SockPath);
  3739. X      if (!RecoverSocket())
  3740. X    {
  3741. X      debug("SCREEN cannot recover from corrupt Socket, bye\n");
  3742. X      Finit(1);
  3743. X    }
  3744. X      else
  3745. X    debug1("'%s' reconstructed\n", SockPath);
  3746. X    }
  3747. X  else
  3748. X    debug2("SigChldHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode);
  3749. X}
  3750. X
  3751. Xstatic sig_t
  3752. XSigChld(SIGDEFARG)
  3753. X{
  3754. X  debug("SigChld()\n");
  3755. X  GotSigChld = 1;
  3756. X#ifndef SIGVOID
  3757. X  return((sig_t) 0);
  3758. X#endif
  3759. X}
  3760. X
  3761. Xsig_t
  3762. XSigHup(SIGDEFARG)
  3763. X{
  3764. X  if (display == 0)
  3765. X    return;
  3766. X  debug("SigHup()\n");
  3767. X  if (d_userfd >= 0)
  3768. X    {
  3769. X      close(d_userfd);
  3770. X      d_userfd = -1;
  3771. X    }
  3772. X  if (auto_detach || displays->_d_next)
  3773. X    Detach(D_DETACH);
  3774. X  else
  3775. X    Finit(0);
  3776. X#ifndef SIGVOID
  3777. X  return((sig_t) 0);
  3778. X#endif
  3779. X}
  3780. X
  3781. X/* 
  3782. X * the backend's Interrupt handler
  3783. X * we cannot d_insert the intrc directly, as we never know
  3784. X * if fore is valid.
  3785. X */
  3786. Xstatic sig_t
  3787. XSigInt(SIGDEFARG)
  3788. X{
  3789. X#if HAZARDOUS
  3790. X  char buf[1];
  3791. X
  3792. X  debug("SigInt()\n");
  3793. X  *buf = (char) intrc;
  3794. X  if (fore)
  3795. X    fore->w_inlen = 0;
  3796. X  if (fore)
  3797. X    write(fore->w_ptyfd, buf, 1);
  3798. X#else
  3799. X  signal(SIGINT, SigInt);
  3800. X  debug("SigInt() careful\n");
  3801. X  InterruptPlease = 1;
  3802. X#endif
  3803. X#ifndef SIGVOID
  3804. X  return((sig_t) 0);
  3805. X#endif
  3806. X}
  3807. X
  3808. Xstatic sig_t
  3809. XCoreDump(sig)
  3810. Xint sig;
  3811. X{
  3812. X  struct display *disp;
  3813. X  char buf[80];
  3814. X
  3815. X#ifdef SYSVSIGS
  3816. X  signal(sig, SIG_IGN);
  3817. X#endif /* SYSV */
  3818. X  setgid(getgid());
  3819. X  setuid(getuid());
  3820. X  unlink("core");
  3821. X  sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sig,
  3822. X#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
  3823. X              ""
  3824. X#else /* SHADOWPW  && !DEBUG */
  3825. X              " (core dumped)"
  3826. X#endif /* SHADOWPW  && !DEBUG */
  3827. X              );
  3828. X  for (disp = displays; disp; disp = disp->_d_next)
  3829. X    {
  3830. X      fcntl(disp->_d_userfd, F_SETFL, 0);
  3831. X      write(disp->_d_userfd, buf, strlen(buf));
  3832. X      Kill(disp->_d_userpid, SIG_BYE);
  3833. X    }
  3834. X#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
  3835. X  eexit(sig);
  3836. X#else /* SHADOWPW && !DEBUG */
  3837. X  abort();
  3838. X#endif /* SHADOWPW  && !DEBUG */
  3839. X#ifndef SIGVOID
  3840. X  return((sig_t) 0);
  3841. X#endif
  3842. X}
  3843. X
  3844. Xstatic void
  3845. XDoWait()
  3846. X{
  3847. X  register int pid;
  3848. X  struct win *p, *next;
  3849. X#ifdef BSDWAIT
  3850. X  union wait wstat;
  3851. X#else
  3852. X  int wstat;
  3853. X#endif
  3854. X
  3855. X#ifdef BSDJOBS
  3856. X# ifndef BSDWAIT
  3857. X  while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0)
  3858. X# else
  3859. X# ifdef USE_WAIT2
  3860. X  /* 
  3861. X   * From: rouilj@sni-usa.com (John Rouillard) 
  3862. X   * note that WUNTRACED is not documented to work, but it is defined in
  3863. X   * /usr/include/sys/wait.h, so it may work 
  3864. X   */
  3865. X  while ((pid = wait2(&wstat, WNOHANG | WUNTRACED )) > 0)
  3866. X#  else /* USE_WAIT2 */
  3867. X  while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0)
  3868. X#  endif /* USE_WAIT2 */
  3869. X# endif
  3870. X#else    /* BSDJOBS */
  3871. X  while ((pid = wait(&wstat)) < 0)
  3872. X    if (errno != EINTR)
  3873. X      break;
  3874. X  if (pid > 0)
  3875. X#endif    /* BSDJOBS */
  3876. X    {
  3877. X      for (p = windows; p; p = next)
  3878. X    {
  3879. X      next = p->w_next;
  3880. X      if (pid == p->w_pid)
  3881. X        {
  3882. X#ifdef BSDJOBS
  3883. X          if (WIFSTOPPED(wstat))
  3884. X        {
  3885. X          debug3("Window %d pid %d: WIFSTOPPED (sig %d)\n", p->w_number, p->w_pid, WSTOPSIG(wstat));
  3886. X#ifdef SIGTTIN
  3887. X          if (WSTOPSIG(wstat) == SIGTTIN)
  3888. X            {
  3889. X              Msg(0, "Suspended (tty input)");
  3890. X              continue;
  3891. X            }
  3892. X#endif
  3893. X#ifdef SIGTTOU
  3894. X          if (WSTOPSIG(wstat) == SIGTTOU)
  3895. X            {
  3896. X              Msg(0, "Suspended (tty output)");
  3897. X              continue;
  3898. X            }
  3899. X#endif
  3900. X          /* Try to restart process */
  3901. X# ifdef NETHACK    
  3902. X                  if (nethackflag)
  3903. X            Msg(0, "You regain consciousness.");
  3904. X          else
  3905. X# endif /* NETHACK */
  3906. X          Msg(0, "Child has been stopped, restarting.");
  3907. X          if (killpg(p->w_pid, SIGCONT))
  3908. X            kill(p->w_pid, SIGCONT);
  3909. X        }
  3910. X          else
  3911. X#endif
  3912. X        KillWindow(p);
  3913. X          break;
  3914. X        }
  3915. X#ifdef PSEUDOS
  3916. X      if (p->w_pwin && pid == p->w_pwin->p_pid)
  3917. X        {
  3918. X          debug2("pseudo of win Nr %d died. pid == %d\n", p->w_number, p->w_pwin->p_pid);
  3919. X          FreePseudowin(p);
  3920. X          break;
  3921. X        }
  3922. X#endif
  3923. X    }
  3924. X      if (p == 0)
  3925. X    {
  3926. X      debug1("pid %d not found - hope that's ok\n", pid);
  3927. X    }
  3928. X    }
  3929. X}
  3930. X
  3931. X
  3932. Xsig_t
  3933. XFinit(i)
  3934. Xint i;
  3935. X{
  3936. X  struct win *p, *next;
  3937. X
  3938. X  signal(SIGCHLD, SIG_IGN);
  3939. X  signal(SIGHUP, SIG_IGN);
  3940. X  debug1("Finit(%d);\n", i);
  3941. X  for (p = windows; p; p = next)
  3942. X    {
  3943. X      next = p->w_next;
  3944. X      FreeWindow(p);
  3945. X    }
  3946. X  if (ServerSocket != -1)
  3947. X    {
  3948. X      debug1("we unlink(%s)\n", SockPath);
  3949. X#ifndef NOREUID
  3950. X      setreuid(eff_uid, real_uid);
  3951. X      setregid(eff_gid, real_gid);
  3952. X#endif
  3953. X      (void) unlink(SockPath);
  3954. X#ifndef NOREUID
  3955. X      setreuid(real_uid, eff_uid);
  3956. X      setregid(real_gid, eff_gid);
  3957. X#endif
  3958. X    }
  3959. X  for (display = displays; display; display = display->_d_next)
  3960. X    {
  3961. X      if (d_status)
  3962. X    RemoveStatus();
  3963. X      FinitTerm();
  3964. X#ifdef UTMPOK
  3965. X      RestoreLoginSlot();
  3966. X#endif
  3967. X      AddStr("[screen is terminating]\r\n");
  3968. X      Flush();
  3969. X      SetTTY(d_userfd, &d_OldMode);
  3970. X      fcntl(d_userfd, F_SETFL, 0);
  3971. X      freetty();
  3972. X      Kill(d_userpid, SIG_BYE);
  3973. X    }
  3974. X  /*
  3975. X   * we _cannot_ call eexit(i) here, 
  3976. X   * instead of playing with the Socket above. Sigh.
  3977. X   */
  3978. X  exit(i);
  3979. X#ifndef SIGVOID
  3980. X  return((sig_t) 0);
  3981. X#endif
  3982. X}
  3983. X
  3984. Xvoid
  3985. Xeexit(e)
  3986. Xint e;
  3987. X{
  3988. X  if (ServerSocket != -1)
  3989. X    {
  3990. X      debug1("we unlink(%s)\n", SockPath);
  3991. X      setuid(real_uid);
  3992. X      setgid(real_gid);
  3993. X      (void) unlink(SockPath);
  3994. X    }
  3995. X  exit(e);
  3996. X}
  3997. X
  3998. X
  3999. X/*
  4000. X * Detach now has the following modes:
  4001. X *    D_DETACH    SIG_BYE        detach backend and exit attacher
  4002. X *    D_STOP        SIG_STOP    stop attacher (and detach backend)
  4003. X *    D_REMOTE    SIG_BYE        remote detach -- reattach to new attacher
  4004. X *    D_POWER     SIG_POWER_BYE     power detach -- attacher kills his parent
  4005. X *    D_REMOTE_POWER    SIG_POWER_BYE    remote power detach -- both
  4006. X *    D_LOCK        SIG_LOCK    lock the attacher
  4007. X * (jw)
  4008. X * we always remove our utmp slots. (even when "lock" or "stop")
  4009. X * Note: Take extra care here, we may be called by interrupt!
  4010. X */
  4011. Xvoid
  4012. XDetach(mode)
  4013. Xint mode;
  4014. X{
  4015. X  int sign = 0, pid;
  4016. X#ifdef UTMPOK
  4017. X  struct win *p;
  4018. X#endif
  4019. X
  4020. X  if (display == 0)
  4021. X    return;
  4022. X  signal(SIGHUP, SIG_IGN);
  4023. X  debug1("Detach(%d)\n", mode);
  4024. X  if (d_status)
  4025. X    RemoveStatus();
  4026. X  FinitTerm();
  4027. X  switch (mode)
  4028. X    {
  4029. X    case D_DETACH:
  4030. X      AddStr("[detached]\r\n");
  4031. X      sign = SIG_BYE;
  4032. X      break;
  4033. X#ifdef BSDJOBS
  4034. X    case D_STOP:
  4035. X      sign = SIG_STOP;
  4036. X      break;
  4037. X#endif
  4038. X#ifdef REMOTE_DETACH
  4039. X    case D_REMOTE:
  4040. X      AddStr("[remote detached]\r\n");
  4041. X      sign = SIG_BYE;
  4042. X      break;
  4043. X#endif
  4044. X#ifdef POW_DETACH
  4045. X    case D_POWER:
  4046. X      AddStr("[power detached]\r\n");
  4047. X      if (PowDetachString) 
  4048. X    {
  4049. X      AddStr(expand_vars(PowDetachString));
  4050. X      AddStr("\r\n");
  4051. X    }
  4052. X      sign = SIG_POWER_BYE;
  4053. X      break;
  4054. X#ifdef REMOTE_DETACH
  4055. X    case D_REMOTE_POWER:
  4056. X      AddStr("[remote power detached]\r\n");
  4057. X      if (PowDetachString) 
  4058. X    {
  4059. X      AddStr(expand_vars(PowDetachString));
  4060. X      AddStr("\r\n");
  4061. X    }
  4062. X      sign = SIG_POWER_BYE;
  4063. X      break;
  4064. X#endif
  4065. X#endif
  4066. X    case D_LOCK:
  4067. X      ClearDisplay();
  4068. X      sign = SIG_LOCK;
  4069. X      /* tell attacher to lock terminal with a lockprg. */
  4070. X      break;
  4071. X    }
  4072. X#ifdef UTMPOK
  4073. X  if (displays->_d_next == 0)
  4074. X    {
  4075. X      for (p = windows; p; p = p->w_next)
  4076. X    if (p->w_slot != (slot_t) -1)
  4077. X      {
  4078. X        RemoveUtmp(p);
  4079. X        /*
  4080. X         * Set the slot to 0 to get the window
  4081. X         * logged in again.
  4082. X         */
  4083. X        p->w_slot = (slot_t) 0;
  4084. X      }
  4085. X      if (console_window)
  4086. X    {
  4087. X      if (TtyGrabConsole(console_window->w_ptyfd, 0, "detach"))
  4088. X        {
  4089. X          debug("could not release console - killing window\n");
  4090. X          KillWindow(console_window);
  4091. X          display = displays;
  4092. X        }
  4093. X    }
  4094. X    }
  4095. X  RestoreLoginSlot();
  4096. X#endif
  4097. X  if (d_fore)
  4098. X    {
  4099. X      d_fore->w_active = 0;
  4100. X      d_fore->w_display = 0;
  4101. X      d_lay = &BlankLayer;
  4102. X      d_layfn = d_lay->l_layfn;
  4103. X    }
  4104. X  while (d_lay != &BlankLayer)
  4105. X    ExitOverlayPage();
  4106. X  if (d_userfd >= 0)
  4107. X    {
  4108. X      Flush();
  4109. X      SetTTY(d_userfd, &d_OldMode);
  4110. X      fcntl(d_userfd, F_SETFL, 0);
  4111. X    }
  4112. X  freetty();
  4113. X  pid = d_userpid;
  4114. X  debug2("display: %#x displays: %#x\n", (unsigned int)display, (unsigned int)displays);
  4115. X  FreeDisplay();
  4116. X  if (displays == 0)
  4117. X    /* Flag detached-ness */
  4118. X    (void) chsock();
  4119. X  /*
  4120. X   * tell father to father what to do. We do that after we
  4121. X   * freed the tty, thus getty feels more comfortable on hpux
  4122. X   * if it was a power detach.
  4123. X   */
  4124. X  Kill(pid, sign);
  4125. X  debug2("Detach: Signal %d to Attacher(%d)!\n", sign, pid);
  4126. X  debug("Detach returns, we are successfully detached.\n");
  4127. X  signal(SIGHUP, SigHup);
  4128. X}
  4129. X
  4130. Xstatic int
  4131. XIsSymbol(e, s)
  4132. Xregister char *e, *s;
  4133. X{
  4134. X  register int l;
  4135. X
  4136. X  l = strlen(s);
  4137. X  return strncmp(e, s, l) == 0 && e[l] == '=';
  4138. X}
  4139. X
  4140. Xvoid
  4141. XMakeNewEnv()
  4142. X{
  4143. X  register char **op, **np;
  4144. X  static char stybuf[MAXSTR];
  4145. X
  4146. X  for (op = environ; *op; ++op)
  4147. X    ;
  4148. X  if (NewEnv)
  4149. X    free(NewEnv);
  4150. X  NewEnv = np = (char **) malloc((unsigned) (op - environ + 7 + 1) * sizeof(char **));
  4151. X  if (!NewEnv)
  4152. X    Panic(0, strnomem);
  4153. X  SockName = SockNamePtr;
  4154. X  if (strlen(SockNamePtr) > MAXSTR - 5)
  4155. X    SockName = "?";
  4156. X  sprintf(stybuf, "STY=%s", SockNamePtr);
  4157. X  *np++ = stybuf;                    /* NewEnv[0] */
  4158. X  *np++ = Term;                    /* NewEnv[1] */
  4159. X  np++;        /* room for SHELL */
  4160. X#ifdef TIOCSWINSZ
  4161. X  np += 2;    /* room for TERMCAP and WINDOW */
  4162. X#else
  4163. X  np += 4;    /* room for TERMCAP WINDOW LINES COLUMNS */
  4164. X#endif
  4165. X
  4166. X  for (op = environ; *op; ++op)
  4167. X    {
  4168. X      if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP")
  4169. X      && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW")
  4170. X      && !IsSymbol(*op, "SCREENCAP") && !IsSymbol(*op, "SHELL")
  4171. X      && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS")
  4172. X     )
  4173. X    *np++ = *op;
  4174. X    }
  4175. X  *np = 0;
  4176. X}
  4177. X
  4178. Xvoid
  4179. X#ifdef USEVARARGS
  4180. X/*VARARGS2*/
  4181. X# if defined(__STDC__)
  4182. XMsg(int err, char *fmt, ...)
  4183. X# else /* __STDC__ */
  4184. XMsg(err, fmt, va_alist)
  4185. Xint err;
  4186. Xchar *fmt;
  4187. Xva_dcl
  4188. X# endif /* __STDC__ */
  4189. X{
  4190. X  static va_list ap;
  4191. X#else /* USEVARARRGS */
  4192. X/*VARARGS2*/
  4193. XMsg(err, fmt, p1, p2, p3, p4, p5, p6)
  4194. Xint err;
  4195. Xchar *fmt;
  4196. Xunsigned long p1, p2, p3, p4, p5, p6;
  4197. X{
  4198. X#endif /* USEVARARRGS */
  4199. X  char buf[MAXPATHLEN*2];
  4200. X  char *p = buf;
  4201. X
  4202. X#ifdef USEVARARGS
  4203. X# if defined(__STDC__)
  4204. X  va_start(ap, fmt);
  4205. X# else /* __STDC__ */
  4206. X  va_start(ap);
  4207. X# endif /* __STDC__ */
  4208. X  (void) vsprintf(p, fmt, ap);
  4209. X  va_end(ap);
  4210. X#else /* USEVARARRGS */
  4211. X  sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
  4212. X#endif /* USEVARARRGS */
  4213. X  if (err)
  4214. X    {
  4215. X      p += strlen(p);
  4216. X      if (err > 0 && err < sys_nerr)
  4217. X    sprintf(p, ": %s", sys_errlist[err]);
  4218. X      else
  4219. X    sprintf(p, ": Error %d", err);
  4220. X    }
  4221. X  debug2("Msg('%s') (%#x);\n", buf, (unsigned int)display);
  4222. X  if (display)
  4223. X    MakeStatus(buf);
  4224. X  else if (displays)
  4225. X    {
  4226. X      for (display = displays; display; display = display->_d_next)
  4227. X    MakeStatus(buf);
  4228. X    }
  4229. X  else
  4230. X    printf("%s\r\n", buf);
  4231. X}
  4232. X
  4233. Xvoid
  4234. X#ifdef USEVARARGS
  4235. X/*VARARGS2*/
  4236. X# if defined(__STDC__)
  4237. XPanic(int err, char *fmt, ...)
  4238. X# else /* __STDC__ */
  4239. XPanic(err, fmt, va_alist)
  4240. Xint err;
  4241. Xchar *fmt;
  4242. Xva_dcl
  4243. X# endif /* __STDC__ */
  4244. X{
  4245. X  static va_list ap;
  4246. X#else /* USEVARARRGS */
  4247. X/*VARARGS2*/
  4248. XPanic(err, fmt, p1, p2, p3, p4, p5, p6)
  4249. Xint err;
  4250. Xchar *fmt;
  4251. Xunsigned long p1, p2, p3, p4, p5, p6;
  4252. X{
  4253. X#endif /* USEVARARRGS */
  4254. X  char buf[MAXPATHLEN*2];
  4255. X  char *p = buf;
  4256. X
  4257. X#ifdef USEVARARGS
  4258. X# if defined(__STDC__)
  4259. X  va_start(ap, fmt);
  4260. X# else /* __STDC__ */
  4261. X  va_start(ap);
  4262. X# endif /* __STDC__ */
  4263. X  (void) vsprintf(p, fmt, ap);
  4264. X  va_end(ap);
  4265. X#else /* USEVARARRGS */
  4266. X  sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
  4267. X#endif /* USEVARARRGS */
  4268. X  if (err)
  4269. X    {
  4270. X      p += strlen(p);
  4271. X      if (err > 0 && err < sys_nerr)
  4272. X    sprintf(p, ": %s", sys_errlist[err]);
  4273. X      else
  4274. X    sprintf(p, ": Error %d", err);
  4275. X    }
  4276. X  debug1("Panic('%s');\n", buf);
  4277. X  if (displays == 0)
  4278. X    printf("%s\r\n", buf);
  4279. X  else
  4280. X    for (display = displays; display; display = display->_d_next)
  4281. X      {
  4282. X        if (d_status)
  4283. X      RemoveStatus();
  4284. X        FinitTerm();
  4285. X        Flush();
  4286. X#ifdef UTMPOK
  4287. X        RestoreLoginSlot();
  4288. X#endif
  4289. X        SetTTY(d_userfd, &d_OldMode);
  4290. X        fcntl(d_userfd, F_SETFL, 0);
  4291. X        write(d_userfd, buf, strlen(buf));
  4292. X        write(d_userfd, "\n", 1);
  4293. X        freetty();
  4294. X    if (d_userpid)
  4295. X      Kill(d_userpid, SIG_BYE);
  4296. X      }
  4297. X#ifdef MULTIUSER
  4298. X  if (tty_oldmode >= 0)
  4299. X    {
  4300. X# ifdef NOREUID
  4301. X      setuid(eff_uid);
  4302. X# else
  4303. X      setreuid(real_uid, eff_uid);
  4304. X# endif
  4305. X      debug1("Panic: changing back modes from %s\n", attach_tty);
  4306. X      chmod(attach_tty, tty_oldmode);
  4307. X    }
  4308. X#endif
  4309. X  eexit(1);
  4310. X}
  4311. X
  4312. X
  4313. X/*
  4314. X * '^' is allowed as an escape mechanism for control characters. jw.
  4315. X */
  4316. Xstatic char *
  4317. XMakeWinMsg(s, n)
  4318. Xregister char *s;
  4319. Xint n;
  4320. X{
  4321. X  static char buf[MAXSTR];
  4322. X  register char *p = buf;
  4323. X  register int ctrl;
  4324. X
  4325. X  ctrl = 0;
  4326. X  for (; *s && p < buf + MAXSTR - 1; s++, p++)
  4327. X    if (ctrl)
  4328. X      {
  4329. X        ctrl = 0;
  4330. X        if (*s == '^' || *s < 64)
  4331. X          *p = *s;
  4332. X        else 
  4333. X          *p = *s - 64;
  4334. X      }
  4335. X    else
  4336. X      {
  4337. X        switch (*s)
  4338. X          {
  4339. X          case '%':
  4340. X        sprintf(p, "%d", n);
  4341. X        p += strlen(p) - 1;
  4342. X        break;
  4343. X          case '~':
  4344. X        *p = BELL;
  4345. X        break;
  4346. X      case '^':
  4347. X        ctrl = 1;
  4348. X        *p-- = '^';
  4349. X        break;
  4350. X          default:
  4351. X        *p = *s;
  4352. X        break;
  4353. X          }
  4354. X      }
  4355. X  *p = '\0';
  4356. X  return buf;
  4357. X}
  4358. X
  4359. Xvoid
  4360. XDisplaySleep(n)
  4361. Xint n;
  4362. X{
  4363. X  char buf;
  4364. X  fd_set r;
  4365. X  struct timeval t;
  4366. X
  4367. X  if (!display)
  4368. X    {
  4369. X      debug("DisplaySleep has no display sigh\n");
  4370. X      sleep(n);
  4371. X      return;
  4372. X    }
  4373. X  t.tv_usec = 0;
  4374. X  t.tv_sec = n;
  4375. X  FD_ZERO(&r);
  4376. X  FD_SET(d_userfd, &r);
  4377. X  if (select(FD_SETSIZE, &r, (fd_set *)0, (fd_set *)0, &t) > 0)
  4378. X    {
  4379. X      debug("display activity stopped sleep\n");
  4380. X      read(d_userfd, &buf, 1);
  4381. X    }
  4382. X  debug1("DisplaySleep(%d) ending\n", n);
  4383. X}
  4384. END_OF_FILE
  4385. if test 50777 -ne `wc -c <'screen.c'`; then
  4386.     echo shar: \"'screen.c'\" unpacked with wrong size!
  4387. fi
  4388. # end of 'screen.c'
  4389. fi
  4390. echo shar: End of archive 6 \(of 10\).
  4391. cp /dev/null ark6isdone
  4392. MISSING=""
  4393. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  4394.     if test ! -f ark${I}isdone ; then
  4395.     MISSING="${MISSING} ${I}"
  4396.     fi
  4397. done
  4398. if test "${MISSING}" = "" ; then
  4399.     echo You have unpacked all 10 archives.
  4400.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  4401. else
  4402.     echo You still need to unpack the following archives:
  4403.     echo "        " ${MISSING}
  4404. fi
  4405. ##  End of shell archive.
  4406. exit 0
  4407.