#!/usr/bin/env ruby require 'pty' mask = [] File.readlines( File.join(ENV['HOME'], ".ttymask") ).each do |line| mask << line.chomp unless line.empty? end mask_regexp = /(#{Regexp.union(*mask)})/ trap(15) do `stty echo cooked` exit(1) end begin `stty -echo raw` rio, wio, pid = PTY.spawn(ENV['SHELL'] || "/bin/sh") Thread.new do open('typescript', 'w') do |file| while buf = rio.sysread(1024) $stdout.syswrite buf.gsub(mask_regexp) {|s| '*'*s.length} file.syswrite buf end end end while buf = $stdin.sysread(1024) wio.syswrite buf end rescue PTY::ChildExited # ignore ensure `stty echo cooked` end