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

  1. Newsgroups: comp.sources.misc
  2. From: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  3. Subject:  v28i020:  screen-3.2 - multiple windows on an ASCII terminal, v3.2, Part03/11
  4. Message-ID: <1992Feb9.223455.6514@sparky.imd.sterling.com>
  5. X-Md4-Signature: 0cbde4287dc9ff7f7e7fcbbbebdd1d11
  6. Date: Sun, 9 Feb 1992 22:34:55 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  10. Posting-number: Volume 28, Issue 20
  11. Archive-name: screen-3.2/part03
  12. Environment: UNIX
  13.  
  14. #!/bin/sh
  15. # do not concatenate these parts, unpack them in order with /bin/sh
  16. # file screen3.2/fileio.c continued
  17. #
  18. if test ! -r _shar_seq_.tmp; then
  19.     echo 'Please unpack part 1 first!'
  20.     exit 1
  21. fi
  22. (read Scheck
  23.  if test "$Scheck" != 3; then
  24.     echo Please unpack part "$Scheck" next!
  25.     exit 1
  26.  else
  27.     exit 0
  28.  fi
  29. ) < _shar_seq_.tmp || exit 1
  30. if test ! -f _shar_wnt_.tmp; then
  31.     echo 'x - still skipping screen3.2/fileio.c'
  32. else
  33. echo 'x - continuing file screen3.2/fileio.c'
  34. sed 's/^X//' << 'SHAR_EOF' >> 'screen3.2/fileio.c' &&
  35. X      if (fore && rc_name[0] == '\0')
  36. X        Msg(0, "scrollback set to %d", fore->histheight);
  37. X    }
  38. X      else
  39. X    ParseNum(argc, ap, &default_histheight);
  40. X      return;
  41. X    case RC_SLOWPASTE:
  42. X      ParseNum(argc, ap, &slowpaste);
  43. X      if (fore && rc_name[0] == '\0')
  44. X    Msg(0, "slowpaste set to %d milliseconds", slowpaste);
  45. X      return;
  46. X    case RC_MARKKEYS:
  47. X      {
  48. X        char *tmp = NULL;
  49. X
  50. X        ParseSaveStr(argc, ap, &tmp, "markkeys");
  51. X        if (CompileKeys(ap[1], mark_key_tab))
  52. X      {
  53. X        DeadlyMsg = 0;
  54. X        Msg(0, "%s: markkeys: syntax error.", rc_name);
  55. X        Free(tmp);
  56. X        return;
  57. X      }
  58. X        debug1("markkeys %s\n", ap[1]);
  59. X        Free(tmp);
  60. X        return;
  61. X      }
  62. #ifdef NETHACK
  63. X    case RC_NETHACK:
  64. X      ParseOnOff(argc, ap, &nethackflag);
  65. X      return;
  66. #endif
  67. X    case RC_HARDCOPY_APP:
  68. X      ParseOnOff(argc, ap, &hardcopy_append);
  69. X      return;
  70. X    case RC_VBELL_MSG:
  71. X    case RC_VISUALBELL_MSG:
  72. X      ParseSaveStr(argc, ap, &VisualBellString, "vbell_msg");
  73. X      debug1(" new vbellstr '%s'\n", VisualBellString);
  74. X      return;
  75. X    case RC_MODE:
  76. X      if (argc != 2)
  77. X    {
  78. X      DeadlyMsg = 0; 
  79. X      Msg(0, "%s: mode: one argument required.", rc_name);
  80. X      return;
  81. X    }
  82. X      if (!IsNum(ap[1], 7))
  83. X    {
  84. X      DeadlyMsg = 0; 
  85. X      Msg(0, "%s: mode: octal number expected.", rc_name);
  86. X      return;
  87. X    }
  88. X      (void) sscanf(ap[1], "%o", &TtyMode);
  89. X      return;
  90. X    case RC_CRLF:
  91. X      ParseOnOff(argc, ap, &join_with_cr);
  92. X      return;
  93. X    case RC_AUTODETACH:
  94. X      ParseOnOff(argc, ap, &auto_detach);
  95. X      return;
  96. X    case RC_STARTUP_MESSAGE:
  97. X      ParseOnOff(argc, ap, &default_startup);
  98. X      return;
  99. #ifdef PASSWORD
  100. X    case RC_PASSWORD:
  101. X      CheckPassword = 1;
  102. X      if (argc >= 2)
  103. X    {
  104. X      strncpy(Password, ap[1], sizeof Password);
  105. X      if (!strcmp(Password, "none"))
  106. X        CheckPassword = 0;
  107. X    }
  108. X      else
  109. X    {
  110. X      char *mstr = 0;
  111. X      int msleep = 0, st;
  112. X          char salt[2];
  113. X
  114. #ifdef POSIX
  115. X      if (HasWindow)
  116. X        {
  117. X          Msg(0, "Cannot ask for password on POSIX systems");
  118. X          return;
  119. X        }
  120. #endif
  121. X      /* there is a clear screen sequence in the buffer. */
  122. X      fflush(stdout);
  123. X      if (HasWindow)
  124. X        {
  125. X              ClearDisplay();
  126. X          SetTTY(0, &OldMode);
  127. X        }
  128. X      strncpy(Password, getpass("New screen password:"),
  129. X          sizeof(Password));
  130. X      if (strcmp(Password, getpass("Retype new password:")))
  131. X        {
  132. #ifdef NETHACK
  133. X              if (nethackflag)
  134. X            mstr = "[ Passwords don't match - your armor crumbles away ]";
  135. X          else
  136. #endif
  137. X          mstr = "[ Passwords don't match - checking turned off ]";
  138. X          msleep = 1;
  139. X          CheckPassword = 0;
  140. X        }
  141. X      if (Password[0] == '\0')
  142. X        {
  143. X          CheckPassword = 0;
  144. X          mstr = "[ No password - no secure ]";
  145. X          msleep = 1;
  146. X        }
  147. X      for (st=0; st<2; st++)
  148. X            salt[st] = 'A' + (int)((time(0) >> 6*st) % 26);
  149. X      strncpy(Password, crypt(Password, salt), sizeof(Password));
  150. X      if (CheckPassword)
  151. X        {
  152. #ifdef COPY_PASTE
  153. X          if (copybuffer)
  154. X
  155. X        Free(copybuffer);
  156. X          copylen = strlen(Password);
  157. X          if ((copybuffer = (char *) malloc(copylen+1)) == NULL)
  158. X        {
  159. X          Msg_nomem;
  160. X          return;
  161. X        }
  162. X          strcpy(copybuffer, Password);
  163. X          mstr = "[ Password moved into copybuffer ]";
  164. X          msleep = 1;
  165. #else                /* COPY_PASTE */
  166. X          mstr = "[ Crypted password is \"%s\" ]";
  167. X          msleep = 5;
  168. #endif                /* COPY_PASTE */
  169. X        }
  170. X          if (HasWindow)
  171. X        {
  172. X          SetTTY(0, &NewMode);
  173. X          Activate(0); /* Redraw */
  174. X          if (mstr)
  175. X            {
  176. X              Msg(0, mstr, Password);
  177. X            }
  178. X        }
  179. X          else
  180. X        {
  181. X          if (mstr)
  182. X            {
  183. X              printf(mstr, Password);
  184. X              putchar('\n');
  185. X              sleep(msleep);
  186. X            }
  187. X              ClearDisplay();
  188. X        }
  189. X    }
  190. X      debug1("finishrc: our password is: --%s%-- \n", Password);
  191. X      return;
  192. #endif                /* PASSWORD */
  193. X    case RC_ALL:
  194. X      if (!setflag || !HasWindow || *rc_name)
  195. X        break;
  196. X      display_help();
  197. X      return;
  198. X    case RC_BIND:
  199. X      if (setflag)
  200. X    break;
  201. X      p = ap[1];
  202. X      if (argc < 2 || *p == '\0')
  203. X    {
  204. X      DeadlyMsg = 0; 
  205. X      Msg(0, "%s: key expected after bind.", rc_name);
  206. X      return;
  207. X    }
  208. X      if ((p = ParseChar(p, &key)) == NULL || *p)
  209. X    {
  210. X      DeadlyMsg = 0; 
  211. X      Msg(0, "%s: bind: character, ^x, or (octal) \\032 expected.",
  212. X          rc_name);
  213. X      return;
  214. X    }
  215. X      if (ktab[key].type != KEY_IGNORE)
  216. X    {
  217. X      ktab[key].type = KEY_IGNORE;
  218. X      if ((pp = ktab[key].args) != NULL)
  219. X        {
  220. X          for (; *pp; pp++)
  221. X        Free(*pp);
  222. X          Free(ktab[key].args);
  223. X        }
  224. X    }
  225. X      if (argc > 2)
  226. X    {
  227. X      for (pp = KeyNames; *pp; ++pp)
  228. X        if (strcmp(ap[2], *pp) == 0)
  229. X          break;
  230. X      if (*pp)
  231. X        {
  232. X          ktab[key].type = (enum keytype) (pp - KeyNames + 1);
  233. X          if (argc > 3)
  234. X        {
  235. X          ktab[key].args = SaveArgs(argc - 3, ap + 3);
  236. X        }
  237. X          else
  238. X        ktab[key].args = NULL;
  239. X        }
  240. X      else
  241. X        {
  242. X          ktab[key].type = KEY_CREATE;
  243. X          ktab[key].args = SaveArgs(argc - 2, ap + 2);
  244. X        }
  245. X    }
  246. X      return;
  247. X    case RC_RCEND:
  248. X    default:
  249. X    {
  250. X      char ibuf[3];
  251. X      /*
  252. X       * now we are user-friendly: 
  253. X       * if anyone typed a key name like "help" or "next" ...
  254. X       * we did not match anything above. so look in the KeyNames table.
  255. X       */
  256. X      debug1("--ap[0] %s\n", ap[0]);
  257. X      for (pp = KeyNames; *pp; ++pp)
  258. X        if (strcmp(ap[0], *pp) == 0)
  259. X        break;
  260. X      if (*pp == 0)
  261. X        break;
  262. X
  263. X      ibuf[0] = Esc;
  264. X      ibuf[1] = pp - KeyNames +1;
  265. X      debug1("RcLine: it was a keyname: '%s'\n", *pp);
  266. X      q = 2; qq = 0;
  267. X      if (HasWindow)
  268. X        ProcessInput(ibuf, &q, (char *)0, &qq, 0);
  269. X      else
  270. X        {
  271. X          DeadlyMsg = 0; 
  272. X          Msg(0, "%s: Key '%s' has no effect while no window open...\n",
  273. X              rc_name, ap[0]);
  274. X        }
  275. X    }
  276. X      return;
  277. X    }
  278. X  DeadlyMsg = 0; 
  279. X  Msg(0, "%s: unknown %skeyword \"%s\"", rc_name, 
  280. X      setflag?"'set' ":"", ap[0]);
  281. }
  282. X
  283. static int 
  284. Parse(buf, args)
  285. char *buf, **args;
  286. {
  287. X  register char *p = buf, **ap = args;
  288. X  register int delim, argc;
  289. X
  290. X  argc = 0;
  291. X  for (;;)
  292. X    {
  293. X      while (*p && (*p == ' ' || *p == '\t'))
  294. X    ++p;
  295. X      if (*p == '\0' || *p == '#')
  296. X    {
  297. X      *p = '\0';
  298. X      return argc;
  299. X    }
  300. X      if (argc > MAXARGS - 1)
  301. X    Msg(0, "%s: too many tokens.", rc_name);
  302. X      delim = 0;
  303. X      if (*p == '"' || *p == '\'')
  304. X    delim = *p++;
  305. X      argc++;
  306. X      *ap = p;
  307. X      *++ap = 0;
  308. X      while (*p && !(delim ? *p == delim : (*p == ' ' || *p == '\t')))
  309. X    ++p;
  310. X      if (*p == '\0')
  311. X    {
  312. X      if (delim)
  313. X        {
  314. X          DeadlyMsg = 0;
  315. X          Msg(0, "%s: Missing quote.", rc_name);
  316. X          return 0;
  317. X    }
  318. X      return argc;
  319. X    }
  320. X      *p++ = '\0';
  321. X    }
  322. }
  323. X
  324. int 
  325. ParseEscape(p)
  326. char *p;
  327. {
  328. X  if ((p = ParseChar(p, &Esc)) == NULL ||
  329. X      (p = ParseChar(p, &MetaEsc)) == NULL || *p)
  330. X    return 0;
  331. X  return 1;
  332. }
  333. X
  334. static void
  335. ParseNum(argc, ap, var)
  336. int argc;
  337. char *ap[];
  338. int *var;
  339. {
  340. X  int i;
  341. X  char *p;
  342. X
  343. X  if (argc == 2 && ap[1][0] != '\0')
  344. X    {
  345. X      i = 0; 
  346. X      p = ap[1];
  347. X      while (*p)
  348. X    {
  349. X      if (*p >= '0' && *p <= '9')
  350. X        i = 10 * i + (*p - '0');
  351. X      else
  352. X        {
  353. X          DeadlyMsg = 0;
  354. X          Msg(0, "%s: %s: invalid argument. Give numeric argument",
  355. X          rc_name, ap[0]);
  356. X          return;
  357. X        }    
  358. X      p++;
  359. X    }
  360. X    }
  361. X  else
  362. X    {
  363. X      DeadlyMsg = 0;
  364. X      Msg(0, "%s: %s: invalid argument. Give one argument",
  365. X          rc_name, ap[0]);
  366. X      return;
  367. X    }
  368. X  debug1("ParseNum got %d\n", i);
  369. X  *var = i;
  370. }
  371. X
  372. static void
  373. ParseSaveStr(argc, ap, var, title)
  374. int argc;
  375. char *ap[];
  376. char **var;
  377. char *title;
  378. {
  379. X  if (argc != 2)
  380. X    {
  381. X      DeadlyMsg = 0;
  382. X      Msg(0, "%s: %s: one argument required.", rc_name, title);
  383. X      return;
  384. X    }
  385. X  if (*var)
  386. X    Free(*var);
  387. X  *var = SaveStr(ap[1]);
  388. X  return;
  389. }
  390. static void
  391. ParseOnOff(argc, ap, var)
  392. int argc;
  393. char *ap[];
  394. int *var;
  395. {
  396. X  register int num = -1;
  397. X
  398. X  if (argc == 2 && ap[1][0] == 'o')
  399. X    {
  400. X      if (ap[1][1] == 'f')
  401. X    num = 0;
  402. X      else if (ap[1][1] == 'n')
  403. X    num = 1;
  404. X    }
  405. X  if (num < 0)
  406. X    {
  407. X      DeadlyMsg = 0;
  408. X      Msg(0, "%s: %s: invalid argument. Give 'on' or 'off'", rc_name, ap[0]);
  409. X      return;
  410. X    }
  411. X  *var = num;
  412. }
  413. X
  414. X
  415. static int IsNum(s, base)
  416. register char *s;
  417. register int base;
  418. {
  419. X  for (base += '0'; *s; ++s)
  420. X    if (*s < '0' || *s > base)
  421. X      return 0;
  422. X  return 1;
  423. }
  424. X
  425. static int IsNumColon(s, base, p, psize)
  426. int base, psize;
  427. char *s, *p;
  428. {
  429. X  char *q;
  430. X  if ((q = rindex(s, ':')) != NULL)
  431. X    {
  432. X      strncpy(p, q + 1, psize - 1);
  433. X      p[psize - 1] = '\0';
  434. X      *q = '\0';
  435. X    }
  436. X  else
  437. X    *p = '\0';
  438. X  return IsNum(s, base);
  439. }
  440. X
  441. void
  442. SlotToggle(how)
  443. int how;
  444. /*
  445. X * how = 0    real toggle mode
  446. X * how > 0    do try to set a utmp slot.
  447. X * how < 0    try to withdraw a utmp slot
  448. X *
  449. X * slot = -1    window not logged in.
  450. X * slot = 0     window not logged in, but should be logged in. 
  451. X *              (unable to write utmp, or detached).
  452. X */
  453. {
  454. X  debug1("SlotToggle %d\n", how);
  455. X  if (how == 0)
  456. X    how = (fore->slot == (slot_t) -1)?(1):(-1);
  457. X    /* 
  458. X     * slot 0 or active -> we try to log out.
  459. X     * slot -1          -> we try to log in.
  460. X     */
  461. #ifdef UTMPOK
  462. X  if (how > 0)
  463. X    {
  464. X      debug(" try to log in\n");
  465. X      if ((fore->slot == (slot_t) -1) || (fore->slot == (slot_t) 0))
  466. X    {
  467. #ifdef USRLIMIT
  468. X          if (CountUsers() >= USRLIMIT)
  469. X            Msg(0, "User limit reached.");
  470. X          else
  471. #endif
  472. X            {
  473. X              if (SetUtmp(fore, ForeNum) == 0)
  474. X                Msg(0, "This window is now logged in.");
  475. X              else
  476. X                Msg(0, "This window should now be logged in.");
  477. X            }
  478. X    }
  479. X      else
  480. X    Msg(0, "This window is already logged in.");
  481. X    }
  482. X  else if (how < 0)
  483. X    {
  484. X      debug(" try to log out\n");
  485. X      if (fore->slot == (slot_t) -1)
  486. X    Msg(0, "This window is already logged out\n");
  487. X      else if (fore->slot == (slot_t) 0)
  488. X    {
  489. X      debug("What a relief! In fact, it was not logged in\n");
  490. X      Msg(0, "This window is not logged in.");
  491. X      fore->slot = (slot_t) -1;
  492. X    }
  493. X      else
  494. X    {
  495. X      RemoveUtmp(fore);
  496. X      if (fore->slot != (slot_t) -1)
  497. X        Msg(0, "What? Cannot remove Utmp slot?");
  498. X      else
  499. X        Msg(0, "This window is no longer logged in.");
  500. X    }
  501. X    }
  502. #else    /* !UTMPOK */
  503. X  Msg(0, "Unable to modify %s.\n", UTMPFILE);
  504. #endif
  505. }
  506. X
  507. void
  508. DoScreen(fn, av)
  509. char *fn, **av;
  510. {
  511. X  register int flowflag, num, lflag = loginflag, aflag = 0;
  512. X  register char *aka = NULL;
  513. X  register int histheight = default_histheight;
  514. X  char buf[20];
  515. X  char termbuf[25];
  516. X  char *termp;
  517. X  char *args[2];
  518. X
  519. X  flowflag = default_flow;
  520. X  termbuf[0] = '\0';
  521. X  termp = NULL;
  522. X  while (av && *av && av[0][0] == '-')
  523. X    {
  524. X      switch (av[0][1])
  525. X    {
  526. X    case 'f':
  527. X      switch (av[0][2])
  528. X        {
  529. X        case 'n':
  530. X        case '0':
  531. X          flowflag = FLOW_NOW * 0;
  532. X          break;
  533. X        case 'y':
  534. X        case '1':
  535. X        case '\0':
  536. X          flowflag = FLOW_NOW * 1;
  537. X          break;
  538. X        case 'a':
  539. X          flowflag = FLOW_AUTOFLAG;
  540. X          break;
  541. X        default:
  542. X          break;
  543. X        }
  544. X      break;
  545. X    case 'k':
  546. X    case 't':
  547. X      if (av[0][2])
  548. X        aka = &av[0][2];
  549. X      else if (*++av)
  550. X        aka = *av;
  551. X      else
  552. X        --av;
  553. X      break;
  554. X    case 'T':
  555. X      if (av[0][2])
  556. X        termp = &av[0][2];
  557. X      else if (*++av)
  558. X        termp = *av;
  559. X      else
  560. X        --av;
  561. X      break;
  562. X    case 'h':
  563. X      if (av[0][2])
  564. X        histheight = atoi(av[0] + 2);
  565. X      else if (*++av)
  566. X        histheight = atoi(*av);
  567. X      else 
  568. X        --av;
  569. X      break;
  570. X    case 'l':
  571. X      switch (av[0][2])
  572. X        {
  573. X        case 'n':
  574. X        case '0':
  575. X          lflag = 0;
  576. X          break;
  577. X        case 'y':
  578. X        case '1':
  579. X        case '\0':
  580. X          lflag = 1;
  581. X          break;
  582. X        default:
  583. X          break;
  584. X        }
  585. X      break;
  586. X    case 'a':
  587. X      aflag = 1;
  588. X      break;
  589. X    default:
  590. X      Msg(0, "%s: screen: invalid option -%c.", fn, av[0][1]);
  591. X      break;
  592. X    }
  593. X      ++av;
  594. X    }
  595. X  num = 0;
  596. X  if (av && *av && IsNumColon(*av, 10, buf, sizeof(buf)))
  597. X    {
  598. X      if (*buf != '\0')
  599. X    aka = buf;
  600. X      num = atoi(*av);
  601. X      if (num < 0 || num > MAXWIN - 1)
  602. X    {
  603. X      Msg(0, "%s: illegal screen number %d.", fn, num);
  604. X      num = 0;
  605. X    }
  606. X      ++av;
  607. X    }
  608. X  if (!av || !*av)
  609. X    {
  610. X      av = args;
  611. X      av[0] = ShellProg;
  612. X      av[1] = NULL;
  613. X      if (!aka)
  614. X    aka = shellaka;
  615. X    }
  616. X  MakeWindow(aka, av, aflag, flowflag, num, (char *) 0, lflag, histheight, termp);
  617. }
  618. X
  619. void
  620. WriteFile(dump)
  621. int dump;
  622. {
  623. X  /* dump==0:    create .termcap,
  624. X   * dump==1:    hardcopy,
  625. X   * #ifdef COPY_PASTE
  626. X   * dump==2:    BUFFERFILE
  627. X   * #endif COPY_PASTE 
  628. X   */
  629. X  register int i, j, k;
  630. X  register char *p;
  631. X  register FILE *f;
  632. X  char fn[1024];
  633. X  char *mode = "w";
  634. X
  635. X  switch (dump)
  636. X    {
  637. X    case DUMP_TERMCAP:
  638. X      i = SockNamePtr - SockPath;
  639. X      strncpy(fn, SockPath, i);
  640. X      strcpy(fn + i, ".termcap");
  641. X      break;
  642. X    case DUMP_HARDCOPY:
  643. X      sprintf(fn, "hardcopy.%d", ForeNum);
  644. X      if (hardcopy_append && !access(fn, W_OK))
  645. X    mode = "a";
  646. X      break;
  647. X    case DUMP_EXCHANGE:
  648. X      sprintf(fn, "%s", BufferFile);
  649. X      umask(0);
  650. X      break;
  651. X    }
  652. X
  653. X  debug2("WriteFile(%d) %s\n", dump, fn);
  654. X  if (UserContext() > 0)
  655. X    {
  656. X      debug("Writefile: usercontext\n");
  657. X      if ((f = fopen(fn, mode)) == NULL)
  658. X    {
  659. X      debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode);
  660. X      UserReturn(0);
  661. X    }
  662. X      else
  663. X    {
  664. X      switch (dump)
  665. X        {
  666. X        case DUMP_HARDCOPY:
  667. X          if (*mode == 'a')
  668. X        {
  669. X          putc('>', f);
  670. X          for (j = screenwidth - 2; j > 0; j--)
  671. X            putc('=', f);
  672. X          fputs("<\n", f);
  673. X        }
  674. X          for (i = 0; i < screenheight; ++i)
  675. X        {
  676. X          p = fore->image[i];
  677. X          for (k = screenwidth - 1; k >= 0 && p[k] == ' '; --k)
  678. X            ;
  679. X          for (j = 0; j <= k; ++j)
  680. X            putc(p[j], f);
  681. X          putc('\n', f);
  682. X        }
  683. X          break;
  684. X        case DUMP_TERMCAP:
  685. X          if ((p = index(MakeTermcap(fore->aflag), '=')) != NULL)
  686. X        {
  687. X          fputs(++p, f);
  688. X          putc('\n', f);
  689. X        }
  690. X          break;
  691. #ifdef COPY_PASTE
  692. X        case DUMP_EXCHANGE:
  693. X          p = copybuffer;
  694. X          for (i = 0; i < copylen; i++)
  695. X        putc(*p++, f);
  696. X          break;
  697. #endif
  698. X        }
  699. X      (void) fclose(f);
  700. X      UserReturn(1);
  701. X    }
  702. X    }
  703. X  if (UserStatus() <= 0)
  704. X    Msg(0, "Cannot open \"%s\"", fn);
  705. X  else
  706. X    {
  707. X      switch (dump)
  708. X    {
  709. X    case DUMP_TERMCAP:
  710. X      Msg(0, "Termcap entry written to \"%s\".", fn);
  711. X      break;
  712. X    case DUMP_HARDCOPY:
  713. X      Msg(0, "Screen image %s to \"%s\".",
  714. X          (*mode == 'a') ? "appended" : "written", fn);
  715. X      break;
  716. #ifdef COPY_PASTE
  717. X    case DUMP_EXCHANGE:
  718. X      Msg(0, "Copybuffer written to \"%s\".", fn);
  719. #endif
  720. X    }
  721. X    }
  722. }
  723. X
  724. #ifdef COPY_PASTE
  725. X
  726. void
  727. ReadFile()
  728. {
  729. X  int i, l, size;
  730. X  char fn[1024], c;
  731. X  struct stat stb;
  732. X
  733. X  sprintf(fn, "%s", BufferFile);
  734. X  debug1("ReadFile(%s)\n", fn);
  735. X  if ((i = secopen(fn, O_RDONLY, 0)) < 0)
  736. X    {
  737. X      Msg(errno, "no %s -- no slurp", fn);
  738. X      return;
  739. X    }
  740. X  if (fstat(i, &stb))
  741. X    {
  742. X      Msg(errno, "no good %s -- no slurp", fn);
  743. X      close(i);
  744. X      return;
  745. X    }
  746. X  size = stb.st_size;
  747. X  if (copybuffer)
  748. X    Free(copybuffer);
  749. X  copylen = 0;
  750. X  if ((copybuffer = malloc(size)) == NULL)
  751. X    {
  752. X      close(i);
  753. X      Msg_nomem;
  754. X      return;
  755. X    }
  756. X  errno = 0;
  757. X  if ((l = read(i, copybuffer, size)) != size)
  758. X    {
  759. X      copylen = (l > 0) ? l : 0;
  760. #ifdef NETHACK
  761. X      if (nethackflag)
  762. X        Msg(errno, "You choke on your food: %d bytes", copylen);
  763. X      else
  764. #endif
  765. X      Msg(errno, "Got only %d bytes from %s", copylen, fn);
  766. X      close(i);
  767. X      return;
  768. X    }
  769. X  copylen = l;
  770. X  if (read(i, &c, 1) > 0)
  771. X    Msg(0, "Slurped only %d characters into buffer - try again", copylen);
  772. X  else
  773. X    Msg(0, "Slurped %d characters into buffer", copylen);
  774. X  close(i);
  775. X  return;
  776. }
  777. X
  778. void
  779. KillBuffers()
  780. {
  781. X  char fn[1024];
  782. X  sprintf(fn, "%s", BufferFile);
  783. X  errno = 0;
  784. X  if (access(fn, W_OK) == -1)
  785. X    {
  786. X      Msg(errno, "%s not removed", fn);
  787. X      return;
  788. X    }
  789. X  else
  790. X    {
  791. X      unlink(fn);
  792. X      Msg(errno, "%s removed", fn);
  793. X    }
  794. }
  795. #endif    /* COPY_PASTE */
  796. X
  797. #ifdef USRLIMIT
  798. CountUsers()
  799. {
  800. #ifdef GETUTENT
  801. X  struct utmp *ut, *getutent();
  802. #else
  803. X  struct utmp utmpbuf;
  804. #endif
  805. X  int UserCount;
  806. X
  807. X  debug1("CountUsers() - utmp=%d\n",utmp);
  808. X  if (!utmp)
  809. X    return(0);
  810. X  UserCount = 0;
  811. #ifdef GETUTENT
  812. X  setutent();
  813. X  while (ut = getutent())
  814. X    if (ut->ut_type == USER_PROCESS)
  815. X      UserCount++;
  816. #else
  817. X  (void) lseek(utmpf, (off_t) 0, 0);
  818. X  while (read(utmpf, &utmpbuf, sizeof(struct utmp)) > 0)
  819. X    {
  820. X      if (utmpbuf.ut_name[0] != '\0')
  821. X       UserCount++;
  822. X    }
  823. #endif
  824. X  return(UserCount);
  825. }
  826. #endif
  827. X
  828. #ifdef UTMPOK
  829. X
  830. static slot_t loginslot;
  831. static struct utmp utmp_logintty;
  832. #ifdef _SEQUENT_
  833. static char loginhost[100+1];
  834. #endif
  835. X
  836. void
  837. InitUtmp()
  838. {
  839. X  debug("InitUtmp testing...\n");
  840. X  if ((utmpf = open(UtmpName, O_RDWR)) == -1)
  841. X    {
  842. X      if (errno != EACCES)
  843. X    Msg(errno, UtmpName);
  844. X      debug("InitUtmp failed.\n");
  845. X      utmp = 0;
  846. X      return;
  847. X    }
  848. #ifdef GETUTENT
  849. X  close(utmpf);
  850. X  utmpf= -1;
  851. #endif
  852. #ifdef MIPS
  853. X  if ((utmpfappend = open(UtmpName, O_APPEND)) == -1) 
  854. X    {
  855. X      if (errno != EACCES)
  856. X    Msg(errno, UtmpName);
  857. X      return;
  858. X    }
  859. #endif
  860. X  utmp = 1;
  861. #ifndef apollo
  862. X  ReInitUtmp();
  863. #endif
  864. }
  865. X
  866. void
  867. ReInitUtmp()
  868. {
  869. #ifndef apollo
  870. X  if (!utmp)
  871. X    {
  872. X      debug("Reinitutmp: utmp == 0\n");
  873. X      return;
  874. X    }
  875. #endif
  876. X  debug("(Re)InitUtmp: removing your logintty\n");
  877. X  loginslot = TtyNameSlot(display_tty);
  878. X  if (loginslot!=(slot_t)0 && loginslot!=(slot_t)-1)
  879. X    {
  880. #ifdef _SEQUENT_
  881. X      if (p=ut_find_host(loginslot))
  882. X        strncpy(loginhost, p, 100);
  883. #endif
  884. X      RemoveLoginSlot(loginslot, &utmp_logintty);
  885. X    }
  886. X  debug1(" slot %d zapped\n", loginslot);
  887. }
  888. X
  889. void
  890. RestoreLoginSlot()
  891. {
  892. X  debug("RestoreLoginSlot()\n");
  893. #ifdef apollo
  894. X  InitUtmp();
  895. #endif
  896. X  if (utmp && loginslot!=(slot_t)0 && loginslot!=(slot_t)-1)
  897. X    {
  898. #ifdef GETUTENT
  899. # ifdef _SEQUENT_
  900. X      int fail;
  901. X      debug1(" logging you in again (slot %s)\n", loginslot);
  902. /*
  903. X * We have problems if we add the console and use ut_add_user()
  904. X * because the id will be 'scon' instead of 'co'. So we
  905. X * restore it with pututline(). The reason why we don't use
  906. X * pututline all the time is that we want to set the host field.
  907. X * Unfortunatelly this can only be done with ut_add_user().
  908. X */
  909. X      if (*loginhost)
  910. X        {
  911. X          fail = (ut_add_user(LoginName, loginslot, utmp_logintty.ut_pid,
  912. X                              *loginhost?loginhost:(char *)0) == 0);
  913. X        }
  914. X      else
  915. X        {
  916. X          setutent();
  917. X          fail = (pututline(&utmp_logintty) == 0);
  918. X        }
  919. X      if (fail)
  920. # else    /* _SEQUENT_ */
  921. X      debug1(" logging you in again (slot %s)\n", loginslot);
  922. X      setutent();
  923. X      if (pututline(&utmp_logintty)==0)
  924. # endif    /* _SEQUENT */
  925. #else    /* GETUTENT */
  926. X      debug1(" logging you in again (slot %d)\n", loginslot);
  927. # ifdef sequent
  928. X      /* call sequent undocumented routine to count logins and add utmp entry if possible */
  929. X      if (add_utmp(loginslot, &utmp_logintty) == -1)
  930. # else
  931. X      (void) lseek(utmpf, (off_t) (loginslot * sizeof(struct utmp)), 0);
  932. X      if (write(utmpf, (char *) &utmp_logintty, sizeof(struct utmp))
  933. X      != sizeof(struct utmp))
  934. # endif /* sequent */
  935. #endif    /* GETUTENT */
  936. X        {
  937. #ifdef NETHACK
  938. X          if (nethackflag)
  939. X            Msg(errno, "%s is too hard to dig in.", UTMPFILE);
  940. X      else
  941. #endif
  942. X          Msg(errno,"Could not write %s.", UTMPFILE);
  943. X        }
  944. X    }
  945. #ifdef apollo
  946. X  close(utmpf);
  947. #endif
  948. X  loginslot = (slot_t) 0;
  949. }
  950. X
  951. void
  952. RemoveLoginSlot(slot, up)
  953. slot_t slot;
  954. struct utmp *up;
  955. {
  956. #ifdef GETUTENT
  957. X  struct utmp *uu;
  958. #endif
  959. X  struct utmp u;
  960. #ifdef apollo
  961. X  struct utmp *uq;
  962. #endif
  963. X
  964. #ifdef GETUTENT
  965. X  debug2("RemoveLoginSlot(%s, %08x)\n", (slot == (slot_t) 0 ||
  966. X         slot == (slot_t) -1 ) ? "no slot" : slot, up);
  967. #else
  968. X  debug2("RemoveLoginSlot(%d, %08x)\n", slot, up);
  969. #endif
  970. #ifdef apollo
  971. X  InitUtmp();
  972. X  bzero((char *)up, sizeof(struct utmp));
  973. X  uq = (struct utmp *)malloc(sizeof(struct utmp));
  974. X  bzero((char *)uq, sizeof(struct utmp));
  975. #endif /* apollo */
  976. X  if (!utmp)
  977. X    return;
  978. X  if (slot != (slot_t) 0 && slot != (slot_t) -1)
  979. X    {
  980. X      bzero((char *) &u, sizeof u);
  981. #ifdef GETUTENT
  982. X      setutent();
  983. X      strncpy(u.ut_line, slot, sizeof(u.ut_line));
  984. X      if ((uu = getutline(&u)) == 0)
  985. X        {
  986. X      DeadlyMsg = 0;
  987. X          Msg(0, "Utmp slot not found -> not removed");
  988. X          return;
  989. X        }
  990. X      *up= *uu;
  991. # ifdef _SEQUENT_
  992. X      if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
  993. # else
  994. X      uu->ut_type = DEAD_PROCESS;
  995. X      uu->ut_exit.e_termination = 0;
  996. X      uu->ut_exit.e_exit= 0;
  997. X      if (pututline(uu) == 0)
  998. # endif
  999. #else
  1000. X      (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  1001. X      if (read(utmpf, (char *) up, sizeof u) != sizeof u)
  1002. X    {
  1003. X      DeadlyMsg = 0;
  1004. X      Msg(errno, "cannot read %s ???", UTMPFILE);
  1005. X      sleep(1);
  1006. X    }
  1007. X      (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  1008. # ifdef apollo
  1009. X      bcopy((char *)up, (char *)uq, sizeof(struct utmp));
  1010. X      bzero(uq->ut_name, sizeof(uq->ut_name));
  1011. X      bzero(uq->ut_host, sizeof(uq->ut_host));
  1012. X      if (write(utmpf, (char *)uq, sizeof(struct utmp)) != sizeof(struct utmp))
  1013. # else
  1014. X      if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
  1015. # endif /* apollo */
  1016. #endif
  1017. X        {
  1018. #ifdef NETHACK
  1019. X          if (nethackflag)
  1020. X        {
  1021. X          DeadlyMsg = 0;
  1022. X              Msg(errno, "%s is too hard to dig in.", UTMPFILE); 
  1023. X        }
  1024. X          else
  1025. #endif
  1026. X        {
  1027. X          DeadlyMsg = 0;
  1028. X              Msg(errno, "Could not write %s.", UTMPFILE);
  1029. X        }
  1030. X        }
  1031. X    }
  1032. X  else 
  1033. X    {
  1034. X      debug1("There is no utmp-slot to be removed(%d)\n", slot);
  1035. X    }
  1036. #ifdef apollo
  1037. X  close(utmpf);
  1038. X  free(uq);
  1039. #endif
  1040. }
  1041. X
  1042. char *
  1043. stripdev(nam)
  1044. char *nam;
  1045. {
  1046. #ifdef apollo
  1047. X  char *p;
  1048. X
  1049. X  if (nam == NULL)
  1050. X    return NULL;
  1051. X  if (p = strstr(nam,"/dev/"))
  1052. X    return p + 5;
  1053. #else
  1054. X  if (nam == NULL)
  1055. X    return NULL;
  1056. X  if (strncmp(nam, "/dev/", 5) == 0)
  1057. X    return nam + 5;
  1058. #endif
  1059. X  return nam;
  1060. }
  1061. X
  1062. static slot_t TtyNameSlot(nam)
  1063. char *nam;
  1064. {
  1065. X  char *name;
  1066. X  register slot_t slot;
  1067. #ifndef GETUTENT
  1068. X  register struct ttyent *tp;
  1069. #endif
  1070. #ifdef apollo
  1071. X  struct utmp *up;
  1072. #endif
  1073. X
  1074. X  debug1("TtyNameSlot(%s)\n", nam);
  1075. #ifdef apollo
  1076. X  InitUtmp();
  1077. #endif
  1078. X  if (!utmp || nam == NULL)
  1079. X    return (slot_t)0;
  1080. X  name = stripdev(nam);
  1081. #ifdef GETUTENT
  1082. X  slot = name;
  1083. #else
  1084. # ifdef apollo
  1085. X  slot = 0;
  1086. X  up = (struct utmp *)malloc(sizeof(struct utmp));
  1087. X  while (1)
  1088. X    {
  1089. X      if ((read(utmpf, (char *)up, sizeof(struct utmp)) ==
  1090. X       sizeof(struct utmp)) && (strcmp(up->ut_line, name)))
  1091. X    slot++;
  1092. X      else
  1093. X    break;
  1094. X    }
  1095. X  close(utmpf);
  1096. X  free(up);
  1097. # else /* !apollo */
  1098. X  slot = 1;
  1099. X  setttyent();
  1100. X  while ((tp = getttyent()) != NULL && strcmp(name, tp->ty_name) != 0)
  1101. X    {
  1102. X      debug2("'%s' %d, ", tp->ty_name, slot);
  1103. X      ++slot;
  1104. X    }
  1105. X  debug("\n");
  1106. #  ifdef MIPS
  1107. X  if (tp == NULL)
  1108. X    {
  1109. X      slot = CreateUtmp(name);
  1110. X    }
  1111. #  endif /* MIPS */
  1112. # endif /* apollo */
  1113. #endif /* GETUTENT */
  1114. X  return slot;
  1115. }
  1116. X
  1117. int
  1118. SetUtmp(wi, displaynumber)
  1119. struct win *wi;
  1120. int displaynumber;
  1121. {
  1122. X  register char *p;
  1123. X  register slot_t slot;
  1124. X  char *line;
  1125. X  struct utmp u;
  1126. #ifdef UTHOST
  1127. # ifdef _SEQUENT_
  1128. X  char host[100+5];
  1129. # else
  1130. X  char host[sizeof(utmp_logintty.ut_host)+5];
  1131. # endif
  1132. #endif
  1133. X
  1134. X  wi->slot = (slot_t) 0;
  1135. X  if (!utmp)
  1136. X    return -1;
  1137. X  if ((slot = TtyNameSlot(wi->tty)) == (slot_t) NULL)
  1138. X    {
  1139. X      debug1("SetUtmp failed (tty %s).\n",wi->tty);
  1140. X      return -1;
  1141. X    }
  1142. X  debug2("SetUtmp %d will get slot %d...\n", displaynumber, (int)slot);
  1143. #ifdef apollo
  1144. X  InitUtmp();
  1145. #endif
  1146. X
  1147. #ifdef UTHOST
  1148. X  host[sizeof(host)-5] = '\0';
  1149. # ifdef _SEQUENT_
  1150. X  strncpy(host, loginhost, sizeof(host) - 5);
  1151. # else
  1152. X  strncpy(host, utmp_logintty.ut_host, sizeof(host) - 5);
  1153. # endif
  1154. X  if (loginslot != (slot_t)0 && loginslot != (slot_t)-1 && host[0] != '\0')
  1155. X    {
  1156. X      /*
  1157. X       * we want to set our ut_host field to something like
  1158. X       * ":ttyhf:s.0" or
  1159. X       * "faui45:s.0" or
  1160. X       * "132.199.81.4:s.0" (even this may hurt..), but not
  1161. X       * "faui45.informati"......:s.0
  1162. X       */
  1163. X      for (p = host; *p; p++)
  1164. X    {
  1165. X      if ((*p < '0' || *p > '9') && (*p != '.'))
  1166. X        break;
  1167. X    }
  1168. X      if (*p)
  1169. X    {
  1170. X      for (p = host; *p; p++)
  1171. X        {
  1172. X          if (*p == '.')
  1173. X        {
  1174. X          *p = '\0';
  1175. X          break;
  1176. X        }
  1177. X        }
  1178. X    }
  1179. X    }
  1180. X  else
  1181. X    {
  1182. X      strncpy(host + 1, stripdev(display_tty), sizeof(host) - 6);
  1183. X      host[0] = ':';
  1184. X    }
  1185. X  debug1("rlogin hostname: '%s'\n", host);
  1186. X  sprintf(host + strlen(host), ":S.%c", '0' + displaynumber);
  1187. X  debug1("rlogin hostname: '%s'\n", host);
  1188. #endif /* UTHOST */
  1189. X
  1190. X  line = stripdev(wi->tty);
  1191. X  bzero((char *) &u, sizeof u);
  1192. X
  1193. #ifdef GETUTENT
  1194. # ifdef _SEQUENT_
  1195. X  if (ut_add_user(LoginName, slot, wi->wpid, host)==0)
  1196. # else
  1197. X  strncpy(u.ut_user, LoginName, sizeof(u.ut_user));
  1198. X  strncpy(u.ut_id, line + strlen(line) - 2, sizeof(u.ut_id));
  1199. X  strncpy(u.ut_line, line, sizeof(u.ut_line));
  1200. X  u.ut_pid = wi->wpid;
  1201. X  u.ut_type = USER_PROCESS;
  1202. #  ifdef SVR4
  1203. X    (void) time(&u.ut_tv.tv_sec);
  1204. X    u.ut_tv.tv_usec=0;
  1205. #  else
  1206. X    (void) time(&u.ut_time);
  1207. #  endif /* SVR4 */
  1208. #  ifdef UTHOST
  1209. X  strncpy(u.ut_host, host, sizeof(u.ut_host));
  1210. #  endif /* UTHOST */
  1211. X  if (pututline(&u) == 0)
  1212. # endif /* _SEQUENT_ */
  1213. #else    /* GETUTENT */
  1214. X  strncpy(u.ut_line, line, sizeof(u.ut_line));
  1215. X  strncpy(u.ut_name, LoginName, sizeof(u.ut_name));
  1216. # ifdef UTHOST
  1217. X  strncpy(u.ut_host, host, sizeof(u.ut_host));
  1218. # endif    /* UTHOST */
  1219. # ifdef MIPS
  1220. X  u.ut_type = 7; /* USER_PROCESS */
  1221. X  strncpy(u.ut_id, line + 3, 4);
  1222. # endif /* MIPS */
  1223. X  (void) time(&u.ut_time);
  1224. # ifdef sequent
  1225. /* call sequent undocumented routine to count logins and add utmp entry if possible */
  1226. X  if (add_utmp(slot, &u) == -1)
  1227. # else
  1228. X  (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  1229. X  if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
  1230. # endif /* sequent */
  1231. #endif    /* GETUTENT */
  1232. X
  1233. X    {
  1234. #ifdef NETHACK
  1235. X      if (nethackflag)
  1236. X        Msg(errno, "%s is too hard to dig in.", UTMPFILE);
  1237. X      else
  1238. #endif
  1239. X      Msg(errno,"Could not write %s.", UTMPFILE);
  1240. #ifdef apollo
  1241. X      close(utmpf);
  1242. #endif
  1243. X      return -1;
  1244. X    }
  1245. X  debug("SetUtmp successful\n");
  1246. X  wi->slot = slot;
  1247. #ifdef apollo
  1248. X  close(utmpf);
  1249. #endif
  1250. X  return 0;
  1251. }
  1252. X
  1253. #ifdef MIPS
  1254. X
  1255. #define GETTTYENT
  1256. static int ttyfd = 0;
  1257. X
  1258. static void setttyent()
  1259. {
  1260. X  if (ttyfd)
  1261. X    close(ttyfd);
  1262. X  ttyfd = open(UtmpName, O_RDONLY);
  1263. }
  1264. X
  1265. static struct ttyent *getttyent()
  1266. {
  1267. X  static struct utmp u;
  1268. X  static struct ttyent t;
  1269. X
  1270. X  if (!ttyfd)
  1271. X    return NULL;
  1272. X  
  1273. X  if (read(ttyfd, &u, sizeof u)) 
  1274. X    {
  1275. X      t.ty_name = u.ut_line;
  1276. X      return &t;
  1277. X    }
  1278. X  return NULL;
  1279. }
  1280. X
  1281. CreateUtmp(name)
  1282. char *name;
  1283. {
  1284. X  int slot;
  1285. X  struct utmp u;
  1286. X
  1287. X  strncpy(u.ut_line, name, 8);
  1288. X  strncpy(u.ut_name, LoginName, 8);
  1289. X  u.ut_type = 7; /* USER_PROCESS */
  1290. X  strncpy(u.ut_id, name+3, 4);
  1291. X  (void) time(&u.ut_time);
  1292. X  slot = (lseek(utmpfappend, 0, 2) + 1) / sizeof u;
  1293. X  (void) write(utmpfappend, (char *)&u, sizeof u);
  1294. X  close(utmpfappend);
  1295. X  if ((utmpfappend = open(UtmpName, O_APPEND)) == -1) 
  1296. X    {
  1297. X      if (errno != EACCES)
  1298. X        Msg(errno, UtmpName);
  1299. X      return;
  1300. X    }
  1301. X  return slot;
  1302. }
  1303. #endif /* MIPS */
  1304. X
  1305. /*
  1306. X * if slot could be removed or was 0,  wi->slot = -1;
  1307. X * else not changed.
  1308. X */
  1309. int
  1310. RemoveUtmp(wi)
  1311. struct win *wi;
  1312. {
  1313. #ifdef GETUTENT
  1314. X  struct utmp *uu;
  1315. #endif
  1316. #ifdef apollo
  1317. X  struct utmp *up;
  1318. #endif
  1319. X  struct utmp u;
  1320. X  slot_t slot;
  1321. X
  1322. X  slot = wi->slot;
  1323. #ifdef GETUTENT
  1324. X  debug1("RemoveUtmp(%s)\n", (slot == (slot_t) 0) ?
  1325. X         "no slot (0)":((slot == (slot_t) -1) ? "no slot (-1)" : slot));
  1326. #else
  1327. X  debug1("RemoveUtmp(wi.slot: %d)\n", slot);
  1328. #endif
  1329. #ifdef apollo
  1330. X  InitUtmp();
  1331. X  up = (struct utmp *)malloc(sizeof(struct utmp));
  1332. X  bzero((char *)up, sizeof(struct utmp));
  1333. #endif /* apollo */
  1334. X  if (!utmp)
  1335. X    return -1;
  1336. X  if (slot == (slot_t) 0 || slot == (slot_t) -1)
  1337. X    {
  1338. X      debug1("There is no utmp-slot to be removed(%d)\n", slot);
  1339. X      wi->slot = (slot_t) -1;
  1340. X      return 0;
  1341. X    }
  1342. X  bzero((char *) &u, sizeof u);
  1343. #ifdef GETUTENT
  1344. X  setutent();
  1345. X  strncpy(u.ut_line, slot, sizeof(u.ut_line));
  1346. X  if ((uu = getutline(&u)) == 0)
  1347. X    {
  1348. X      Msg(0, "Utmp slot not found -> not removed");
  1349. X      return -1;
  1350. X    }
  1351. # ifdef _SEQUENT_
  1352. X  if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
  1353. # else
  1354. X  uu->ut_type = DEAD_PROCESS;
  1355. X  uu->ut_exit.e_termination = 0;
  1356. X  uu->ut_exit.e_exit= 0;
  1357. X  if (pututline(uu) == 0)
  1358. # endif
  1359. #else    /* GETUTENT */
  1360. X  (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  1361. # ifdef apollo
  1362. X  if (read(utmpf, (char *) up, sizeof u) != sizeof u)
  1363. X    {
  1364. X      DeadlyMsg = 0;
  1365. X      Msg(errno, "cannot read %s?", UTMPFILE);
  1366. X      sleep(1);
  1367. X    }
  1368. X  (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  1369. X  bzero(up->ut_name, sizeof(u.ut_name));
  1370. X  bzero(up->ut_host, sizeof(u.ut_host));
  1371. X  if (write(utmpf, (char *)up, sizeof u) != sizeof u)
  1372. # else
  1373. X  if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
  1374. # endif /* apollo */
  1375. #endif
  1376. X    {
  1377. #ifdef NETHACK
  1378. X      if (nethackflag)
  1379. X        Msg(errno, "%s is too hard to dig in.", UTMPFILE);
  1380. X      else
  1381. #endif
  1382. X      Msg(errno,"Could not write %s.", UTMPFILE);
  1383. #ifdef apollo
  1384. X      close(utmpf);
  1385. X      free(up);
  1386. #endif
  1387. X      return -1;
  1388. X    }
  1389. X  debug("RemoveUtmp successfull\n");
  1390. X  wi->slot = (slot_t) -1;
  1391. #ifdef apollo
  1392. X  close(utmpf);
  1393. X  free(up);
  1394. #endif
  1395. X  return 0;
  1396. }
  1397. X
  1398. #endif    /* UTMPOK */
  1399. X
  1400. #if !defined(GETTTYENT) && !defined(GETUTENT)
  1401. X
  1402. static void setttyent()
  1403. {
  1404. X  struct stat s;
  1405. X  register int f;
  1406. X  register char *p, *ep;
  1407. X
  1408. X  if (ttnext)
  1409. X    {
  1410. X      ttnext = tt;
  1411. X      return;
  1412. X    }
  1413. X  if ((f = open(ttys, O_RDONLY)) == -1 || fstat(f, &s) == -1)
  1414. X    Msg(errno, ttys);
  1415. X  if ((tt = malloc((unsigned) s.st_size + 1)) == 0)
  1416. X    Msg_nomem;
  1417. X  if (read(f, tt, s.st_size) != s.st_size)
  1418. X    Msg(errno, ttys);
  1419. X  close(f);
  1420. X  for (p = tt, ep = p + s.st_size; p < ep; ++p)
  1421. X    if (*p == '\n')
  1422. X      *p = '\0';
  1423. X  *p = '\0';
  1424. X  ttnext = tt;
  1425. }
  1426. X
  1427. static struct ttyent *getttyent()
  1428. {
  1429. X  static struct ttyent t;
  1430. X
  1431. X  if (*ttnext == '\0')
  1432. X    return NULL;
  1433. X  t.ty_name = ttnext + 2;
  1434. X  ttnext += strlen(ttnext) + 1;
  1435. X  return &t;
  1436. }
  1437. X
  1438. #endif    /* GETTTYENT */
  1439. X
  1440. #ifdef LOADAV
  1441. # ifdef LOADAV_NEXT
  1442. void
  1443. InitNeXTLoadAvg()
  1444. {
  1445. X  error = processor_set_default(host_self(), &default_set);
  1446. X  if (error != KERN_SUCCESS)
  1447. X    mach_error("Error calling processor_set_default", error);
  1448. X  else
  1449. X    avenrun = 1;
  1450. }
  1451. X
  1452. int
  1453. GetAvenrun()
  1454. {
  1455. X  info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
  1456. X  error = processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, &host,
  1457. X                 (processor_set_info_t)&info, &info_count);
  1458. X  if (error != KERN_SUCCESS)
  1459. X    {
  1460. X      mach_error("Error calling processor_set_info", error);
  1461. X      return 0;
  1462. X    }
  1463. X  else
  1464. X    {
  1465. X      loadav = (float)info.load_average / LOAD_SCALE;
  1466. X      return 1;
  1467. X    }
  1468. }
  1469. X
  1470. # else /* need kmem for load avg */
  1471. X
  1472. void
  1473. InitKmem()
  1474. {
  1475. X  debug("Init Kmem...\n");
  1476. #  ifndef apollo
  1477. X  if ((kmemf = open(KmemName, O_RDONLY)) == -1)
  1478. X    return;
  1479. X  debug("Kmem opened\n");
  1480. X  nl[0].n_name = AvenrunSym;
  1481. X  debug2("Searching in %s for %s\n", UnixName, nl[0].n_name);
  1482. X  nlist(UnixName, nl);
  1483. X  if (/* nl[0].n_type == 0 || */ nl[0].n_value == 0)
  1484. X    {
  1485. X      close(kmemf);
  1486. X      return;
  1487. X    }
  1488. #   ifdef sgi
  1489. X  nl[0].n_value &= ~(1 << 31); /* clear upper bit */
  1490. #   endif /* sgi */
  1491. X  debug("AvenrunSym found!!\n");
  1492. #  endif /* apollo */
  1493. X  avenrun = 1;
  1494. }
  1495. X
  1496. int
  1497. GetAvenrun()
  1498. {
  1499. # ifdef apollo
  1500. X  int load[3];
  1501. X  register int i;
  1502. X
  1503. X  proc1_$get_loadav(load);
  1504. X  for (i = 0; i < 3; i++)
  1505. X    loadav[i] = (double)load[i] / 65536.0;
  1506. # else
  1507. X  if (lseek(kmemf, (off_t) nl[0].n_value, 0) == (off_t) - 1)
  1508. X    return 0;
  1509. X  if (read(kmemf, (char *) loadav, sizeof loadav) != sizeof loadav)
  1510. X    return 0;
  1511. # endif /* apollo */
  1512. X
  1513. X  return 1;
  1514. }
  1515. X
  1516. # endif /* !NeXT, need kmem for load avg */
  1517. #endif    /* LOADAV */
  1518. X
  1519. /*
  1520. X * (Almost) secure open and fopen... mlschroe.
  1521. X */
  1522. X
  1523. FILE *
  1524. secfopen(name, mode)
  1525. char *name;
  1526. char *mode;
  1527. {
  1528. X  FILE *fi;
  1529. #ifdef NOREUID
  1530. X  int flags, fd;
  1531. #endif
  1532. X
  1533. X  debug2("secfopen(%s, %s)\n", name, mode);
  1534. X  if (eff_uid == real_uid)
  1535. X    return(fopen(name, mode));
  1536. #ifndef NOREUID
  1537. X  setreuid(eff_uid, real_uid);
  1538. X  setregid(eff_gid, real_gid);
  1539. X  fi = fopen(name, mode);
  1540. X  setreuid(real_uid, eff_uid);
  1541. X  setregid(real_gid, eff_gid);
  1542. #else
  1543. X  if (mode[0] && mode[1] == '+')
  1544. X    flags = O_RDWR;
  1545. X  else
  1546. X    flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY;
  1547. X  if (mode[0] == 'w')
  1548. X    flags |= O_CREAT | O_TRUNC;
  1549. X  else if (mode[0] == 'a')
  1550. X    flags |= O_CREAT | O_APPEND;
  1551. X  else if (mode[0] != 'r')
  1552. X    {
  1553. X      errno = EINVAL;
  1554. X      return(0);
  1555. X    }
  1556. X  if ((fd = secopen(name, flags, 0666)) < 0)
  1557. X    return(0);
  1558. X  if ((fi = fdopen(fd, mode)) == 0)
  1559. X    {
  1560. X      close(fd);
  1561. X      return(0);
  1562. X    }
  1563. #endif
  1564. X  return(fi);
  1565. }
  1566. X
  1567. X
  1568. int
  1569. secopen(name, flags, mode)
  1570. char *name;
  1571. int flags;
  1572. int mode;
  1573. {
  1574. X  int fd;
  1575. #ifdef NOREUID
  1576. X  int q;
  1577. X  struct stat stb;
  1578. #endif
  1579. X
  1580. X  debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode);
  1581. X  if (eff_uid == real_uid)
  1582. X    return(open(name, flags, mode));
  1583. #ifndef NOREUID
  1584. X  setreuid(eff_uid, real_uid);
  1585. X  setregid(eff_gid, real_gid);
  1586. X  fd = open(name, flags, mode);
  1587. X  setreuid(real_uid, eff_uid);
  1588. X  setregid(real_gid, eff_gid);
  1589. #else
  1590. X  /* Truncation/creation is done in UserContext */
  1591. X  if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK)))
  1592. X    {
  1593. X      if (UserContext() > 0)
  1594. X    {
  1595. X          if ((fd = open(name, flags, mode)) >= 0)
  1596. X        {
  1597. X          close(fd);
  1598. X          UserReturn(0);
  1599. X            }
  1600. X      if (errno == 0)
  1601. X        errno = EACCES;
  1602. X      UserReturn(errno);
  1603. X    }
  1604. X      if (q = UserStatus())
  1605. X    {
  1606. X      if (q > 0)
  1607. X        errno = q;
  1608. X          return(-1);
  1609. X    }
  1610. X    }
  1611. X  if (access(name, F_OK))
  1612. X    return(-1);
  1613. X  if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0)
  1614. X    return(-1);
  1615. X  debug("open successful\n");
  1616. X  if (fstat(fd, &stb))
  1617. X    {
  1618. X      close(fd);
  1619. X      return(-1);
  1620. X    }
  1621. X  debug("fstat successful\n");
  1622. X  if (stb.st_uid != real_uid)
  1623. X    {
  1624. X      switch (flags & (O_RDONLY | O_WRONLY | O_RDWR))
  1625. X        {
  1626. X    case O_RDONLY:
  1627. X      q = 0004;
  1628. X      break;
  1629. X    case O_WRONLY:
  1630. X      q = 0002;
  1631. X      break;
  1632. X    default:
  1633. X      q = 0006;
  1634. X      break;
  1635. X        }
  1636. X      if ((stb.st_mode & q) != q)
  1637. X    {
  1638. X          debug("secopen: permission denied\n");
  1639. X      close(fd);
  1640. X      errno = EACCES;
  1641. X      return(-1);
  1642. X    }
  1643. X    }
  1644. #endif
  1645. X  debug1("secopen ok - returning %d\n", fd);
  1646. X  return(fd);
  1647. }
  1648. X
  1649. #ifdef BUGGYGETLOGIN
  1650. char *
  1651. getlogin()
  1652. {
  1653. X  char *tty;
  1654. #ifdef utmp
  1655. # undef utmp
  1656. #endif
  1657. X  struct utmp u;
  1658. X  static char retbuf[sizeof(u.ut_user)+1];
  1659. X  int fd;
  1660. X
  1661. X  for (fd = 0; fd <= 2 && (tty = ttyname(fd)) == NULL; fd++)
  1662. X    ;
  1663. X  if ((tty == NULL) || ((fd = open(UTMP_FILE, O_RDONLY)) < 0))
  1664. X    return NULL;
  1665. X  tty = stripdev(tty);
  1666. X  retbuf[0] = '\0';
  1667. X  while (read(fd, &u, sizeof(struct utmp)) == sizeof(struct utmp))
  1668. X    {
  1669. X      if (!strncmp(tty, u.ut_line, sizeof(u.ut_line)))
  1670. X    {
  1671. X      strncpy(retbuf, u.ut_user, sizeof(u.ut_user));
  1672. X      retbuf[sizeof(u.ut_user)] = '\0';
  1673. X      if (u.ut_type == USER_PROCESS)
  1674. X        break;
  1675. X    }
  1676. X    }
  1677. X  close(fd);
  1678. X
  1679. X  return *retbuf ? retbuf : NULL;
  1680. }
  1681. #endif
  1682. SHAR_EOF
  1683. echo 'File screen3.2/fileio.c is complete' &&
  1684. chmod 0444 screen3.2/fileio.c ||
  1685. echo 'restore of screen3.2/fileio.c failed'
  1686. Wc_c="`wc -c < 'screen3.2/fileio.c'`"
  1687. test 54830 -eq "$Wc_c" ||
  1688.     echo 'screen3.2/fileio.c: original size 54830, current size' "$Wc_c"
  1689. rm -f _shar_wnt_.tmp
  1690. fi
  1691. # ============= screen3.2/help.c ==============
  1692. if test -f 'screen3.2/help.c' -a X"$1" != X"-c"; then
  1693.     echo 'x - skipping screen3.2/help.c (File already exists)'
  1694.     rm -f _shar_wnt_.tmp
  1695. else
  1696. > _shar_wnt_.tmp
  1697. echo 'x - extracting screen3.2/help.c (Text)'
  1698. sed 's/^X//' << 'SHAR_EOF' > 'screen3.2/help.c' &&
  1699. /* Copyright (c) 1991
  1700. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  1701. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  1702. X * Copyright (c) 1987 Oliver Laumann
  1703. X *
  1704. X * This program is free software; you can redistribute it and/or modify
  1705. X * it under the terms of the GNU General Public License as published by
  1706. X * the Free Software Foundation; either version 1, or (at your option)
  1707. X * any later version.
  1708. X *
  1709. X * This program is distributed in the hope that it will be useful,
  1710. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1711. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1712. X * GNU General Public License for more details.
  1713. X *
  1714. X * You should have received a copy of the GNU General Public License
  1715. X * along with this program (see the file COPYING); if not, write to the
  1716. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1717. X *
  1718. X * Noteworthy contributors to screen's design and implementation:
  1719. X *    Wayne Davison (davison@borland.com)
  1720. X *    Patrick Wolfe (pat@kai.com, kailand!pat)
  1721. X *    Bart Schaefer (schaefer@cse.ogi.edu)
  1722. X *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  1723. X *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  1724. X *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  1725. X *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  1726. X *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  1727. X *    Marc Boucher (marc@CAM.ORG)
  1728. X *
  1729. X ****************************************************************
  1730. X */
  1731. X
  1732. #ifndef lint
  1733. X  static char rcs_id[] = "$Id: help.c,v 1.2 92/02/03 02:28:33 jnweiger Exp $ FAU";
  1734. #endif
  1735. X
  1736. #include "config.h"
  1737. #include <stdio.h>
  1738. #include <sys/types.h>
  1739. X
  1740. #ifdef BSDI
  1741. # include <sys/signal.h>
  1742. #endif /* BSDI */
  1743. X
  1744. #include "screen.h"
  1745. #include "ansi.h"
  1746. #include "extern.h"
  1747. #include "patchlevel.h"
  1748. X
  1749. int help_page = 0;
  1750. int command_search, command_bindings = 0;
  1751. extern char Esc, MetaEsc;
  1752. extern char *KeyNames[];
  1753. extern struct key ktab[];
  1754. extern int screenwidth, screenheight;
  1755. extern char *blank, *null, *CE;
  1756. extern struct win *fore;
  1757. X
  1758. static void centerline __P((char *));
  1759. static void HelpRedisplayLine __P((int, int, int, int));
  1760. static void process_help_input __P((char **, int *));
  1761. static void AbortHelp __P((void));
  1762. static void add_key_to_buf __P((char *, int));
  1763. X
  1764. void
  1765. exit_with_usage(myname)
  1766. char *myname;
  1767. {
  1768. X  printf("Use: %s [-opts] [cmd [args]]\n", myname);
  1769. X  printf(" or: %s -r [host.tty]\n\nOptions:\n", myname);
  1770. X  printf("-a           Force all capabilities into each window's termcap\n");
  1771. X  printf("-A -[r|R]    Adapt all windows to the new display width & height\n");
  1772. X  printf("-c file      Read configuration file instead of .screenrc\n");
  1773. #ifdef REMOTE_DETACH
  1774. X  printf("-d (-r)      Detach the elsewhere running screen (and reattach here)\n");
  1775. X  printf("-D (-r)      Detach and logout remote (and reattach here)\n");
  1776. #endif
  1777. X  printf("-e xy        Change command characters\n");
  1778. X  printf("-f           Flow control on, -fn = off, -fa = auto\n");
  1779. X  printf("-h lines     Set the size of the scrollback history buffer\n");
  1780. X  printf("-i           Interrupt output sooner when flow control is on\n");
  1781. X  printf("-l           Login mode on (update %s), -ln = off\n", UTMPFILE);
  1782. X  printf("-list        or -ls. Do nothing, just list our SockDir\n");
  1783. X  printf("-L           Terminal's last character can be safely updated\n");
  1784. X  printf("-O           Choose optimal output rather than exact vt100 emulation\n");
  1785. X  printf("-q           Quiet startup. Sets $status if unsuccessful.\n");
  1786. X  printf("-r           Reattach to a detached screen process\n");
  1787. X  printf("-R           Reattach if possible, otherwise start a new session\n");
  1788. X  printf("-s shell     Shell to execute rather than $SHELL\n");
  1789. X  printf("-T term      Use term as $TERM for windows, rather than \"screen\"\n");
  1790. X  printf("-t title     Set command's a.k.a. (window title)\n");
  1791. X  printf("-wipe        Do nothing, just clean up SockDir\n");
  1792. X  exit(1);
  1793. }
  1794. X
  1795. /* Esc-char is not consumed. All others are. Esc-char, space, and return end */
  1796. static void
  1797. process_help_input(ppbuf, plen)
  1798. char **ppbuf;
  1799. int *plen;
  1800. {
  1801. X  int done = 0;
  1802. X
  1803. X  if (ppbuf == 0)
  1804. X    {
  1805. X      AbortHelp();
  1806. X      return;
  1807. X    }
  1808. X  while (!done && *plen > 0)
  1809. X    {
  1810. X      switch (**ppbuf)
  1811. X    {
  1812. X    case ' ':
  1813. X      if (display_help() == 0)
  1814. X            break;
  1815. X      /* FALLTHROUGH */
  1816. X    case '\r':
  1817. X    case '\n':
  1818. X      done = 1;
  1819. X      break;
  1820. X    default:
  1821. X      if (**ppbuf == Esc)
  1822. X        {
  1823. X          done = 1;
  1824. X          continue;
  1825. X        }
  1826. X      break;
  1827. X    }
  1828. X      ++*ppbuf;
  1829. X      --*plen;
  1830. X    }
  1831. X  if (done)
  1832. X    AbortHelp();
  1833. }
  1834. X
  1835. static void
  1836. AbortHelp()
  1837. {
  1838. X  help_page = 0;
  1839. X  ExitOverlayPage();
  1840. X  Activate(0);
  1841. }
  1842. X
  1843. static int maxrow, grow, numcols, numrows, num_names;
  1844. static int numskip, numpages;
  1845. X
  1846. int
  1847. display_help()
  1848. {
  1849. X  int col, crow, n, key = 0;
  1850. X  enum keytype typ = ktab[0].type;
  1851. X  char buf[256], Esc_buf[5], cbuf[256];
  1852. X
  1853. X  if (!help_page++)
  1854. X    {
  1855. X      if (screenwidth < 26 || screenheight < 6)
  1856. X        {
  1857. X      Msg(0, "Window size too small for help page");
  1858. X      help_page = 0;
  1859. X      return -1;
  1860. X        }
  1861. X      InitOverlayPage(process_help_input, HelpRedisplayLine, (int (*)())0, 0);
  1862. X
  1863. X      command_bindings = 0;
  1864. X      for (key = 0; key < 256; key++)
  1865. X        if ((typ = ktab[key].type) == KEY_CREATE
  1866. X        || typ == KEY_SCREEN
  1867. X        || typ == KEY_SET
  1868. X        || (typ == KEY_AKA && ktab[key].args))
  1869. X      command_bindings++;
  1870. X      debug1("help: command_bindings counted: %d\n",command_bindings);
  1871. X      for (n = 0; KeyNames[n] != NULL; n++)
  1872. X    ; /* we dont know "sizeof * KeyNames" */
  1873. X      num_names = n - 1;
  1874. X      debug1("help: we find %d named keys (+1).\n", num_names);
  1875. X      command_search = 0;
  1876. X
  1877. X      numcols = screenwidth/26;
  1878. X      if (numcols == 0)
  1879. X        numcols = 1;
  1880. X      numrows = (num_names + numcols -1) / numcols;
  1881. X      debug1("Numrows: %d\n", numrows);
  1882. X      numskip = screenheight-5 - (2 + numrows);
  1883. X      while (numskip < 0)
  1884. X    numskip += screenheight-5;
  1885. X      numskip %= screenheight-5;
  1886. X      debug1("Numskip: %d\n", numskip);
  1887. X      if (numskip > screenheight/3 || numskip > command_bindings)
  1888. X    numskip = 1;
  1889. X      maxrow = 2 + numrows + numskip + command_bindings;
  1890. X      grow = 0;
  1891. X
  1892. X      numpages = (maxrow + screenheight-6) / (screenheight-5);
  1893. X    }
  1894. X
  1895. X  if (grow >= maxrow)
  1896. X    { 
  1897. X      return(-1);
  1898. X    }
  1899. X
  1900. X  /* Clear the help screen */
  1901. X  ClearDisplay();
  1902. X  
  1903. X  sprintf(cbuf,"Screen key bindings, page %d of %d.", help_page, numpages);
  1904. X  centerline(cbuf);
  1905. X  printf("\n");
  1906. X  crow = 2;
  1907. X
  1908. X  *Esc_buf = '\0';
  1909. X  add_key_to_buf(Esc_buf, Esc);
  1910. X  Esc_buf[strlen(Esc_buf) - 1] = '\0';
  1911. X
  1912. X  for (; crow < screenheight - 3; crow++)
  1913. X    {
  1914. X      if (grow < 1)
  1915. X        {
  1916. X         *buf = '\0';
  1917. X          add_key_to_buf(buf, MetaEsc);
  1918. X          buf[strlen(buf) - 1] = '\0';
  1919. X          sprintf(cbuf,"Command key:  %s   Literal %s:  %s", Esc_buf, Esc_buf, buf);
  1920. X          centerline(cbuf);
  1921. X      grow++;
  1922. X        }
  1923. X      else if (grow >= 2 && grow-2 < numrows)
  1924. X    {
  1925. X      for (col = 0; col < numcols && (n = numrows * col + (grow-2)) < num_names; col++)
  1926. X        {
  1927. X          debug1("help: searching key %d\n", n);
  1928. X          buf[0] = '\0';
  1929. X          for (key = 0; key < 128; key++)
  1930. X        if (ktab[key].type == (enum keytype) (n + 2)
  1931. X            && ((enum keytype) (n + 2) != KEY_AKA || !ktab[key].args) )
  1932. X          add_key_to_buf(buf, key);
  1933. X          buf[14] = '\0';
  1934. X          /*
  1935. X           * Format is up to 10 chars of name, 1 spaces, 14 chars of key
  1936. X           * bindings, and a space.
  1937. X           */
  1938. X          printf("%-10.10s %-14.14s ", KeyNames[n + 1], buf);
  1939. X        }
  1940. X      printf("\r\n");
  1941. X          grow++;
  1942. X        }
  1943. X      else if (grow-2-numrows >= numskip 
  1944. X               && grow-2-numrows-numskip < command_bindings)
  1945. X        {
  1946. X          char **pp, *cp;
  1947. X
  1948. X      while (command_search < 128
  1949. X         && (typ = ktab[command_search].type) != KEY_CREATE
  1950. X         && typ != KEY_SCREEN
  1951. X         && typ != KEY_SET
  1952. X         && (typ != KEY_AKA || !ktab[command_search].args))
  1953. X        command_search++;
  1954. X      buf[0] = '\0';
  1955. X      add_key_to_buf(buf, command_search);
  1956. X      printf("%-4s", buf);
  1957. X      col = 4;
  1958. X      if (typ != KEY_CREATE)
  1959. X        {
  1960. X          col += strlen(KeyNames[(int)typ - 1]) + 1;
  1961. X          printf("%s ", KeyNames[(int)typ - 1]);
  1962. X        }
  1963. X      pp = ktab[command_search++].args;
  1964. X      while (pp && (cp = *pp) != NULL)
  1965. X        {
  1966. X          if (!*cp || (index(cp, ' ') != NULL))
  1967. X        {
  1968. X          if (index(cp, '\'') != NULL)
  1969. X            *buf = '"';
  1970. X          else
  1971. X            *buf = '\'';
  1972. X          sprintf(buf + 1, "%s%c", cp, *buf);
  1973. X          cp = buf;
  1974. X        }
  1975. X          if ((col += strlen(cp) + 1) >= screenwidth)
  1976. X        {
  1977. X          col = screenwidth - (col - (strlen(cp) + 1)) - 2;
  1978. X          if (col >= 0)
  1979. X            {
  1980. X              n = cp[col];
  1981. X              cp[col] = '\0';
  1982. X              printf("%s$", *pp);
  1983. X              cp[col] = (char) n;
  1984. X              }
  1985. X              break;
  1986. X            }
  1987. X          printf("%s%c", cp, (screenwidth - col != 1 || !pp[1]) ? ' ' : '$');
  1988. X          pp++;
  1989. X        }
  1990. X      printf("\r\n");
  1991. X      grow++;
  1992. X    }
  1993. X      else
  1994. X    {
  1995. X          putchar('\n');
  1996. X      grow++;
  1997. X    }
  1998. X    }
  1999. X  printf("\n");
  2000. X  sprintf(cbuf,"[Press Space %s Return to end; %s to begin a command.]",
  2001. X     grow < maxrow ? "for next page;" : "or", Esc_buf);
  2002. X  centerline(cbuf);
  2003. X  fflush(stdout);
  2004. X  SetLastPos(0, screenheight-1);
  2005. X  return(0);
  2006. }
  2007. X
  2008. static void
  2009. add_key_to_buf(buf, key)
  2010. char *buf;
  2011. int key;
  2012. {
  2013. X  debug1("help: key found: %c\n", key);
  2014. X  switch (key)
  2015. X    {
  2016. X    case ' ':
  2017. X      strcat(buf, "sp ");
  2018. X      break;
  2019. X    case 0x7f:
  2020. X      strcat(buf, "^? ");
  2021. X      break;
  2022. X    default:
  2023. X      if (key < ' ')
  2024. X    sprintf(buf + strlen(buf), "^%c ", (key | 0x40));
  2025. X      else
  2026. X    sprintf(buf + strlen(buf), "%c ", key);
  2027. X      break;
  2028. X    }
  2029. }
  2030. X
  2031. static void
  2032. centerline(str)
  2033. char *str;
  2034. {
  2035. X  int l;
  2036. X  l = (screenwidth - 1 + strlen(str)) / 2;
  2037. X  if (l > screenwidth - 1)
  2038. X    l = screenwidth - 1;
  2039. X  printf("%*.*s\r\n", l, l, str);
  2040. }
  2041. X
  2042. static void
  2043. HelpRedisplayLine(y, xs, xe, isblank)
  2044. int y, xs, xe, isblank;
  2045. {
  2046. X  if (isblank)
  2047. X    return;
  2048. X  if (CE)
  2049. X    {
  2050. X      GotoPos(xs, y);
  2051. X      PutStr(CE);
  2052. X      return;
  2053. X    }
  2054. X  DisplayLine(null, null, null, blank, null, null, y, xs, xe);
  2055. }
  2056. X
  2057. /*
  2058. X * here all the copyright stuff 
  2059. X */
  2060. X
  2061. X
  2062. static char version[40];
  2063. X
  2064. static char cpmsg[] = "\
  2065. \n\
  2066. iScreen version %v\n\
  2067. \n\
  2068. Copyright (c) 1991\n\
  2069. X    Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)\n\
  2070. X    Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)\n\
  2071. Copyright (c) 1987 Oliver Laumann\n\
  2072. \n\
  2073. This program is free software; you can redistribute it and/or \
  2074. modify it under the terms of the GNU General Public License as published \
  2075. by the Free Software Foundation; either version 1, or (at your option) \
  2076. any later version.\n\
  2077. \n\
  2078. This program is distributed in the hope that it will be useful, \
  2079. but WITHOUT ANY WARRANTY; without even the implied warranty of \
  2080. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \
  2081. GNU General Public License for more details.\n\
  2082. \n\
  2083. You should have received a copy of the GNU General Public License \
  2084. along with this program (see the file COPYING); if not, write to the \
  2085. Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n";
  2086. X
  2087. X
  2088. static void process_copyright_input __P((char **, int *));
  2089. static void AbortCopyright __P((void));
  2090. static void copypage __P((void));
  2091. X
  2092. static char *cps, *savedcps;
  2093. X
  2094. static void
  2095. process_copyright_input(ppbuf, plen)
  2096. char **ppbuf;
  2097. int *plen;
  2098. {
  2099. X  int done = 0;
  2100. X
  2101. X  if (ppbuf == 0)
  2102. X    {
  2103. X      AbortCopyright();
  2104. X      return;
  2105. X    }
  2106. X  while (!done && *plen > 0)
  2107. X    {
  2108. X      switch (**ppbuf)
  2109. X    {
  2110. X    case ' ':
  2111. X          if (*cps)
  2112. X        {
  2113. X          copypage();
  2114. X          break;
  2115. X        }
  2116. X      /* FALLTHROUGH */
  2117. X    case '\r':
  2118. X    case '\n':
  2119. X      AbortCopyright();
  2120. X      done = 1;
  2121. X      break;
  2122. X    default:
  2123. X      break;
  2124. X    }
  2125. X      ++*ppbuf;
  2126. X      --*plen;
  2127. X    }
  2128. }
  2129. X
  2130. static void
  2131. AbortCopyright()
  2132. {
  2133. X  ExitOverlayPage();
  2134. X  Activate(0);
  2135. }
  2136. X
  2137. void
  2138. display_copyright()
  2139. {
  2140. X  if (screenwidth < 10 || screenheight < 5)
  2141. X    {
  2142. X      Msg(0, "Window size too small for copyright page");
  2143. X      return;
  2144. X    }
  2145. X  InitOverlayPage(process_copyright_input, HelpRedisplayLine, (int (*)())0, 0);
  2146. X  sprintf(version, "%d.%.2d.%.2d%s (%s) %s", REV, VERS, PATCHLEVEL, STATE, ORIGIN, DATE);
  2147. X  cps = cpmsg;
  2148. X  savedcps = 0;
  2149. X  copypage();
  2150. }
  2151. X
  2152. X
  2153. static void
  2154. copypage()
  2155. {
  2156. X  char *ws;
  2157. X  int x, y, l;
  2158. X  char cbuf[80];
  2159. X
  2160. X  ClearDisplay();
  2161. X  x = y = 0;
  2162. X  while(*cps)
  2163. X    {
  2164. X      ws = cps;
  2165. X      while (*cps == ' ')
  2166. X    cps++;
  2167. X      if (strncmp(cps, "%v", 2) == 0)
  2168. X    {
  2169. X      savedcps = cps + 2;
  2170. X      ws = cps = version;
  2171. X    }
  2172. X      while (*cps && *cps != ' ' && *cps != '\n')
  2173. X    cps++;
  2174. X      l = cps - ws;
  2175. X      cps = ws;
  2176. X      if (l > screenwidth - 1)
  2177. X    l = screenwidth - 1;
  2178. X      if (x && x + l >= screenwidth - 2)
  2179. X    {
  2180. X      printf("\r\n");
  2181. X      x = 0;
  2182. X      if (++y > screenheight - 4)
  2183. X            break;
  2184. X    }
  2185. X      if (x)
  2186. X    {
  2187. X      putchar(' ');
  2188. X      x++;
  2189. X    }
  2190. X      if (l)
  2191. X        printf("%*.*s", l, l, ws);
  2192. X      x += l;
  2193. X      cps += l;
  2194. X      if (*cps == 0 && savedcps)
  2195. X    {
  2196. X      cps = savedcps;
  2197. X      savedcps = 0;
  2198. X    }
  2199. X      if (*cps == '\n')
  2200. X    {
  2201. X      printf("\r\n");
  2202. X      x = 0;
  2203. X      if (++y > screenheight - 4)
  2204. X            break;
  2205. X    }
  2206. X      if (*cps == ' ' || *cps == '\n')
  2207. X    cps++;
  2208. X    }
  2209. X  while (y++ < screenheight - 2)
  2210. X    printf("\r\n");
  2211. X  sprintf(cbuf,"[Press Space %s Return to end.]",
  2212. X     *cps ? "for next page;" : "or");
  2213. X  centerline(cbuf);
  2214. X  fflush(stdout);
  2215. X  SetLastPos(0, screenheight-1);
  2216. }
  2217. X  
  2218. SHAR_EOF
  2219. chmod 0444 screen3.2/help.c ||
  2220. echo 'restore of screen3.2/help.c failed'
  2221. Wc_c="`wc -c < 'screen3.2/help.c'`"
  2222. test 12878 -eq "$Wc_c" ||
  2223.     echo 'screen3.2/help.c: original size 12878, current size' "$Wc_c"
  2224. rm -f _shar_wnt_.tmp
  2225. fi
  2226. # ============= screen3.2/mark.c ==============
  2227. if test -f 'screen3.2/mark.c' -a X"$1" != X"-c"; then
  2228.     echo 'x - skipping screen3.2/mark.c (File already exists)'
  2229.     rm -f _shar_wnt_.tmp
  2230. else
  2231. > _shar_wnt_.tmp
  2232. echo 'x - extracting screen3.2/mark.c (Text)'
  2233. sed 's/^X//' << 'SHAR_EOF' > 'screen3.2/mark.c' &&
  2234. /* Copyright (c) 1991
  2235. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  2236. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  2237. X * Copyright (c) 1987 Oliver Laumann
  2238. X *
  2239. X * This program is free software; you can redistribute it and/or modify
  2240. X * it under the terms of the GNU General Public License as published by
  2241. X * the Free Software Foundation; either version 1, or (at your option)
  2242. X * any later version.
  2243. X *
  2244. X * This program is distributed in the hope that it will be useful,
  2245. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2246. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2247. X * GNU General Public License for more details.
  2248. X *
  2249. X * You should have received a copy of the GNU General Public License
  2250. X * along with this program (see the file COPYING); if not, write to the
  2251. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2252. X *
  2253. X * Noteworthy contributors to screen's design and implementation:
  2254. X *    Wayne Davison (davison@borland.com)
  2255. X *    Patrick Wolfe (pat@kai.com, kailand!pat)
  2256. X *    Bart Schaefer (schaefer@cse.ogi.edu)
  2257. X *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  2258. X *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  2259. X *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  2260. X *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  2261. X *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  2262. X *    Marc Boucher (marc@CAM.ORG)
  2263. X *
  2264. X ****************************************************************
  2265. X */
  2266. X
  2267. #ifndef lint
  2268. X  static char rcs_id[] = "$Id: mark.c,v 1.2 92/02/03 02:27:48 jnweiger Exp $ FAU";
  2269. #endif
  2270. X
  2271. #include <sys/types.h>
  2272. X
  2273. #ifdef BSD
  2274. # include <sys/signal.h>
  2275. #endif /* BSDI */
  2276. X
  2277. #include "config.h"
  2278. #include "screen.h"
  2279. #include "ansi.h"    /* here we find A_SO, ASCII, EXPENSIVE */
  2280. #include "extern.h"
  2281. X
  2282. static int is_letter __P((int));
  2283. static void nextword __P((int *, int *, int, int));
  2284. static int linestart __P((int));
  2285. static int lineend __P((int));
  2286. static int rem __P((int, int , int , int , int , char *, int));
  2287. static int eq __P((int, int ));
  2288. static void revto __P((int, int));
  2289. static void revto_line __P((int, int, int));
  2290. static void MarkRedisplayLine __P((int, int, int, int));
  2291. static int MarkRewrite __P((int, int, int, int));
  2292. static void process_mark_input __P((char **, int *));
  2293. static void AbortMarkRoutine __P((void));
  2294. static int MarkScrollDownDisplay __P((int));
  2295. static int MarkScrollUpDisplay __P((int));
  2296. X
  2297. int join_with_cr =  0;
  2298. extern struct win *fore, *wtab[];
  2299. extern int screenwidth, screenheight;
  2300. extern int screentop, screenbot;
  2301. extern char GlobalAttr, GlobalCharset;
  2302. extern int in_ovl;
  2303. extern int HS;
  2304. extern int LP;
  2305. extern char *null, *blank;
  2306. X
  2307. #ifdef NETHACK
  2308. extern nethackflag;
  2309. #endif
  2310. X
  2311. char *copybuffer = NULL;
  2312. int copylen = 0;
  2313. char mark_key_tab[256]; /* this array must be initialised first! */
  2314. X
  2315. static int in_mark;    /* mark routine active */
  2316. static int left_mar, right_mar, nonl;
  2317. static int x1, y1, second; /* y1 is in terms of WIN coordinates, not DISPLAY */
  2318. static int cx, cy;    /* Cursor Position in WIN coords*/
  2319. static rep_cnt;        /* no. of repeats are rep_cnt+1. jw. */
  2320. static int append_mode;    /* shall we overwrite or append to copybuffer */
  2321. static write_buffer;    /* shall we do a KEY_WRITE_EXCHANGE right away? */
  2322. static hist_offset;
  2323. X
  2324. static int is_letter(c)
  2325. char c;
  2326. {
  2327. X  if ((c >= 'a' && c <= 'z') ||
  2328. X      (c >= 'A' && c <= 'Z') ||
  2329. X      (c >= '0' && c <= '9') ||
  2330. X      c == '_' || c == '.' ||
  2331. X      c == '@' || c == ':' ||
  2332. X      c == '%' || c == '!' ||
  2333. X      c == '-' || c == '+')
  2334. X    /* thus we can catch email-addresses as a word :-) */
  2335. X    return 1;
  2336. X  else if (c != ' ')
  2337. X    return 2;
  2338. X  return 0;
  2339. }
  2340. X
  2341. /*
  2342. X * iWIN gives us a reference to line y of the *whole* image 
  2343. X * where line 0 is the oldest line in our history.
  2344. X * y must be in WIN coordinate system, not in display.
  2345. X */
  2346. #define iWIN(y) ((y < fore->histheight) ? fore->ihist[(fore->histidx + y)\
  2347. X        % fore->histheight] : fore->image[y - fore->histheight])
  2348. #define aWIN(y) ((y < fore->histheight) ? fore->ahist[(fore->histidx + y)\
  2349. X        % fore->histheight] : fore->attr[y - fore->histheight])
  2350. #define fWIN(y) ((y < fore->histheight) ? fore->fhist[(fore->histidx + y)\
  2351. X        % fore->histheight] : fore->font[y - fore->histheight])
  2352. /*
  2353. X * hist_offset tells us, how many lines there are on top of the
  2354. X * visible screen.
  2355. X */
  2356. X
  2357. #define W2D(y) ((y)-hist_offset)
  2358. #define D2W(y) ((y)+hist_offset)
  2359. X
  2360. static int
  2361. linestart(y)
  2362. int y;
  2363. {
  2364. X  register int x;
  2365. X  register char *i;
  2366. X
  2367. X  for (x = left_mar, i = iWIN(y) + x; x < screenwidth-1; x++)
  2368. X    if (*i++ != ' ')
  2369. X      break;
  2370. X  if (x == screenwidth-1)
  2371. X    x = left_mar;
  2372. X  return(x);
  2373. }
  2374. X
  2375. static int
  2376. lineend(y)
  2377. int y;
  2378. {
  2379. X  register int x;
  2380. X  register char *i;
  2381. X
  2382. X  for (x = right_mar, i = iWIN(y) + x; x >= 0; x--)
  2383. X    if (*i-- != ' ')
  2384. X      break;
  2385. X  if (x < 0)
  2386. X    x = left_mar;
  2387. X  return(x);
  2388. }
  2389. X
  2390. X
  2391. /*
  2392. X *  nextword calculates the cursor position of the num'th word.
  2393. X *  If the cursor is on a word, it counts as the first.
  2394. X *  NW_BACK:        search backward
  2395. X *  NW_ENDOFWORD:    find the end of the word
  2396. X *  NW_MUSTMOVE:    move even if the position is correct.
  2397. X */
  2398. X
  2399. #define NW_BACK        1
  2400. #define NW_ENDOFWORD    2
  2401. #define NW_MUSTMOVE    4
  2402. X
  2403. static void
  2404. nextword(xp, yp, flags, num)
  2405. int *xp, *yp, flags, num;
  2406. {
  2407. X  int xx = screenwidth, yy = fore->histheight + screenheight;
  2408. X  register int sx, oq, q, x, y;
  2409. X
  2410. X  x = *xp;
  2411. X  y = *yp;
  2412. X  sx = (flags & NW_BACK) ? -1 : 1;
  2413. X  if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE))
  2414. X    x += sx;
  2415. X  for (oq = -1; ; x += sx, oq = q)
  2416. X    {
  2417. X      if (x >= xx || x < 0)
  2418. X    q = 0;
  2419. X      else
  2420. X        q = is_letter(iWIN(y)[x]);
  2421. X      if (oq >= 0 && oq != q)
  2422. SHAR_EOF
  2423. true || echo 'restore of screen3.2/mark.c failed'
  2424. fi
  2425. echo 'End of  part 3'
  2426. echo 'File screen3.2/mark.c is continued in part 4'
  2427. echo 4 > _shar_seq_.tmp
  2428. exit 0
  2429. exit 0 # Just in case...
  2430.