I applied all of these to my devel tree except this one. It's huge and I don't know why we need it, or want it, or want C++ or whatever... -Eric On Mon, Oct 1, 2012 at 12:31 PM, Laurent Bigonville <bigon@xxxxxxxxxx> wrote: > From: Russell Coker <russell@xxxxxxxxxxxx> > > --- > policycoreutils/run_init/Makefile | 7 +- > policycoreutils/run_init/open_init_pty.c | 399 -------------------------- > policycoreutils/run_init/open_init_pty.cpp | 423 ++++++++++++++++++++++++++++ > 3 files changed, 427 insertions(+), 402 deletions(-) > delete mode 100644 policycoreutils/run_init/open_init_pty.c > create mode 100644 policycoreutils/run_init/open_init_pty.cpp > > diff --git a/policycoreutils/run_init/Makefile b/policycoreutils/run_init/Makefile > index 5815a08..e3c6e9d 100644 > --- a/policycoreutils/run_init/Makefile > +++ b/policycoreutils/run_init/Makefile > @@ -10,6 +10,7 @@ AUDITH = $(shell ls /usr/include/libaudit.h 2>/dev/null) > > CFLAGS ?= -Werror -Wall -W > override CFLAGS += -I$(PREFIX)/include -DUSE_NLS -DLOCALEDIR="\"$(LOCALEDIR)\"" -DPACKAGE="\"policycoreutils\"" > +CPPFLAGS ?= $(CFLAGS) > LDLIBS += -lselinux -L$(PREFIX)/lib > ifeq ($(PAMH), /usr/include/security/pam_appl.h) > override CFLAGS += -DUSE_PAM > @@ -23,12 +24,12 @@ ifeq ($(AUDITH), /usr/include/libaudit.h) > LDLIBS += -laudit > endif > > -TARGETS=$(patsubst %.c,%,$(wildcard *.c)) > +TARGETS=open_init_pty run_init > > all: $(TARGETS) > > -open_init_pty: open_init_pty.c > - $(LINK.c) $^ -ldl -lutil -o $@ > +open_init_pty: open_init_pty.cpp > + $(LINK.cpp) $^ -ldl -lutil -o $@ > > > install: all > diff --git a/policycoreutils/run_init/open_init_pty.c b/policycoreutils/run_init/open_init_pty.c > deleted file mode 100644 > index 4f04e72..0000000 > --- a/policycoreutils/run_init/open_init_pty.c > +++ /dev/null > @@ -1,399 +0,0 @@ > -/* -*- Mode: C -*- > - * open_init_pty.c --- > - * Author : Manoj Srivastava ( srivasta@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ) > - * Created On : Fri Jan 14 10:48:28 2005 > - * Created On Node : glaurung.internal.golden-gryphon.com > - * Last Modified By : Manoj Srivastava > - * Last Modified On : Thu Sep 15 00:57:00 2005 > - * Last Machine Used: glaurung.internal.golden-gryphon.com > - * Update Count : 92 > - * Status : Unknown, Use with caution! > - * HISTORY : > - * Description : > - * > - * Distributed under the terms of the GNU General Public License v2 > - * > - * open_init_pty > - * > - * SYNOPSIS: > - * > - * This program allows a systems administrator to execute daemons > - * which need to work in the initrc domain, and which need to have > - * pty's as system_u:system_r:initrc_t > - * > - * USAGE: > - * > - * * arch-tag: a5583d39-72b9-4cdf-ba1b-5678ea4cbe20 > - */ > - > -#include <stdio.h> > -#include <stdlib.h> > -#include <unistd.h> > -#include <signal.h> > -#include <errno.h> > - > -#include <sysexits.h> > - > -#include <pty.h> /* for openpty and forkpty */ > -#include <utmp.h> /* for login_tty */ > -#include <termios.h> > -#include <fcntl.h> > - > -#include <sys/select.h> > - > -static struct termios saved_termios; > -static int saved_fd = -1; > -static enum { RESET, RAW, CBREAK } tty_state = RESET; > - > -static int tty_semi_raw(int fd) > -{ > - struct termios buf; > - > - if (tty_state == RESET) { > - if (tcgetattr(fd, &saved_termios) < 0) { > - return -1; > - } > - } > - > - buf = saved_termios; > - /* > - * echo off, canonical mode off, extended input processing off, > - * signal chars off > - */ > - buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); > - /* > - * no SIGINT on break, CR-to-NL off, input parity check off, do not > - * strip 8th bit on input,output flow control off > - */ > - buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); > - /* Clear size bits, parity checking off */ > - buf.c_cflag &= ~(CSIZE | PARENB); > - /* set 8 bits/char */ > - buf.c_cflag |= CS8; > - /* Output processing off > - buf.c_oflag &= ~(OPOST); */ > - > - buf.c_cc[VMIN] = 1; /* one byte at a time, no timer */ > - buf.c_cc[VTIME] = 0; > - if (tcsetattr(fd, TCSANOW, &buf) < 0) { > - return -1; > - } /* end of if(tcsetattr(fileno(stdin), TCSANOW, &buf) < 0) */ > - tty_state = RAW; > - saved_fd = fd; > - return 0; > -} > - > -void tty_atexit(void) > -{ > - if (tty_state != CBREAK && tty_state != RAW) { > - return; > - } > - > - if (tcsetattr(saved_fd, TCSANOW, &saved_termios) < 0) { > - return; > - } /* end of if(tcsetattr(fileno(stdin), TCSANOW, &buf) < 0) */ > - tty_state = RESET; > - return; > -} > - > -int main(int argc, char *argv[]) > -{ > - pid_t child_pid; > - struct termios tty_attr; > - struct winsize window_size; > - int pty_master; > - int retval = 0; > - > - /* for select */ > - fd_set readfds; > - fd_set writefds; > - fd_set exceptfds; > - > - int err_count = 0; > - > - /* for sigtimedwait() */ > - struct timespec timeout; > - char buf[16384]; > - > - if (argc == 1) { > - printf("usage: %s PROGRAM [ARGS]...\n", argv[0]); > - exit(1); > - } > - > - sigset_t signal_set; > - siginfo_t signalinfo; > - > - /* set up SIGCHLD */ > - sigemptyset(&signal_set); /* no signals */ > - sigaddset(&signal_set, SIGCHLD); /* Add sig child */ > - sigprocmask(SIG_BLOCK, &signal_set, NULL); /* Block the signal */ > - > - /* Set both to 0, so sigtimed wait just does a poll */ > - timeout.tv_sec = 0; > - timeout.tv_nsec = 0; > - > - if (isatty(fileno(stdin))) { > - /* get terminal parameters associated with stdout */ > - if (tcgetattr(fileno(stdout), &tty_attr) < 0) { > - perror("tcgetattr:"); > - exit(EX_OSERR); > - } > - > - /* end of if(tcsetattr(&tty_attr)) */ > - /* get window size */ > - if (ioctl(fileno(stdout), TIOCGWINSZ, &window_size) < 0) { > - perror("ioctl stdout:"); > - exit(1); > - } > - > - child_pid = forkpty(&pty_master, NULL, &tty_attr, &window_size); > - } /* end of if(isatty(fileno(stdin))) */ > - else { /* not interactive */ > - child_pid = forkpty(&pty_master, NULL, NULL, NULL); > - } > - > - if (child_pid < 0) { > - perror("forkpty():"); > - fflush(stdout); > - fflush(stderr); > - exit(EX_OSERR); > - } /* end of if(child_pid < 0) */ > - if (child_pid == 0) { > - /* in the child */ > - struct termios s_tty_attr; > - if (tcgetattr(fileno(stdin), &s_tty_attr)) { > - perror("Child:"); > - fflush(stdout); > - fflush(stderr); > - exit(EXIT_FAILURE); > - } > - /* Turn off echo */ > - s_tty_attr.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); > - /* Also turn of NL to CR?LF on output */ > - s_tty_attr.c_oflag &= ~(ONLCR); > - if (tcsetattr(fileno(stdin), TCSANOW, &s_tty_attr)) { > - perror("Child:"); > - exit(EXIT_FAILURE); > - } > - { /* There is no reason to block sigchild for the process we > - shall exec here */ > - sigset_t chld_signal_set; > - /* release SIGCHLD */ > - sigemptyset(&chld_signal_set); /* no signals */ > - sigaddset(&chld_signal_set, SIGCHLD); /* Add sig child */ > - sigprocmask(SIG_UNBLOCK, &chld_signal_set, NULL); /* Unblock the signal */ > - } > - > - if (execvp(argv[1], argv + 1)) { > - perror("Exec:"); > - fflush(stdout); > - fflush(stderr); > - exit(EXIT_FAILURE); > - } > - } > - > - /* end of if(child_pid == 0) */ > - /* > - * OK. Prepare to handle IO from the child. We need to transfer > - * everything from the child's stdout to ours. > - */ > - FD_ZERO(&readfds); > - FD_ZERO(&writefds); > - FD_ZERO(&exceptfds); > - > - /* > - * Read current file descriptor flags, preparing to do non blocking reads > - */ > - retval = fcntl(pty_master, F_GETFL); > - if (retval < 0) { > - perror("fcntl_get"); > - fflush(stdout); > - fflush(stderr); > - exit(EX_IOERR); > - } > - > - /* Set the connection to be non-blocking */ > - if (fcntl(pty_master, F_SETFL, retval | O_NONBLOCK) < 0) { > - perror("fcnt_setFlag_nonblock:"); > - fflush(stdout); > - fflush(stderr); > - exit(1); > - } > - > - FD_SET(pty_master, &readfds); > - FD_SET(pty_master, &writefds); > - FD_SET(fileno(stdin), &readfds); > - if (isatty(fileno(stdin))) { > - if (tty_semi_raw(fileno(stdin)) < 0) { > - perror("Error: settingraw mode:"); > - fflush(stdout); > - fflush(stderr); > - } /* end of if(tty_raw(fileno(stdin)) < 0) */ > - if (atexit(tty_atexit) < 0) { > - perror("Atexit setup:"); > - fflush(stdout); > - fflush(stderr); > - } /* end of if(atexit(tty_atexit) < 0) */ > - } > - > - /* ignore return from nice, but lower our priority */ > - int ignore __attribute__ ((unused)) = nice(19); > - > - /* while no signal, we loop around */ > - int done = 0; > - while (!done) { > - struct timeval interval; > - fd_set t_readfds; > - fd_set t_writefds; > - fd_set t_exceptfds; > - /* > - * We still use a blocked signal, and check for SIGCHLD every > - * loop, since waiting infinitely did not really help the load > - * when running, say, top. > - */ > - interval.tv_sec = 0; > - interval.tv_usec = 200000; /* so, check for signals every 200 milli > - seconds */ > - > - t_readfds = readfds; > - t_writefds = writefds; > - t_exceptfds = exceptfds; > - > - /* check for the signal */ > - retval = sigtimedwait(&signal_set, &signalinfo, &timeout); > - > - if (retval == SIGCHLD) { > - /* child terminated */ > - done = 1; /* in case they do not close off their > - file descriptors */ > - } else { > - if (retval < 0) { > - if (errno != EAGAIN) { > - perror("sigtimedwait"); > - fflush(stdout); > - fflush(stderr); > - exit(EX_IOERR); > - } else { > - /* No signal in set was delivered within the timeout period specified */ > - } > - } > - } /* end of else */ > - > - if (select > - (pty_master + 1, &t_readfds, &t_writefds, &t_exceptfds, > - &interval) < 0) { > - perror("Select:"); > - fflush(stdout); > - fflush(stderr); > - exit(EX_IOERR); > - } > - > - if (FD_ISSET(pty_master, &t_readfds)) { > - retval = read(pty_master, buf, (unsigned int)16384); > - if (retval < 0) { > - if (errno != EINTR && errno != EAGAIN) { /* Nothing left to read? */ > - fflush(stdout); > - fflush(stderr); > - /* fprintf(stderr, "DEBUG: %d: Nothing left to read?\n", __LINE__); */ > - exit(EXIT_SUCCESS); > - } /* end of else */ > - } /* end of if(retval < 0) */ > - else { > - if (retval == 0) { > - if (++err_count > 5) { /* child closed connection */ > - fflush(stdout); > - fflush(stderr); > - /*fprintf(stderr, "DEBUG: %d: child closed connection?\n", __LINE__); */ > - exit(EXIT_SUCCESS); > - } > - } /* end of if(retval == 0) */ > - else { > - ssize_t nleft = retval; > - ssize_t nwritten = 0; > - char *ptr = buf; > - while (nleft > 0) { > - if ((nwritten = > - write(fileno(stdout), ptr, > - (unsigned int)nleft)) > - <= 0) { > - if (errno == EINTR) { > - nwritten = 0; > - } /* end of if(errno == EINTR) */ > - else { > - perror("write"); > - fflush(stdout); > - fflush(stderr); > - exit(EXIT_SUCCESS); > - } /* end of else */ > - } /* end of if((nwritten = write(sockfd, ptr, nleft)) <= 0) */ > - nleft -= nwritten; > - ptr += nwritten; > - } /* end of while(nleft > 0) */ > - > - /* fprintf(stderr, "DEBUG: %d: wrote %d\n", __LINE__, retval); */ > - fflush(stdout); > - } /* end of else */ > - } /* end of else */ > - } > - if (FD_ISSET(fileno(stdin), &t_readfds)) { > - if (FD_ISSET(pty_master, &t_writefds)) { > - retval = > - read(fileno(stdin), buf, > - (unsigned int)16384); > - if (retval < 0) { > - if (errno != EINTR && errno != EAGAIN) { /* Nothing left to read? */ > - fflush(stdout); > - fflush(stderr); > - exit(EXIT_SUCCESS); > - } /* end of else */ > - } /* end of if(retval < 0) */ > - else { > - if (retval == 0) { > - if (++err_count > 5) { /* lost controlling tty */ > - fflush(stdout); > - fflush(stderr); > - exit(EXIT_SUCCESS); > - } > - } /* end of if(retval == 0) */ > - else { > - ssize_t nleft = retval; > - ssize_t nwritten = 0; > - char *ptr = buf; > - while (nleft > 0) { > - if ((nwritten = > - write(pty_master, > - ptr, > - (unsigned > - int)nleft)) > - <= 0) { > - if (errno == > - EINTR) { > - nwritten > - = 0; > - } /* end of if(errno == EINTR) */ > - else { > - perror > - ("write"); > - fflush > - (stdout); > - fflush > - (stderr); > - exit(EXIT_SUCCESS); > - } /* end of else */ > - } /* end of if((nwritten = write(sockfd, ptr, nleft)) <= 0) */ > - nleft -= nwritten; > - ptr += nwritten; > - } /* end of while(nleft > 0) */ > - > - fflush(stdout); > - } /* end of else */ > - } /* end of else */ > - } /* end of if(FD_ISSET(pty_master, &writefds)) */ > - } /* something to read on stdin */ > - } /* Loop */ > - > - fflush(stdout); > - fflush(stderr); > - > - exit(EXIT_SUCCESS); > -} /* end of main() */ > diff --git a/policycoreutils/run_init/open_init_pty.cpp b/policycoreutils/run_init/open_init_pty.cpp > new file mode 100644 > index 0000000..b82f7f5 > --- /dev/null > +++ b/policycoreutils/run_init/open_init_pty.cpp > @@ -0,0 +1,423 @@ > +/* -*- Mode: C -*- > + * open_init_pty.c --- > + * Author : Manoj Srivastava ( srivasta@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ) > + * Created On : Fri Jan 14 10:48:28 2005 > + * Created On Node : glaurung.internal.golden-gryphon.com > + * Last Modified By : Manoj Srivastava > + * Last Modified On : Thu Sep 15 00:57:00 2005 > + * Last Machine Used: glaurung.internal.golden-gryphon.com > + * Update Count : 92 > + * Status : Unknown, Use with caution! > + * HISTORY : > + * Description : > + * > + * Distributed under the terms of the GNU General Public License v2 > + * > + * open_init_pty > + * > + * SYNOPSIS: > + * > + * This program allows a systems administrator to execute daemons > + * which need to work in the initrc domain, and which need to have > + * pty's as system_u:system_r:initrc_t > + * > + * USAGE: > + * > + * * arch-tag: a5583d39-72b9-4cdf-ba1b-5678ea4cbe20 > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > +#include <signal.h> > +#include <errno.h> > + > +#include <sysexits.h> > + > +#include <pty.h> /* for openpty and forkpty */ > +#include <utmp.h> /* for login_tty */ > +#include <termios.h> > +#include <fcntl.h> > + > +#include <sys/select.h> > +#include <sys/wait.h> > + > + > +#define MAXRETR 3 /* The max number of IO retries on a fd */ > +#define BUFSIZE 2048 /* The ring buffer size */ > + > +static struct termios saved_termios; > +static int saved_fd = -1; > +static enum { RESET, RAW, CBREAK } tty_state = RESET; > + > +static int tty_semi_raw(int fd) > +{ > + struct termios buf; > + > + if (tty_state == RESET) { > + if (tcgetattr(fd, &saved_termios) < 0) { > + return -1; > + } > + } > + > + buf = saved_termios; > + /* > + * echo off, canonical mode off, extended input processing off, > + * signal chars off > + */ > + buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); > + /* > + * no SIGINT on break, CR-to-NL off, input parity check off, do not > + * strip 8th bit on input,output flow control off > + */ > + buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); > + /* Clear size bits, parity checking off */ > + buf.c_cflag &= ~(CSIZE | PARENB); > + /* set 8 bits/char */ > + buf.c_cflag |= CS8; > + /* Output processing off > + buf.c_oflag &= ~(OPOST); */ > + > + buf.c_cc[VMIN] = 1; /* one byte at a time, no timer */ > + buf.c_cc[VTIME] = 0; > + if (tcsetattr(fd, TCSANOW, &buf) < 0) { > + return -1; > + } > + tty_state = RAW; > + saved_fd = fd; > + return 0; > +} > + > +static void tty_atexit(void) > +{ > + if (tty_state != CBREAK && tty_state != RAW) { > + return; > + } > + > + if (tcsetattr(saved_fd, TCSANOW, &saved_termios) < 0) { > + return; > + } > + tty_state = RESET; > + return; > +} > + > + > +/* The simple ring buffer */ > +class ring_buffer > +{ > +public: > + ring_buffer(char *buf, size_t size) > + { > + m_buf = m_wptr = m_rptr = buf; > + m_size = size; > + m_count = 0; > + } > + > + size_t get_count() { return m_count; } > + int isempty() { return m_count == 0; } > + > + // return the unused space size in the buffer > + size_t space() > + { > + if(m_rptr > m_wptr) > + return m_rptr - m_wptr; > + if(m_rptr < m_wptr || m_count == 0) > + return m_buf + m_size - m_wptr; > + return 0; // should not hit this > + } > + > + // return the used space in the buffer > + size_t chunk_size() > + { > + if(m_rptr < m_wptr) > + return m_wptr - m_rptr; > + if(m_rptr > m_wptr || m_count > 0) > + return m_buf + m_size - m_rptr; > + return 0; // should not hit this > + } > + > + // read from fd and write to buffer memory > + ssize_t rb_read(int fd) > + { > + ssize_t n = read(fd, m_wptr, space()); > + if(n <= 0) > + return n; > + m_wptr += n; > + m_count += n; > + if(m_buf + m_size <= m_wptr) > + m_wptr = m_buf; > + return n; > + } > + > + ssize_t rb_write(int fd) > + { > + ssize_t n = write(fd, m_rptr, chunk_size()); > + if(n <= 0) > + return n; > + m_rptr += n; > + m_count -= n; > + if(m_buf + m_size <= m_rptr) > + m_rptr = m_buf; > + return n; > + } > + > +private: > + char *m_buf; /* pointer to buffer memory */ > + char *m_wptr; > + char *m_rptr; > + size_t m_size; /* the number of bytes allocated for buf */ > + size_t m_count; > +}; > + > +static void setfd_nonblock(int fd) > +{ > + int fsflags = fcntl(fd, F_GETFL); > + > + if (fsflags < 0) { > + fprintf(stderr, "fcntl(%d, F_GETFL): %s\n", > + fd, strerror(errno)); > + exit(EX_IOERR); > + } > + > + if (fcntl(STDIN_FILENO, F_SETFL, fsflags | O_NONBLOCK) < 0) { > + fprintf(stderr, "fcntl(%d, F_SETFL, ... | O_NONBLOCK): %s\n", > + fd, strerror(errno)); > + exit(EX_IOERR); > + } > +} > + > +static void sigchld_handler(int asig __attribute__ ((unused))) > +{ > +} > + > +int main(int argc, char *argv[]) > +{ > + pid_t child_pid; > + int child_exit_status; > + struct termios tty_attr; > + struct winsize window_size; > + int pty_master; > + char inbuf_mem[BUFSIZE]; > + char outbuf_mem[BUFSIZE]; > + ring_buffer inbuf(inbuf_mem, sizeof(inbuf_mem)); > + ring_buffer outbuf(outbuf_mem, sizeof(outbuf_mem)); > + > + if (argc == 1) { > + printf("usage: %s PROGRAM [ARGS]...\n", argv[0]); > + exit(1); > + } > + > + /* Wee need I/O calls to fail with EINTR on SIGCHLD... */ > + if ( signal(SIGCHLD, sigchld_handler) == SIG_ERR ) { > + perror("signal(SIGCHLD,...)"); > + exit(EX_OSERR); > + } > + > + if (isatty(STDIN_FILENO)) { > + /* get terminal parameters associated with stdout */ > + if (tcgetattr(STDOUT_FILENO, &tty_attr) < 0) { > + perror("tcgetattr(stdout,...)"); > + exit(EX_OSERR); > + } > + > + /* end of if(tcsetattr(&tty_attr)) */ > + /* get window size */ > + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window_size) < 0) { > + perror("ioctl(stdout,...)"); > + exit(1); > + } > + > + child_pid = forkpty(&pty_master, NULL, &tty_attr, &window_size); > + } /* end of if(isatty(STDIN_FILENO)) */ > + else { /* not interactive */ > + child_pid = forkpty(&pty_master, NULL, NULL, NULL); > + } > + > + if (child_pid < 0) { > + perror("forkpty()"); > + fflush(stdout); > + fflush(stderr); > + exit(EX_OSERR); > + } /* end of if(child_pid < 0) */ > + if (child_pid == 0) { > + /* in the child */ > + struct termios s_tty_attr; > + if (tcgetattr(STDIN_FILENO, &s_tty_attr)) { > + perror("tcgetattr(stdin,...)"); > + exit(EXIT_FAILURE); > + } > + /* Turn off echo */ > + s_tty_attr.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); > + /* Also turn of NL to CR?LF on output */ > + s_tty_attr.c_oflag &= ~(ONLCR); > + if (tcsetattr(STDIN_FILENO, TCSANOW, &s_tty_attr)) { > + perror("tcsetattr(stdin,...)"); > + exit(EXIT_FAILURE); > + } > + > + if (execvp(argv[1], argv + 1)) { > + perror("execvp()"); > + exit(EXIT_FAILURE); > + } > + } > + > + /* > + * Non blocking mode for all file descriptors. > + */ > + setfd_nonblock(pty_master); > + setfd_nonblock(STDIN_FILENO); > + setfd_nonblock(STDOUT_FILENO); > + > + if (isatty(STDIN_FILENO)) { > + if (tty_semi_raw(STDIN_FILENO) < 0) { > + perror("tty_semi_raw(stdin)"); > + } > + if (atexit(tty_atexit) < 0) { > + perror("atexit()"); > + } > + } > + > + /* for select()... */ > + fd_set readfds; > + fd_set writefds; > + fd_set exceptfds; > + FD_ZERO(&readfds); > + FD_ZERO(&writefds); > + FD_ZERO(&exceptfds); > + > + unsigned err_n_rpty = 0; > + unsigned err_n_wpty = 0; > + unsigned err_n_stdin = 0; > + unsigned err_n_stdout = 0; > + > + int done = 0; > + > + do { > + /* Accept events only on fds, that we can handle now. */ > + int do_select = 0; > + > + if ( outbuf.space() > 0 && err_n_rpty < MAXRETR ) { > + FD_SET(pty_master, &readfds); > + do_select = 1; > + } else > + FD_CLR(pty_master, &readfds); > + > + if ( ! inbuf.isempty() && err_n_wpty < MAXRETR ) { > + FD_SET(pty_master, &writefds); > + do_select = 1; > + } else > + FD_CLR(pty_master, &writefds); > + > + if ( inbuf.space() > 0 && err_n_stdin < MAXRETR ) { > + FD_SET(STDIN_FILENO, &readfds); > + do_select = 1; > + } else > + FD_CLR(STDIN_FILENO, &readfds); > + > + if ( ! outbuf.isempty() && err_n_stdout < MAXRETR ) { > + FD_SET(STDOUT_FILENO, &writefds); > + do_select = 1; > + } else > + FD_CLR(STDOUT_FILENO, &writefds); > + > + if ( ! do_select ) > + { > +#ifdef DEBUG > + fprintf(stderr, "No I/O job for us, calling waitpid()...\n"); > +#endif > + while ( waitpid(child_pid, &child_exit_status, 0) < 0 ) > + ; > + break; > + } > + > + int select_rc = select(pty_master + 1, > + &readfds, &writefds, &exceptfds, NULL); > + if ( select_rc < 0 ) { > + perror("select()"); > + exit(EX_IOERR); > + } > +#ifdef DEBUG > + fprintf(stderr, "select() returned %d\n", select_rc); > +#endif > + > + if (FD_ISSET(STDOUT_FILENO, &writefds)) { > +#ifdef DEBUG > + fprintf(stderr, "stdout can be written\n"); > +#endif > + ssize_t n = outbuf.rb_write(STDOUT_FILENO); > + if ( n <= 0 && n != EINTR && n != EAGAIN ) > + err_n_stdout++; > +#ifdef DEBUG > + if ( n >= 0 ) > + fprintf(stderr, "%d bytes written into stdout\n", n); > + else > + perror("write(stdout,...)"); > +#endif > + } > + if (FD_ISSET(pty_master, &writefds)) { > +#ifdef DEBUG > + fprintf(stderr, "pty_master can be written\n"); > +#endif > + ssize_t n = inbuf.rb_write(pty_master); > + if ( n <= 0 && n != EINTR && n != EAGAIN ) > + err_n_wpty++; > +#ifdef DEBUG > + if ( n >= 0 ) > + fprintf(stderr, "%d bytes written into pty_master\n", n); > + else > + perror("write(pty_master,...)"); > +#endif > + } > + if (FD_ISSET(STDIN_FILENO, &readfds)) { > +#ifdef DEBUG > + fprintf(stderr, "stdin can be read\n"); > +#endif > + ssize_t n = inbuf.rb_read(STDIN_FILENO); > + if ( n <= 0 && n != EINTR && n != EAGAIN ) > + err_n_stdin++; > +#ifdef DEBUG > + if ( n >= 0 ) > + fprintf(stderr, "%d bytes read from stdin\n", n); > + else > + perror("read(stdin,...)"); > +#endif > + } > + if (FD_ISSET(pty_master, &readfds)) { > +#ifdef DEBUG > + fprintf(stderr, "pty_master can be read\n"); > +#endif > + ssize_t n = outbuf.rb_read(pty_master); > + if ( n <= 0 && n != EINTR && n != EAGAIN ) > + err_n_rpty++; > +#ifdef DEBUG > + if ( n >= 0 ) > + fprintf(stderr, "%d bytes read from pty_master\n", n); > + else > + perror("read(pty_master,...)"); > +#endif > + } > + > + if ( ! done ) > + if ( waitpid(child_pid, &child_exit_status, WNOHANG) > 0 ) > + done = 1; > + > + } while ( !done > + || !(inbuf.isempty() || err_n_wpty >= MAXRETR) > + || !(outbuf.isempty() || err_n_stdout >= MAXRETR) ); > + > +#ifdef DEBUG > + fprintf(stderr, "inbuf: %u bytes left, outbuf: %u bytes left\n", > + inbuf.get_count(), outbuf.get_count()); > + fprintf(stderr, "err_n_rpty=%u, err_n_wpty=%u, " > + "err_n_stdin=%u, err_n_stdout=%u\n", > + err_n_rpty, err_n_wpty, err_n_stdin, err_n_stdout); > +#endif > + if ( WIFEXITED(child_exit_status) ) > + exit(WEXITSTATUS(child_exit_status)); > + exit(EXIT_FAILURE); > +} /* end of main() */ > + > +/* > + * vim:ts=4: > + */ > -- > 1.7.10.4 > > > -- > This message was distributed to subscribers of the selinux mailing list. > If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with > the words "unsubscribe selinux" without quotes as the message. -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with the words "unsubscribe selinux" without quotes as the message.