Skip to content

Commit

Permalink
Revert "Clean up structure of io/console and avoid stty on Windows."
Browse files Browse the repository at this point in the history
This reverts commit 43a6732.
headius committed May 8, 2017
1 parent 59d305e commit b444a61
Showing 7 changed files with 279 additions and 342 deletions.
File renamed without changes.
306 changes: 279 additions & 27 deletions lib/ruby/1.9/io/console.rb
Original file line number Diff line number Diff line change
@@ -19,49 +19,301 @@
# we don't actually disable echo and the password is shown...we will try to
# do a better version of this in 1.7.1.

require 'rbconfig'
# attempt to call stty; if failure, fall back on stubbed version

require 'io/console/common'
if RbConfig::CONFIG['host_os'].downcase =~ /darwin|openbsd|freebsd|netbsd|linux/
require 'java'

# If Windows, always use the stub version
if RbConfig::CONFIG['host_os'] =~ /(mswin)|(win32)|(ming)/
require 'io/console/stub_console'
else
result = begin
if RbConfig::CONFIG['host_os'].downcase =~ /darwin|openbsd|freebsd|netbsd/
require File.join(File.dirname(__FILE__), 'bsd_console')

# If Linux or BSD, try to load the native version
if RbConfig::CONFIG['host_os'].downcase =~ /darwin|openbsd|freebsd|netbsd|linux/
begin
elsif RbConfig::CONFIG['host_os'].downcase =~ /linux/
require File.join(File.dirname(__FILE__), 'linux_console')

else
raise LoadError.new("no native io/console support")
end

class IO
module LibC
begin
FD_FIELD = java.io.FileDescriptor.java_class.declared_field("fd")
FD_FIELD.accessible = true

def self.fd(io)
FD_FIELD.value io.to_java.open_file_checked.main_stream_safe.descriptor.file_descriptor
end
rescue
def self.fd(io)
io.fileno
end
end
end

def ttymode
termios = LibC::Termios.new
if LibC.tcgetattr(LibC.fd(self), termios) != 0
raise SystemCallError.new("tcgetattr", FFI.errno)
end

if block_given?
yield tmp = termios.dup
if LibC.tcsetattr(LibC.fd(self), LibC::TCSADRAIN, tmp) != 0
raise SystemCallError.new("tcsetattr", FFI.errno)
end
end
termios
end

def ttymode_yield(block, &setup)
begin
orig_termios = ttymode { |t| setup.call(t) }
block.call(self)
ensure
if orig_termios && LibC.tcsetattr(LibC.fd(self), LibC::TCSADRAIN, orig_termios) != 0
raise SystemCallError.new("tcsetattr", FFI.errno)
end
end
end

TTY_RAW = Proc.new do |t|
LibC.cfmakeraw(t)
t[:c_lflag] &= ~(LibC::ECHOE|LibC::ECHOK)
end

def raw(*, &block)
ttymode_yield(block, &TTY_RAW)
end

def raw!(*)
ttymode(&TTY_RAW)
end

# Attempt to load the native Linux and BSD console logic
# require 'io/console/native_console'
# ready = true
TTY_COOKED = Proc.new do |t|
t[:c_iflag] |= (LibC::BRKINT|LibC::ISTRIP|LibC::ICRNL|LibC::IXON)
t[:c_oflag] |= LibC::OPOST
t[:c_lflag] |= (LibC::ECHO|LibC::ECHOE|LibC::ECHOK|LibC::ECHONL|LibC::ICANON|LibC::ISIG|LibC::IEXTEN)
end

rescue Exception => ex
def cooked(*, &block)
ttymode_yield(block, &TTY_COOKED)
end

warn "failed to load native console support: #{ex}" if $VERBOSE
ready = false
def cooked!(*)
ttymode(&TTY_COOKED)
end

TTY_ECHO = LibC::ECHO | LibC::ECHOE | LibC::ECHOK | LibC::ECHONL
def echo=(echo)
ttymode do |t|
if echo
t[:c_lflag] |= TTY_ECHO
else
t[:c_lflag] &= ~TTY_ECHO
end
end
end

def echo?
(ttymode[:c_lflag] & (LibC::ECHO | LibC::ECHONL)) != 0
end

def noecho(&block)
ttymode_yield(block) { |t| t[:c_lflag] &= ~(TTY_ECHO) }
end

def getch(*)
raw do
getc
end
end

def winsize
ws = LibC::Winsize.new
if LibC.ioctl(LibC.fd(self), LibC::TIOCGWINSZ, :pointer, ws.pointer) != 0
raise SystemCallError.new("ioctl(TIOCGWINSZ)", FFI.errno)
end
[ ws[:ws_row], ws[:ws_col] ]
end

