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