]> Cypherpunks repositories - gostls13.git/commitdiff
syscall, os, exec: introduce *syscall.SysProcAttr field in os.ProcAttr and exec.Cmd
authorRuss Cox <rsc@golang.org>
Tue, 14 Jun 2011 14:49:34 +0000 (10:49 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 14 Jun 2011 14:49:34 +0000 (10:49 -0400)
R=r, bradfitz, alex.brainman, borman, vincent.vanackere
CC=golang-dev
https://golang.org/cl/4607046

src/pkg/debug/proc/proc_linux.go
src/pkg/exec/exec.go
src/pkg/os/exec.go
src/pkg/os/exec_plan9.go
src/pkg/os/exec_posix.go
src/pkg/syscall/exec_plan9.go
src/pkg/syscall/exec_unix.go
src/pkg/syscall/exec_windows.go

index 153c3e99b75d90f1972653f5b6fe197a5178a5c8..5831b0e9795f814c6f7f2d180501f8bd09b2d143 100644 (file)
@@ -1284,9 +1284,11 @@ func Attach(pid int) (Process, os.Error) {
 // details.
 func StartProcess(argv0 string, argv []string, attr *os.ProcAttr) (Process, os.Error) {
        sysattr := &syscall.ProcAttr{
-               Dir:    attr.Dir,
-               Env:    attr.Env,
-               Ptrace: true,
+               Dir: attr.Dir,
+               Env: attr.Env,
+               Sys: &syscall.SysProcAttr{
+                       Ptrace: true,
+               },
        }
        p := newProcess(-1)
 
index 935f24c2179b7f480c315293fe7dcf4da6320870..5b988d5eb41e113d0f03379749fbbea23480989b 100644 (file)
@@ -12,6 +12,7 @@ import (
        "io"
        "os"
        "strconv"
+       "syscall"
 )
 
 // Error records the name of a binary that failed to be be executed
@@ -62,6 +63,10 @@ type Cmd struct {
        Stdout 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 *os.Process
 
@@ -225,6 +230,7 @@ func (c *Cmd) Start() os.Error {
                Dir:   c.Dir,
                Files: c.childFiles,
                Env:   c.envv(),
+               Sys:   c.SysProcAttr,
        })
        if err != nil {
                return err
index f62caf9a069b15b8fa7b10b24f92925a3b3a17d0..e2234f14a065cf43f319a191b1ec4e221e712ba9 100644 (file)
@@ -37,6 +37,12 @@ type ProcAttr struct {
        // depending on the underlying operating system.  A nil entry corresponds
        // to that file being closed when the process starts.
        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.
index 11874aba6779fc37a66df990545cc3089ffbed8c..299d3fa4db3ecfb56cb3754a5781ed879fdfd3c9 100644 (file)
@@ -15,6 +15,7 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err E
        sysattr := &syscall.ProcAttr{
                Dir: attr.Dir,
                Env: attr.Env,
+               Sys: attr.Sys,
        }
 
        // Create array of integer (system) fds.
index bf992ef42ef49774d8a368e2fff7e5b80f7689ce..734bf887b393bcb6158dc32e89bdc1484d583025 100644 (file)
@@ -30,6 +30,7 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err E
        sysattr := &syscall.ProcAttr{
                Dir: attr.Dir,
                Env: attr.Env,
+               Sys: attr.Sys,
        }
        if sysattr.Env == nil {
                sysattr.Env = Environ()
index 01edb49ecf7b8b7e39919a7636a25a6404b1e9be..66ab1fced6743c12d695c43ec97b5d1ab65dccc4 100644 (file)
@@ -169,7 +169,7 @@ func init() {
 // no rescheduling, no malloc calls, and no new stack segments.
 // The calls to RawSyscall are okay because they are assembly
 // 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
        // declarations require heap allocation (e.g., errbuf).
        var (
@@ -190,7 +190,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, chroot, dir *
 
        // About to call fork.
        // 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 int(r1) == -1 {
@@ -338,14 +338,18 @@ type envItem struct {
 }
 
 type ProcAttr struct {
-       Dir    string   // Current working directory.
-       Env    []string // Environment.
-       Files  []int    // File descriptors.
-       Chroot string   // Chroot.
+       Dir   string   // Current working directory.
+       Env   []string // Environment.
+       Files []int    // File descriptors.
+       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) {
        var (
@@ -356,7 +360,11 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error)
        )
 
        if attr == nil {
-               attr = &zeroAttributes
+               attr = &zeroProcAttr
+       }
+       sys := attr.Sys
+       if sys == nil {
+               sys = &zeroSysProcAttr
        }
 
        p[0] = -1
@@ -366,10 +374,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error)
        argv0p := StringBytePtr(argv0)
        argvp := StringSlicePtr(argv)
 
-       var chroot *byte
-       if attr.Chroot != "" {
-               chroot = StringBytePtr(attr.Chroot)
-       }
        var dir *byte
        if 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])
 
        // 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 p[0] >= 0 {
index dee30226886a4401ad0117ed62e5f144c103b80a..31bed926a3d802446300e80dec900d5514cf84eb 100644 (file)
@@ -96,7 +96,7 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
 // no rescheduling, no malloc calls, and no new stack segments.
 // The calls to RawSyscall are okay because they are assembly
 // 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
        // declarations require heap allocation (e.g., err1).
        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.
 
        // Enable tracing if requested.
-       if attr.Ptrace {
+       if sys.Ptrace {
                _, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
                if err1 != 0 {
                        goto childerror
@@ -139,7 +139,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        }
 
        // Session ID
-       if attr.Setsid {
+       if sys.Setsid {
                _, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
                if err1 != 0 {
                        goto childerror
@@ -155,21 +155,21 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        }
 
        // User and groups
-       if attr.Credential != nil {
-               ngroups := uintptr(len(attr.Credential.Groups))
+       if cred := sys.Credential; cred != nil {
+               ngroups := uintptr(len(cred.Groups))
                groups := uintptr(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)
                if err1 != 0 {
                        goto childerror
                }
-               _, _, err1 = RawSyscall(SYS_SETGID, uintptr(attr.Credential.Gid), 0, 0)
+               _, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
                if err1 != 0 {
                        goto childerror
                }
-               _, _, err1 = RawSyscall(SYS_SETUID, uintptr(attr.Credential.Uid), 0, 0)
+               _, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
                if err1 != 0 {
                        goto childerror
                }
@@ -267,16 +267,21 @@ type Credential struct {
 }
 
 type ProcAttr struct {
-       Setsid     bool        // Create session.
-       Ptrace     bool        // Enable tracing.
-       Dir        string      // Current working directory.
-       Env        []string    // Environment.
-       Files      []int       // File descriptors.
+       Dir   string   // Current working directory.
+       Env   []string // Environment.
+       Files []int    // File descriptors.
+       Sys   *SysProcAttr
+}
+
+type SysProcAttr struct {
        Chroot     string      // Chroot.
        Credential *Credential // Credential.
+       Ptrace     bool        // Enable tracing.
+       Setsid     bool        // Create session.
 }
 
-var zeroAttributes ProcAttr
+var zeroProcAttr ProcAttr
+var zeroSysProcAttr SysProcAttr
 
 func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
        var p [2]int
@@ -285,7 +290,11 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
        var wstatus WaitStatus
 
        if attr == nil {
-               attr = &zeroAttributes
+               attr = &zeroProcAttr
+       }
+       sys := attr.Sys
+       if sys == nil {
+               sys = &zeroSysProcAttr
        }
 
        p[0] = -1
@@ -301,8 +310,8 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
        }
 
        var chroot *byte
-       if attr.Chroot != "" {
-               chroot = StringBytePtr(attr.Chroot)
+       if sys.Chroot != "" {
+               chroot = StringBytePtr(sys.Chroot)
        }
        var dir *byte
        if attr.Dir != "" {
@@ -326,7 +335,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
        }
 
        // 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 {
        error:
                if p[0] >= 0 {
index b25f4a65072110e23a510ddbf6536e41a955d8d9..96a01e7675f05e81f72fdc4448ffba9c89821f62 100644 (file)
@@ -218,22 +218,32 @@ func joinExeDirAndFName(dir, p string) (name string, err int) {
 }
 
 type ProcAttr struct {
-       Dir        string
-       Env        []string
-       Files      []int
+       Dir   string
+       Env   []string
+       Files []int
+       Sys   *SysProcAttr
+}
+
+type SysProcAttr struct {
        HideWindow bool
        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) {
        if len(argv0) == 0 {
                return 0, 0, EWINDOWS
        }
        if attr == nil {
-               attr = &zeroAttributes
+               attr = &zeroProcAttr
        }
+       sys := attr.Sys
+       if sys == nil {
+               sys = &zeroSysProcAttr
+       }
+
        if len(attr.Files) > 3 {
                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:
        // use attr.CmdLine if set, else build the command line by escaping
        // and joining each argument with spaces
-       if attr.CmdLine != "" {
-               cmdline = attr.CmdLine
+       if sys.CmdLine != "" {
+               cmdline = sys.CmdLine
        } else {
                cmdline = makeCmdLine(argv)
        }
@@ -293,7 +303,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
        si := new(StartupInfo)
        si.Cb = uint32(unsafe.Sizeof(*si))
        si.Flags = STARTF_USESTDHANDLES
-       if attr.HideWindow {
+       if sys.HideWindow {
                si.Flags |= STARTF_USESHOWWINDOW
                si.ShowWindow = SW_HIDE
        }