1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Wang at The University of California, Berkeley. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)wwinit.c 8.1 (Berkeley) 6/6/93 37 * $FreeBSD: src/usr.bin/window/wwinit.c,v 1.11.2.1 2001/05/17 09:45:01 obrien Exp $ 38 * $DragonFly: src/usr.bin/window/wwinit.c,v 1.3 2006/01/12 13:43:11 corecode Exp $ 39 */ 40 41 #include <signal.h> 42 #include <fcntl.h> 43 #include <stdio.h> 44 #include <termcap.h> 45 46 #include "ww.h" 47 #include "tt.h" 48 #include "char.h" 49 50 wwinit() 51 { 52 register i, j; 53 char *kp; 54 int s; 55 56 wwdtablesize = getdtablesize(); 57 wwhead.ww_forw = &wwhead; 58 wwhead.ww_back = &wwhead; 59 60 s = sigblock(sigmask(SIGIO) | sigmask(SIGCHLD) | sigmask(SIGALRM) | 61 sigmask(SIGHUP) | sigmask(SIGTERM)); 62 if (signal(SIGIO, wwrint) == BADSIG || 63 signal(SIGCHLD, wwchild) == BADSIG || 64 signal(SIGHUP, wwquit) == BADSIG || 65 signal(SIGTERM, wwquit) == BADSIG || 66 signal(SIGPIPE, SIG_IGN) == BADSIG) { 67 wwerrno = WWE_SYS; 68 return -1; 69 } 70 71 if (wwgettty(0, &wwoldtty) < 0) 72 return -1; 73 wwwintty = wwoldtty; 74 #ifdef OLD_TTY 75 wwwintty.ww_sgttyb.sg_flags &= ~XTABS; 76 wwnewtty.ww_sgttyb = wwoldtty.ww_sgttyb; 77 wwnewtty.ww_sgttyb.sg_erase = -1; 78 wwnewtty.ww_sgttyb.sg_kill = -1; 79 wwnewtty.ww_sgttyb.sg_flags |= CBREAK; 80 wwnewtty.ww_sgttyb.sg_flags &= ~(ECHO|CRMOD); 81 wwnewtty.ww_tchars.t_intrc = -1; 82 wwnewtty.ww_tchars.t_quitc = -1; 83 wwnewtty.ww_tchars.t_startc = -1; 84 wwnewtty.ww_tchars.t_stopc = -1; 85 wwnewtty.ww_tchars.t_eofc = -1; 86 wwnewtty.ww_tchars.t_brkc = -1; 87 wwnewtty.ww_ltchars.t_suspc = -1; 88 wwnewtty.ww_ltchars.t_dsuspc = -1; 89 wwnewtty.ww_ltchars.t_rprntc = -1; 90 wwnewtty.ww_ltchars.t_flushc = -1; 91 wwnewtty.ww_ltchars.t_werasc = -1; 92 wwnewtty.ww_ltchars.t_lnextc = -1; 93 wwnewtty.ww_lmode = wwoldtty.ww_lmode | LLITOUT; 94 wwnewtty.ww_ldisc = wwoldtty.ww_ldisc; 95 #else 96 #ifndef OXTABS 97 #define OXTABS XTABS 98 #endif 99 #ifndef _POSIX_VDISABLE 100 #define _POSIX_VDISABLE -1 101 #endif 102 wwwintty.ww_termios.c_oflag &= ~OXTABS; 103 wwnewtty.ww_termios = wwoldtty.ww_termios; 104 wwnewtty.ww_termios.c_iflag &= 105 ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IMAXBEL); 106 wwnewtty.ww_termios.c_oflag = 0; 107 wwnewtty.ww_termios.c_cflag &= ~(CSIZE | PARENB); 108 wwnewtty.ww_termios.c_cflag |= CS8; 109 wwnewtty.ww_termios.c_lflag = 0; 110 for (i = 0; i < NCCS; i++) 111 wwnewtty.ww_termios.c_cc[i] = _POSIX_VDISABLE; 112 wwnewtty.ww_termios.c_cc[VMIN] = 0; 113 wwnewtty.ww_termios.c_cc[VTIME] = 0; 114 #endif 115 wwnewtty.ww_fflags = wwoldtty.ww_fflags | FASYNC; 116 if (wwsettty(0, &wwnewtty) < 0) 117 goto bad; 118 119 if ((wwterm = getenv("TERM")) == 0) { 120 wwerrno = WWE_BADTERM; 121 goto bad; 122 } 123 if (tgetent(wwtermcap, wwterm) != 1) { 124 wwerrno = WWE_BADTERM; 125 goto bad; 126 } 127 #ifdef OLD_TTY 128 ospeed = wwoldtty.ww_sgttyb.sg_ospeed; 129 switch (ospeed) { 130 default: 131 case B0: 132 goto bad; 133 case B50: 134 wwbaud = 50; 135 break; 136 case B75: 137 wwbaud = 75; 138 break; 139 case B110: 140 wwbaud = 110; 141 break; 142 case B134: 143 wwbaud = 134; 144 break; 145 case B150: 146 wwbaud = 150; 147 break; 148 case B200: 149 wwbaud = 200; 150 break; 151 case B300: 152 wwbaud = 300; 153 break; 154 case B600: 155 wwbaud = 600; 156 break; 157 case B1200: 158 wwbaud = 1200; 159 break; 160 case B1800: 161 wwbaud = 1800; 162 break; 163 case B2400: 164 wwbaud = 2400; 165 break; 166 case B4800: 167 wwbaud = 4800; 168 break; 169 case B9600: 170 wwbaud = 9600; 171 break; 172 #ifdef B19200 173 case B19200: 174 #else 175 case EXTA: 176 #endif 177 wwbaud = 19200; 178 break; 179 #ifdef B38400 180 case B38400: 181 #else 182 case EXTB: 183 #endif 184 wwbaud = 38400; 185 break; 186 #ifdef B57600 187 case B57600: 188 wwbaud = 57600; 189 break; 190 #endif 191 #ifdef B115200 192 case B115200: 193 wwbaud = 115200; 194 break; 195 #endif 196 } 197 #else 198 if ((wwbaud = cfgetospeed(&wwoldtty.ww_termios)) == B0) 199 goto bad; 200 #endif 201 wwospeed = ospeed; 202 203 if (xxinit() < 0) 204 goto bad; 205 wwnrow = tt.tt_nrow; 206 wwncol = tt.tt_ncol; 207 wwavailmodes = tt.tt_availmodes; 208 wwwrap = tt.tt_wrap; 209 210 if (wwavailmodes & WWM_REV) 211 wwcursormodes = WWM_REV | wwavailmodes & WWM_BLK; 212 else if (wwavailmodes & WWM_UL) 213 wwcursormodes = WWM_UL; 214 215 if ((wwib = malloc((unsigned) 512)) == 0) 216 goto bad; 217 wwibe = wwib + 512; 218 wwibq = wwibp = wwib; 219 220 if ((wwsmap = wwalloc(0, 0, wwnrow, wwncol, sizeof (char))) == 0) 221 goto bad; 222 for (i = 0; i < wwnrow; i++) 223 for (j = 0; j < wwncol; j++) 224 wwsmap[i][j] = WWX_NOBODY; 225 226 wwos = (union ww_char **) 227 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char)); 228 if (wwos == 0) 229 goto bad; 230 /* wwos is cleared in wwstart1() */ 231 wwns = (union ww_char **) 232 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char)); 233 if (wwns == 0) 234 goto bad; 235 for (i = 0; i < wwnrow; i++) 236 for (j = 0; j < wwncol; j++) 237 wwns[i][j].c_w = ' '; 238 if (tt.tt_checkpoint) { 239 /* wwcs is also cleared in wwstart1() */ 240 wwcs = (union ww_char **) 241 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char)); 242 if (wwcs == 0) 243 goto bad; 244 } 245 246 wwtouched = malloc((unsigned) wwnrow); 247 if (wwtouched == 0) { 248 wwerrno = WWE_NOMEM; 249 goto bad; 250 } 251 for (i = 0; i < wwnrow; i++) 252 wwtouched[i] = 0; 253 254 wwupd = (struct ww_update *) malloc((unsigned) wwnrow * sizeof *wwupd); 255 if (wwupd == 0) { 256 wwerrno = WWE_NOMEM; 257 goto bad; 258 } 259 260 wwindex[WWX_NOBODY] = &wwnobody; 261 wwnobody.ww_order = NWW; 262 263 kp = wwwintermcap; 264 if (wwavailmodes & WWM_REV) 265 wwaddcap1(WWT_REV, &kp); 266 if (wwavailmodes & WWM_BLK) 267 wwaddcap1(WWT_BLK, &kp); 268 if (wwavailmodes & WWM_UL) 269 wwaddcap1(WWT_UL, &kp); 270 if (wwavailmodes & WWM_GRP) 271 wwaddcap1(WWT_GRP, &kp); 272 if (wwavailmodes & WWM_DIM) 273 wwaddcap1(WWT_DIM, &kp); 274 if (wwavailmodes & WWM_USR) 275 wwaddcap1(WWT_USR, &kp); 276 if (tt.tt_insline && tt.tt_delline || tt.tt_setscroll) 277 wwaddcap1(WWT_ALDL, &kp); 278 if (tt.tt_inschar) 279 wwaddcap1(WWT_IMEI, &kp); 280 if (tt.tt_insspace) 281 wwaddcap1(WWT_IC, &kp); 282 if (tt.tt_delchar) 283 wwaddcap1(WWT_DC, &kp); 284 wwaddcap("kb", &kp); 285 wwaddcap2("ku", &kp); 286 wwaddcap2("kd", &kp); 287 wwaddcap2("kl", &kp); 288 wwaddcap2("kr", &kp); 289 wwaddcap("kh", &kp); 290 if ((j = tgetnum("kn")) >= 0) { 291 char cap[32]; 292 293 (void) sprintf(kp, "kn#%d:", j); 294 for (; *kp; kp++) 295 ; 296 for (i = 1; i <= j; i++) { 297 (void) sprintf(cap, "k%d", i); 298 wwaddcap(cap, &kp); 299 cap[0] = 'l'; 300 wwaddcap(cap, &kp); 301 } 302 } 303 /* 304 * It's ok to do this here even if setenv() is destructive 305 * since tt_init() has already made its own copy of it and 306 * wwterm now points to the copy. 307 */ 308 if (setenv("TERM", WWT_TERM, 1) == -1) 309 err(1, "setenv: cannot set TERM=%s", WWT_TERM); 310 #ifdef TERMINFO 311 if (wwterminfoinit() < 0) 312 goto bad; 313 #endif 314 315 if (tt.tt_checkpoint) 316 if (signal(SIGALRM, wwalarm) == BADSIG) { 317 wwerrno = WWE_SYS; 318 goto bad; 319 } 320 fcntl(0, F_SETOWN, getpid()); 321 /* catch typeahead before ASYNC was set */ 322 (void) kill(getpid(), SIGIO); 323 wwstart1(); 324 (void) sigsetmask(s); 325 return 0; 326 bad: 327 /* 328 * Don't bother to free storage. We're supposed 329 * to exit when wwinit fails anyway. 330 */ 331 (void) signal(SIGIO, SIG_DFL); 332 (void) wwsettty(0, &wwoldtty); 333 (void) sigsetmask(s); 334 return -1; 335 } 336 337 wwaddcap(cap, kp) 338 register char *cap; 339 register char **kp; 340 { 341 char tbuf[512]; 342 char *tp = tbuf; 343 register char *str, *p; 344 345 if ((str = tgetstr(cap, &tp)) != 0) { 346 while (*(*kp)++ = *cap++) 347 ; 348 (*kp)[-1] = '='; 349 while (*str) { 350 for (p = unctrl(*str++); *(*kp)++ = *p++;) 351 ; 352 (*kp)--; 353 } 354 *(*kp)++ = ':'; 355 **kp = 0; 356 } 357 } 358 359 wwaddcap1(cap, kp) 360 register char *cap; 361 register char **kp; 362 { 363 while (*(*kp)++ = *cap++) 364 ; 365 (*kp)--; 366 } 367 368 wwaddcap2(cap, kp) 369 register char *cap; 370 register char **kp; 371 { 372 char tbuf[512]; 373 char *tp = tbuf; 374 register char *str, *p; 375 376 if ((str = tgetstr(cap, &tp)) != 0) { 377 /* we don't support vt100's application key mode, remap */ 378 if (str[0] == ctrl('[') && str[1] == 'O') 379 str[1] = '['; 380 while (*(*kp)++ = *cap++) 381 ; 382 (*kp)[-1] = '='; 383 while (*str) { 384 for (p = unctrl(*str++); *(*kp)++ = *p++;) 385 ; 386 (*kp)--; 387 } 388 *(*kp)++ = ':'; 389 **kp = 0; 390 } 391 } 392 393 wwstart() 394 { 395 register i; 396 397 (void) wwsettty(0, &wwnewtty); 398 signal(SIGIO, wwrint); 399 for (i = 0; i < wwnrow; i++) 400 wwtouched[i] = WWU_TOUCHED; 401 wwstart1(); 402 } 403 404 wwstart1() 405 { 406 register i, j; 407 408 for (i = 0; i < wwnrow; i++) 409 for (j = 0; j < wwncol; j++) { 410 wwos[i][j].c_w = ' '; 411 if (tt.tt_checkpoint) 412 wwcs[i][j].c_w = ' '; 413 } 414 xxstart(); 415 if (tt.tt_checkpoint) 416 wwdocheckpoint = 1; 417 } 418 419 /* 420 * Reset data structures and terminal from an unknown state. 421 * Restoring wwos has been taken care of elsewhere. 422 */ 423 wwreset() 424 { 425 register i; 426 427 xxreset(); 428 for (i = 0; i < wwnrow; i++) 429 wwtouched[i] = WWU_TOUCHED; 430 } 431