Re: [PATCH 04/15] policycoreutils: Add new open_init_pty that doesn't waste CPU time

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.


[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux