Need Solaris Help

  • Thread starter James Edward Gray II
  • Start date
J

James Edward Gray II

I'm told the following bit of code doesn't work on Solaris:

# A Unix savvy method to fetch the console columns, and rows.
def terminal_size
`stty size`.split.map { |x| x.to_i }.reverse
end

HighLine makes use of this method as does Capistrano by extension, so
we need find a portable solution.

Can anyone provide an equivalent technique that works on Solaris?

Thanks.

James Edward Gray II
 
G

Gregory Brown

I'm told the following bit of code doesn't work on Solaris:

# A Unix savvy method to fetch the console columns, and rows.
def terminal_size
`stty size`.split.map { |x| x.to_i }.reverse
end

HighLine makes use of this method as does Capistrano by extension, so
we need find a portable solution.

Ruport vendors this chunk of code, so sorry for the 'me too', but me too!
 
D

Douglas F Shearer

I'm told the following bit of code doesn't work on Solaris:
`stty size`.split.map { |x| x.to_i }.reverse

James Edward Gray II

If it helps, the output from stty looks like the following:

-bash-3.00# stty size
unknown mode: size
-bash-3.00# stty
speed 38400 baud; -parity
rows = 24; columns = 80; ypixels = 0; xpixels = 0;
eol = -^?; eol2 = -^?; swtch = <undef>; flush = -^?; lnext = -^?;
brkint -inpck -istrip icrnl imaxbel onlcr tab3
echo echoe echok echoctl echoke iexten

Had a quick look at the man pages, there doesn't seem to be an alias
for size.

The man pages are also on the Sun site here: http://docs.sun.com/app/
docs/doc/816-5165/6mbb0m9tb?a=view

Hope this is of some help.

Douglas F Shearer
http://douglasfshearer.com
 
A

Alex Young

Douglas said:
If it helps, the output from stty looks like the following:

-bash-3.00# stty size
unknown mode: size
-bash-3.00# stty
speed 38400 baud; -parity
rows = 24; columns = 80; ypixels = 0; xpixels = 0;
eol = -^?; eol2 = -^?; swtch = <undef>; flush = -^?; lnext = -^?;
brkint -inpck -istrip icrnl imaxbel onlcr tab3
echo echoe echok echoctl echoke iexten
On FreeBSD:

[alex@panama ~/noodling/rubinius]$ stty
speed 38400 baud;
lflags: echoe echoke echoctl pendin
oflags: -oxtabs
cflags: cs8 -parenb

No rows or columns. How about stty -a?

[alex@panama ~/noodling/rubinius]$ stty -a
speed 38400 baud; 62 rows; 157 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
-extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel -ignbrk
brkint -inpck -ignpar -parmrk
oflags: opost onlcr -ocrnl -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
eol2 = <undef>; erase = ^?; erase2 = ^H; intr = ^C; kill = ^U;
lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
 
T

Tim Pease

Can anyone provide an equivalent technique that works on Solaris?

$ cat t.rb
def terminal_size
m = %r/rows\s(?:=\s)?(\d+);.*columns\s(?:=\s)?(\d+);/.match(`stty -a`)
[Integer(m[2]), Integer(m[1])]
end

puts terminal_size.inspect

$ uname -a
SunOS hedwig 5.9 Generic_112233-12 sun4u sparc SUNW,Sun-Blade-1500

$ ruby t.rb
[80, 36]


And on the Linux box ...

$ uname -a
Linux pong 2.6.21-1.3228.fc7 #1 SMP Tue Jun 12 15:37:31 EDT 2007 i686
i686 i386 GNU/Linux

$ ruby t.rb
[80, 24]


Blessings,
TwP
 
A

Alex Young

Tim said:
Can anyone provide an equivalent technique that works on Solaris?

$ cat t.rb
def terminal_size
m = %r/rows\s(?:=\s)?(\d+);.*columns\s(?:=\s)?(\d+);/.match(`stty -a`)
[Integer(m[2]), Integer(m[1])]
end

puts terminal_size.inspect

$ uname -a
SunOS hedwig 5.9 Generic_112233-12 sun4u sparc SUNW,Sun-Blade-1500

$ ruby t.rb
[80, 36]


And on the Linux box ...

$ uname -a
Linux pong 2.6.21-1.3228.fc7 #1 SMP Tue Jun 12 15:37:31 EDT 2007 i686
i686 i386 GNU/Linux

$ ruby t.rb
[80, 24]
How's this:

