hack.tty.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /* $NetBSD: hack.tty.c,v 1.12 2003/08/07 09:37:19 agc Exp $ */
  2. /*-
  3. * Copyright (c) 1988, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #include <sys/cdefs.h>
  31. #ifndef lint
  32. #if 0
  33. static char sccsid[] = "@(#)hack.tty.c 8.1 (Berkeley) 5/31/93";
  34. #else
  35. __RCSID("$NetBSD: hack.tty.c,v 1.12 2003/08/07 09:37:19 agc Exp $");
  36. #endif
  37. #endif /* not lint */
  38. /*
  39. * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
  40. * Amsterdam
  41. * All rights reserved.
  42. *
  43. * Redistribution and use in source and binary forms, with or without
  44. * modification, are permitted provided that the following conditions are
  45. * met:
  46. *
  47. * - Redistributions of source code must retain the above copyright notice,
  48. * this list of conditions and the following disclaimer.
  49. *
  50. * - Redistributions in binary form must reproduce the above copyright
  51. * notice, this list of conditions and the following disclaimer in the
  52. * documentation and/or other materials provided with the distribution.
  53. *
  54. * - Neither the name of the Stichting Centrum voor Wiskunde en
  55. * Informatica, nor the names of its contributors may be used to endorse or
  56. * promote products derived from this software without specific prior
  57. * written permission.
  58. *
  59. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  60. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  61. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  62. * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  63. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  64. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  65. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  66. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  67. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  68. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  69. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  70. */
  71. /*
  72. * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
  73. * All rights reserved.
  74. *
  75. * Redistribution and use in source and binary forms, with or without
  76. * modification, are permitted provided that the following conditions
  77. * are met:
  78. * 1. Redistributions of source code must retain the above copyright
  79. * notice, this list of conditions and the following disclaimer.
  80. * 2. Redistributions in binary form must reproduce the above copyright
  81. * notice, this list of conditions and the following disclaimer in the
  82. * documentation and/or other materials provided with the distribution.
  83. * 3. The name of the author may not be used to endorse or promote products
  84. * derived from this software without specific prior written permission.
  85. *
  86. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  87. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  88. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  89. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  90. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  91. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  92. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  93. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  94. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  95. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  96. */
  97. /* hack.tty.c - version 1.0.3 */
  98. /*
  99. * With thanks to the people who sent code for SYSV - hpscdi!jon,
  100. * arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others.
  101. */
  102. #include <termios.h>
  103. #include <termcap.h>
  104. #include "hack.h"
  105. #include "extern.h"
  106. /*
  107. * Some systems may have getchar() return EOF for various reasons, and
  108. * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
  109. */
  110. #ifndef BSD
  111. #define NR_OF_EOFS 20
  112. #endif /* BSD */
  113. static char erase_char, kill_char;
  114. static boolean settty_needed = FALSE;
  115. struct termios inittyb, curttyb;
  116. /*
  117. * Get initial state of terminal, set ospeed (for termcap routines)
  118. * and switch off tab expansion if necessary.
  119. * Called by startup() in termcap.c and after returning from ! or ^Z
  120. */
  121. void
  122. gettty()
  123. {
  124. if (tcgetattr(0, &inittyb) < 0)
  125. perror("Hack (gettty)");
  126. curttyb = inittyb;
  127. ospeed = cfgetospeed(&inittyb);
  128. erase_char = inittyb.c_cc[VERASE];
  129. kill_char = inittyb.c_cc[VKILL];
  130. getioctls();
  131. /* do not expand tabs - they might be needed inside a cm sequence */
  132. if (curttyb.c_oflag & OXTABS) {
  133. curttyb.c_oflag &= ~OXTABS;
  134. setctty();
  135. }
  136. settty_needed = TRUE;
  137. }
  138. /* reset terminal to original state */
  139. void
  140. settty(s)
  141. const char *s;
  142. {
  143. clear_screen();
  144. end_screen();
  145. if (s)
  146. printf("%s", s);
  147. (void) fflush(stdout);
  148. if (tcsetattr(0, TCSADRAIN, &inittyb) < 0)
  149. perror("Hack (settty)");
  150. flags.echo = (inittyb.c_lflag & ECHO) ? ON : OFF;
  151. flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON;
  152. setioctls();
  153. }
  154. void
  155. setctty()
  156. {
  157. if (tcsetattr(0, TCSADRAIN, &curttyb) < 0)
  158. perror("Hack (setctty)");
  159. }
  160. void
  161. setftty()
  162. {
  163. int change = 0;
  164. flags.cbreak = ON;
  165. flags.echo = OFF;
  166. /* Should use (ECHO|CRMOD) here instead of ECHO */
  167. if (curttyb.c_lflag & ECHO) {
  168. curttyb.c_lflag &= ~ECHO;
  169. change++;
  170. }
  171. if (curttyb.c_lflag & ICANON) {
  172. curttyb.c_lflag &= ~ICANON;
  173. /* be satisfied with one character; no timeout */
  174. curttyb.c_cc[VMIN] = 1;
  175. curttyb.c_cc[VTIME] = 0;
  176. change++;
  177. }
  178. if (change) {
  179. setctty();
  180. }
  181. start_screen();
  182. }
  183. /* fatal error */
  184. /* VARARGS1 */
  185. void
  186. error(const char *fmt, ...)
  187. {
  188. va_list ap;
  189. va_start(ap, fmt);
  190. if (settty_needed)
  191. settty((char *) 0);
  192. vprintf(fmt, ap);
  193. va_end(ap);
  194. putchar('\n');
  195. exit(1);
  196. }
  197. /*
  198. * Read a line closed with '\n' into the array char bufp[BUFSZ].
  199. * (The '\n' is not stored. The string is closed with a '\0'.)
  200. * Reading can be interrupted by an escape ('\033') - now the
  201. * resulting string is "\033".
  202. */
  203. void
  204. getlin(bufp)
  205. char *bufp;
  206. {
  207. char *obufp = bufp;
  208. int c;
  209. flags.toplin = 2; /* nonempty, no --More-- required */
  210. for (;;) {
  211. (void) fflush(stdout);
  212. if ((c = getchar()) == EOF) {
  213. *bufp = 0;
  214. return;
  215. }
  216. if (c == '\033') {
  217. *obufp = c;
  218. obufp[1] = 0;
  219. return;
  220. }
  221. if (c == erase_char || c == '\b') {
  222. if (bufp != obufp) {
  223. bufp--;
  224. putstr("\b \b"); /* putsym converts \b */
  225. } else
  226. bell();
  227. } else if (c == '\n') {
  228. *bufp = 0;
  229. return;
  230. } else if (' ' <= c && c < '\177') {
  231. /*
  232. * avoid isprint() - some people don't have it ' ' is
  233. * not always a printing char
  234. */
  235. *bufp = c;
  236. bufp[1] = 0;
  237. putstr(bufp);
  238. if (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)
  239. bufp++;
  240. } else if (c == kill_char || c == '\177') { /* Robert Viduya */
  241. /* this test last - @ might be the kill_char */
  242. while (bufp != obufp) {
  243. bufp--;
  244. putstr("\b \b");
  245. }
  246. } else
  247. bell();
  248. }
  249. }
  250. void
  251. getret()
  252. {
  253. cgetret("");
  254. }
  255. void
  256. cgetret(s)
  257. const char *s;
  258. {
  259. putsym('\n');
  260. if (flags.standout)
  261. standoutbeg();
  262. putstr("Hit ");
  263. putstr(flags.cbreak ? "space" : "return");
  264. putstr(" to continue: ");
  265. if (flags.standout)
  266. standoutend();
  267. xwaitforspace(s);
  268. }
  269. char morc; /* tell the outside world what char he used */
  270. void
  271. xwaitforspace(s)
  272. const char *s; /* chars allowed besides space or return */
  273. {
  274. int c;
  275. morc = 0;
  276. while ((c = readchar()) != '\n') {
  277. if (flags.cbreak) {
  278. if (c == ' ')
  279. break;
  280. if (s && strchr(s, c)) {
  281. morc = c;
  282. break;
  283. }
  284. bell();
  285. }
  286. }
  287. }
  288. char *
  289. parse()
  290. {
  291. static char inputline[COLNO];
  292. int foo;
  293. flags.move = 1;
  294. if (!Invisible)
  295. curs_on_u();
  296. else
  297. home();
  298. while ((foo = readchar()) >= '0' && foo <= '9')
  299. multi = 10 * multi + foo - '0';
  300. if (multi) {
  301. multi--;
  302. save_cm = inputline;
  303. }
  304. inputline[0] = foo;
  305. inputline[1] = 0;
  306. if (foo == 'f' || foo == 'F') {
  307. inputline[1] = getchar();
  308. #ifdef QUEST
  309. if (inputline[1] == foo)
  310. inputline[2] = getchar();
  311. else
  312. #endif /* QUEST */
  313. inputline[2] = 0;
  314. }
  315. if (foo == 'm' || foo == 'M') {
  316. inputline[1] = getchar();
  317. inputline[2] = 0;
  318. }
  319. clrlin();
  320. return (inputline);
  321. }
  322. char
  323. readchar()
  324. {
  325. int sym;
  326. (void) fflush(stdout);
  327. if ((sym = getchar()) == EOF)
  328. #ifdef NR_OF_EOFS
  329. { /*
  330. * Some SYSV systems seem to return EOFs for various reasons
  331. * (?like when one hits break or for interrupted systemcalls?),
  332. * and we must see several before we quit.
  333. */
  334. int cnt = NR_OF_EOFS;
  335. while (cnt--) {
  336. clearerr(stdin); /* omit if clearerr is
  337. * undefined */
  338. if ((sym = getchar()) != EOF)
  339. goto noteof;
  340. }
  341. end_of_input();
  342. noteof: ;
  343. }
  344. #else
  345. end_of_input();
  346. #endif /* NR_OF_EOFS */
  347. if (flags.toplin == 1)
  348. flags.toplin = 2;
  349. return ((char) sym);
  350. }
  351. void
  352. end_of_input()
  353. {
  354. settty("End of input?\n");
  355. clearlocks();
  356. exit(0);
  357. }