Пример #1
0
int
tty_setty(int fd, ttydata_t *td)
{
#ifdef POSIX
    RETRY(xtcsetattr(fd, TCSADRAIN, &td->d_t)); 
#else
# ifdef TERMIO
    RETRY(ioctl(fd, TCSETAW,    (ioctl_t) &td->d_t));
# else
#  ifdef TIOCSETN
    RETRY(ioctl(fd, TIOCSETN,  (ioctl_t) &td->d_t));
#  endif /* TIOCSETN */
#  ifdef TIOCGETC
    RETRY(ioctl(fd, TIOCSETC,  (ioctl_t) &td->d_tc));
#  endif /* TIOCGETC */
#  ifdef TIOCGPAGE
    RETRY(ioctl(fd, TIOCSPAGE, (ioctl_t) &td->d_pc));
#  endif /* TIOCGPAGE */
#  ifdef TIOCLGET
    RETRY(ioctl(fd, TIOCLSET,  (ioctl_t) &td->d_lb));
#  endif /* TIOCLGET */
# endif /* TERMIO */
#endif /* POSIX */

#ifdef TIOCGLTC
    RETRY(ioctl(fd, TIOCSLTC,  (ioctl_t) &td->d_ltc));
#endif /* TIOCGLTC */

    return 0;
}
Пример #2
0
static void
set_window_size(int fd, const struct window_size* ws)
{
    int ret;
    struct winsize wz = {
        .ws_row = ws->row,
        .ws_col = ws->col,
        .ws_xpixel = ws->xpixel,
        .ws_ypixel = ws->ypixel,
    };

    do {
        ret = ioctl(fd, TIOCSWINSZ, &wz);
    } while (ret == -1 && errno == EINTR);

    dbg("TIOCSWINSZ(%ux%u): %d", wz.ws_row, wz.ws_col, ret);
}

struct stub {
    struct fb_adb_sh sh;
    struct child* child;
};

static void
stub_process_msg(struct fb_adb_sh* sh, struct msg mhdr)
{
    if (mhdr.type == MSG_WINDOW_SIZE) {
        struct msg_window_size m;
        read_cmdmsg(sh, mhdr, &m, sizeof (m));
        dbgmsg(&m.msg, "recv");
        struct stub* stub = (struct stub*) sh;
        if (stub->child->pty_master)
            set_window_size(stub->child->pty_master->fd, &m.ws);

        return;
    }

    fb_adb_sh_process_msg(sh, mhdr);
}

static void
setup_pty(int master, int slave, void* arg)
{
    struct msg_shex_hello* shex_hello = arg;
    char* hello_end = (char*) shex_hello + shex_hello->msg.size;
    struct termios attr = { 0 };
    xtcgetattr(slave, &attr);
    if (shex_hello->ispeed)
        cfsetispeed(&attr, shex_hello->ispeed);
    if (shex_hello->ospeed)
        cfsetospeed(&attr, shex_hello->ospeed);

    const struct termbit* tb = &termbits[0];
    const struct termbit* tb_end = tb + nr_termbits;
    struct term_control* tc = &shex_hello->tctl[0];

    while ((char*)(tc+1) <= hello_end && tb < tb_end) {
        int cmp = strncmp(tc->name, tb->name, sizeof (tc->name));
        if (cmp < 0) {
            dbg("tc not present: %.*s", (int) sizeof (tc->name), tc->name);
            tc++;
            continue;
        }

        if (cmp > 0) {
            dbg("tc not sent: %s", tb->name);
            tb++;
            continue;
        }

        tcflag_t* flg = NULL;
        if (tb->thing == TERM_IFLAG) {
            flg = &attr.c_iflag;
        } else if (tb->thing == TERM_OFLAG) {
            flg = &attr.c_oflag;
        } else if (tb->thing == TERM_LFLAG) {
            flg = &attr.c_lflag;
        } else if (tb->thing == TERM_C_CC) {
            if (tc->value == shex_hello->posix_vdisable_value)
                attr.c_cc[tb->value] = _POSIX_VDISABLE;
            else
                attr.c_cc[tb->value] = tc->value;

            dbg("c_cc[%s] = %d", tb->name, tc->value);
        }

        if (flg) {
            if (tc->value) {
                dbg("pty %s: set", tb->name);
                *flg |= tb->value;
            } else {
                dbg("pty %s: reset", tb->name);
                *flg &= ~tb->value;
            }
        }

        tc++;
        tb++;
    }

    xtcsetattr(slave, &attr);
    if (shex_hello->have_ws) {
        dbg("ws %ux%u (%ux%u)",
            shex_hello->ws.row,
            shex_hello->ws.col,
            shex_hello->ws.xpixel,
            shex_hello->ws.ypixel);
        set_window_size(master, &shex_hello->ws);
    }
}

static char**
read_child_arglist(size_t expected)
{
    char** argv;

    if (expected >= SIZE_MAX / sizeof (*argv))
        die(EFBIG, "too many arguments");

    argv = xalloc(sizeof (*argv) * (1+expected));
    for (size_t argno = 0; argno < expected; ++argno) {
        SCOPED_RESLIST(rl_read_arg);
        struct msg_cmdline_argument* m;
        struct msg* mhdr = read_msg(0, read_all_adb_encoded);
        reslist_pop_nodestroy(rl_read_arg);

        const char* argval;
        size_t arglen;

        if (mhdr->type == MSG_CMDLINE_ARGUMENT) {
            m = (struct msg_cmdline_argument*) mhdr;
            if (mhdr->size < sizeof (*m))
                die(ECOMM,
                    "bad handshake: MSG_CMDLINE_ARGUMENT size %u < %u",
                    (unsigned) mhdr->size,
                    (unsigned) sizeof (*m));

            argval = m->value;
            arglen = m->msg.size - sizeof (*m);
        } else if (mhdr->type == MSG_CMDLINE_DEFAULT_SH ||
                   mhdr->type == MSG_CMDLINE_DEFAULT_SH_LOGIN)
        {
            argval = getenv("SHELL");
            if (argval == NULL)
                argval = DEFAULT_SHELL;

            if (mhdr->type == MSG_CMDLINE_DEFAULT_SH_LOGIN)
                argval = xaprintf("-%s", argval);

            arglen = strlen(argval);
        } else {
            die(ECOMM,
                "bad handshake: unknown init msg s=%u t=%u",
                (unsigned) mhdr->size, (unsigned) mhdr->type);
        }

        argv[argno] = xalloc(arglen + 1);
        memcpy(argv[argno], argval, arglen);
        argv[argno][arglen] = '\0';
    }

    argv[expected] = NULL;
    return argv;
}