Created
January 19, 2015 15:01
-
-
Save usmanbashir/5e25852b10f43b61e7a1 to your computer and use it in GitHub Desktop.
A Unix Shell In Ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'shellwords' | |
def main | |
loop do | |
$stdout.print ENV['PROMPT'] | |
line = $stdin.gets | |
if line | |
line.strip! | |
else | |
# in the case, EOF was received on $stdin | |
exit | |
end | |
command, *arguments = Shellwords.shellsplit(line) | |
if BUILTINS[command] | |
BUILTINS[command].call(*arguments) | |
else | |
pid = fork { | |
exec command, *arguments | |
} | |
Process.wait pid | |
end | |
end | |
end | |
def main2 | |
loop do | |
$stdout.print ENV['PROMPT'] | |
line = $stdin.gets | |
commands = split_on_pipes(line) | |
placeholder_in = $stdin | |
placeholder_out = $stdout | |
pipe = [] | |
commands.each_with_index do |command, index| | |
program, *arguments = Shellwords.shellsplit(command) | |
if builtin?(program) | |
call_builtin(program, *arguments) | |
else | |
if index+1 < commands.size | |
pipe = IO.pipe | |
placeholder_out = pipe.last | |
else | |
placeholder_out = $stdout | |
end | |
spawn_program(program, *arguments, placeholder_out, placeholder_in) | |
placeholder_out.close unless placeholder_out == $stdout | |
placeholder_in.close unless placeholder_in == $stdin | |
placeholder_in = pipe.first | |
end | |
end | |
Process.waitall | |
end | |
end | |
def split_on_pipes(line) | |
line.scan( /([^"'|]+)|["']([^"']*)["']/ ).flatten.compact | |
end | |
def spawn_program(program, *arguments, placeholder_out, placeholder_in) | |
fork { | |
unless placeholder_out == $stdout | |
$stdout.reopen(placeholder_out) | |
placeholdder_out.close | |
end | |
unless placeholder_in == $stdin | |
$stdin.reopen(placeholder_in) | |
placeholder_in.close | |
end | |
exec program, *arguments | |
} | |
end | |
BUILTINS = { | |
'cd' => lambda { |dir = ENV['HOME']| Dir.chdir(dir) }, | |
'exit' => lambda { |code = 0| exit(code.to_i) }, | |
'exec' => lambda { |*command| exec *command }, | |
'set' => lambda { |args| | |
key, value = args.split('=') | |
ENV[key] = value | |
} | |
} | |
ENV['PROMPT'] = '> ' | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment