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 37 #ifndef lint 38 static char sccsid[] = "@(#)wwinit.c 8.1 (Berkeley) 6/6/93"; 39 static char rcsid[] = 40 "$FreeBSD: src/usr.bin/window/wwinit.c,v 1.11.2.1 2001/05/17 09:45:01 obrien Exp $"; 41 #endif /* not lint */ 42 43 #include "ww.h" 44 #include "tt.h" 45 #include <signal.h> 46 #include <fcntl.h> 47 #include <termcap.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 (void) setenv("TERM", WWT_TERM, 1); 309 #ifdef TERMINFO 310 if (wwterminfoinit() < 0) 311 goto bad; 312 #endif 313 314 if (tt.tt_checkpoint) 315 if (signal(SIGALRM, wwalarm) == BADSIG) { 316 wwerrno = WWE_SYS; 317 goto bad; 318 } 319 fcntl(0, F_SETOWN, getpid()); 320 /* catch typeahead before ASYNC was set */ 321 (void) kill(getpid(), SIGIO); 322 wwstart1(); 323 (void) sigsetmask(s); 324 return 0; 325 bad: 326 /* 327 * Don't bother to free storage. We're supposed 328 * to exit when wwinit fails anyway. 329 */ 330 (void) signal(SIGIO, SIG_DFL); 331 (void) wwsettty(0, &wwoldtty); 332 (void) sigsetmask(s); 333 return -1; 334 } 335 336 wwaddcap(cap, kp) 337 register char *cap; 338 register char **kp; 339 { 340 char tbuf[512]; 341 char *tp = tbuf; 342 register char *str, *p; 343 344 if ((str = tgetstr(cap, &tp)) != 0) { 345 while (*(*kp)++ = *cap++) 346 ; 347 (*kp)[-1] = '='; 348 while (*str) { 349 for (p = unctrl(*str++); *(*kp)++ = *p++;) 350 ; 351 (*kp)--; 352 } 353 *(*kp)++ = ':'; 354 **kp = 0; 355 } 356 } 357 358 wwaddcap1(cap, kp) 359 register char *cap; 360 register char **kp; 361 { 362 while (*(*kp)++ = *cap++) 363 ; 364 (*kp)--; 365 } 366 367 wwaddcap2(cap, kp) 368 register char *cap; 369 register char **kp; 370 { 371 char tbuf[512]; 372 char *tp = tbuf; 373 register char *str, *p; 374 375 if ((str = tgetstr(cap, &tp)) != 0) { 376 /* we don't support vt100's application key mode, remap */ 377 if (str[0] == ctrl('[') && str[1] == 'O') 378 str[1] = '['; 379 while (*(*kp)++ = *cap++) 380 ; 381 (*kp)[-1] = '='; 382 while (*str) { 383 for (p = unctrl(*str++); *(*kp)++ = *p++;) 384 ; 385 (*kp)--; 386 } 387 *(*kp)++ = ':'; 388 **kp = 0; 389 } 390 } 391 392 wwstart() 393 { 394 register i; 395 396 (void) wwsettty(0, &wwnewtty); 397 signal(SIGIO, wwrint); 398 for (i = 0; i < wwnrow; i++) 399 wwtouched[i] = WWU_TOUCHED; 400 wwstart1(); 401 } 402 403 wwstart1() 404 { 405 register i, j; 406 407 for (i = 0; i < wwnrow; i++) 408 for (j = 0; j < wwncol; j++) { 409 wwos[i][j].c_w = ' '; 410 if (tt.tt_checkpoint) 411 wwcs[i][j].c_w = ' '; 412 } 413 xxstart(); 414 if (tt.tt_checkpoint) 415 wwdocheckpoint = 1; 416 } 417 418 /* 419 * Reset data structures and terminal from an unknown state. 420 * Restoring wwos has been taken care of elsewhere. 421 */ 422 wwreset() 423 { 424 register i; 425 426 xxreset(); 427 for (i = 0; i < wwnrow; i++) 428 wwtouched[i] = WWU_TOUCHED; 429 } 430