From 7b03f01630454c5913d933020d0f130ab0c08850 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Thu, 24 Mar 2016 02:19:02 +0000 Subject: [PATCH 1/5] Vendor github.com/kr and github.com/willdonnelly/passwd --- vendor/github.com/kr/pty/License | 23 ++++++ vendor/github.com/kr/pty/README.md | 36 +++++++++ vendor/github.com/kr/pty/doc.go | 16 ++++ vendor/github.com/kr/pty/ioctl.go | 11 +++ vendor/github.com/kr/pty/ioctl_bsd.go | 39 ++++++++++ vendor/github.com/kr/pty/mktypes.bash | 19 +++++ vendor/github.com/kr/pty/pty_darwin.go | 60 +++++++++++++++ vendor/github.com/kr/pty/pty_freebsd.go | 73 +++++++++++++++++++ vendor/github.com/kr/pty/pty_linux.go | 46 ++++++++++++ vendor/github.com/kr/pty/pty_unsupported.go | 11 +++ vendor/github.com/kr/pty/run.go | 32 ++++++++ vendor/github.com/kr/pty/types.go | 10 +++ vendor/github.com/kr/pty/types_freebsd.go | 15 ++++ vendor/github.com/kr/pty/util.go | 35 +++++++++ vendor/github.com/kr/pty/ztypes_386.go | 9 +++ vendor/github.com/kr/pty/ztypes_amd64.go | 9 +++ vendor/github.com/kr/pty/ztypes_arm.go | 9 +++ vendor/github.com/kr/pty/ztypes_arm64.go | 11 +++ .../github.com/kr/pty/ztypes_freebsd_386.go | 13 ++++ .../github.com/kr/pty/ztypes_freebsd_amd64.go | 14 ++++ .../github.com/kr/pty/ztypes_freebsd_arm.go | 13 ++++ vendor/github.com/kr/pty/ztypes_ppc64.go | 11 +++ vendor/github.com/kr/pty/ztypes_ppc64le.go | 11 +++ vendor/github.com/kr/pty/ztypes_s390x.go | 11 +++ vendor/github.com/willdonnelly/passwd/README | 26 +++++++ .../github.com/willdonnelly/passwd/passwd.go | 71 ++++++++++++++++++ vendor/manifest | 14 +++- 27 files changed, 647 insertions(+), 1 deletion(-) create mode 100644 vendor/github.com/kr/pty/License create mode 100644 vendor/github.com/kr/pty/README.md create mode 100644 vendor/github.com/kr/pty/doc.go create mode 100644 vendor/github.com/kr/pty/ioctl.go create mode 100644 vendor/github.com/kr/pty/ioctl_bsd.go create mode 100644 vendor/github.com/kr/pty/mktypes.bash create mode 100644 vendor/github.com/kr/pty/pty_darwin.go create mode 100644 vendor/github.com/kr/pty/pty_freebsd.go create mode 100644 vendor/github.com/kr/pty/pty_linux.go create mode 100644 vendor/github.com/kr/pty/pty_unsupported.go create mode 100644 vendor/github.com/kr/pty/run.go create mode 100644 vendor/github.com/kr/pty/types.go create mode 100644 vendor/github.com/kr/pty/types_freebsd.go create mode 100644 vendor/github.com/kr/pty/util.go create mode 100644 vendor/github.com/kr/pty/ztypes_386.go create mode 100644 vendor/github.com/kr/pty/ztypes_amd64.go create mode 100644 vendor/github.com/kr/pty/ztypes_arm.go create mode 100644 vendor/github.com/kr/pty/ztypes_arm64.go create mode 100644 vendor/github.com/kr/pty/ztypes_freebsd_386.go create mode 100644 vendor/github.com/kr/pty/ztypes_freebsd_amd64.go create mode 100644 vendor/github.com/kr/pty/ztypes_freebsd_arm.go create mode 100644 vendor/github.com/kr/pty/ztypes_ppc64.go create mode 100644 vendor/github.com/kr/pty/ztypes_ppc64le.go create mode 100644 vendor/github.com/kr/pty/ztypes_s390x.go create mode 100644 vendor/github.com/willdonnelly/passwd/README create mode 100644 vendor/github.com/willdonnelly/passwd/passwd.go diff --git a/vendor/github.com/kr/pty/License b/vendor/github.com/kr/pty/License new file mode 100644 index 000000000..6b7558b6b --- /dev/null +++ b/vendor/github.com/kr/pty/License @@ -0,0 +1,23 @@ +Copyright (c) 2011 Keith Rarick + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall +be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/kr/pty/README.md b/vendor/github.com/kr/pty/README.md new file mode 100644 index 000000000..7b7900c3a --- /dev/null +++ b/vendor/github.com/kr/pty/README.md @@ -0,0 +1,36 @@ +# pty + +Pty is a Go package for using unix pseudo-terminals. + +## Install + + go get github.com/kr/pty + +## Example + +```go +package main + +import ( + "github.com/kr/pty" + "io" + "os" + "os/exec" +) + +func main() { + c := exec.Command("grep", "--color=auto", "bar") + f, err := pty.Start(c) + if err != nil { + panic(err) + } + + go func() { + f.Write([]byte("foo\n")) + f.Write([]byte("bar\n")) + f.Write([]byte("baz\n")) + f.Write([]byte{4}) // EOT + }() + io.Copy(os.Stdout, f) +} +``` diff --git a/vendor/github.com/kr/pty/doc.go b/vendor/github.com/kr/pty/doc.go new file mode 100644 index 000000000..190cfbea9 --- /dev/null +++ b/vendor/github.com/kr/pty/doc.go @@ -0,0 +1,16 @@ +// Package pty provides functions for working with Unix terminals. +package pty + +import ( + "errors" + "os" +) + +// ErrUnsupported is returned if a function is not +// available on the current platform. +var ErrUnsupported = errors.New("unsupported") + +// Opens a pty and its corresponding tty. +func Open() (pty, tty *os.File, err error) { + return open() +} diff --git a/vendor/github.com/kr/pty/ioctl.go b/vendor/github.com/kr/pty/ioctl.go new file mode 100644 index 000000000..5b856e871 --- /dev/null +++ b/vendor/github.com/kr/pty/ioctl.go @@ -0,0 +1,11 @@ +package pty + +import "syscall" + +func ioctl(fd, cmd, ptr uintptr) error { + _, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr) + if e != 0 { + return e + } + return nil +} diff --git a/vendor/github.com/kr/pty/ioctl_bsd.go b/vendor/github.com/kr/pty/ioctl_bsd.go new file mode 100644 index 000000000..73b12c53c --- /dev/null +++ b/vendor/github.com/kr/pty/ioctl_bsd.go @@ -0,0 +1,39 @@ +// +build darwin dragonfly freebsd netbsd openbsd + +package pty + +// from +const ( + _IOC_VOID uintptr = 0x20000000 + _IOC_OUT uintptr = 0x40000000 + _IOC_IN uintptr = 0x80000000 + _IOC_IN_OUT uintptr = _IOC_OUT | _IOC_IN + _IOC_DIRMASK = _IOC_VOID | _IOC_OUT | _IOC_IN + + _IOC_PARAM_SHIFT = 13 + _IOC_PARAM_MASK = (1 << _IOC_PARAM_SHIFT) - 1 +) + +func _IOC_PARM_LEN(ioctl uintptr) uintptr { + return (ioctl >> 16) & _IOC_PARAM_MASK +} + +func _IOC(inout uintptr, group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return inout | (param_len&_IOC_PARAM_MASK)<<16 | uintptr(group)<<8 | ioctl_num +} + +func _IO(group byte, ioctl_num uintptr) uintptr { + return _IOC(_IOC_VOID, group, ioctl_num, 0) +} + +func _IOR(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_OUT, group, ioctl_num, param_len) +} + +func _IOW(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_IN, group, ioctl_num, param_len) +} + +func _IOWR(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_IN_OUT, group, ioctl_num, param_len) +} diff --git a/vendor/github.com/kr/pty/mktypes.bash b/vendor/github.com/kr/pty/mktypes.bash new file mode 100644 index 000000000..9952c8883 --- /dev/null +++ b/vendor/github.com/kr/pty/mktypes.bash @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +GOOSARCH="${GOOS}_${GOARCH}" +case "$GOOSARCH" in +_* | *_ | _) + echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 + exit 1 + ;; +esac + +GODEFS="go tool cgo -godefs" + +$GODEFS types.go |gofmt > ztypes_$GOARCH.go + +case $GOOS in +freebsd) + $GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go + ;; +esac diff --git a/vendor/github.com/kr/pty/pty_darwin.go b/vendor/github.com/kr/pty/pty_darwin.go new file mode 100644 index 000000000..4f4d5ca26 --- /dev/null +++ b/vendor/github.com/kr/pty/pty_darwin.go @@ -0,0 +1,60 @@ +package pty + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + err = grantpt(p) + if err != nil { + return nil, nil, err + } + + err = unlockpt(p) + if err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + n := make([]byte, _IOC_PARM_LEN(syscall.TIOCPTYGNAME)) + + err := ioctl(f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0]))) + if err != nil { + return "", err + } + + for i, c := range n { + if c == 0 { + return string(n[:i]), nil + } + } + return "", errors.New("TIOCPTYGNAME string not NUL-terminated") +} + +func grantpt(f *os.File) error { + return ioctl(f.Fd(), syscall.TIOCPTYGRANT, 0) +} + +func unlockpt(f *os.File) error { + return ioctl(f.Fd(), syscall.TIOCPTYUNLK, 0) +} diff --git a/vendor/github.com/kr/pty/pty_freebsd.go b/vendor/github.com/kr/pty/pty_freebsd.go new file mode 100644 index 000000000..b341babd0 --- /dev/null +++ b/vendor/github.com/kr/pty/pty_freebsd.go @@ -0,0 +1,73 @@ +package pty + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func posix_openpt(oflag int) (fd int, err error) { + r0, _, e1 := syscall.Syscall(syscall.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0) + fd = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +func open() (pty, tty *os.File, err error) { + fd, err := posix_openpt(syscall.O_RDWR | syscall.O_CLOEXEC) + if err != nil { + return nil, nil, err + } + + p := os.NewFile(uintptr(fd), "/dev/pts") + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + t, err := os.OpenFile("/dev/"+sname, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func isptmaster(fd uintptr) (bool, error) { + err := ioctl(fd, syscall.TIOCPTMASTER, 0) + return err == nil, err +} + +var ( + emptyFiodgnameArg fiodgnameArg + ioctl_FIODGNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) +) + +func ptsname(f *os.File) (string, error) { + master, err := isptmaster(f.Fd()) + if err != nil { + return "", err + } + if !master { + return "", syscall.EINVAL + } + + const n = _C_SPECNAMELEN + 1 + var ( + buf = make([]byte, n) + arg = fiodgnameArg{Len: n, Buf: (*byte)(unsafe.Pointer(&buf[0]))} + ) + err = ioctl(f.Fd(), ioctl_FIODGNAME, uintptr(unsafe.Pointer(&arg))) + if err != nil { + return "", err + } + + for i, c := range buf { + if c == 0 { + return string(buf[:i]), nil + } + } + return "", errors.New("FIODGNAME string not NUL-terminated") +} diff --git a/vendor/github.com/kr/pty/pty_linux.go b/vendor/github.com/kr/pty/pty_linux.go new file mode 100644 index 000000000..cb901a21e --- /dev/null +++ b/vendor/github.com/kr/pty/pty_linux.go @@ -0,0 +1,46 @@ +package pty + +import ( + "os" + "strconv" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + err = unlockpt(p) + if err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + var n _C_uint + err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) + if err != nil { + return "", err + } + return "/dev/pts/" + strconv.Itoa(int(n)), nil +} + +func unlockpt(f *os.File) error { + var u _C_int + // use TIOCSPTLCK with a zero valued arg to clear the slave pty lock + return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) +} diff --git a/vendor/github.com/kr/pty/pty_unsupported.go b/vendor/github.com/kr/pty/pty_unsupported.go new file mode 100644 index 000000000..898c7303c --- /dev/null +++ b/vendor/github.com/kr/pty/pty_unsupported.go @@ -0,0 +1,11 @@ +// +build !linux,!darwin,!freebsd + +package pty + +import ( + "os" +) + +func open() (pty, tty *os.File, err error) { + return nil, nil, ErrUnsupported +} diff --git a/vendor/github.com/kr/pty/run.go b/vendor/github.com/kr/pty/run.go new file mode 100644 index 000000000..c2bc48878 --- /dev/null +++ b/vendor/github.com/kr/pty/run.go @@ -0,0 +1,32 @@ +package pty + +import ( + "os" + "os/exec" + "syscall" +) + +// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, +// and c.Stderr, calls c.Start, and returns the File of the tty's +// corresponding pty. +func Start(c *exec.Cmd) (pty *os.File, err error) { + pty, tty, err := Open() + if err != nil { + return nil, err + } + defer tty.Close() + c.Stdout = tty + c.Stdin = tty + c.Stderr = tty + if c.SysProcAttr == nil { + c.SysProcAttr = &syscall.SysProcAttr{} + } + c.SysProcAttr.Setctty = true + c.SysProcAttr.Setsid = true + err = c.Start() + if err != nil { + pty.Close() + return nil, err + } + return pty, err +} diff --git a/vendor/github.com/kr/pty/types.go b/vendor/github.com/kr/pty/types.go new file mode 100644 index 000000000..5aecb6bcd --- /dev/null +++ b/vendor/github.com/kr/pty/types.go @@ -0,0 +1,10 @@ +// +build ignore + +package pty + +import "C" + +type ( + _C_int C.int + _C_uint C.uint +) diff --git a/vendor/github.com/kr/pty/types_freebsd.go b/vendor/github.com/kr/pty/types_freebsd.go new file mode 100644 index 000000000..ce3eb9518 --- /dev/null +++ b/vendor/github.com/kr/pty/types_freebsd.go @@ -0,0 +1,15 @@ +// +build ignore + +package pty + +/* +#include +#include +*/ +import "C" + +const ( + _C_SPECNAMELEN = C.SPECNAMELEN /* max length of devicename */ +) + +type fiodgnameArg C.struct_fiodgname_arg diff --git a/vendor/github.com/kr/pty/util.go b/vendor/github.com/kr/pty/util.go new file mode 100644 index 000000000..67c52d06c --- /dev/null +++ b/vendor/github.com/kr/pty/util.go @@ -0,0 +1,35 @@ +package pty + +import ( + "os" + "syscall" + "unsafe" +) + +// Getsize returns the number of rows (lines) and cols (positions +// in each line) in terminal t. +func Getsize(t *os.File) (rows, cols int, err error) { + var ws winsize + err = windowrect(&ws, t.Fd()) + return int(ws.ws_row), int(ws.ws_col), err +} + +type winsize struct { + ws_row uint16 + ws_col uint16 + ws_xpixel uint16 + ws_ypixel uint16 +} + +func windowrect(ws *winsize, fd uintptr) error { + _, _, errno := syscall.Syscall( + syscall.SYS_IOCTL, + fd, + syscall.TIOCGWINSZ, + uintptr(unsafe.Pointer(ws)), + ) + if errno != 0 { + return syscall.Errno(errno) + } + return nil +} diff --git a/vendor/github.com/kr/pty/ztypes_386.go b/vendor/github.com/kr/pty/ztypes_386.go new file mode 100644 index 000000000..ff0b8fd83 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_386.go @@ -0,0 +1,9 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_amd64.go b/vendor/github.com/kr/pty/ztypes_amd64.go new file mode 100644 index 000000000..ff0b8fd83 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_amd64.go @@ -0,0 +1,9 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_arm.go b/vendor/github.com/kr/pty/ztypes_arm.go new file mode 100644 index 000000000..ff0b8fd83 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_arm.go @@ -0,0 +1,9 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_arm64.go b/vendor/github.com/kr/pty/ztypes_arm64.go new file mode 100644 index 000000000..6c29a4b91 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_arm64.go @@ -0,0 +1,11 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +// +build arm64 + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_freebsd_386.go b/vendor/github.com/kr/pty/ztypes_freebsd_386.go new file mode 100644 index 000000000..d9975374e --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_freebsd_386.go @@ -0,0 +1,13 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Buf *byte +} diff --git a/vendor/github.com/kr/pty/ztypes_freebsd_amd64.go b/vendor/github.com/kr/pty/ztypes_freebsd_amd64.go new file mode 100644 index 000000000..5fa102fcd --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_freebsd_amd64.go @@ -0,0 +1,14 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Pad_cgo_0 [4]byte + Buf *byte +} diff --git a/vendor/github.com/kr/pty/ztypes_freebsd_arm.go b/vendor/github.com/kr/pty/ztypes_freebsd_arm.go new file mode 100644 index 000000000..d9975374e --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_freebsd_arm.go @@ -0,0 +1,13 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Buf *byte +} diff --git a/vendor/github.com/kr/pty/ztypes_ppc64.go b/vendor/github.com/kr/pty/ztypes_ppc64.go new file mode 100644 index 000000000..4e1af8431 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_ppc64.go @@ -0,0 +1,11 @@ +// +build ppc64 + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_ppc64le.go b/vendor/github.com/kr/pty/ztypes_ppc64le.go new file mode 100644 index 000000000..e6780f4e2 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_ppc64le.go @@ -0,0 +1,11 @@ +// +build ppc64le + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_s390x.go b/vendor/github.com/kr/pty/ztypes_s390x.go new file mode 100644 index 000000000..a7452b61c --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_s390x.go @@ -0,0 +1,11 @@ +// +build s390x + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/willdonnelly/passwd/README b/vendor/github.com/willdonnelly/passwd/README new file mode 100644 index 000000000..0024c0a4f --- /dev/null +++ b/vendor/github.com/willdonnelly/passwd/README @@ -0,0 +1,26 @@ +> godoc github.com/willdonnelly/passwd + +PACKAGE + +package passwd + import "github.com/willdonnelly/passwd" + + +FUNCTIONS + +func Parse() (map[string]Entry, error) + Parse opens the '/etc/passwd' file and parses it into a map from + usernames to Entries + + +TYPES + +type Entry struct { + Pass string + Uid string + Gid string + Gecos string + Home string + Shell string +} + An Entry contains all the fields for a specific user diff --git a/vendor/github.com/willdonnelly/passwd/passwd.go b/vendor/github.com/willdonnelly/passwd/passwd.go new file mode 100644 index 000000000..de9f6b462 --- /dev/null +++ b/vendor/github.com/willdonnelly/passwd/passwd.go @@ -0,0 +1,71 @@ +// Package passwd parsed content and files in form of /etc/passwd +package passwd + +import ( + "bufio" + "errors" + "io" + "os" + "strings" +) + +// An Entry contains all the fields for a specific user +type Entry struct { + Pass string + Uid string + Gid string + Gecos string + Home string + Shell string +} + +// Parse opens the '/etc/passwd' file and parses it into a map from usernames +// to Entries +func Parse() (map[string]Entry, error) { + return ParseFile("/etc/passwd") +} + +// ParseFile opens the file and parses it into a map from usernames to Entries +func ParseFile(path string) (map[string]Entry, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + + defer file.Close() + + return ParseReader(file) +} + +// ParseReader consumes the contents of r and parses it into a map from +// usernames to Entries +func ParseReader(r io.Reader) (map[string]Entry, error) { + lines := bufio.NewReader(r) + entries := make(map[string]Entry) + for { + line, _, err := lines.ReadLine() + if err != nil { + break + } + name, entry, err := parseLine(string(copyBytes(line))) + if err != nil { + return nil, err + } + entries[name] = entry + } + return entries, nil +} + +func parseLine(line string) (string, Entry, error) { + fs := strings.Split(line, ":") + if len(fs) != 7 { + return "", Entry{}, errors.New("Unexpected number of fields in /etc/passwd") + } + return fs[0], Entry{fs[1], fs[2], fs[3], fs[4], fs[5], fs[6]}, nil +} + +func copyBytes(x []byte) []byte { + y := make([]byte, len(x)) + copy(y, x) + return y +} diff --git a/vendor/manifest b/vendor/manifest index 3f70106c0..99077b18e 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -681,6 +681,12 @@ "revision": "77ed1c8a01217656d2080ad51981f6e99adaa177", "branch": "master" }, + { + "importpath": "github.com/kr/pty", + "repository": "https://github.com/kr/pty", + "revision": "f7ee69f31298ecbe5d2b349c711e2547a617d398", + "branch": "master" + }, { "importpath": "github.com/lsegal/gucumber", "repository": "https://github.com/lsegal/gucumber", @@ -871,6 +877,12 @@ "branch": "master", "path": "/common" }, + { + "importpath": "github.com/willdonnelly/passwd", + "repository": "https://github.com/willdonnelly/passwd", + "revision": "7935dab3074ca1d47c8805e0230f8685116b6019", + "branch": "master" + }, { "importpath": "golang.org/x/crypto/curve25519", "repository": "https://go.googlesource.com/crypto", @@ -1199,4 +1211,4 @@ "branch": "master" } ] -} +} \ No newline at end of file From c1c40ad20db70a19fff09c5d38d28b27f15adcee Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Wed, 23 Mar 2016 22:31:46 +0000 Subject: [PATCH 2/5] Add host-level terminals --- common/xfer/pipes.go | 11 +++- integration/410_container_control_test.sh | 2 - integration/420_host_control_test.sh | 19 ++++++ probe/controls/pipes.go | 16 ++++- probe/docker/controls.go | 2 +- probe/docker/reporter.go | 2 +- probe/host/controls.go | 66 +++++++++++++++++++ probe/host/controls_darwin.go | 3 + probe/host/controls_linux.go | 78 +++++++++++++++++++++++ probe/host/reporter.go | 13 +++- probe/host/reporter_test.go | 3 +- prog/probe.go | 5 +- 12 files changed, 208 insertions(+), 12 deletions(-) create mode 100755 integration/420_host_control_test.sh create mode 100644 probe/host/controls.go create mode 100644 probe/host/controls_darwin.go create mode 100644 probe/host/controls_linux.go diff --git a/common/xfer/pipes.go b/common/xfer/pipes.go index 9510a9d7f..895b2bb33 100644 --- a/common/xfer/pipes.go +++ b/common/xfer/pipes.go @@ -27,7 +27,16 @@ type pipe struct { onClose func() } -// NewPipe makes a new... pipe. +// NewPipeFromEnds makes a new pipe specifying its ends +func NewPipeFromEnds(local io.ReadWriter, remote io.ReadWriter) Pipe { + return &pipe{ + port: local, + starboard: remote, + quit: make(chan struct{}), + } +} + +// NewPipe makes a new pipe func NewPipe() Pipe { r1, w1 := io.Pipe() r2, w2 := io.Pipe() diff --git a/integration/410_container_control_test.sh b/integration/410_container_control_test.sh index 483c18622..b85a57a8b 100755 --- a/integration/410_container_control_test.sh +++ b/integration/410_container_control_test.sh @@ -13,8 +13,6 @@ wait_for_containers $HOST1 60 alpine assert "docker_on $HOST1 inspect --format='{{.State.Running}}' alpine" "true" PROBEID=$(docker_on $HOST1 logs weavescope 2>&1 | grep "probe starting" | sed -n 's/^.*ID \([0-9a-f]*\)$/\1/p') -HOSTID=$(echo $HOST1 | cut -d"." -f1) - # Execute 'echo foo' in a container tty and check its output PIPEID=$(curl -s -f -X POST "http://$HOST1:4040/api/control/$PROBEID/$CID;/docker_exec_container" | jq -r '.pipe' ) diff --git a/integration/420_host_control_test.sh b/integration/420_host_control_test.sh new file mode 100755 index 000000000..54d23314f --- /dev/null +++ b/integration/420_host_control_test.sh @@ -0,0 +1,19 @@ +#! /bin/bash + +. ./config.sh + +start_suite "Test host controls" + +weave_on $HOST1 launch +scope_on $HOST1 launch + +sleep 10 + +PROBEID=$(docker_on $HOST1 logs weavescope 2>&1 | grep "probe starting" | sed -n 's/^.*ID \([0-9a-f]*\)$/\1/p') +HOSTID=$($SSH $HOST1 hostname) + +# Execute 'echo foo' in the host tty and check its output +PIPEID=$(curl -s -f -X POST "http://$HOST1:4040/api/control/$PROBEID/$HOSTID;/host_exec" | jq -r '.pipe' ) +assert "(sleep 1 && echo \"PS1=''; echo foo\" && sleep 1) | wscat -b 'ws://$HOST1:4040/api/pipe/$PIPEID' | col -pb | tail -n 1" "foo\n" + +scope_end_suite diff --git a/probe/controls/pipes.go b/probe/controls/pipes.go index cf540419f..ec4198eed 100644 --- a/probe/controls/pipes.go +++ b/probe/controls/pipes.go @@ -2,6 +2,7 @@ package controls import ( "fmt" + "io" "math/rand" "github.com/weaveworks/scope/common/xfer" @@ -21,11 +22,10 @@ type pipe struct { client PipeClient } -// NewPipe creats a new pipe and connects it to the app. -var NewPipe = func(c PipeClient, appID string) (string, xfer.Pipe, error) { +func newPipe(p xfer.Pipe, c PipeClient, appID string) (string, xfer.Pipe, error) { pipeID := fmt.Sprintf("pipe-%d", rand.Int63()) pipe := &pipe{ - Pipe: xfer.NewPipe(), + Pipe: p, appID: appID, id: pipeID, client: c, @@ -36,6 +36,16 @@ var NewPipe = func(c PipeClient, appID string) (string, xfer.Pipe, error) { return pipeID, pipe, nil } +// NewPipe creates a new pipe and connects it to the app. +var NewPipe = func(c PipeClient, appID string) (string, xfer.Pipe, error) { + return newPipe(xfer.NewPipe(), c, appID) +} + +// NewPipeFromEnds creates a new pipe from its ends and connects it to the app. +func NewPipeFromEnds(local, remote io.ReadWriter, c PipeClient, appID string) (string, xfer.Pipe, error) { + return newPipe(xfer.NewPipeFromEnds(local, remote), c, appID) +} + func (p *pipe) Close() error { err1 := p.Pipe.Close() err2 := p.client.PipeClose(p.appID, p.id) diff --git a/probe/docker/controls.go b/probe/docker/controls.go index 8977523e9..23b8d23ba 100644 --- a/probe/docker/controls.go +++ b/probe/docker/controls.go @@ -10,7 +10,7 @@ import ( "github.com/weaveworks/scope/report" ) -// Control IDs used by the docker intergation. +// Control IDs used by the docker integration. const ( StopContainer = "docker_stop_container" StartContainer = "docker_start_container" diff --git a/probe/docker/reporter.go b/probe/docker/reporter.go index d56a2677e..87b69a606 100644 --- a/probe/docker/reporter.go +++ b/probe/docker/reporter.go @@ -102,7 +102,7 @@ func (r *Reporter) containerTopology(localAddrs []net.IP) report.Topology { }) result.Controls.AddControl(report.Control{ ID: ExecContainer, - Human: "Exec /bin/sh", + Human: "Exec shell", Icon: "fa-terminal", }) diff --git a/probe/host/controls.go b/probe/host/controls.go new file mode 100644 index 000000000..c7d8d878c --- /dev/null +++ b/probe/host/controls.go @@ -0,0 +1,66 @@ +package host + +import ( + "os/exec" + + log "github.com/Sirupsen/logrus" + "github.com/kr/pty" + + "github.com/weaveworks/scope/common/xfer" + "github.com/weaveworks/scope/probe/controls" +) + +// Control IDs used by the host integration. +const ( + ExecHost = "host_exec" +) + +// Controls handles controls for a hosts. +type Controls struct { + pipes controls.PipeClient +} + +// NewControls creates new host controls. +func NewControls(pipes controls.PipeClient) *Controls { + c := &Controls{pipes: pipes} + controls.Register(ExecHost, c.execHost) + return c +} + +// Stop stops the host controls. +func (*Controls) Stop() { + controls.Rm(ExecHost) +} + +func (c *Controls) execHost(req xfer.Request) xfer.Response { + cmd := exec.Command(hostShellCmd[0], hostShellCmd[1:]...) + cmd.Env = []string{"TERM=xterm"} + ptyPipe, err := pty.Start(cmd) + if err != nil { + return xfer.ResponseError(err) + } + + id, pipe, err := controls.NewPipeFromEnds(nil, ptyPipe, c.pipes, req.AppID) + if err != nil { + return xfer.ResponseError(err) + } + pipe.OnClose(func() { + if err := cmd.Process.Kill(); err != nil { + log.Errorf("Error closing host shell: %v", err) + return + } + log.Info("Host shell closed.") + }) + go func() { + if err := cmd.Wait(); err != nil { + log.Errorf("Error waiting on host shell: %v", err) + } + ptyPipe.Close() + pipe.Close() + }() + + return xfer.Response{ + Pipe: id, + RawTTY: true, + } +} diff --git a/probe/host/controls_darwin.go b/probe/host/controls_darwin.go new file mode 100644 index 000000000..418293025 --- /dev/null +++ b/probe/host/controls_darwin.go @@ -0,0 +1,3 @@ +package host + +var hostShellCmd = []string{"/bin/bash"} diff --git a/probe/host/controls_linux.go b/probe/host/controls_linux.go new file mode 100644 index 000000000..2a4ef4459 --- /dev/null +++ b/probe/host/controls_linux.go @@ -0,0 +1,78 @@ +package host + +import ( + "bytes" + "os/exec" + "syscall" + + "github.com/willdonnelly/passwd" +) + +var hostShellCmd []string + +func init() { + if isProbeContainerized() { + // Escape the container namespaces and jump into the ones from + // the host's init process. + // Note: There should be no need to enter into the host network + // and PID namespace because we should already already be there + // but it doesn't hurt. + readPasswdCmd := []string{"/usr/bin/nsenter", "-t1", "-m", "--no-fork", "cat", "/etc/passwd"} + uid, gid, shell := getRootUserDetails(readPasswdCmd) + hostShellCmd = []string{ + "/usr/bin/nsenter", "-t1", "-m", "-i", "-n", "-p", "--no-fork", + "--setuid", uid, + "--setgid", gid, + shell, + } + return + } + + _, _, shell := getRootUserDetails([]string{"cat", "/etc/passwd"}) + hostShellCmd = []string{shell} +} + +func getRootUserDetails(readPasswdCmd []string) (uid, gid, shell string) { + uid = "0" + gid = "0" + shell = "/bin/sh" + + cmd := exec.Command(readPasswdCmd[0], readPasswdCmd[1:]...) + cmdBuffer := &bytes.Buffer{} + cmd.Stdout = cmdBuffer + if err := cmd.Run(); err != nil { + return + } + + entries, err := passwd.ParseReader(cmdBuffer) + if err != nil { + return + } + + entry, ok := entries["root"] + if !ok { + return + } + + return entry.Uid, entry.Gid, entry.Shell +} + +func isProbeContainerized() bool { + // Figure out whether we are running in a container by checking if our + // mount namespace matches the one from init process. This works + // because, when containerized, the Scope probes run in the host's PID + // namespace (and if they weren't due to a configuration problem, we + // wouldn't have a way to escape the container anyhow). + var statT syscall.Stat_t + + if err := syscall.Stat("/proc/self/ns/mnt", &statT); err != nil { + return false + } + selfMountNamespaceID := statT.Ino + + if err := syscall.Stat("/proc/1/ns/mnt", &statT); err != nil { + return false + } + + return selfMountNamespaceID != statT.Ino +} diff --git a/probe/host/reporter.go b/probe/host/reporter.go index 5d20e3fcf..eced090eb 100644 --- a/probe/host/reporter.go +++ b/probe/host/reporter.go @@ -36,14 +36,16 @@ const ( type Reporter struct { hostID string hostName string + probeID string } // NewReporter returns a Reporter which produces a report containing host // topology for this host. -func NewReporter(hostID, hostName string) *Reporter { +func NewReporter(hostID, hostName, probeID string) *Reporter { return &Reporter{ hostID: hostID, hostName: hostName, + probeID: probeID, } } @@ -98,6 +100,7 @@ func (r *Reporter) Report() (report.Report, error) { memoryUsage, max := GetMemoryUsageBytes() metrics[MemoryUsage] = report.MakeMetric().Add(now, memoryUsage).WithMax(max) + metadata := map[string]string{report.ControlProbeID: r.probeID} rep.Host.AddNode(report.MakeHostNodeID(r.hostID), report.MakeNodeWith(map[string]string{ Timestamp: mtime.Now().UTC().Format(time.RFC3339Nano), HostName: r.hostName, @@ -106,7 +109,13 @@ func (r *Reporter) Report() (report.Report, error) { Uptime: uptime.String(), }).WithSets(report.EmptySets. Add(LocalNetworks, report.MakeStringSet(localCIDRs...)), - ).WithMetrics(metrics)) + ).WithMetrics(metrics).WithControls(ExecHost).WithLatests(metadata)) + + rep.Host.Controls.AddControl(report.Control{ + ID: ExecHost, + Human: "Exec shell", + Icon: "fa-terminal", + }) return rep, nil } diff --git a/probe/host/reporter_test.go b/probe/host/reporter_test.go index 4bf7ba2e1..86abd89fe 100644 --- a/probe/host/reporter_test.go +++ b/probe/host/reporter_test.go @@ -18,6 +18,7 @@ func TestReporter(t *testing.T) { network = "192.168.0.0/16" hostID = "hostid" hostname = "hostname" + probeID = "abcdeadbeef" timestamp = time.Now() metrics = report.Metrics{ host.Load1: report.MakeMetric().Add(timestamp, 1.0), @@ -57,7 +58,7 @@ func TestReporter(t *testing.T) { host.GetMemoryUsageBytes = func() (float64, float64) { return 60.0, 100.0 } host.GetLocalNetworks = func() ([]*net.IPNet, error) { return []*net.IPNet{ipnet}, nil } - rpt, err := host.NewReporter(hostID, hostname).Report() + rpt, err := host.NewReporter(hostID, hostname, probeID).Report() if err != nil { t.Fatal(err) } diff --git a/prog/probe.go b/prog/probe.go index ccb7f10e6..79408f9b4 100644 --- a/prog/probe.go +++ b/prog/probe.go @@ -129,6 +129,9 @@ func probeMain() { }) defer clients.Stop() + hostControls := host.NewControls(clients) + defer hostControls.Stop() + resolver := appclient.NewResolver(targets, net.LookupIP, clients.Set) defer resolver.Stop() @@ -142,7 +145,7 @@ func probeMain() { p.AddTicker(processCache) p.AddReporter( endpointReporter, - host.NewReporter(hostID, hostName), + host.NewReporter(hostID, hostName, probeID), process.NewReporter(processCache, hostID, process.GetDeltaTotalJiffies), ) p.AddTagger(probe.NewTopologyTagger(), host.NewTagger(hostID)) From 59af5d28adf679af1a537cd03781577b4f518f70 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 29 Mar 2016 16:44:25 +0000 Subject: [PATCH 3/5] Review feedback: merge host controls with reporter --- probe/host/controls.go | 19 +++++-------------- probe/host/reporter.go | 14 ++++++++++++-- probe/host/reporter_test.go | 2 +- prog/probe.go | 7 +++---- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/probe/host/controls.go b/probe/host/controls.go index c7d8d878c..0ecad9f59 100644 --- a/probe/host/controls.go +++ b/probe/host/controls.go @@ -15,24 +15,15 @@ const ( ExecHost = "host_exec" ) -// Controls handles controls for a hosts. -type Controls struct { - pipes controls.PipeClient +func (r *Reporter) registerControls() { + controls.Register(ExecHost, r.execHost) } -// NewControls creates new host controls. -func NewControls(pipes controls.PipeClient) *Controls { - c := &Controls{pipes: pipes} - controls.Register(ExecHost, c.execHost) - return c -} - -// Stop stops the host controls. -func (*Controls) Stop() { +func (*Reporter) deregisterControls() { controls.Rm(ExecHost) } -func (c *Controls) execHost(req xfer.Request) xfer.Response { +func (r *Reporter) execHost(req xfer.Request) xfer.Response { cmd := exec.Command(hostShellCmd[0], hostShellCmd[1:]...) cmd.Env = []string{"TERM=xterm"} ptyPipe, err := pty.Start(cmd) @@ -40,7 +31,7 @@ func (c *Controls) execHost(req xfer.Request) xfer.Response { return xfer.ResponseError(err) } - id, pipe, err := controls.NewPipeFromEnds(nil, ptyPipe, c.pipes, req.AppID) + id, pipe, err := controls.NewPipeFromEnds(nil, ptyPipe, r.pipes, req.AppID) if err != nil { return xfer.ResponseError(err) } diff --git a/probe/host/reporter.go b/probe/host/reporter.go index eced090eb..23b7c48e4 100644 --- a/probe/host/reporter.go +++ b/probe/host/reporter.go @@ -6,6 +6,7 @@ import ( "time" "github.com/weaveworks/scope/common/mtime" + "github.com/weaveworks/scope/probe/controls" "github.com/weaveworks/scope/report" ) @@ -37,16 +38,20 @@ type Reporter struct { hostID string hostName string probeID string + pipes controls.PipeClient } // NewReporter returns a Reporter which produces a report containing host // topology for this host. -func NewReporter(hostID, hostName, probeID string) *Reporter { - return &Reporter{ +func NewReporter(hostID, hostName, probeID string, pipes controls.PipeClient) *Reporter { + r := &Reporter{ hostID: hostID, hostName: hostName, probeID: probeID, + pipes: pipes, } + r.registerControls() + return r } // Name of this reporter, for metrics gathering @@ -119,3 +124,8 @@ func (r *Reporter) Report() (report.Report, error) { return rep, nil } + +// Stop stops the reporter. +func (r *Reporter) Stop() { + r.deregisterControls() +} diff --git a/probe/host/reporter_test.go b/probe/host/reporter_test.go index 86abd89fe..3933c1e27 100644 --- a/probe/host/reporter_test.go +++ b/probe/host/reporter_test.go @@ -58,7 +58,7 @@ func TestReporter(t *testing.T) { host.GetMemoryUsageBytes = func() (float64, float64) { return 60.0, 100.0 } host.GetLocalNetworks = func() ([]*net.IPNet, error) { return []*net.IPNet{ipnet}, nil } - rpt, err := host.NewReporter(hostID, hostname, probeID).Report() + rpt, err := host.NewReporter(hostID, hostname, probeID, nil).Report() if err != nil { t.Fatal(err) } diff --git a/prog/probe.go b/prog/probe.go index 79408f9b4..7ae166747 100644 --- a/prog/probe.go +++ b/prog/probe.go @@ -129,9 +129,6 @@ func probeMain() { }) defer clients.Stop() - hostControls := host.NewControls(clients) - defer hostControls.Stop() - resolver := appclient.NewResolver(targets, net.LookupIP, clients.Set) defer resolver.Stop() @@ -143,9 +140,11 @@ func probeMain() { p := probe.New(*spyInterval, *publishInterval, clients) p.AddTicker(processCache) + hostReporter := host.NewReporter(hostID, hostName, probeID, clients) + defer hostReporter.Stop() p.AddReporter( endpointReporter, - host.NewReporter(hostID, hostName, probeID), + hostReporter, process.NewReporter(processCache, hostID, process.GetDeltaTotalJiffies), ) p.AddTagger(probe.NewTopologyTagger(), host.NewTagger(hostID)) From 4a496073b0bec3f07330fd1a0c1697d845b53016 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Wed, 30 Mar 2016 23:57:31 +0000 Subject: [PATCH 4/5] More robust obtention of host shell command --- probe/host/controls.go | 2 +- probe/host/controls_darwin.go | 4 +++- probe/host/controls_linux.go | 26 ++++++++++++++++++-------- probe/host/reporter.go | 18 ++++++++++-------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/probe/host/controls.go b/probe/host/controls.go index 0ecad9f59..3f666c66c 100644 --- a/probe/host/controls.go +++ b/probe/host/controls.go @@ -24,7 +24,7 @@ func (*Reporter) deregisterControls() { } func (r *Reporter) execHost(req xfer.Request) xfer.Response { - cmd := exec.Command(hostShellCmd[0], hostShellCmd[1:]...) + cmd := exec.Command(r.hostShellCmd[0], r.hostShellCmd[1:]...) cmd.Env = []string{"TERM=xterm"} ptyPipe, err := pty.Start(cmd) if err != nil { diff --git a/probe/host/controls_darwin.go b/probe/host/controls_darwin.go index 418293025..cae9c363e 100644 --- a/probe/host/controls_darwin.go +++ b/probe/host/controls_darwin.go @@ -1,3 +1,5 @@ package host -var hostShellCmd = []string{"/bin/bash"} +func getHostShellCmd() []string { + return []string{"/bin/bash"} +} diff --git a/probe/host/controls_linux.go b/probe/host/controls_linux.go index 2a4ef4459..f4870c33d 100644 --- a/probe/host/controls_linux.go +++ b/probe/host/controls_linux.go @@ -3,14 +3,14 @@ package host import ( "bytes" "os/exec" + "strings" "syscall" + log "github.com/Sirupsen/logrus" "github.com/willdonnelly/passwd" ) -var hostShellCmd []string - -func init() { +func getHostShellCmd() []string { if isProbeContainerized() { // Escape the container namespaces and jump into the ones from // the host's init process. @@ -19,17 +19,16 @@ func init() { // but it doesn't hurt. readPasswdCmd := []string{"/usr/bin/nsenter", "-t1", "-m", "--no-fork", "cat", "/etc/passwd"} uid, gid, shell := getRootUserDetails(readPasswdCmd) - hostShellCmd = []string{ + return []string{ "/usr/bin/nsenter", "-t1", "-m", "-i", "-n", "-p", "--no-fork", "--setuid", uid, "--setgid", gid, shell, } - return } _, _, shell := getRootUserDetails([]string{"cat", "/etc/passwd"}) - hostShellCmd = []string{shell} + return []string{shell} } func getRootUserDetails(readPasswdCmd []string) (uid, gid, shell string) { @@ -41,16 +40,23 @@ func getRootUserDetails(readPasswdCmd []string) (uid, gid, shell string) { cmdBuffer := &bytes.Buffer{} cmd.Stdout = cmdBuffer if err := cmd.Run(); err != nil { + log.Warnf( + "getRootUserDetails(): error running read passwd command %q: %s", + strings.Join(readPasswdCmd, " "), + err, + ) return } entries, err := passwd.ParseReader(cmdBuffer) if err != nil { + log.Warnf("getRootUserDetails(): error parsing passwd: %s", err) return } entry, ok := entries["root"] if !ok { + log.Warnf("getRootUserDetails(): no root entry in passwd") return } @@ -65,12 +71,16 @@ func isProbeContainerized() bool { // wouldn't have a way to escape the container anyhow). var statT syscall.Stat_t - if err := syscall.Stat("/proc/self/ns/mnt", &statT); err != nil { + path := "/proc/self/ns/mnt" + if err := syscall.Stat(path, &statT); err != nil { + log.Warnf("isProbeContainerized(): stat() error on %q: %s", path, err) return false } selfMountNamespaceID := statT.Ino - if err := syscall.Stat("/proc/1/ns/mnt", &statT); err != nil { + path = "/proc/1/ns/mnt" + if err := syscall.Stat(path, &statT); err != nil { + log.Warnf("isProbeContainerized(): stat() error on %q: %s", path, err) return false } diff --git a/probe/host/reporter.go b/probe/host/reporter.go index 23b7c48e4..04019d376 100644 --- a/probe/host/reporter.go +++ b/probe/host/reporter.go @@ -35,20 +35,22 @@ const ( // Reporter generates Reports containing the host topology. type Reporter struct { - hostID string - hostName string - probeID string - pipes controls.PipeClient + hostID string + hostName string + probeID string + pipes controls.PipeClient + hostShellCmd []string } // NewReporter returns a Reporter which produces a report containing host // topology for this host. func NewReporter(hostID, hostName, probeID string, pipes controls.PipeClient) *Reporter { r := &Reporter{ - hostID: hostID, - hostName: hostName, - probeID: probeID, - pipes: pipes, + hostID: hostID, + hostName: hostName, + probeID: probeID, + pipes: pipes, + hostShellCmd: getHostShellCmd(), } r.registerControls() return r From 2c4de6243ae9f681ed2ae0c382845e52f59ce36a Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Fri, 1 Apr 2016 12:14:55 +0000 Subject: [PATCH 5/5] Review comment: move pty's Close --- probe/host/controls.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/probe/host/controls.go b/probe/host/controls.go index 3f666c66c..4e67e7a55 100644 --- a/probe/host/controls.go +++ b/probe/host/controls.go @@ -37,8 +37,10 @@ func (r *Reporter) execHost(req xfer.Request) xfer.Response { } pipe.OnClose(func() { if err := cmd.Process.Kill(); err != nil { - log.Errorf("Error closing host shell: %v", err) - return + log.Errorf("Error stopping host shell: %v", err) + } + if err := ptyPipe.Close(); err != nil { + log.Errorf("Error closing host shell's pty: %v", err) } log.Info("Host shell closed.") }) @@ -46,7 +48,6 @@ func (r *Reporter) execHost(req xfer.Request) xfer.Response { if err := cmd.Wait(); err != nil { log.Errorf("Error waiting on host shell: %v", err) } - ptyPipe.Close() pipe.Close() }()