mirror of
https://gogs.blitter.com/RLabs/xs
synced 2024-08-14 10:26:42 +00:00
Changed to use runShellAs() (pass cmdline to bash) rather than runCmdAs (os.exec)
to allow pipelines, redir etc.
This commit is contained in:
parent
6fd8ac1519
commit
59337db7e3
1 changed files with 44 additions and 2 deletions
|
@ -66,6 +66,48 @@ func runCmdAs(who string, cmd string, conn hkex.Conn) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run a command (via default shell) as a specific user
|
||||||
|
//
|
||||||
|
// Uses ptys to support commands which expect a terminal.
|
||||||
|
func runShellAs(who string, cmd string, interactive bool, conn hkex.Conn) (err error) {
|
||||||
|
u, _ := user.Lookup(who)
|
||||||
|
var uid, gid uint32
|
||||||
|
fmt.Sscanf(u.Uid, "%d", &uid)
|
||||||
|
fmt.Sscanf(u.Gid, "%d", &gid)
|
||||||
|
fmt.Println("uid:", uid, "gid:", gid)
|
||||||
|
|
||||||
|
var c *exec.Cmd
|
||||||
|
if interactive {
|
||||||
|
c = exec.Command("/bin/bash", "-i")
|
||||||
|
} else {
|
||||||
|
c = exec.Command("/bin/bash", "-c", cmd)
|
||||||
|
}
|
||||||
|
c.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
c.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}
|
||||||
|
c.Stdin = conn
|
||||||
|
c.Stdout = conn
|
||||||
|
c.Stderr = conn
|
||||||
|
|
||||||
|
// Start the command with a pty.
|
||||||
|
ptmx, err := pty.Start(c) // returns immediately with ptmx file
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Make sure to close the pty at the end.
|
||||||
|
defer func() { _ = ptmx.Close() }() // Best effort.
|
||||||
|
// Copy stdin to the pty and the pty to stdout.
|
||||||
|
go func() { _, _ = io.Copy(ptmx, conn) }()
|
||||||
|
_, _ = io.Copy(conn, ptmx)
|
||||||
|
|
||||||
|
//err = c.Run() // returns when c finishes.
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Command finished with error: %v", err)
|
||||||
|
log.Printf("[%s]\n", cmd)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Demo of a simple server that listens and spawns goroutines for each
|
// Demo of a simple server that listens and spawns goroutines for each
|
||||||
// connecting client. Note this code is identical to standard tcp
|
// connecting client. Note this code is identical to standard tcp
|
||||||
// server code, save for declaring 'hkex' rather than 'net'
|
// server code, save for declaring 'hkex' rather than 'net'
|
||||||
|
@ -155,14 +197,14 @@ func main() {
|
||||||
if rec.op[0] == 'c' {
|
if rec.op[0] == 'c' {
|
||||||
// Non-interactive command
|
// Non-interactive command
|
||||||
fmt.Println("[Running command]")
|
fmt.Println("[Running command]")
|
||||||
runCmdAs(string(rec.who), string(rec.cmd), conn)
|
runShellAs(string(rec.who), string(rec.cmd), false, conn)
|
||||||
// Returned hopefully via an EOF or exit/logout;
|
// Returned hopefully via an EOF or exit/logout;
|
||||||
// Clear current op so user can enter next, or EOF
|
// Clear current op so user can enter next, or EOF
|
||||||
rec.op[0] = 0
|
rec.op[0] = 0
|
||||||
fmt.Println("[Command complete]")
|
fmt.Println("[Command complete]")
|
||||||
} else if rec.op[0] == 's' {
|
} else if rec.op[0] == 's' {
|
||||||
fmt.Println("[Running shell]")
|
fmt.Println("[Running shell]")
|
||||||
runCmdAs(string(rec.who), "bash -l -i", conn)
|
runShellAs(string(rec.who), string(rec.cmd), true, conn)
|
||||||
// Returned hopefully via an EOF or exit/logout;
|
// Returned hopefully via an EOF or exit/logout;
|
||||||
// Clear current op so user can enter next, or EOF
|
// Clear current op so user can enter next, or EOF
|
||||||
rec.op[0] = 0
|
rec.op[0] = 0
|
||||||
|
|
Loading…
Reference in a new issue