[alex@panama ~/noodling/ruby]$ ruby t.rb
[157, 62]
[alex@panama ~/noodling/ruby]$ cat t.rb
def terminal_size
%r{([^;]*rows[^;]*;)([^;]*columns[^;]*;)}.match(`stty
-a`)[1..-1].map{|i| i.gsub(/\D/, '').to_i}.reverse
end

puts terminal_size.inspect


'Scuse the line break, but it works on FreeBSD, Linux and Cygwin+OCI...
 
C

Coey Minear

ronald said:
This is not pretty but it works on my Solaris 10 x64 box. But you may have
been looking
for something more elegant.

if `stty` =~ /.*\brows = (\d+).*\bcolumns = (\d+)/
rows = $1
columns = $2
end

Ron

Here's my stab at a cross-platform implementation:

def terminal_size
if /solaris/ =~ RUBY_PLATFORM
output = `stty`
[output.match('columns = (\d+)')[1].to_i,
output.match('rows = (\d+)')[1].to_i]
else
`stty size`.split.map { |x| x.to_i }.reverse
end
end

I did a quick test on Solaris (9 and 10), FreeBSD and Linux, and got
the same results in every case. (No guarantees on AIX, HP-UX, etc.)

Coey
 
A

Alex Young

James said:
I assume the current code (using `stty size`) works on FreeBSD. Does it
not?
It does. I was aiming at something that would work everywhere.
 
J

James Edward Gray II

ronald said:
This is not pretty but it works on my Solaris 10 x64 box. But
you may have
been looking
for something more elegant.

if `stty` =~ /.*\brows = (\d+).*\bcolumns = (\d+)/
rows = $1
columns = $2
end

Ron

Here's my stab at a cross-platform implementation:

def terminal_size
if /solaris/ =~ RUBY_PLATFORM
output = `stty`
[output.match('columns = (\d+)')[1].to_i,
output.match('rows = (\d+)')[1].to_i]
else
`stty size`.split.map { |x| x.to_i }.reverse
end
end

I did a quick test on Solaris (9 and 10), FreeBSD and Linux, and got
the same results in every case. (No guarantees on AIX, HP-UX, etc.)

Thanks all. I appreciate the help.

James Edward Gray II
 
J

James Edward Gray II

It does. I was aiming at something that would work everywhere.

I think it's fine just to special case Solaris since it's the only
place the old code didn't seem to hold up, for now anyway.

James Edward Gray II
 
D

Daniel Berger

Here's my stab at a cross-platform implementation:
def terminal_size
if /solaris/ =~ RUBY_PLATFORM
output = `stty`
[output.match('columns = (\d+)')[1].to_i,
output.match('rows = (\d+)')[1].to_i]
else
`stty size`.split.map { |x| x.to_i }.reverse
end
end
I did a quick test on Solaris (9 and 10), FreeBSD and Linux, and got
the same results in every case. (No guarantees on AIX, HP-UX, etc.)

Thanks all. I appreciate the help.

James,

I think you're better off using this snippet that Greg Hurrell showed
you earlier this year instead of shelling out at all. I've modified it
to use the correct value of TIOCGWINSZ for Solaris:

TIOCGWINSZ = 21608
buf = [0, 0, 0, 0].pack('SSSS')
if $stdin.ioctl(TIOCGWINSZ, buf) >= 0
rows, cols, xpixels, ypixels = buf.unpack("SSSS")
p rows, cols, xpixels, ypixels
else
puts "Unable to get window size"
end

[24, 80, 730, 370]

Regards,

Dan

PS - First time I think I've ever used IO#ioctl for anything. :)
 
J

James Edward Gray II

I think you're better off using this snippet that Greg Hurrell showed
you earlier this year instead of shelling out at all. I've modified it
to use the correct value of TIOCGWINSZ for Solaris:

TIOCGWINSZ = 21608
buf = [0, 0, 0, 0].pack('SSSS')
if $stdin.ioctl(TIOCGWINSZ, buf) >= 0
rows, cols, xpixels, ypixels = buf.unpack("SSSS")
p rows, cols, xpixels, ypixels
else
puts "Unable to get window size"
end

Can you explain why you feel the above is "better?"

James Edward Gray II
 
D

Daniel Berger

I think you're better off using this snippet that Greg Hurrell showed
you earlier this year instead of shelling out at all. I've modified it
to use the correct value of TIOCGWINSZ for Solaris:
TIOCGWINSZ = 21608
buf = [0, 0, 0, 0].pack('SSSS')
if $stdin.ioctl(TIOCGWINSZ, buf) >= 0
rows, cols, xpixels, ypixels = buf.unpack("SSSS")
p rows, cols, xpixels, ypixels
else
puts "Unable to get window size"
end

