fosl 0.0.1

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.
@@ -0,0 +1,2 @@
1
+ module FOSL
2
+ end
@@ -0,0 +1,162 @@
1
+ require "fosl/namespace"
2
+ require "fosl/process"
3
+
4
+ class FOSL::Parser
5
+ # Fields are separated by newlines or null
6
+ # Fields start with a character followed by the data
7
+
8
+ # These are the fields according to the lsof manpage.
9
+ # If you want to implement one, you should write a 'parse_<field letter>'
10
+ # method. It should return a hash of key => value you want to save.
11
+ #
12
+ # # The following copied mostly verbatim from the lsof manpage.
13
+ # - a file access mode
14
+ # - c process command name (all characters from proc or user structure)
15
+ # - C file structure share count
16
+ # - d file's device character code
17
+ # - D file's major/minor device number (0x<hexadecimal>)
18
+ # - f file descriptor
19
+ # - F file structure address (0x<hexadecimal>)
20
+ # - G file flaGs (0x<hexadecimal>; names if +fg follows)
21
+ # - i file's inode number
22
+ # - k link count
23
+ # - l file's lock status
24
+ # - L process login name
25
+ # - m marker between repeated output
26
+ # - n file name, comment, Internet address
27
+ # - N node identifier (ox<hexadecimal>
28
+ # - o file's offset (decimal)
29
+ # - p process ID (always selected)
30
+ # - g process group ID
31
+ # - P protocol name
32
+ # - r raw device number (0x<hexadecimal>)
33
+ # - R parent process ID
34
+ # - s file's size (decimal)
35
+ # - S file's stream identification
36
+ # - t file's type
37
+ # - T TCP/TPI information, identified by prefixes (the
38
+ # - u process user ID
39
+ # - z Solaris 10 and higher zone name
40
+ # - Z SELinux security context (inhibited when SELinux is disabled)
41
+
42
+ # T is various network/tcp/socket information.
43
+ def parse_T(data)
44
+ prefix, value = data.split("=")
45
+ case prefix
46
+ when "ST" ; prefix = :state
47
+ when "QR" ; prefix = :read_queue
48
+ when "QS" ; prefix = :send_queue
49
+
50
+ # (sissel) I don't know the values of these fields. Feel free
51
+ # to implement them and send me patches.
52
+ #when "SO" ; prefix = :socket_options
53
+ #when "SS" ; prefix = :socket_State
54
+ #when "TF" ; prefix = :tcp_flags
55
+ #when "WR" ; prefix = :read_window
56
+ #when "WW" ; prefix = :write_window
57
+ end
58
+ return { prefix => value }
59
+ end # def parse_T
60
+
61
+ # The file's type
62
+ def parse_t(data)
63
+ return { :type => data }
64
+ end
65
+
66
+ # The protocol name
67
+ def parse_P(data)
68
+ return { :protocol => data }
69
+ end
70
+
71
+ # the pid
72
+ def parse_p(data)
73
+ new_pid(data.to_i)
74
+ return :new_pid
75
+ end
76
+
77
+ # the file name or identifier
78
+ def parse_n(data)
79
+ return { :name => data }
80
+ end
81
+
82
+ # file descriptor (or 'cwd' etc...)
83
+ def parse_f(data)
84
+ new_file
85
+
86
+ # Convert to int it looks like a number.
87
+ if data.to_i != 0 or data == "0"
88
+ data = data.to_i
89
+ end
90
+
91
+ return { :fd => data }
92
+ end
93
+
94
+ # The command name
95
+ def parse_c(data)
96
+ @current_process.command = data
97
+ return nil
98
+ end
99
+
100
+ # state helper, creates a new process
101
+ def new_pid(pid)
102
+ new_file # push the last file (if any) onto the last process
103
+ @current_process = FOSL::Process.new(pid)
104
+ end
105
+
106
+ # state helper, creates a new file hash
107
+ def new_file
108
+ if !@current_file.nil? && !@current_file.empty?
109
+ @current_process.files << @current_file
110
+ end
111
+
112
+ @current_file = {}
113
+ end
114
+
115
+ # Parse output from an lsof(1) run. You must run
116
+ # This output must be from lsof run with this flag '-F Pcfnt0'
117
+ def parse(data)
118
+ if data[0..0] != "p"
119
+ raise "Expected first character to be 'p'. Unexpected data input - #{data[0..30]}..."
120
+ end
121
+
122
+ result = Hash.new { |h,k| h[k] = FOSL::Process.new(k) }
123
+
124
+ data.split(/[\n\0]/).each do |field|
125
+ next if field.empty?
126
+ type = field[0 .. 0]
127
+ value = field[1 .. -1]
128
+
129
+ method = "parse_#{type}".to_sym
130
+ if self.respond_to?(method)
131
+ r = self.send(method, value)
132
+ #p field => r
133
+ if r.is_a?(Hash)
134
+ @current_file.merge!(r)
135
+ elsif r == :new_pid
136
+ result[@current_process.pid] = @current_process
137
+ end
138
+ else
139
+ $stderr.puts "Unsupported field type '#{type}': #{field.inspect}"
140
+ end
141
+ end
142
+
143
+ # push last file
144
+ new_file
145
+
146
+ return result
147
+ end # def parse
148
+
149
+ # Helper for running lsof.
150
+ # Returns the same thing as 'parse'
151
+ #
152
+ # Example:
153
+ # lsof("-i :443")
154
+ def lsof(args="")
155
+ output = `lsof -F PcfntT0 #{args}`
156
+ # Should we raise an exception, or just return empty results, on failure?
157
+ if $?.exitstatus != 0
158
+ raise "lsof exited with status #{$?.exitstatus}"
159
+ end
160
+ return self.parse(output)
161
+ end
162
+ end # class FOSL::Parser
@@ -0,0 +1,18 @@
1
+ require "fosl/namespace"
2
+
3
+ class FOSL::Process
4
+ attr_reader :files
5
+ attr_reader :pid
6
+ attr_accessor :command
7
+
8
+ def initialize(pid)
9
+ @command = nil
10
+ @pid = pid
11
+ @files = []
12
+ end
13
+
14
+ # helpers
15
+ def listeners
16
+ @files.find_all { |f| f[:state] == "LISTEN" }
17
+ end
18
+ end # class FOSL::Process
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fosl
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Jordan Sissel
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-18 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: ""
23
+ email: jls@semicomplete.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/fosl/parser.rb
32
+ - lib/fosl/namespace.rb
33
+ - lib/fosl/process.rb
34
+ has_rdoc: true
35
+ homepage: https://github.com/jordansissel/ruby-lsof
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ hash: 3
50
+ segments:
51
+ - 0
52
+ version: "0"
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.5.1
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: fosl - a ruby api for reading lsof(1) output
69
+ test_files: []
70
+