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