コード例 #1
0
ファイル: process.py プロジェクト: sailfish009/oil
    def Pop(self):
        # type: () -> None
        frame = self.stack.pop()
        #log('< Pop %s', frame)
        for rf in reversed(frame.saved):
            if rf.saved_fd == NO_FD:
                #log('Close %d', orig)
                try:
                    posix.close(rf.orig_fd)
                except OSError as e:
                    log('Error closing descriptor %d: %s', rf.orig_fd,
                        pyutil.strerror(e))
                    raise
            else:
                try:
                    posix.dup2(rf.saved_fd, rf.orig_fd)
                except OSError as e:
                    log('dup2(%d, %d) error: %s', rf.saved_fd, rf.orig_fd,
                        pyutil.strerror(e))
                    #log('fd state:')
                    #posix.system('ls -l /proc/%s/fd' % posix.getpid())
                    raise
                posix.close(rf.saved_fd)
                #log('dup2 %s %s', saved, orig)

        # Wait for here doc processes to finish.
        for proc, waiter in frame.need_wait:
            unused_status = proc.Wait(waiter)
コード例 #2
0
ファイル: process.py プロジェクト: sailfish009/oil
    def _PushDup(self, fd1, loc):
        # type: (int, redir_loc_t) -> int
        """Save fd2 in a higher range, and dup fd1 onto fd2.

    Returns whether F_DUPFD/dup2 succeeded, and the new descriptor.
    """
        UP_loc = loc
        if loc.tag_() == redir_loc_e.VarName:
            fd2_name = cast(redir_loc__VarName, UP_loc).name
            try:
                # F_DUPFD: GREATER than range
                new_fd = fcntl_.fcntl(fd1, fcntl_.F_DUPFD,
                                      _SHELL_MIN_FD)  # type: int
            except IOError as e:
                if e.errno == errno_.EBADF:
                    self.errfmt.Print_('%d: %s' % (fd1, pyutil.strerror(e)))
                    return NO_FD
                else:
                    raise  # this redirect failed

            self._WriteFdToMem(fd2_name, new_fd)

        elif loc.tag_() == redir_loc_e.Fd:
            fd2 = cast(redir_loc__Fd, UP_loc).fd

            if fd1 == fd2:
                # The user could have asked for it to be open on descrptor 3, but open()
                # already returned 3, e.g. echo 3>out.txt
                return NO_FD

            # Check the validity of fd1 before _PushSave(fd2)
            try:
                fcntl_.fcntl(fd1, fcntl_.F_GETFD)
            except IOError as e:
                self.errfmt.Print_('%d: %s' % (fd1, pyutil.strerror(e)))
                raise

            need_restore = self._PushSave(fd2)

            #log('==== dup2 %s %s\n' % (fd1, fd2))
            try:
                posix.dup2(fd1, fd2)
            except OSError as e:
                # bash/dash give this error too, e.g. for 'echo hi 1>&3'
                self.errfmt.Print_('%d: %s' % (fd1, pyutil.strerror(e)))

                # Restore and return error
                if need_restore:
                    rf = self.cur_frame.saved.pop()
                    posix.dup2(rf.saved_fd, rf.orig_fd)
                    posix.close(rf.saved_fd)

                raise  # this redirect failed

            new_fd = fd2

        else:
            raise AssertionError()

        return new_fd
コード例 #3
0
ファイル: process.py プロジェクト: shamrin/oil
  def Pop(self):
    # type: () -> None
    frame = self.stack.pop()
    #log('< Pop %s', frame)
    for saved, orig in reversed(frame.saved):
      try:
        posix.dup2(saved, orig)
      except OSError as e:
        log('dup2(%d, %d) error: %s', saved, orig, e)
        #log('fd state:')
        #posix.system('ls -l /proc/%s/fd' % posix.getpid())
        raise
      posix.close(saved)
      #log('dup2 %s %s', saved, orig)

    for fd in frame.need_close:
      #log('Close %d', fd)
      try:
        posix.close(fd)
      except OSError as e:
        log('Error closing descriptor %d: %s', fd, e)
        raise

    # Wait for here doc processes to finish.
    for proc, waiter in frame.need_wait:
      unused_status = proc.Wait(waiter)
コード例 #4
0
ファイル: process.py プロジェクト: shamrin/oil
  def Open(self, path, mode='r'):
    # type: (str, str) -> mylib.LineReader
    """Opens a path for read, but moves it out of the reserved 3-9 fd range.

    Returns:
      A Python file object.  The caller is responsible for Close().

    Raises:
      OSError if the path can't be found.
    """
    if mode == 'r':
      fd_mode = posix.O_RDONLY
    elif mode == 'w':
      fd_mode = posix.O_CREAT | posix.O_RDWR
    else:
      raise AssertionError(mode)

    fd = posix.open(path, fd_mode, 0o666)  # may raise OSError
    new_fd = self._GetFreeDescriptor()
    posix.dup2(fd, new_fd)
    posix.close(fd)
    try:
      f = posix.fdopen(new_fd, mode)  # Might raise IOError
    except IOError as e:
      raise OSError(*e.args)  # Consistently raise OSError
    return f
コード例 #5
0
ファイル: process.py プロジェクト: shamrin/oil
  def _PushDup(self, fd1, fd2):
    # type: (int, int) -> bool
    """Save fd2, and dup fd1 onto fd2.

    Mutates self.cur_frame.saved.

    Returns:
      success Bool
    """
    new_fd = self._GetFreeDescriptor()
    #log('---- _PushDup %s %s', fd1, fd2)
    need_restore = True
    try:
      fcntl.fcntl(fd2, fcntl.F_DUPFD, new_fd)
    except IOError as e:
      # Example program that causes this error: exec 4>&1.  Descriptor 4 isn't
      # open.
      # This seems to be ignored in dash too in savefd()?
      if e.errno == errno.EBADF:
        #log('ERROR %s', e)
        need_restore = False
      else:
        raise
    else:
      posix.close(fd2)
      fcntl.fcntl(new_fd, fcntl.F_SETFD, fcntl.FD_CLOEXEC)

    #log('==== dup %s %s\n' % (fd1, fd2))
    try:
      posix.dup2(fd1, fd2)
    except OSError as e:
      # bash/dash give this error too, e.g. for 'echo hi 1>&3'
      self.errfmt.Print('%d: %s', fd1, posix.strerror(e.errno))

      # Restore and return error
      posix.dup2(new_fd, fd2)
      posix.close(new_fd)
      # Undo it
      return False

    if need_restore:
      self.cur_frame.saved.append((new_fd, fd2))
    return True
コード例 #6
0
ファイル: process.py プロジェクト: sailfish009/oil
    def Apply(self):
        # type: () -> None
        posix.dup2(self.w, 1)
        posix.close(self.w)  # close after dup

        posix.close(self.r)  # we're writing to the pipe, not reading
コード例 #7
0
ファイル: process.py プロジェクト: sailfish009/oil
    def Apply(self):
        # type: () -> None
        posix.dup2(self.r, 0)
        posix.close(self.r)  # close after dup

        posix.close(self.w)  # we're reading from the pipe, not writing