Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GetProcCredName implementation to windows gosigar #13

Merged
merged 1 commit into from
Jan 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sigar_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const (

type ProcState struct {
Name string
Username string
State RunState
Ppid int
Tty int
Expand Down
47 changes: 47 additions & 0 deletions sigar_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,12 @@ func (self *ProcState) Get(pid int) error {
if err != nil {
return err
}

self.Username, err = GetProcCredName(pid)
if err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -306,6 +312,47 @@ func GetProcName(pid int) (string, error) {

}

func GetProcCredName(pid int) (string, error) {
var err error

handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))

if err != nil {
return "", fmt.Errorf("OpenProcess fails with %v", err)
}

defer syscall.CloseHandle(handle)

var token syscall.Token
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using golang.org/x/sys/windows would be better. That package has windows.Token with methods like GetTokenUser.

The functions in that package will handle the ERROR_INSUFFICIENT_BUFFER that can be returned by GetTokenInformation. It also has a constant for TokenUser which makes code a little more clear (edit: you won't even need the TokenUser constant if you switch to using golang.org/x/sys/windows).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think that is enough reason to use two libraries instead of just one? I'm worried that would confuse things having two libraries hit win32... otherwise we should probably just change ALL the windows method implementations to use golang.org/x/sys/windows instead of syscall.

The other windows gosigar methods use the syscall import to get at win32. What do you think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrewkroh x/sys/windows would definitely simplify the account lookup and it looks really bullet proof from an error perspective... perhaps we could just use it for GetProcGredName and defer the re-implementation of the other methods to a later date and add an issue for that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it OK to use golang.org/x/sys/windows here and leave the other methods as is.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I'm silly! So x/sys/windows GetTokenUser is already there. When in Rome I guess :)

The go x/foo/bar thing threw me, definitely new to go.


// Find process token via win32
err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token)

if err != nil {
return "", fmt.Errorf("Error opening process token %v", err)
}

// Find the token user
tokenUser, err := token.GetTokenUser()
if err != nil {
return "", fmt.Errorf("Error getting token user %v", err)
}

// Close token to prevent handle leaks
err = token.Close()
if err != nil {
return "", fmt.Errorf("Error failed to closed process token")
}

// look up domain account by sid
account, domain, _, err := tokenUser.User.Sid.LookupAccount("localhost")
if err != nil {
return "", fmt.Errorf("Error looking up sid %v", err)
}

return fmt.Sprintf("%s\\%s", domain, account), nil
}

func GetProcStatus(pid int) (RunState, error) {

handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
Expand Down
13 changes: 13 additions & 0 deletions sigar_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package sigar_test
import (
"math"
"os"
"os/user"
"strings"
"testing"

Expand Down Expand Up @@ -32,6 +33,18 @@ var _ = Describe("SigarWindows", func() {
Ω(usage.Total).Should(BeNumerically(">", 0))
})
})

Describe("Process", func() {
It("gets the current process user name", func() {
proc := sigar.ProcState{}
err := proc.Get(os.Getpid())
user, usererr := user.Current()

Ω(err).ShouldNot(HaveOccurred())
Ω(usererr).ShouldNot(HaveOccurred())
Ω(proc.Username).Should(Equal(user.Username))
})
})
})

func TestProcArgs(t *testing.T) {
Expand Down