commit-inetutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Inetutils branch, master, updated. inetutils-1_9_1_100-15-g17


From: Mats Erik Andersson
Subject: [SCM] GNU Inetutils branch, master, updated. inetutils-1_9_1_100-15-g17518fb
Date: Thu, 28 Nov 2013 19:25:58 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Inetutils ".

The branch, master has been updated
       via  17518fbec9610f2ac9d2c576774917e419d7e4a5 (commit)
      from  fa0085314a98c2acce9a5a99116f829c4a46f742 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=17518fbec9610f2ac9d2c576774917e419d7e4a5


commit 17518fbec9610f2ac9d2c576774917e419d7e4a5
Author: Mats Erik Andersson <address@hidden>
Date:   Thu Nov 28 19:25:55 2013 +0100

    rlogind, telnet, telnetd: Modify exit status.
    
    As a side effect, a race condition is now avoided,
    while `rlogind' is tearing down pseudo-terminal pairs.

diff --git a/ChangeLog b/ChangeLog
index f03aa11..4e8b94a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,36 @@
+2013-11-28  Mats Erik Andersson  <address@hidden>
+
+       rlogind, telnet, telnetd: Modify exit status.
+
+       * src/rlogind.c (rlogind_mainloop): Delay cleanup()
+       call until libshishi has torn down its structures.
+       (cleanup): New variable STATUS.  If `signo' is SIGCHLD,
+       call waitpid() to reap the waiting child process and
+       use its return status for the whole server's status.
+       Waiting for the child resolves a race condition when
+       tearing down the pseudo-terminal pair, since the slave
+       now is gone when the master side is being closed down.
+
+       * telnet/commands.c (tn): Use exit status 0 when setjmp()
+       manages to execute telnet().  Otherwise, keep 1.
+       (command) [unix || __unix || __unix__]: Enclose the
+       complete else-block within preprocessor conditionals.
+
+       * telnetd/pty.c (cleanup): Let STATUS have full scope
+       in this function, and use it for exit().  Execute waitpid()
+       only if `sig' is SIGCHLD, and update STATUS for later use.
+       On SIGHUP, set STATUS to success, which happens only at
+       reception of TELOPT_LOGOUT from client.
+       * telnetd/state.c (dooption) <TELOPT_LOGOUT>: Call cleanup()
+       with argument SIGHUP, since the client willingly leaves off.
+
 2013-11-24  Mats Erik Andersson  <address@hidden>
 
        inetd: Ensure successful daemon mode.
 
        * src/inetd.c (main) <!debug>: Abort with a syslog message,
        should daemon() return unsuccessfully.
-       * libinetutils/damon.c (waitdaemon): Return with failure,
+       * libinetutils/daemon.c (waitdaemon): Return with failure,
        should chdir("/") fail.
 
 
diff --git a/src/rlogind.c b/src/rlogind.c
index 409a929..d279f71 100644
--- a/src/rlogind.c
+++ b/src/rlogind.c
@@ -618,7 +618,7 @@ main (int argc, char *argv[])
   else
     exit (rlogind_mainloop (fileno (stdin), fileno (stdout)));
 
-  return 0;
+  return 0;            /* Not reachable.  */
 }
 
 /* Create a listening socket for the indicated
@@ -852,6 +852,7 @@ rlogin_daemon (int maxchildren, int port)
          close (fd);
        }
     }
+  /* NOT REACHED */
 }
 
 int
@@ -1266,7 +1267,6 @@ rlogind_mainloop (int infd, int outfd)
   setsig (SIGCHLD, cleanup);
   protocol (infd, master, &auth_data);
   setsig (SIGCHLD, SIG_IGN);
-  cleanup (0);
 
 #ifdef SHISHI
   if (kerberos)
@@ -1288,6 +1288,9 @@ rlogind_mainloop (int infd, int outfd)
     }
 #endif /* SHISHI */
 
+  cleanup (0);
+  /* NOT REACHED */
+
   return 0;
 }
 
@@ -2063,10 +2066,18 @@ control (int pty, char *cp, size_t n)
 }
 
 void
-cleanup (int signo _GL_UNUSED_PARAMETER)
+cleanup (int signo)
 {
+  int status = EXIT_FAILURE;
   char *p;
 
+  if (signo == SIGCHLD)
+    {
+      (void) waitpid ((pid_t) -1, &status, WNOHANG);
+
+      status = WEXITSTATUS (status);
+    }
+
   p = line + sizeof (PATH_TTY_PFX) - 1;
 #if !defined HAVE_LOGOUT || !defined HAVE_LOGWTMP
   utmp_logout (p);
@@ -2082,7 +2093,7 @@ cleanup (int signo _GL_UNUSED_PARAMETER)
   chown (line, 0, 0);
 #endif
   shutdown (netf, 2);
-  exit (EXIT_FAILURE);
+  exit (status);
 }
 
 int
diff --git a/telnet/commands.c b/telnet/commands.c
index 25ed235..dd30b5a 100644
--- a/telnet/commands.c
+++ b/telnet/commands.c
@@ -2814,11 +2814,15 @@ tn (int argc, char *argv[])
       env_export ("USER");
     }
   call (status, "status", "notmuch", 0);
+  err = 0;
   if (setjmp (peerdied) == 0)
     telnet (user);
+  else
+    err = 1;
 
   close (net);
-  ExitString ("Connection closed by foreign host.\n", 1);
+  ExitString ("Connection closed by foreign host.\n", err);
+  /* NOT REACHED */
   return 0;
 }
 
@@ -2942,14 +2946,14 @@ command (int top, char *tbuf, int cnt)
   if (!top)
     {
       putchar ('\n');
-#if defined unix || defined __unix || defined __unix__
     }
+#if defined unix || defined __unix || defined __unix__
   else
     {
       signal (SIGINT, SIG_DFL);
       signal (SIGQUIT, SIG_DFL);
-#endif /* unix || __unix || __unix__ */
     }
+#endif /* unix || __unix || __unix__ */
   for (;;)
     {
       if (rlogin == _POSIX_VDISABLE)
diff --git a/telnet/main.c b/telnet/main.c
index 419462a..765144a 100644
--- a/telnet/main.c
+++ b/telnet/main.c
@@ -371,6 +371,8 @@ main (int argc, char *argv[])
 
   if (argc)
     {
+      /* The command line contains at least one argument.
+       */
       char *args[8], **argp = args;
 
       if (argc > 2)
@@ -393,11 +395,14 @@ main (int argc, char *argv[])
 
       if (setjmp (toplevel) != 0)
        Exit (0);
-      if (tn (argp - args, args) == 1)
+      if (tn (argp - args, args) == 1) /* Returns only on error.  */
        return (0);
       else
        return (1);
+      /* NOT REACHED */
     }
+
+  /* Built-in parser loop; sub-commands jump to `toplevel' mark.  */
   setjmp (toplevel);
   for (;;)
     {
@@ -408,4 +413,5 @@ main (int argc, char *argv[])
 #endif
        command (1, 0, 0);
     }
