From 3b6073a94958720f0d632aa704446f7261e86a8a Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Thu, 10 Oct 2019 03:35:21 +0200
Subject: [PATCH] Better CLI.
---
src/main.cr | 142 +++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 113 insertions(+), 29 deletions(-)
diff --git a/src/main.cr b/src/main.cr
index 7f34264..5ccc88e 100644
--- a/src/main.cr
+++ b/src/main.cr
@@ -10,9 +10,11 @@ prefered_network_configuration_program = nil
prefered_wireless_configuration_program = nil
prefered_dhcp_client = nil
+root = "/"
print_autodetect = false
command = "list"
+args = Array(String).new
OptionParser.parse! do |parser|
parser.on "-s", "--simulation", "Export the network configuration." do
@@ -35,6 +37,10 @@ OptionParser.parse! do |parser|
prefered_dhcp_client = prog
end
+ parser.on "-r root", "--root root", "Root where to search for /etc/hostname.* files." do |optsn|
+ root = optsn
+ end
+
parser.on "-f file", "--file file", "Parse a configuration file." do |optsn|
file = optsn
end
@@ -57,22 +63,22 @@ OptionParser.parse! do |parser|
parser.unknown_args do |arg|
command = arg.shift
+ args = arg
case command
when /^(list)/
- STDERR.puts "TODO: list" unless arg.empty?
when /^(up)/
- STDERR.puts "TODO: up" unless arg.empty?
when /^(down)/
- STDERR.puts "TODO: down" unless arg.empty?
+ when /^(scan)/
else
STDERR.puts "Command #{command} not understood"
- end
-
- unless arg.empty?
- STDERR.puts "unknown arg: #{arg}"
exit 1
end
+
+ # unless arg.empty?
+ # STDERR.puts "unknown arg: #{arg}"
+ # exit 1
+ # end
end
parser.on "-h", "--help", "Show this help" do
@@ -92,6 +98,15 @@ class Do < Process
Process.run cmd, params
end
end
+
+ def self.run(cmd : String, params : Array(String) = nil, &block : Process -> _)
+ if @@simulation
+ puts "simulation, do: #{cmd} #{params.join(" ")}"
+ Process::Status.new 0
+ else
+ Process.run cmd, params, &block
+ end
+ end
end
class NotSetup
@@ -109,14 +124,29 @@ end
class NetworkCommands
class_property cmd_network_configuration : IfconfigCommand.class | IPCommand.class = IfconfigCommand
- class_property cmd_wireless_configuration : IWCommand.class | NotSetup.class = NotSetup
+ class_property cmd_wireless_configuration : IfconfigCommand.class | IWCommand.class | NotSetup.class = NotSetup
class_property cmd_dhcp_client : UDHCPCCommand.class | DHClientCommand.class | NotSetup.class = NotSetup
class IWCommand
- def self.get_ssid(ifname : String, ssid)
- unless Do.run(cmd, [ ifname ]).success?
- raise "(#{cmd}) dhcp failed on #{ifname}"
+ # get the available SSID
+ def self.scan(ifname : String) : Array(String)
+ ssids = Array(String).new
+
+ Do.run("iw", [ ifname, "scan" ]) do |p|
+ p.output.each_line do |line|
+ ssid = /SSID: (?[a-zA-Z0-9_-]+)/.match(line).try &.["ssid"]
+
+ unless ssid.nil?
+ ssids << ssid
+ end
+ end
end
+
+ if ssids.empty?
+ raise "(iw) cannot get ssid list from #{ifname}"
+ end
+
+ ssids
end
end
@@ -190,6 +220,11 @@ class NetworkCommands
raise "(ifconfig) Cannot set down #{name}"
end
end
+
+ # ifconfig also performs wireless configuration on some OSs
+ def self.scan(name : String)
+ puts "TODO: (ifconfig) ifconfig ifname scan | grep SSID"
+ end
end
class IPCommand
@@ -293,13 +328,13 @@ class NetworkCommands
@@cmd_network_configuration.down name
end
- def self.wireless_list_ssid(ifname : String)
+ def self.scan(ifname : String)
cmd = @@cmd_wireless_configuration
case cmd
when NotSetup.class
puts "no wireless configuration program: cannot list ssid"
- when IWCommand.class
- cmd.list_ssid ifname
+ else
+ cmd.scan ifname
end
end
@@ -308,7 +343,7 @@ class NetworkCommands
case cmd
when NotSetup.class
puts "no wireless configuration program: cannot connect to ssid #{ssid}"
- when IWCommand.class
+ else
cmd.list_ssid ifname
end
end
@@ -566,6 +601,15 @@ class InterfaceConfiguration
NetworkCommands.flush name
NetworkCommands.down name
end
+
+ def scan
+ unless NetworkCommands.interface_exists(@name)
+ raise "The interface #{@name} doesn't exists or is already down."
+ end
+
+ ssid_list = NetworkCommands.scan name
+ pp! ssid_list
+ end
end
class NetworkConfigurationParser
@@ -819,7 +863,8 @@ possible_dhcp_clients = {
# iw = linux
possible_wireless_configuration_cmds = {
- "iw" => NetworkCommands::IWCommand
+ "iw" => NetworkCommands::IWCommand,
+ "ifconfig" => NetworkCommands::IfconfigCommand
}
key = prefered_network_configuration_program
@@ -838,20 +883,59 @@ key = possible_wireless_configuration_cmds.keys.find { |key| Autodetect.which(ke
NetworkCommands.cmd_wireless_configuration = possible_wireless_configuration_cmds[key.not_nil!]
-if file.nil?
- raise "Cannot search for files yet"
+
+files = Array(String).new
+Dir.children("#{root}/etc/").each do |f|
+ if /^hostname\./.match(f)
+ files << f
+ end
end
-case command
-when "list"
+interface_files = Array(String).new
+
+if ! file.nil?
+ # file passed via the '-f' option
# TODO: why having to force "not_nil!" ? Seems like a compiler bug
- puts NetworkConfigurationParser.parse_file(file.not_nil!)
-when "up"
- # TODO: why having to force "not_nil!" ? Seems like a compiler bug
- network_configuration = NetworkConfigurationParser.parse_file(file.not_nil!)
- network_configuration.execute
-when "down"
- # TODO: why having to force "not_nil!" ? Seems like a compiler bug
- network_configuration = NetworkConfigurationParser.parse_file(file.not_nil!)
- network_configuration.down
+ interface_files << file.not_nil!
+elsif args.empty?
+ # every configured interface
+ files.each do |f|
+ interface_files << "#{root}/etc/#{f}"
+ end
+else
+ # only interfaces in arguments
+ args.each do |interface|
+ interface_files << "#{root}/etc/hostname.#{interface}"
+ end
+end
+
+
+
+begin
+ case command
+ when "list"
+ interface_files.each do |f|
+ puts NetworkConfigurationParser.parse_file(f.not_nil!)
+ end
+ when "up"
+ # TODO: why having to force "not_nil!" ? Seems like a compiler bug
+ interface_files.each do |f|
+ network_configuration = NetworkConfigurationParser.parse_file(f.not_nil!)
+ network_configuration.execute
+ end
+ when "down"
+ # TODO: why having to force "not_nil!" ? Seems like a compiler bug
+ interface_files.each do |f|
+ network_configuration = NetworkConfigurationParser.parse_file(f.not_nil!)
+ network_configuration.down
+ end
+ when "scan"
+ # TODO: why having to force "not_nil!" ? Seems like a compiler bug
+ interface_files.each do |f|
+ network_configuration = NetworkConfigurationParser.parse_file(f.not_nil!)
+ network_configuration.scan
+ end
+ end
+rescue e
+ STDERR.puts "#{CRED}Exception: #{CRESET}#{e}"
end