*** empty log message ***
[dana/urxvt.git] / src / main.C
index a61dbe1..e08736b 100644 (file)
@@ -13,7 +13,7 @@
  * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
  * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
  *                              - extensive modifications
- * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com>
+ * Copyright (c) 2003-2006 Marc Lehmann <pcg@goof.com>
  *
  * 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
@@ -63,7 +63,7 @@ rxvt_set_locale (const char *locale)
   return true;
 }
 
-bool
+void
 rxvt_push_locale (const char *locale)
 {
   strcpy (savelocale, curlocale);
@@ -148,9 +148,6 @@ rxvt_term::rxvt_term ()
 #ifdef HAVE_SCROLLBARS
     scrollbar_ev (this, &rxvt_term::x_cb),
 #endif
-#ifdef MENUBAR
-    menubar_ev (this, &rxvt_term::x_cb),
-#endif
 #ifdef CURSOR_BLINK
     cursor_blink_ev (this, &rxvt_term::cursor_blink_cb),
 #endif
@@ -199,16 +196,12 @@ void rxvt_term::emergency_cleanup ()
   if (cmd_pid)
     kill (-cmd_pid, SIGHUP);
 
-#ifdef UTMP_SUPPORT
-  privileged_utmp (RESTORE);
-#endif
-
-  pty.put ();
+  delete pty; pty = 0;
 }
 
 rxvt_term::~rxvt_term ()
 {
-  PERL_INVOKE ((this, HOOK_DESTROY, DT_END));
+  HOOK_INVOKE ((this, HOOK_DESTROY, DT_END));
 
   termlist.erase (find (termlist.begin (), termlist.end(), this));
 
@@ -230,9 +223,6 @@ rxvt_term::~rxvt_term ()
 #ifdef USE_XIM
       im_destroy ();
 #endif
-#ifdef MENUBAR
-      if (menubarGC)    XFreeGC (disp, menubarGC);
-#endif
 #ifdef XTERM_SCROLLBAR
       if (xscrollbarGC) XFreeGC (disp, xscrollbarGC);
       if (ShadowGC)     XFreeGC (disp, ShadowGC);
@@ -252,18 +242,13 @@ rxvt_term::~rxvt_term ()
       if (upArrowHi)    XFreePixmap (disp, upArrowHi);
       if (downArrowHi)  XFreePixmap (disp, downArrowHi);
 #endif
-#if defined(MENUBAR) || defined(RXVT_SCROLLBAR)
+#ifdef RXVT_SCROLLBAR
       if (topShadowGC)  XFreeGC (disp, topShadowGC);
       if (botShadowGC)  XFreeGC (disp, botShadowGC);
       if (scrollbarGC)  XFreeGC (disp, scrollbarGC);
 #endif
       if (gc)   XFreeGC (disp, gc);
 
-#if defined(MENUBAR) && (MENUBAR_MAX > 1)
-      delete menuBar.drawable;
-      //if (menuBar.win)
-      //  XDestroyWindow (disp, menuBar.win);
-#endif
       delete drawable;
       // destroy all windows
       if (parent[0])
@@ -271,7 +256,6 @@ rxvt_term::~rxvt_term ()
     }
 
   // TODO: free pixcolours, colours should become part of rxvt_display
-
   delete pix_colors_focused;
 #if OFF_FOCUS_FADING
   delete pix_colors_unfocused;
@@ -330,9 +314,6 @@ rxvt_term::destroy ()
 #if HAVE_SCROLLBARS
       scrollbar_ev.stop (display);
 #endif
-#if MENUBAR
-      menubar_ev.stop (display);
-#endif
 #if TRANSPARENT
       rootwin_ev.stop (display);
 #endif
@@ -365,7 +346,7 @@ rxvt_term::destroy ()
 void
 rxvt_term::destroy_cb (time_watcher &w)
 {
-  SET_R (this);
+  make_current ();
 
   delete this;
 }
