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