コード例 #1
0
ファイル: serial_unix.cpp プロジェクト: dougmencken/macemu
bool XSERDPort::open_pty(void)
{
	// Talk to a process via a pty
	char slave[128];
	int slavefd;

	protocol = pty;
	if (!pty_allocate(&fd, &slavefd, slave, sizeof(slave)))
		return false;

	fflush(stdout);
	fflush(stderr);
	switch (pid = fork()) {
	case -1:				// error
		return false;
		break;
	case 0:					// child
		::close(fd);

		/* Make the pseudo tty our controlling tty. */
		pty_make_controlling_tty(&slavefd, slave);

		::close(0); dup(slavefd); // Use the slave fd for stdin,
		::close(1); dup(slavefd); // stdout,
		::close(2); dup(slavefd); // and stderr.

		// <should we be more paranoid about closing unused fds?>
		// <should we drop privileges if running setuid?>

		// Let the shell do the dirty work
		execlp("/bin/sh", "/bin/sh", "-c", ++device_name, (char *)NULL);

		// exec failed!
		printf("serial_open:  could not exec %s: %s\n",
			   "/bin/sh", strerror(errno));
		exit(1);
		break;
	default:				// parent
		// Pid was stored above
		break;
	}

	return true;
}
コード例 #2
0
ファイル: chansession.c プロジェクト: TheTypoMaster/AH4222
/* Execute a command or shell within a pty environment, and set up
 * redirection as appropriate.
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {

	pid_t pid;
	struct logininfo *li;

	TRACE(("enter ptycommand"));

	/* we already have a pty allocated */
	assert(chansess->master != -1 && chansess->tty != NULL);
	pid = fork();
	if (pid < 0)
		return DROPBEAR_FAILURE;

	if (pid == 0) {
		/* child */
		
		/* redirect stdin/stdout/stderr */
		close(chansess->master);

		pty_make_controlling_tty(&chansess->slave, chansess->tty);
		
		if ((dup2(chansess->slave, STDIN_FILENO) < 0) ||
			(dup2(chansess->slave, STDERR_FILENO) < 0) ||
			(dup2(chansess->slave, STDOUT_FILENO) < 0)) {
			TRACE(("leave ptycommand: error redirecting filedesc"));
			return DROPBEAR_FAILURE;
		}

		close(chansess->slave);

		/* write the utmp/wtmp login record - must be after changing the
		 * terminal used for stdout with the dup2 above */
		li= login_alloc_entry(getpid(), ses.authstate.username,
				ses.hostname, chansess->tty);
		login_login(li);
		login_free_entry(li);

		m_free(chansess->tty);

		execchild(chansess);
		/* not reached */

	} else {
		/* parent */
		TRACE(("continue ptycommand: parent"));
		chansess->pid = pid;

		/* add a child pid */
		addchildpid(chansess, pid);

		close(chansess->slave);
		channel->infd = chansess->master;
		channel->outfd = chansess->master;
		/* don't need to set stderr here */
		ses.maxfd = MAX(ses.maxfd, chansess->master);

		if (fcntl(chansess->master, F_SETFL, O_NONBLOCK) < 0) {
			dropbear_exit("Couldn't set nonblocking");
		}

	}

	TRACE(("leave ptycommand"));
	return DROPBEAR_SUCCESS;
}
コード例 #3
0
ファイル: pseudo.c プロジェクト: MarkTseng/cgdb
/* pty_fork:  Creates a pseudo terminal and then calls fork. In the parent 
 * process, the slave side of the pseudo terminal is closed. In the child 
 * process, the master side of the pseudo terminal is closed and the slave 
 * side is made the controlling terminal. It is duplicated onto standard 
 * input, output and error and then closed. The master side of the pseudo 
 * terminal is stored in masterfd for the parent process. The device name 
 * of the slave side of the pseudo terminal is stored in the buffer pointed 
 * to by slavename which must be able to hold at least 64 bytes.  
 * slavenamesize is the size of the buffer pointed to by slavename. No
 * more than slavenamesize bytes will be written to slavename, including 
 * the terminating nul byte. If slave_termios is not null, it is passed to 
 * tcsetattr with the command TCSANOW to set the terminal attributes of the 
 * slave device. If slave_winsize is not null, it is passed to ioctl with 
 * the command TIOCSWINSZ to set the window size of the slave device. 
 * On success, returns 0 to the child process and returns the process 
 * id of the child process to the parent process. On error, returns -1 with 
 * errno set appropriately.
 */
pid_t pty_fork(int *masterfd, char *slavename, size_t slavenamesize,
        const struct termios * slave_termios,
        const struct winsize * slave_winsize)
{
    int slavefd = 0;
    pid_t pid = 0;

    /*
     ** Note: we don't use forkpty() because it closes the master in the
     ** child process before making the slave the controlling terminal of the
     ** child proces and this can prevent the slave from becoming the
     ** controlling terminal (but I have no idea why).
     */

    if (pty_open(masterfd, &slavefd, slavename, slavenamesize, slave_termios,
                    slave_winsize) == -1)
        return -1;

    switch (pid = fork()) {
        case -1:
            pty_release(slavename);
            close(slavefd);
            close(*masterfd);
            return -1;

        case 0:
        {
            /* Make the slave our controlling tty */
            if (pty_make_controlling_tty(&slavefd, slavename) == -1)
                _exit(EXIT_FAILURE);

            /* Redirect stdin, stdout and stderr from the pseudo tty */

            if (slavefd != STDIN_FILENO && dup2(slavefd, STDIN_FILENO) == -1)
                _exit(EXIT_FAILURE);

            if (slavefd != STDOUT_FILENO && dup2(slavefd, STDOUT_FILENO) == -1)
                _exit(EXIT_FAILURE);

            if (slavefd != STDERR_FILENO && dup2(slavefd, STDERR_FILENO) == -1)
                _exit(EXIT_FAILURE);

            /* Close the extra descriptor for the pseudo tty */

            if (slavefd != STDIN_FILENO && slavefd != STDOUT_FILENO
                    && slavefd != STDERR_FILENO)
                close(slavefd);

            /* Close the master side of the pseudo tty in the child */

            close(*masterfd);

            return 0;
        }

        default:
        {
            /* Close the slave side of the pseudo tty in the parent */

            close(slavefd);

            return pid;
        }
    }
}