package process
import (
"context"
"errors"
"fmt"
"io/fs"
"os"
"os/user"
"path/filepath"
"strconv"
"strings"
"syscall"
"golang.org/x/sys/unix"
"github.com/gofiber/fiber/v2/internal/gopsutil/common"
)
func getTerminalMap() (map [uint64 ]string , error ) {
ret := make (map [uint64 ]string )
var termfiles []string
d , err := os .Open ("/dev" )
if err != nil {
return nil , err
}
defer d .Close ()
devnames , err := d .Readdirnames (-1 )
if err != nil {
return nil , err
}
for _ , devname := range devnames {
if strings .HasPrefix (devname , "/dev/tty" ) {
termfiles = append (termfiles , "/dev/tty/" +devname )
}
}
var ptsnames []string
ptsd , err := os .Open ("/dev/pts" )
if err != nil {
ptsnames , _ = filepath .Glob ("/dev/ttyp*" )
if ptsnames == nil {
return nil , err
}
}
defer ptsd .Close ()
if ptsnames == nil {
defer ptsd .Close ()
ptsnames , err = ptsd .Readdirnames (-1 )
if err != nil {
return nil , err
}
for _ , ptsname := range ptsnames {
termfiles = append (termfiles , "/dev/pts/" +ptsname )
}
} else {
termfiles = ptsnames
}
for _ , name := range termfiles {
stat := unix .Stat_t {}
if err = unix .Stat (name , &stat ); err != nil {
return nil , err
}
rdev := uint64 (stat .Rdev )
ret [rdev ] = strings .Replace (name , "/dev" , "" , -1 )
}
return ret , nil
}
func PidExistsWithContext (ctx context .Context , pid int32 ) (bool , error ) {
if pid <= 0 {
return false , fmt .Errorf ("invalid pid %v" , pid )
}
proc , err := os .FindProcess (int (pid ))
if err != nil {
return false , err
}
if _ , err := os .Stat (common .HostProc ()); err == nil {
_ , err := os .Stat (common .HostProc (strconv .Itoa (int (pid ))))
if errors .Is (err , fs .ErrNotExist ) {
return false , nil
}
return err == nil , err
}
err = proc .Signal (syscall .Signal (0 ))
if err == nil {
return true , nil
}
if err .Error() == "os: process already finished" {
return false , nil
}
errno , ok := err .(syscall .Errno )
if !ok {
return false , err
}
switch errno {
case syscall .ESRCH :
return false , nil
case syscall .EPERM :
return true , nil
}
return false , err
}
func (p *Process ) SendSignal (sig syscall .Signal ) error {
return p .SendSignalWithContext (context .Background (), sig )
}
func (p *Process ) SendSignalWithContext (ctx context .Context , sig syscall .Signal ) error {
process , err := os .FindProcess (int (p .Pid ))
if err != nil {
return err
}
err = process .Signal (sig )
if err != nil {
return err
}
return nil
}
func (p *Process ) Suspend () error {
return p .SuspendWithContext (context .Background ())
}
func (p *Process ) SuspendWithContext (ctx context .Context ) error {
return p .SendSignal (unix .SIGSTOP )
}
func (p *Process ) Resume () error {
return p .ResumeWithContext (context .Background ())
}
func (p *Process ) ResumeWithContext (ctx context .Context ) error {
return p .SendSignal (unix .SIGCONT )
}
func (p *Process ) Terminate () error {
return p .TerminateWithContext (context .Background ())
}
func (p *Process ) TerminateWithContext (ctx context .Context ) error {
return p .SendSignal (unix .SIGTERM )
}
func (p *Process ) Kill () error {
return p .KillWithContext (context .Background ())
}
func (p *Process ) KillWithContext (ctx context .Context ) error {
return p .SendSignal (unix .SIGKILL )
}
func (p *Process ) Username () (string , error ) {
return p .UsernameWithContext (context .Background ())
}
func (p *Process ) UsernameWithContext (ctx context .Context ) (string , error ) {
uids , err := p .Uids ()
if err != nil {
return "" , err
}
if len (uids ) > 0 {
u , err := user .LookupId (strconv .Itoa (int (uids [0 ])))
if err != nil {
return "" , err
}
return u .Username , nil
}
return "" , nil
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .