-}
-
-static void
-control_client_sighandler(int signo)
-{
- control_client_terminate = signo;
-}
-
-static void
-control_client_sigrelay(int signo)
-{
- if (control_server_pid > 1)
- kill(control_server_pid, signo);
-}
-
-static int
-env_permitted(char *env)
-{
- int i;
- char name[1024], *cp;
-
- strlcpy(name, env, sizeof(name));
- if ((cp = strchr(name, '=')) == NULL)
- return (0);
-
- *cp = '\0';
-
- for (i = 0; i < options.num_send_env; i++)
- if (match_pattern(name, options.send_env[i]))
- return (1);
-
- return (0);
-}
-
-static void
-control_client(const char *path)
-{
- struct sockaddr_un addr;
- int i, r, fd, sock, exitval, num_env, addr_len;
- Buffer m;
- char *term;
- extern char **environ;
- u_int flags;
-
- memset(&addr, '\0', sizeof(addr));
- addr.sun_family = AF_UNIX;
- addr_len = offsetof(struct sockaddr_un, sun_path) +
- strlen(path) + 1;
-
- if (strlcpy(addr.sun_path, path,
- sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
- fatal("ControlPath too long");
-
- if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
- fatal("%s socket(): %s", __func__, strerror(errno));
-
- if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1) {
- debug("Couldn't connect to %s: %s", path, strerror(errno));
- close(sock);
- return;
- }
-
- if (stdin_null_flag) {
- if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
- fatal("open(/dev/null): %s", strerror(errno));
- if (dup2(fd, STDIN_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (fd > STDERR_FILENO)
- close(fd);
- }
-
- if ((term = getenv("TERM")) == NULL)
- term = "";
-
- flags = 0;
- if (tty_flag)
- flags |= SSHMUX_FLAG_TTY;
- if (subsystem_flag)
- flags |= SSHMUX_FLAG_SUBSYS;
-
- buffer_init(&m);
-
- /* Send our command to server */
- buffer_put_int(&m, mux_command);
- buffer_put_int(&m, flags);
- if (ssh_msg_send(sock, /* version */1, &m) == -1)
- fatal("%s: msg_send", __func__);
- buffer_clear(&m);
-
- /* Get authorisation status and PID of controlee */
- if (ssh_msg_recv(sock, &m) == -1)
- fatal("%s: msg_recv", __func__);
- if (buffer_get_char(&m) != 1)
- fatal("%s: wrong version", __func__);
- if (buffer_get_int(&m) != 1)
- fatal("Connection to master denied");
- control_server_pid = buffer_get_int(&m);
-
- buffer_clear(&m);
-
- switch (mux_command) {
- case SSHMUX_COMMAND_ALIVE_CHECK:
- fprintf(stderr, "Master running (pid=%d)\r\n",
- control_server_pid);
- exit(0);
- case SSHMUX_COMMAND_TERMINATE:
- fprintf(stderr, "Exit request sent.\r\n");
- exit(0);
- case SSHMUX_COMMAND_OPEN:
- /* continue below */
- break;
- default:
- fatal("silly mux_command %d", mux_command);
- }
-
- /* SSHMUX_COMMAND_OPEN */
- buffer_put_cstring(&m, term);
- buffer_append(&command, "\0", 1);
- buffer_put_cstring(&m, buffer_ptr(&command));
-
- if (options.num_send_env == 0 || environ == NULL) {
- buffer_put_int(&m, 0);
- } else {
- /* Pass environment */
- num_env = 0;
- for (i = 0; environ[i] != NULL; i++)
- if (env_permitted(environ[i]))
- num_env++; /* Count */
-
- buffer_put_int(&m, num_env);
-
- for (i = 0; environ[i] != NULL && num_env >= 0; i++)
- if (env_permitted(environ[i])) {
- num_env--;
- buffer_put_cstring(&m, environ[i]);
- }
- }
-
- if (ssh_msg_send(sock, /* version */1, &m) == -1)
- fatal("%s: msg_send", __func__);
-
- mm_send_fd(sock, STDIN_FILENO);
- mm_send_fd(sock, STDOUT_FILENO);
- mm_send_fd(sock, STDERR_FILENO);
-
- /* Wait for reply, so master has a chance to gather ttymodes */
- buffer_clear(&m);
- if (ssh_msg_recv(sock, &m) == -1)
- fatal("%s: msg_recv", __func__);
- if (buffer_get_char(&m) != 1)
- fatal("%s: wrong version", __func__);
- buffer_free(&m);
-
- signal(SIGHUP, control_client_sighandler);
- signal(SIGINT, control_client_sighandler);
- signal(SIGTERM, control_client_sighandler);
- signal(SIGWINCH, control_client_sigrelay);
-
- if (tty_flag)
- enter_raw_mode();
-
- /* Stick around until the controlee closes the client_fd */
- exitval = 0;
- for (;!control_client_terminate;) {
- r = read(sock, &exitval, sizeof(exitval));
- if (r == 0) {
- debug2("Received EOF from master");
- break;
- }
- if (r > 0)
- debug2("Received exit status from master %d", exitval);
- if (r == -1 && errno != EINTR)
- fatal("%s: read %s", __func__, strerror(errno));
- }
-
- if (control_client_terminate)
- debug2("Exiting on signal %d", control_client_terminate);
-
- close(sock);
-
- leave_raw_mode();
-
- if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
- fprintf(stderr, "Connection to master closed.\r\n");
-
- exit(exitval);