Can you explain why you feel the above is "better?"

Because the output is predictable and therefore more reliable. It also
doesn't require forking off a new process.

I've no idea if the output from 'stty -a' is the same from Solaris
2.5.1 through Solaris 10. Also, have you verified that shelling out to
stty returns the output you expect on other platforms such as HP-UX or
AIX?

Mind you, this approach requires figuring out the appropriate value
for TIOCGWINSZ for each platform (which probably doesn't change
between releases), but that's easier than parsing stdout for each
platform IMHO.

Just my .02.

Regards,

Dan
 
J

James Edward Gray II

I think you're better off using this snippet that Greg Hurrell
showed
you earlier this year instead of shelling out at all. I've
modified it
to use the correct value of TIOCGWINSZ for Solaris:
TIOCGWINSZ = 21608
buf = [0, 0, 0, 0].pack('SSSS')
if $stdin.ioctl(TIOCGWINSZ, buf) >= 0
rows, cols, xpixels, ypixels = buf.unpack("SSSS")
p rows, cols, xpixels, ypixels
else
puts "Unable to get window size"
end

Can you explain why you feel the above is "better?"

Because the output is predictable and therefore more reliable. It also
doesn't require forking off a new process.

I've no idea if the output from 'stty -a' is the same from Solaris
2.5.1 through Solaris 10. Also, have you verified that shelling out to
stty returns the output you expect on other platforms such as HP-UX or
AIX?

Mind you, this approach requires figuring out the appropriate value
for TIOCGWINSZ for each platform (which probably doesn't change
between releases), but that's easier than parsing stdout for each
platform IMHO.

It's this magic number work that scares me. In fact, the entire
chunk of code above is pretty opaque to me.

On the flip size, I understand exactly what the stty code does and
how it works. If it someone complains that it's broken on HP-UX,
AIX, or their POSIX-compliant toaster, we will add another branch in
the if chain.

I don't see that as any more maintenance than finding the magic
number and I know how to ask users to help me do the former.

Ronald parsed the output for Solaris with a single trivial Regexp, so
that didn't feel like a significant hurdle to me.

In short, I'm comfortable with the stty approach. So far I haven't
seen it blow up in anyway that I feel we would escape using ioctl().

Thanks for the advice though.

James Edward Gray II
 
D

Daniel Berger

On Aug 7, 2007, at 3:04 PM, Daniel Berger wrote:
I think you're better off using this snippet that Greg Hurrell
showed
you earlier this year instead of shelling out at all. I've
modified it
to use the correct value of TIOCGWINSZ for Solaris:
TIOCGWINSZ = 21608
buf = [0, 0, 0, 0].pack('SSSS')
if $stdin.ioctl(TIOCGWINSZ, buf) >= 0
rows, cols, xpixels, ypixels = buf.unpack("SSSS")
p rows, cols, xpixels, ypixels
else
puts "Unable to get window size"
end
Can you explain why you feel the above is "better?"
Because the output is predictable and therefore more reliable. It also
doesn't require forking off a new process.
I've no idea if the output from 'stty -a' is the same from Solaris
2.5.1 through Solaris 10. Also, have you verified that shelling out to
stty returns the output you expect on other platforms such as HP-UX or
AIX?
Mind you, this approach requires figuring out the appropriate value
for TIOCGWINSZ for each platform (which probably doesn't change
between releases), but that's easier than parsing stdout for each
platform IMHO.

It's this magic number work that scares me. In fact, the entire
chunk of code above is pretty opaque to me.

On the flip size, I understand exactly what the stty code does and
how it works. If it someone complains that it's broken on HP-UX,
AIX, or their POSIX-compliant toaster, we will add another branch in
the if chain.

I don't see that as any more maintenance than finding the magic
number and I know how to ask users to help me do the former.

Ronald parsed the output for Solaris with a single trivial Regexp, so
that didn't feel like a significant hurdle to me.

In short, I'm comfortable with the stty approach. So far I haven't
seen it blow up in anyway that I feel we would escape using ioctl().

Fair enough.

I thought I'd take a moment to explain that code a bit better. I
figure it might make it seem less opaque to you, and perhaps others
who stumble onto this thread later on will find it useful.

First, the code supplied above requires visually inspecting the
termios.h file on your system (yep, sorry, no way around that). It's
probably under /usr/include or /usr/include/sys (or you can probably
find its declaration online). That's where I got the value for
TIOCGWINSZ - it's a #define'd value.

Moving on, I realized that the row and column data (along with the
xpixel and ypixel data) is stored in structure called 'winsize'. It's
declared like so:

