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.2 2003/06/17 04:29:34 dillon Exp $ 39 */ 40 41 #include "ww.h" 42 #include "tt.h" 43 #include <signal.h> 44 #include <fcntl.h> 45 #include <termcap.h> 46 #include "char.h" 47 48 wwinit() 49 { 50 register i, j; 51 char *kp; 52 int s; 53 54 wwdtablesize = getdtablesize(); 55 wwhead.ww_forw = &wwhead; 56 wwhead.ww_back = &wwhead; 57 58 s = sigblock(sigmask(SIGIO) | sigmask(SIGCHLD) | sigmask(SIGALRM) | 59 sigmask(SIGHUP) | sigmask(SIGTERM)); 60 if (signal(SIGIO, wwrint) == BADSIG || 61 signal(SIGCHLD, wwchild) == BADSIG || 62 signal(SIGHUP, wwquit) == BADSIG || 63 signal(SIGTERM, wwquit) == BADSIG || 64 signal(SIGPIPE, SIG_IGN) == BADSIG) { 65 wwerrno = WWE_SYS; 66 return -1; 67 } 68 69 if (wwgettty(0, &wwoldtty) < 0) 70 return -1; 71 wwwintty = wwoldtty; 72 #ifdef OLD_TTY 73 wwwintty.ww_sgttyb.sg_flags &= ~XTABS; 74 wwnewtty.ww_sgttyb = wwoldtty.ww_sgttyb; 75 wwnewtty.ww_sgttyb.sg_erase = -1; 76 wwnewtty.ww_sgttyb.sg_kill = -1; 77 wwnewtty.ww_sgttyb.sg_flags |= CBREAK; 78 wwnewtty.ww_sgttyb.sg_flags &= ~(ECHO|CRMOD); 79 wwnewtty.ww_tchars.t_intrc = -1; 80 wwnewtty.ww_tchars.t_quitc = -1; 81 wwnewtty.ww_tchars.t_startc = -1; 82 wwnewtty.ww_tchars.t_stopc = -1; 83 wwnewtty.ww_tchars.t_eofc = -1; 84 wwnewtty.ww_tchars.t_brkc = -1; 85 wwnewtty.ww_ltchars.t_suspc = -1; 86 wwnewtty.ww_ltchars.t_dsuspc = -1; 87 wwnewtty.ww_ltchars.t_rprntc = -1; 88 wwnewtty.ww_ltchars.t_flushc = -1; 89 wwnewtty.ww_ltchars.t_werasc = -1; 90 wwnewtty.ww_ltchars.t_lnextc = -1; 91 wwnewtty.ww_lmode = wwoldtty.ww_lmode | LLITOUT; 92 wwnewtty.ww_ldisc = wwoldtty.ww_ldisc; 93 #else 94 #ifndef OXTABS 95 #define OXTABS XTABS 96 #endif 97 #ifndef _POSIX_VDISABLE 98 #define _POSIX_VDISABLE -1 99 #endif 100 wwwintty.ww_termios.c_oflag &= ~OXTABS; 101 wwnewtty.ww_termios = wwoldtty.ww_termios; 102 wwnewtty.ww_termios.c_iflag &= 103 ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IMAXBEL); 104 wwnewtty.ww_termios.c_oflag = 0; 105 wwnewtty.ww_termios.c_cflag &= ~(CSIZE | PARENB); 106 wwnewtty.ww_termios.c_cflag |= CS8; 107 wwnewtty.ww_termios.c_lflag = 0; 108 for (i = 0; i < NCCS; i++) 109 wwnewtty.ww_termios.c_cc[i] = _POSIX_VDISABLE; 110 wwnewtty.ww_termios.c_cc[VMIN] = 0; 111 wwnewtty.ww_termios.c_cc[VTIME] = 0; 112 #endif 113 wwnewtty.ww_fflags = wwoldtty.ww_fflags | FASYNC; 114 if (wwsettty(0, &wwnewtty) < 0) 115 goto bad; 116 117 if ((wwterm = getenv("TERM")) == 0) { 118 wwerrno = WWE_BADTERM; 119 goto bad; 120 } 121 if (tgetent(wwtermcap, wwterm) != 1) { 122 wwerrno = WWE_BADTERM; 123 goto bad; 124 } 125 #ifdef OLD_TTY 126 ospeed = wwoldtty.ww_sgttyb.sg_ospeed; 127 switch (ospeed) { 128 default: 129 case B0: 130 goto bad; 131 case B50: 132 wwbaud = 50; 133 break; 134 case B75: 135 wwbaud = 75; 136 break; 137 case B110: 138 wwbaud = 110; 139 break; 140 case B134: 141 wwbaud = 134; 142 break; 143 case B150: 144 wwbaud = 150; 145 break; 146 case B200: 147 wwbaud = 200; 148 break; 149 case B300: 150 wwbaud = 300; 151 break; 152 case B600: 153 wwbaud = 600; 154 break; 155 case B1200: 156 wwbaud = 1200; 157 break; 158 case B1800: 159 wwbaud = 1800; 160 break; 161 case B2400: 162 wwbaud = 2400; 163 break; 164 case B4800: 165 wwbaud = 4800; 166 break; 167 case B9600: 168 wwbaud = 9600; 169 break; 170 #ifdef B19200 171 case B19200: 172 #else 173 case EXTA: 174 #endif 175 wwbaud = 19200; 176 break; 177 #ifdef B38400 178 case B38400: 179 #else 180 case EXTB: 181 #endif 182 wwbaud = 38400; 183 break; 184 #ifdef B57600 185 case B57600: 186 wwbaud = 57600; 187 break; 188 #endif 189 #ifdef B115200 190 case B115200: 191 wwbaud = 115200; 192 break; 193 #endif 194 } 195 #else 196 if ((wwbaud = cfgetospeed(&wwoldtty.ww_termios)) == B0) 197 goto bad; 198 #endif 199 wwospeed = ospeed; 200 201 if (xxinit() < 0) 202 goto bad; 203 wwnrow = tt.tt_nrow; 204 wwncol = tt.tt_ncol; 205 wwavailmodes = tt.tt_availmodes; 206 wwwrap = tt.tt_wrap; 207 208 if (wwavailmodes & WWM_REV) 209 wwcursormodes = WWM_REV | wwavailmodes & WWM_BLK; 210 else if (wwavailmodes & WWM_UL) 211 wwcursormodes = WWM_UL; 212 213 if ((wwib = malloc((unsigned) 512)) == 0) 214 goto bad; 215 wwibe = wwib + 512; 216 wwibq = wwibp = wwib; 217 218 if ((wwsmap = wwalloc(0, 0, wwnrow, wwncol, sizeof (char))) == 0) 219 goto bad; 220 for (i = 0; i < wwnrow; i++) 221 for (j = 0; j < wwncol; j++) 222 wwsmap[i][j] = WWX_NOBODY; 223 224 wwos = (union ww_char **) 225 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char)); 226 if (wwos == 0) 227 goto bad; 228 /* wwos is cleared in wwstart1() */ 229 wwns = (union ww_char **) 230 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char)); 231 if (wwns == 0) 232 goto bad; 233 for (i = 0; i < wwnrow; i++) 234 for (j = 0; j < wwncol; j++) 235 wwns[i][j].c_w = ' '; 236 if (tt.tt_checkpoint) { 237 /* wwcs is also cleared in wwstart1() */ 238 wwcs = (union ww_char **) 239 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char)); 240 if (wwcs == 0) 241 goto bad; 242 } 243 244 wwtouched = malloc((unsigned) wwnrow); 245 if (wwtouched == 0) { 246 wwerrno = WWE_NOMEM; 247 goto bad; 248 } 249 for (i = 0; i < wwnrow; i++) 250 wwtouched[i] = 0; 251 252 wwupd = (struct ww_update *) malloc((unsigned) wwnrow * sizeof *wwupd); 253 if (wwupd == 0) { 254 wwerrno = WWE_NOMEM; 255 goto bad; 256 } 257 258 wwindex[WWX_NOBODY] = &wwnobody; 259 wwnobody.ww_order = NWW; 260 261 kp = wwwintermcap; 262 if (wwavailmodes & WWM_REV) 263 wwaddcap1(WWT_REV, &kp); 264 if (wwavailmodes & WWM_BLK) 265 wwaddcap1(WWT_BLK, &kp); 266 if (wwavailmodes & WWM_UL) 267 wwaddcap1(WWT_UL, &kp); 268 if (wwavailmodes & WWM_GRP) 269 wwaddcap1(WWT_GRP, &kp); 270 if (wwavailmodes & WWM_DIM) 271 wwaddcap1(WWT_DIM, &kp); 272 if (wwavailmodes & WWM_USR) 273 wwaddcap1(WWT_USR, &kp); 274 if (tt.tt_insline && tt.tt_delline || tt.tt_setscroll) 275 wwaddcap1(WWT_ALDL, &kp); 276 if (tt.tt_inschar) 277 wwaddcap1(WWT_IMEI, &kp); 278 if (tt.tt_insspace) 279 wwaddcap1(WWT_IC, &kp); 280 if (tt.tt_delchar) 281 wwaddcap1(WWT_DC, &kp); 282 wwaddcap("kb", &kp); 283 wwaddcap2("ku", &kp); 284 wwaddcap2("kd", &kp); 285 wwaddcap2("kl", &kp); 286 wwaddcap2("kr", &kp); 287 wwaddcap("kh", &kp); 288 if ((j = tgetnum("kn")) >= 0) { 289 char cap[32]; 290 291 (void) sprintf(kp, "kn#%d:", j); 292 for (; *kp; kp++) 293 ; 294 for (i = 1; i <= j; i++) { 295 (void) sprintf(cap, "k%d", i); 296 wwaddcap(cap, &kp); 297 cap[0] = 'l'; 298 wwaddcap(cap, &kp); 299 } 300 } 301 /* 302 * It's ok to do this here even if setenv() is destructive 303 * since tt_init() has already made its own copy of it and 304 * wwterm now points to the copy. 305 */ 306 (void) setenv("TERM", WWT_TERM, 1); 307 #ifdef TERMINFO 308 if (wwterminfoinit() < 0) 309 goto bad; 310 #endif 311 312 if (tt.tt_checkpoint) 313 if (signal(SIGALRM, wwalarm) == BADSIG) { 314 wwerrno = WWE_SYS; 315 goto bad; 316 } 317 fcntl(0, F_SETOWN, getpid()); 318 /* catch typeahead before ASYNC was set */ 319 (void) kill(getpid(), SIGIO); 320 wwstart1(); 321 (void) sigsetmask(s); 322 return 0; 323 bad: 324 /* 325 * Don't bother to free storage. We're supposed 326 * to exit when wwinit fails anyway. 327 */ 328 (void) signal(SIGIO, SIG_DFL); 329 (void) wwsettty(0, &wwoldtty); 330 (void) sigsetmask(s); 331 return -1; 332 } 333 334 wwaddcap(cap, kp) 335 register char *cap; 336 register char **kp; 337 { 338 char tbuf[512]; 339 char *tp = tbuf; 340 register char *str, *p; 341 342 if ((str = tgetstr(cap, &tp)) != 0) { 343 while (*(*kp)++ = *cap++) 344 ; 345 (*kp)[-1] = '='; 346 while (*str) { 347 for (p = unctrl(*str++); *(*kp)++ = *p++;) 348 ; 349 (*kp)--; 350 } 351 *(*kp)++ = ':'; 352 **kp = 0; 353 } 354 } 355 356 wwaddcap1(cap, kp) 357 register char *cap; 358 register char **kp; 359 { 360 while (*(*kp)++ = *cap++) 361 ; 362 (*kp)--; 363 } 364 365 wwaddcap2(cap, kp) 366 register char *cap; 367 register char **kp; 368 { 369 char tbuf[512]; 370 char *tp = tbuf; 371 register char *str, *p; 372 373 if ((str = tgetstr(cap, &tp)) != 0) { 374 /* we don't support vt100's application key mode, remap */ 375 if (str[0] == ctrl('[') && str[1] == 'O') 376 str[1] = '['; 377 while (*(*kp)++ = *cap++) 378 ; 379 (*kp)[-1] = '='; 380 while (*str) { 381 for (p = unctrl(*str++); *(*kp)++ = *p++;) 382 ; 383 (*kp)--; 384 } 385 *(*kp)++ = ':'; 386 **kp = 0; 387 } 388 } 389 390 wwstart() 391 { 392 register i; 393 394 (void) wwsettty(0, &wwnewtty); 395 signal(SIGIO, wwrint); 396 for (i = 0; i < wwnrow; i++) 397 wwtouched[i] = WWU_TOUCHED; 398 wwstart1(); 399 } 400 401 wwstart1() 402 { 403 register i, j; 404 405 for (i = 0; i < wwnrow; i++) 406 for (j = 0; j < wwncol; j++) { 407 wwos[i][j].c_w = ' '; 408 if (tt.tt_checkpoint) 409 wwcs[i][j].c_w = ' '; 410 } 411 xxstart(); 412 if (tt.tt_checkpoint) 413 wwdocheckpoint = 1; 414 } 415 416 /* 417 * Reset data structures and terminal from an unknown state. 418 * Restoring wwos has been taken care of elsewhere. 419 */ 420 wwreset() 421 { 422 register i; 423 424 xxreset(); 425 for (i = 0; i < wwnrow; i++) 426 wwtouched[i] = WWU_TOUCHED; 427 } 428