mirror of
https://github.com/fosrl/newt.git
synced 2026-07-19 06:19:52 +02:00
Fall back gracefully when home dir does not exist
Former-commit-id: 07bf861179
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
package nativessh
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/creack/pty"
|
||||
@@ -31,6 +34,42 @@ func findShell() string {
|
||||
return "/bin/sh"
|
||||
}
|
||||
|
||||
// userShell returns the login shell configured for u in /etc/passwd.
|
||||
// If the field is empty or the binary does not exist, it falls back to
|
||||
// findShell so there is always a usable shell.
|
||||
func userShell(u *user.User) string {
|
||||
if shell := passwdShell(u.Username); shell != "" {
|
||||
if _, err := exec.LookPath(shell); err == nil {
|
||||
return shell
|
||||
}
|
||||
}
|
||||
return findShell()
|
||||
}
|
||||
|
||||
// passwdShell reads /etc/passwd and returns the login shell for the named user.
|
||||
// Returns "" if the user is not found or the file cannot be read.
|
||||
func passwdShell(username string) string {
|
||||
f, err := os.Open("/etc/passwd")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer f.Close()
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if line == "" || line[0] == '#' {
|
||||
continue
|
||||
}
|
||||
// Fields: username:password:uid:gid:gecos:home:shell
|
||||
fields := strings.SplitN(line, ":", 7)
|
||||
if len(fields) == 7 && fields[0] == username {
|
||||
return fields[6]
|
||||
}
|
||||
}
|
||||
_ = scanner.Err()
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewPTYSession spawns the best available shell in a PTY.
|
||||
func NewPTYSession() (*PTYSession, error) {
|
||||
shell := findShell()
|
||||
|
||||
@@ -4,6 +4,7 @@ package nativessh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"strconv"
|
||||
@@ -42,7 +43,15 @@ func NewPTYSessionAs(username string) (*PTYSession, error) {
|
||||
}
|
||||
}
|
||||
|
||||
shell := findShell()
|
||||
shell := userShell(u)
|
||||
|
||||
// Prefer the user's home directory as the working directory, but fall back
|
||||
// to / if it does not exist (e.g. useradd was run without -m).
|
||||
homeDir := u.HomeDir
|
||||
if _, err := os.Stat(homeDir); err != nil {
|
||||
homeDir = "/"
|
||||
}
|
||||
|
||||
cmd := exec.Command(shell, "--login")
|
||||
cmd.Env = []string{
|
||||
"TERM=xterm-256color",
|
||||
@@ -52,7 +61,7 @@ func NewPTYSessionAs(username string) (*PTYSession, error) {
|
||||
"SHELL=" + shell,
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
}
|
||||
cmd.Dir = u.HomeDir
|
||||
cmd.Dir = homeDir
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Credential: &syscall.Credential{
|
||||
Uid: uint32(uid),
|
||||
|
||||
Reference in New Issue
Block a user