@@ -466,8 +447,8 @@ bool
 rxvt_term::init (int argc, const char *const *argv)
 {
   SET_R (this);
-
   set_locale ("");
+  set_environ (envv); // few things in X do not call setlocale :(
 
   if (!init_vars ())
     return false;
@@ -480,19 +461,25 @@ rxvt_term::init (int argc, const char *const *argv)
   keyboard->register_done ();
 #endif
 
-#if MENUBAR_MAX
-  menubar_read (rs[Rs_menu]);
-#endif
 #ifdef HAVE_SCROLLBARS
   if (OPTION (Opt_scrollBar))
     scrollBar.setIdle ();    /* set existence for size calculations */
 #endif
 
 #if ENABLE_PERL
-  rxvt_perl.init ();
+  if (!rs[Rs_perl_ext_1])
+    rs[Rs_perl_ext_1] = "default";
+
+  if ((rs[Rs_perl_ext_1] && *rs[Rs_perl_ext_1])
+      || (rs[Rs_perl_ext_2] && *rs[Rs_perl_ext_2])
+      || (rs[Rs_perl_eval] && *rs[Rs_perl_eval]))
+    {
+      rxvt_perl.init (this);
+      HOOK_INVOKE ((this, HOOK_INIT, DT_END));
+    }
 #endif
 
-  PERL_INVOKE ((this, HOOK_INIT, DT_END));
+  pty = rxvt_new_ptytty ();
 
   create_windows (argc, argv);
 
@@ -500,7 +487,7 @@ rxvt_term::init (int argc, const char *const *argv)
 
   init_xlocale ();
 
-  scr_reset ();         /* initialize screen */
+  scr_reset (); // initialize screen
 
 #if 0
   XSynchronize (disp, True);
@@ -510,10 +497,6 @@ rxvt_term::init (int argc, const char *const *argv)
   if (OPTION (Opt_scrollBar))
     resize_scrollbar ();      /* create and map scrollbar */
 #endif
-#if (MENUBAR_MAX)
-  if (menubar_visible ())
-    XMapWindow (disp, menuBar.win);
-#endif
 #ifdef TRANSPARENT
   if (OPTION (Opt_transparent))
     {
@@ -532,11 +515,12 @@ rxvt_term::init (int argc, const char *const *argv)
 
   free (cmd_argv);
 
-  pty_ev.start (pty.pty, EVENT_READ);
+  if (pty->pty >= 0)
+    pty_ev.start (pty->pty, EVENT_READ);
 
   check_ev.start ();
 
-  PERL_INVOKE ((this, HOOK_START, DT_END));
+  HOOK_INVOKE ((this, HOOK_START, DT_END));
 
   return true;
 }
@@ -581,18 +565,43 @@ static struct sig_handlers
   }
 } sig_handlers;
 
+char **rxvt_environ; // startup environment
+
 void
 rxvt_init ()
 {
-  /*
-   * Save and then give up any super-user privileges
-   * If we need privileges in any area then we must specifically request it.
-   * We should only need to be root in these cases:
-   *  1.  write utmp entries on some systems
-   *  2.  chown tty on some systems
-   */
-  rxvt_privileges (SAVE);
-  rxvt_privileges (IGNORE);
+  uid_t uid = getuid ();
+  gid_t gid = getgid ();
+      
+  // before doing anything else, check for setuid/setgid operation,
+  // start the helper process and drop privileges
+  if (uid != geteuid ()
+      || gid != getegid ())
+    {
+#if PTYTTY_HELPER
+      rxvt_ptytty_server ();
+#else
+      rxvt_warn ("running setuid/setgid without pty helper compiled in, continuing unprivileged.\n");
+#endif
+
+      // drop privileges
+#if HAVE_SETRESUID
+      setresgid (gid, gid, gid);
+      setresuid (uid, uid, uid);
+#elif HAVE_SETREUID
+      setregid (gid, gid);
+      setreuid (uid, uid);
+#elif HAVE_SETUID
+      setgid (gid);
+      setuid (uid);
+#endif
+
+      if (uid != geteuid ()
+          || gid != getegid ())
+        rxvt_fatal ("unable to drop privileges, aborting.\n");
+    }
+
+  rxvt_environ = environ;
 
   signal (SIGHUP,  SIG_IGN);
   signal (SIGPIPE, SIG_IGN);
@@ -607,6 +616,8 @@ rxvt_init ()
   old_xerror_handler = XSetErrorHandler ((XErrorHandler) rxvt_xerror_handler);
   // TODO: handle this with exceptions and tolerate the memory loss
   XSetIOErrorHandler (rxvt_xioerror_handler);
+
+  XrmInitialize ();
 }
 
 /* ------------------------------------------------------------------------- *
@@ -645,80 +656,6 @@ rxvt_realloc (void *ptr, size_t size)
   return p;
 }
 
-/* ------------------------------------------------------------------------- *
- *                            PRIVILEGED OPERATIONS                          *
- * ------------------------------------------------------------------------- */
-/* take care of suid/sgid super-user (root) privileges */
-void
-rxvt_privileges (rxvt_privaction action)
-{
-#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__)
-  static uid_t euid;
-  static gid_t egid;
-#endif
-
-#if ! defined(__CYGWIN32__)
-# if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
-  /* setreuid () is the poor man's setuid (), seteuid () */
-#  define seteuid(a)    setreuid(-1, (a))
-#  define setegid(a)    setregid(-1, (a))
-#  define HAVE_SETEUID
-# endif
-# ifdef HAVE_SETEUID
-  switch (action)
-    {
-      case IGNORE:
-        /*
-         * change effective uid/gid - not real uid/gid - so we can switch
-         * back to root later, as required
-         */
-        seteuid (getuid ());
-        setegid (getgid ());
-        break;
-      case SAVE:
-        euid = geteuid ();
-        egid = getegid ();
-        break;
-      case RESTORE:
-        seteuid (euid);
-        setegid (egid);
-        break;
-    }
-# else
-  switch (action)
-    {
-      case IGNORE:
-        setuid (getuid ());
-        setgid (getgid ());
-        /* FALLTHROUGH */
-      case SAVE:
-        /* FALLTHROUGH */
-      case RESTORE:
-        break;
-    }
-# endif
-#endif
-}
-
-#ifdef UTMP_SUPPORT
-void
-rxvt_term::privileged_utmp (rxvt_privaction action)
-{
-  if (OPTION (Opt_utmpInhibit)
-      || !pty.name || !*pty.name)
-    return;
-
-  rxvt_privileges (RESTORE);
-
-  if (action == SAVE)
-    makeutent (pty.name, rs[Rs_display_name]);
-  else
-    cleanutent ();
-
-  rxvt_privileges (IGNORE);
-}
-#endif
-
 /*----------------------------------------------------------------------*/
 /*
  * window size/position calculcations for XSizeHint and other storage.
@@ -728,7 +665,7 @@ void
 rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
 {
   short recalc_x, recalc_y;
-  int x, y, sb_w, mb_h, flags;
+  int x, y, sb_w, flags;
   unsigned int w, h;
   unsigned int max_width, max_height;
   dDisp;
@@ -799,10 +736,10 @@ rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
 
   szHint.base_width = szHint.base_height = 2 * int_bwidth;
 
-  sb_w = mb_h = 0;
+  sb_w = 0;
   window_vt_x = window_vt_y = int_bwidth;
 
-  if (scrollbar_visible ())
+  if (scrollBar.state)
     {
       sb_w = scrollbar_TotalWidth ();
       szHint.base_width += sb_w;
@@ -810,13 +747,6 @@ rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
         window_vt_x += sb_w;
     }
 
-  if (menubar_visible ())
-    {
-      mb_h = menuBar_TotalHeight ();
-      szHint.base_height += mb_h;
-      window_vt_y += mb_h;
-    }
-
   szHint.width_inc = fwidth;
   szHint.height_inc = fheight;
   szHint.min_width = szHint.base_width + szHint.width_inc;
@@ -844,7 +774,7 @@ rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
       szHint.height = szHint.base_height + height;
     }
 
-  if (scrollbar_visible () && OPTION (Opt_scrollBar_right))
+  if (scrollBar.state && OPTION (Opt_scrollBar_right))
     window_sb_x = szHint.width - sb_w;
 
   if (recalc_x)
@@ -868,7 +798,7 @@ rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
 void
 rxvt_term::tt_winch ()
 {
-  if (pty.pty < 0)
+  if (pty->pty < 0)
     return;
 
   struct winsize ws;
@@ -877,7 +807,7 @@ rxvt_term::tt_winch ()
   ws.ws_row = nrow;
   ws.ws_xpixel = width;
   ws.ws_ypixel = height;
-  (void)ioctl (pty.pty, TIOCSWINSZ, &ws);
+  (void)ioctl (pty->pty, TIOCSWINSZ, &ws);
 
 #if 0
   // TIOCSWINSZ⎈ is supposed to do this automatically and correctly
@@ -923,7 +853,7 @@ rxvt_term::set_fonts ()
 
   fwidth  = prop.width;
   fheight = prop.height;
-  fbase   = (*fs)[1]->ascent;
+  fbase   = prop.ascent;
 
   for (int style = 1; style < 4; style++)
     {
@@ -1024,11 +954,9 @@ rxvt_term::set_window_color (int idx, const char *color)
       if (i >= 8 && i <= 15)
         {        /* bright colors */
           i -= 8;
