--- rxvt-unicode/src/init.C 2011/04/07 12:19:40 1.294 +++ rxvt-unicode/src/init.C 2022/12/23 21:46:46 1.351 @@ -13,10 +13,11 @@ * Copyright (c) 1998-2001 Geoff Wing * - extensive modifications * Copyright (c) 2003-2008 Marc Lehmann + * Copyright (c) 2015 Emanuele Giaquinta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -40,23 +41,30 @@ #include -#include +#include #include +#ifdef HAVE_XMU +# include +#endif + #ifdef HAVE_XSETLOCALE # define X_LOCALE # include #else -# ifdef HAVE_SETLOCALE -# include -# endif +# include #endif #ifdef HAVE_NL_LANGINFO # include #endif +#ifdef HAVE_STARTUP_NOTIFICATION +# define SN_API_NOT_YET_FROZEN +# include +#endif + #ifdef DISPLAY_IS_IP /* On Solaris link with -lsocket and -lnsl */ #include @@ -75,7 +83,7 @@ #include #include -static char * +static char * ecb_cold rxvt_network_display (const char *display) { char buffer[1024], *rval = NULL; @@ -145,6 +153,31 @@ } #endif +#define NULL_5 \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, + +#define NULL_10 \ + NULL_5 \ + NULL_5 + +#define NULL_40 \ + NULL_10 \ + NULL_10 \ + NULL_10 \ + NULL_10 + +#define NULL_50 \ + NULL_40 \ + NULL_10 + +#define NULL_100 \ + NULL_50 \ + NULL_50 + static const char *const def_colorName[] = { COLOR_FOREGROUND, @@ -250,6 +283,12 @@ "rgb:b9/b9/b9", "rgb:d0/d0/d0", "rgb:e7/e7/e7", + NULL_100 + NULL_40 + NULL, + NULL, + NULL, + NULL, #else // 256 xterm colours "rgb:00/00/00", @@ -492,6 +531,10 @@ "rgb:da/da/da", "rgb:e4/e4/e4", "rgb:ee/ee/ee", + NULL_100 + NULL_100 + NULL_40 + NULL_5 #endif #ifndef NO_CURSORCOLOR @@ -518,9 +561,6 @@ #ifdef RXVT_SCROLLBAR COLOR_SCROLLTROUGH, #endif -#if ENABLE_TRANSPARENCY - NULL, -#endif #if OFF_FOCUS_FADING "rgb:00/00/00", #endif @@ -560,40 +600,20 @@ set_option (Opt_buffered); } +#if ENABLE_PERL +static void +rxvt_perl_parse_resource (rxvt_term *term, const char *k, const char *v) +{ + rxvt_perl.parse_resource (term, k, false, false, 0, v); +} +#endif + /*----------------------------------------------------------------------*/ const char ** rxvt_term::init_resources (int argc, const char *const *argv) { - int i, r_argc; - const char **cmd_argv, **r_argv; - - /* - * Look for -e option. Find => split and make cmd_argv[] of command args - */ - for (r_argc = 0; r_argc < argc; r_argc++) - if (!strcmp (argv[r_argc], "-e")) - break; - - if (r_argc == argc) - cmd_argv = NULL; - else if (!argv[r_argc + 1]) - rxvt_fatal ("option '-e' requires an argument, aborting.\n"); - else - { - cmd_argv = (const char **)rxvt_malloc (sizeof (char *) * (argc - r_argc)); - - for (i = 0; i < argc - r_argc - 1; i++) - cmd_argv[i] = (const char *)argv[i + r_argc + 1]; - - cmd_argv[i] = NULL; - } - - r_argv = (const char **)rxvt_malloc (sizeof (char *) * (r_argc + 1)); - - for (i = 0; i < r_argc; i++) - r_argv[i] = (const char *)argv[i]; - - r_argv[i] = NULL; + int i; + const char **cmd_argv; rs[Rs_name] = rxvt_basename (argv[0]); @@ -604,13 +624,10 @@ if ((rs[Rs_display_name] = getenv ("DISPLAY")) == NULL) rs[Rs_display_name] = ":0"; - get_options (r_argc, r_argv); + cmd_argv = get_options (argc, argv); if (!(display = displays.get (rs[Rs_display_name]))) - { - free (r_argv); - rxvt_fatal ("can't open display %s, aborting.\n", rs[Rs_display_name]); - } + rxvt_fatal ("can't open display %s, aborting.\n", rs[Rs_display_name]); // using a local pointer decreases code size a lot xa = display->xa; @@ -618,26 +635,17 @@ set (display); extract_resources (); -#if XFT - if (rs[Rs_depth]) - select_visual (strtol (rs[Rs_depth], 0, 0)); +#if ENABLE_FRILLS + if (rs[Rs_visual]) + select_visual (strtol (rs[Rs_visual], 0, 0)); + else if (rs[Rs_depth]) + select_depth (strtol (rs[Rs_depth], 0, 0)); #endif - free (r_argv); - for (int i = NUM_RESOURCES; i--; ) if (rs [i] == resval_undef) rs [i] = 0; -#ifdef HAVE_AFTERIMAGE - set_application_name ((char *)rs[Rs_name]); - set_output_threshold (OUTPUT_LEVEL_WARNING); -#endif - -#ifdef HAVE_PIXBUF - g_type_init (); -#endif - #if ENABLE_PERL if (!rs[Rs_perl_ext_1]) rs[Rs_perl_ext_1] = "default"; @@ -647,10 +655,15 @@ || (rs[Rs_perl_eval] && *rs[Rs_perl_eval])) { rxvt_perl.init (this); + enumerate_resources (rxvt_perl_parse_resource); HOOK_INVOKE ((this, HOOK_INIT, DT_END)); } #endif + // must be called after initialising the perl interpreter as it + // may invoke the `on_register_command' hook + extract_keysym_resources (); + /* * set any defaults not already set */ @@ -684,8 +697,19 @@ if (rs[Rs_lineSpace] && (i = atoi (rs[Rs_lineSpace])) >= 0) lineSpace = min (i, std::numeric_limits::max ()); - if (rs[Rs_letterSpace]) - letterSpace = atoi (rs[Rs_letterSpace]); + if (const char *v = rs[Rs_letterSpace]) + letterSpace = atoi (v); + + rewrap_always = rewrap_never = 0; + if (const char *v = rs[Rs_rewrapMode]) + if (!strcmp (v, "never")) + rewrap_never = 1; + else if (!strcmp (v, "always")) + rewrap_always = 1; + else if (!strcmp (v, "auto")) + /* nop **/; + else + rxvt_warn ("invalid rewrapMode, must be auto, always or never.\n"); #endif #ifdef POINTER_BLANK @@ -695,6 +719,13 @@ pointerBlankDelay = 2; #endif + if (rs[Rs_multiClickTime] && (i = atoi (rs[Rs_multiClickTime])) >= 0) + multiClickTime = i; + else + multiClickTime = 500; + + cursor_type = option (Opt_cursorUnderline) ? 1 : 0; + /* no point having a scrollbar without having any scrollback! */ if (!saveLines) set_option (Opt_scrollBar, 0); @@ -768,13 +799,46 @@ /*----------------------------------------------------------------------*/ void -rxvt_term::init (int argc, const char *const *argv, stringvec *envv) +rxvt_term::init (stringvec *argv, stringvec *envv) { + argv->push_back (0); + envv->push_back (0); + + this->argv = argv; this->envv = envv; + env = new char *[this->envv->size ()]; + for (int i = 0; i < this->envv->size (); i++) + env[i] = this->envv->at (i); + + init2 (argv->size () - 1, argv->begin ()); +} + +void +rxvt_term::init (int argc, const char *const *argv, const char *const *envv) +{ +#if ENABLE_PERL + // perl might want to access the stringvecs later, so we need to copy them + stringvec *args = new stringvec; + for (int i = 0; i < argc; i++) + args->push_back (strdup (argv [i])); + + stringvec *envs = new stringvec; + for (const char *const *var = envv; *var; var++) + envs->push_back (strdup (*var)); + + init (args, envs); +#else + init2 (argc, argv); +#endif +} + +void +rxvt_term::init2 (int argc, const char *const *argv) +{ SET_R (this); set_locale (""); - set_environ (envv); // a few things in X do not call setlocale :( + set_environ (env); // a few things in X do not call setlocale :( init_vars (); @@ -784,6 +848,23 @@ keyboard->register_done (); #endif + { + ev_tstamp interval = 1. / 60.; + +#if ENABLE_FRILLS + if (rs[Rs_refreshRate]) + { + interval = atof (rs[Rs_refreshRate]); + if (interval <= 0.) + interval = -interval; + else + interval = 1. / interval; + } +#endif + + flush_ev.set (interval, interval); + } + if (const char *path = rs[Rs_chdir]) if (*path) // ignored if empty { @@ -795,7 +876,7 @@ } if (option (Opt_scrollBar)) - scrollBar.state = STATE_IDLE; /* set existence for size calculations */ + scrollBar.state = SB_STATE_IDLE; /* set existence for size calculations */ pty = ptytty::create (); @@ -811,61 +892,15 @@ if (option (Opt_scrollBar)) scrollBar.resize (); /* create and map scrollbar */ -#ifdef HAVE_BG_PIXMAP - { - bg_init (); - -#ifdef ENABLE_TRANSPARENCY - if (option (Opt_transparent)) - { - bg_set_transparent (); - - if (rs [Rs_blurradius]) - bg_set_blur (rs [Rs_blurradius]); - - if (ISSET_PIXCOLOR (Color_tint)) - bg_set_tint (pix_colors_focused [Color_tint]); - - if (rs [Rs_shade]) - bg_set_shade (rs [Rs_shade]); - - bg_set_root_pixmap (); - XSelectInput (dpy, display->root, PropertyChangeMask); - rootwin_ev.start (display, display->root); - } -#endif - -#ifdef BG_IMAGE_FROM_FILE - if (rs[Rs_backgroundPixmap]) - { - const char *p = rs[Rs_backgroundPixmap]; - - if ((p = strchr (p, ';')) != 0) - { - p++; - bg_set_geometry (p); - } - else - bg_set_default_geometry (); - - if (bg_set_file (rs[Rs_backgroundPixmap])) - if (!bg_window_position_sensitive ()) - update_background (); - } -#endif - } -#endif #if ENABLE_PERL rootwin_ev.start (display, display->root); #endif - set_colorfgbg (); + init_done = 1; init_command (cmd_argv); - free (cmd_argv); - if (pty->pty >= 0) pty_ev.start (pty->pty, ev::READ); @@ -881,9 +916,33 @@ } #endif +#if HAVE_STARTUP_NOTIFICATION + SnDisplay *snDisplay; + SnLauncheeContext *snContext; + + snDisplay = sn_display_new (dpy, NULL, NULL); + snContext = sn_launchee_context_new_from_environment (snDisplay, DefaultScreen (dpy)); + + /* Tell the window manager that this window is part of the startup context */ + if (snContext) + sn_launchee_context_setup_window (snContext, parent); +#endif + XMapWindow (dpy, vt); XMapWindow (dpy, parent); +#if HAVE_STARTUP_NOTIFICATION + if (snContext) + { + /* Mark the startup process as complete */ + sn_launchee_context_complete (snContext); + + sn_launchee_context_unref (snContext); + } + + sn_display_unref (snDisplay); +#endif + refresh_check (); } @@ -892,6 +951,10 @@ rxvt_term::init_env () { char *val; + char *env_display; + char *env_windowid; + char *env_colorfgbg; + char *env_term; #ifdef DISPLAY_IS_IP /* Fixup display_name for export over pty to any interested terminal @@ -918,6 +981,7 @@ sprintf (env_display, "DISPLAY=%s", val); + env_windowid = (char *)rxvt_malloc (21); sprintf (env_windowid, "WINDOWID=%lu", (unsigned long)parent); /* add entries to the environment: @@ -931,17 +995,17 @@ putenv (env_display); putenv (env_windowid); - if (env_colorfgbg) - putenv (env_colorfgbg); + env_colorfgbg = get_colorfgbg (); + putenv (env_colorfgbg); #ifdef RXVT_TERMINFO putenv ("TERMINFO=" RXVT_TERMINFO); #endif if (depth <= 2) - putenv ("COLORTERM=" COLORTERMENV "-mono"); + putenv ((char *)"COLORTERM=" COLORTERMENV "-mono"); else - putenv ("COLORTERM=" COLORTERMENVFULL); + putenv ((char *)"COLORTERM=" COLORTERMENVFULL); if (rs[Rs_term_name] != NULL) { @@ -950,7 +1014,7 @@ putenv (env_term); } else - putenv ("TERM=" TERMENV); + putenv ((char *)"TERM=" TERMENV); #ifdef HAVE_UNSETENV /* avoid passing old settings and confusing term size */ @@ -961,16 +1025,11 @@ } /*----------------------------------------------------------------------*/ -/* - * This is more or less stolen straight from XFree86 xterm. - * This should support all European type languages. - */ void rxvt_term::set_locale (const char *locale) { - set_environ (envv); + set_environ (env); -#if HAVE_XSETLOCALE || HAVE_SETLOCALE free (this->locale); this->locale = setlocale (LC_CTYPE, locale); @@ -984,23 +1043,21 @@ else rxvt_warn ("default locale unavailable, check LC_* and LANG variables. Continuing.\n"); - this->locale = "C"; + this->locale = (char *)"C"; /* strdup'ed below */ } this->locale = strdup (this->locale); SET_LOCALE (this->locale); mbstate.reset (); -#endif #if HAVE_NL_LANGINFO - char *codeset = strdup (nl_langinfo (CODESET)); + char *codeset = nl_langinfo (CODESET); // /^UTF.?8/i enc_utf8 = (codeset[0] == 'U' || codeset[0] == 'u') && (codeset[1] == 'T' || codeset[1] == 't') && (codeset[2] == 'F' || codeset[2] == 'f') && (codeset[3] == '8' || codeset[4] == '8'); - free (codeset); #else enc_utf8 = 0; #endif @@ -1009,18 +1066,18 @@ void rxvt_term::init_xlocale () { - set_environ (envv); + set_environ (env); -#ifdef USE_XIM +#if USE_XIM if (!locale) - rxvt_warn ("setting locale failed, working without locale support.\n"); + rxvt_warn ("setting locale failed, continuing without locale support.\n"); else { set_string_property (xa[XA_WM_LOCALE_NAME], locale); if (!XSupportsLocale ()) { - rxvt_warn ("the locale is not supported by Xlib, working without locale support.\n"); + rxvt_warn ("the locale is not supported by Xlib, continuing without locale support.\n"); return; } @@ -1071,7 +1128,7 @@ /*----------------------------------------------------------------------*/ void -rxvt_term::get_colours () +rxvt_term::get_colors () { int i; @@ -1079,61 +1136,9 @@ pix_colors = pix_colors_focused; #endif - for (i = 0; i < (depth <= 2 ? 2 : NRS_COLORS); i++) - { - const char *name = rs[Rs_color + i]; - - if (!name) - continue; - - rxvt_color xcol; - - if (!set_color (xcol, name)) - { -#ifndef XTERM_REVERSE_VIDEO - if (i < 2 && option (Opt_reverseVideo)) - name = def_colorName [1 - i]; - else -#endif - name = def_colorName [i]; - - if (!name) - continue; - - if (!set_color (xcol, name)) - { - switch (i) - { - case Color_fg: - case Color_bg: - rxvt_warn ("unable to get foreground/background colour, continuing.\n"); - name = ""; - break; -#ifndef NO_CURSORCOLOR - case Color_cursor2: -#endif - case Color_pointer_fg: - name = rs[Rs_color + Color_fg]; - xcol.set (this, name); - break; - default: - name = rs[Rs_color + Color_bg]; - xcol.set (this, name); - break; - } - } - } - - pix_colors[i] = xcol; - rs[Rs_color + i] = name; - } - - if (depth <= 2) - { - if (!rs[Rs_color + Color_pointer_fg]) alias_color (Color_pointer_fg, Color_fg); - if (!rs[Rs_color + Color_pointer_bg]) alias_color (Color_pointer_bg, Color_bg); - if (!rs[Rs_color + Color_border] ) alias_color (Color_border, Color_fg); - } + for (i = 0; i < NRS_COLORS; i++) + if (const char *name = rs[Rs_color + i]) + set_color (pix_colors [i], name); /* * get scrollBar shadow colors @@ -1142,35 +1147,25 @@ * from the fvwm window manager. */ #ifdef RXVT_SCROLLBAR - if (depth <= 2) - { - /* Monochrome */ - alias_color (Color_scroll, Color_fg); - alias_color (Color_topShadow, Color_bg); - alias_color (Color_bottomShadow, Color_bg); - } - else - { - pix_colors [Color_scroll].fade (this, 50, pix_colors [Color_bottomShadow]); + pix_colors [Color_scroll].fade (this, 50, pix_colors [Color_bottomShadow]); - rgba cscroll; - pix_colors [Color_scroll].get (cscroll); + rgba cscroll; + pix_colors [Color_scroll].get (cscroll); - /* topShadowColor */ - if (!pix_colors[Color_topShadow].set (this, - rgba ( - min ((int)rgba::MAX_CC, max (cscroll.r / 5, cscroll.r) * 7 / 5), - min ((int)rgba::MAX_CC, max (cscroll.g / 5, cscroll.g) * 7 / 5), - min ((int)rgba::MAX_CC, max (cscroll.b / 5, cscroll.b) * 7 / 5), - cscroll.a) - )) - alias_color (Color_topShadow, Color_White); - } + /* topShadowColor */ + if (!pix_colors[Color_topShadow].set (this, + rgba ( + min ((int)rgba::MAX_CC, max (cscroll.r / 5, cscroll.r) * 7 / 5), + min ((int)rgba::MAX_CC, max (cscroll.g / 5, cscroll.g) * 7 / 5), + min ((int)rgba::MAX_CC, max (cscroll.b / 5, cscroll.b) * 7 / 5), + cscroll.a) + )) + alias_color (Color_topShadow, Color_White); #endif #ifdef OFF_FOCUS_FADING - for (i = 0; i < (depth <= 2 ? 2 : NRS_COLORS); i++) - update_fade_color (i); + for (i = 0; i < NRS_COLORS; i++) + update_fade_color (i, true); #endif } @@ -1179,7 +1174,7 @@ void rxvt_term::color_aliases (int idx) { - if (rs[Rs_color + idx] && isdigit (* (rs[Rs_color + idx]))) + if (rs[Rs_color + idx] && isdigit (*rs[Rs_color + idx])) { int i = atoi (rs[Rs_color + idx]); @@ -1229,7 +1224,7 @@ if (kc[k] == 0) break; - switch (XKeycodeToKeysym (dpy, kc[k], 0)) + switch (rxvt_XKeycodeToKeysym (dpy, kc[k], 0)) { case XK_Num_Lock: ModNumLockMask = modmasks[i - 1]; @@ -1284,58 +1279,7 @@ void rxvt_term::set_icon (const char *file) { -#ifdef HAVE_AFTERIMAGE - init_asv (); - - ASImage *im = file2ASImage (file, 0xFFFFFFFF, SCREEN_GAMMA, 0, NULL); - if (!im) - { - rxvt_warn ("Loading image icon failed, continuing without.\n"); - return; - } - - unsigned int w = im->width; - unsigned int h = im->height; - - if (!IN_RANGE_INC (w, 1, 16383) || !IN_RANGE_INC (h, 1, 16383)) - { - rxvt_warn ("Icon image too big, continuing without.\n"); - destroy_asimage (&im); - return; - } - - ASImage *result = scale_asimage (asv, im, - w, h, ASA_ARGB32, - 100, ASIMAGE_QUALITY_DEFAULT); - destroy_asimage (&im); - - if (!result) - { - rxvt_warn ("Icon image transformation to ARGB failed, continuing without.\n"); - return; - } - - long *buffer = (long *)malloc ((2 + w * h) * sizeof (long)); - if (buffer) - { - ARGB32 *asbuf = result->alt.argb32; - buffer [0] = w; - buffer [1] = h; - - for (unsigned int i = 0; i < w * h; ++i) - buffer [i + 2] = asbuf [i]; - - XChangeProperty (dpy, parent, xa[XA_NET_WM_ICON], XA_CARDINAL, 32, - PropModeReplace, (const unsigned char *) buffer, 2 + w * h); - free (buffer); - } - else - rxvt_warn ("Memory allocation for icon hint failed, continuing without.\n"); - - destroy_asimage (&result); -#endif - -#ifdef HAVE_PIXBUF +#if HAVE_PIXBUF && ENABLE_EWMH GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (file, NULL); if (!pixbuf) { @@ -1394,7 +1338,7 @@ } /*----------------------------------------------------------------------*/ -/* rxvt_Create_Windows () - Open and map the window */ +/* Open and map the window */ void rxvt_term::create_windows (int argc, const char *const *argv) { @@ -1410,7 +1354,7 @@ dLocal (Display *, dpy); /* grab colors before netscape does */ - get_colours (); + get_colors (); if (!set_fonts ()) rxvt_fatal ("unable to load base fontset, please specify a valid one using -fn, aborting.\n"); @@ -1450,7 +1394,7 @@ window_calc (0, 0); - /* sub-window placement & size in rxvt_resize_subwindows () */ + /* sub-window placement & size in rxvt_term::resize_all_windows () */ attributes.background_pixel = pix_colors_focused [Color_border]; attributes.border_pixel = pix_colors_focused [Color_border]; attributes.colormap = cmap; @@ -1465,9 +1409,6 @@ this->parent = top; - old_width = szHint.width; - old_height = szHint.height; - set_title (rs [Rs_title]); set_icon_name (rs [Rs_iconName]); @@ -1476,7 +1417,9 @@ wmHint.flags = InputHint | StateHint | WindowGroupHint; wmHint.input = True; - wmHint.initial_state = option (Opt_iconic) ? IconicState : NormalState; + wmHint.initial_state = option (Opt_iconic) ? IconicState + : option (Opt_dockapp) ? WithdrawnState + : NormalState; wmHint.window_group = top; XmbSetWMProperties (dpy, top, NULL, NULL, (char **)argv, argc, @@ -1488,9 +1431,7 @@ */ if (rs [Rs_iconfile]) - { - set_icon (rs [Rs_iconfile]); - } + set_icon (rs [Rs_iconfile]); #endif #if ENABLE_FRILLS @@ -1506,7 +1447,7 @@ #endif }; - XSetWMProtocols (dpy, top, protocols, ARRAY_LENGTH(protocols)); + XSetWMProtocols (dpy, top, protocols, ecb_array_length (protocols)); #if ENABLE_FRILLS if (rs[Rs_transient_for]) @@ -1534,12 +1475,23 @@ termwin_ev.start (display, top); /* vt cursor: Black-on-White is standard, but this is more popular */ - TermWin_cursor = XCreateFontCursor (dpy, XC_xterm); + unsigned int shape = XC_xterm; + +#ifdef HAVE_XMU + if (rs[Rs_pointerShape]) + { + int stmp = XmuCursorNameToIndex (rs[Rs_pointerShape]); + if (stmp >= 0) + shape = stmp; + } +#endif + + TermWin_cursor = XCreateFontCursor (dpy, shape); /* the vt window */ vt = XCreateSimpleWindow (dpy, top, window_vt_x, window_vt_y, - width, height, + vt_width, vt_height, 0, pix_colors_focused[Color_fg], pix_colors_focused[Color_bg]); @@ -1576,7 +1528,7 @@ #endif pointer_unblank (); - scr_recolour (); + scr_recolor (); } /*----------------------------------------------------------------------*/ @@ -1598,7 +1550,7 @@ if (getfd_hook) pty->pty = (*getfd_hook) (pty->pty); - if (pty->pty < 0 || fcntl (pty->pty, F_SETFL, O_NONBLOCK)) + if (pty->pty < 0) rxvt_fatal ("unusable pty-fd filehandle, aborting.\n"); } } @@ -1607,6 +1559,8 @@ if (!pty->get ()) rxvt_fatal ("can't initialize pseudo-tty, aborting.\n"); + fcntl (pty->pty, F_SETFL, O_NONBLOCK); + struct termios tio = def_tio; #ifndef NO_BACKSPACE_KEY @@ -1665,7 +1619,14 @@ default: if (!option (Opt_utmpInhibit)) - pty->login (cmd_pid, option (Opt_loginShell), rs[Rs_display_name]); + { +#ifdef LOG_ONLY_ON_LOGIN + bool login_shell = option (Opt_loginShell); +#else + bool login_shell = true; +#endif + pty->login (cmd_pid, login_shell, rs[Rs_display_name]); + } pty->close_tty (); @@ -1700,8 +1661,10 @@ fd = open (CONSOLE, O_WRONLY, 0); if (fd >= 0) - if (ioctl (fd, SRIOCSREDIR, NULL) < 0) + { + ioctl (fd, SRIOCSREDIR, STDIN_FILENO); close (fd); + } #endif /* SRIOCSREDIR */ }