Class: FOSL::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/fosl/parser.rb

Instance Method Summary collapse

Instance Method Details

#lsof(args = "") ⇒ Object

Helper for running lsof. Returns the same thing as ‘parse’

Example:

lsof("-i :443")


160
161
162
163
164
165
166
167
# File 'lib/fosl/parser.rb', line 160

def lsof(args="")
  output = `lsof -F PcfntT0L #{args}`
  # Should we raise an exception, or just return empty results, on failure?
  if $?.exitstatus != 0
    raise "lsof exited with status #{$?.exitstatus}"
  end
  return self.parse(output)
end

#new_fileObject

state helper, creates a new file hash



113
114
115
116
117
118
119
# File 'lib/fosl/parser.rb', line 113

def new_file
  if !@current_file.nil? && !@current_file.empty?
    @current_process.files << @current_file
  end

  @current_file = {}
end

#new_pid(pid) ⇒ Object

state helper, creates a new process



107
108
109
110
# File 'lib/fosl/parser.rb', line 107

def new_pid(pid)
  new_file # push the last file (if any) onto the last process
  @current_process = FOSL::Process.new(pid)
end

#parse(data) ⇒ Object

Parse output from an lsof(1) run. You must run This output must be from lsof run with this flag ‘-F Pcfnt0’



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/fosl/parser.rb', line 123

def parse(data)
  if data[0..0] != "p"
    raise "Expected first character to be 'p'. Unexpected data input - #{data[0..30]}..."
  end

  result = Hash.new { |h,k| h[k] = FOSL::Process.new(k) }

  data.split(/[\n\0]/).each do |field|
    next if field.empty?
    type = field[0 .. 0]
    value = field[1 .. -1]

    method = "parse_#{type}".to_sym
    if self.respond_to?(method)
      r = self.send(method, value)
      #p field => r
      if r.is_a?(Hash)
        @current_file.merge!(r)
      elsif r == :new_pid
        result[@current_process.pid] = @current_process
      end
    else
      $stderr.puts "Unsupported field type '#{type}': #{field.inspect}"
    end
  end

  # push last file
  new_file

  return result
end

#parse_c(data) ⇒ Object

The command name



95
96
97
98
# File 'lib/fosl/parser.rb', line 95

def parse_c(data)
  @current_process.command = data
  return nil
end

#parse_f(data) ⇒ Object

file descriptor (or ‘cwd’ etc…)



83
84
85
86
87
88
89
90
91
92
# File 'lib/fosl/parser.rb', line 83

def parse_f(data)
  new_file

  # Convert to int it looks like a number.
  if data.to_i != 0 or data == "0"
    data = data.to_i
  end

  return { :fd => data }
end

#parse_L(data) ⇒ Object

The login name



101
102
103
104
# File 'lib/fosl/parser.rb', line 101

def parse_L(data)
  @current_process. = data
  return nil
end

#parse_n(data) ⇒ Object

the file name or identifier



78
79
80
# File 'lib/fosl/parser.rb', line 78

def parse_n(data)
  return { :name => data }
end

#parse_p(data) ⇒ Object

the pid



72
73
74
75
# File 'lib/fosl/parser.rb', line 72

def parse_p(data)
  new_pid(data.to_i)
  return :new_pid
end

#parse_P(data) ⇒ Object

The protocol name



67
68
69
# File 'lib/fosl/parser.rb', line 67

def parse_P(data)
  return { :protocol => data }
end

#parse_t(data) ⇒ Object

The file’s type



62
63
64
# File 'lib/fosl/parser.rb', line 62

def parse_t(data)
  return { :type => data }
end

#parse_T(data) ⇒ Object

T is various network/tcp/socket information.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/fosl/parser.rb', line 43

def parse_T(data)
  prefix, value = data.split("=")
  case prefix
    when "ST" ; prefix = :state
    when "QR" ; prefix = :read_queue
    when "QS" ; prefix = :send_queue

    # (sissel) I don't know the  values of these fields. Feel free
    # to implement them and send me patches.
    #when "SO" ; prefix = :socket_options
    #when "SS" ; prefix = :socket_State
    #when "TF" ; prefix = :tcp_flags
    #when "WR" ; prefix = :read_window
    #when "WW" ; prefix = :write_window
  end
  return { prefix => value }
end