diff --git a/src/context/context.rs b/src/context/context.rs index d971cee..a81fa61 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -31,6 +31,8 @@ pub enum Status { pub struct Context { /// The ID of this context pub id: ContextId, + /// The group ID of this context + pub pgid: ContextId, /// The ID of the parent context pub ppid: ContextId, /// The real user id @@ -99,6 +101,7 @@ impl Context { pub fn new(id: ContextId) -> Context { Context { id: id, + pgid: id, ppid: ContextId::from(0), ruid: 0, rgid: 0, diff --git a/src/scheme/sys/context.rs b/src/scheme/sys/context.rs index f0bec7e..5712977 100644 --- a/src/scheme/sys/context.rs +++ b/src/scheme/sys/context.rs @@ -5,8 +5,9 @@ use context; use syscall::error::Result; pub fn resource() -> Result> { - let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", + let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", "PID", + "PGID", "PPID", "RUID", "RGID", @@ -89,8 +90,9 @@ pub fn resource() -> Result> { let name_bytes = context.name.lock(); let name = str::from_utf8(&name_bytes).unwrap_or(""); - string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", + string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", context.id.into(), + context.pgid.into(), context.ppid.into(), context.ruid, context.rgid, diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 77e6412..a443d72 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -83,6 +83,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_FUTEX => futex(validate_slice_mut(b as *mut i32, 1).map(|uaddr| &mut uaddr[0])?, c, d as i32, e, f as *mut i32), SYS_BRK => brk(b), SYS_GETPID => getpid().map(ContextId::into), + SYS_GETPGID => getpgid(ContextId::from(b)).map(ContextId::into), SYS_GETPPID => getppid().map(ContextId::into), SYS_CLONE => clone(b, bp).map(ContextId::into), SYS_EXIT => exit((b & 0xFF) << 8), @@ -99,6 +100,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_GETNS => getns(), SYS_GETUID => getuid(), SYS_MKNS => mkns(validate_slice(b as *const [usize; 2], c)?), + SYS_SETPGID => setpgid(ContextId::from(b), ContextId::from(c)), SYS_SETREUID => setreuid(b as u32, c as u32), SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)), SYS_SETREGID => setregid(b as u32, c as u32), diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 1138fa6..aed80e3 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -64,6 +64,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let ppid; let pid; { + let pgid; let ruid; let rgid; let rns; @@ -95,6 +96,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let context = context_lock.read(); ppid = context.id; + pgid = context.pgid; ruid = context.ruid; rgid = context.rgid; rns = context.rns; @@ -331,6 +333,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { pid = context.id; + context.pgid = pgid; context.ppid = ppid; context.ruid = ruid; context.rgid = rgid; @@ -991,6 +994,17 @@ pub fn getpid() -> Result { Ok(context.id) } +pub fn getpgid(pid: ContextId) -> Result { + let contexts = context::contexts(); + let context_lock = if pid.into() == 0 { + contexts.current().ok_or(Error::new(ESRCH))? + } else { + contexts.get(pid).ok_or(Error::new(ESRCH))? + }; + let context = context_lock.read(); + Ok(context.pgid) +} + pub fn getppid() -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -1024,6 +1038,34 @@ pub fn kill(pid: ContextId, sig: usize) -> Result { } } +pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result { + let contexts = context::contexts(); + + let current_pid = { + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + context.id + }; + + let context_lock = if pid.into() == 0 { + contexts.current().ok_or(Error::new(ESRCH))? + } else { + contexts.get(pid).ok_or(Error::new(ESRCH))? + }; + + let mut context = context_lock.write(); + if context.id == current_pid || context.ppid == current_pid { + if pgid.into() == 0 { + context.pgid = context.id; + } else { + context.pgid = pgid; + } + Ok(0) + } else { + Err(Error::new(ESRCH)) + } +} + pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>, restorer: usize) -> Result { if sig > 0 && sig <= 0x7F { let contexts = context::contexts();