-# ifndef NO_BRIGHTCOLOR
           pix_colors_focused[idx] = pix_colors_focused[minBrightCOLOR + i];
           SET_PIXCOLOR (idx);
           goto done;
-# endif
         }
 
       if (i >= 0 && i <= 7)
@@ -1211,7 +1139,7 @@ rxvt_term::resize_all_windows (unsigned int newwidth, unsigned int newheight, in
 
   if (fix_screen || newwidth != old_width || newheight != old_height)
     {
-      if (scrollbar_visible ())
+      if (scrollBar.state)
         {
           XMoveResizeWindow (disp, scrollBar.win,
                              window_sb_x, 0,
@@ -1219,14 +1147,9 @@ rxvt_term::resize_all_windows (unsigned int newwidth, unsigned int newheight, in
           resize_scrollbar ();
         }
 
-      if (menubar_visible ())
-        XMoveResizeWindow (disp, menuBar.win,
-                           window_vt_x, 0,
-                           TermWin_TotalWidth (), menuBar_TotalHeight ());
-
       XMoveResizeWindow (disp, vt,
                          window_vt_x, window_vt_y,
-                         TermWin_TotalWidth (), TermWin_TotalHeight ());
+                         width, height);
 
       scr_clear ();
 #ifdef XPM_BACKGROUND
@@ -1417,6 +1340,8 @@ rxvt_term::IM_get_IC (const char *modifiers)
   char **s;
   XIMStyles *xim_styles;
 
+  set_environ (envv);
+
   if (! ((p = XSetLocaleModifiers (modifiers)) && *p))
     return false;
 
@@ -1591,7 +1516,7 @@ rxvt_term::im_cb ()
   char **s;
   char buf[IMBUFSIZ];
 
-  SET_R (this);
+  make_current ();
 
   im_destroy ();