networkctl/src/cli.cr

203 lines
5.7 KiB
Crystal

file_option : String? = nil
OptionParser.parse do |parser|
parser.on "-s", "--simulation", "Export the network configuration." do
Context.simulation = true
end
parser.on "-k keydir", "--keydir keydir", "Key storing directory for wireless access point connection." do |keydir|
Context.keydir = keydir
end
parser.on "-a", "--print-autodetect", "Print autodetection of the installed programs." do
Context.print_autodetect = true
end
parser.on "-w wireless-configuration-program", "--wireless wireless-configuration-program", "iw" do |prog|
Context.prefered_wireless_configuration_program = prog
end
parser.on "-n network-configuration-program", "--net-conf network-configuration-program", "ifconfig | ip" do |prog|
Context.prefered_network_configuration_program = prog
end
parser.on "-d dhcp-client-program", "--dhcp-client dhcp-client-program", "udhcpc | dhclient" do |prog|
Context.prefered_dhcp_client = prog
end
parser.on "-r root", "--root root", "Root where to search for <root>/etc/hostname.* files." do |optsn|
Context.root = optsn
end
parser.on "-f file", "--file file", "Parse a configuration file." do |optsn|
file_option = optsn
end
# 0: nothing is printed, 1: only events, 2: events and messages
parser.on "-v verbosity", "--verbosity verbosity", "Verbosity (0-2). Default: 1" do |optsn|
Context.verbosity = optsn.to_i
end
parser.missing_option do |opt|
STDERR.puts "You missed the argument for option #{opt}"
# TODO: explain the different arguments
exit 1
end
parser.invalid_option do |flag|
STDERR.puts "Error: #{flag} not a valid option"
exit 1
end
parser.unknown_args do |arg|
Context.command = arg.shift
Context.args = arg
case Context.command
when /^(list)/
when /^(up)/
when /^(down)/
when /^(scan)/
when /^(store-keys)/
when /^(context)/
else
STDERR.puts "Command #{Context.command} not understood"
exit 1
end
# unless arg.empty?
# STDERR.puts "unknown arg: #{arg}"
# exit 1
# end
end
parser.on "-h", "--help", "Show this help" do
puts parser
exit 0
end
end
Do.simulation = Context.simulation
Autodetect.print_autodetect = Context.print_autodetect
#
# discover available configuration commands
#
# ifconfig = *bsd and some linux
# ip = linux
possible_network_configuration_cmds = {
"ifconfig" => NetworkCommands::IfconfigCommand,
"ip" => NetworkCommands::IPCommand
}
# udhcpc = busybox dhcp client
possible_dhcp_clients = {
"udhcpc" => NetworkCommands::UDHCPCCommand,
"dhclient" => NetworkCommands::DHClientCommand
}
# iw = linux
possible_wireless_configuration_cmds = {
"iw" => NetworkCommands::IWCommand,
"ifconfig" => NetworkCommands::IfconfigCommand
}
# first, check if we are on OpenBSD
Context.os = Autodetect.uname
case Context.os
when "OpenBSD"
NetworkCommands.cmd_network_configuration = NetworkCommands::OpenBSDIfconfigCommand
NetworkCommands.cmd_wireless_configuration = NetworkCommands::OpenBSDIfconfigCommand
NetworkCommands.cmd_dhcp_client = NetworkCommands::OpenBSDDHClientCommand
NetworkCommands.cmd_sysctl = NetworkCommands::OpenBSDSysctlCommand
when "Linux"
key = Context.prefered_network_configuration_program
key = possible_network_configuration_cmds.keys.find { |key| Autodetect.which(key) } if key.nil?
# should crash if there is no network command installed
NetworkCommands.cmd_network_configuration = possible_network_configuration_cmds[key.not_nil!]
key = Context.prefered_wireless_configuration_program
key = possible_wireless_configuration_cmds.keys.find { |key| Autodetect.which(key) } if key.nil?
# should crash if there is no wireless command installed
NetworkCommands.cmd_wireless_configuration = possible_wireless_configuration_cmds[key.not_nil!]
key = Context.prefered_dhcp_client
key = possible_dhcp_clients.keys.find { |key| Autodetect.which(key) } if key.nil?
# should not crash if there is no dhcp client on the system
NetworkCommands.cmd_dhcp_client = possible_dhcp_clients[key] unless key.nil?
NetworkCommands.cmd_sysctl = NetworkCommands::SysctlCommand
end
files = Array(String).new
Dir.children("#{Context.root}/etc/").each do |f|
if /^hostname\./.match(f)
files << f
end
end
interface_files = Array(String).new
if ! file_option.nil?
# file passed via the '-f' option
# TODO: why having to force "not_nil!" ? Seems like a compiler bug
interface_files << file_option.not_nil!
elsif Context.args.empty?
# every configured interface
files.each do |f|
interface_files << "#{Context.root}/etc/#{f}"
end
else
# only interfaces in arguments
Context.args.each do |interface|
interface_files << "#{Context.root}/etc/hostname.#{interface}"
end
end
begin
case Context.command
when "list"
interface_files.each do |f|
puts NetworkConfigurationParser.parse_file(f)
end
when "up"
interface_files.each do |f|
network_configuration = NetworkConfigurationParser.parse_file(f)
network_configuration.execute
end
when "down"
interface_files.each do |f|
network_configuration = NetworkConfigurationParser.parse_file(f)
network_configuration.down
end
when "scan"
interface_files.each do |f|
network_configuration = NetworkConfigurationParser.parse_file(f)
network_configuration.scan
end
when "store-keys"
interface_files.each do |f|
network_configuration = NetworkConfigurationParser.parse_file(f)
network_configuration.store_access_point_keys
end
when "context"
pp! Context.root
pp! Context.keydir
pp! Context.simulation
pp! Context.verbosity
pp! Context.prefered_network_configuration_program
pp! Context.prefered_wireless_configuration_program
pp! Context.prefered_dhcp_client
pp! Context.print_autodetect
pp! Context.command
pp! Context.args
end
rescue e
STDERR.puts "#{CRED}Exception: #{CRESET}#{e}"
end