From: Doug Beaver Date: 2003-03-07T12:24:22+09:00 Subject: pty & signals with wrapped shell hello, for fun, i am trying to use PTY to wrap my shell. i adapted script.rb from ext/pty and can run and exit my shell okay, but i'm having trouble getting the signals to work correctly. i can start up the shell, run ps and vi, and do some basic shell comands, but i can't interrupt or suspend any jobs started by the shell. when i call PTY.spawn, it gives me the pid of my shell. i put a trap call in my ruby code to grab sigint and sigstop and send those onto the shell's pid, but i'm pretty sure i need to send those signals to whatever subprocess my shell is currently running. i've already written a class that parses ps output and lets me query the process stack, but it's pretty heavy and i'd rather not use it unless i have to. i'm hoping that there is a cleaner way to do this in pure ruby, parsing ps or /proc feels like i'm using too much brute force. i like how short the current code is, so is there a ruby way to route the signal properly? if you're wondering why i'm doing this, i thought it would be fun to create a ruby program that runs a shell and lets you filter the input and output of the shell with ruby plugins. when you hit enter after entering a command on the prompt, your command is compared and if it matches any plugins, they are ran instead of the command being passed to the shell. i don't know if it's possible but it sounded like it would be fun to experiment with... thank you, doug p.s. i'm running ruby-1.8.0-preview2 compiled on os x 10.2. #!/usr/bin/env ruby require 'pty' input, output, pid = nil, nil, nil shell = ENV['SHELL'] if shell =~ /[^\w\/.]/ || !File.stat(shell).executable? raise "ENV[SHELL] must be a valid shell path!" exit 1 # never reached end # sending the signal to the shell doesn't do it, i need to send the # signal to the process the shell is currently running. not sure # how to do that... %w/INT STOP/.each do |signal| trap(signal) do if pid # kill(signal, pid) end end end begin system "stty -echo raw lnext ^_" input, output, pid = PTY.spawn(shell) puts "input, output, pid = #{input}, #{output}, #{pid}" Thread.new do while true output.print STDIN.getc.chr output.flush end end begin while true c = input.sysread(512) break if c.nil? print c STDOUT.flush end rescue end rescue STDERR.puts "general pty exception: #{$!}" ensure # sometimes first stty call fails, don't know why... system("stty echo -raw lnext ^v") || system("stty -raw") input.close output.close Process.kill(0, pid) && Process.kill(9, pid) end -- "Contrary to what most people say, the most dangerous animal in the world is not the lion or the tiger or even the elephant. It's a shark riding on an elephant's back, just trampling and eating everything they see." -- Jack Handey