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