def winsize=(size)
ws = LibC::Winsize.new
if LibC.ioctl(LibC.fd(self), LibC::TIOCGWINSZ, :pointer, ws.pointer) != 0
raise SystemCallError.new("ioctl(TIOCGWINSZ)", FFI.errno)
end

ws[:ws_row] = size[0]
ws[:ws_col] = size[1]
if LibC.ioctl(LibC.fd(self), LibC::TIOCSWINSZ, :pointer, ws.pointer) != 0
raise SystemCallError.new("ioctl(TIOCSWINSZ)", FFI.errno)
end
end

def iflush
raise SystemCallError.new("tcflush(TCIFLUSH)", FFI.errno) unless LibC.tcflush(LibC.fd(self), LibC::TCIFLUSH) == 0
end

def oflush
raise SystemCallError.new("tcflush(TCOFLUSH)", FFI.errno) unless LibC.tcflush(LibC.fd(self), LibC::TCOFLUSH) == 0
end

def ioflush
raise SystemCallError.new("tcflush(TCIOFLUSH)", FFI.errno) unless LibC.tcflush(LibC.fd(self), LibC::TCIOFLUSH) == 0
end
end
true
rescue Exception => ex
warn "failed to load native console support: #{ex}" if $VERBOSE
begin
`stty 2> /dev/null`
$?.exitstatus != 0
rescue Exception
nil
end
end
else
result = begin
old_stderr = $stderr.dup
$stderr.reopen('/dev/null')
`stty -a`
$?.exitstatus != 0
rescue Exception
nil
ensure
$stderr.reopen(old_stderr)
end
end

# Native failed, try to use stty
if !ready
begin
if !result || RbConfig::CONFIG['host_os'] =~ /(mswin)|(win32)|(ming)/
warn "io/console not supported; tty will not be manipulated" if $VERBOSE

require 'io/console/stty_console'
ready = true
# Windows version is always stubbed for now
class IO
def raw(*)
yield self
end

rescue Exception
def raw!(*)
end

warn "failed to load stty console support: #{ex}" if $VERBOSE
ready = false
def cooked(*)
yield self
end

def cooked!(*)
end

def getch(*)
getc
end

def echo=(echo)
end

def echo?
true
end

def noecho
yield self
end
end

# If still not ready, just use stubbed version
if !ready
require 'io/console/stub_console'
def winsize
[25, 80]
end

def winsize=(size)
end

def iflush
end

def oflush
end

def ioflush
end
end
elsif !IO.method_defined?:ttymode
warn "io/console on JRuby shells out to stty for most operations"

# Non-Windows assumes stty command is available
class IO
if RbConfig::CONFIG['host_os'].downcase =~ /linux/ && File.exists?("/proc/#{Process.pid}/fd")
def stty(*args)
`stty #{args.join(' ')} < /proc/#{Process.pid}/fd/#{fileno}`
end
else
def stty(*args)
`stty #{args.join(' ')}`
end
end

def raw(*)
saved = stty('-g')
stty('raw')
yield self
ensure
stty(saved)
end

def raw!(*)
stty('raw')
end

def cooked(*)
saved = stty('-g')
stty('-raw')
yield self
ensure
stty(saved)
end

def cooked!(*)
stty('-raw')
end

def getch(*)
getc
end

def echo=(echo)
stty(echo ? 'echo' : '-echo')
end

def echo?
(stty('-a') =~ / -echo /) ? false : true
end

def noecho
saved = stty('-g')
stty('-echo')
yield self
ensure
stty(saved)
end

# Not all systems return same format of stty -a output
IEEE_STD_1003_2 = '(?<rows>\d+) rows; (?<columns>\d+) columns'
UBUNTU = 'rows (?<rows>\d+); columns (?<columns>\d+)'

def winsize
match = stty('-a').match(/#{IEEE_STD_1003_2}|#{UBUNTU}/)
[match[:rows].to_i, match[:columns].to_i]
end

def winsize=(size)
stty("rows #{size[0]} cols #{size[1]}")
end

def iflush
end

def oflush
end

def ioflush
end
end
end
35 changes: 0 additions & 35 deletions lib/ruby/1.9/io/console/common.rb

This file was deleted.

153 changes: 0 additions & 153 deletions lib/ruby/1.9/io/console/native_console.rb

This file was deleted.

82 changes: 0 additions & 82 deletions lib/ruby/1.9/io/console/stty_console.rb

This file was deleted.

45 changes: 0 additions & 45 deletions lib/ruby/1.9/io/console/stub_console.rb

This file was deleted.

File renamed without changes.

0 comments on commit b444a61

Please sign in to comment.