1 /*--------------------------------*-C-*---------------------------------*
2  * File:	init.c
3  *----------------------------------------------------------------------*
4  * $Id: init.c,v 1.103 2002/12/04 05:21:29 gcw Exp $
5  *
6  * All portions of code are copyright by their respective author/s.
7  * Copyright (c) 1992      John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
8  *				- original version
9  * Copyright (c) 1994      Robert Nation <nation@rocket.sanders.lockheed.com>
10  * 				- extensive modifications
11  * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
12  * 				- extensive modifications
13  * Copyright (c) 1999      D J Hawkey Jr <hawkeyd@visi.com>
14  *				- QNX support
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29  *---------------------------------------------------------------------*/
30 /*
31  * Initialisation routines.
32  */
33 
34 #include "../config.h"		/* NECESSARY */
35 #include "xvt.h"		/* NECESSARY */
36 #include "init.h"
37 
38 #include <signal.h>
39 
40 const char *const def_colorName[] = {
41     COLOR_FOREGROUND,
42     COLOR_BACKGROUND,
43 /* low-intensity colors */
44     "Black",			/* 0: black             (#000000) */
45 #ifndef NO_BRIGHTCOLOR
46     "Red3",			/* 1: red               (#CD0000) */
47     "Green3",			/* 2: green             (#00CD00) */
48     "Yellow3",			/* 3: yellow            (#CDCD00) */
49     "Blue3",			/* 4: blue              (#0000CD) */
50     "Magenta3",			/* 5: magenta           (#CD00CD) */
51     "Cyan3",			/* 6: cyan              (#00CDCD) */
52 # ifdef XTERM_COLORS
53     "Grey90",			/* 7: white             (#E5E5E5) */
54 # else
55     "AntiqueWhite",		/* 7: white             (#FAEBD7) */
56 # endif
57 /* high-intensity colors */
58 # ifdef XTERM_COLORS
59     "Grey30",			/* 8: bright black      (#4D4D4D) */
60 # else
61     "Grey25",			/* 8: bright black      (#404040) */
62 # endif
63 #endif				/* NO_BRIGHTCOLOR */
64     "Red",			/* 1/9: bright red      (#FF0000) */
65     "Green",			/* 2/10: bright green   (#00FF00) */
66     "Yellow",			/* 3/11: bright yellow  (#FFFF00) */
67     "Blue",			/* 4/12: bright blue    (#0000FF) */
68     "Magenta",			/* 5/13: bright magenta (#FF00FF) */
69     "Cyan",			/* 6/14: bright cyan    (#00FFFF) */
70     "White",			/* 7/15: bright white   (#FFFFFF) */
71 #ifdef TTY_256COLOR
72     "rgb:00/00/00",		/* default 16-255 color table     */
73     "rgb:00/00/2a",
74     "rgb:00/00/55",
75     "rgb:00/00/7f",
76     "rgb:00/00/aa",
77     "rgb:00/00/d4",
78     "rgb:00/2a/00",
79     "rgb:00/2a/2a",
80     "rgb:00/2a/55",
81     "rgb:00/2a/7f",
82     "rgb:00/2a/aa",
83     "rgb:00/2a/d4",
84     "rgb:00/55/00",
85     "rgb:00/55/2a",
86     "rgb:00/55/55",
87     "rgb:00/55/7f",
88     "rgb:00/55/aa",
89     "rgb:00/55/d4",
90     "rgb:00/7f/00",
91     "rgb:00/7f/2a",
92     "rgb:00/7f/55",
93     "rgb:00/7f/7f",
94     "rgb:00/7f/aa",
95     "rgb:00/7f/d4",
96     "rgb:00/aa/00",
97     "rgb:00/aa/2a",
98     "rgb:00/aa/55",
99     "rgb:00/aa/7f",
100     "rgb:00/aa/aa",
101     "rgb:00/aa/d4",
102     "rgb:00/d4/00",
103     "rgb:00/d4/2a",
104     "rgb:00/d4/55",
105     "rgb:00/d4/7f",
106     "rgb:00/d4/aa",
107     "rgb:00/d4/d4",
108     "rgb:2a/00/00",
109     "rgb:2a/00/2a",
110     "rgb:2a/00/55",
111     "rgb:2a/00/7f",
112     "rgb:2a/00/aa",
113     "rgb:2a/00/d4",
114     "rgb:2a/2a/00",
115     "rgb:2a/2a/2a",
116     "rgb:2a/2a/55",
117     "rgb:2a/2a/7f",
118     "rgb:2a/2a/aa",
119     "rgb:2a/2a/d4",
120     "rgb:2a/55/00",
121     "rgb:2a/55/2a",
122     "rgb:2a/55/55",
123     "rgb:2a/55/7f",
124     "rgb:2a/55/aa",
125     "rgb:2a/55/d4",
126     "rgb:2a/7f/00",
127     "rgb:2a/7f/2a",
128     "rgb:2a/7f/55",
129     "rgb:2a/7f/7f",
130     "rgb:2a/7f/aa",
131     "rgb:2a/7f/d4",
132     "rgb:2a/aa/00",
133     "rgb:2a/aa/2a",
134     "rgb:2a/aa/55",
135     "rgb:2a/aa/7f",
136     "rgb:2a/aa/aa",
137     "rgb:2a/aa/d4",
138     "rgb:2a/d4/00",
139     "rgb:2a/d4/2a",
140     "rgb:2a/d4/55",
141     "rgb:2a/d4/7f",
142     "rgb:2a/d4/aa",
143     "rgb:2a/d4/d4",
144     "rgb:55/00/00",
145     "rgb:55/00/2a",
146     "rgb:55/00/55",
147     "rgb:55/00/7f",
148     "rgb:55/00/aa",
149     "rgb:55/00/d4",
150     "rgb:55/2a/00",
151     "rgb:55/2a/2a",
152     "rgb:55/2a/55",
153     "rgb:55/2a/7f",
154     "rgb:55/2a/aa",
155     "rgb:55/2a/d4",
156     "rgb:55/55/00",
157     "rgb:55/55/2a",
158     "rgb:55/55/55",
159     "rgb:55/55/7f",
160     "rgb:55/55/aa",
161     "rgb:55/55/d4",
162     "rgb:55/7f/00",
163     "rgb:55/7f/2a",
164     "rgb:55/7f/55",
165     "rgb:55/7f/7f",
166     "rgb:55/7f/aa",
167     "rgb:55/7f/d4",
168     "rgb:55/aa/00",
169     "rgb:55/aa/2a",
170     "rgb:55/aa/55",
171     "rgb:55/aa/7f",
172     "rgb:55/aa/aa",
173     "rgb:55/aa/d4",
174     "rgb:55/d4/00",
175     "rgb:55/d4/2a",
176     "rgb:55/d4/55",
177     "rgb:55/d4/7f",
178     "rgb:55/d4/aa",
179     "rgb:55/d4/d4",
180     "rgb:7f/00/00",
181     "rgb:7f/00/2a",
182     "rgb:7f/00/55",
183     "rgb:7f/00/7f",
184     "rgb:7f/00/aa",
185     "rgb:7f/00/d4",
186     "rgb:7f/2a/00",
187     "rgb:7f/2a/2a",
188     "rgb:7f/2a/55",
189     "rgb:7f/2a/7f",
190     "rgb:7f/2a/aa",
191     "rgb:7f/2a/d4",
192     "rgb:7f/55/00",
193     "rgb:7f/55/2a",
194     "rgb:7f/55/55",
195     "rgb:7f/55/7f",
196     "rgb:7f/55/aa",
197     "rgb:7f/55/d4",
198     "rgb:7f/7f/00",
199     "rgb:7f/7f/2a",
200     "rgb:7f/7f/55",
201     "rgb:7f/7f/7f",
202     "rgb:7f/7f/aa",
203     "rgb:7f/7f/d4",
204     "rgb:7f/aa/00",
205     "rgb:7f/aa/2a",
206     "rgb:7f/aa/55",
207     "rgb:7f/aa/7f",
208     "rgb:7f/aa/aa",
209     "rgb:7f/aa/d4",
210     "rgb:7f/d4/00",
211     "rgb:7f/d4/2a",
212     "rgb:7f/d4/55",
213     "rgb:7f/d4/7f",
214     "rgb:7f/d4/aa",
215     "rgb:7f/d4/d4",
216     "rgb:aa/00/00",
217     "rgb:aa/00/2a",
218     "rgb:aa/00/55",
219     "rgb:aa/00/7f",
220     "rgb:aa/00/aa",
221     "rgb:aa/00/d4",
222     "rgb:aa/2a/00",
223     "rgb:aa/2a/2a",
224     "rgb:aa/2a/55",
225     "rgb:aa/2a/7f",
226     "rgb:aa/2a/aa",
227     "rgb:aa/2a/d4",
228     "rgb:aa/55/00",
229     "rgb:aa/55/2a",
230     "rgb:aa/55/55",
231     "rgb:aa/55/7f",
232     "rgb:aa/55/aa",
233     "rgb:aa/55/d4",
234     "rgb:aa/7f/00",
235     "rgb:aa/7f/2a",
236     "rgb:aa/7f/55",
237     "rgb:aa/7f/7f",
238     "rgb:aa/7f/aa",
239     "rgb:aa/7f/d4",
240     "rgb:aa/aa/00",
241     "rgb:aa/aa/2a",
242     "rgb:aa/aa/55",
243     "rgb:aa/aa/7f",
244     "rgb:aa/aa/aa",
245     "rgb:aa/aa/d4",
246     "rgb:aa/d4/00",
247     "rgb:aa/d4/2a",
248     "rgb:aa/d4/55",
249     "rgb:aa/d4/7f",
250     "rgb:aa/d4/aa",
251     "rgb:aa/d4/d4",
252     "rgb:d4/00/00",
253     "rgb:d4/00/2a",
254     "rgb:d4/00/55",
255     "rgb:d4/00/7f",
256     "rgb:d4/00/aa",
257     "rgb:d4/00/d4",
258     "rgb:d4/2a/00",
259     "rgb:d4/2a/2a",
260     "rgb:d4/2a/55",
261     "rgb:d4/2a/7f",
262     "rgb:d4/2a/aa",
263     "rgb:d4/2a/d4",
264     "rgb:d4/55/00",
265     "rgb:d4/55/2a",
266     "rgb:d4/55/55",
267     "rgb:d4/55/7f",
268     "rgb:d4/55/aa",
269     "rgb:d4/55/d4",
270     "rgb:d4/7f/00",
271     "rgb:d4/7f/2a",
272     "rgb:d4/7f/55",
273     "rgb:d4/7f/7f",
274     "rgb:d4/7f/aa",
275     "rgb:d4/7f/d4",
276     "rgb:d4/aa/00",
277     "rgb:d4/aa/2a",
278     "rgb:d4/aa/55",
279     "rgb:d4/aa/7f",
280     "rgb:d4/aa/aa",
281     "rgb:d4/aa/d4",
282     "rgb:d4/d4/00",
283     "rgb:d4/d4/2a",
284     "rgb:d4/d4/55",
285     "rgb:d4/d4/7f",
286     "rgb:d4/d4/aa",
287     "rgb:d4/d4/d4",
288     "rgb:08/08/08",
289     "rgb:12/12/12",
290     "rgb:1c/1c/1c",
291     "rgb:26/26/26",
292     "rgb:30/30/30",
293     "rgb:3a/3a/3a",
294     "rgb:44/44/44",
295     "rgb:4e/4e/4e",
296     "rgb:58/58/58",
297     "rgb:62/62/62",
298     "rgb:6c/6c/6c",
299     "rgb:76/76/76",
300     "rgb:80/80/80",
301     "rgb:8a/8a/8a",
302     "rgb:94/94/94",
303     "rgb:9e/9e/9e",
304     "rgb:a8/a8/a8",
305     "rgb:b2/b2/b2",
306     "rgb:bc/bc/bc",
307     "rgb:c6/c6/c6",
308     "rgb:d0/d0/d0",
309     "rgb:da/da/da",
310     "rgb:e4/e4/e4",
311     "rgb:ee/ee/ee",
312 #endif
313 #ifndef NO_CURSORCOLOR
314     COLOR_CURSOR_BACKGROUND,
315     COLOR_CURSOR_FOREGROUND,
316 #endif				/* ! NO_CURSORCOLOR */
317     NULL,			/* Color_pointer                  */
318     NULL,			/* Color_border                   */
319 #ifndef NO_BOLD_UNDERLINE_REVERSE
320     NULL,			/* Color_BD                       */
321     NULL,			/* Color_UL                       */
322     NULL,			/* Color_RV                       */
323 #endif				/* ! NO_BOLD_UNDERLINE_REVERSE */
324 #ifdef OPTION_HC
325     NULL,
326 #endif
327 #ifdef KEEP_SCROLLCOLOR
328     COLOR_SCROLLBAR,
329     COLOR_SCROLLTROUGH,
330 #endif				/* KEEP_SCROLLCOLOR */
331 };
332 
333 const char *const xa_names[NUM_XA] = {
334     "COMPOUND_TEXT",
335     "MULTIPLE",
336     "TARGETS",
337     "TEXT",
338     "TIMESTAMP",
339     "VT_SELECTION",
340     "INCR",
341     "WM_DELETE_WINDOW",
342 #ifdef TRANSPARENT
343     "_XROOTPMAP_ID",
344 #endif
345 #ifdef OFFIX_DND
346     "DndProtocol",
347     "DndSelection",
348 #endif
349     "CLIPBOARD"
350 };
351 
352 /*----------------------------------------------------------------------*/
353 /* substitute system functions */
354 #if defined(__svr4__) && ! defined(_POSIX_VERSION)
355 /* INTPROTO */
356 int
xvt_getdtablesize(void)357 xvt_getdtablesize(void)
358 {
359     struct rlimit   rlim;
360 
361     getrlimit(RLIMIT_NOFILE, &rlim);
362     return rlim.rlim_cur;
363 }
364 #endif
365 /*----------------------------------------------------------------------*/
366 /* EXTPROTO */
367 int
xvt_init_vars(xvt_t * r)368 xvt_init_vars(xvt_t *r)
369 {
370     struct xvt_hidden *h;
371 
372 #ifndef NULLS_ARE_NOT_ZEROS
373     MEMSET(r, 0, sizeof(xvt_t));
374 #endif
375     h = r->h = (struct xvt_hidden *)xvt_calloc(1, sizeof(struct xvt_hidden));
376 
377     r->PixColors = (Pixel *)xvt_malloc(sizeof(Pixel) * TOTAL_COLORS);
378     if (r->h == NULL || r->PixColors == NULL)
379 	return -1;
380 #ifdef NULLS_ARE_NOT_ZEROS
381     r->Xdisplay = NULL;
382     r->TermWin.fontset = NULL;
383 #ifndef NO_BOLDFONT
384     r->TermWin.boldFont_loaded = NULL;
385 #endif
386     r->h->ttydev = NULL;
387     h->xa[XA_COMPOUND_TEXT] = h->xa[XA_MULTIPLE] = h->xa[XA_TARGETS] =
388 	h->xa[XA_TEXT] = h->xa[XA_TIMESTAMP] = h->xa[XA_VT_SELECTION] =
389 	h->xa[XA_INCR] = NULL;
390     h->locale = NULL;
391 # ifdef MENUBAR
392     h->menubarGC = None;
393     h->BuildMenu = NULL;	/* the menu currently being built */
394 #  if (MENUBAR_MAX > 1)
395     h->CurrentBar = NULL;
396 #  endif			/* (MENUBAR_MAX > 1) */
397 # endif
398 # ifdef USE_XIM
399     h->Input_Context = NULL;
400 # endif
401     h->v_bufstr = NULL;
402 # ifdef XVT_GRAPHICS
403     h->gr_root = NULL;
404     h->gr_last_id = None;
405 # endif
406     h->buffer = NULL;
407     h->compose.compose_ptr = NULL;
408 #endif				/* NULLS_ARE_NOT_ZEROS */
409 
410 #if defined(XPM_BACKGROUND) || defined(TRANSPARENT)
411     r->TermWin.pixmap = None;
412 #endif
413 #ifdef UTMP_SUPPORT
414     h->next_utmp_action = SAVE;
415 #endif
416 #ifndef NO_SETOWNER_TTYDEV
417     h->next_tty_action = SAVE;
418 #endif
419     h->MEvent.time = CurrentTime;
420     h->MEvent.button = AnyButton;
421     r->Options = DEFAULT_OPTIONS;
422     h->want_refresh = 1;
423     h->cmd_pid = -1;
424     r->cmd_fd = r->tty_fd = r->Xfd = -1;
425     h->PrivateModes = h->SavedModes = PrivMode_Default;
426     r->TermWin.focus = 1;
427     r->TermWin.ncol = 80;
428     r->TermWin.nrow = 24;
429     r->TermWin.int_bwidth = INTERNALBORDERWIDTH;
430     r->TermWin.ext_bwidth = EXTERNALBORDERWIDTH;
431     r->TermWin.lineSpace = LINESPACE;
432     r->TermWin.saveLines = SAVELINES;
433     r->numPixColors = TOTAL_COLORS;
434 #ifndef NO_NEW_SELECTION
435     r->selection_style = NEW_SELECT;
436 #else
437     r->selection_style = OLD_SELECT;
438 #endif
439 #ifndef NO_BRIGHTCOLOR
440     h->colorfgbg = DEFAULT_RSTYLE;
441 #endif
442 #if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
443     h->ks_bigfont = XK_greater;
444     h->ks_smallfont = XK_less;
445 #endif
446 #ifdef GREEK_SUPPORT
447     h->ks_greekmodeswith = GREEK_KEYBOARD_MODESWITCH;
448 #endif
449     h->refresh_limit = 1;
450     h->refresh_type = SLOW_REFRESH;
451     h->prev_nrow = h->prev_ncol = 0;
452 #ifdef MULTICHAR_SET
453 # ifdef MULTICHAR_ENCODING
454     r->encoding_method = MULTICHAR_ENCODING;
455 # endif
456     h->multichar_decode = xvt_euc2jis;
457 #endif
458     h->oldcursor.row = h->oldcursor.col = -1;
459 #ifdef XPM_BACKGROUND
460 /*  h->bgPixmap.w = h->bgPixmap.h = 0; */
461     h->bgPixmap.x = h->bgPixmap.y = 50;
462     h->bgPixmap.pixmap = None;
463 #endif
464     h->last_bot = h->last_state = -1;
465 #ifdef MENUBAR
466     h->menu_readonly = 1;
467 # if !(MENUBAR_MAX > 1)
468     h->CurrentBar = &(h->BarList);
469 # endif				/* (MENUBAR_MAX > 1) */
470 #endif
471     return 0;
472 }
473 
474 /* EXTPROTO */
475 void
xvt_init_secondary(xvt_t * r)476 xvt_init_secondary(xvt_t *r)
477 {
478 #ifdef TTY_GID_SUPPORT
479     struct group   *gr = getgrnam("tty");
480 
481     if (gr) {		/* change group ownership of tty to "tty" */
482 	r->h->ttymode = S_IRUSR | S_IWUSR | S_IWGRP;
483 	r->h->ttygid = gr->gr_gid;
484     } else
485 #endif				/* TTY_GID_SUPPORT */
486     {
487 	r->h->ttymode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
488 	r->h->ttygid = getgid();
489     }
490 #if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
491     r->h->locale = setlocale(LC_CTYPE, "");
492 #endif
493 }
494 
495 /*----------------------------------------------------------------------*/
496 /* EXTPROTO */
497 const char    **
xvt_init_resources(xvt_t * r,int argc,const char * const * argv)498 xvt_init_resources(xvt_t *r, int argc, const char *const *argv)
499 {
500     int             i, r_argc;
501     char           *val;
502     const char    **cmd_argv, **r_argv;
503     const char    **rs;
504 
505 /*
506  * Look for -exec option.  Find => split and make cmd_argv[] of command args
507  */
508     for (r_argc = 0; r_argc < argc; r_argc++)
509 	if (!STRCMP(argv[r_argc], "-e") || !STRCMP(argv[r_argc], "-exec"))
510 	    break;
511     r_argv = (const char **)xvt_malloc(sizeof(char *) * (r_argc + 1));
512 
513     for (i = 0; i < r_argc; i++)
514 	r_argv[i] = (const char *)argv[i];
515     r_argv[i] = NULL;
516     if (r_argc == argc)
517 	cmd_argv = NULL;
518     else {
519 	cmd_argv = (const char **)xvt_malloc(sizeof(char *) * (argc - r_argc));
520 
521 	for (i = 0; i < argc - r_argc - 1; i++)
522 	    cmd_argv[i] = (const char *)argv[i + r_argc + 1];
523 	cmd_argv[i] = NULL;
524     }
525 
526 /* clear all resources */
527     rs = r->h->rs;
528     for (i = 0; i < NUM_RESOURCES;)
529 	rs[i++] = NULL;
530 
531     rs[Rs_name] = xvt_r_basename(argv[0]);
532 /*
533  * Open display, get options/resources and create the window
534  */
535     if ((rs[Rs_display_name] = getenv("DISPLAY")) == NULL)
536 	rs[Rs_display_name] = ":0";
537 
538     xvt_get_options(r, r_argc, r_argv);
539     free(r_argv);
540 
541 #ifdef LOCAL_X_IS_UNIX
542     if (rs[Rs_display_name][0] == ':') {
543 	val = xvt_malloc(5 + STRLEN(rs[Rs_display_name]));
544 	STRCPY(val, "unix");
545 	STRCAT(val, rs[Rs_display_name]);
546 	r->Xdisplay = XOpenDisplay(val);
547 	free(val);
548     }
549 #endif
550 
551     if (r->Xdisplay == NULL
552 	&& (r->Xdisplay = XOpenDisplay(rs[Rs_display_name])) == NULL) {
553 	xvt_print_error("can't open display %s", rs[Rs_display_name]);
554 	exit(EXIT_FAILURE);
555     }
556 
557     xvt_extract_resources(r, r->Xdisplay, rs[Rs_name]);
558 
559 /*
560  * set any defaults not already set
561  */
562     if (cmd_argv && cmd_argv[0]) {
563 	if (!rs[Rs_title])
564 	    rs[Rs_title] = xvt_r_basename(cmd_argv[0]);
565 	if (!rs[Rs_iconName])
566 	    rs[Rs_iconName] = rs[Rs_title];
567     } else {
568 	if (!rs[Rs_title])
569 	    rs[Rs_title] = rs[Rs_name];
570 	if (!rs[Rs_iconName])
571 	    rs[Rs_iconName] = rs[Rs_name];
572     }
573     if (rs[Rs_saveLines] && (i = atoi(rs[Rs_saveLines])) >= 0)
574 	r->TermWin.saveLines = BOUND_POSITIVE_INT16(i);
575 #ifndef NO_FRILLS
576     if (rs[Rs_int_bwidth] && (i = atoi(rs[Rs_int_bwidth])) >= 0)
577 	r->TermWin.int_bwidth = min(i, 100);	/* arbitrary limit */
578     if (rs[Rs_ext_bwidth] && (i = atoi(rs[Rs_ext_bwidth])) >= 0)
579 	r->TermWin.ext_bwidth = min(i, 100);	/* arbitrary limit */
580 #endif
581 #ifndef NO_LINESPACE
582     if (rs[Rs_lineSpace] && (i = atoi(rs[Rs_lineSpace])) >= 0)
583 	r->TermWin.lineSpace = min(i, 100);	/* arbitrary limit */
584 #endif
585 
586 /* no point having a scrollbar without having any scrollback! */
587     if (!r->TermWin.saveLines)
588 	r->Options &= ~Opt_scrollBar;
589 
590 #ifdef PRINTPIPE
591     if (!rs[Rs_print_pipe])
592 	rs[Rs_print_pipe] = PRINTPIPE;
593 #endif
594     if (!rs[Rs_cutchars])
595 	rs[Rs_cutchars] = CUTCHARS;
596 #ifndef NO_BACKSPACE_KEY
597     if (!rs[Rs_backspace_key])
598 # ifdef DEFAULT_BACKSPACE
599 	r->h->key_backspace = DEFAULT_BACKSPACE;
600 # else
601 	r->h->key_backspace = "DEC";	/* can toggle between \033 or \177 */
602 # endif
603     else {
604 	val = STRDUP(rs[Rs_backspace_key]);
605 	xvt_Str_trim(val);
606 	xvt_Str_escaped(val);
607 	r->h->key_backspace = val;
608     }
609 #endif
610 #ifndef NO_DELETE_KEY
611     if (!rs[Rs_delete_key])
612 # ifdef DEFAULT_DELETE
613 	r->h->key_delete = DEFAULT_DELETE;
614 # else
615 	r->h->key_delete = "\033[3~";
616 # endif
617     else {
618 	val = STRDUP(rs[Rs_delete_key]);
619 	xvt_Str_trim(val);
620 	xvt_Str_escaped(val);
621 	r->h->key_delete = val;
622     }
623 #endif
624     if (rs[Rs_answerbackstring]) {
625 	xvt_Str_trim((char *)rs[Rs_answerbackstring]);
626 	xvt_Str_escaped((char *)rs[Rs_answerbackstring]);
627     }
628 
629     if (rs[Rs_selectstyle]) {
630 	if (STRNCASECMP(rs[Rs_selectstyle], "oldword", 7) == 0)
631 	    r->selection_style = OLD_WORD_SELECT;
632 #ifndef NO_OLD_SELECTION
633 	else if (STRNCASECMP(rs[Rs_selectstyle], "old", 3) == 0)
634 	    r->selection_style = OLD_SELECT;
635 #endif
636     }
637 
638 #ifdef HAVE_SCROLLBARS
639     xvt_setup_scrollbar(r, rs[Rs_scrollBar_align], rs[Rs_scrollstyle],
640 			 rs[Rs_scrollBar_thickness]);
641 #endif
642 
643 #if 0	/* #ifndef NO_BOLDFONT */
644     if (rs[Rs_font] == NULL && rs[Rs_boldFont] != NULL) {
645 	rs[Rs_font] = rs[Rs_boldFont];
646 	rs[Rs_boldFont] = NULL;
647     }
648 #endif
649     xvt_set_defaultfont(r, rs);
650 
651 #ifdef XTERM_REVERSE_VIDEO
652 /* this is how xterm implements reverseVideo */
653     if (r->Options & Opt_reverseVideo) {
654 	if (!rs[Rs_color + Color_fg])
655 	    rs[Rs_color + Color_fg] = def_colorName[Color_bg];
656 	if (!rs[Rs_color + Color_bg])
657 	    rs[Rs_color + Color_bg] = def_colorName[Color_fg];
658     }
659 #endif
660 
661     for (i = 0; i < NRS_COLORS; i++)
662 	if (!rs[Rs_color + i])
663 	    rs[Rs_color + i] = def_colorName[i];
664 
665 #ifndef XTERM_REVERSE_VIDEO
666 /* this is how we implement reverseVideo */
667     if (r->Options & Opt_reverseVideo)
668 	SWAP_IT(rs[Rs_color + Color_fg], rs[Rs_color + Color_bg], const char *);
669 #endif
670 
671 /* convenient aliases for setting fg/bg to colors */
672     xvt_color_aliases(r, Color_fg);
673     xvt_color_aliases(r, Color_bg);
674 #ifndef NO_CURSORCOLOR
675     xvt_color_aliases(r, Color_cursor);
676     xvt_color_aliases(r, Color_cursor2);
677 #endif				/* NO_CURSORCOLOR */
678     xvt_color_aliases(r, Color_pointer);
679     xvt_color_aliases(r, Color_border);
680 #ifndef NO_BOLD_UNDERLINE_REVERSE
681     xvt_color_aliases(r, Color_BD);
682     xvt_color_aliases(r, Color_UL);
683     xvt_color_aliases(r, Color_RV);
684 #endif				/* ! NO_BOLD_UNDERLINE_REVERSE */
685 
686     return cmd_argv;
687 }
688 
689 /*----------------------------------------------------------------------*/
690 /* EXTPROTO */
691 void
xvt_init_env(xvt_t * r)692 xvt_init_env(xvt_t *r)
693 {
694     int             i;
695     unsigned int    u;
696     char           *val;
697 
698 #ifdef DISPLAY_IS_IP
699 /* Fixup display_name for export over pty to any interested terminal
700  * clients via "ESC[7n" (e.g. shells).  Note we use the pure IP number
701  * (for the first non-loopback interface) that we get from
702  * xvt_network_display().  This is more "name-resolution-portable", if you
703  * will, and probably allows for faster x-client startup if your name
704  * server is beyond a slow link or overloaded at client startup.  Of
705  * course that only helps the shell's child processes, not us.
706  *
707  * Giving out the display_name also affords a potential security hole
708  */
709     val = xvt_network_display(r->h->rs[Rs_display_name]);
710     r->h->rs[Rs_display_name] = (const char *)val;
711     if (val == NULL)
712 #endif				/* DISPLAY_IS_IP */
713 	val = XDisplayString(r->Xdisplay);
714     if (r->h->rs[Rs_display_name] == NULL)
715 	r->h->rs[Rs_display_name] = val;	/* use broken `:0' value */
716 
717     i = STRLEN(val);
718     r->h->env_display = xvt_malloc((i + 9) * sizeof(char));
719 
720     sprintf(r->h->env_display, "DISPLAY=%s", val);
721 
722     /* avoiding the math library:
723      * i = (int)(ceil(log10((unsigned int)r->TermWin.parent[0]))) */
724     for (i = 0, u = (unsigned int)r->TermWin.parent[0]; u; u /= 10, i++) ;
725     MAX_IT(i, 1);
726     r->h->env_windowid = xvt_malloc((i + 10) * sizeof(char));
727 
728     sprintf(r->h->env_windowid, "WINDOWID=%u",
729 	    (unsigned int)r->TermWin.parent[0]);
730 
731 /* add entries to the environment:
732  * @ DISPLAY:   in case we started with -display
733  * @ WINDOWID:  X window id number of the window
734  * @ COLORTERM: terminal sub-name and also indicates its color
735  * @ TERM:      terminal name
736  * @ TERMINFO:	path to terminfo directory
737  */
738     putenv(r->h->env_display);
739     putenv(r->h->env_windowid);
740 #ifdef XVT_TERMINFO
741     putenv("TERMINFO=" XVT_TERMINFO);
742 #endif
743     if (XDEPTH <= 2)
744 	putenv("COLORTERM=" COLORTERMENV "-mono");
745     else
746 	putenv("COLORTERM=" COLORTERMENVFULL);
747     if (r->h->rs[Rs_term_name] != NULL) {
748 	r->h->env_term = xvt_malloc((STRLEN(r->h->rs[Rs_term_name]) + 6)
749 				* sizeof(char));
750 	sprintf(r->h->env_term, "TERM=%s", r->h->rs[Rs_term_name]);
751 	putenv(r->h->env_term);
752     } else
753 	putenv("TERM=" TERMENV);
754 
755 #ifdef HAVE_UNSETENV
756 /* avoid passing old settings and confusing term size */
757     unsetenv("LINES");
758     unsetenv("COLUMNS");
759     unsetenv("TERMCAP");	/* terminfo should be okay */
760 #endif				/* HAVE_UNSETENV */
761 }
762 
763 /*----------------------------------------------------------------------*/
764 /*
765  * This is more or less stolen straight from XFree86 xterm.
766  * This should support all European type languages.
767  */
768 /* EXTPROTO */
769 void
xvt_init_xlocale(xvt_t * r)770 xvt_init_xlocale(xvt_t *r)
771 {
772 #ifdef USE_XIM
773     if (r->h->locale == NULL)
774 	xvt_print_error("Setting locale failed.");
775     else {
776 	Atom            wmlocale;
777 
778 	wmlocale = XInternAtom(r->Xdisplay, "WM_LOCALE_NAME", False);
779 	XChangeProperty(r->Xdisplay, r->TermWin.parent[0], wmlocale,
780 			XA_STRING, 8, PropModeReplace,
781 			(unsigned char *)r->h->locale, STRLEN(r->h->locale));
782 
783 	if (XSupportsLocale() != True) {
784 	    xvt_print_error("The locale is not supported by Xlib");
785 	    return;
786 	}
787 	xvt_setTermFontSet(r, 0);
788 
789 	/* see if we can connect yet */
790 	xvt_IMInstantiateCallback(r->Xdisplay, NULL, NULL);
791 
792 	/* To avoid Segmentation Fault in C locale: Solaris only? */
793 	if (STRCMP(r->h->locale, "C"))
794 	    XRegisterIMInstantiateCallback(r->Xdisplay, NULL, NULL, NULL,
795 					   xvt_IMInstantiateCallback, NULL);
796     }
797 #endif
798 }
799 
800 /*----------------------------------------------------------------------*/
801 /* EXTPROTO */
802 void
xvt_init_command(xvt_t * r,const char * const * argv)803 xvt_init_command(xvt_t *r, const char *const *argv)
804 {
805 /*
806  * Initialize the command connection.
807  * This should be called after the X server connection is established.
808  */
809     int             i;
810 
811     for (i = 0; i < NUM_XA; i++)
812 	r->h->xa[i] = XInternAtom(r->Xdisplay, xa_names[i], False);
813 
814 /* Enable delete window protocol */
815     XSetWMProtocols(r->Xdisplay, r->TermWin.parent[0],
816 		    &(r->h->xa[XA_WMDELETEWINDOW]), 1);
817 
818 #ifdef USING_W11LIB
819 /* enable W11 callbacks */
820     W11AddEventHandler(r->Xdisplay, xvt_W11_process_x_event);
821 #endif
822 
823 /* get number of available file descriptors */
824 #if defined(_POSIX_VERSION) || ! defined(__svr4__)
825     r->num_fds = (int)sysconf(_SC_OPEN_MAX);
826 #else
827     r->num_fds = xvt_getdtablesize();
828 #endif
829 
830 #ifdef META8_OPTION
831     r->h->meta_char = (r->Options & Opt_meta8 ? 0x80 : C0_ESC);
832 #endif
833     xvt_get_ourmods(r);
834     if (!(r->Options & Opt_scrollTtyOutput))
835 	r->h->PrivateModes |= PrivMode_TtyOutputInh;
836     if (r->Options & Opt_scrollTtyKeypress)
837 	r->h->PrivateModes |= PrivMode_Keypress;
838     if (!(r->Options & Opt_jumpScroll))
839 	r->h->PrivateModes |= PrivMode_smoothScroll;
840 #ifndef NO_BACKSPACE_KEY
841     if (STRCMP(r->h->key_backspace, "DEC") == 0)
842 	r->h->PrivateModes |= PrivMode_HaveBackSpace;
843 #endif
844 /* add value for scrollBar */
845     if (scrollbar_visible(r)) {
846 	r->h->PrivateModes |= PrivMode_scrollBar;
847 	r->h->SavedModes |= PrivMode_scrollBar;
848     }
849     if (menubar_visible(r)) {
850 	r->h->PrivateModes |= PrivMode_menuBar;
851 	r->h->SavedModes |= PrivMode_menuBar;
852     }
853     greek_init();
854 
855     r->Xfd = XConnectionNumber(r->Xdisplay);
856 
857     if ((r->cmd_fd = xvt_run_command(r, argv)) < 0) {
858 	xvt_print_error("aborting");
859 	exit(EXIT_FAILURE);
860     }
861 }
862 
863 /*----------------------------------------------------------------------*/
864 /* INTPROTO */
865 void
xvt_Get_Colours(xvt_t * r)866 xvt_Get_Colours(xvt_t *r)
867 {
868     int             i;
869 
870     for (i = 0; i < (XDEPTH <= 2 ? 2 : NRS_COLORS); i++) {
871 	XColor          xcol;
872 
873 	if (!r->h->rs[Rs_color + i])
874 	    continue;
875 
876 	if (!xvt_rXParseAllocColor(r, &xcol, r->h->rs[Rs_color + i])) {
877 #ifndef XTERM_REVERSE_VIDEO
878 	    if (i < 2 && (r->Options & Opt_reverseVideo)) {
879 		r->h->rs[Rs_color + i] = def_colorName[!i];
880 	    } else
881 #endif
882 		r->h->rs[Rs_color + i] = def_colorName[i];
883 	    if (!r->h->rs[Rs_color + i])
884 		continue;
885 	    if (!xvt_rXParseAllocColor(r, &xcol, r->h->rs[Rs_color + i])) {
886 		switch (i) {
887 		case Color_fg:
888 		case Color_bg:
889 		    /* fatal: need bg/fg color */
890 		    xvt_print_error("aborting");
891 		    exit(EXIT_FAILURE);
892 		/* NOTREACHED */
893 		    break;
894 #ifndef NO_CURSORCOLOR
895 		case Color_cursor2:
896 		    xcol.pixel = r->PixColors[Color_fg];
897 		    break;
898 #endif				/* ! NO_CURSORCOLOR */
899 		case Color_pointer:
900 		    xcol.pixel = r->PixColors[Color_fg];
901 		    break;
902 		default:
903 		    xcol.pixel = r->PixColors[Color_bg];	/* None */
904 		    break;
905 		}
906 	    }
907 	}
908 	r->PixColors[i] = xcol.pixel;
909 	SET_PIXCOLOR(r->h, i);
910     }
911 
912     if (XDEPTH <= 2 || !r->h->rs[Rs_color + Color_pointer])
913 	r->PixColors[Color_pointer] = r->PixColors[Color_fg];
914     if (XDEPTH <= 2 || !r->h->rs[Rs_color + Color_border])
915 	r->PixColors[Color_border] = r->PixColors[Color_fg];
916 
917 /*
918  * get scrollBar/menuBar shadow colors
919  *
920  * The calculations of topShadow/bottomShadow values are adapted
921  * from the fvwm window manager.
922  */
923 #ifdef KEEP_SCROLLCOLOR
924     if (XDEPTH <= 2) {	/* Monochrome */
925 	r->PixColors[Color_scroll] = r->PixColors[Color_fg];
926 	r->PixColors[Color_topShadow] = r->PixColors[Color_bg];
927 	r->PixColors[Color_bottomShadow] = r->PixColors[Color_bg];
928     } else {
929 	XColor           xcol[3];
930 	/* xcol[0] == white
931 	 * xcol[1] == top shadow
932 	 * xcol[2] == bot shadow */
933 
934 	xcol[1].pixel = r->PixColors[Color_scroll];
935 # ifdef PREFER_24BIT
936 	xcol[0].red = xcol[0].green = xcol[0].blue = (unsigned short)~0;
937 	xvt_rXAllocColor(r, &(xcol[0]), "White");
938 /*        XFreeColors(r->Xdisplay, XCMAP, &(xcol[0].pixel), 1, ~0); */
939 	XQueryColors(r->Xdisplay, XCMAP, &(xcol[1]), 1);
940 # else
941 	xcol[0].pixel = WhitePixel(r->Xdisplay, Xscreen);
942 	XQueryColors(r->Xdisplay, XCMAP, xcol, 2);
943 # endif
944 
945 	/* bottomShadowColor */
946 	xcol[2].red = xcol[1].red / 2;
947 	xcol[2].green = xcol[1].green / 2;
948 	xcol[2].blue = xcol[1].blue / 2;
949 	if (!xvt_rXAllocColor(r, &(xcol[2]), "Color_bottomShadow"))
950 	    xcol[2].pixel = r->PixColors[Color_Black];
951 	r->PixColors[Color_bottomShadow] = xcol[2].pixel;
952 
953 	/* topShadowColor */
954 	xcol[1].red = max((xcol[0].red / 5), xcol[1].red);
955 	xcol[1].green = max((xcol[0].green / 5), xcol[1].green);
956 	xcol[1].blue = max((xcol[0].blue / 5), xcol[1].blue);
957 	xcol[1].red = min(xcol[0].red, (xcol[1].red * 7) / 5);
958 	xcol[1].green = min(xcol[0].green, (xcol[1].green * 7) / 5);
959 	xcol[1].blue = min(xcol[0].blue, (xcol[1].blue * 7) / 5);
960 
961 	if (!xvt_rXAllocColor(r, &(xcol[1]), "Color_topShadow"))
962 	    xcol[1].pixel = r->PixColors[Color_White];
963 	r->PixColors[Color_topShadow] = xcol[1].pixel;
964     }
965 #endif				/* KEEP_SCROLLCOLOR */
966 }
967 
968 /*----------------------------------------------------------------------*/
969 /* color aliases, fg/bg bright-bold */
970 /* INTPROTO */
971 void
xvt_color_aliases(xvt_t * r,int idx)972 xvt_color_aliases(xvt_t *r, int idx)
973 {
974     if (r->h->rs[Rs_color + idx] && isdigit(*(r->h->rs[Rs_color + idx]))) {
975 	int             i = atoi(r->h->rs[Rs_color + idx]);
976 
977 	if (i >= 8 && i <= 15) {	/* bright colors */
978 	    i -= 8;
979 #ifndef NO_BRIGHTCOLOR
980 	    r->h->rs[Rs_color + idx] = r->h->rs[Rs_color + minBrightCOLOR + i];
981 	    return;
982 #endif
983 	}
984 	if (i >= 0 && i <= 7)	/* normal colors */
985 	    r->h->rs[Rs_color + idx] = r->h->rs[Rs_color + minCOLOR + i];
986     }
987 }
988 
989 /*----------------------------------------------------------------------*/
990 /*
991  * Probe the modifier keymap to get the Meta (Alt) and Num_Lock settings
992  * Use resource ``modifier'' to override the Meta modifier
993  */
994 /* INTPROTO */
995 void
xvt_get_ourmods(xvt_t * r)996 xvt_get_ourmods(xvt_t *r)
997 {
998     int             i, j, k;
999     int             requestedmeta, realmeta, realalt;
1000     const char     *cm, *rsmod;
1001     XModifierKeymap *map;
1002     KeyCode        *kc;
1003     const unsigned int modmasks[] =
1004 	{ Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
1005 
1006     requestedmeta = realmeta = realalt = 0;
1007     rsmod = r->h->rs[Rs_modifier];
1008     if (rsmod
1009 	&& STRCASECMP(rsmod, "mod1") >= 0 && STRCASECMP(rsmod, "mod5") <= 0)
1010 	requestedmeta = rsmod[3] - '0';
1011 
1012     map = XGetModifierMapping(r->Xdisplay);
1013     kc = map->modifiermap;
1014     for (i = 1; i < 6; i++) {
1015 	k = (i + 2) * map->max_keypermod;	/* skip shift/lock/control */
1016 	for (j = map->max_keypermod; j--; k++) {
1017 	    if (kc[k] == 0)
1018 		break;
1019 	    switch (XKeycodeToKeysym(r->Xdisplay, kc[k], 0)) {
1020 	    case XK_Num_Lock:
1021 		r->h->ModNumLockMask = modmasks[i - 1];
1022 		/* FALLTHROUGH */
1023 	    default:
1024 		continue;	/* for(;;) */
1025 	    case XK_Meta_L:
1026 	    case XK_Meta_R:
1027 		cm = "meta";
1028 		realmeta = i;
1029 		break;
1030 	    case XK_Alt_L:
1031 	    case XK_Alt_R:
1032 		cm = "alt";
1033 		realalt = i;
1034 		break;
1035 	    case XK_Super_L:
1036 	    case XK_Super_R:
1037 		cm = "super";
1038 		break;
1039 	    case XK_Hyper_L:
1040 	    case XK_Hyper_R:
1041 		cm = "hyper";
1042 		break;
1043 	    }
1044 	    if (rsmod && STRNCASECMP(rsmod, cm, STRLEN(cm)) == 0)
1045 		requestedmeta = i;
1046 	}
1047     }
1048     XFreeModifiermap(map);
1049     i = (requestedmeta ? requestedmeta
1050 		       : (realmeta ? realmeta
1051 				   : (realalt ? realalt : 0)));
1052     if (i)
1053 	r->h->ModMetaMask = modmasks[i - 1];
1054 }
1055 
1056 /*----------------------------------------------------------------------*/
1057 /* xvt_Create_Windows() - Open and map the window */
1058 /* EXTPROTO */
1059 void
xvt_Create_Windows(xvt_t * r,int argc,const char * const * argv)1060 xvt_Create_Windows(xvt_t *r, int argc, const char *const *argv)
1061 {
1062     XClassHint      classHint;
1063     XWMHints        wmHint;
1064     XGCValues       gcvalue;
1065 
1066 #ifdef PREFER_24BIT
1067     XSetWindowAttributes attributes;
1068     XWindowAttributes gattr;
1069 
1070     XCMAP = DefaultColormap(r->Xdisplay, Xscreen);
1071     XVISUAL = DefaultVisual(r->Xdisplay, Xscreen);
1072 
1073     if (r->Options & Opt_transparent) {
1074 	XGetWindowAttributes(r->Xdisplay, RootWindow(r->Xdisplay, Xscreen),
1075 			     &gattr);
1076 	XDEPTH = gattr.depth;
1077     } else {
1078 	XDEPTH = DefaultDepth(r->Xdisplay, Xscreen);
1079 /*
1080  * If depth is not 24, look for a 24bit visual.
1081  */
1082 	if (XDEPTH != 24) {
1083 	    XVisualInfo     vinfo;
1084 
1085 	    if (XMatchVisualInfo(r->Xdisplay, Xscreen, 24, TrueColor, &vinfo)) {
1086 		XDEPTH = 24;
1087 		XVISUAL = vinfo.visual;
1088 		XCMAP = XCreateColormap(r->Xdisplay,
1089 					RootWindow(r->Xdisplay, Xscreen),
1090 					XVISUAL, AllocNone);
1091 	    }
1092 	}
1093     }
1094 #endif
1095 
1096 /* grab colors before netscape does */
1097     xvt_Get_Colours(r);
1098 
1099     xvt_change_font(r, 1, NULL);
1100     xvt_window_calc(r, 0, 0);
1101     r->h->old_width = r->szHint.width;
1102     r->h->old_height = r->szHint.height;
1103 
1104 /* parent window - reverse video so we can see placement errors
1105  * sub-window placement & size in xvt_resize_subwindows()
1106  */
1107 
1108 #ifdef PREFER_24BIT
1109     attributes.background_pixel = r->PixColors[Color_fg];
1110     attributes.border_pixel = r->PixColors[Color_border];
1111     attributes.colormap = XCMAP;
1112     r->TermWin.parent[0] = XCreateWindow(r->Xdisplay, Xroot,
1113 					 r->szHint.x, r->szHint.y,
1114 					 r->szHint.width, r->szHint.height,
1115 					 r->TermWin.ext_bwidth,
1116 					 XDEPTH, InputOutput,
1117 					 XVISUAL,
1118 					 CWBackPixel | CWBorderPixel
1119 					 | CWColormap, &attributes);
1120 #else
1121     r->TermWin.parent[0] = XCreateSimpleWindow(r->Xdisplay, Xroot,
1122 					       r->szHint.x, r->szHint.y,
1123 					       r->szHint.width,
1124 					       r->szHint.height,
1125 					       r->TermWin.ext_bwidth,
1126 					       r->PixColors[Color_border],
1127 					       r->PixColors[Color_fg]);
1128 #endif
1129     xvt_xterm_seq(r, XTerm_title, r->h->rs[Rs_title], CHAR_ST);
1130     xvt_xterm_seq(r, XTerm_iconName, r->h->rs[Rs_iconName], CHAR_ST);
1131 
1132     classHint.res_name = (char *)r->h->rs[Rs_name];
1133     classHint.res_class = (char *)APL_CLASS;
1134 
1135     wmHint.flags = (InputHint | StateHint | WindowGroupHint);
1136     wmHint.input = True;
1137     wmHint.initial_state = (r->Options & Opt_iconic ? IconicState
1138 						    : NormalState);
1139     wmHint.window_group = r->TermWin.parent[0];
1140 
1141     XSetWMProperties(r->Xdisplay, r->TermWin.parent[0], NULL, NULL,
1142 		     (char **)argv, argc, &r->szHint, &wmHint, &classHint);
1143     XSelectInput(r->Xdisplay, r->TermWin.parent[0],
1144 		 (KeyPressMask
1145 #if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
1146 		  | KeyReleaseMask
1147 #endif
1148 		  | FocusChangeMask | VisibilityChangeMask
1149 		  | StructureNotifyMask));
1150 
1151 /* vt cursor: Black-on-White is standard, but this is more popular */
1152     r->TermWin_cursor = XCreateFontCursor(r->Xdisplay, XC_xterm);
1153     xvt_recolour_cursor(r);
1154 
1155 #if defined(HAVE_SCROLLBARS) || defined(MENUBAR)
1156 /* cursor (menuBar/scrollBar): Black-on-White */
1157     r->h->cursor_leftptr = XCreateFontCursor(r->Xdisplay, XC_left_ptr);
1158 #endif
1159 
1160 /* the vt window */
1161     r->TermWin.vt = XCreateSimpleWindow(r->Xdisplay, r->TermWin.parent[0],
1162 					r->h->window_vt_x, r->h->window_vt_y,
1163 					TermWin_TotalWidth(),
1164 					TermWin_TotalHeight(),
1165 					0,
1166 					r->PixColors[Color_fg],
1167 					r->PixColors[Color_bg]);
1168 #ifdef DEBUG_X
1169     XStoreName(r->Xdisplay, r->TermWin.vt, "vt window");
1170 #endif
1171     XDefineCursor(r->Xdisplay, r->TermWin.vt, r->TermWin_cursor);
1172     XSelectInput(r->Xdisplay, r->TermWin.vt,
1173 		 (ExposureMask | ButtonPressMask | ButtonReleaseMask
1174 		  | PropertyChangeMask
1175 		  | Button1MotionMask | Button3MotionMask));
1176 
1177 #if defined(MENUBAR) && (MENUBAR_MAX > 1)
1178     if (menuBar_height()) {
1179 	r->menuBar.win = XCreateSimpleWindow(r->Xdisplay, r->TermWin.parent[0],
1180 					     r->h->window_vt_x, 0,
1181 					     TermWin_TotalWidth(),
1182 					     menuBar_TotalHeight(),
1183 					     0,
1184 					     r->PixColors[Color_fg],
1185 					     r->PixColors[Color_scroll]);
1186 #ifdef DEBUG_X
1187     XStoreName(r->Xdisplay, r->menuBar.win, "menubar");
1188 #endif
1189 	XDefineCursor(r->Xdisplay, r->menuBar.win, r->h->cursor_leftptr);
1190 	XSelectInput(r->Xdisplay, r->menuBar.win,
1191 		     (ExposureMask | ButtonPressMask | ButtonReleaseMask
1192 		      | Button1MotionMask));
1193     }
1194 #endif
1195 #ifdef XPM_BACKGROUND
1196     if (r->h->rs[Rs_backgroundPixmap] != NULL
1197 	&& !(r->Options & Opt_transparent)) {
1198 	const char     *p = r->h->rs[Rs_backgroundPixmap];
1199 
1200 	if ((p = STRCHR(p, ';')) != NULL) {
1201 	    p++;
1202 	    xvt_scale_pixmap(r, p);
1203 	}
1204 	xvt_set_bgPixmap(r, r->h->rs[Rs_backgroundPixmap]);
1205 	xvt_scr_touch(r, True);
1206     }
1207 #endif
1208 
1209 /* graphics context for the vt window */
1210     gcvalue.font = r->TermWin.font->fid;
1211     gcvalue.foreground = r->PixColors[Color_fg];
1212     gcvalue.background = r->PixColors[Color_bg];
1213     gcvalue.graphics_exposures = 1;
1214     r->TermWin.gc = XCreateGC(r->Xdisplay, r->TermWin.vt,
1215 			      GCForeground | GCBackground
1216 			      | GCFont | GCGraphicsExposures, &gcvalue);
1217 
1218 #if defined(MENUBAR) || defined(XVT_SCROLLBAR)
1219     gcvalue.foreground = r->PixColors[Color_topShadow];
1220     r->h->topShadowGC = XCreateGC(r->Xdisplay, r->TermWin.vt,
1221 				  GCForeground, &gcvalue);
1222     gcvalue.foreground = r->PixColors[Color_bottomShadow];
1223     r->h->botShadowGC = XCreateGC(r->Xdisplay, r->TermWin.vt,
1224 				  GCForeground, &gcvalue);
1225     gcvalue.foreground = r->PixColors[(XDEPTH <= 2 ? Color_fg
1226 						   : Color_scroll)];
1227     r->h->scrollbarGC = XCreateGC(r->Xdisplay, r->TermWin.vt,
1228 				  GCForeground, &gcvalue);
1229 #endif
1230 }
1231 
1232 /*----------------------------------------------------------------------*/
1233 /*
1234  * Run the command in a subprocess and return a file descriptor for the
1235  * master end of the pseudo-teletype pair with the command talking to
1236  * the slave.
1237  */
1238 /* INTPROTO */
1239 int
xvt_run_command(xvt_t * r,const char * const * argv)1240 xvt_run_command(xvt_t *r, const char *const *argv)
1241 {
1242     int             i, cfd;
1243 
1244 /*
1245  * Close all unused file descriptors
1246  * We don't want them, we don't need them.
1247  */
1248     if ((i = open("/dev/null", O_RDONLY)) < 0) {
1249 	/* TODO: BOO HISS */
1250 	dup2(STDERR_FILENO, STDIN_FILENO);
1251     } else if (i > STDIN_FILENO) {
1252 	dup2(i, STDIN_FILENO);
1253 	close(i);
1254     }
1255     dup2(STDERR_FILENO, STDOUT_FILENO);
1256     for (i = STDERR_FILENO + 1; i < r->num_fds; i++) {
1257 	if (
1258 #ifdef __sgi			/* Alex Coventry says we need 4 & 7 too */
1259 	    i == 4 || i == 7 ||
1260 #endif
1261 	    i == r->Xfd)
1262 	    continue;
1263 	close(i);
1264     }
1265     if ((r->Xfd < STDERR_FILENO + 1
1266 #ifdef FD_SETSIZE
1267 	 || r->Xfd > FD_SETSIZE
1268 #endif
1269         ) && dup2(r->Xfd, STDERR_FILENO + 1) != -1) {
1270 	close(r->Xfd);
1271 	r->Xfd = STDERR_FILENO + 1;
1272     }
1273 
1274 /* get master (pty) */
1275     if ((cfd = xvt_get_pty(&(r->tty_fd), &(r->h->ttydev))) < 0) {
1276 	xvt_print_error("can't open pseudo-tty");
1277 	return -1;
1278     }
1279 #ifdef FD_SETSIZE
1280     if (r->Xfd > FD_SETSIZE || cfd > FD_SETSIZE) {
1281 	xvt_print_error("fd too high: %d max", FD_SETSIZE);
1282 	xvt_clean_exit();
1283 	exit(EXIT_FAILURE);
1284     }
1285 #endif
1286     fcntl(cfd, F_SETFL, O_NDELAY);
1287 
1288 /* get slave (tty) */
1289     if (r->tty_fd < 0) {
1290 	xvt_privileged_ttydev(r, SAVE);
1291 	if ((r->tty_fd = xvt_get_tty(r->h->ttydev)) < 0) {
1292 	    close(cfd);
1293 	    xvt_print_error("can't open slave tty %s", r->h->ttydev);
1294 	    return -1;
1295 	}
1296     }
1297     xvt_get_ttymode(&(r->h->tio));
1298 
1299 /* install exit handler for cleanup */
1300 #ifdef HAVE_ATEXIT
1301     atexit(xvt_clean_exit);
1302 #else
1303 # ifdef HAVE_ON_EXIT
1304     on_exit(xvt_clean_exit, NULL);	/* non-ANSI exit handler */
1305 # endif
1306 #endif
1307 
1308     signal(SIGHUP, xvt_Exit_signal);
1309 #ifndef __svr4__
1310     signal(SIGINT, xvt_Exit_signal);
1311 #endif
1312     signal(SIGQUIT, xvt_Exit_signal);
1313     signal(SIGTERM, xvt_Exit_signal);
1314     signal(SIGCHLD, xvt_Child_signal);
1315 
1316 /* need to trap SIGURG for SVR4 (Unixware) rlogin */
1317 /* signal (SIGURG, SIG_DFL); */
1318 
1319 #ifndef __QNX__
1320 /* spin off the command interpreter */
1321     switch (r->h->cmd_pid = fork()) {
1322     case -1:
1323 	xvt_print_error("can't fork");
1324 	return -1;
1325     case 0:
1326 	close(cfd);		/* only keep r->tty_fd and STDERR open */
1327 	close(r->Xfd);
1328 #ifdef __QNX__
1329 	xvt_run_child(r, argv);
1330 #else
1331 	if (xvt_control_tty(r->tty_fd, r->h->ttydev) < 0)
1332 	    xvt_print_error("could not obtain control of tty");
1333 	else {
1334 	/* Reopen stdin, stdout and stderr over the tty file descriptor */
1335 	    dup2(r->tty_fd, STDIN_FILENO);
1336 	    dup2(r->tty_fd, STDOUT_FILENO);
1337 	    dup2(r->tty_fd, STDERR_FILENO);
1338 	    if (r->tty_fd > 2)
1339 		close(r->tty_fd);
1340 	    xvt_run_child(r, argv);
1341 	}
1342 #endif
1343 	exit(EXIT_FAILURE);
1344 	/* NOTREACHED */
1345     default:
1346 	close(r->tty_fd);	/* keep STDERR_FILENO, r->cmd_fd, r->Xfd open */
1347 	break;
1348     }
1349 #else				/* __QNX__ uses qnxspawn() */
1350     fchmod(r->tty_fd, 0622);
1351     fcntl(r->tty_fd, F_SETFD, FD_CLOEXEC);
1352     fcntl(cfd, F_SETFD, FD_CLOEXEC);
1353 
1354     if (xvt_run_child(r, argv) == -1)
1355 	exit(EXIT_FAILURE);
1356 #endif
1357 /*
1358  * Reduce r->num_fds to what we use, so select() is more efficient
1359  */
1360     r->num_fds = max(STDERR_FILENO, cfd);
1361     MAX_IT(r->num_fds, r->Xfd);
1362 #ifdef __sgi			/* Alex Coventry says we need 4 & 7 too */
1363     MAX_IT(r->num_fds, 7);
1364 #endif
1365     r->num_fds++;		/* counts from 0 */
1366 
1367     xvt_privileged_utmp(r, SAVE);
1368     return cfd;
1369 }
1370 
1371 /* ------------------------------------------------------------------------- *
1372  *                          CHILD PROCESS OPERATIONS                         *
1373  * ------------------------------------------------------------------------- */
1374 /*
1375  * The only open file descriptor is the slave tty - so no error messages.
1376  * returns are fatal
1377  */
1378 /* INTPROTO */
1379 int
xvt_run_child(xvt_t * r,const char * const * argv)1380 xvt_run_child(xvt_t *r, const char *const *argv)
1381 {
1382     char           *login;
1383 
1384     SET_TTYMODE(STDIN_FILENO, &(r->h->tio));	/* init terminal attributes */
1385 
1386     if (r->Options & Opt_console) {	/* be virtual console, fail silently */
1387 #ifdef TIOCCONS
1388 	unsigned int    on = 1;
1389 
1390 	ioctl(STDIN_FILENO, TIOCCONS, &on);
1391 #elif defined (SRIOCSREDIR)
1392 	int             fd;
1393 
1394 	fd = open(CONSOLE, O_WRONLY, 0);
1395 	if (fd >= 0) {
1396 	    if (ioctl(fd, SRIOCSREDIR, NULL) < 0)
1397 		close(fd);
1398 	}
1399 #endif				/* SRIOCSREDIR */
1400     }
1401 
1402     /* set window size */
1403     xvt_tt_winsize(STDIN_FILENO, r->TermWin.ncol, r->TermWin.nrow);
1404 
1405 /* reset signals and spin off the command interpreter */
1406     signal(SIGINT, SIG_DFL);
1407     signal(SIGQUIT, SIG_DFL);
1408     signal(SIGCHLD, SIG_DFL);
1409 /*
1410  * mimick login's behavior by disabling the job control signals
1411  * a shell that wants them can turn them back on
1412  */
1413 #ifdef SIGTSTP
1414     signal(SIGTSTP, SIG_IGN);
1415     signal(SIGTTIN, SIG_IGN);
1416     signal(SIGTTOU, SIG_IGN);
1417 #endif				/* SIGTSTP */
1418 
1419 #ifndef __QNX__
1420 /* command interpreter path */
1421     if (argv != NULL) {
1422 # ifdef DEBUG_CMD
1423 	int             i;
1424 
1425 	for (i = 0; argv[i]; i++)
1426 	    fprintf(stderr, "argv [%d] = \"%s\"\n", i, argv[i]);
1427 # endif
1428 	execvp(argv[0], (char *const *)argv);
1429 	/* no error message: STDERR is closed! */
1430     } else {
1431 	const char     *argv0, *shell;
1432 
1433 	if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
1434 	    shell = "/bin/sh";
1435 
1436 	argv0 = (const char *)xvt_r_basename(shell);
1437 	if (r->Options & Opt_loginShell) {
1438 	    login = xvt_malloc((STRLEN(argv0) + 2) * sizeof(char));
1439 
1440 	    login[0] = '-';
1441 	    STRCPY(&login[1], argv0);
1442 	    argv0 = login;
1443 	}
1444 	execlp(shell, argv0, NULL);
1445 	/* no error message: STDERR is closed! */
1446     }
1447 #else				/* __QNX__ uses qnxspawn() */
1448     {
1449 	char            iov_a[10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
1450 	char           *command = NULL, fullcommand[_MAX_PATH];
1451 	char          **arg_v, *arg_a[2] = { NULL, NULL };
1452 
1453 	if (argv != NULL) {
1454 	    if (access(argv[0], X_OK) == -1) {
1455 		if (STRCHR(argv[0], '/') == NULL) {
1456 		    searchenv(argv[0], "PATH", fullcommand);
1457 		    if (fullcommand[0] != '\0')
1458 			command = fullcommand;
1459 		}
1460 		if (access(command, X_OK) == -1)
1461 		    return -1;
1462 	    } else
1463 		command = argv[0];
1464 	    arg_v = argv;
1465 	} else {
1466 	    if ((command = getenv("SHELL")) == NULL || *command == '\0')
1467 		command = "/bin/sh";
1468 
1469 	    arg_a[0] = my_basename(command);
1470 	    if (r->Options & Opt_loginShell) {
1471 		login = xvt_malloc((STRLEN(arg_a[0]) + 2) * sizeof(char));
1472 
1473 		login[0] = '-';
1474 		STRCPY(&login[1], arg_a[0]);
1475 		arg_a[0] = login;
1476 	    }
1477 	    arg_v = arg_a;
1478 	}
1479 	iov_a[0] = iov_a[1] = iov_a[2] = r->tty_fd;
1480 	r->h->cmd_pid = qnx_spawn(0, 0, 0, -1, -1,
1481 				  _SPAWN_SETSID | _SPAWN_TCSETPGRP,
1482 				  command, arg_v, environ, iov_a, 0);
1483 	if (login)
1484 	    free(login);
1485 	close(r->tty_fd);
1486 	return r->cmd_fd;
1487     }
1488 #endif
1489     return -1;
1490 }
1491 
1492 /* ------------------------------------------------------------------------- *
1493  *                            GET TTY CURRENT STATE                          *
1494  * ------------------------------------------------------------------------- */
1495 /* xvt_get_ttymode() */
1496 /* INTPROTO */
1497 void
xvt_get_ttymode(ttymode_t * tio)1498 xvt_get_ttymode(ttymode_t *tio)
1499 {
1500 #ifdef HAVE_TERMIOS_H
1501 /*
1502  * standard System V termios interface
1503  */
1504     if (GET_TERMIOS(STDIN_FILENO, tio) < 0) {
1505 	/* return error - use system defaults */
1506 	tio->c_cc[VINTR] = CINTR;
1507 	tio->c_cc[VQUIT] = CQUIT;
1508 	tio->c_cc[VERASE] = CERASE;
1509 	tio->c_cc[VKILL] = CKILL;
1510 	tio->c_cc[VSTART] = CSTART;
1511 	tio->c_cc[VSTOP] = CSTOP;
1512 	tio->c_cc[VSUSP] = CSUSP;
1513 # ifdef VDSUSP
1514 	tio->c_cc[VDSUSP] = CDSUSP;
1515 # endif
1516 # ifdef VREPRINT
1517 	tio->c_cc[VREPRINT] = CRPRNT;
1518 # endif
1519 # ifdef VDISCRD
1520 	tio->c_cc[VDISCRD] = CFLUSH;
1521 # endif
1522 # ifdef VWERSE
1523 	tio->c_cc[VWERSE] = CWERASE;
1524 # endif
1525 # ifdef VLNEXT
1526 	tio->c_cc[VLNEXT] = CLNEXT;
1527 # endif
1528     }
1529     tio->c_cc[VEOF] = CEOF;
1530     tio->c_cc[VEOL] = VDISABLE;
1531 # ifdef VEOL2
1532     tio->c_cc[VEOL2] = VDISABLE;
1533 # endif
1534 # ifdef VERASE2
1535     tio->c_cc[VERASE2] = CERASE2;
1536 # endif
1537 # ifdef VSWTC
1538     tio->c_cc[VSWTC] = VDISABLE;
1539 # endif
1540 # ifdef VSWTCH
1541     tio->c_cc[VSWTCH] = VDISABLE;
1542 # endif
1543 # if VMIN != VEOF
1544     tio->c_cc[VMIN] = 1;
1545 # endif
1546 # if VTIME != VEOL
1547     tio->c_cc[VTIME] = 0;
1548 # endif
1549 
1550 /* input modes */
1551     tio->c_iflag = (BRKINT | IGNPAR | ICRNL
1552 # ifdef IMAXBEL
1553 		    | IMAXBEL
1554 # endif
1555 	            | IXON);
1556 
1557 /* output modes */
1558     tio->c_oflag = (OPOST | ONLCR);
1559 
1560 /* control modes */
1561     tio->c_cflag = (CS8 | CREAD);
1562 
1563 /* line discipline modes */
1564     tio->c_lflag = (ISIG | ICANON | IEXTEN | ECHO
1565 # if defined (ECHOCTL) && defined (ECHOKE)
1566 		    | ECHOCTL | ECHOKE
1567 # endif
1568 	            | ECHOE | ECHOK);
1569 # else				/* HAVE_TERMIOS_H */
1570 
1571 /*
1572  * sgtty interface
1573  */
1574 
1575 /* get parameters -- gtty */
1576     if (ioctl(STDIN_FILENO, TIOCGETP, &(tio->sg)) < 0) {
1577 	tio->sg.sg_erase = CERASE;	/* ^H */
1578 	tio->sg.sg_kill = CKILL;	/* ^U */
1579     }
1580     tio->sg.sg_flags = (CRMOD | ECHO | EVENP | ODDP);
1581 
1582 /* get special characters */
1583     if (ioctl(STDIN_FILENO, TIOCGETC, &(tio->tc)) < 0) {
1584 	tio->tc.t_intrc = CINTR;	/* ^C */
1585 	tio->tc.t_quitc = CQUIT;	/* ^\ */
1586 	tio->tc.t_startc = CSTART;	/* ^Q */
1587 	tio->tc.t_stopc = CSTOP;	/* ^S */
1588 	tio->tc.t_eofc = CEOF;	/* ^D */
1589 	tio->tc.t_brkc = -1;
1590     }
1591 /* get local special chars */
1592     if (ioctl(STDIN_FILENO, TIOCGLTC, &(tio->lc)) < 0) {
1593 	tio->lc.t_suspc = CSUSP;	/* ^Z */
1594 	tio->lc.t_dsuspc = CDSUSP;	/* ^Y */
1595 	tio->lc.t_rprntc = CRPRNT;	/* ^R */
1596 	tio->lc.t_flushc = CFLUSH;	/* ^O */
1597 	tio->lc.t_werasc = CWERASE;	/* ^W */
1598 	tio->lc.t_lnextc = CLNEXT;	/* ^V */
1599     }
1600 /* get line discipline */
1601     ioctl(STDIN_FILENO, TIOCGETD, &(tio->line));
1602 # ifdef NTTYDISC
1603     tio->line = NTTYDISC;
1604 # endif				/* NTTYDISC */
1605     tio->local = (LCRTBS | LCRTERA | LCTLECH | LPASS8 | LCRTKIL);
1606 #endif				/* HAVE_TERMIOS_H */
1607 
1608 /*
1609  * Debugging
1610  */
1611 #ifdef DEBUG_TTYMODE
1612 #ifdef HAVE_TERMIOS_H
1613 /* c_iflag bits */
1614     fprintf(stderr, "Input flags\n");
1615 
1616 /* cpp token stringize doesn't work on all machines <sigh> */
1617 # define FOO(flag,name)			\
1618     if ((tio->c_iflag) & flag)		\
1619 	fprintf (stderr, "%s ", name)
1620 
1621 /* c_iflag bits */
1622     FOO(IGNBRK, "IGNBRK");
1623     FOO(BRKINT, "BRKINT");
1624     FOO(IGNPAR, "IGNPAR");
1625     FOO(PARMRK, "PARMRK");
1626     FOO(INPCK, "INPCK");
1627     FOO(ISTRIP, "ISTRIP");
1628     FOO(INLCR, "INLCR");
1629     FOO(IGNCR, "IGNCR");
1630     FOO(ICRNL, "ICRNL");
1631     FOO(IXON, "IXON");
1632     FOO(IXOFF, "IXOFF");
1633 # ifdef IUCLC
1634     FOO(IUCLC, "IUCLC");
1635 # endif
1636 # ifdef IXANY
1637     FOO(IXANY, "IXANY");
1638 # endif
1639 # ifdef IMAXBEL
1640     FOO(IMAXBEL, "IMAXBEL");
1641 # endif
1642     fprintf(stderr, "\n");
1643 
1644 # undef FOO
1645 # define FOO(entry, name)					\
1646     fprintf(stderr, "%-8s = %#04o\n", name, tio->c_cc [entry])
1647 
1648     FOO(VINTR, "VINTR");
1649     FOO(VQUIT, "VQUIT");
1650     FOO(VERASE, "VERASE");
1651     FOO(VKILL, "VKILL");
1652     FOO(VEOF, "VEOF");
1653     FOO(VEOL, "VEOL");
1654 # ifdef VEOL2
1655     FOO(VEOL2, "VEOL2");
1656 # endif
1657 # ifdef VERASE2
1658     FOO(VERASE2, "VERASE2");
1659 # endif
1660 # ifdef VSWTC
1661     FOO(VSWTC, "VSWTC");
1662 # endif
1663 # ifdef VSWTCH
1664     FOO(VSWTCH, "VSWTCH");
1665 # endif
1666     FOO(VSTART, "VSTART");
1667     FOO(VSTOP, "VSTOP");
1668     FOO(VSUSP, "VSUSP");
1669 # ifdef VDSUSP
1670     FOO(VDSUSP, "VDSUSP");
1671 # endif
1672 # ifdef VREPRINT
1673     FOO(VREPRINT, "VREPRINT");
1674 # endif
1675 # ifdef VDISCRD
1676     FOO(VDISCRD, "VDISCRD");
1677 # endif
1678 # ifdef VWERSE
1679     FOO(VWERSE, "VWERSE");
1680 # endif
1681 # ifdef VLNEXT
1682     FOO(VLNEXT, "VLNEXT");
1683 # endif
1684     fprintf(stderr, "\n");
1685 # undef FOO
1686 # endif				/* HAVE_TERMIOS_H */
1687 #endif				/* DEBUG_TTYMODE */
1688 }
1689 
1690 /*----------------------- end-of-file (C source) -----------------------*/
1691