Use PTYs and support interactive SSH sessions (with bugs)
Change-Id: If8cc0905ee0e968fe01b6dff6e1be55b1a65e15e
diff --git a/fuchsia/fuchsia-compat.c b/fuchsia/fuchsia-compat.c
index e126723..5d5356a 100644
--- a/fuchsia/fuchsia-compat.c
+++ b/fuchsia/fuchsia-compat.c
@@ -118,8 +118,16 @@
launchpad_set_args(lp, argc, argv);
launchpad_clone(lp, LP_CLONE_MXIO_ROOT|LP_CLONE_MXIO_CWD);
// TODO: set up environment
- launchpad_transfer_fd(lp, in, STDIN_FILENO);
- launchpad_transfer_fd(lp, out, STDOUT_FILENO);
+ if (in == out) {
+ launchpad_clone_fd(lp, in, STDIN_FILENO);
+ } else {
+ launchpad_transfer_fd(lp, in, STDIN_FILENO);
+ }
+ if (out == err) {
+ launchpad_clone_fd(lp, out, STDOUT_FILENO);
+ } else {
+ launchpad_transfer_fd(lp, out, STDOUT_FILENO);
+ }
launchpad_transfer_fd(lp, err, STDERR_FILENO);
mx_handle_t proc = 0;
diff --git a/fuchsia/sshd_config b/fuchsia/sshd_config
index d8b664b..878ad04 100644
--- a/fuchsia/sshd_config
+++ b/fuchsia/sshd_config
@@ -88,7 +88,7 @@
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
-PermitTTY no
+#PermitTTY no
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
diff --git a/session.c b/session.c
index 19b25f2..627f214 100644
--- a/session.c
+++ b/session.c
@@ -529,6 +529,10 @@
return -1;
}
+#ifdef __Fuchsia__
+ pid = fuchsia_launch_child(command, ttyfd, ttyfd, ttyfd);
+
+#else
/* Fork the child. */
switch ((pid = fork())) {
case -1:
@@ -588,6 +592,8 @@
cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
#endif
+#endif // __Fuchsia__
+
s->pid = pid;
/* Parent. Close the slave side of the pseudo tty. */
diff --git a/sshpty.c b/sshpty.c
index fe2fb5a..a5f8f34 100644
--- a/sshpty.c
+++ b/sshpty.c
@@ -53,6 +53,10 @@
# endif
#endif
+#ifdef __Fuchsia__
+#include <magenta/device/pty.h>
+#endif // __Fuchsia__
+
/*
* Allocates and opens a pty. Returns 0 if no pty could be allocated, or
* nonzero if a pty was successfully allocated. On success, open file
@@ -63,6 +67,21 @@
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
{
+#ifdef __Fuchsia__
+ *ptyfd = open("/dev/misc/ptmx", O_RDWR | O_NONBLOCK);
+ if (*ptyfd < 0) {
+ error("open /dev/misc/ptmx: %s", strerror(errno));
+ return 0;
+ }
+ *ttyfd = openat(*ptyfd, "0", O_RDWR | O_NONBLOCK);
+ if (*ttyfd < 0) {
+ error("openat /dev/misc/ptmx 0: %s", strerror(errno));
+ return 0;
+ }
+ // ssh thinks it wants to be able to manipulate a PTY by filename but
+ // that isn't possible on Fuchsia.
+ strlcpy(namebuf, "/dev/not-a-file", namebuflen);
+#else
/* openpty(3) exists in OSF/1 and some other os'es */
char *name;
int i;
@@ -77,6 +96,7 @@
fatal("openpty returns device for which ttyname fails.");
strlcpy(namebuf, name, namebuflen); /* possible truncation */
+#endif // __Fuchsia__
return 1;
}
@@ -176,6 +196,13 @@
pty_change_window_size(int ptyfd, u_int row, u_int col,
u_int xpixel, u_int ypixel)
{
+#ifdef __Fuchsia__
+ pty_window_size_t w;
+
+ w.width = col;
+ w.height = row;
+ ioctl_pty_set_window_size(ptyfd, &w);
+#else
struct winsize w;
/* may truncate u_int -> u_short */
@@ -184,11 +211,17 @@
w.ws_xpixel = xpixel;
w.ws_ypixel = ypixel;
(void) ioctl(ptyfd, TIOCSWINSZ, &w);
+#endif // __Fuchsia__
}
void
pty_setowner(struct passwd *pw, const char *tty)
{
+#ifdef __Fuchsia__
+ // This is meaningless on Fuchsia.
+ return;
+#endif
+
struct group *grp;
gid_t gid;
mode_t mode;