Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 569a1301 authored by Dan Albert's avatar Dan Albert
Browse files

Make pty raw in adb shell when non-interactive.

The main goal here is fixing the line ending translation from \n to
\r\n, but we probably don't want any translation to happen.

Bug: http://b/19735063
Change-Id: I1d6d6c6b57cc741b046c2432cd864b344ce1f28a
parent 4e000812
Loading
Loading
Loading
Loading
+37 −27
Original line number Original line Diff line number Diff line
@@ -24,6 +24,11 @@
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>


#if !ADB_HOST
#include <pty.h>
#include <termios.h>
#endif

#ifndef _WIN32
#ifndef _WIN32
#include <netdb.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in.h>
@@ -238,43 +243,48 @@ static void init_subproc_child()
    }
    }
}
}


static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
#if !ADB_HOST
{
static int create_subproc_pty(const char* cmd, const char* arg0,
                              const char* arg1, pid_t* pid) {
    D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
    D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
#if defined(_WIN32)
    char pts_name[PATH_MAX];
    fprintf(stderr, "error: create_subproc_pty not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
    return -1;
#else
    int ptm;
    int ptm;

    *pid = forkpty(&ptm, pts_name, nullptr, nullptr);
    ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); // | O_NOCTTY);
    if (*pid == -1) {
    if(ptm < 0){
        printf("- fork failed: %s -\n", strerror(errno));
        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
        adb_close(ptm);
        return -1;
        return -1;
    }
    }


    char devname[64];
    if (*pid == 0) {
    if(grantpt(ptm) || unlockpt(ptm) || ptsname_r(ptm, devname, sizeof(devname)) != 0) {
        init_subproc_child();
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));

        int pts = unix_open(pts_name, O_RDWR | O_CLOEXEC);
        if (pts == -1) {
            fprintf(stderr, "child failed to open pseudo-term slave %s: %s\n",
                    pts_name, strerror(errno));
            adb_close(ptm);
            adb_close(ptm);
        return -1;
            exit(-1);
        }
        }


    *pid = fork();
        // arg0 is "-c" in batch mode and "-" in interactive mode.
    if(*pid < 0) {
        if (strcmp(arg0, "-c") == 0) {
        printf("- fork failed: %s -\n", strerror(errno));
            termios tattr;
            if (tcgetattr(pts, &tattr) == -1) {
                fprintf(stderr, "tcgetattr failed: %s\n", strerror(errno));
                adb_close(pts);
                adb_close(ptm);
                adb_close(ptm);
        return -1;
                exit(-1);
            }
            }


    if (*pid == 0) {
            cfmakeraw(&tattr);
        init_subproc_child();
            if (tcsetattr(pts, TCSADRAIN, &tattr) == -1) {

                fprintf(stderr, "tcsetattr failed: %s\n", strerror(errno));
        int pts = unix_open(devname, O_RDWR | O_CLOEXEC);
                adb_close(pts);
        if (pts < 0) {
                adb_close(ptm);
            fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
                exit(-1);
                exit(-1);
            }
            }
        }


        dup2(pts, STDIN_FILENO);
        dup2(pts, STDIN_FILENO);
        dup2(pts, STDOUT_FILENO);
        dup2(pts, STDOUT_FILENO);
@@ -283,15 +293,15 @@ static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg
        adb_close(pts);
        adb_close(pts);
        adb_close(ptm);
        adb_close(ptm);


        execl(cmd, cmd, arg0, arg1, NULL);
        execl(cmd, cmd, arg0, arg1, nullptr);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
                cmd, strerror(errno), errno);
                cmd, strerror(errno), errno);
        exit(-1);
        exit(-1);
    } else {
    } else {
        return ptm;
        return ptm;
    }
    }
#endif /* !defined(_WIN32) */
}
}
#endif // !ADB_HOST


static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
{
+11 −3
Original line number Original line Diff line number Diff line
@@ -164,7 +164,8 @@ class AdbWrapper(object):
        return call_combined(self.adb_cmd + "shell " + cmd)
        return call_combined(self.adb_cmd + "shell " + cmd)


    def install(self, filename):
    def install(self, filename):
        return call_checked(self.adb_cmd + "install {}".format(pipes.quote(filename)))
        return call_checked(
            self.adb_cmd + "install {}".format(pipes.quote(filename)))


    def push(self, local, remote):
    def push(self, local, remote):
        return call_checked(self.adb_cmd + "push {} {}".format(local, remote))
        return call_checked(self.adb_cmd + "push {} {}".format(local, remote))
@@ -283,7 +284,7 @@ class AdbBasic(unittest.TestCase):
        result = adb.shell("sh -c 'echo hello; echo world'").splitlines()
        result = adb.shell("sh -c 'echo hello; echo world'").splitlines()
        self.assertEqual(["", "world"], result)
        self.assertEqual(["", "world"], result)
        # If you really wanted "hello" and "world", here's what you'd do:
        # If you really wanted "hello" and "world", here's what you'd do:
        result = adb.shell("echo hello\;echo world").splitlines()
        result = adb.shell(r"echo hello\;echo world").splitlines()
        self.assertEqual(["hello", "world"], result)
        self.assertEqual(["hello", "world"], result)


        # http://b/15479704
        # http://b/15479704
@@ -292,7 +293,7 @@ class AdbBasic(unittest.TestCase):


        # http://b/20564385
        # http://b/20564385
        self.assertEqual('t', adb.shell("FOO=a BAR=b echo t").strip())
        self.assertEqual('t', adb.shell("FOO=a BAR=b echo t").strip())
        self.assertEqual('123Linux', adb.shell("echo -n 123\;uname").strip())
        self.assertEqual('123Linux', adb.shell(r"echo -n 123\;uname").strip())


    def test_install_argument_escaping(self):
    def test_install_argument_escaping(self):
        """Make sure that install argument escaping works."""
        """Make sure that install argument escaping works."""
@@ -306,6 +307,13 @@ class AdbBasic(unittest.TestCase):
        tf = tempfile.NamedTemporaryFile("w", suffix="-Live Hold'em.apk")
        tf = tempfile.NamedTemporaryFile("w", suffix="-Live Hold'em.apk")
        self.assertIn("-Live Hold'em.apk", adb.install(tf.name))
        self.assertIn("-Live Hold'em.apk", adb.install(tf.name))


    def test_line_endings(self):
        """Ensure that line ending translation is not happening in the pty.

        Bug: http://b/19735063
        """
        self.assertFalse(AdbWrapper().shell("uname").endswith("\r\n"))



class AdbFile(unittest.TestCase):
class AdbFile(unittest.TestCase):
    SCRATCH_DIR = "/data/local/tmp"
    SCRATCH_DIR = "/data/local/tmp"