mirror of
https://github.com/golang/go
synced 2024-11-21 23:34:42 -07:00
syscall, os, exec: introduce *syscall.SysProcAttr field in os.ProcAttr and exec.Cmd
R=r, bradfitz, alex.brainman, borman, vincent.vanackere CC=golang-dev https://golang.org/cl/4607046
This commit is contained in:
parent
371aa14e06
commit
4d0f2e9195
@ -1284,9 +1284,11 @@ func Attach(pid int) (Process, os.Error) {
|
|||||||
// details.
|
// details.
|
||||||
func StartProcess(argv0 string, argv []string, attr *os.ProcAttr) (Process, os.Error) {
|
func StartProcess(argv0 string, argv []string, attr *os.ProcAttr) (Process, os.Error) {
|
||||||
sysattr := &syscall.ProcAttr{
|
sysattr := &syscall.ProcAttr{
|
||||||
Dir: attr.Dir,
|
Dir: attr.Dir,
|
||||||
Env: attr.Env,
|
Env: attr.Env,
|
||||||
Ptrace: true,
|
Sys: &syscall.SysProcAttr{
|
||||||
|
Ptrace: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
p := newProcess(-1)
|
p := newProcess(-1)
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error records the name of a binary that failed to be be executed
|
// Error records the name of a binary that failed to be be executed
|
||||||
@ -62,6 +63,10 @@ type Cmd struct {
|
|||||||
Stdout io.Writer
|
Stdout io.Writer
|
||||||
Stderr io.Writer
|
Stderr io.Writer
|
||||||
|
|
||||||
|
// SysProcAttr holds optional, operating system-specific attributes.
|
||||||
|
// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
|
||||||
|
SysProcAttr *syscall.SysProcAttr
|
||||||
|
|
||||||
// Process is the underlying process, once started.
|
// Process is the underlying process, once started.
|
||||||
Process *os.Process
|
Process *os.Process
|
||||||
|
|
||||||
@ -225,6 +230,7 @@ func (c *Cmd) Start() os.Error {
|
|||||||
Dir: c.Dir,
|
Dir: c.Dir,
|
||||||
Files: c.childFiles,
|
Files: c.childFiles,
|
||||||
Env: c.envv(),
|
Env: c.envv(),
|
||||||
|
Sys: c.SysProcAttr,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -37,6 +37,12 @@ type ProcAttr struct {
|
|||||||
// depending on the underlying operating system. A nil entry corresponds
|
// depending on the underlying operating system. A nil entry corresponds
|
||||||
// to that file being closed when the process starts.
|
// to that file being closed when the process starts.
|
||||||
Files []*File
|
Files []*File
|
||||||
|
|
||||||
|
// Operating system-specific process creation attributes.
|
||||||
|
// Note that setting this field means that your program
|
||||||
|
// may not execute properly or even compile on some
|
||||||
|
// operating systems.
|
||||||
|
Sys *syscall.SysProcAttr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getpid returns the process id of the caller.
|
// Getpid returns the process id of the caller.
|
||||||
|
@ -15,6 +15,7 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err E
|
|||||||
sysattr := &syscall.ProcAttr{
|
sysattr := &syscall.ProcAttr{
|
||||||
Dir: attr.Dir,
|
Dir: attr.Dir,
|
||||||
Env: attr.Env,
|
Env: attr.Env,
|
||||||
|
Sys: attr.Sys,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create array of integer (system) fds.
|
// Create array of integer (system) fds.
|
||||||
|
@ -30,6 +30,7 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err E
|
|||||||
sysattr := &syscall.ProcAttr{
|
sysattr := &syscall.ProcAttr{
|
||||||
Dir: attr.Dir,
|
Dir: attr.Dir,
|
||||||
Env: attr.Env,
|
Env: attr.Env,
|
||||||
|
Sys: attr.Sys,
|
||||||
}
|
}
|
||||||
if sysattr.Env == nil {
|
if sysattr.Env == nil {
|
||||||
sysattr.Env = Environ()
|
sysattr.Env = Environ()
|
||||||
|
@ -169,7 +169,7 @@ func init() {
|
|||||||
// no rescheduling, no malloc calls, and no new stack segments.
|
// no rescheduling, no malloc calls, and no new stack segments.
|
||||||
// The calls to RawSyscall are okay because they are assembly
|
// The calls to RawSyscall are okay because they are assembly
|
||||||
// functions that do not grow the stack.
|
// functions that do not grow the stack.
|
||||||
func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, chroot, dir *byte, attr *ProcAttr, fdsToClose []int, pipe int) (pid int, err Error) {
|
func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, attr *ProcAttr, fdsToClose []int, pipe int, rflag int) (pid int, err Error) {
|
||||||
// Declare all variables at top in case any
|
// Declare all variables at top in case any
|
||||||
// declarations require heap allocation (e.g., errbuf).
|
// declarations require heap allocation (e.g., errbuf).
|
||||||
var (
|
var (
|
||||||
@ -190,7 +190,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, chroot, dir *
|
|||||||
|
|
||||||
// About to call fork.
|
// About to call fork.
|
||||||
// No more allocation or calls of non-assembly functions.
|
// No more allocation or calls of non-assembly functions.
|
||||||
r1, _, _ = RawSyscall(SYS_RFORK, uintptr(RFPROC|RFFDG|RFREND|clearenv), 0, 0)
|
r1, _, _ = RawSyscall(SYS_RFORK, uintptr(RFPROC|RFFDG|RFREND|clearenv|rflag), 0, 0)
|
||||||
|
|
||||||
if r1 != 0 {
|
if r1 != 0 {
|
||||||
if int(r1) == -1 {
|
if int(r1) == -1 {
|
||||||
@ -338,14 +338,18 @@ type envItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProcAttr struct {
|
type ProcAttr struct {
|
||||||
Dir string // Current working directory.
|
Dir string // Current working directory.
|
||||||
Env []string // Environment.
|
Env []string // Environment.
|
||||||
Files []int // File descriptors.
|
Files []int // File descriptors.
|
||||||
Chroot string // Chroot.
|
Sys *SysProcAttr
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeroAttributes ProcAttr
|
type SysProcAttr struct {
|
||||||
|
Rfork int // additional flags to pass to rfork
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroProcAttr ProcAttr
|
||||||
|
var zeroSysProcAttr SysProcAttr
|
||||||
|
|
||||||
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error) {
|
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error) {
|
||||||
var (
|
var (
|
||||||
@ -356,7 +360,11 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error)
|
|||||||
)
|
)
|
||||||
|
|
||||||
if attr == nil {
|
if attr == nil {
|
||||||
attr = &zeroAttributes
|
attr = &zeroProcAttr
|
||||||
|
}
|
||||||
|
sys := attr.Sys
|
||||||
|
if sys == nil {
|
||||||
|
sys = &zeroSysProcAttr
|
||||||
}
|
}
|
||||||
|
|
||||||
p[0] = -1
|
p[0] = -1
|
||||||
@ -366,10 +374,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error)
|
|||||||
argv0p := StringBytePtr(argv0)
|
argv0p := StringBytePtr(argv0)
|
||||||
argvp := StringSlicePtr(argv)
|
argvp := StringSlicePtr(argv)
|
||||||
|
|
||||||
var chroot *byte
|
|
||||||
if attr.Chroot != "" {
|
|
||||||
chroot = StringBytePtr(attr.Chroot)
|
|
||||||
}
|
|
||||||
var dir *byte
|
var dir *byte
|
||||||
if attr.Dir != "" {
|
if attr.Dir != "" {
|
||||||
dir = StringBytePtr(attr.Dir)
|
dir = StringBytePtr(attr.Dir)
|
||||||
@ -439,7 +443,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error)
|
|||||||
fdsToClose = append(fdsToClose, p[0])
|
fdsToClose = append(fdsToClose, p[0])
|
||||||
|
|
||||||
// Kick off child.
|
// Kick off child.
|
||||||
pid, err = forkAndExecInChild(argv0p, argvp, envvParsed, chroot, dir, attr, fdsToClose, p[1])
|
pid, err = forkAndExecInChild(argv0p, argvp, envvParsed, dir, attr, fdsToClose, p[1], sys.Rfork)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if p[0] >= 0 {
|
if p[0] >= 0 {
|
||||||
|
@ -96,7 +96,7 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
|
|||||||
// no rescheduling, no malloc calls, and no new stack segments.
|
// no rescheduling, no malloc calls, and no new stack segments.
|
||||||
// The calls to RawSyscall are okay because they are assembly
|
// The calls to RawSyscall are okay because they are assembly
|
||||||
// functions that do not grow the stack.
|
// functions that do not grow the stack.
|
||||||
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, pipe int) (pid int, err int) {
|
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err int) {
|
||||||
// Declare all variables at top in case any
|
// Declare all variables at top in case any
|
||||||
// declarations require heap allocation (e.g., err1).
|
// declarations require heap allocation (e.g., err1).
|
||||||
var r1, r2, err1 uintptr
|
var r1, r2, err1 uintptr
|
||||||
@ -131,7 +131,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
|
|||||||
// Fork succeeded, now in child.
|
// Fork succeeded, now in child.
|
||||||
|
|
||||||
// Enable tracing if requested.
|
// Enable tracing if requested.
|
||||||
if attr.Ptrace {
|
if sys.Ptrace {
|
||||||
_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
|
_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
@ -139,7 +139,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Session ID
|
// Session ID
|
||||||
if attr.Setsid {
|
if sys.Setsid {
|
||||||
_, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
|
_, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
@ -155,21 +155,21 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// User and groups
|
// User and groups
|
||||||
if attr.Credential != nil {
|
if cred := sys.Credential; cred != nil {
|
||||||
ngroups := uintptr(len(attr.Credential.Groups))
|
ngroups := uintptr(len(cred.Groups))
|
||||||
groups := uintptr(0)
|
groups := uintptr(0)
|
||||||
if ngroups > 0 {
|
if ngroups > 0 {
|
||||||
groups = uintptr(unsafe.Pointer(&attr.Credential.Groups[0]))
|
groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
|
||||||
}
|
}
|
||||||
_, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0)
|
_, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
_, _, err1 = RawSyscall(SYS_SETGID, uintptr(attr.Credential.Gid), 0, 0)
|
_, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
_, _, err1 = RawSyscall(SYS_SETUID, uintptr(attr.Credential.Uid), 0, 0)
|
_, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
@ -267,16 +267,21 @@ type Credential struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProcAttr struct {
|
type ProcAttr struct {
|
||||||
Setsid bool // Create session.
|
Dir string // Current working directory.
|
||||||
Ptrace bool // Enable tracing.
|
Env []string // Environment.
|
||||||
Dir string // Current working directory.
|
Files []int // File descriptors.
|
||||||
Env []string // Environment.
|
Sys *SysProcAttr
|
||||||
Files []int // File descriptors.
|
|
||||||
Chroot string // Chroot.
|
|
||||||
Credential *Credential // Credential.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeroAttributes ProcAttr
|
type SysProcAttr struct {
|
||||||
|
Chroot string // Chroot.
|
||||||
|
Credential *Credential // Credential.
|
||||||
|
Ptrace bool // Enable tracing.
|
||||||
|
Setsid bool // Create session.
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroProcAttr ProcAttr
|
||||||
|
var zeroSysProcAttr SysProcAttr
|
||||||
|
|
||||||
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
|
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
|
||||||
var p [2]int
|
var p [2]int
|
||||||
@ -285,7 +290,11 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
|
|||||||
var wstatus WaitStatus
|
var wstatus WaitStatus
|
||||||
|
|
||||||
if attr == nil {
|
if attr == nil {
|
||||||
attr = &zeroAttributes
|
attr = &zeroProcAttr
|
||||||
|
}
|
||||||
|
sys := attr.Sys
|
||||||
|
if sys == nil {
|
||||||
|
sys = &zeroSysProcAttr
|
||||||
}
|
}
|
||||||
|
|
||||||
p[0] = -1
|
p[0] = -1
|
||||||
@ -301,8 +310,8 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var chroot *byte
|
var chroot *byte
|
||||||
if attr.Chroot != "" {
|
if sys.Chroot != "" {
|
||||||
chroot = StringBytePtr(attr.Chroot)
|
chroot = StringBytePtr(sys.Chroot)
|
||||||
}
|
}
|
||||||
var dir *byte
|
var dir *byte
|
||||||
if attr.Dir != "" {
|
if attr.Dir != "" {
|
||||||
@ -326,7 +335,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Kick off child.
|
// Kick off child.
|
||||||
pid, err = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, p[1])
|
pid, err = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
error:
|
error:
|
||||||
if p[0] >= 0 {
|
if p[0] >= 0 {
|
||||||
|
@ -218,22 +218,32 @@ func joinExeDirAndFName(dir, p string) (name string, err int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProcAttr struct {
|
type ProcAttr struct {
|
||||||
Dir string
|
Dir string
|
||||||
Env []string
|
Env []string
|
||||||
Files []int
|
Files []int
|
||||||
|
Sys *SysProcAttr
|
||||||
|
}
|
||||||
|
|
||||||
|
type SysProcAttr struct {
|
||||||
HideWindow bool
|
HideWindow bool
|
||||||
CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
|
CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeroAttributes ProcAttr
|
var zeroProcAttr ProcAttr
|
||||||
|
var zeroSysProcAttr SysProcAttr
|
||||||
|
|
||||||
func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
|
func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
|
||||||
if len(argv0) == 0 {
|
if len(argv0) == 0 {
|
||||||
return 0, 0, EWINDOWS
|
return 0, 0, EWINDOWS
|
||||||
}
|
}
|
||||||
if attr == nil {
|
if attr == nil {
|
||||||
attr = &zeroAttributes
|
attr = &zeroProcAttr
|
||||||
}
|
}
|
||||||
|
sys := attr.Sys
|
||||||
|
if sys == nil {
|
||||||
|
sys = &zeroSysProcAttr
|
||||||
|
}
|
||||||
|
|
||||||
if len(attr.Files) > 3 {
|
if len(attr.Files) > 3 {
|
||||||
return 0, 0, EWINDOWS
|
return 0, 0, EWINDOWS
|
||||||
}
|
}
|
||||||
@ -257,8 +267,8 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
|
|||||||
// Windows CreateProcess takes the command line as a single string:
|
// Windows CreateProcess takes the command line as a single string:
|
||||||
// use attr.CmdLine if set, else build the command line by escaping
|
// use attr.CmdLine if set, else build the command line by escaping
|
||||||
// and joining each argument with spaces
|
// and joining each argument with spaces
|
||||||
if attr.CmdLine != "" {
|
if sys.CmdLine != "" {
|
||||||
cmdline = attr.CmdLine
|
cmdline = sys.CmdLine
|
||||||
} else {
|
} else {
|
||||||
cmdline = makeCmdLine(argv)
|
cmdline = makeCmdLine(argv)
|
||||||
}
|
}
|
||||||
@ -293,7 +303,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
|
|||||||
si := new(StartupInfo)
|
si := new(StartupInfo)
|
||||||
si.Cb = uint32(unsafe.Sizeof(*si))
|
si.Cb = uint32(unsafe.Sizeof(*si))
|
||||||
si.Flags = STARTF_USESTDHANDLES
|
si.Flags = STARTF_USESTDHANDLES
|
||||||
if attr.HideWindow {
|
if sys.HideWindow {
|
||||||
si.Flags |= STARTF_USESHOWWINDOW
|
si.Flags |= STARTF_USESHOWWINDOW
|
||||||
si.ShowWindow = SW_HIDE
|
si.ShowWindow = SW_HIDE
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user