ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/init.C
Revision: 1.184
Committed: Fri Jun 8 20:04:12 2007 UTC (16 years, 11 months ago) by sasha
Content type: text/plain
Branch: MAIN
Changes since 1.183: +4 -1 lines
Log Message:
added preliminary support to use libAfterImage for background pixmap loading and rendering of transparency effects including blending of pixmap over background using several methods, and gaussian blurr of the transparency background

File Contents

# Content
1 /*----------------------------------------------------------------------*
2 * File: init.C
3 *----------------------------------------------------------------------*
4 *
5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 1992 John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
7 * - original version
8 * Copyright (c) 1994 Robert Nation <nation@rocket.sanders.lockheed.com>
9 * - extensive modifications
10 * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
11 * - extensive modifications
12 * Copyright (c) 1999 D J Hawkey Jr <hawkeyd@visi.com>
13 * - QNX support
14 * Copyright (c) 2003-2006 Marc Lehmann <pcg@goof.com>
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 "rxvt.h" /* NECESSARY */
36 #include "rxvtutil.h"
37 #include "init.h"
38
39 #include <limits>
40
41 #include <csignal>
42
43 const char *const def_colorName[] =
44 {
45 COLOR_FOREGROUND,
46 COLOR_BACKGROUND,
47 /* low-intensity colors */
48 "rgb:00/00/00", // 0: black (Black)
49 "rgb:cd/00/00", // 1: red (Red3)
50 "rgb:00/cd/00", // 2: green (Green3)
51 "rgb:cd/cd/00", // 3: yellow (Yellow3)
52 "rgb:00/00/cd", // 4: blue (Blue3)
53 "rgb:cd/00/cd", // 5: magenta (Magenta3)
54 "rgb:00/cd/cd", // 6: cyan (Cyan3)
55 # ifdef XTERM_COLORS
56 "rgb:e5/e5/e5", // 7: white (Grey90)
57 # else
58 "rgb:fa/eb/d7", // 7: white (AntiqueWhite)
59 # endif
60 /* high-intensity colors */
61 # ifdef XTERM_COLORS
62 "rgb:4d/4d/4d", // 8: bright black (Grey30)
63 # else
64 "rgb:40/40/40", // 8: bright black (Grey25)
65 # endif
66 "rgb:ff/00/00", // 1/9: bright red (Reed)
67 "rgb:00/ff/00", // 2/10: bright green (Green)
68 "rgb:ff/ff/00", // 3/11: bright yellow (Yellow)
69 "rgb:00/00/ff", // 4/12: bright blue (Blue)
70 "rgb:ff/00/ff", // 5/13: bright magenta (Magenta)
71 "rgb:00/ff/ff", // 6/14: bright cyan (Cyan)
72 "rgb:ff/ff/ff", // 7/15: bright white (White)
73
74 // 88 xterm colours
75 "rgb:00/00/00",
76 "rgb:00/00/8b",
77 "rgb:00/00/cd",
78 "rgb:00/00/ff",
79 "rgb:00/8b/00",
80 "rgb:00/8b/8b",
81 "rgb:00/8b/cd",
82 "rgb:00/8b/ff",
83 "rgb:00/cd/00",
84 "rgb:00/cd/8b",
85 "rgb:00/cd/cd",
86 "rgb:00/cd/ff",
87 "rgb:00/ff/00",
88 "rgb:00/ff/8b",
89 "rgb:00/ff/cd",
90 "rgb:00/ff/ff",
91 "rgb:8b/00/00",
92 "rgb:8b/00/8b",
93 "rgb:8b/00/cd",
94 "rgb:8b/00/ff",
95 "rgb:8b/8b/00",
96 "rgb:8b/8b/8b",
97 "rgb:8b/8b/cd",
98 "rgb:8b/8b/ff",
99 "rgb:8b/cd/00",
100 "rgb:8b/cd/8b",
101 "rgb:8b/cd/cd",
102 "rgb:8b/cd/ff",
103 "rgb:8b/ff/00",
104 "rgb:8b/ff/8b",
105 "rgb:8b/ff/cd",
106 "rgb:8b/ff/ff",
107 "rgb:cd/00/00",
108 "rgb:cd/00/8b",
109 "rgb:cd/00/cd",
110 "rgb:cd/00/ff",
111 "rgb:cd/8b/00",
112 "rgb:cd/8b/8b",
113 "rgb:cd/8b/cd",
114 "rgb:cd/8b/ff",
115 "rgb:cd/cd/00",
116 "rgb:cd/cd/8b",
117 "rgb:cd/cd/cd",
118 "rgb:cd/cd/ff",
119 "rgb:cd/ff/00",
120 "rgb:cd/ff/8b",
121 "rgb:cd/ff/cd",
122 "rgb:cd/ff/ff",
123 "rgb:ff/00/00",
124 "rgb:ff/00/8b",
125 "rgb:ff/00/cd",
126 "rgb:ff/00/ff",
127 "rgb:ff/8b/00",
128 "rgb:ff/8b/8b",
129 "rgb:ff/8b/cd",
130 "rgb:ff/8b/ff",
131 "rgb:ff/cd/00",
132 "rgb:ff/cd/8b",
133 "rgb:ff/cd/cd",
134 "rgb:ff/cd/ff",
135 "rgb:ff/ff/00",
136 "rgb:ff/ff/8b",
137 "rgb:ff/ff/cd",
138 "rgb:ff/ff/ff",
139 "rgb:2e/2e/2e",
140 "rgb:5c/5c/5c",
141 "rgb:73/73/73",
142 "rgb:8b/8b/8b",
143 "rgb:a2/a2/a2",
144 "rgb:b9/b9/b9",
145 "rgb:d0/d0/d0",
146 "rgb:e7/e7/e7",
147
148 #ifndef NO_CURSORCOLOR
149 COLOR_CURSOR_BACKGROUND,
150 COLOR_CURSOR_FOREGROUND,
151 #endif /* ! NO_CURSORCOLOR */
152 NULL, /* Color_pointer_fg */
153 NULL, /* Color_pointer_bg */
154 NULL, /* Color_border */
155 #ifndef NO_BOLD_UNDERLINE_REVERSE
156 NULL, /* Color_BD */
157 NULL, /* Color_IT */
158 NULL, /* Color_UL */
159 NULL, /* Color_RV */
160 #endif /* ! NO_BOLD_UNDERLINE_REVERSE */
161 #if ENABLE_FRILLS
162 NULL, // Color_underline
163 #endif
164 #ifdef OPTION_HC
165 NULL,
166 #endif
167 #ifdef KEEP_SCROLLCOLOR
168 COLOR_SCROLLBAR,
169 COLOR_SCROLLTROUGH,
170 #endif /* KEEP_SCROLLCOLOR */
171 #if TINTING
172 NULL,
173 #endif
174 #if OFF_FOCUS_FADING
175 "rgb:00/00/00",
176 #endif
177 };
178
179 bool
180 rxvt_term::init_vars ()
181 {
182 pix_colors = //
183 pix_colors_focused = new rxvt_color [TOTAL_COLORS];
184 #ifdef OFF_FOCUS_FADING
185 pix_colors_unfocused = new rxvt_color [TOTAL_COLORS];
186 #endif
187
188 #if defined(XPM_BACKGROUND) || defined(TRANSPARENT)
189 pixmap = None;
190 #endif
191
192 MEvent.time = CurrentTime;
193 MEvent.button = AnyButton;
194 want_refresh = 1;
195 priv_modes = SavedModes = PrivMode_Default;
196 ncol = 80;
197 nrow = 24;
198 int_bwidth = INTERNALBORDERWIDTH;
199 ext_bwidth = EXTERNALBORDERWIDTH;
200 lineSpace = LINESPACE;
201 saveLines = SAVELINES;
202 numpix_colors = TOTAL_COLORS;
203
204 refresh_limit = 1;
205 refresh_type = SLOW_REFRESH;
206
207 oldcursor.row = oldcursor.col = -1;
208 #ifdef XPM_BACKGROUND
209 /* bgPixmap.w = bgPixmap.h = 0; */
210 bgPixmap.x = bgPixmap.y = 0;
211 bgPixmap.pixmap = None;
212 #endif
213
214 last_bot = last_state = -1;
215
216 set_option (Opt_scrollBar);
217 set_option (Opt_scrollTtyOutput);
218 set_option (Opt_jumpScroll);
219 set_option (Opt_secondaryScreen);
220 set_option (Opt_secondaryScroll);
221 set_option (Opt_pastableTabs);
222 set_option (Opt_intensityStyles);
223
224 return true;
225 }
226
227 void
228 rxvt_term::init_secondary ()
229 {
230 int i;
231
232 /*
233 * Close all unused file descriptors
234 * We don't want them, we don't need them.
235 */
236 if ((i = open ("/dev/null", O_RDONLY)) < 0)
237 {
238 /* TODO: BOO HISS */
239 dup2 (STDERR_FILENO, STDIN_FILENO);
240 }
241 else if (i > STDIN_FILENO)
242 {
243 dup2 (i, STDIN_FILENO);
244 close (i);
245 }
246
247 dup2 (STDERR_FILENO, STDOUT_FILENO);
248
249 #if 0 // schmorp sayz closing filies is murder
250 for (i = STDERR_FILENO + 1; i < num_fds; i++)
251 {
252 #ifdef __sgi /* Alex Coventry says we need 4 & 7 too */
253 if (i == 4 || i == 7)
254 continue;
255 #endif
256 close (i);
257 }
258 #endif
259 }
260
261 /*----------------------------------------------------------------------*/
262 const char **
263 rxvt_term::init_resources (int argc, const char *const *argv)
264 {
265 int i, r_argc;
266 char *val;
267 const char **cmd_argv, **r_argv;
268
269 /*
270 * Look for -e option. Find => split and make cmd_argv[] of command args
271 */
272 for (r_argc = 0; r_argc < argc; r_argc++)
273 if (!strcmp (argv[r_argc], "-e"))
274 break;
275
276 r_argv = (const char **)rxvt_malloc (sizeof (char *) * (r_argc + 1));
277
278 for (i = 0; i < r_argc; i++)
279 r_argv[i] = (const char *)argv[i];
280
281 r_argv[i] = NULL;
282
283 if (r_argc == argc)
284 cmd_argv = NULL;
285 else
286 {
287 cmd_argv = (const char **)rxvt_malloc (sizeof (char *) * (argc - r_argc));
288
289 for (i = 0; i < argc - r_argc - 1; i++)
290 cmd_argv[i] = (const char *)argv[i + r_argc + 1];
291
292 cmd_argv[i] = NULL;
293 }
294
295 rs[Rs_name] = rxvt_r_basename (argv[0]);
296
297 /*
298 * Open display, get options/resources and create the window
299 */
300
301 if ((rs[Rs_display_name] = getenv ("DISPLAY")) == NULL)
302 rs[Rs_display_name] = ":0";
303
304 get_options (r_argc, r_argv);
305
306 if (!(display = displays.get (rs[Rs_display_name])))
307 rxvt_fatal ("can't open display %s, aborting.\n", rs[Rs_display_name]);
308
309 // using a local pointer decreases code size a lot
310 xa = display->xa;
311
312 set (display);
313 extract_resources ();
314
315 #if XFT
316 if (rs[Rs_depth])
317 select_visual (strtol (rs[Rs_depth], 0, 0));
318 #endif
319
320 free (r_argv);
321
322 for (int i = NUM_RESOURCES; i--; )
323 if (rs [i] == resval_undef)
324 rs [i] = 0;
325
326 #if ENABLE_PERL
327 if (!rs[Rs_perl_ext_1])
328 rs[Rs_perl_ext_1] = "default";
329
330 if ((rs[Rs_perl_ext_1] && *rs[Rs_perl_ext_1])
331 || (rs[Rs_perl_ext_2] && *rs[Rs_perl_ext_2])
332 || (rs[Rs_perl_eval] && *rs[Rs_perl_eval]))
333 {
334 rxvt_perl.init (this);
335 HOOK_INVOKE ((this, HOOK_INIT, DT_END));
336 }
337 #endif
338
339 /*
340 * set any defaults not already set
341 */
342 if (cmd_argv && cmd_argv[0])
343 {
344 if (!rs[Rs_title])
345 rs[Rs_title] = rxvt_r_basename (cmd_argv[0]);
346 if (!rs[Rs_iconName])
347 rs[Rs_iconName] = rs[Rs_title];
348 }
349 else
350 {
351 if (!rs[Rs_title])
352 rs[Rs_title] = rs[Rs_name];
353 if (!rs[Rs_iconName])
354 rs[Rs_iconName] = rs[Rs_name];
355 }
356
357 if (rs[Rs_saveLines] && (i = atoi (rs[Rs_saveLines])) >= 0)
358 saveLines = min (i, MAX_SAVELINES);
359
360 #if ENABLE_FRILLS
361 if (rs[Rs_int_bwidth] && (i = atoi (rs[Rs_int_bwidth])) >= 0)
362 int_bwidth = min (i, std::numeric_limits<int16_t>::max ());
363
364 if (rs[Rs_ext_bwidth] && (i = atoi (rs[Rs_ext_bwidth])) >= 0)
365 ext_bwidth = min (i, std::numeric_limits<int16_t>::max ());
366
367 if (rs[Rs_lineSpace] && (i = atoi (rs[Rs_lineSpace])) >= 0)
368 lineSpace = min (i, std::numeric_limits<int16_t>::max ());
369 #endif
370
371 #ifdef POINTER_BLANK
372 if (rs[Rs_pointerBlankDelay] && (i = atoi (rs[Rs_pointerBlankDelay])) >= 0)
373 pointerBlankDelay = i;
374 else
375 pointerBlankDelay = 2;
376 #endif
377
378 /* no point having a scrollbar without having any scrollback! */
379 if (!saveLines)
380 set_option (Opt_scrollBar, 0);
381
382 #ifdef PRINTPIPE
383 if (!rs[Rs_print_pipe])
384 rs[Rs_print_pipe] = PRINTPIPE;
385 #endif
386
387 if (!rs[Rs_cutchars])
388 rs[Rs_cutchars] = CUTCHARS;
389
390 #ifndef NO_BACKSPACE_KEY
391 if (!rs[Rs_backspace_key])
392 # ifdef DEFAULT_BACKSPACE
393 key_backspace = DEFAULT_BACKSPACE;
394 # else
395 key_backspace = "DEC"; /* can toggle between \010 or \177 */
396 # endif
397 else
398 {
399 val = strdup (rs[Rs_backspace_key]);
400 rxvt_Str_trim (val);
401 rxvt_Str_escaped (val);
402 key_backspace = val;
403 }
404 #endif
405
406 #ifndef NO_DELETE_KEY
407 if (!rs[Rs_delete_key])
408 # ifdef DEFAULT_DELETE
409 key_delete = DEFAULT_DELETE;
410 # else
411 key_delete = "\033[3~";
412 # endif
413 else
414 {
415 val = strdup (rs[Rs_delete_key]);
416 rxvt_Str_trim (val);
417 rxvt_Str_escaped (val);
418 key_delete = val;
419 }
420 #endif
421 if (rs[Rs_answerbackstring])
422 {
423 rxvt_Str_trim ((char *)rs[Rs_answerbackstring]);
424 rxvt_Str_escaped ((char *)rs[Rs_answerbackstring]);
425 }
426
427 #ifdef HAVE_SCROLLBARS
428 setup_scrollbar (rs[Rs_scrollBar_align], rs[Rs_scrollstyle], rs[Rs_scrollBar_thickness]);
429 #endif
430
431 #ifdef XTERM_REVERSE_VIDEO
432 /* this is how xterm implements reverseVideo */
433 if (option (Opt_reverseVideo))
434 {
435 if (!rs[Rs_color + Color_fg])
436 rs[Rs_color + Color_fg] = def_colorName[Color_bg];
437
438 if (!rs[Rs_color + Color_bg])
439 rs[Rs_color + Color_bg] = def_colorName[Color_fg];
440 }
441 #endif
442
443 for (i = 0; i < NRS_COLORS; i++)
444 if (!rs[Rs_color + i])
445 rs[Rs_color + i] = def_colorName[i];
446
447 #ifndef XTERM_REVERSE_VIDEO
448 /* this is how we implement reverseVideo */
449 if (option (Opt_reverseVideo))
450 ::swap (rs[Rs_color + Color_fg], rs[Rs_color + Color_bg]);
451 #endif
452
453 /* convenient aliases for setting fg/bg to colors */
454 color_aliases (Color_fg);
455 color_aliases (Color_bg);
456 #ifndef NO_CURSORCOLOR
457 color_aliases (Color_cursor);
458 color_aliases (Color_cursor2);
459 #endif /* NO_CURSORCOLOR */
460 color_aliases (Color_pointer_fg);
461 color_aliases (Color_pointer_bg);
462 color_aliases (Color_border);
463 #ifndef NO_BOLD_UNDERLINE_REVERSE
464 color_aliases (Color_BD);
465 color_aliases (Color_UL);
466 color_aliases (Color_RV);
467 #endif /* ! NO_BOLD_UNDERLINE_REVERSE */
468
469 if (!rs[Rs_color + Color_border])
470 rs[Rs_color + Color_border] = rs[Rs_color + Color_bg];
471
472 return cmd_argv;
473 }
474
475 /*----------------------------------------------------------------------*/
476 void
477 rxvt_term::init_env ()
478 {
479 int i;
480 unsigned int u;
481 char *val;
482
483 #ifdef DISPLAY_IS_IP
484 /* Fixup display_name for export over pty to any interested terminal
485 * clients via "ESC[7n" (e.g. shells). Note we use the pure IP number
486 * (for the first non-loopback interface) that we get from
487 * rxvt_network_display (). This is more "name-resolution-portable", if you
488 * will, and probably allows for faster x-client startup if your name
489 * server is beyond a slow link or overloaded at client startup. Of
490 * course that only helps the shell's child processes, not us.
491 *
492 * Giving out the display_name also affords a potential security hole
493 */
494 val = rxvt_network_display (rs[Rs_display_name]);
495 rs[Rs_display_name] = (const char *)val;
496
497 if (val == NULL)
498 #endif /* DISPLAY_IS_IP */
499 val = XDisplayString (dpy);
500
501 if (rs[Rs_display_name] == NULL)
502 rs[Rs_display_name] = val; /* use broken `:0' value */
503
504 i = strlen (val);
505 env_display = (char *)rxvt_malloc ((i + 9) * sizeof (char));
506
507 sprintf (env_display, "DISPLAY=%s", val);
508
509 sprintf (env_windowid, "WINDOWID=%lu", (unsigned long)parent[0]);
510
511 /* add entries to the environment:
512 * @ DISPLAY: in case we started with -display
513 * @ WINDOWID: X window id number of the window
514 * @ COLORTERM: terminal sub-name and also indicates its color
515 * @ TERM: terminal name
516 * @ TERMINFO: path to terminfo directory
517 * @ COLORFGBG: fg;bg color codes
518 */
519 putenv (env_display);
520 putenv (env_windowid);
521
522 if (env_colorfgbg)
523 putenv (env_colorfgbg);
524
525 #ifdef RXVT_TERMINFO
526 putenv ("TERMINFO=" RXVT_TERMINFO);
527 #endif
528
529 if (depth <= 2)
530 putenv ("COLORTERM=" COLORTERMENV "-mono");
531 else
532 putenv ("COLORTERM=" COLORTERMENVFULL);
533
534 if (rs[Rs_term_name] != NULL)
535 {
536 env_term = (char *)rxvt_malloc ((strlen (rs[Rs_term_name]) + 6) * sizeof (char));
537 sprintf (env_term, "TERM=%s", rs[Rs_term_name]);
538 putenv (env_term);
539 }
540 else
541 putenv ("TERM=" TERMENV);
542
543 #ifdef HAVE_UNSETENV
544 /* avoid passing old settings and confusing term size */
545 unsetenv ("LINES");
546 unsetenv ("COLUMNS");
547 unsetenv ("TERMCAP"); /* terminfo should be okay */
548 #endif /* HAVE_UNSETENV */
549 }
550
551 /*----------------------------------------------------------------------*/
552 /*
553 * This is more or less stolen straight from XFree86 xterm.
554 * This should support all European type languages.
555 */
556 void
557 rxvt_term::set_locale (const char *locale)
558 {
559 set_environ (envv);
560
561 #if HAVE_XSETLOCALE || HAVE_SETLOCALE
562 free (this->locale);
563 this->locale = setlocale (LC_CTYPE, locale);
564
565 if (!this->locale)
566 {
567 if (*locale)
568 {
569 rxvt_warn ("unable to set locale \"%s\", using C locale instead.\n", locale);
570 setlocale (LC_CTYPE, "C");
571 }
572 else
573 rxvt_warn ("default locale unavailable, check LC_* and LANG variables. Continuing.\n");
574
575 this->locale = "C";
576 }
577
578
579 this->locale = rxvt_strdup (this->locale);
580 SET_LOCALE (this->locale);
581 mbstate.reset ();
582 #endif
583
584 #if HAVE_NL_LANGINFO
585 char *codeset = strdup (nl_langinfo (CODESET));
586 // /^UTF.?8/i
587 enc_utf8 = (codeset[0] == 'U' || codeset[0] == 'u')
588 && (codeset[1] == 'T' || codeset[1] == 't')
589 && (codeset[2] == 'F' || codeset[2] == 'f')
590 && (codeset[3] == '8' || codeset[4] == '8');
591 free (codeset);
592 #else
593 enc_utf8 = 0;
594 #endif
595 }
596
597 void
598 rxvt_term::init_xlocale ()
599 {
600 set_environ (envv);
601
602 #ifdef USE_XIM
603 if (!locale)
604 rxvt_warn ("setting locale failed, working without locale support.\n");
605 else
606 {
607 set_string_property (xa[XA_WM_LOCALE_NAME], locale);
608
609 if (!XSupportsLocale ())
610 {
611 rxvt_warn ("the locale is not supported by Xlib, working without locale support.\n");
612 return;
613 }
614
615 im_ev.start (display);
616
617 /* see if we can connect already */
618 im_cb ();
619 }
620 #endif
621 }
622
623 /*----------------------------------------------------------------------*/
624 void
625 rxvt_term::init_command (const char *const *argv)
626 {
627 /*
628 * Initialize the command connection.
629 * This should be called after the X server connection is established.
630 */
631
632 #ifdef META8_OPTION
633 meta_char = option (Opt_meta8) ? 0x80 : C0_ESC;
634 #endif
635
636 get_ourmods ();
637
638 if (!option (Opt_scrollTtyOutput))
639 priv_modes |= PrivMode_TtyOutputInh;
640 if (option (Opt_scrollTtyKeypress))
641 priv_modes |= PrivMode_Keypress;
642 if (!option (Opt_jumpScroll))
643 priv_modes |= PrivMode_smoothScroll;
644
645 #ifndef NO_BACKSPACE_KEY
646 if (strcmp (key_backspace, "DEC") == 0)
647 priv_modes |= PrivMode_HaveBackSpace;
648 #endif
649
650 /* add value for scrollBar */
651 if (scrollBar.state)
652 {
653 priv_modes |= PrivMode_scrollBar;
654 SavedModes |= PrivMode_scrollBar;
655 }
656
657 run_command (argv);
658 }
659
660 /*----------------------------------------------------------------------*/
661 void
662 rxvt_term::Get_Colours ()
663 {
664 int i;
665
666 #ifdef OFF_FOCUS_FADING
667 pix_colors = pix_colors_focused;
668 #endif
669
670 for (i = 0; i < (depth <= 2 ? 2 : NRS_COLORS); i++)
671 {
672 const char *name = rs[Rs_color + i];
673
674 if (!name)
675 continue;
676
677 rxvt_color xcol;
678
679 if (!set_color (xcol, name))
680 {
681 #ifndef XTERM_REVERSE_VIDEO
682 if (i < 2 && option (Opt_reverseVideo))
683 name = def_colorName [1 - i];
684 else
685 #endif
686 name = def_colorName [i];
687
688 if (!name)
689 continue;
690
691 if (!set_color (xcol, name))
692 {
693 switch (i)
694 {
695 case Color_fg:
696 case Color_bg:
697 rxvt_warn ("unable to get foreground/background colour, continuing.\n");
698 name = "";
699 break;
700 #ifndef NO_CURSORCOLOR
701 case Color_cursor2:
702 #endif
703 case Color_pointer_fg:
704 name = rs[Rs_color + Color_fg];
705 xcol.set (this, name);
706 break;
707 default:
708 name = rs[Rs_color + Color_bg];
709 xcol.set (this, name);
710 break;
711 }
712 }
713 }
714
715 pix_colors[i] = xcol;
716 rs[Rs_color + i] = name;
717 }
718
719 if (depth <= 2)
720 {
721 if (!rs[Rs_color + Color_pointer_fg]) alias_color (Color_pointer_fg, Color_fg);
722 if (!rs[Rs_color + Color_pointer_bg]) alias_color (Color_pointer_bg, Color_bg);
723 if (!rs[Rs_color + Color_border] ) alias_color (Color_border, Color_fg);
724 }
725
726 /*
727 * get scrollBar shadow colors
728 *
729 * The calculations of topShadow/bottomShadow values are adapted
730 * from the fvwm window manager.
731 */
732 #ifdef KEEP_SCROLLCOLOR
733 if (depth <= 2)
734 {
735 /* Monochrome */
736 alias_color (Color_scroll, Color_fg);
737 alias_color (Color_topShadow, Color_bg);
738 alias_color (Color_bottomShadow, Color_bg);
739 }
740 else
741 {
742 pix_colors [Color_scroll].fade (this, 50, pix_colors [Color_bottomShadow]);
743
744 rgba cscroll;
745 pix_colors [Color_scroll].get (cscroll);
746
747 /* topShadowColor */
748 if (!pix_colors[Color_topShadow].set (this,
749 rgba (
750 min ((int)rgba::MAX_CC, max (cscroll.r / 5, cscroll.r) * 7 / 5),
751 min ((int)rgba::MAX_CC, max (cscroll.g / 5, cscroll.g) * 7 / 5),
752 min ((int)rgba::MAX_CC, max (cscroll.b / 5, cscroll.b) * 7 / 5),
753 cscroll.a)
754 ))
755 alias_color (Color_topShadow, Color_White);
756 }
757 #endif /* KEEP_SCROLLCOLOR */
758
759 #ifdef OFF_FOCUS_FADING
760 for (i = 0; i < (depth <= 2 ? 2 : NRS_COLORS); i++)
761 update_fade_color (i);
762 #endif
763 }
764
765 /*----------------------------------------------------------------------*/
766 /* color aliases, fg/bg bright-bold */
767 void
768 rxvt_term::color_aliases (int idx)
769 {
770 if (rs[Rs_color + idx] && isdigit (* (rs[Rs_color + idx])))
771 {
772 int i = atoi (rs[Rs_color + idx]);
773
774 if (i >= 8 && i <= 15)
775 { /* bright colors */
776 i -= 8;
777 rs[Rs_color + idx] = rs[Rs_color + minBrightCOLOR + i];
778 return;
779 }
780
781 if (i >= 0 && i <= 7) /* normal colors */
782 rs[Rs_color + idx] = rs[Rs_color + minCOLOR + i];
783 }
784 }
785
786 /*----------------------------------------------------------------------*/
787 /*
788 * Probe the modifier keymap to get the Meta (Alt) and Num_Lock settings
789 * Use resource ``modifier'' to override the Meta modifier
790 */
791 void
792 rxvt_term::get_ourmods ()
793 {
794 int i, j, k;
795 int requestedmeta, realmeta, realalt;
796 const char *cm, *rsmod;
797 XModifierKeymap *map;
798 KeyCode *kc;
799 const unsigned int modmasks[] =
800 {
801 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
802 };
803
804 requestedmeta = realmeta = realalt = 0;
805 rsmod = rs[Rs_modifier];
806
807 if (rsmod
808 && strcasecmp (rsmod, "mod1") >= 0 && strcasecmp (rsmod, "mod5") <= 0)
809 requestedmeta = rsmod[3] - '0';
810
811 map = XGetModifierMapping (dpy);
812 kc = map->modifiermap;
813
814 for (i = 1; i < 6; i++)
815 {
816 k = (i + 2) * map->max_keypermod; /* skip shift/lock/control */
817
818 for (j = map->max_keypermod; j--; k++)
819 {
820 if (kc[k] == 0)
821 break;
822
823 switch (XKeycodeToKeysym (dpy, kc[k], 0))
824 {
825 case XK_Num_Lock:
826 ModNumLockMask = modmasks[i - 1];
827 continue;
828
829 case XK_ISO_Level3_Shift:
830 ModLevel3Mask = modmasks[i - 1];
831 continue;
832
833 case XK_Meta_L:
834 case XK_Meta_R:
835 cm = "meta";
836 realmeta = i;
837 break;
838
839 case XK_Alt_L:
840 case XK_Alt_R:
841 cm = "alt";
842 realalt = i;
843 break;
844
845 case XK_Super_L:
846 case XK_Super_R:
847 cm = "super";
848 break;
849
850 case XK_Hyper_L:
851 case XK_Hyper_R:
852 cm = "hyper";
853 break;
854
855 default:
856 continue;
857 }
858
859 if (rsmod && strncasecmp (rsmod, cm, strlen (cm)) == 0)
860 requestedmeta = i;
861 }
862 }
863
864 XFreeModifiermap (map);
865
866 i = requestedmeta ? requestedmeta
867 : realmeta ? realmeta
868 : realalt ? realalt
869 : 0;
870
871 if (i)
872 ModMetaMask = modmasks[i - 1];
873 }
874
875 /*----------------------------------------------------------------------*/
876 /* rxvt_Create_Windows () - Open and map the window */
877 void
878 rxvt_term::create_windows (int argc, const char *const *argv)
879 {
880 XClassHint classHint;
881 XWMHints wmHint;
882 #if ENABLE_FRILLS
883 MWMHints mwmhints;
884 #endif
885 XGCValues gcvalue;
886 XSetWindowAttributes attributes;
887 Window top, parent;
888
889 dLocal (Display *, dpy);
890
891 /* grab colors before netscape does */
892 Get_Colours ();
893
894 if (!set_fonts ())
895 rxvt_fatal ("unable to load base fontset, please specify a valid one using -fn, aborting.\n");
896
897 parent = display->root;
898
899 attributes.override_redirect = !!option (Opt_override_redirect);
900
901 #if ENABLE_FRILLS
902 if (option (Opt_borderLess))
903 {
904 if (XInternAtom (dpy, "_MOTIF_WM_INFO", True) == None)
905 {
906 /* print_warning("Window Manager does not support MWM hints. Bypassing window manager control for borderless window.\n");*/
907 attributes.override_redirect = true;
908 mwmhints.flags = 0;
909 }
910 else
911 {
912 mwmhints.flags = MWM_HINTS_DECORATIONS;
913 mwmhints.decorations = 0;
914 }
915 }
916 else
917 mwmhints.flags = 0;
918 #endif
919
920 #if ENABLE_XEMBED
921 if (rs[Rs_embed])
922 {
923 XWindowAttributes wattr;
924
925 parent = strtol (rs[Rs_embed], 0, 0);
926
927 if (!XGetWindowAttributes (dpy, parent, &wattr))
928 rxvt_fatal ("invalid window-id specified with -embed, aborting.\n");
929
930 window_calc (wattr.width, wattr.height);
931 }
932 #endif
933
934 window_calc (0, 0);
935
936 /* sub-window placement & size in rxvt_resize_subwindows () */
937 attributes.background_pixel = pix_colors_focused [Color_border];
938 attributes.border_pixel = pix_colors_focused [Color_border];
939 attributes.colormap = cmap;
940
941 top = XCreateWindow (dpy, parent,
942 szHint.x, szHint.y,
943 szHint.width, szHint.height,
944 ext_bwidth,
945 depth, InputOutput, visual,
946 CWColormap | CWBackPixel | CWBorderPixel | CWOverrideRedirect,
947 &attributes);
948
949 this->parent[0] = top;
950
951 old_width = szHint.width;
952 old_height = szHint.height;
953
954 process_xterm_seq (XTerm_title, rs[Rs_title], CHAR_ST);
955 process_xterm_seq (XTerm_iconName, rs[Rs_iconName], CHAR_ST);
956
957 classHint.res_name = (char *)rs[Rs_name];
958 classHint.res_class = (char *)RESCLASS;
959
960 wmHint.flags = InputHint | StateHint | WindowGroupHint;
961 wmHint.input = True;
962 wmHint.initial_state = option (Opt_iconic) ? IconicState : NormalState;
963 wmHint.window_group = top;
964
965 XmbSetWMProperties (dpy, top, NULL, NULL, (char **)argv, argc,
966 &szHint, &wmHint, &classHint);
967
968 #if ENABLE_FRILLS
969 if (mwmhints.flags)
970 XChangeProperty (dpy, top, xa[XA_MOTIF_WM_HINTS], xa[XA_MOTIF_WM_HINTS], 32,
971 PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
972 #endif
973
974 Atom protocols[] = {
975 xa[XA_WM_DELETE_WINDOW],
976 #if ENABLE_EWMH
977 xa[XA_NET_WM_PING],
978 #endif
979 };
980
981 XSetWMProtocols (dpy, top, protocols, sizeof (protocols) / sizeof (protocols[0]));
982
983 #if ENABLE_FRILLS
984 if (rs[Rs_transient_for])
985 XSetTransientForHint (dpy, top, (Window)strtol (rs[Rs_transient_for], 0, 0));
986 #endif
987
988 #if ENABLE_EWMH
989 long pid = getpid ();
990
991 XChangeProperty (dpy, top,
992 xa[XA_NET_WM_PID], XA_CARDINAL, 32,
993 PropModeReplace, (unsigned char *)&pid, 1);
994
995 // _NET_WM_WINDOW_TYPE is NORMAL, which is the default
996 #endif
997
998 XSelectInput (dpy, top,
999 KeyPressMask
1000 #if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ENABLE_FRILLS || ISO_14755
1001 | KeyReleaseMask
1002 #endif
1003 | FocusChangeMask | VisibilityChangeMask
1004 | ExposureMask | StructureNotifyMask);
1005
1006 termwin_ev.start (display, top);
1007
1008 /* vt cursor: Black-on-White is standard, but this is more popular */
1009 TermWin_cursor = XCreateFontCursor (dpy, XC_xterm);
1010
1011 #ifdef HAVE_SCROLLBARS
1012 /* cursor scrollBar: Black-on-White */
1013 leftptr_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1014 #endif
1015
1016 /* the vt window */
1017 vt = XCreateSimpleWindow (dpy, top,
1018 window_vt_x, window_vt_y,
1019 width, height,
1020 0,
1021 pix_colors_focused[Color_fg],
1022 pix_colors_focused[Color_bg]);
1023
1024 attributes.bit_gravity = NorthWestGravity;
1025 XChangeWindowAttributes (dpy, vt, CWBitGravity, &attributes);
1026
1027 vt_emask = ExposureMask | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask;
1028
1029 if (option (Opt_pointerBlank))
1030 vt_emask |= PointerMotionMask;
1031 else
1032 vt_emask |= Button1MotionMask | Button3MotionMask;
1033
1034 vt_select_input ();
1035
1036 vt_ev.start (display, vt);
1037
1038 #ifdef XPM_BACKGROUND
1039 if (rs[Rs_backgroundPixmap] != NULL
1040 #ifndef HAVE_AFTERIMAGE
1041 && !OPTION (Opt_transparent)
1042 #endif
1043 )
1044 {
1045 const char *p = rs[Rs_backgroundPixmap];
1046
1047 if ((p = strchr (p, ';')) != NULL)
1048 {
1049 p++;
1050 scale_pixmap (p);
1051 }
1052
1053 set_bgPixmap (rs[Rs_backgroundPixmap]);
1054 scr_touch (true);
1055 }
1056 #endif
1057
1058 /* graphics context for the vt window */
1059 gcvalue.foreground = pix_colors[Color_fg];
1060 gcvalue.background = pix_colors[Color_bg];
1061 gcvalue.graphics_exposures = 0;
1062
1063 gc = XCreateGC (dpy, vt,
1064 GCForeground | GCBackground | GCGraphicsExposures,
1065 &gcvalue);
1066
1067 drawable = new rxvt_drawable (this, vt);
1068
1069 #ifdef RXVT_SCROLLBAR
1070 gcvalue.foreground = pix_colors[Color_topShadow];
1071 topShadowGC = XCreateGC (dpy, vt, GCForeground, &gcvalue);
1072 gcvalue.foreground = pix_colors[Color_bottomShadow];
1073 botShadowGC = XCreateGC (dpy, vt, GCForeground, &gcvalue);
1074 gcvalue.foreground = pix_colors[ (depth <= 2 ? Color_fg : Color_scroll)];
1075 scrollbarGC = XCreateGC (dpy, vt, GCForeground, &gcvalue);
1076 #endif
1077
1078 #ifdef OFF_FOCUS_FADING
1079 // initially we are in unfocused state
1080 if (rs[Rs_fade])
1081 pix_colors = pix_colors_unfocused;
1082 #endif
1083
1084 pointer_unblank ();
1085 scr_recolour ();
1086 }
1087
1088 /* ------------------------------------------------------------------------- *
1089 * GET TTY CURRENT STATE *
1090 * ------------------------------------------------------------------------- */
1091 void
1092 rxvt_get_ttymode (ttymode_t *tio, int erase)
1093 {
1094 /*
1095 * standard System V termios interface
1096 */
1097 if (GET_TERMIOS (STDIN_FILENO, tio) < 0)
1098 {
1099 // return error - use system defaults,
1100 // where possible, and zero elsewhere
1101 memset (tio, 0, sizeof (ttymode_t));
1102
1103 tio->c_cc[VINTR] = CINTR;
1104 tio->c_cc[VQUIT] = CQUIT;
1105 tio->c_cc[VERASE] = CERASE;
1106 #ifdef VERASE2
1107 tio->c_cc[VERASE2] = CERASE2;
1108 #endif
1109 tio->c_cc[VKILL] = CKILL;
1110 tio->c_cc[VSTART] = CSTART;
1111 tio->c_cc[VSTOP] = CSTOP;
1112 tio->c_cc[VSUSP] = CSUSP;
1113 # ifdef VDSUSP
1114 tio->c_cc[VDSUSP] = CDSUSP;
1115 # endif
1116 # ifdef VREPRINT
1117 tio->c_cc[VREPRINT] = CRPRNT;
1118 # endif
1119 # ifdef VDISCRD
1120 tio->c_cc[VDISCRD] = CFLUSH;
1121 # endif
1122 # ifdef VWERSE
1123 tio->c_cc[VWERSE] = CWERASE;
1124 # endif
1125 # ifdef VLNEXT
1126 tio->c_cc[VLNEXT] = CLNEXT;
1127 # endif
1128 }
1129
1130 tio->c_cc[VEOF] = CEOF;
1131 tio->c_cc[VEOL] = VDISABLE;
1132 # ifdef VEOL2
1133 tio->c_cc[VEOL2] = VDISABLE;
1134 # endif
1135 # ifdef VSWTC
1136 tio->c_cc[VSWTC] = VDISABLE;
1137 # endif
1138 # ifdef VSWTCH
1139 tio->c_cc[VSWTCH] = VDISABLE;
1140 # endif
1141 # if VMIN != VEOF
1142 tio->c_cc[VMIN] = 1;
1143 # endif
1144 # if VTIME != VEOL
1145 tio->c_cc[VTIME] = 0;
1146 # endif
1147
1148 if (erase != -1)
1149 tio->c_cc[VERASE] = (char)erase;
1150
1151 /* input modes */
1152 tio->c_iflag = (BRKINT | IGNPAR | ICRNL
1153 # ifdef IMAXBEL
1154 | IMAXBEL
1155 # endif
1156 | IXON);
1157
1158 /* output modes */
1159 tio->c_oflag = (OPOST | ONLCR);
1160
1161 /* control modes */
1162 tio->c_cflag = (CS8 | CREAD);
1163
1164 /* line discipline modes */
1165 tio->c_lflag = (ISIG | ICANON | IEXTEN | ECHO
1166 # if defined (ECHOCTL) && defined (ECHOKE)
1167 | ECHOCTL | ECHOKE
1168 # endif
1169 | ECHOE | ECHOK);
1170
1171 /*
1172 * Debugging
1173 */
1174 #ifdef DEBUG_TTYMODE
1175 #ifdef HAVE_TERMIOS_H
1176 /* c_iflag bits */
1177 fprintf (stderr, "Input flags\n");
1178
1179 /* cpp token stringize doesn't work on all machines <sigh> */
1180 # define FOO(flag,name) \
1181 if ((tio->c_iflag) & flag) \
1182 fprintf (stderr, "%s ", name)
1183
1184 /* c_iflag bits */
1185 FOO (IGNBRK, "IGNBRK");
1186 FOO (BRKINT, "BRKINT");
1187 FOO (IGNPAR, "IGNPAR");
1188 FOO (PARMRK, "PARMRK");
1189 FOO (INPCK, "INPCK");
1190 FOO (ISTRIP, "ISTRIP");
1191 FOO (INLCR, "INLCR");
1192 FOO (IGNCR, "IGNCR");
1193 FOO (ICRNL, "ICRNL");
1194 FOO (IXON, "IXON");
1195 FOO (IXOFF, "IXOFF");
1196 # ifdef IUCLC
1197 FOO (IUCLC, "IUCLC");
1198 # endif
1199 # ifdef IXANY
1200 FOO (IXANY, "IXANY");
1201 # endif
1202 # ifdef IMAXBEL
1203 FOO (IMAXBEL, "IMAXBEL");
1204 # endif
1205
1206 fprintf (stderr, "\n");
1207
1208 # undef FOO
1209 # define FOO(entry, name) \
1210 fprintf (stderr, "%-8s = %#04o\n", name, tio->c_cc [entry])
1211
1212 FOO (VINTR, "VINTR");
1213 FOO (VQUIT, "VQUIT");
1214 FOO (VERASE, "VERASE");
1215 FOO (VKILL, "VKILL");
1216 FOO (VEOF, "VEOF");
1217 FOO (VEOL, "VEOL");
1218 # ifdef VEOL2
1219 FOO (VEOL2, "VEOL2");
1220 # endif
1221 # ifdef VSWTC
1222 FOO (VSWTC, "VSWTC");
1223 # endif
1224 # ifdef VSWTCH
1225 FOO (VSWTCH, "VSWTCH");
1226 # endif
1227 FOO (VSTART, "VSTART");
1228 FOO (VSTOP, "VSTOP");
1229 FOO (VSUSP, "VSUSP");
1230 # ifdef VDSUSP
1231 FOO (VDSUSP, "VDSUSP");
1232 # endif
1233 # ifdef VREPRINT
1234 FOO (VREPRINT, "VREPRINT");
1235 # endif
1236 # ifdef VDISCRD
1237 FOO (VDISCRD, "VDISCRD");
1238 # endif
1239 # ifdef VWERSE
1240 FOO (VWERSE, "VWERSE");
1241 # endif
1242 # ifdef VLNEXT
1243 FOO (VLNEXT, "VLNEXT");
1244 # endif
1245
1246 fprintf (stderr, "\n");
1247 # undef FOO
1248 # endif /* HAVE_TERMIOS_H */
1249 #endif /* DEBUG_TTYMODE */
1250 }
1251
1252 /*----------------------------------------------------------------------*/
1253 /*
1254 * Run the command in a subprocess and return a file descriptor for the
1255 * master end of the pseudo-teletype pair with the command talking to
1256 * the slave.
1257 */
1258 void
1259 rxvt_term::run_command (const char *const *argv)
1260 {
1261 #if ENABLE_FRILLS
1262 if (rs[Rs_pty_fd])
1263 {
1264 pty->pty = atoi (rs[Rs_pty_fd]);
1265
1266 if (pty->pty >= 0)
1267 {
1268 if (getfd_hook)
1269 pty->pty = (*getfd_hook) (pty->pty);
1270
1271 if (pty->pty < 0 || fcntl (pty->pty, F_SETFL, O_NONBLOCK))
1272 rxvt_fatal ("unusable pty-fd filehandle, aborting.\n");
1273 }
1274 }
1275 else
1276 #endif
1277 if (!pty->get ())
1278 rxvt_fatal ("can't initialize pseudo-tty, aborting.\n");
1279
1280 int er;
1281
1282 #ifndef NO_BACKSPACE_KEY
1283 if (key_backspace[0] && !key_backspace[1])
1284 er = key_backspace[0];
1285 else if (strcmp (key_backspace, "DEC") == 0)
1286 er = '\177'; /* the initial state anyway */
1287 else
1288 #endif
1289 er = -1;
1290
1291 rxvt_get_ttymode (&tio, er);
1292 SET_TERMIOS (pty->tty, &tio); /* init terminal attributes */
1293 pty->set_utf8_mode (enc_utf8);
1294
1295 /* set initial window size */
1296 tt_winch ();
1297
1298 #if ENABLE_FRILLS
1299 if (rs[Rs_pty_fd])
1300 return;
1301 #endif
1302
1303 /* spin off the command interpreter */
1304 switch (cmd_pid = fork ())
1305 {
1306 case -1:
1307 {
1308 cmd_pid = 0;
1309 rxvt_fatal ("can't fork, aborting.\n");
1310 }
1311 case 0:
1312 init_env ();
1313
1314 if (!pty->make_controlling_tty ())
1315 fprintf (stderr, "%s: could not obtain control of tty.", RESNAME);
1316 else
1317 {
1318 /* Reopen stdin, stdout and stderr over the tty file descriptor */
1319 dup2 (pty->tty, STDIN_FILENO);
1320 dup2 (pty->tty, STDOUT_FILENO);
1321 dup2 (pty->tty, STDERR_FILENO);
1322
1323 // close all our file handles that we do no longer need
1324 for (rxvt_term **t = termlist.begin (); t < termlist.end (); t++)
1325 {
1326 if ((*t)->pty->pty > 2) close ((*t)->pty->pty);
1327 if ((*t)->pty->tty > 2) close ((*t)->pty->tty);
1328 }
1329
1330 run_child (argv);
1331 fprintf (stderr, "%s: unable to exec child.", RESNAME);
1332 }
1333
1334 _exit (EXIT_FAILURE);
1335
1336 default:
1337 if (!option (Opt_utmpInhibit))
1338 pty->login (cmd_pid, option (Opt_loginShell), rs[Rs_display_name]);
1339
1340 pty->close_tty ();
1341
1342 child_ev.start (cmd_pid);
1343
1344 HOOK_INVOKE ((this, HOOK_CHILD_START, DT_INT, cmd_pid, DT_END));
1345 break;
1346 }
1347 }
1348
1349 /* ------------------------------------------------------------------------- *
1350 * CHILD PROCESS OPERATIONS *
1351 * ------------------------------------------------------------------------- */
1352 /*
1353 * The only open file descriptor is the slave tty - so no error messages.
1354 * returns are fatal
1355 */
1356 int
1357 rxvt_term::run_child (const char *const *argv)
1358 {
1359 char *login;
1360
1361 if (option (Opt_console))
1362 { /* be virtual console, fail silently */
1363 #ifdef TIOCCONS
1364 unsigned int on = 1;
1365
1366 ioctl (STDIN_FILENO, TIOCCONS, &on);
1367 #elif defined (SRIOCSREDIR)
1368 int fd;
1369
1370 fd = open (CONSOLE, O_WRONLY, 0);
1371 if (fd >= 0)
1372 if (ioctl (fd, SRIOCSREDIR, NULL) < 0)
1373 close (fd);
1374 #endif /* SRIOCSREDIR */
1375 }
1376
1377 /* reset signals and spin off the command interpreter */
1378 signal (SIGINT, SIG_DFL);
1379 signal (SIGQUIT, SIG_DFL);
1380 signal (SIGCHLD, SIG_DFL);
1381 signal (SIGHUP, SIG_DFL);
1382 signal (SIGPIPE, SIG_DFL);
1383 /*
1384 * mimick login's behavior by disabling the job control signals
1385 * a shell that wants them can turn them back on
1386 */
1387 #ifdef SIGTSTP
1388 signal (SIGTSTP, SIG_IGN);
1389 signal (SIGTTIN, SIG_IGN);
1390 signal (SIGTTOU, SIG_IGN);
1391 #endif /* SIGTSTP */
1392
1393 // unblock signals (signals are blocked by iom.C
1394 sigset_t ss;
1395 sigemptyset (&ss);
1396 sigprocmask (SIG_SETMASK, &ss, 0);
1397
1398 /* command interpreter path */
1399 if (argv != NULL)
1400 {
1401 # ifdef DEBUG_CMD
1402 int i;
1403
1404 for (i = 0; argv[i]; i++)
1405 fprintf (stderr, "argv [%d] = \"%s\"\n", i, argv[i]);
1406 # endif
1407
1408 execvp (argv[0], (char *const *)argv);
1409 /* no error message: STDERR is closed! */
1410 }
1411 else
1412 {
1413 const char *argv0, *shell;
1414
1415 if ((shell = getenv ("SHELL")) == NULL || *shell == '\0')
1416 shell = "/bin/sh";
1417
1418 argv0 = (const char *)rxvt_r_basename (shell);
1419
1420 if (option (Opt_loginShell))
1421 {
1422 login = (char *)rxvt_malloc ((strlen (argv0) + 2) * sizeof (char));
1423
1424 login[0] = '-';
1425 strcpy (&login[1], argv0);
1426 argv0 = login;
1427 }
1428
1429 execlp (shell, argv0, NULL);
1430 /* no error message: STDERR is closed! */
1431 }
1432
1433 return -1;
1434 }
1435
1436 /*----------------------- end-of-file (C source) -----------------------*/