Esempio n. 1
0
pid_t pty_fork(int *ptrfdm, char** pts_name) {
    pid_t pid;
    char* name;
    int master_fd, pty_fd;

    if ((master_fd = ptm_open()) < 0) {
        err_sys("ERROR: ptm_open() failed [%d]\n", master_fd);
    }

    if ((name = ptsname(master_fd)) == NULL) {
        close(master_fd);
        return -1;
    }

    // Put values to the output params
    *pts_name = name;
    *ptrfdm = master_fd;

    if ((pid = fork()) < 0) {
        printf("FAILED");
        return (-1);
    }

    if (pid == 0) { /* child */
        if (setsid() < 0) {
            err_sys("setsid error");
        }

        if ((pty_fd = pts_open(master_fd)) < 0) {
            err_sys("can't open slave pty");
        }

        close(master_fd);
        dup_fd(pty_fd);

        return (0); /* child returns 0 just like fork() */
    } else { /* parent */
        return (pid); /* parent returns pid of child */
    }

}
Esempio n. 2
0
int connect_daemon(int argc, char *argv[], int ppid) {
    int uid = getuid();
    int ptmx = -1;
    char pts_slave[PATH_MAX];

    struct sockaddr_un sun;

    // Open a socket to the daemon
    int socketfd = socket(AF_LOCAL, SOCK_STREAM, 0);
    if (socketfd < 0) {
        PLOGE("socket");
        exit(-1);
    }
    if (fcntl(socketfd, F_SETFD, FD_CLOEXEC)) {
        PLOGE("fcntl FD_CLOEXEC");
        exit(-1);
    }

    memset(&sun, 0, sizeof(sun));
    sun.sun_family = AF_LOCAL;
    sprintf(sun.sun_path, "%s/server", REQUESTOR_DAEMON_PATH);

    memset(sun.sun_path, 0, sizeof(sun.sun_path));
    memcpy(sun.sun_path, "\0" "SUPERUSER", strlen("SUPERUSER") + 1);

    if (0 != connect(socketfd, (struct sockaddr*)&sun, sizeof(sun))) {
        PLOGE("connect");
        exit(-1);
    }

    LOGD("connecting client %d", getpid());

    int mount_storage = getenv("MOUNT_EMULATED_STORAGE") != NULL;

    // Determine which one of our streams are attached to a TTY
    int atty = 0;

    // Send TTYs directly (instead of proxying with a PTY) if
    // the SUPERUSER_SEND_TTY environment variable is set.
    if (getenv("SUPERUSER_SEND_TTY") == NULL) {
        if (isatty(STDIN_FILENO))  atty |= ATTY_IN;
        if (isatty(STDOUT_FILENO)) atty |= ATTY_OUT;
        if (isatty(STDERR_FILENO)) atty |= ATTY_ERR;
    }

    if (atty) {
        // We need a PTY. Get one.
        ptmx = pts_open(pts_slave, sizeof(pts_slave));
        if (ptmx < 0) {
            PLOGE("pts_open");
            exit(-1);
        }
    } else {
        pts_slave[0] = '\0';
    }

    // Send some info to the daemon, starting with our PID
    write_int(socketfd, getpid());
    // Send the slave path to the daemon
    // (This is "" if we're not using PTYs)
    write_string(socketfd, pts_slave);
    // User ID
    write_int(socketfd, uid);
    // Parent PID
    write_int(socketfd, ppid);
    write_int(socketfd, mount_storage);

    // Send stdin
    if (atty & ATTY_IN) {
        // Using PTY
        send_fd(socketfd, -1);
    } else {
        send_fd(socketfd, STDIN_FILENO);
    }

    // Send stdout
    if (atty & ATTY_OUT) {
        // Forward SIGWINCH
        watch_sigwinch_async(STDOUT_FILENO, ptmx);

        // Using PTY
        send_fd(socketfd, -1);
    } else {
        send_fd(socketfd, STDOUT_FILENO);
    }

    // Send stderr
    if (atty & ATTY_ERR) {
        // Using PTY
        send_fd(socketfd, -1);
    } else {
        send_fd(socketfd, STDERR_FILENO);
    }

    // Number of command line arguments
    write_int(socketfd, mount_storage ? argc - 1 : argc);

    // Command line arguments
    int i;
    for (i = 0; i < argc; i++) {
        if (i == 1 && mount_storage) {
            continue;
        }
        write_string(socketfd, argv[i]);
    }

    // Wait for acknowledgement from daemon
    read_int(socketfd);

    if (atty & ATTY_IN) {
        setup_sighandlers();
        pump_stdin_async(ptmx);
    }
    if (atty & ATTY_OUT) {
        pump_stdout_blocking(ptmx);
    }

    // Get the exit code
    int code = read_int(socketfd);
    close(socketfd);
    LOGD("client exited %d", code);

    return code;
}