safe_shell 1.0.1 → 1.0.2
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.
- data/.gitignore +3 -0
- data/README.rdoc +4 -1
- data/lib/safe_shell.rb +15 -0
- data/lib/safe_shell/version.rb +1 -1
- data/spec/safe_shell_spec.rb +12 -0
- metadata +6 -6
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -17,6 +17,9 @@ SafeShell sets the $? operator to the process status, in the same manner as the
|
|
17
17
|
# Return true if the command exits with a zero status:
|
18
18
|
SafeShell.execute?("echo", "Hello, world!")
|
19
19
|
|
20
|
+
# Raise an exception if the command exits with a non-zero status:
|
21
|
+
SafeShell.execute!("echo", "Hello, world!")
|
22
|
+
|
20
23
|
== Why?
|
21
24
|
|
22
25
|
If you use backticks to process a file supplied by a user, a carefully crafted filename could allow execution of an arbitrary command:
|
@@ -36,7 +39,7 @@ SafeShell solves this.
|
|
36
39
|
Tested with Ruby 1.8.7, but it should be happy on pretty much any Ruby version. Maybe not so much on Windows.
|
37
40
|
|
38
41
|
== Developing
|
39
|
-
|
42
|
+
|
40
43
|
* Fork the project.
|
41
44
|
* Make your feature addition or bug fix.
|
42
45
|
* Add tests for it. This is important so I don't break it in a
|
data/lib/safe_shell.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
module SafeShell
|
2
|
+
class CommandFailedException < RuntimeError; end
|
3
|
+
|
2
4
|
def self.execute(command, *args)
|
3
5
|
opts = args.last.kind_of?(Hash) ? args.pop : {}
|
4
6
|
read_end, write_end = IO.pipe
|
@@ -21,4 +23,17 @@ module SafeShell
|
|
21
23
|
execute(*args)
|
22
24
|
$?.success?
|
23
25
|
end
|
26
|
+
|
27
|
+
def self.execute!(*args)
|
28
|
+
execute(*args).tap do
|
29
|
+
raise_command_failed_exception(*args) unless $?.success?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def self.raise_command_failed_exception(*args)
|
36
|
+
raise CommandFailedException.new("Shell command #{args.inspect} failed with status #{$?}")
|
37
|
+
end
|
38
|
+
|
24
39
|
end
|
data/lib/safe_shell/version.rb
CHANGED
data/spec/safe_shell_spec.rb
CHANGED
@@ -40,4 +40,16 @@ describe "SafeShell" do
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
context ".execute!" do
|
44
|
+
it "returns the output of the command" do
|
45
|
+
SafeShell.execute!("echo", "Hello, world!").should == "Hello, world!\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "raises an exception of the command fails" do
|
49
|
+
expect {
|
50
|
+
SafeShell.execute!("test", "a", "=", "b")
|
51
|
+
}.should raise_error(SafeShell::CommandFailedException)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
43
55
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe_shell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 19
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 2
|
10
|
+
version: 1.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Envato
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date:
|
20
|
+
date: 2012-01-03 00:00:00 +11:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
88
|
requirements: []
|
89
89
|
|
90
90
|
rubyforge_project: safe_shell
|
91
|
-
rubygems_version: 1.
|
91
|
+
rubygems_version: 1.6.2
|
92
92
|
signing_key:
|
93
93
|
specification_version: 3
|
94
94
|
summary: Safely execute shell commands and get their output.
|