Skip to content

Commit

Permalink
Merge pull request #599 from bmeneguele/plat-util
Browse files Browse the repository at this point in the history
util: create os-specific layer for syscalls
  • Loading branch information
bmeneg committed Feb 23, 2021
2 parents f5951aa + 090ff30 commit 4613fc6
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 7 deletions.
13 changes: 6 additions & 7 deletions cmd/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"os/exec"
"strconv"
"strings"
"syscall"

"github.com/pkg/errors"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -413,8 +412,8 @@ func textToMarkdown(text string) string {
// to avoid some markdown rendering garbage going to other outputs that
// don't support some control chars.
func isOutputTerminal() bool {
if !terminal.IsTerminal(int(syscall.Stdout)) ||
!terminal.IsTerminal(int(syscall.Stderr)) {
if !terminal.IsTerminal(sysStdout) ||
!terminal.IsTerminal(sysStderr) {
return false
}
return true
Expand Down Expand Up @@ -445,8 +444,8 @@ func NewPager(fs *flag.FlagSet) *Pager {
Files: []*os.File{pr, os.Stdout, os.Stderr},
})

savedStdout, _ := syscall.Dup(syscall.Stdout)
_ = syscall.Dup2(int(pw.Fd()), syscall.Stdout)
savedStdout, _ := dupFD(sysStdout)
_ = dupFD2(int(pw.Fd()), sysStdout)

return &Pager{
proc: proc,
Expand All @@ -456,8 +455,8 @@ func NewPager(fs *flag.FlagSet) *Pager {

func (pager *Pager) Close() {
if pager.stdout > 0 {
_ = syscall.Dup2(pager.stdout, syscall.Stdout)
_ = syscall.Close(pager.stdout)
_ = dupFD2(pager.stdout, sysStdout)
_ = closeFD(pager.stdout)
}
if pager.proc != nil {
pager.proc.Wait()
Expand Down
32 changes: 32 additions & 0 deletions cmd/util_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This file contains Linux specific calls.

// +build !windows

package cmd

// Since we're using some system calls that are platform-specific, we need
// to make sure we have a small layer of compatibility for Unix-like and
// Windows operating systems. For now, this file is still valid for BSDs
// (MacOS included).

import "syscall"

// We're using the Linux API as primary model, hence we can only return
// the results from the default syscalls.

var (
sysStdout = syscall.Stdout
sysStderr = syscall.Stderr
)

func closeFD(fd int) error {
return syscall.Close(fd)
}

func dupFD(fd int) (int, error) {
return syscall.Dup(fd)
}

func dupFD2(newFD, oldFD int) error {
return syscall.Dup2(newFD, oldFD)
}
57 changes: 57 additions & 0 deletions cmd/util_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// This file contains Windows specific calls.

// +build windows

package cmd

// Even though Windows has a POSIX layer, it's implemented in userspace and,
// consequently, the "syscall" lib doesn't export it.
// Because of it, we need to use specific Windows calls to handle some of the
// syscall we're using the `lab`.

import "syscall"

// SetStdHandle is not exported by golang syscall lib, we need to get it
// ourselves from kernel32.dll.
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
procSetStdHandleAddr = kernel32.MustFindProc("SetStdHandle").Addr()
)

// Windows has the concept of "Handles", which in Unix can be directly
// converted to integers.
var (
sysStdout = int(syscall.Stdout)
sysStderr = int(syscall.Stderr)
)

// closeFD behaves the as POSIX close()
func closeFD(fd int) error {
return syscall.Close(syscall.Handle(fd))
}

// dupFD behaves the same as POSIX dup()
func dupFD(fd int) (int, error) {
proc, err := syscall.GetCurrentProcess()
if err != nil {
return 0, err
}

var hndl syscall.Handle
err = syscall.DuplicateHandle(proc, syscall.Handle(fd), proc, &hndl, 0, true, syscall.DUPLICATE_SAME_ACCESS)
return int(hndl), err
}

// dupFD2 behaves the same as POSIX dup2()
func dupFD2(oldFD, newFD int) error {
ret, _, err := syscall.Syscall(procSetStdHandleAddr, 2, uintptr(oldFD), uintptr(newFD), 0)
if err != 0 {
return error(err)
}

if ret == 0 {
return syscall.EINVAL
}

return nil
}

0 comments on commit 4613fc6

Please sign in to comment.