+  /* NOT REACHED */
 }
diff --git a/telnetd/pty.c b/telnetd/pty.c
index 58bf4e2..21b0b69 100644
--- a/telnetd/pty.c
+++ b/telnetd/pty.c
@@ -136,23 +136,35 @@ start_login (char *host, int autologin, char *name)
   fatalperror (net, cmd);
 }
 
+/* SIG is generally naught every time the server itself
+ * decides to close the connection out of an error condition.
+ * In response to TELOPT_LOGOUT from the client, SIG is set
+ * to SIGHUP, so we consider the exit as a success.  In other
+ * cases, when the forked client process is caught exiting,
+ * then SIG will be SIGCHLD.  Then we deliver the clients's
+ * reported exit code.
+ */
 void
 cleanup (int sig)
 {
+  int status = EXIT_FAILURE;
   char *p;
 
-  if (sig)
+  if (sig == SIGCHLD)
     {
-      int status;
       pid_t pid = waitpid ((pid_t) - 1, &status, WNOHANG);
       syslog (LOG_INFO, "child process %ld exited: %d",
              (long) pid, WEXITSTATUS (status));
+
+      status = WEXITSTATUS (status);
     }
+  else if (sig == SIGHUP)
+    status = EXIT_SUCCESS;     /* Response to TELOPT_LOGOUT.  */
 
   p = line + sizeof (PATH_TTY_PFX) - 1;
   utmp_logout (p);
   chmod (line, 0644);
   chown (line, 0, 0);
   shutdown (net, 2);
-  exit (EXIT_FAILURE);
+  exit (status);
 }
diff --git a/telnetd/state.c b/telnetd/state.c
index 81dd9d7..6878c3d 100644
--- a/telnetd/state.c
+++ b/telnetd/state.c
@@ -1000,7 +1000,7 @@ dooption (int option)
          send_will (TELOPT_LOGOUT, 0);
          set_my_state_will (TELOPT_LOGOUT);
          netflush ();
-         cleanup (0);
+         cleanup (SIGHUP);
          /* NOT REACHED */
          break;
 
diff --git a/telnetd/telnetd.c b/telnetd/telnetd.c
index 30e2f3b..cf7ce0f 100644
--- a/telnetd/telnetd.c
+++ b/telnetd/telnetd.c
@@ -221,7 +221,7 @@ main (int argc, char **argv)
     error (EXIT_FAILURE, 0, "junk arguments in the command line");
 
   telnetd_setup (0);
-  return telnetd_run ();
+  return telnetd_run ();       /* Never returning.  */
 }
 
 void
@@ -719,7 +719,9 @@ telnetd_run (void)
       if (FD_ISSET (pty, &obits) && pty_output_level () > 0)
        ptyflush ();
     }
+
   cleanup (0);
+  /* NOT REACHED */
 
   return 0;
 }
diff --git a/telnetd/utility.c b/telnetd/utility.c
index 5fb31b9..5703f1e 100644
--- a/telnetd/utility.c
+++ b/telnetd/utility.c
@@ -274,6 +274,7 @@ net_read (void)
     {
       syslog (LOG_INFO, "telnetd:  peer died");
       cleanup (0);
+      /* NOT REACHED */
     }
   else if (ncc > 0)
     {
@@ -338,6 +339,7 @@ ptyflush (void)
       if (errno == EWOULDBLOCK || errno == EINTR)
        return;
       cleanup (0);
+      /* NOT REACHED */
     }
 
   pbackp += n;
@@ -615,6 +617,7 @@ netflush (void)
       if (errno == EWOULDBLOCK || errno == EINTR)
        return;
       cleanup (0);
+      /* NOT REACHED */
     }
 
   nbackp += n;

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog         |   28 +++++++++++++++++++++++++++-
 src/rlogind.c     |   19 +++++++++++++++----
 telnet/commands.c |   10 +++++++---
 telnet/main.c     |    8 +++++++-
 telnetd/pty.c     |   18 +++++++++++++++---
 telnetd/state.c   |    2 +-
 telnetd/telnetd.c |    4 +++-
 telnetd/utility.c |    3 +++
 8 files changed, 78 insertions(+), 14 deletions(-)


hooks/post-receive
-- 
GNU Inetutils 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]