-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #65 from essentialkaos/develop
Version 3.3.0
- Loading branch information
Showing
8 changed files
with
449 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package color | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
// // | ||
// Copyright (c) 2009-2016 Essential Kaos // | ||
// Essential Kaos Open Source License <http://essentialkaos.com/ekol?en> // | ||
// // | ||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
func ExampleRGB2Hex() { | ||
fmt.Printf("%x\n", RGB2Hex(127, 25, 75)) | ||
// Output: 7f194b | ||
} | ||
|
||
func ExampleHex2RGB() { | ||
r, g, b := Hex2RGB(0x7f194b) | ||
|
||
fmt.Printf("r:%d g:%d b:%d\n", r, g, b) | ||
|
||
// Output: r:127 g:25 b:75 | ||
} | ||
|
||
func ExampleHex2RGBA() { | ||
r, g, b, a := Hex2RGBA(0x7f194bcc) | ||
|
||
fmt.Printf("r:%d g:%d b:%d a:%d\n", r, g, b, a) | ||
|
||
// Output: r:127 g:25 b:75 a:204 | ||
} | ||
|
||
func ExampleRGB2HSB() { | ||
h, s, v := RGB2HSB(127, 25, 75) | ||
|
||
fmt.Printf("h:%d s:%d v:%d\n", h, s, v) | ||
|
||
// Output: h:331 s:81 v:50 | ||
} | ||
|
||
func ExampleHSB2RGB() { | ||
r, g, b := HSB2RGB(331, 81, 50) | ||
|
||
fmt.Printf("r:%d g:%d b:%d\n", r, g, b) | ||
|
||
// Output: r:128 g:24 b:74 | ||
} | ||
|
||
func ExampleIsRGBA() { | ||
fmt.Println(IsRGBA(0xAABBCC)) | ||
fmt.Println(IsRGBA(0xAABBCCDD)) | ||
|
||
// Output: | ||
// false | ||
// true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package process | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
// // | ||
// Copyright (c) 2009-2016 Essential Kaos // | ||
// Essential Kaos Open Source License <http://essentialkaos.com/ekol?en> // | ||
// // | ||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
func Example_getTree() { | ||
process, err := GetTree() | ||
|
||
if err != nil { | ||
return | ||
} | ||
|
||
// process is top process in tree | ||
} | ||
|
||
func Example_getList() { | ||
processes, err := GetList() | ||
|
||
if err != nil { | ||
return | ||
} | ||
|
||
// processes is slice with info about all active processes | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
// +build linux | ||
|
||
// Package process provides methods for getting information about active processes | ||
package process | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
// // | ||
// Copyright (c) 2009-2016 Essential Kaos // | ||
// Essential Kaos Open Source License <http://essentialkaos.com/ekol?en> // | ||
// // | ||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
import ( | ||
"errors" | ||
"io/ioutil" | ||
"strconv" | ||
"strings" | ||
|
||
"pkg.re/essentialkaos/ek.v3/fsutil" | ||
"pkg.re/essentialkaos/ek.v3/system" | ||
) | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
// ProcessInfo contains basic info about process | ||
type ProcessInfo struct { | ||
Command string // Full command | ||
User string // Username | ||
PID int // PID | ||
IsThread bool // True if process is thread | ||
Parent int // Parent process PID | ||
Childs []*ProcessInfo // Slice with child processes | ||
} | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
// GetTree return root process with all subprocesses on system | ||
func GetTree() (*ProcessInfo, error) { | ||
list, err := findInfo("/proc", make(map[int]string)) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if len(list) == 0 { | ||
return nil, errors.New("Can't find any processes") | ||
} | ||
|
||
processMap := processListToMap(list) | ||
|
||
for _, process := range processMap { | ||
if process.Parent < 0 { | ||
continue | ||
} | ||
|
||
parentProcess := processMap[process.Parent] | ||
|
||
if parentProcess == nil { | ||
continue | ||
} | ||
|
||
parentProcess.Childs = append(parentProcess.Childs, process) | ||
} | ||
|
||
return processMap[1], nil | ||
} | ||
|
||
// GetList return slice with all active processes on system | ||
func GetList() ([]*ProcessInfo, error) { | ||
return findInfo("/proc", make(map[int]string)) | ||
} | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
func findInfo(dir string, userMap map[int]string) ([]*ProcessInfo, error) { | ||
var result []*ProcessInfo | ||
|
||
dirs := fsutil.List(dir, true, &fsutil.ListingFilter{Perms: "DRX"}) | ||
|
||
for _, pidDir := range dirs { | ||
if !isPID(pidDir) { | ||
continue | ||
} | ||
|
||
taskDir := dir + "/" + pidDir + "/task" | ||
|
||
if fsutil.IsExist(taskDir) { | ||
threads, err := findInfo(taskDir, userMap) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if len(threads) == 0 { | ||
continue | ||
} | ||
|
||
processThreads(threads) | ||
|
||
result = append(result, threads...) | ||
|
||
continue | ||
} | ||
|
||
info, err := readProcessInfo(dir+"/"+pidDir, pidDir, userMap) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if info == nil { | ||
continue | ||
} | ||
|
||
result = append(result, info) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
func readProcessInfo(dir, pid string, userMap map[int]string) (*ProcessInfo, error) { | ||
cmd, err := ioutil.ReadFile(dir + "/cmdline") | ||
|
||
if len(cmd) == 0 { | ||
return nil, nil | ||
} | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
uid, _, err := fsutil.GetOwner(dir) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
username, err := getProcessUser(uid, userMap) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pidInt, err := strconv.Atoi(pid) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &ProcessInfo{ | ||
Command: formatCommand(string(cmd)), | ||
User: username, | ||
PID: pidInt, | ||
Parent: getProcessParent(dir, pidInt), | ||
}, nil | ||
} | ||
|
||
func getProcessUser(uid int, userMap map[int]string) (string, error) { | ||
if uid == 0 { | ||
return "root", nil | ||
} | ||
|
||
if userMap[uid] != "" { | ||
return userMap[uid], nil | ||
} | ||
|
||
user, err := system.LookupUser(strconv.Itoa(uid)) | ||
|
||
if err != nil { | ||
return "", err | ||
} | ||
|
||
userMap[uid] = user.Name | ||
|
||
return user.Name, nil | ||
} | ||
|
||
func processThreads(threads []*ProcessInfo) { | ||
for _, info := range threads { | ||
info.IsThread = true | ||
} | ||
} | ||
|
||
func getProcessParent(pidDir string, pid int) int { | ||
tgid, ppid := getParentPIDs(pidDir) | ||
|
||
if tgid != pid { | ||
return tgid | ||
} | ||
|
||
return ppid | ||
} | ||
|
||
func getParentPIDs(pidDir string) (int, int) { | ||
data, err := ioutil.ReadFile(pidDir + "/status") | ||
|
||
if err != nil { | ||
return -1, -1 | ||
} | ||
|
||
var ( | ||
ppid string | ||
tgid string | ||
) | ||
|
||
for _, line := range strings.Split(string(data), "\n") { | ||
if strings.HasPrefix(line, "Tgid:") { | ||
tgid = strings.TrimSpace(line[5:]) | ||
} | ||
|
||
if strings.HasPrefix(line, "PPid:") { | ||
ppid = strings.TrimSpace(line[5:]) | ||
} | ||
|
||
if ppid != "" && tgid != "" { | ||
break | ||
} | ||
} | ||
|
||
if tgid == "" || ppid == "" { | ||
return -1, -1 | ||
} | ||
|
||
tgidInt, _ := strconv.Atoi(tgid) | ||
ppidInt, _ := strconv.Atoi(ppid) | ||
|
||
return tgidInt, ppidInt | ||
} | ||
|
||
func formatCommand(cmd string) string { | ||
// Normalize delemiters | ||
command := strings.Replace(cmd, "\000", " ", -1) | ||
|
||
// Remove space on the end of command | ||
command = strings.TrimSpace(command) | ||
|
||
return command | ||
} | ||
|
||
func processListToMap(processes []*ProcessInfo) map[int]*ProcessInfo { | ||
var result = make(map[int]*ProcessInfo) | ||
|
||
for _, info := range processes { | ||
result[info.PID] = info | ||
} | ||
|
||
return result | ||
} | ||
|
||
func isPID(pid string) bool { | ||
if pid == "" { | ||
return false | ||
} | ||
|
||
// Pid must start from number | ||
switch pid[0] { | ||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': | ||
return true | ||
} | ||
|
||
return false | ||
} |
Oops, something went wrong.