FEATURE: -f -f - fork after successful open of fwd port/display/agent
Nicolas Williams
Nicolas.Williams at ubsw.com
Sat Feb 2 05:10:57 EST 2002
Background
==========
"ssh -f ..." causes ssh to fork into the background when userauth
successfully completes.
WHAT
===
With this patch "ssh -f -f ..." causes ssh to fork into the background
when the first forwarded port/x11 display/agent is successfully opened.
WHY
===
This feature makes launching remote X11 apps more reliable: when ssh
exits it must have exited because the app exited, and you can observe
the error messages / exit status, OR because the app opened the display,
meaning it can now display any future errors.
****
ALSO, "ssh -f -f ..." actually detaches from the tty, and it closes the
session channel correctly.
Please see the forkoff() function added to clientloop.c: it correctly
closes the channel for the SSHv2 session.
Comments?
Nico
--
-DISCLAIMER: an automatically appended disclaimer may follow. By posting-
-to a public e-mail mailing list I hereby grant permission to distribute-
-and copy this message.-
-------------- next part --------------
Index: 3_0_2p1.1/ssh.c
--- 3_0_2p1.1/ssh.c Wed, 21 Nov 2001 10:38:46 -0500
+++ 3_0_2p1_double_dash_f.1/ssh.c Fri, 01 Feb 2002 12:59:13 -0500
@@ -111,6 +111,7 @@
* background.
*/
int fork_after_authentication_flag = 0;
+int wait_for_port_open_before_fork = 0;
/*
* General data structure for command line options and options configurable
@@ -330,6 +331,8 @@
stdin_null_flag = 1;
break;
case 'f':
+ if (fork_after_authentication_flag)
+ wait_for_port_open_before_fork = 1;
fork_after_authentication_flag = 1;
stdin_null_flag = 1;
break;
@@ -1164,7 +1167,7 @@
id = ssh_session2_open();
/* If requested, let ssh continue in the background. */
- if (fork_after_authentication_flag)
+ if (fork_after_authentication_flag && !wait_for_port_open_before_fork)
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
Index: 3_0_2p1.1/clientloop.c
--- 3_0_2p1.1/clientloop.c Wed, 21 Nov 2001 10:38:46 -0500
+++ 3_0_2p1_double_dash_f.1/clientloop.c Fri, 01 Feb 2002 12:59:13 -0500
@@ -95,6 +95,9 @@
*/
extern char *host;
+extern int fork_after_authentication_flag;
+extern int wait_for_port_open_before_fork;
+
/*
* Flag to indicate that we have received a window change signal which has
* not yet been processed. This will cause a message indicating the new
@@ -1007,6 +1010,80 @@
/*********/
+/*
+ * Detach the program (continue to serve connections,
+ * but put in background and no more new connections).
+ */
+static
+void
+forkoff(int stop_listening, int detach)
+{
+ pid_t pid;
+ int fd;
+ Channel *c;
+
+ /* Restore tty modes. */
+ leave_raw_mode();
+
+ /* Stop listening for new connections. */
+ if (stop_listening)
+ channel_stop_listening();
+
+ fprintf(stderr, "Forking off into the background - %s",
+ stop_listening ? "no longer listening" : "still listening");
+
+ /* Fork into background. */
+ pid = fork();
+ if (pid < 0) {
+ error("fork: %.100s", strerror(errno));
+ return;
+ }
+ if (pid != 0) { /* This is the parent. */
+ /* The parent just exits. */
+ exit(0);
+ }
+
+ c = channel_lookup(session_ident);
+ if (c == NULL)
+ error("couldn't lookup session channel");
+
+ /* The child continues serving connections. */
+ /* fake EOF on stdin */
+ if (compat20) {
+ buffer_append(&stdin_buffer, "\004", 1);
+ } else if (!stdin_eof) {
+ /*
+ * Sending SSH_CMSG_EOF alone does not always appear
+ * to be enough. So we try to send an EOF character
+ * first.
+ */
+ packet_start(SSH_CMSG_STDIN_DATA);
+ packet_put_string("\004", 1);
+ packet_send();
+ /* Close stdin. */
+ stdin_eof = 1;
+ if (buffer_len(&stdin_buffer) == 0) {
+ packet_start(SSH_CMSG_EOF);
+ packet_send();
+ }
+ }
+
+ if (detach) {
+ chan_read_failed(c);
+ chan_write_failed(c);
+ channel_close_fds(c);
+ fd = open(_PATH_DEVNULL, O_RDWR, 0);
+ if (fd < 0)
+ return;
+ (void) dup2(fd, STDIN_FILENO);
+ (void) dup2(fd, STDOUT_FILENO);
+ (void) dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ (void) close(fd);
+ (void) setsid();
+ }
+}
+
static void
client_input_stdout_data(int type, int plen, void *ctxt)
{
@@ -1187,6 +1264,8 @@
packet_put_int(c->local_maxpacket);
packet_send();
}
+ if (fork_after_authentication_flag && wait_for_port_open_before_fork)
+ forkoff(0, 1);
} else {
debug("failure %s", ctype);
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
Index: 3_0_2p1.1/channels.h
--- 3_0_2p1.1/channels.h Wed, 21 Nov 2001 10:38:46 -0500
+++ 3_0_2p1_double_dash_f.1/channels.h Fri, 01 Feb 2002 12:59:13 -0500
@@ -153,6 +153,7 @@
void channel_register_filter(int, channel_filter_fn *);
void channel_cancel_cleanup(int);
int channel_close_fd(int *);
+void channel_close_fds(Channel *);
/* protocol handler */
Index: 3_0_2p1.1/channels.c
--- 3_0_2p1.1/channels.c Wed, 21 Nov 2001 10:38:46 -0500
+++ 3_0_2p1_double_dash_f.1/channels.c Fri, 01 Feb 2002 12:59:13 -0500
@@ -301,7 +301,7 @@
/* Close all channel fd/socket. */
-static void
+void
channel_close_fds(Channel *c)
{
debug3("channel_close_fds: channel %d: r %d w %d e %d",
-------------- next part --------------
Visit our website at http://www.ubswarburg.com
This message contains confidential information and is intended only
for the individual named. If you are not the named addressee you
should not disseminate, distribute or copy this e-mail. Please
notify the sender immediately by e-mail if you have received this
e-mail by mistake and delete this e-mail from your system.
E-mail transmission cannot be guaranteed to be secure or error-free
as information could be intercepted, corrupted, lost, destroyed,
arrive late or incomplete, or contain viruses. The sender therefore
does not accept liability for any errors or omissions in the contents
of this message which arise as a result of e-mail transmission. If
verification is required please request a hard-copy version. This
message is provided for informational purposes and should not be
construed as a solicitation or offer to buy or sell any securities or
related financial instruments.
More information about the openssh-unix-dev
mailing list