message: Fix background jobs that don't request TTY access
diff: @@ -13,14 +13,13 @@ pub(crate) fn redir(old: RawFd, new: RawFd) {
  /// Duplicates STDIN, STDOUT, and STDERR; in that order; and returns them as `File`s.
  /// Why, you ask? A simple safety mechanism to ensure that the duplicated FDs are closed
  /// when dropped.
  -pub(crate) fn duplicate_streams() -> io::Result<(File, File, File)> {
  - // Duplicates STDIN and converts it into a `File`.
  - sys::dup(sys::STDIN_FILENO).map(|fd| unsafe { File::from_raw_fd(fd) })
  - // Do the same for stdout, and then meld the result with stdin
  - .and_then(|stdin| sys::dup(sys::STDOUT_FILENO)
  +pub(crate) fn duplicate_streams() -> io::Result<(Option<File>, File, File)> {
  + // STDIN may have been closed for a background shell, so it is ok if it cannot be duplicated.
  + let stdin = sys::dup(sys::STDIN_FILENO).ok().map(|fd| unsafe { File::from_raw_fd(fd) });
  +
  + sys::dup(sys::STDOUT_FILENO)
  .map(|fd| unsafe { File::from_raw_fd(fd) })
  .map(|stdout| (stdin, stdout))
  - )
  // And then meld stderr alongside stdin and stdout
  .and_then(|(stdin, stdout)| sys::dup(sys::STDERR_FILENO)
  .map(|fd| unsafe { File::from_raw_fd(fd) })
  @@ -28,8 +27,10 @@ pub(crate) fn duplicate_streams() -> io::Result<(File, File, File)> {
  )
  }
  -pub(crate) fn redirect_streams(inp: File, out: File, err: File) {
  +pub(crate) fn redirect_streams(inp: Option<File>, out: File, err: File) {
  + if let Some(inp) = inp {
  redir(inp.as_raw_fd(), sys::STDIN_FILENO);
  + }
  redir(out.as_raw_fd(), sys::STDOUT_FILENO);
  redir(err.as_raw_fd(), sys::STDERR_FILENO);
  }
  