rash-command-shell 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rash.rb +30 -4
- data/lib/rash/ext/filesystem.rb +2 -2
- data/lib/rash/pipeline.rb +95 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6769401d090279e0c3f7b3a2e26a52c59af013196c84e9b42ec09e5d9e5b5a42
|
4
|
+
data.tar.gz: 9a93bc36eb0316ba762cefa301457b9537df4009ee8127ae8c8691bdb18eecaa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1462afc1e5767594c11f45104046618a3c5158cab07ad1315fe2e46b7ed64cea0c2972516338086cbb5e6ae2ba3f99e7e442873bc7213d72830697f36adf3cdd
|
7
|
+
data.tar.gz: c296445d776d3dcde932617030279866961e1f77126e9551d08a5e31835dc0d583b710ba34a8382b245b6c142b1d51ab02081ef0a744b29556d4aef06a830933
|
data/lib/rash.rb
CHANGED
@@ -2,6 +2,7 @@ class Environment
|
|
2
2
|
|
3
3
|
attr_reader :aliasing_disabled
|
4
4
|
attr_reader :superuser_mode
|
5
|
+
attr_reader :umask
|
5
6
|
|
6
7
|
def initialize
|
7
8
|
common_init
|
@@ -28,6 +29,11 @@ class Environment
|
|
28
29
|
super
|
29
30
|
end
|
30
31
|
end
|
32
|
+
|
33
|
+
def umask=(mask)
|
34
|
+
File.umask(mask)
|
35
|
+
@umask = mask
|
36
|
+
end
|
31
37
|
|
32
38
|
def as_superuser(&block)
|
33
39
|
@superuser_mode = true
|
@@ -37,16 +43,32 @@ class Environment
|
|
37
43
|
@superuser_mode = false
|
38
44
|
end
|
39
45
|
end
|
40
|
-
|
46
|
+
|
47
|
+
def with_limits(limits, &block)
|
48
|
+
if block_given?
|
49
|
+
pid = fork do
|
50
|
+
limits.each {|resource, limit| Process.setrlimit(resource, *limit)}
|
51
|
+
block.call
|
52
|
+
exit!(true)
|
53
|
+
end
|
54
|
+
Process.wait(pid)
|
55
|
+
else
|
56
|
+
limits.each {|resource, limit| Process.setrlimit(resource, *limit)}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
41
60
|
private
|
42
61
|
|
43
62
|
def common_init
|
44
63
|
@working_directory = Dir.pwd
|
64
|
+
@umask = File.umask
|
45
65
|
|
46
66
|
@aliases = {}
|
47
67
|
@aliasing_disabled = false
|
48
68
|
@active_jobs = []
|
49
69
|
|
70
|
+
@active_pipelines = []
|
71
|
+
|
50
72
|
@prompt = {
|
51
73
|
AUTO_INDENT: true,
|
52
74
|
RETURN: ""
|
@@ -58,6 +80,7 @@ end
|
|
58
80
|
require_relative "rash/redirection"
|
59
81
|
require_relative "rash/aliasing"
|
60
82
|
require_relative "rash/jobcontrol"
|
83
|
+
require_relative "rash/pipeline"
|
61
84
|
|
62
85
|
$env = Environment.new
|
63
86
|
|
@@ -80,7 +103,7 @@ def run(file, *args)
|
|
80
103
|
unless File.executable?(exe)
|
81
104
|
raise SystemCallError.new("No such executable file - #{exe}", Errno::ENOENT::Errno)
|
82
105
|
end
|
83
|
-
system(exe, *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin})
|
106
|
+
system(exe, *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin, umask: $env.umask})
|
84
107
|
end
|
85
108
|
|
86
109
|
alias cmd __send__
|
@@ -118,13 +141,16 @@ end
|
|
118
141
|
|
119
142
|
# Note that I defy convention and don't define `respond_to_missing?`. This
|
120
143
|
# is because doing so screws with irb.
|
144
|
+
# This code is a nightmarish monstrosity. I need some kind of "dispatch" method on Environment
|
121
145
|
def self.method_missing(m, *args, &block)
|
122
146
|
exe = which(m.to_s)
|
123
147
|
if exe || ($env.alias?(m) && !$env.aliasing_disabled)
|
124
148
|
if $env.superuser_mode
|
125
|
-
system("sudo", *$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin, exception: true})
|
149
|
+
system("sudo", *$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin, exception: true, umask: $env.umask})
|
150
|
+
elsif $env.pipelined? # implicitly disallowing superuser_mode for now. Need to refactor to allow
|
151
|
+
$env.add_pipeline(m, *args)
|
126
152
|
else
|
127
|
-
system(*$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin})
|
153
|
+
system(*$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin, umask: $env.umask})
|
128
154
|
end
|
129
155
|
else
|
130
156
|
super
|
data/lib/rash/ext/filesystem.rb
CHANGED
@@ -126,9 +126,9 @@ def self.method_missing(m, *args, &block)
|
|
126
126
|
$env.local_call(m, *args, &block)
|
127
127
|
elsif exe || ($env.alias?(m) && !$env.aliasing_disabled)
|
128
128
|
if $env.superuser_mode
|
129
|
-
system("sudo", *$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin})
|
129
|
+
system("sudo", *$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin, exception: true, umask: $env.umask})
|
130
130
|
else
|
131
|
-
system(*$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin})
|
131
|
+
system(*$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: $stdout, err: $stderr, in: $stdin, umask: $env.umask})
|
132
132
|
end
|
133
133
|
else
|
134
134
|
super
|
@@ -0,0 +1,95 @@
|
|
1
|
+
class Environment
|
2
|
+
|
3
|
+
def pipelined?
|
4
|
+
@in_pipeline
|
5
|
+
end
|
6
|
+
|
7
|
+
def start_pipeline
|
8
|
+
@in_pipeline = true
|
9
|
+
end
|
10
|
+
|
11
|
+
def end_pipeline
|
12
|
+
@in_pipeline = false
|
13
|
+
if @active_pipelines.size > 0
|
14
|
+
Process.wait(@active_pipelines.last.pid)
|
15
|
+
@active_pipelines.last.writer.close # probably redundant, but leaving it for now
|
16
|
+
IO.copy_stream(@active_pipelines.last.reader, $stdout)
|
17
|
+
@active_pipelines.pop.close
|
18
|
+
@active_pipelines.reverse_each {|pipe| pipe.terminate}
|
19
|
+
@active_pipelines.clear
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_pipeline(m, *args)
|
24
|
+
input = (@active_pipelines.empty? ? $stdin : @active_pipelines.last.reader)
|
25
|
+
@active_pipelines << Pipeline.new
|
26
|
+
output = @active_pipelines.last.writer
|
27
|
+
error = ($stderr == $stdout ? output : $stderr)
|
28
|
+
pid = fork do # might not be necessary, spawn might cover it. Not risking it before testing
|
29
|
+
system(*$env.resolve_alias(m), *args.flatten.map{|a| a.to_s}, {out: output, in: input, err: error, exception: true, umask: @umask})
|
30
|
+
output.close
|
31
|
+
exit!(true)
|
32
|
+
end
|
33
|
+
output.close
|
34
|
+
@active_pipelines.last.link_process(pid)
|
35
|
+
end
|
36
|
+
|
37
|
+
def as_pipe(&block)
|
38
|
+
input = (@active_pipelines.empty? ? $stdin : @active_pipelines.last.reader)
|
39
|
+
@active_pipelines << Pipeline.new
|
40
|
+
output = @active_pipelines.last.writer
|
41
|
+
error = ($stderr == $stdout ? output : $stderr)
|
42
|
+
pid = fork do
|
43
|
+
@in_pipeline = false
|
44
|
+
$stdin = input
|
45
|
+
$stdout = output
|
46
|
+
$stderr = error
|
47
|
+
block.call
|
48
|
+
output.close
|
49
|
+
exit!(true)
|
50
|
+
end
|
51
|
+
output.close
|
52
|
+
@active_pipelines.last.link_process(pid)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
class Pipeline
|
58
|
+
attr_reader :writer, :reader, :pid
|
59
|
+
|
60
|
+
def initialize
|
61
|
+
@reader, @writer = IO.pipe
|
62
|
+
end
|
63
|
+
|
64
|
+
def link_process(pid)
|
65
|
+
@pid ||= pid
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
def close
|
70
|
+
@writer.close
|
71
|
+
@reader.close
|
72
|
+
end
|
73
|
+
|
74
|
+
def terminate
|
75
|
+
self.close
|
76
|
+
Process.kill(:PIPE, @pid)
|
77
|
+
Process.wait(@pid)
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_s
|
81
|
+
@pid
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def in_pipeline(&block)
|
88
|
+
raise IOError.new("pipelining already enabled") if $env.pipelined?
|
89
|
+
$env.start_pipeline
|
90
|
+
begin
|
91
|
+
block.call
|
92
|
+
ensure
|
93
|
+
$env.end_pipeline
|
94
|
+
end
|
95
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rash-command-shell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kellen Watt
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- lib/rash/aliasing.rb
|
37
37
|
- lib/rash/ext/filesystem.rb
|
38
38
|
- lib/rash/jobcontrol.rb
|
39
|
+
- lib/rash/pipeline.rb
|
39
40
|
- lib/rash/prompt/irb.rb
|
40
41
|
- lib/rash/redirection.rb
|
41
42
|
homepage: https://github.com/KellenWatt/rash
|