*** empty log message ***
authorroot <root>
Mon, 23 Jan 2006 12:05:12 +0000 (12:05 +0000)
committerroot <root>
Mon, 23 Jan 2006 12:05:12 +0000 (12:05 +0000)
src/libptytty.h
src/ptytty.C
src/ptytty.h
src/ptytty_conf.h

index b8af01d2fc731a7fca0d0aa3d7f07c1a416c373f..090a5ecd9f21104d952a628bf4e2fc5b3b24c051 100644 (file)
@@ -4,6 +4,10 @@
 #ifndef LIBPTYTTY_H_ /* public libptytty header file */
 #define LIBPTYTTY_H_
 
+#ifdef __cplusplus
+
+// c++ api
+
 struct ptytty {
   int pty; // pty file descriptor; connected to rxvt
   int tty; // tty file descriptor; connected to child
@@ -36,5 +40,26 @@ protected:
   }
 };
 
+#else
+
+// c api
+int ptytty_pty (void *ptytty);
+int ptytty_tty (void *ptytty);
+void ptytty_delete (void *ptytty);
+int ptytty_get (void *ptytty);
+void ptytty_login (void *ptytty, int cmd_pid, bool login_shell, const char *hostname);
+
+void ptytty_close_tty (void *ptytty);
+int ptytty_make_controlling_tty (void *ptytty);
+void ptytty_set_utf8_mode (void *ptytty, int on);
+
+void ptytty_init ();
+void *ptytty_create ();
+
+void ptytty_drop_privileges ();
+void ptytty_use_helper ();
+
+#endif
+
 #endif
 
index b401532ad414886952defb3b8e9d4777a600da8b..03554e043d10d1fe9e8b1f1fa6f6d1c3bf89f338 100644 (file)
@@ -8,7 +8,7 @@
  * All portions of code are copyright by their respective author/s.
  * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
  * Copyright (c) 2004-2006 Marc Lehmann <pcg@goof.com>
- * Copyright (c) 2006 Emanuele Giaquinta <e.giaquinta@glauco.it>
+ * Copyright (c) 2006      Emanuele Giaquinta <e.giaquinta@glauco.it>
  *
  * 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
@@ -31,6 +31,7 @@
 
 #include <cstdlib>
 #include <cstring>
+#include <csignal>
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -373,9 +374,12 @@ ptytty_unix::get ()
   return true;
 }
 
+/////////////////////////////////////////////////////////////////////////////
+// helper/proxy support
+
 #if PTYTTY_HELPER
 
-static int sock_fd = -1;
+static int sock_fd = -1, lock_fd = -1;
 static int helper_pid, owner_pid;
 
 struct command
@@ -404,9 +408,19 @@ struct ptytty_proxy : ptytty
   void login (int cmd_pid, bool login_shell, const char *hostname);
 };
 
+#if PTYTTY_REENTRANT
+# define NEED_TOKEN do { char ch; read  (lock_fd, &ch, 1); } while (0)
+# define GIVE_TOKEN do { char ch; write (lock_fd, &ch, 1); } while (0)
+#else
+# define NEED_TOKEN (void)0
+# define GIVE_TOKEN (void)0
+#endif
+
 bool
 ptytty_proxy::get ()
 {
+  NEED_TOKEN;
+
   command cmd;
 
   cmd.type = command::get;
@@ -417,18 +431,24 @@ ptytty_proxy::get ()
     ptytty_fatal ("protocol error while creating pty using helper process, aborting.\n");
 
   if (!id)
-    return false;
+    {
+      GIVE_TOKEN;
+      return false;
+    }
 
   if ((pty = recv_fd (sock_fd)) < 0
       || (tty = recv_fd (sock_fd)) < 0)
     ptytty_fatal ("protocol error while reading pty/tty fds from helper process, aborting.\n");
 
+  GIVE_TOKEN;
   return true;
 }
 
 void
 ptytty_proxy::login (int cmd_pid, bool login_shell, const char *hostname)
 {
+  NEED_TOKEN;
+
   command cmd;
 
   cmd.type = command::login;
@@ -438,18 +458,24 @@ ptytty_proxy::login (int cmd_pid, bool login_shell, const char *hostname)
   strncpy (cmd.hostname, hostname, sizeof (cmd.hostname));
 
   write (sock_fd, &cmd, sizeof (cmd));
+
+  GIVE_TOKEN;
 }
 
 ptytty_proxy::~ptytty_proxy ()
 {
   if (id)
     {
+      NEED_TOKEN;
+
       command cmd;
 
       cmd.type = command::destroy;
       cmd.id = id;
 
       write (sock_fd, &cmd, sizeof (cmd));
+
+      GIVE_TOKEN;
     }
 }
 
@@ -459,8 +485,13 @@ void serve ()
   command cmd;
   vector<ptytty *> ptys;
 
