Skip to content

Commit

Permalink
Replace golang.org/x/term with golang.org/x/sys/unix
Browse files Browse the repository at this point in the history
A subsequent commit will use this to ensure that the user can still
interact with the image download prompt while 'skopeo inspect' fetches
the image size from the remote registry.

To do this, at some point, the terminal device will be put into
non-canonical mode input and the echoing of input characters will be
disabled to retain full control of the cursor position.  Unfortunately,
this will require access to the full termios(3) struct that isn't given
by golang.org/x/term, and, hence, the code needs to be written using the
underlying termios(3) API.

This future code will have enough overlap with the IsTerminal API from
golang.org/x/term that it doesn't make sense to use a separate module
(ie., golang.org/x/term) for it.

#752
#1263
  • Loading branch information
debarshiray committed Dec 13, 2023
1 parent 2149609 commit 34d46db
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 27 deletions.
11 changes: 3 additions & 8 deletions src/cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ import (
"github.com/containers/toolbox/pkg/podman"
"github.com/containers/toolbox/pkg/shell"
"github.com/containers/toolbox/pkg/skopeo"
"github.com/containers/toolbox/pkg/term"
"github.com/containers/toolbox/pkg/utils"
"github.com/docker/go-units"
"github.com/godbus/dbus/v5"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/term"
)

const (
Expand Down Expand Up @@ -449,10 +449,7 @@ func createContainer(container, image, release, authFile string, showCommandToEn
}

s := spinner.New(spinner.CharSets[9], 500*time.Millisecond)

stdoutFd := os.Stdout.Fd()
stdoutFdInt := int(stdoutFd)
if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel && term.IsTerminal(stdoutFdInt) {
if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel && term.IsTerminal(os.Stdout) {
s.Prefix = fmt.Sprintf("Creating container %s: ", container)
s.Writer = os.Stdout
s.Start()
Expand Down Expand Up @@ -731,9 +728,7 @@ func pullImage(image, release, authFile string) (bool, error) {

logrus.Debugf("Pulling image %s", imageFull)

stdoutFd := os.Stdout.Fd()
stdoutFdInt := int(stdoutFd)
if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel && term.IsTerminal(stdoutFdInt) {
if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel && term.IsTerminal(os.Stdout) {
s := spinner.New(spinner.CharSets[9], 500*time.Millisecond)
s.Prefix = fmt.Sprintf("Pulling %s: ", imageFull)
s.Writer = os.Stdout
Expand Down
14 changes: 6 additions & 8 deletions src/cmd/list.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2019 – 2022 Red Hat Inc.
* Copyright © 2019 – 2023 Red Hat Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -25,10 +25,10 @@ import (
"text/tabwriter"

"github.com/containers/toolbox/pkg/podman"
"github.com/containers/toolbox/pkg/term"
"github.com/containers/toolbox/pkg/utils"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/term"
)

type toolboxContainer struct {
Expand Down Expand Up @@ -247,11 +247,9 @@ func listOutput(images []podman.Image, containers []toolboxContainer) {
const defaultColor = "\033[0;00m" // identical to resetColor, but same length as boldGreenColor
const resetColor = "\033[0m"

stdoutFd := os.Stdout.Fd()
stdoutFdInt := int(stdoutFd)
writer := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)

if term.IsTerminal(stdoutFdInt) {
if term.IsTerminal(os.Stdout) {
fmt.Fprintf(writer, "%s", defaultColor)
}

Expand All @@ -263,7 +261,7 @@ func listOutput(images []podman.Image, containers []toolboxContainer) {
"STATUS",
"IMAGE NAME")

if term.IsTerminal(stdoutFdInt) {
if term.IsTerminal(os.Stdout) {
fmt.Fprintf(writer, "%s", resetColor)
}

Expand All @@ -275,7 +273,7 @@ func listOutput(images []podman.Image, containers []toolboxContainer) {
isRunning = container.Status == "running"
}

if term.IsTerminal(stdoutFdInt) {
if term.IsTerminal(os.Stdout) {
var color string
if isRunning {
color = boldGreenColor
Expand All @@ -293,7 +291,7 @@ func listOutput(images []podman.Image, containers []toolboxContainer) {
container.Status,
container.Image)

if term.IsTerminal(stdoutFdInt) {
if term.IsTerminal(os.Stdout) {
fmt.Fprintf(writer, "%s", resetColor)
}

Expand Down
10 changes: 2 additions & 8 deletions src/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ import (

"github.com/containers/toolbox/pkg/podman"
"github.com/containers/toolbox/pkg/shell"
"github.com/containers/toolbox/pkg/term"
"github.com/containers/toolbox/pkg/utils"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/term"
)

var (
Expand Down Expand Up @@ -317,13 +317,7 @@ func runCommandWithFallbacks(container string,
var stderr io.Writer
var ttyNeeded bool

stdinFd := os.Stdin.Fd()
stdinFdInt := int(stdinFd)

stdoutFd := os.Stdout.Fd()
stdoutFdInt := int(stdoutFd)

if term.IsTerminal(stdinFdInt) && term.IsTerminal(stdoutFdInt) {
if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
ttyNeeded = true
if logLevel := logrus.GetLevel(); logLevel >= logrus.DebugLevel {
stderr = os.Stderr
Expand Down
1 change: 0 additions & 1 deletion src/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ require (
github.com/spf13/viper v1.10.1
github.com/stretchr/testify v1.7.0
golang.org/x/sys v0.1.0
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
)
2 changes: 0 additions & 2 deletions src/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,6 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
2 changes: 2 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ sources = files(
'pkg/shell/shell.go',
'pkg/shell/shell_test.go',
'pkg/skopeo/skopeo.go',
'pkg/term/term.go',
'pkg/term/term_test.go',
'pkg/utils/libsubid-wrappers.c',
'pkg/utils/errors.go',
'pkg/utils/utils.go',
Expand Down
38 changes: 38 additions & 0 deletions src/pkg/term/term.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright © 2023 Red Hat Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package term

import (
"os"

"golang.org/x/sys/unix"
)

func GetState(file *os.File) (*unix.Termios, error) {
fileFD := file.Fd()
fileFDInt := int(fileFD)
state, err := unix.IoctlGetTermios(fileFDInt, unix.TCGETS)
return state, err
}

func IsTerminal(file *os.File) bool {
if _, err := GetState(file); err != nil {
return false
}

return true
}
45 changes: 45 additions & 0 deletions src/pkg/term/term_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright © 2023 Red Hat Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package term

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestIsTerminalTempFile(t *testing.T) {
dir := t.TempDir()
file, err := os.CreateTemp(dir, "TestIsTerminalTempFile")
assert.NoError(t, err)
fileName := file.Name()
defer os.Remove(fileName)
defer file.Close()

ok := IsTerminal(file)
assert.False(t, ok)
}

func TestIsTerminalTerm(t *testing.T) {
file, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
assert.NoError(t, err)
defer file.Close()

ok := IsTerminal(file)
assert.True(t, ok)
}

0 comments on commit 34d46db

Please sign in to comment.