Skip to content

Commit c4672c3

Browse files
committed
Add support for z/OS
Add an implementation of NewPty for the zos platform. The other functions in console_zos.go exactly match those in console_unix.go. There is no need for ptsname/unlockpt on z/OS, so tc_zos.go looks just like the implementation for linux/solaris except for the omission of those functions. Signed-off-by: Neil Johnson <[email protected]>
1 parent 2f1e3d2 commit c4672c3

File tree

3 files changed

+190
-1
lines changed

3 files changed

+190
-1
lines changed

console_zos.go

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// +build zos
2+
3+
/*
4+
Copyright The containerd Authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package console
20+
21+
import (
22+
"fmt"
23+
"os"
24+
25+
"golang.org/x/sys/unix"
26+
)
27+
28+
// NewPty creates a new pty pair
29+
// The master is returned as the first console and a string
30+
// with the path to the pty slave is returned as the second
31+
func NewPty() (Console, string, error) {
32+
var f File
33+
var err error
34+
var slave string
35+
for i := 0;; i++ {
36+
ptyp := fmt.Sprintf("/dev/ptyp%04d", i)
37+
f, err = os.OpenFile(ptyp, os.O_RDWR, 0600)
38+
if err == nil {
39+
slave = fmt.Sprintf("/dev/ttyp%04d", i)
40+
break
41+
}
42+
if os.IsNotExist(err) {
43+
return nil, "", err
44+
}
45+
// else probably Resource Busy
46+
}
47+
m, err := newMaster(f)
48+
if err != nil {
49+
return nil, "", err
50+
}
51+
return m, slave, nil
52+
}
53+
54+
type master struct {
55+
f File
56+
original *unix.Termios
57+
}
58+
59+
func (m *master) Read(b []byte) (int, error) {
60+
return m.f.Read(b)
61+
}
62+
63+
func (m *master) Write(b []byte) (int, error) {
64+
return m.f.Write(b)
65+
}
66+
67+
func (m *master) Close() error {
68+
return m.f.Close()
69+
}
70+
71+
func (m *master) Resize(ws WinSize) error {
72+
return tcswinsz(m.f.Fd(), ws)
73+
}
74+
75+
func (m *master) ResizeFrom(c Console) error {
76+
ws, err := c.Size()
77+
if err != nil {
78+
return err
79+
}
80+
return m.Resize(ws)
81+
}
82+
83+
func (m *master) Reset() error {
84+
if m.original == nil {
85+
return nil
86+
}
87+
return tcset(m.f.Fd(), m.original)
88+
}
89+
90+
func (m *master) getCurrent() (unix.Termios, error) {
91+
var termios unix.Termios
92+
if err := tcget(m.f.Fd(), &termios); err != nil {
93+
return unix.Termios{}, err
94+
}
95+
return termios, nil
96+
}
97+
98+
func (m *master) SetRaw() error {
99+
rawState, err := m.getCurrent()
100+
if err != nil {
101+
return err
102+
}
103+
rawState = cfmakeraw(rawState)
104+
rawState.Oflag = rawState.Oflag | unix.OPOST
105+
return tcset(m.f.Fd(), &rawState)
106+
}
107+
108+
func (m *master) DisableEcho() error {
109+
rawState, err := m.getCurrent()
110+
if err != nil {
111+
return err
112+
}
113+
rawState.Lflag = rawState.Lflag &^ unix.ECHO
114+
return tcset(m.f.Fd(), &rawState)
115+
}
116+
117+
func (m *master) Size() (WinSize, error) {
118+
return tcgwinsz(m.f.Fd())
119+
}
120+
121+
func (m *master) Fd() uintptr {
122+
return m.f.Fd()
123+
}
124+
125+
func (m *master) Name() string {
126+
return m.f.Name()
127+
}
128+
129+
// checkConsole checks if the provided file is a console
130+
func checkConsole(f File) error {
131+
var termios unix.Termios
132+
if tcget(f.Fd(), &termios) != nil {
133+
return ErrNotAConsole
134+
}
135+
return nil
136+
}
137+
138+
func newMaster(f File) (Console, error) {
139+
m := &master{
140+
f: f,
141+
}
142+
t, err := m.getCurrent()
143+
if err != nil {
144+
return nil, err
145+
}
146+
m.original = &t
147+
return m, nil
148+
}
149+
150+
// ClearONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
151+
// created by us acts normally. In particular, a not-very-well-known default of
152+
// Linux unix98 ptys is that they have +onlcr by default. While this isn't a
153+
// problem for terminal emulators, because we relay data from the terminal we
154+
// also relay that funky line discipline.
155+
func ClearONLCR(fd uintptr) error {
156+
return setONLCR(fd, false)
157+
}
158+
159+
// SetONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
160+
// created by us acts as intended for a terminal emulator.
161+
func SetONLCR(fd uintptr) error {
162+
return setONLCR(fd, true)
163+
}

tc_unix.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build darwin freebsd linux netbsd openbsd solaris
1+
// +build darwin freebsd linux netbsd openbsd solaris zos
22

33
/*
44
Copyright The containerd Authors.

tc_zos.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package console
18+
19+
import (
20+
"golang.org/x/sys/unix"
21+
)
22+
23+
const (
24+
cmdTcGet = unix.TCGETS
25+
cmdTcSet = unix.TCSETS
26+
)

0 commit comments

Comments
 (0)