mirror of
https://github.com/golang/go
synced 2024-11-22 00:34:40 -07:00
os: implement new Process api
Fixes #1004. Fixes #1460. R=mattn, r, niemeyer, rog, rsc CC=golang-dev https://golang.org/cl/4029053
This commit is contained in:
parent
8b9d6e38be
commit
4ecebfea53
@ -32,10 +32,11 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err)
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2})
|
p, err := os.StartProcess(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err)
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
|
defer p.Release()
|
||||||
r0.Close()
|
r0.Close()
|
||||||
w1.Close()
|
w1.Close()
|
||||||
w2.Close()
|
w2.Close()
|
||||||
@ -55,7 +56,7 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
|||||||
<-c
|
<-c
|
||||||
<-c
|
<-c
|
||||||
|
|
||||||
w, err := os.Wait(pid, 0)
|
w, err := p.Wait(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err)
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
|
@ -83,20 +83,21 @@ func exec(rw http.ResponseWriter, args []string) (status int) {
|
|||||||
if *verbose {
|
if *verbose {
|
||||||
log.Printf("executing %v", args)
|
log.Printf("executing %v", args)
|
||||||
}
|
}
|
||||||
pid, err := os.ForkExec(bin, args, os.Environ(), *goroot, fds)
|
p, err := os.StartProcess(bin, args, os.Environ(), *goroot, fds)
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
w.Close()
|
w.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("os.ForkExec(%q): %v", bin, err)
|
log.Printf("os.StartProcess(%q): %v", bin, err)
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
defer p.Release()
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
io.Copy(&buf, r)
|
io.Copy(&buf, r)
|
||||||
wait, err := os.Wait(pid, 0)
|
wait, err := p.Wait(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Stderr.Write(buf.Bytes())
|
os.Stderr.Write(buf.Bytes())
|
||||||
log.Printf("os.Wait(%d, 0): %v", pid, err)
|
log.Printf("os.Wait(%d, 0): %v", p.Pid, err)
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
status = wait.ExitStatus()
|
status = wait.ExitStatus()
|
||||||
|
@ -22,12 +22,12 @@ const (
|
|||||||
// Stdin, Stdout, and Stderr are Files representing pipes
|
// Stdin, Stdout, and Stderr are Files representing pipes
|
||||||
// connected to the running command's standard input, output, and error,
|
// connected to the running command's standard input, output, and error,
|
||||||
// or else nil, depending on the arguments to Run.
|
// or else nil, depending on the arguments to Run.
|
||||||
// Pid is the running command's operating system process ID.
|
// Process represents the underlying operating system process.
|
||||||
type Cmd struct {
|
type Cmd struct {
|
||||||
Stdin *os.File
|
Stdin *os.File
|
||||||
Stdout *os.File
|
Stdout *os.File
|
||||||
Stderr *os.File
|
Stderr *os.File
|
||||||
Pid int
|
Process *os.Process
|
||||||
}
|
}
|
||||||
|
|
||||||
// PathError records the name of a binary that was not
|
// PathError records the name of a binary that was not
|
||||||
@ -88,24 +88,24 @@ func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) {
|
|||||||
// If a parameter is Pipe, then the corresponding field (Stdin, Stdout, Stderr)
|
// If a parameter is Pipe, then the corresponding field (Stdin, Stdout, Stderr)
|
||||||
// of the returned Cmd is the other end of the pipe.
|
// of the returned Cmd is the other end of the pipe.
|
||||||
// Otherwise the field in Cmd is nil.
|
// Otherwise the field in Cmd is nil.
|
||||||
func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (p *Cmd, err os.Error) {
|
func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (c *Cmd, err os.Error) {
|
||||||
p = new(Cmd)
|
c = new(Cmd)
|
||||||
var fd [3]*os.File
|
var fd [3]*os.File
|
||||||
|
|
||||||
if fd[0], p.Stdin, err = modeToFiles(stdin, 0); err != nil {
|
if fd[0], c.Stdin, err = modeToFiles(stdin, 0); err != nil {
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
if fd[1], p.Stdout, err = modeToFiles(stdout, 1); err != nil {
|
if fd[1], c.Stdout, err = modeToFiles(stdout, 1); err != nil {
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
if stderr == MergeWithStdout {
|
if stderr == MergeWithStdout {
|
||||||
fd[2] = fd[1]
|
fd[2] = fd[1]
|
||||||
} else if fd[2], p.Stderr, err = modeToFiles(stderr, 2); err != nil {
|
} else if fd[2], c.Stderr, err = modeToFiles(stderr, 2); err != nil {
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run command.
|
// Run command.
|
||||||
p.Pid, err = os.ForkExec(name, argv, envv, dir, fd[0:])
|
c.Process, err = os.StartProcess(name, argv, envv, dir, fd[0:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int
|
|||||||
if fd[2] != os.Stderr && fd[2] != fd[1] {
|
if fd[2] != os.Stderr && fd[2] != fd[1] {
|
||||||
fd[2].Close()
|
fd[2].Close()
|
||||||
}
|
}
|
||||||
return p, nil
|
return c, nil
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
if fd[0] != os.Stdin && fd[0] != nil {
|
if fd[0] != os.Stdin && fd[0] != nil {
|
||||||
@ -130,63 +130,67 @@ Error:
|
|||||||
if fd[2] != os.Stderr && fd[2] != nil && fd[2] != fd[1] {
|
if fd[2] != os.Stderr && fd[2] != nil && fd[2] != fd[1] {
|
||||||
fd[2].Close()
|
fd[2].Close()
|
||||||
}
|
}
|
||||||
if p.Stdin != nil {
|
if c.Stdin != nil {
|
||||||
p.Stdin.Close()
|
c.Stdin.Close()
|
||||||
}
|
}
|
||||||
if p.Stdout != nil {
|
if c.Stdout != nil {
|
||||||
p.Stdout.Close()
|
c.Stdout.Close()
|
||||||
}
|
}
|
||||||
if p.Stderr != nil {
|
if c.Stderr != nil {
|
||||||
p.Stderr.Close()
|
c.Stderr.Close()
|
||||||
|
}
|
||||||
|
if c.Process != nil {
|
||||||
|
c.Process.Release()
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait waits for the running command p,
|
// Wait waits for the running command c,
|
||||||
// returning the Waitmsg returned by os.Wait and an error.
|
// returning the Waitmsg returned when the process exits.
|
||||||
// The options are passed through to os.Wait.
|
// The options are passed to the process's Wait method.
|
||||||
// Setting options to 0 waits for p to exit;
|
// Setting options to 0 waits for c to exit;
|
||||||
// other options cause Wait to return for other
|
// other options cause Wait to return for other
|
||||||
// process events; see package os for details.
|
// process events; see package os for details.
|
||||||
func (p *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
|
func (c *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
|
||||||
if p.Pid <= 0 {
|
if c.Process == nil {
|
||||||
return nil, os.ErrorString("exec: invalid use of Cmd.Wait")
|
return nil, os.ErrorString("exec: invalid use of Cmd.Wait")
|
||||||
}
|
}
|
||||||
w, err := os.Wait(p.Pid, options)
|
w, err := c.Process.Wait(options)
|
||||||
if w != nil && (w.Exited() || w.Signaled()) {
|
if w != nil && (w.Exited() || w.Signaled()) {
|
||||||
p.Pid = -1
|
c.Process.Release()
|
||||||
|
c.Process = nil
|
||||||
}
|
}
|
||||||
return w, err
|
return w, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close waits for the running command p to exit,
|
// Close waits for the running command c to exit,
|
||||||
// if it hasn't already, and then closes the non-nil file descriptors
|
// if it hasn't already, and then closes the non-nil file descriptors
|
||||||
// p.Stdin, p.Stdout, and p.Stderr.
|
// c.Stdin, c.Stdout, and c.Stderr.
|
||||||
func (p *Cmd) Close() os.Error {
|
func (c *Cmd) Close() os.Error {
|
||||||
if p.Pid > 0 {
|
if c.Process != nil {
|
||||||
// Loop on interrupt, but
|
// Loop on interrupt, but
|
||||||
// ignore other errors -- maybe
|
// ignore other errors -- maybe
|
||||||
// caller has already waited for pid.
|
// caller has already waited for pid.
|
||||||
_, err := p.Wait(0)
|
_, err := c.Wait(0)
|
||||||
for err == os.EINTR {
|
for err == os.EINTR {
|
||||||
_, err = p.Wait(0)
|
_, err = c.Wait(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the FDs that are still open.
|
// Close the FDs that are still open.
|
||||||
var err os.Error
|
var err os.Error
|
||||||
if p.Stdin != nil && p.Stdin.Fd() >= 0 {
|
if c.Stdin != nil && c.Stdin.Fd() >= 0 {
|
||||||
if err1 := p.Stdin.Close(); err1 != nil {
|
if err1 := c.Stdin.Close(); err1 != nil {
|
||||||
err = err1
|
err = err1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Stdout != nil && p.Stdout.Fd() >= 0 {
|
if c.Stdout != nil && c.Stdout.Fd() >= 0 {
|
||||||
if err1 := p.Stdout.Close(); err1 != nil && err != nil {
|
if err1 := c.Stdout.Close(); err1 != nil && err != nil {
|
||||||
err = err1
|
err = err1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Stderr != nil && p.Stderr != p.Stdout && p.Stderr.Fd() >= 0 {
|
if c.Stderr != nil && c.Stderr != c.Stdout && c.Stderr.Fd() >= 0 {
|
||||||
if err1 := p.Stderr.Close(); err1 != nil && err != nil {
|
if err1 := c.Stderr.Close(); err1 != nil && err != nil {
|
||||||
err = err1
|
err = err1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,15 +99,16 @@ func DateServer(rw http.ResponseWriter, req *http.Request) {
|
|||||||
fmt.Fprintf(rw, "pipe: %s\n", err)
|
fmt.Fprintf(rw, "pipe: %s\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pid, err := os.ForkExec("/bin/date", []string{"date"}, os.Environ(), "", []*os.File{nil, w, w})
|
p, err := os.StartProcess("/bin/date", []string{"date"}, os.Environ(), "", []*os.File{nil, w, w})
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
w.Close()
|
w.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(rw, "fork/exec: %s\n", err)
|
fmt.Fprintf(rw, "fork/exec: %s\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer p.Release()
|
||||||
io.Copy(rw, r)
|
io.Copy(rw, r)
|
||||||
wait, err := os.Wait(pid, 0)
|
wait, err := p.Wait(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(rw, "wait: %s\n", err)
|
fmt.Fprintf(rw, "wait: %s\n", err)
|
||||||
return
|
return
|
||||||
|
@ -22,21 +22,25 @@ GOFILES_freebsd=\
|
|||||||
env_unix.go\
|
env_unix.go\
|
||||||
file_unix.go\
|
file_unix.go\
|
||||||
sys_bsd.go\
|
sys_bsd.go\
|
||||||
|
exec_unix.go\
|
||||||
|
|
||||||
GOFILES_darwin=\
|
GOFILES_darwin=\
|
||||||
env_unix.go\
|
env_unix.go\
|
||||||
file_unix.go\
|
file_unix.go\
|
||||||
sys_bsd.go\
|
sys_bsd.go\
|
||||||
|
exec_unix.go\
|
||||||
|
|
||||||
GOFILES_linux=\
|
GOFILES_linux=\
|
||||||
env_unix.go\
|
env_unix.go\
|
||||||
file_unix.go\
|
file_unix.go\
|
||||||
sys_linux.go\
|
sys_linux.go\
|
||||||
|
exec_unix.go\
|
||||||
|
|
||||||
GOFILES_windows=\
|
GOFILES_windows=\
|
||||||
env_windows.go\
|
env_windows.go\
|
||||||
file_windows.go\
|
file_windows.go\
|
||||||
sys_windows.go\
|
sys_windows.go\
|
||||||
|
exec_windows.go\
|
||||||
|
|
||||||
GOFILES+=$(GOFILES_$(GOOS))
|
GOFILES+=$(GOFILES_$(GOOS))
|
||||||
|
|
||||||
|
@ -5,17 +5,29 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ForkExec forks the current process and invokes Exec with the program, arguments,
|
// Process stores the information about a process created by StartProcess.
|
||||||
// and environment specified by name, argv, and envv. It returns the process
|
type Process struct {
|
||||||
// id of the forked process and an Error, if any. The fd array specifies the
|
Pid int
|
||||||
|
handle int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProcess(pid, handle int) *Process {
|
||||||
|
p := &Process{pid, handle}
|
||||||
|
runtime.SetFinalizer(p, (*Process).Release)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartProcess starts a new process with the program, arguments,
|
||||||
|
// and environment specified by name, argv, and envv. The fd array specifies the
|
||||||
// file descriptors to be set up in the new process: fd[0] will be Unix file
|
// file descriptors to be set up in the new process: fd[0] will be Unix file
|
||||||
// descriptor 0 (standard input), fd[1] descriptor 1, and so on. A nil entry
|
// descriptor 0 (standard input), fd[1] descriptor 1, and so on. A nil entry
|
||||||
// will cause the child to have no open file descriptor with that index.
|
// will cause the child to have no open file descriptor with that index.
|
||||||
// If dir is not empty, the child chdirs into the directory before execing the program.
|
// If dir is not empty, the child chdirs into the directory before execing the program.
|
||||||
func ForkExec(name string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
|
func StartProcess(name string, argv []string, envv []string, dir string, fd []*File) (p *Process, err Error) {
|
||||||
if envv == nil {
|
if envv == nil {
|
||||||
envv = Environ()
|
envv = Environ()
|
||||||
}
|
}
|
||||||
@ -29,17 +41,17 @@ func ForkExec(name string, argv []string, envv []string, dir string, fd []*File)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
|
pid, h, e := syscall.StartProcess(name, argv, envv, dir, intfd)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return 0, &PathError{"fork/exec", name, Errno(e)}
|
return nil, &PathError{"fork/exec", name, Errno(e)}
|
||||||
}
|
}
|
||||||
return p, nil
|
return newProcess(pid, h), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec replaces the current process with an execution of the
|
// Exec replaces the current process with an execution of the
|
||||||
// named binary, with arguments argv and environment envv.
|
// named binary, with arguments argv and environment envv.
|
||||||
// If successful, Exec never returns. If it fails, it returns an Error.
|
// If successful, Exec never returns. If it fails, it returns an Error.
|
||||||
// ForkExec is almost always a better way to execute a program.
|
// StartProcess is almost always a better way to execute a program.
|
||||||
func Exec(name string, argv []string, envv []string) Error {
|
func Exec(name string, argv []string, envv []string) Error {
|
||||||
if envv == nil {
|
if envv == nil {
|
||||||
envv = Environ()
|
envv = Environ()
|
||||||
@ -65,37 +77,18 @@ type Waitmsg struct {
|
|||||||
Rusage *syscall.Rusage // System-dependent resource usage info.
|
Rusage *syscall.Rusage // System-dependent resource usage info.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options for Wait.
|
|
||||||
const (
|
|
||||||
WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
|
|
||||||
WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
|
|
||||||
WUNTRACED = syscall.WUNTRACED // Usually an alias for WSTOPPED.
|
|
||||||
WRUSAGE = 1 << 20 // Record resource usage.
|
|
||||||
)
|
|
||||||
|
|
||||||
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
|
|
||||||
// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
|
|
||||||
// the options
|
|
||||||
|
|
||||||
// Wait waits for process pid to exit or stop, and then returns a
|
// Wait waits for process pid to exit or stop, and then returns a
|
||||||
// Waitmsg describing its status and an Error, if any. The options
|
// Waitmsg describing its status and an Error, if any. The options
|
||||||
// (WNOHANG etc.) affect the behavior of the Wait call.
|
// (WNOHANG etc.) affect the behavior of the Wait call.
|
||||||
|
// Wait is equivalent to calling FindProcess and then Wait
|
||||||
|
// and Release on the result.
|
||||||
func Wait(pid int, options int) (w *Waitmsg, err Error) {
|
func Wait(pid int, options int) (w *Waitmsg, err Error) {
|
||||||
var status syscall.WaitStatus
|
p, e := FindProcess(pid)
|
||||||
var rusage *syscall.Rusage
|
if e != nil {
|
||||||
if options&WRUSAGE != 0 {
|
return nil, e
|
||||||
rusage = new(syscall.Rusage)
|
|
||||||
options ^= WRUSAGE
|
|
||||||
}
|
}
|
||||||
pid1, e := syscall.Wait4(pid, &status, options, rusage)
|
defer p.Release()
|
||||||
if e != 0 {
|
return p.Wait(options)
|
||||||
return nil, NewSyscallError("wait", e)
|
|
||||||
}
|
|
||||||
w = new(Waitmsg)
|
|
||||||
w.Pid = pid1
|
|
||||||
w.WaitStatus = status
|
|
||||||
w.Rusage = rusage
|
|
||||||
return w, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert i to decimal string.
|
// Convert i to decimal string.
|
||||||
|
63
src/pkg/os/exec_unix.go
Normal file
63
src/pkg/os/exec_unix.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Options for Wait.
|
||||||
|
const (
|
||||||
|
WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
|
||||||
|
WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
|
||||||
|
WUNTRACED = syscall.WUNTRACED // Usually an alias for WSTOPPED.
|
||||||
|
WRUSAGE = 1 << 20 // Record resource usage.
|
||||||
|
)
|
||||||
|
|
||||||
|
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
|
||||||
|
// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
|
||||||
|
// the options
|
||||||
|
|
||||||
|
// Wait waits for the Process to exit or stop, and then returns a
|
||||||
|
// Waitmsg describing its status and an Error, if any. The options
|
||||||
|
// (WNOHANG etc.) affect the behavior of the Wait call.
|
||||||
|
func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
|
||||||
|
if p.Pid == -1 {
|
||||||
|
return nil, EINVAL
|
||||||
|
}
|
||||||
|
var status syscall.WaitStatus
|
||||||
|
var rusage *syscall.Rusage
|
||||||
|
if options&WRUSAGE != 0 {
|
||||||
|
rusage = new(syscall.Rusage)
|
||||||
|
options ^= WRUSAGE
|
||||||
|
}
|
||||||
|
pid1, e := syscall.Wait4(p.Pid, &status, options, rusage)
|
||||||
|
if e != 0 {
|
||||||
|
return nil, NewSyscallError("wait", e)
|
||||||
|
}
|
||||||
|
w = new(Waitmsg)
|
||||||
|
w.Pid = pid1
|
||||||
|
w.WaitStatus = status
|
||||||
|
w.Rusage = rusage
|
||||||
|
return w, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release releases any resources associated with the Process.
|
||||||
|
func (p *Process) Release() Error {
|
||||||
|
// NOOP for unix.
|
||||||
|
p.Pid = -1
|
||||||
|
// no need for a finalizer anymore
|
||||||
|
runtime.SetFinalizer(p, nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindProcess looks for a running process by its pid.
|
||||||
|
// The Process it returns can be used to obtain information
|
||||||
|
// about the underlying operating system process.
|
||||||
|
func FindProcess(pid int) (p *Process, err Error) {
|
||||||
|
// NOOP for unix.
|
||||||
|
return newProcess(pid, 0), nil
|
||||||
|
}
|
50
src/pkg/os/exec_windows.go
Normal file
50
src/pkg/os/exec_windows.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
|
||||||
|
s, e := syscall.WaitForSingleObject(int32(p.handle), syscall.INFINITE)
|
||||||
|
switch s {
|
||||||
|
case syscall.WAIT_OBJECT_0:
|
||||||
|
break
|
||||||
|
case syscall.WAIT_FAILED:
|
||||||
|
return nil, NewSyscallError("WaitForSingleObject", e)
|
||||||
|
default:
|
||||||
|
return nil, ErrorString("os: unexpected result from WaitForSingleObject")
|
||||||
|
}
|
||||||
|
var ec uint32
|
||||||
|
if ok, e := syscall.GetExitCodeProcess(uint32(p.handle), &ec); !ok {
|
||||||
|
return nil, NewSyscallError("GetExitCodeProcess", e)
|
||||||
|
}
|
||||||
|
return &Waitmsg{p.Pid, syscall.WaitStatus{s, ec}, new(syscall.Rusage)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Process) Release() Error {
|
||||||
|
if p.handle == -1 {
|
||||||
|
return EINVAL
|
||||||
|
}
|
||||||
|
if ok, e := syscall.CloseHandle(int32(p.handle)); !ok {
|
||||||
|
return NewSyscallError("CloseHandle", e)
|
||||||
|
}
|
||||||
|
p.handle = -1
|
||||||
|
// no need for a finalizer anymore
|
||||||
|
runtime.SetFinalizer(p, nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindProcess(pid int) (p *Process, err Error) {
|
||||||
|
const da = syscall.STANDARD_RIGHTS_READ |
|
||||||
|
syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
|
||||||
|
h, e := syscall.OpenProcess(da, false, uint32(pid))
|
||||||
|
if e != 0 {
|
||||||
|
return nil, NewSyscallError("OpenProcess", e)
|
||||||
|
}
|
||||||
|
return newProcess(pid, int(h)), nil
|
||||||
|
}
|
@ -427,10 +427,11 @@ func TestForkExec(t *testing.T) {
|
|||||||
adir = "/"
|
adir = "/"
|
||||||
expect = "/\n"
|
expect = "/\n"
|
||||||
}
|
}
|
||||||
pid, err := ForkExec(cmd, args, nil, adir, []*File{nil, w, Stderr})
|
p, err := StartProcess(cmd, args, nil, adir, []*File{nil, w, Stderr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ForkExec: %v", err)
|
t.Fatalf("StartProcess: %v", err)
|
||||||
}
|
}
|
||||||
|
defer p.Release()
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
@ -440,7 +441,7 @@ func TestForkExec(t *testing.T) {
|
|||||||
args[0] = cmd
|
args[0] = cmd
|
||||||
t.Errorf("exec %q returned %q wanted %q", strings.Join(args, " "), output, expect)
|
t.Errorf("exec %q returned %q wanted %q", strings.Join(args, " "), output, expect)
|
||||||
}
|
}
|
||||||
Wait(pid, 0)
|
p.Wait(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkMode(t *testing.T, path string, mode uint32) {
|
func checkMode(t *testing.T, path string, mode uint32) {
|
||||||
@ -750,15 +751,16 @@ func run(t *testing.T, cmd []string) string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
pid, err := ForkExec("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr})
|
p, err := StartProcess("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer p.Release()
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
io.Copy(&b, r)
|
io.Copy(&b, r)
|
||||||
Wait(pid, 0)
|
p.Wait(0)
|
||||||
output := b.String()
|
output := b.String()
|
||||||
if n := len(output); n > 0 && output[n-1] == '\n' {
|
if n := len(output); n > 0 && output[n-1] == '\n' {
|
||||||
output = output[0 : n-1]
|
output = output[0 : n-1]
|
||||||
|
@ -310,3 +310,9 @@ func Exec(argv0 string, argv []string, envv []string) (err int) {
|
|||||||
uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0])))
|
uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0])))
|
||||||
return int(err1)
|
return int(err1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartProcess wraps ForkExec for package os.
|
||||||
|
func StartProcess(argv0 string, argv []string, envv []string, dir string, fd []int) (pid, handle int, err int) {
|
||||||
|
pid, err = forkExec(argv0, argv, envv, false, dir, fd)
|
||||||
|
return pid, 0, err
|
||||||
|
}
|
||||||
|
@ -117,13 +117,9 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
|
|||||||
|
|
||||||
// TODO(kardia): Add trace
|
// TODO(kardia): Add trace
|
||||||
//The command and arguments are passed via the Command line parameter.
|
//The command and arguments are passed via the Command line parameter.
|
||||||
func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) {
|
func StartProcess(argv0 string, argv []string, envv []string, dir string, fd []int) (pid, handle int, err int) {
|
||||||
if traceme == true {
|
|
||||||
return 0, EWINDOWS
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fd) > 3 {
|
if len(fd) > 3 {
|
||||||
return 0, EWINDOWS
|
return 0, 0, EWINDOWS
|
||||||
}
|
}
|
||||||
|
|
||||||
//CreateProcess will throw an error if the dir is not set to a valid dir
|
//CreateProcess will throw an error if the dir is not set to a valid dir
|
||||||
@ -153,19 +149,19 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
|
|||||||
var currentProc, _ = GetCurrentProcess()
|
var currentProc, _ = GetCurrentProcess()
|
||||||
if len(fd) > 0 && fd[0] > 0 {
|
if len(fd) > 0 && fd[0] > 0 {
|
||||||
if ok, err := DuplicateHandle(currentProc, int32(fd[0]), currentProc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
if ok, err := DuplicateHandle(currentProc, int32(fd[0]), currentProc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
defer CloseHandle(int32(startupInfo.StdInput))
|
defer CloseHandle(int32(startupInfo.StdInput))
|
||||||
}
|
}
|
||||||
if len(fd) > 1 && fd[1] > 0 {
|
if len(fd) > 1 && fd[1] > 0 {
|
||||||
if ok, err := DuplicateHandle(currentProc, int32(fd[1]), currentProc, &startupInfo.StdOutput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
if ok, err := DuplicateHandle(currentProc, int32(fd[1]), currentProc, &startupInfo.StdOutput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
defer CloseHandle(int32(startupInfo.StdOutput))
|
defer CloseHandle(int32(startupInfo.StdOutput))
|
||||||
}
|
}
|
||||||
if len(fd) > 2 && fd[2] > 0 {
|
if len(fd) > 2 && fd[2] > 0 {
|
||||||
if ok, err := DuplicateHandle(currentProc, int32(fd[2]), currentProc, &startupInfo.StdErr, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
if ok, err := DuplicateHandle(currentProc, int32(fd[2]), currentProc, &startupInfo.StdErr, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
defer CloseHandle(int32(startupInfo.StdErr))
|
defer CloseHandle(int32(startupInfo.StdErr))
|
||||||
}
|
}
|
||||||
@ -188,21 +184,12 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
|
|||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
pid = int(processInfo.ProcessId)
|
pid = int(processInfo.ProcessId)
|
||||||
CloseHandle(processInfo.Process)
|
handle = int(processInfo.Process)
|
||||||
CloseHandle(processInfo.Thread)
|
CloseHandle(processInfo.Thread)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
|
|
||||||
return forkExec(argv0, argv, envv, false, dir, fd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PtraceForkExec is like ForkExec, but starts the child in a traced state.
|
|
||||||
func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
|
|
||||||
return forkExec(argv0, argv, envv, true, dir, fd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ordinary exec.
|
// Ordinary exec.
|
||||||
func Exec(argv0 string, argv []string, envv []string) (err int) {
|
func Exec(argv0 string, argv []string, envv []string) (err int) {
|
||||||
return EWINDOWS
|
return EWINDOWS
|
||||||
|
@ -136,6 +136,8 @@ func NewCallback(fn interface{}) uintptr
|
|||||||
//sys GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (ok bool, errno int)
|
//sys GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (ok bool, errno int)
|
||||||
//sys CancelIo(s uint32) (ok bool, errno int)
|
//sys CancelIo(s uint32) (ok bool, errno int)
|
||||||
//sys CreateProcess(appName *int16, commandLine *uint16, procSecurity *int16, threadSecurity *int16, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (ok bool, errno int) = CreateProcessW
|
//sys CreateProcess(appName *int16, commandLine *uint16, procSecurity *int16, threadSecurity *int16, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (ok bool, errno int) = CreateProcessW
|
||||||
|
//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int)
|
||||||
|
//sys GetExitCodeProcess(handle uint32, exitcode *uint32) (ok bool, errno int)
|
||||||
//sys GetStartupInfo(startupInfo *StartupInfo) (ok bool, errno int) = GetStartupInfoW
|
//sys GetStartupInfo(startupInfo *StartupInfo) (ok bool, errno int) = GetStartupInfoW
|
||||||
//sys GetCurrentProcess() (pseudoHandle int32, errno int)
|
//sys GetCurrentProcess() (pseudoHandle int32, errno int)
|
||||||
//sys DuplicateHandle(hSourceProcessHandle int32, hSourceHandle int32, hTargetProcessHandle int32, lpTargetHandle *int32, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (ok bool, errno int)
|
//sys DuplicateHandle(hSourceProcessHandle int32, hSourceHandle int32, hTargetProcessHandle int32, lpTargetHandle *int32, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (ok bool, errno int)
|
||||||
@ -146,8 +148,6 @@ func NewCallback(fn interface{}) uintptr
|
|||||||
//sys CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) = advapi32.CryptAcquireContextW
|
//sys CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) = advapi32.CryptAcquireContextW
|
||||||
//sys CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) = advapi32.CryptReleaseContext
|
//sys CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) = advapi32.CryptReleaseContext
|
||||||
//sys CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno int) = advapi32.CryptGenRandom
|
//sys CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno int) = advapi32.CryptGenRandom
|
||||||
//sys OpenProcess(da uint32,b int, pid uint32) (handle uint32, errno int)
|
|
||||||
//sys GetExitCodeProcess(h uint32, c *uint32) (ok bool, errno int)
|
|
||||||
//sys GetEnvironmentStrings() (envs *uint16, errno int) [failretval==nil] = kernel32.GetEnvironmentStringsW
|
//sys GetEnvironmentStrings() (envs *uint16, errno int) [failretval==nil] = kernel32.GetEnvironmentStringsW
|
||||||
//sys FreeEnvironmentStrings(envs *uint16) (ok bool, errno int) = kernel32.FreeEnvironmentStringsW
|
//sys FreeEnvironmentStrings(envs *uint16) (ok bool, errno int) = kernel32.FreeEnvironmentStringsW
|
||||||
//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) = kernel32.GetEnvironmentVariableW
|
//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) = kernel32.GetEnvironmentVariableW
|
||||||
@ -672,6 +672,32 @@ func WSASendto(s uint32, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invented structures to support what package os expects.
|
||||||
|
type Rusage struct{}
|
||||||
|
|
||||||
|
type WaitStatus struct {
|
||||||
|
Status uint32
|
||||||
|
ExitCode uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WaitStatus) Exited() bool { return true }
|
||||||
|
|
||||||
|
func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
|
||||||
|
|
||||||
|
func (w WaitStatus) Signal() int { return -1 }
|
||||||
|
|
||||||
|
func (w WaitStatus) CoreDump() bool { return false }
|
||||||
|
|
||||||
|
func (w WaitStatus) Stopped() bool { return false }
|
||||||
|
|
||||||
|
func (w WaitStatus) Continued() bool { return false }
|
||||||
|
|
||||||
|
func (w WaitStatus) StopSignal() int { return -1 }
|
||||||
|
|
||||||
|
func (w WaitStatus) Signaled() bool { return true }
|
||||||
|
|
||||||
|
func (w WaitStatus) TrapCause() int { return -1 }
|
||||||
|
|
||||||
// TODO(brainman): fix all needed for net
|
// TODO(brainman): fix all needed for net
|
||||||
|
|
||||||
func Accept(fd int) (nfd int, sa Sockaddr, errno int) { return 0, nil, EWINDOWS }
|
func Accept(fd int) (nfd int, sa Sockaddr, errno int) { return 0, nil, EWINDOWS }
|
||||||
@ -735,67 +761,3 @@ const (
|
|||||||
SYS_EXIT
|
SYS_EXIT
|
||||||
SYS_READ
|
SYS_READ
|
||||||
)
|
)
|
||||||
|
|
||||||
type Rusage struct {
|
|
||||||
Utime Timeval
|
|
||||||
Stime Timeval
|
|
||||||
Maxrss int32
|
|
||||||
Ixrss int32
|
|
||||||
Idrss int32
|
|
||||||
Isrss int32
|
|
||||||
Minflt int32
|
|
||||||
Majflt int32
|
|
||||||
Nswap int32
|
|
||||||
Inblock int32
|
|
||||||
Oublock int32
|
|
||||||
Msgsnd int32
|
|
||||||
Msgrcv int32
|
|
||||||
Nsignals int32
|
|
||||||
Nvcsw int32
|
|
||||||
Nivcsw int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type WaitStatus struct {
|
|
||||||
Status uint32
|
|
||||||
ExitCode uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
|
||||||
const da = STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | SYNCHRONIZE
|
|
||||||
handle, errno := OpenProcess(da, 0, uint32(pid))
|
|
||||||
if errno != 0 {
|
|
||||||
return 0, errno
|
|
||||||
}
|
|
||||||
defer CloseHandle(int32(handle))
|
|
||||||
e, errno := WaitForSingleObject(int32(handle), INFINITE)
|
|
||||||
var c uint32
|
|
||||||
if ok, errno := GetExitCodeProcess(handle, &c); !ok {
|
|
||||||
return 0, errno
|
|
||||||
}
|
|
||||||
*wstatus = WaitStatus{e, c}
|
|
||||||
return pid, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (w WaitStatus) Exited() bool { return w.Status == WAIT_OBJECT_0 }
|
|
||||||
|
|
||||||
func (w WaitStatus) ExitStatus() int {
|
|
||||||
if w.Status == WAIT_OBJECT_0 {
|
|
||||||
return int(w.ExitCode)
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (WaitStatus) Signal() int { return -1 }
|
|
||||||
|
|
||||||
func (WaitStatus) CoreDump() bool { return false }
|
|
||||||
|
|
||||||
func (WaitStatus) Stopped() bool { return false }
|
|
||||||
|
|
||||||
func (WaitStatus) Continued() bool { return false }
|
|
||||||
|
|
||||||
func (WaitStatus) StopSignal() int { return -1 }
|
|
||||||
|
|
||||||
func (w WaitStatus) Signaled() bool { return w.Status == WAIT_OBJECT_0 }
|
|
||||||
|
|
||||||
func (WaitStatus) TrapCause() int { return -1 }
|
|
||||||
|
@ -45,6 +45,8 @@ var (
|
|||||||
procGetQueuedCompletionStatus = getSysProcAddr(modkernel32, "GetQueuedCompletionStatus")
|
procGetQueuedCompletionStatus = getSysProcAddr(modkernel32, "GetQueuedCompletionStatus")
|
||||||
procCancelIo = getSysProcAddr(modkernel32, "CancelIo")
|
procCancelIo = getSysProcAddr(modkernel32, "CancelIo")
|
||||||
procCreateProcessW = getSysProcAddr(modkernel32, "CreateProcessW")
|
procCreateProcessW = getSysProcAddr(modkernel32, "CreateProcessW")
|
||||||
|
procOpenProcess = getSysProcAddr(modkernel32, "OpenProcess")
|
||||||
|
procGetExitCodeProcess = getSysProcAddr(modkernel32, "GetExitCodeProcess")
|
||||||
procGetStartupInfoW = getSysProcAddr(modkernel32, "GetStartupInfoW")
|
procGetStartupInfoW = getSysProcAddr(modkernel32, "GetStartupInfoW")
|
||||||
procGetCurrentProcess = getSysProcAddr(modkernel32, "GetCurrentProcess")
|
procGetCurrentProcess = getSysProcAddr(modkernel32, "GetCurrentProcess")
|
||||||
procDuplicateHandle = getSysProcAddr(modkernel32, "DuplicateHandle")
|
procDuplicateHandle = getSysProcAddr(modkernel32, "DuplicateHandle")
|
||||||
@ -55,8 +57,6 @@ var (
|
|||||||
procCryptAcquireContextW = getSysProcAddr(modadvapi32, "CryptAcquireContextW")
|
procCryptAcquireContextW = getSysProcAddr(modadvapi32, "CryptAcquireContextW")
|
||||||
procCryptReleaseContext = getSysProcAddr(modadvapi32, "CryptReleaseContext")
|
procCryptReleaseContext = getSysProcAddr(modadvapi32, "CryptReleaseContext")
|
||||||
procCryptGenRandom = getSysProcAddr(modadvapi32, "CryptGenRandom")
|
procCryptGenRandom = getSysProcAddr(modadvapi32, "CryptGenRandom")
|
||||||
procOpenProcess = getSysProcAddr(modkernel32, "OpenProcess")
|
|
||||||
procGetExitCodeProcess = getSysProcAddr(modkernel32, "GetExitCodeProcess")
|
|
||||||
procGetEnvironmentStringsW = getSysProcAddr(modkernel32, "GetEnvironmentStringsW")
|
procGetEnvironmentStringsW = getSysProcAddr(modkernel32, "GetEnvironmentStringsW")
|
||||||
procFreeEnvironmentStringsW = getSysProcAddr(modkernel32, "FreeEnvironmentStringsW")
|
procFreeEnvironmentStringsW = getSysProcAddr(modkernel32, "FreeEnvironmentStringsW")
|
||||||
procGetEnvironmentVariableW = getSysProcAddr(modkernel32, "GetEnvironmentVariableW")
|
procGetEnvironmentVariableW = getSysProcAddr(modkernel32, "GetEnvironmentVariableW")
|
||||||
@ -550,6 +550,42 @@ func CreateProcess(appName *int16, commandLine *uint16, procSecurity *int16, thr
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int) {
|
||||||
|
var _p0 uint32
|
||||||
|
if inheritHandle {
|
||||||
|
_p0 = 1
|
||||||
|
} else {
|
||||||
|
_p0 = 0
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(procOpenProcess, 3, uintptr(da), uintptr(_p0), uintptr(pid))
|
||||||
|
handle = uint32(r0)
|
||||||
|
if handle == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
errno = int(e1)
|
||||||
|
} else {
|
||||||
|
errno = EINVAL
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errno = 0
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetExitCodeProcess(handle uint32, exitcode *uint32) (ok bool, errno int) {
|
||||||
|
r0, _, e1 := Syscall(procGetExitCodeProcess, 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
|
||||||
|
ok = bool(r0 != 0)
|
||||||
|
if !ok {
|
||||||
|
if e1 != 0 {
|
||||||
|
errno = int(e1)
|
||||||
|
} else {
|
||||||
|
errno = EINVAL
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errno = 0
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func GetStartupInfo(startupInfo *StartupInfo) (ok bool, errno int) {
|
func GetStartupInfo(startupInfo *StartupInfo) (ok bool, errno int) {
|
||||||
r0, _, e1 := Syscall(procGetStartupInfoW, 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
|
r0, _, e1 := Syscall(procGetStartupInfoW, 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
|
||||||
ok = bool(r0 != 0)
|
ok = bool(r0 != 0)
|
||||||
@ -706,36 +742,6 @@ func CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func OpenProcess(da uint32, b int, pid uint32) (handle uint32, errno int) {
|
|
||||||
r0, _, e1 := Syscall(procOpenProcess, 3, uintptr(da), uintptr(b), uintptr(pid))
|
|
||||||
handle = uint32(r0)
|
|
||||||
if handle == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
errno = int(e1)
|
|
||||||
} else {
|
|
||||||
errno = EINVAL
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errno = 0
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetExitCodeProcess(h uint32, c *uint32) (ok bool, errno int) {
|
|
||||||
r0, _, e1 := Syscall(procGetExitCodeProcess, 2, uintptr(h), uintptr(unsafe.Pointer(c)), 0)
|
|
||||||
ok = bool(r0 != 0)
|
|
||||||
if !ok {
|
|
||||||
if e1 != 0 {
|
|
||||||
errno = int(e1)
|
|
||||||
} else {
|
|
||||||
errno = EINVAL
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errno = 0
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetEnvironmentStrings() (envs *uint16, errno int) {
|
func GetEnvironmentStrings() (envs *uint16, errno int) {
|
||||||
r0, _, e1 := Syscall(procGetEnvironmentStringsW, 0, 0, 0, 0)
|
r0, _, e1 := Syscall(procGetEnvironmentStringsW, 0, 0, 0, 0)
|
||||||
envs = (*uint16)(unsafe.Pointer(r0))
|
envs = (*uint16)(unsafe.Pointer(r0))
|
||||||
|
Loading…
Reference in New Issue
Block a user