resize.c revision 1.2 1 1.2 christos /* $XTermId: resize.c,v 1.144 2020/06/03 00:26:23 tom Exp $ */
2 1.1 reinoud
3 1.1 reinoud /*
4 1.2 christos * Copyright 2003-2018,2020 by Thomas E. Dickey
5 1.1 reinoud *
6 1.1 reinoud * All Rights Reserved
7 1.1 reinoud *
8 1.1 reinoud * Permission is hereby granted, free of charge, to any person obtaining a
9 1.1 reinoud * copy of this software and associated documentation files (the
10 1.1 reinoud * "Software"), to deal in the Software without restriction, including
11 1.1 reinoud * without limitation the rights to use, copy, modify, merge, publish,
12 1.1 reinoud * distribute, sublicense, and/or sell copies of the Software, and to
13 1.1 reinoud * permit persons to whom the Software is furnished to do so, subject to
14 1.1 reinoud * the following conditions:
15 1.1 reinoud *
16 1.1 reinoud * The above copyright notice and this permission notice shall be included
17 1.1 reinoud * in all copies or substantial portions of the Software.
18 1.1 reinoud *
19 1.1 reinoud * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 1.1 reinoud * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 1.1 reinoud * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 1.1 reinoud * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
23 1.1 reinoud * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 1.1 reinoud * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 1.1 reinoud * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 1.1 reinoud *
27 1.1 reinoud * Except as contained in this notice, the name(s) of the above copyright
28 1.1 reinoud * holders shall not be used in advertising or otherwise to promote the
29 1.1 reinoud * sale, use or other dealings in this Software without prior written
30 1.1 reinoud * authorization.
31 1.1 reinoud *
32 1.1 reinoud *
33 1.1 reinoud * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
34 1.1 reinoud *
35 1.1 reinoud * All Rights Reserved
36 1.1 reinoud *
37 1.1 reinoud * Permission to use, copy, modify, and distribute this software and its
38 1.1 reinoud * documentation for any purpose and without fee is hereby granted,
39 1.1 reinoud * provided that the above copyright notice appear in all copies and that
40 1.1 reinoud * both that copyright notice and this permission notice appear in
41 1.1 reinoud * supporting documentation, and that the name of Digital Equipment
42 1.1 reinoud * Corporation not be used in advertising or publicity pertaining to
43 1.1 reinoud * distribution of the software without specific, written prior permission.
44 1.1 reinoud *
45 1.1 reinoud *
46 1.1 reinoud * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
47 1.1 reinoud * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
48 1.1 reinoud * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
49 1.1 reinoud * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
50 1.1 reinoud * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
51 1.1 reinoud * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
52 1.1 reinoud * SOFTWARE.
53 1.1 reinoud */
54 1.1 reinoud
55 1.1 reinoud /* resize.c */
56 1.1 reinoud
57 1.1 reinoud #include <stdio.h>
58 1.1 reinoud #include <ctype.h>
59 1.1 reinoud
60 1.2 christos #ifdef RESIZE_ONLY
61 1.2 christos #include "resize.h"
62 1.2 christos #else
63 1.2 christos #include <xterm.h>
64 1.2 christos #include <version.h>
65 1.2 christos #include <xstrings.h>
66 1.2 christos #include <xtermcap.h>
67 1.2 christos #include <xterm_io.h>
68 1.2 christos #endif
69 1.2 christos
70 1.2 christos #ifndef USE_TERMINFO /* avoid conflict with configure script */
71 1.2 christos #if defined(__QNX__) || defined(__SCO__) || defined(linux) || defined(__OpenBSD__) || defined(__UNIXWARE__)
72 1.2 christos #define USE_TERMINFO
73 1.2 christos #endif
74 1.2 christos #endif
75 1.2 christos
76 1.2 christos #if defined(__QNX__)
77 1.2 christos #include <unix.h>
78 1.2 christos #endif
79 1.1 reinoud
80 1.2 christos /*
81 1.2 christos * Some OS's may want to use both, like SCO for example. We catch here anyone
82 1.2 christos * who hasn't decided what they want.
83 1.2 christos */
84 1.2 christos #if !defined(USE_TERMCAP) && !defined(USE_TERMINFO)
85 1.2 christos #define USE_TERMINFO
86 1.2 christos #endif
87 1.1 reinoud
88 1.1 reinoud #include <signal.h>
89 1.1 reinoud #include <pwd.h>
90 1.1 reinoud
91 1.2 christos #ifdef USE_IGNORE_RC
92 1.2 christos int ignore_unused;
93 1.2 christos #endif
94 1.2 christos
95 1.2 christos #ifdef __MVS__
96 1.2 christos #define ESCAPE(string) "\047" string
97 1.2 christos #else
98 1.1 reinoud #define ESCAPE(string) "\033" string
99 1.2 christos #endif
100 1.1 reinoud
101 1.1 reinoud #define EMULATIONS 2
102 1.1 reinoud #define SUN 1
103 1.1 reinoud #define VT100 0
104 1.1 reinoud
105 1.1 reinoud #define TIMEOUT 10
106 1.1 reinoud
107 1.1 reinoud #define SHELL_UNKNOWN 0
108 1.1 reinoud #define SHELL_C 1
109 1.1 reinoud #define SHELL_BOURNE 2
110 1.2 christos
111 1.1 reinoud /* *INDENT-OFF* */
112 1.1 reinoud static struct {
113 1.1 reinoud const char *name;
114 1.1 reinoud int type;
115 1.1 reinoud } shell_list[] = {
116 1.1 reinoud { "csh", SHELL_C }, /* vanilla cshell */
117 1.1 reinoud { "jcsh", SHELL_C },
118 1.1 reinoud { "tcsh", SHELL_C },
119 1.1 reinoud { "sh", SHELL_BOURNE }, /* vanilla Bourne shell */
120 1.1 reinoud { "ash", SHELL_BOURNE },
121 1.1 reinoud { "bash", SHELL_BOURNE }, /* GNU Bourne again shell */
122 1.1 reinoud { "dash", SHELL_BOURNE },
123 1.1 reinoud { "jsh", SHELL_BOURNE },
124 1.1 reinoud { "ksh", SHELL_BOURNE }, /* Korn shell (from AT&T toolchest) */
125 1.1 reinoud { "ksh-i", SHELL_BOURNE }, /* another name for Korn shell */
126 1.1 reinoud { "ksh93", SHELL_BOURNE }, /* Korn shell */
127 1.1 reinoud { "mksh", SHELL_BOURNE },
128 1.1 reinoud { "pdksh", SHELL_BOURNE },
129 1.1 reinoud { "zsh", SHELL_BOURNE },
130 1.1 reinoud { NULL, SHELL_BOURNE } /* default (same as xterm's) */
131 1.1 reinoud };
132 1.1 reinoud /* *INDENT-ON* */
133 1.1 reinoud
134 1.1 reinoud static const char *const emuname[EMULATIONS] =
135 1.1 reinoud {
136 1.1 reinoud "VT100",
137 1.1 reinoud "Sun",
138 1.1 reinoud };
139 1.1 reinoud static char *myname;
140 1.1 reinoud static int shell_type = SHELL_UNKNOWN;
141 1.1 reinoud static const char *const getsize[EMULATIONS] =
142 1.1 reinoud {
143 1.1 reinoud ESCAPE("7") ESCAPE("[r") ESCAPE("[9999;9999H") ESCAPE("[6n"),
144 1.1 reinoud ESCAPE("[18t"),
145 1.1 reinoud };
146 1.2 christos #if defined(USE_STRUCT_WINSIZE)
147 1.2 christos static const char *const getwsize[EMULATIONS] =
148 1.2 christos { /* size in pixels */
149 1.2 christos 0,
150 1.2 christos ESCAPE("[14t"),
151 1.2 christos };
152 1.2 christos #endif /* USE_STRUCT_WINSIZE */
153 1.1 reinoud static const char *const restore[EMULATIONS] =
154 1.1 reinoud {
155 1.1 reinoud ESCAPE("8"),
156 1.1 reinoud 0,
157 1.1 reinoud };
158 1.1 reinoud static const char *const setsize[EMULATIONS] =
159 1.1 reinoud {
160 1.1 reinoud 0,
161 1.1 reinoud ESCAPE("[8;%s;%st"),
162 1.1 reinoud };
163 1.1 reinoud
164 1.2 christos #ifdef USE_ANY_SYSV_TERMIO
165 1.2 christos static struct termio tioorig;
166 1.2 christos #elif defined(USE_TERMIOS)
167 1.1 reinoud static struct termios tioorig;
168 1.2 christos #else
169 1.2 christos static struct sgttyb sgorig;
170 1.2 christos #endif /* USE_ANY_SYSV_TERMIO/USE_TERMIOS */
171 1.1 reinoud
172 1.1 reinoud static const char *const size[EMULATIONS] =
173 1.1 reinoud {
174 1.1 reinoud ESCAPE("[%d;%dR"),
175 1.1 reinoud ESCAPE("[8;%d;%dt"),
176 1.1 reinoud };
177 1.1 reinoud static const char sunname[] = "sunsize";
178 1.1 reinoud static int tty;
179 1.1 reinoud static FILE *ttyfp;
180 1.1 reinoud
181 1.2 christos #if defined(USE_STRUCT_WINSIZE)
182 1.2 christos static const char *wsize[EMULATIONS] =
183 1.2 christos {
184 1.2 christos 0,
185 1.2 christos ESCAPE("[4;%hd;%hdt"),
186 1.2 christos };
187 1.2 christos #endif /* USE_STRUCT_WINSIZE */
188 1.2 christos
189 1.2 christos static void failed(const char *) GCC_NORETURN;
190 1.2 christos static void onintr(int) GCC_NORETURN;
191 1.2 christos static void resize_timeout(int) GCC_NORETURN;
192 1.2 christos static void Usage(void) GCC_NORETURN;
193 1.1 reinoud
194 1.1 reinoud static void
195 1.1 reinoud failed(const char *s)
196 1.1 reinoud {
197 1.1 reinoud int save = errno;
198 1.1 reinoud IGNORE_RC(write(2, myname, strlen(myname)));
199 1.1 reinoud IGNORE_RC(write(2, ": ", (size_t) 2));
200 1.1 reinoud errno = save;
201 1.1 reinoud perror(s);
202 1.1 reinoud exit(EXIT_FAILURE);
203 1.1 reinoud }
204 1.1 reinoud
205 1.1 reinoud /* ARGSUSED */
206 1.1 reinoud static void
207 1.1 reinoud onintr(int sig GCC_UNUSED)
208 1.1 reinoud {
209 1.2 christos #ifdef USE_ANY_SYSV_TERMIO
210 1.2 christos (void) ioctl(tty, TCSETAW, &tioorig);
211 1.2 christos #elif defined(USE_TERMIOS)
212 1.1 reinoud (void) tcsetattr(tty, TCSADRAIN, &tioorig);
213 1.2 christos #else /* not USE_TERMIOS */
214 1.2 christos (void) ioctl(tty, TIOCSETP, &sgorig);
215 1.2 christos #endif /* USE_ANY_SYSV_TERMIO/USE_TERMIOS */
216 1.1 reinoud exit(EXIT_FAILURE);
217 1.1 reinoud }
218 1.1 reinoud
219 1.1 reinoud static void
220 1.1 reinoud resize_timeout(int sig)
221 1.1 reinoud {
222 1.1 reinoud fprintf(stderr, "\n%s: Time out occurred\r\n", myname);
223 1.1 reinoud onintr(sig);
224 1.1 reinoud }
225 1.1 reinoud
226 1.1 reinoud static void
227 1.1 reinoud Usage(void)
228 1.1 reinoud {
229 1.1 reinoud fprintf(stderr, strcmp(myname, sunname) == 0 ?
230 1.1 reinoud "Usage: %s [rows cols]\n" :
231 1.1 reinoud "Usage: %s [-v] [-u] [-c] [-s [rows cols]]\n", myname);
232 1.1 reinoud exit(EXIT_FAILURE);
233 1.1 reinoud }
234 1.1 reinoud
235 1.2 christos #ifdef USE_TERMCAP
236 1.2 christos static void
237 1.2 christos print_termcap(const char *termcap)
238 1.2 christos {
239 1.2 christos int ch;
240 1.2 christos
241 1.2 christos putchar('\'');
242 1.2 christos while ((ch = *termcap++) != '\0') {
243 1.2 christos switch (ch & 0xff) {
244 1.2 christos case 127: /* undo bug in GNU termcap */
245 1.2 christos printf("^?");
246 1.2 christos break;
247 1.2 christos case '\'': /* must escape anyway (unlikely) */
248 1.2 christos /* FALLTHRU */
249 1.2 christos case '!': /* must escape for SunOS csh */
250 1.2 christos putchar('\\');
251 1.2 christos /* FALLTHRU */
252 1.2 christos default:
253 1.2 christos putchar(ch);
254 1.2 christos break;
255 1.2 christos }
256 1.2 christos }
257 1.2 christos putchar('\'');
258 1.2 christos }
259 1.2 christos #endif /* USE_TERMCAP */
260 1.1 reinoud
261 1.1 reinoud static int
262 1.1 reinoud checkdigits(char *str)
263 1.1 reinoud {
264 1.1 reinoud while (*str) {
265 1.1 reinoud if (!isdigit(CharOf(*str)))
266 1.1 reinoud return (0);
267 1.1 reinoud str++;
268 1.1 reinoud }
269 1.1 reinoud return (1);
270 1.1 reinoud }
271 1.1 reinoud
272 1.1 reinoud static void
273 1.1 reinoud readstring(FILE *fp, char *buf, const char *str)
274 1.1 reinoud {
275 1.1 reinoud int last, c;
276 1.2 christos #if !defined(USG) && !defined(__minix)
277 1.2 christos /* What is the advantage of setitimer() over alarm()? */
278 1.1 reinoud struct itimerval it;
279 1.2 christos #endif
280 1.1 reinoud
281 1.1 reinoud signal(SIGALRM, resize_timeout);
282 1.2 christos #if defined(USG) || defined(__minix)
283 1.2 christos alarm(TIMEOUT);
284 1.2 christos #else
285 1.1 reinoud memset((char *) &it, 0, sizeof(struct itimerval));
286 1.1 reinoud it.it_value.tv_sec = TIMEOUT;
287 1.1 reinoud setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL);
288 1.2 christos #endif
289 1.1 reinoud if ((c = getc(fp)) == 0233) { /* meta-escape, CSI */
290 1.1 reinoud c = ESCAPE("")[0];
291 1.1 reinoud *buf++ = (char) c;
292 1.1 reinoud *buf++ = '[';
293 1.1 reinoud } else {
294 1.1 reinoud *buf++ = (char) c;
295 1.1 reinoud }
296 1.1 reinoud if (c != *str) {
297 1.1 reinoud fprintf(stderr, "%s: unknown character, exiting.\r\n", myname);
298 1.1 reinoud onintr(0);
299 1.1 reinoud }
300 1.1 reinoud last = str[strlen(str) - 1];
301 1.1 reinoud while ((*buf++ = (char) getc(fp)) != last) {
302 1.1 reinoud ;
303 1.1 reinoud }
304 1.2 christos #if defined(USG) || defined(__minix)
305 1.2 christos alarm(0);
306 1.2 christos #else
307 1.1 reinoud memset((char *) &it, 0, sizeof(struct itimerval));
308 1.1 reinoud setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL);
309 1.2 christos #endif
310 1.1 reinoud *buf = 0;
311 1.1 reinoud }
312 1.1 reinoud
313 1.1 reinoud /*
314 1.1 reinoud resets termcap string to reflect current screen size
315 1.1 reinoud */
316 1.1 reinoud int
317 1.1 reinoud main(int argc, char **argv ENVP_ARG)
318 1.1 reinoud {
319 1.2 christos #ifdef USE_TERMCAP
320 1.2 christos char *env;
321 1.2 christos #endif
322 1.1 reinoud char *ptr;
323 1.1 reinoud int emu = VT100;
324 1.1 reinoud char *shell;
325 1.1 reinoud int i;
326 1.1 reinoud int rc;
327 1.1 reinoud int rows, cols;
328 1.2 christos #ifdef USE_ANY_SYSV_TERMIO
329 1.2 christos struct termio tio;
330 1.2 christos #elif defined(USE_TERMIOS)
331 1.1 reinoud struct termios tio;
332 1.2 christos #else
333 1.2 christos struct sgttyb sg;
334 1.2 christos #endif /* USE_ANY_SYSV_TERMIO/USE_TERMIOS */
335 1.2 christos #ifdef USE_TERMCAP
336 1.2 christos int ok_tcap = 1;
337 1.2 christos char termcap[TERMCAP_SIZE];
338 1.2 christos char newtc[TERMCAP_SIZE];
339 1.2 christos #endif /* USE_TERMCAP */
340 1.1 reinoud char buf[BUFSIZ];
341 1.2 christos #ifdef TTYSIZE_STRUCT
342 1.2 christos TTYSIZE_STRUCT ts;
343 1.2 christos #endif
344 1.1 reinoud char *name_of_tty;
345 1.2 christos #ifdef CANT_OPEN_DEV_TTY
346 1.2 christos extern char *ttyname();
347 1.2 christos #endif
348 1.1 reinoud const char *setname = "";
349 1.1 reinoud
350 1.1 reinoud myname = x_basename(argv[0]);
351 1.1 reinoud if (strcmp(myname, sunname) == 0)
352 1.1 reinoud emu = SUN;
353 1.1 reinoud for (argv++, argc--; argc > 0 && **argv == '-'; argv++, argc--) {
354 1.1 reinoud switch ((*argv)[1]) {
355 1.1 reinoud case 's': /* Sun emulation */
356 1.1 reinoud if (emu == SUN)
357 1.1 reinoud Usage(); /* Never returns */
358 1.1 reinoud emu = SUN;
359 1.1 reinoud break;
360 1.1 reinoud case 'u': /* Bourne (Unix) shell */
361 1.1 reinoud shell_type = SHELL_BOURNE;
362 1.1 reinoud break;
363 1.1 reinoud case 'c': /* C shell */
364 1.1 reinoud shell_type = SHELL_C;
365 1.1 reinoud break;
366 1.1 reinoud case 'v':
367 1.2 christos printf("%s\n", xtermVersion());
368 1.1 reinoud exit(EXIT_SUCCESS);
369 1.1 reinoud default:
370 1.1 reinoud Usage(); /* Never returns */
371 1.1 reinoud }
372 1.1 reinoud }
373 1.1 reinoud
374 1.1 reinoud if (SHELL_UNKNOWN == shell_type) {
375 1.1 reinoud /* Find out what kind of shell this user is running.
376 1.1 reinoud * This is the same algorithm that xterm uses.
377 1.1 reinoud */
378 1.1 reinoud if ((ptr = x_getenv("SHELL")) == NULL) {
379 1.1 reinoud uid_t uid = getuid();
380 1.1 reinoud struct passwd pw;
381 1.1 reinoud
382 1.1 reinoud if (x_getpwuid(uid, &pw)) {
383 1.1 reinoud (void) x_getlogin(uid, &pw);
384 1.1 reinoud }
385 1.1 reinoud if (!OkPasswd(&pw)
386 1.1 reinoud || *(ptr = pw.pw_shell) == 0) {
387 1.1 reinoud /* this is the same default that xterm uses */
388 1.1 reinoud ptr = x_strdup("/bin/sh");
389 1.1 reinoud }
390 1.1 reinoud }
391 1.1 reinoud
392 1.1 reinoud shell = x_basename(ptr);
393 1.1 reinoud
394 1.1 reinoud /* now that we know, what kind is it? */
395 1.1 reinoud for (i = 0; shell_list[i].name; i++) {
396 1.1 reinoud if (!strcmp(shell_list[i].name, shell)) {
397 1.1 reinoud break;
398 1.1 reinoud }
399 1.1 reinoud }
400 1.1 reinoud shell_type = shell_list[i].type;
401 1.1 reinoud }
402 1.1 reinoud
403 1.1 reinoud if (argc == 2) {
404 1.1 reinoud if (!setsize[emu]) {
405 1.1 reinoud fprintf(stderr,
406 1.1 reinoud "%s: Can't set window size under %s emulation\n",
407 1.1 reinoud myname, emuname[emu]);
408 1.1 reinoud exit(EXIT_FAILURE);
409 1.1 reinoud }
410 1.1 reinoud if (!checkdigits(argv[0]) || !checkdigits(argv[1])) {
411 1.1 reinoud Usage(); /* Never returns */
412 1.1 reinoud }
413 1.1 reinoud } else if (argc != 0) {
414 1.1 reinoud Usage(); /* Never returns */
415 1.1 reinoud }
416 1.2 christos #ifdef CANT_OPEN_DEV_TTY
417 1.2 christos if ((name_of_tty = ttyname(fileno(stderr))) == NULL)
418 1.2 christos #endif
419 1.1 reinoud name_of_tty = x_strdup("/dev/tty");
420 1.1 reinoud
421 1.1 reinoud if ((ttyfp = fopen(name_of_tty, "r+")) == NULL) {
422 1.1 reinoud fprintf(stderr, "%s: can't open terminal %s\n",
423 1.1 reinoud myname, name_of_tty);
424 1.1 reinoud exit(EXIT_FAILURE);
425 1.1 reinoud }
426 1.1 reinoud tty = fileno(ttyfp);
427 1.2 christos #ifdef USE_TERMCAP
428 1.2 christos if ((env = x_getenv("TERM")) == 0) {
429 1.2 christos env = x_strdup(DFT_TERMTYPE);
430 1.2 christos if (SHELL_BOURNE == shell_type) {
431 1.2 christos setname = "TERM=" DFT_TERMTYPE ";\nexport TERM;\n";
432 1.2 christos } else {
433 1.2 christos setname = "setenv TERM " DFT_TERMTYPE ";\n";
434 1.2 christos }
435 1.2 christos }
436 1.2 christos termcap[0] = 0; /* ...just in case we've accidentally gotten terminfo */
437 1.2 christos if (tgetent(termcap, env) <= 0 || termcap[0] == 0) {
438 1.2 christos ok_tcap = 0;
439 1.2 christos }
440 1.2 christos #endif /* USE_TERMCAP */
441 1.2 christos #ifdef USE_TERMINFO
442 1.1 reinoud if (x_getenv("TERM") == 0) {
443 1.1 reinoud if (SHELL_BOURNE == shell_type) {
444 1.1 reinoud setname = "TERM=" DFT_TERMTYPE ";\nexport TERM;\n";
445 1.1 reinoud } else {
446 1.1 reinoud setname = "setenv TERM " DFT_TERMTYPE ";\n";
447 1.1 reinoud }
448 1.1 reinoud }
449 1.2 christos #endif /* USE_TERMINFO */
450 1.1 reinoud
451 1.2 christos #ifdef USE_ANY_SYSV_TERMIO
452 1.2 christos rc = ioctl(tty, TCGETA, &tioorig);
453 1.2 christos tio = tioorig;
454 1.2 christos UIntClr(tio.c_iflag, (ICRNL | IUCLC));
455 1.2 christos UIntClr(tio.c_lflag, (ICANON | ECHO));
456 1.2 christos tio.c_cflag |= CS8;
457 1.2 christos tio.c_cc[VMIN] = 6;
458 1.2 christos tio.c_cc[VTIME] = 1;
459 1.2 christos #elif defined(USE_TERMIOS)
460 1.1 reinoud rc = tcgetattr(tty, &tioorig);
461 1.1 reinoud tio = tioorig;
462 1.1 reinoud UIntClr(tio.c_iflag, ICRNL);
463 1.1 reinoud UIntClr(tio.c_lflag, (ICANON | ECHO));
464 1.1 reinoud tio.c_cflag |= CS8;
465 1.1 reinoud tio.c_cc[VMIN] = 6;
466 1.1 reinoud tio.c_cc[VTIME] = 1;
467 1.2 christos #else /* not USE_TERMIOS */
468 1.2 christos rc = ioctl(tty, TIOCGETP, &sgorig);
469 1.2 christos sg = sgorig;
470 1.2 christos sg.sg_flags |= RAW;
471 1.2 christos UIntClr(sg.sg_flags, ECHO);
472 1.2 christos #endif /* USE_ANY_SYSV_TERMIO/USE_TERMIOS */
473 1.1 reinoud if (rc != 0)
474 1.1 reinoud failed("get tty settings");
475 1.1 reinoud
476 1.1 reinoud signal(SIGINT, onintr);
477 1.1 reinoud signal(SIGQUIT, onintr);
478 1.1 reinoud signal(SIGTERM, onintr);
479 1.1 reinoud
480 1.2 christos #ifdef USE_ANY_SYSV_TERMIO
481 1.2 christos rc = ioctl(tty, TCSETAW, &tio);
482 1.2 christos #elif defined(USE_TERMIOS)
483 1.1 reinoud rc = tcsetattr(tty, TCSADRAIN, &tio);
484 1.2 christos #else /* not USE_TERMIOS */
485 1.2 christos rc = ioctl(tty, TIOCSETP, &sg);
486 1.2 christos #endif /* USE_ANY_SYSV_TERMIO/USE_TERMIOS */
487 1.1 reinoud if (rc != 0)
488 1.1 reinoud failed("set tty settings");
489 1.1 reinoud
490 1.1 reinoud if (argc == 2) { /* look for optional parameters of "-s" */
491 1.1 reinoud char *tmpbuf = TypeMallocN(char,
492 1.1 reinoud strlen(setsize[emu]) +
493 1.1 reinoud strlen(argv[0]) +
494 1.1 reinoud strlen(argv[1]) +
495 1.1 reinoud 1);
496 1.1 reinoud if (tmpbuf == 0) {
497 1.1 reinoud fprintf(stderr, "%s: Cannot query size\n", myname);
498 1.1 reinoud onintr(0);
499 1.1 reinoud } else {
500 1.1 reinoud sprintf(tmpbuf, setsize[emu], argv[0], argv[1]);
501 1.1 reinoud IGNORE_RC(write(tty, tmpbuf, strlen(tmpbuf)));
502 1.1 reinoud free(tmpbuf);
503 1.1 reinoud }
504 1.1 reinoud }
505 1.1 reinoud IGNORE_RC(write(tty, getsize[emu], strlen(getsize[emu])));
506 1.1 reinoud readstring(ttyfp, buf, size[emu]);
507 1.1 reinoud if (sscanf(buf, size[emu], &rows, &cols) != 2) {
508 1.1 reinoud fprintf(stderr, "%s: Can't get rows and columns\r\n", myname);
509 1.1 reinoud onintr(0);
510 1.1 reinoud }
511 1.1 reinoud if (restore[emu])
512 1.1 reinoud IGNORE_RC(write(tty, restore[emu], strlen(restore[emu])));
513 1.2 christos #if defined(USE_STRUCT_WINSIZE)
514 1.2 christos /* finally, set the tty's window size */
515 1.2 christos if (getwsize[emu]) {
516 1.2 christos /* get the window size in pixels */
517 1.2 christos IGNORE_RC(write(tty, getwsize[emu], strlen(getwsize[emu])));
518 1.2 christos readstring(ttyfp, buf, wsize[emu]);
519 1.2 christos if (sscanf(buf, wsize[emu], &ts.ws_xpixel, &ts.ws_ypixel) != 2) {
520 1.2 christos fprintf(stderr, "%s: Can't get window size\r\n", myname);
521 1.2 christos onintr(0);
522 1.2 christos }
523 1.2 christos setup_winsize(ts, rows, cols, 0, 0);
524 1.2 christos SET_TTYSIZE(tty, ts);
525 1.2 christos } else if (ioctl(tty, TIOCGWINSZ, &ts) != -1) {
526 1.2 christos /* we don't have any way of directly finding out
527 1.2 christos the current height & width of the window in pixels. We try
528 1.2 christos our best by computing the font height and width from the "old"
529 1.2 christos window-size values, and multiplying by these ratios... */
530 1.2 christos #define scaled(old,new,len) (old)?((unsigned)(new)*(len)/(old)):(len)
531 1.2 christos setup_winsize(ts, rows, cols,
532 1.2 christos scaled(TTYSIZE_ROWS(ts), rows, ts.ws_ypixel),
533 1.2 christos scaled(TTYSIZE_COLS(ts), cols, ts.ws_xpixel));
534 1.2 christos SET_TTYSIZE(tty, ts);
535 1.2 christos }
536 1.2 christos #endif /* USE_STRUCT_WINSIZE */
537 1.2 christos
538 1.2 christos #ifdef USE_ANY_SYSV_TERMIO
539 1.2 christos rc = ioctl(tty, TCSETAW, &tioorig);
540 1.2 christos #elif defined(USE_TERMIOS)
541 1.1 reinoud rc = tcsetattr(tty, TCSADRAIN, &tioorig);
542 1.2 christos #else /* not USE_TERMIOS */
543 1.2 christos rc = ioctl(tty, TIOCSETP, &sgorig);
544 1.2 christos #endif /* USE_ANY_SYSV_TERMIO/USE_TERMIOS */
545 1.1 reinoud if (rc != 0)
546 1.1 reinoud failed("set tty settings");
547 1.1 reinoud
548 1.1 reinoud signal(SIGINT, SIG_DFL);
549 1.1 reinoud signal(SIGQUIT, SIG_DFL);
550 1.1 reinoud signal(SIGTERM, SIG_DFL);
551 1.1 reinoud
552 1.2 christos #ifdef USE_TERMCAP
553 1.2 christos if (ok_tcap) {
554 1.2 christos /* update termcap string */
555 1.2 christos /* first do columns */
556 1.2 christos if ((ptr = x_strindex(termcap, "co#")) == NULL) {
557 1.2 christos fprintf(stderr, "%s: No `co#'\n", myname);
558 1.2 christos exit(EXIT_FAILURE);
559 1.2 christos }
560 1.2 christos
561 1.2 christos i = (int) (ptr - termcap) + 3;
562 1.2 christos strncpy(newtc, termcap, (size_t) i);
563 1.2 christos sprintf(newtc + i, "%d", cols);
564 1.2 christos if ((ptr = strchr(ptr, ':')) != 0)
565 1.2 christos strcat(newtc, ptr);
566 1.2 christos
567 1.2 christos /* now do lines */
568 1.2 christos if ((ptr = x_strindex(newtc, "li#")) == NULL) {
569 1.2 christos fprintf(stderr, "%s: No `li#'\n", myname);
570 1.2 christos exit(EXIT_FAILURE);
571 1.2 christos }
572 1.2 christos
573 1.2 christos i = (int) (ptr - newtc) + 3;
574 1.2 christos strncpy(termcap, newtc, (size_t) i);
575 1.2 christos sprintf(termcap + i, "%d", rows);
576 1.2 christos if ((ptr = strchr(ptr, ':')) != 0)
577 1.2 christos strcat(termcap, ptr);
578 1.2 christos }
579 1.2 christos #endif /* USE_TERMCAP */
580 1.1 reinoud
581 1.1 reinoud if (SHELL_BOURNE == shell_type) {
582 1.1 reinoud
583 1.2 christos #ifdef USE_TERMCAP
584 1.2 christos if (ok_tcap) {
585 1.2 christos printf("%sTERMCAP=", setname);
586 1.2 christos print_termcap(termcap);
587 1.2 christos printf(";\nexport TERMCAP;\n");
588 1.2 christos }
589 1.2 christos #endif /* USE_TERMCAP */
590 1.2 christos #ifdef USE_TERMINFO
591 1.1 reinoud printf("%sCOLUMNS=%d;\nLINES=%d;\nexport COLUMNS LINES;\n",
592 1.1 reinoud setname, cols, rows);
593 1.2 christos #endif /* USE_TERMINFO */
594 1.1 reinoud
595 1.1 reinoud } else { /* not Bourne shell */
596 1.1 reinoud
597 1.2 christos #ifdef USE_TERMCAP
598 1.2 christos if (ok_tcap) {
599 1.2 christos printf("set noglob;\n%ssetenv TERMCAP ", setname);
600 1.2 christos print_termcap(termcap);
601 1.2 christos printf(";\nunset noglob;\n");
602 1.2 christos }
603 1.2 christos #endif /* USE_TERMCAP */
604 1.2 christos #ifdef USE_TERMINFO
605 1.1 reinoud printf("set noglob;\n%ssetenv COLUMNS '%d';\nsetenv LINES '%d';\nunset noglob;\n",
606 1.1 reinoud setname, cols, rows);
607 1.2 christos #endif /* USE_TERMINFO */
608 1.1 reinoud }
609 1.1 reinoud exit(EXIT_SUCCESS);
610 1.1 reinoud }
611