/* Windowing structure to support JWINSIZE/TIOCSWINSZ/TIOCGWINSZ */
struct winsize {
unsigned short ws_row; /* rows, in characters */
unsigned short ws_col; /* columns, in character */
unsigned short ws_xpixel; /* horizontal size, pixels */
unsigned short ws_ypixel; /* vertical size, pixels */
};

That's why we defined the 'buf' like this:

buf = [0, 0, 0, 0].pack('SSSS')

That says give me a data buffer large enough to hold four unsigned
short integers. We could just as well have done "buf = 0.chr * 8", but
the above notation is more explicit, to C programmers anyway, about
what that 'buf' really is, i.e. a data buffer large enough to hold a
struct with 4 members.

We then pass 'TIOCGWINSZ' and 'buf' as arguments to $stdin.ioctl. The
buf is passed by reference, meaning it will be filled with the
appropriate values after the call.

After ioctl has been called we have to unravel the buf the same way we
created it. That's how we end up with this bit:

rows, cols, xpixels, ypixels = buf.unpack('SSSS')

Hope that helps.

Dan
 
R

Reid Thompson

Daniel said:
I've no idea if the output from 'stty -a' is the same from Solaris
2.5.1 through Solaris 10. Also, have you verified that shelling out to
stty returns the output you expect on other platforms such as HP-UX or
AIX?

Two older versions of Solaris...
A)
$ uname -a
SunOS sun-db-dev 5.8 Generic_117350-46 sun4u sparc SUNW,Ultra-250

[rthompso@sun-db-dev ]/export/home/rthompso
$ stty
speed 38400 baud; -parity
rows = 61; columns = 162; ypixels = 0; xpixels = 0;
swtch = <undef>;
brkint -inpck -istrip icrnl -ixany imaxbel onlcr tab3
echo echoe echok echoctl echoke iexten

[rthompso@sun-db-dev ]/export/home/rthompso
$ stty -a
speed 38400 baud;
rows = 61; columns = 162; ypixels = 0; xpixels = 0;
csdata ?
eucw 1:0:0:0, scrw 1:0:0:0
intr = ^c; quit = ^\; erase = ^?; kill = ^u;
eof = ^d; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^q; stop = ^s; susp = ^z; dsusp = ^y;
rprnt = ^r; flush = ^o; werase = ^w; lnext = ^v;
-parenb -parodd cs8 -cstopb -hupcl cread -clocal -loblk -crtscts
-crtsxoff -parext
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -iuclc
ixon -ixany -ixoff imaxbel
isig icanon -xcase echo echoe echok -echonl -noflsh
-tostop echoctl -echoprt echoke -defecho -flusho -pendin iexten
opost -olcuc onlcr -ocrnl -onocr -onlret -ofill -ofdel tab3

and

B)
$ uname -a
SunOS ender 5.6 Generic_105181-26 sun4u sparc SUNW,Ultra-30

[rthompso@ ]/home/rthompso
$ stty
speed 38400 baud; -parity
rows = 61; columns = 162; ypixels = 0; xpixels = 0;
swtch = <undef>;
brkint -inpck -istrip icrnl -ixany imaxbel onlcr tab3
echo echoe echok echoctl echoke iexten

[rthompso@ ]/home/rthompso
$ stty -a
speed 38400 baud;
rows = 61; columns = 162; ypixels = 0; xpixels = 0;
eucw 1:0:0:0, scrw 1:0:0:0
intr = ^c; quit = ^\; erase = ^?; kill = ^u;
eof = ^d; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^q; stop = ^s; susp = ^z; dsusp = ^y;
rprnt = ^r; flush = ^o; werase = ^w; lnext = ^v;
-parenb -parodd cs8 -cstopb -hupcl cread -clocal -loblk -crtscts
-crtsxoff -parext
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -iuclc
ixon -ixany -ixoff imaxbel
isig icanon -xcase echo echoe echok -echonl -noflsh
-tostop echoctl -echoprt echoke -defecho -flusho -pendin iexten
opost -olcuc onlcr -ocrnl -onocr -onlret -ofill -ofdel tab3
 
F

F. Senault

Le 07 août à 21:29, James Edward Gray II a écrit :
I assume the current code (using `stty size`) works on FreeBSD. Does
it not?

It does.

Note that stty -a is actually in the POSIX specification, meaning that
(with the regexps provided in this thread) you could use that as a
likely fallback for any unknown OS.

Fred
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,780
Messages
2,569,610
Members
45,254
Latest member
Top Crypto TwitterChannel

Latest Threads

Top