Skip to content

Commit

Permalink
Merge pull request #89 from utam0k/tty-refactor
Browse files Browse the repository at this point in the history
clean up around the tty.
  • Loading branch information
Furisto authored Jun 15, 2021
2 parents ea5b8f9 + 11810e7 commit 17a036d
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 65 deletions.
2 changes: 1 addition & 1 deletion src/cgroups/v2/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl Manager {
Ok(controllers)
}

fn write_controllers(path: &Path, controllers: &Vec<String>) -> Result<()> {
fn write_controllers(path: &Path, controllers: &[String]) -> Result<()> {
for controller in controllers {
common::write_cgroup_file_str(path.join(CGROUP_SUBTREE_CONTROL), controller)?;
}
Expand Down
19 changes: 8 additions & 11 deletions src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub struct Create {
bundle: PathBuf,
/// Unix socket (file) path , which will receive file descriptor of the writing end of the pseudoterminal
#[clap(short, long)]
console_socket: Option<String>,
console_socket: Option<PathBuf>,
/// name of the container instance to be started
pub container_id: String,
}
Expand Down Expand Up @@ -86,16 +86,13 @@ impl Create {
let mut notify_socket: NotifyListener = NotifyListener::new(&container_dir)?;
// convert path of root file system of the container to absolute path
let rootfs = fs::canonicalize(&spec.root.path)?;

// if socket file path is given in commandline options,
// get file descriptors of console and console socket
let (csocketfd, _consolefd) = {
if let Some(console_socket) = &self.console_socket {
let (csocketfd, consolefd) =
tty::load_console_sockets(&container_dir, console_socket)?;
(Some(csocketfd), Some(consolefd))
} else {
(None, None)
}
// get file descriptors of console socket
let csocketfd = if let Some(console_socket) = &self.console_socket {
Some(tty::setup_console_socket(&container_dir, console_socket)?)
} else {
None
};

let process = run_container(
Expand Down Expand Up @@ -162,7 +159,7 @@ fn run_container<P: AsRef<Path>>(

// set up tty if specified
if let Some(csocketfd) = csocketfd {
tty::ready(csocketfd)?;
tty::setup_console(csocketfd)?;
}

// set namespaces
Expand Down
1 change: 0 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
//! Container Runtime written in Rust, inspired by [railcar](https://github.com/oracle/railcar)
//! This crate provides a container runtime which can be used by a high-level container runtime to run containers.
use procfs;
use std::fs;
use std::path::{Path, PathBuf};

Expand Down
2 changes: 1 addition & 1 deletion src/namespaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Process (processes in a namespace have two PIDs, one for the global PID,
//! which is used by the main system and the second one is for the child within the process tree),
//! Interprocess Communication (Control or communication between processes),
//! Network (which network devices can be seen by the processes in the namespace), User (User configs),
//! Network (which network devices can be seen by the processes in the namespace), User (User configs),
//! UTS (hostname and domain information, processes will think they're running on servers with different names),
//! Cgroup (Resource limits, execution priority etc.)
Expand Down
77 changes: 33 additions & 44 deletions src/tty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,21 @@ use std::path::Path;

use anyhow::{bail, Result};
use nix::errno::Errno;
use nix::fcntl;
use nix::sys::socket;
use nix::sys::stat;
use nix::sys::uio;
use nix::unistd::{close, setsid};

use crate::stdio;
use crate::stdio::FileDescriptor;

pub fn ready(console_fd: FileDescriptor) -> Result<()> {
let openpty_result = nix::pty::openpty(None, None)?;
let data: &[u8] = b"/dev/ptmx";
let iov = [nix::sys::uio::IoVec::from_slice(data)];
let fds = [openpty_result.master];
let cmsg = socket::ControlMessage::ScmRights(&fds);
socket::sendmsg(
console_fd.as_raw_fd(),
&iov,
&[cmsg],
socket::MsgFlags::empty(),
None,
)?;
// TODO: Handling when there isn't console-socket.

setsid()?;
if unsafe { libc::ioctl(openpty_result.slave, libc::TIOCSCTTY) } < 0 {
log::warn!("could not TIOCSCTTY");
};
let slave = FileDescriptor::from(openpty_result.slave);
stdio::connect_stdio(&slave, &slave, &slave).expect("could not dup tty to stderr");
close(console_fd.as_raw_fd())?;
Ok(())
}

pub fn load_console_sockets(
pub fn setup_console_socket(
container_dir: &Path,
console_socket: &str,
) -> Result<(FileDescriptor, FileDescriptor)> {
let csocket = "console-stdout";
symlink(console_socket, container_dir.join(csocket))?;
console_socket_path: &Path,
) -> Result<FileDescriptor> {
let csocket = "console-socket";
symlink(console_socket_path, container_dir.join(csocket))?;

let mut csocketfd = socket::socket(
socket::AddressFamily::Unix,
Expand All @@ -63,19 +40,31 @@ pub fn load_console_sockets(
}
Ok(()) => csocketfd,
};
let console = "console";
let consolefd = match fcntl::open(
&*console,
fcntl::OFlag::O_NOCTTY | fcntl::OFlag::O_RDWR,
stat::Mode::empty(),
) {
Err(e) => {
if e != ::nix::Error::Sys(Errno::ENOENT) {
bail!("failed to open {}", console);
}
-1
}
Ok(fd) => fd,
Ok(csocketfd.into())
}

pub fn setup_console(console_fd: FileDescriptor) -> Result<()> {
// You can also access pty master, but it is better to use the API.
// ref. https://github.com/containerd/containerd/blob/261c107ffc4ff681bc73988f64e3f60c32233b37/vendor/github.com/containerd/go-runc/console.go#L139-L154
let openpty_result = nix::pty::openpty(None, None)?;
let pty_name: &[u8] = b"/dev/ptmx";
let iov = [uio::IoVec::from_slice(pty_name)];
let fds = [openpty_result.master];
let cmsg = socket::ControlMessage::ScmRights(&fds);
socket::sendmsg(
console_fd.as_raw_fd(),
&iov,
&[cmsg],
socket::MsgFlags::empty(),
None,
)?;

setsid()?;
if unsafe { libc::ioctl(openpty_result.slave, libc::TIOCSCTTY) } < 0 {
log::warn!("could not TIOCSCTTY");
};
Ok((csocketfd.into(), consolefd.into()))
let slave = FileDescriptor::from(openpty_result.slave);
stdio::connect_stdio(&slave, &slave, &slave).expect("could not dup tty to stderr");
close(console_fd.as_raw_fd())?;
Ok(())
}
11 changes: 4 additions & 7 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,10 @@ pub fn do_exec(path: impl AsRef<Path>, args: &[String], envs: &[String]) -> Resu
env::vars().for_each(|(key, _value)| std::env::remove_var(key));
// set env vars
envs.iter().for_each(|e| {
let mut split = e.split("=");
match split.next() {
Some(key) => {
let value: String = split.collect::<Vec<&str>>().join("=");
env::set_var(key, value)
}
None => {}
let mut split = e.split('=');
if let Some(key) = split.next() {
let value: String = split.collect::<Vec<&str>>().join("=");
env::set_var(key, value)
};
});

Expand Down

0 comments on commit 17a036d

Please sign in to comment.