diff --git a/dummy.go b/dummy.go new file mode 100644 index 0000000..d4c3e42 --- /dev/null +++ b/dummy.go @@ -0,0 +1,17 @@ +package stty + +type dummy struct{ + err error +} + +func (d *dummy) SetBaudRate(portPath string, baudrate int) error { + return d.err +} + +func (d *dummy) CheckBaudRate(portPath string) (baudrate int, err error) { + return 0, d.err +} + +func (d *dummy) TestBaudRate(portPath string, baudrate int) error { + return d.err +} diff --git a/error.go b/error.go new file mode 100644 index 0000000..4127374 --- /dev/null +++ b/error.go @@ -0,0 +1,37 @@ +package stty + +import( + "fmt" +) + +func errStack(err1 error, err2 error) error { + return fmt.Errorf("%w: %w", err1, err2) +} + +func ERR_NOT_TTY() error { + return fmt.Errorf("File is not a tty") +} + +func ERR_CANNOT_OPEN_FILE() error { + return fmt.Errorf("Can not open file") +} + +func ERR_NO_WRITE_ACCESS() error { + return fmt.Errorf("No write access") +} + +func ERR_STTY_MISSING() error { + return fmt.Errorf("Stty is missing") +} + +func ERR_BAUDRATE_NOT_SUPPORTED() error { + return fmt.Errorf("Selected baudrate is not supported") +} + +func ERR_SET_BAUDRATE_FAILED() error { + return fmt.Errorf("Failed to set baudrate using stty") +} + +func ERR_CHECK_BAUDRATE_FAILED() error { + return fmt.Errorf("Failed to check baudrate using stty") +} diff --git a/real.go b/real.go new file mode 100644 index 0000000..19a8e3d --- /dev/null +++ b/real.go @@ -0,0 +1,46 @@ +package stty + +import( + "os/exec" + "fmt" +) + +type real struct { +} + +func (r *real) SetBaudRate(portPath string, baudrate int) error { + setBaudRateCMD := exec.Command("stty", "-F", portPath, fmt.Sprint(baudrate)) + _, err := setBaudRateCMD.Output() + return errStack(ERR_SET_BAUDRATE_FAILED(), err) +} + +func (r *real) CheckBaudRate(portPath string) (baudrate int, err error) { + checkBaudRateCMD := exec.Command("stty", "-F", portPath, "speed") + sttyOutput, err := checkBaudRateCMD.Output() + if err != nil { + return 0, err + } + + _, err = fmt.Sscan(string(sttyOutput), &baudrate) + if err != nil { + return 0, err + } + return baudrate, nil +} + +func (r *real) TestBaudRate(portPath string, baudrate int) error { + err := r.SetBaudRate(portPath, baudrate) + if err != nil { + return err + } + + newBaudRate, err := r.CheckBaudRate(portPath) + if err != nil { + return errStack(ERR_CHECK_BAUDRATE_FAILED(), err) + } + + if newBaudRate == baudrate { + return nil + } + return ERR_BAUDRATE_NOT_SUPPORTED() +} diff --git a/stty.go b/stty.go index 7fa39a9..943c784 100644 --- a/stty.go +++ b/stty.go @@ -1,76 +1,47 @@ package stty import ( - "fmt" "os" "golang.org/x/sys/unix" "golang.org/x/term" "os/exec" ) -type stty struct { +type stty interface{ + SetBaudRate(portPath string, baudrate int) error + CheckBaudRate(portPath string) (baudrate int, err error) + TestBaudRate(portPath string, baudrate int) error +} + +var cmd stty + +func CMD() stty { + return cmd +} + +func init() { + checkSttyCMD := exec.Command("stty", "--version") + sttyOutput, err := checkSttyCMD.Output() + if err != nil || len(sttyOutput) == 0 { + cmd = &dummy{errStack(ERR_STTY_MISSING(),err)} + } + cmd = &real{} } func ValidateTtyFile(filepath string) error { file, err := os.Open(filepath) if err != nil { - return err + return errStack(ERR_CANNOT_OPEN_FILE(), err) } defer file.Close() err = unix.Access(filepath, unix.W_OK) if err != nil { - return err + return errStack(ERR_NO_WRITE_ACCESS(), err) } if term.IsTerminal(int(file.Fd())) { return nil } - return fmt.Errorf("File is not a tty.") -} - -func Get() (*stty, error) { - checkSttyCMD := exec.Command("stty", "--version") - sttyOutput, err := checkSttyCMD.Output() - if err != nil || len(sttyOutput) == 0 { - return nil, fmt.Errorf("Stty is missing. Because: " + err.Error()) - } - return &stty{}, nil -} - -func (s *stty) SetBaudRate(portPath string, baudrate int) error { - setBaudRateCMD := exec.Command("stty", "-F", portPath, fmt.Sprint(baudrate)) - _, err := setBaudRateCMD.Output() - return err -} - -func (s *stty) CheckBaudRate(portPath string) (baudrate int, err error) { - checkBaudRateCMD := exec.Command("stty", "-F", portPath, "speed") - sttyOutput, err := checkBaudRateCMD.Output() - if err != nil { - return 0, fmt.Errorf("Failed to invoke stty. Because: " + err.Error()) - } - - _, err = fmt.Sscan(string(sttyOutput), &baudrate) - if err != nil { - return 0, fmt.Errorf("Failed to read baudrate from stty output. Because:" + err.Error()) - } - return baudrate, nil -} - -func (s *stty) TestBaudRate(portPath string, baudrate int) (error) { - err := s.SetBaudRate(portPath, baudrate) - if err != nil { - return fmt.Errorf("Failed to set baudrate using stty. Because: " + err.Error()) - } - - newBaudRate, err := s.CheckBaudRate(portPath) - if err != nil { - return fmt.Errorf("Failed to check baudrate using stty. Because: " + err.Error()) - } - - if newBaudRate == baudrate { - return nil - } - return fmt.Errorf("Selected baudrate is not supported.") + return ERR_NOT_TTY() }