-  while (read (sock_fd, &cmd, sizeof (command)) == sizeof (command))
+  for (;;)
     {
+      GIVE_TOKEN;
+
+      if (read (sock_fd, &cmd, sizeof (command)) != sizeof (command))
+        break;
+
       if (cmd.type == command::get)
         {
           // -> id ptyfd ttyfd
@@ -484,7 +515,7 @@ void serve ()
       else if (cmd.type == command::login)
         {
 #if UTMP_SUPPORT
-          if (find (ptys.begin (), ptys.end (), cmd.id))
+          if (find (ptys.begin (), ptys.end (), cmd.id) != ptys.end ())
             {
               cmd.hostname[sizeof (cmd.hostname) - 1] = 0;
               cmd.id->login (cmd.cmd_pid, cmd.login_shell, cmd.hostname);
@@ -503,6 +534,8 @@ void serve ()
         }
       else
         break;
+
+      NEED_TOKEN;
     }
 
   // destroy all ptys
@@ -513,18 +546,33 @@ void serve ()
 void
 ptytty::use_helper ()
 {
+#ifndef PTYTTY_NO_PID_CHECK
   int pid = getpid ();
+#endif
 
-  if (sock_fd >= 0 && pid == owner_pid)
+  if (sock_fd >= 0
+#ifndef PTYTTY_NO_PID_CHECK
+      && pid == owner_pid
+#endif
+      )
     return;
 
+#ifndef PTYTTY_NO_PID_CHECK
   owner_pid = pid;
+#endif
 
   int sv[2];
 
   if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
     ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n");
 
+#ifdef PTYTTY_REENTRANT
+  int lv[2];
+
+  if (socketpair (AF_UNIX, SOCK_STREAM, 0, lv))
+    ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n");
+#endif
+
   helper_pid = fork ();
 
   if (helper_pid < 0)
@@ -536,16 +584,29 @@ ptytty::use_helper ()
       sock_fd = sv[0];
       close (sv[1]);
       fcntl (sock_fd, F_SETFD, FD_CLOEXEC);
+#ifdef PTYTTY_REENTRANT
+      lock_fd = lv[0];
+      close (lv[1]);
+      fcntl (lock_fd, F_SETFD, FD_CLOEXEC);
+#endif
     }
   else
     {
       // server, pty-helper
       sock_fd = sv[1];
+#ifdef PTYTTY_REENTRANT
+      lock_fd = lv[1];
+#endif
 
       chdir ("/");
 
+      signal (SIGHUP,  SIG_IGN);
+      signal (SIGTERM, SIG_IGN);
+      signal (SIGINT,  SIG_IGN);
+      signal (SIGPIPE, SIG_IGN);
+
       for (int fd = 0; fd < 1023; fd++)
-        if (fd != sock_fd)
+        if (fd != sock_fd && fd != lock_fd)
           close (fd);
 
       serve ();
@@ -559,7 +620,11 @@ ptytty *
 ptytty::create ()
 {
 #if PTYTTY_HELPER
-  if (helper_pid && getpid () == owner_pid)
+  if (helper_pid
+# ifndef PTYTTY_NO_PID_CHECK
+      && getpid () == owner_pid
+# endif
+      )
     // use helper process
     return new ptytty_proxy;
   else
@@ -611,3 +676,39 @@ ptytty::drop_privileges ()
     ptytty_fatal ("unable to drop privileges, aborting.\n");
 }
 
+/////////////////////////////////////////////////////////////////////////////
+// C API
+
+#ifndef PTYTTY_NO_C_API
+
+#define DEFINE_METHOD(retval, name, args1, args2) \
+extern "C" retval ptytty_ ## name args1           \
+{ return ((struct ptytty *)ptytty)->name args2; }
+
+DEFINE_METHOD(int,pty,(void *ptytty),)
+DEFINE_METHOD(int,tty,(void *ptytty),)
+DEFINE_METHOD(int,get,(void *ptytty),())
+DEFINE_METHOD(void,login,(void *ptytty, int cmd_pid, bool login_shell, const char *hostname),(cmd_pid,login_shell,hostname))
+
+DEFINE_METHOD(void,close_tty,(void *ptytty),())
+DEFINE_METHOD(int,make_controlling_tty,(void *ptytty),())
+DEFINE_METHOD(void,set_utf8_mode,(void *ptytty, int on),(on))
+
+#define DEFINE_STATIC(retval, name, args) \
+extern "C" retval ptytty_ ## name args           \
+{ return ptytty::name args; }
+
+DEFINE_STATIC(void,drop_privileges,())
+DEFINE_STATIC(void,use_helper,())
+DEFINE_STATIC(void,init,())
+
+DEFINE_STATIC(void *,create,())
+
+void ptytty_delete (void *ptytty)
+{
+  delete (struct ptytty *)ptytty;
+}
+
+// send_fd, recv_fd not exposed
+
+#endif
index 651e32220270cb22eea473aacc81ce727f21ef4a..85a979aed57a5b85b29dd9c0e90b835b6f251678 100644 (file)
@@ -7,6 +7,10 @@
 #include "libptytty.h"
 #include "ptytty_conf.h"
 
+#if PTYTTY_REENTRANT
+# define PTYTTY_NO_PID_CHECK 1
+#endif
+
 #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY) || defined(UNIX98_PTY)
 # define NO_SETOWNER_TTYDEV 1
 #endif
index e74c9f97d60718640d287ade8a011f1321c90219..2f83dc5453b6ea0805c72cc028163475bc90a4c7 100644 (file)
@@ -3,3 +3,7 @@
 
 #define ptytty_fatal rxvt_fatal
 #define ptytty_warn  rxvt_warn
+
+#define PTYTTY_REENTRANT 1
+#define PTYTTY_NO_PID_CHECK 1
+