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