-- SPDX-License-Identifier: GPL-3.0-or-later ------------------------------------------------------------------------ -- pla-util - A power line adapter utility -- Copyright (C) 2016-2023 John Serock -- -- This file is part of pla-util. -- -- pla-util is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- pla-util is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . ------------------------------------------------------------------------ with Ada.Exceptions; with Ada.Containers.Indefinite_Hashed_Maps; with Ada.Strings.Hash; with GNAT.Command_Line; separate (Console) procedure Process_Command_Line is package String_Hashed_Maps is new Ada.Containers.Indefinite_Hashed_Maps (Key_Type => String, Element_Type => String, Hash => Ada.Strings.Hash, Equivalent_Keys => "="); procedure Process_Help_Switch; procedure Process_Interface_Switch; procedure Process_PLA_Switch; procedure Process_Timeout_Switch; procedure Process_Version_Switch; I_Key : constant String := "interface"; Message_Invalid_PLA_Address : constant String := "Invalid PLA address"; Message_Missing_Command : constant String := "Missing command"; Message_Missing_HFID : constant String := "Missing HFID argument"; Message_Missing_Passphrase : constant String := "Missing passphrase argument"; P_Key : constant String := "pla"; Switch_Parameter_Map : String_Hashed_Maps.Map; Timeout : Positive := Config.Network_Receive_Timeout; Version_Option : Boolean := False; procedure Process_Help_Switch is begin raise GNAT.Command_Line.Exit_From_Command_Line; end Process_Help_Switch; procedure Process_Interface_Switch is begin Switch_Parameter_Map.Include (Key => I_Key, New_Item => GNAT.Command_Line.Parameter); end Process_Interface_Switch; procedure Process_PLA_Switch is begin Switch_Parameter_Map.Include (Key => P_Key, New_Item => GNAT.Command_Line.Parameter); end Process_PLA_Switch; procedure Process_Timeout_Switch is begin Timeout := Integer'Value (GNAT.Command_Line.Parameter); exception when others => raise Syntax_Error with "Invalid timeout '" & GNAT.Command_Line.Parameter & "'"; end Process_Timeout_Switch; procedure Process_Version_Switch is begin Version_Option := True; end Process_Version_Switch; begin Switch_Parameter_Map.Include (Key => I_Key, New_Item => ""); Switch_Parameter_Map.Include (Key => P_Key, New_Item => ""); GNAT.Command_Line.Initialize_Option_Scan (Stop_At_First_Non_Switch => True); loop case GNAT.Command_Line.Getopt (Switches => "h -help V -version i: -interface= p: -pla= t: -timeout=") is when ASCII.NUL => exit; when 'h' => if GNAT.Command_Line.Full_Switch = "h" then Process_Help_Switch; end if; when 'V' => if GNAT.Command_Line.Full_Switch = "V" then Process_Version_Switch; end if; when 'i' => if GNAT.Command_Line.Full_Switch = "i" then Process_Interface_Switch; end if; when 'p' => if GNAT.Command_Line.Full_Switch = "p" then Process_PLA_Switch; end if; when 't' => if GNAT.Command_Line.Full_Switch = "t" then Process_Timeout_Switch; end if; when '-' => if GNAT.Command_Line.Full_Switch = "-help" then Process_Help_Switch; elsif GNAT.Command_Line.Full_Switch = "-version" then Process_Version_Switch; elsif GNAT.Command_Line.Full_Switch = "-interface" then Process_Interface_Switch; elsif GNAT.Command_Line.Full_Switch = "-pla" then Process_PLA_Switch; elsif GNAT.Command_Line.Full_Switch = "-timeout" then Process_Timeout_Switch; end if; when others => raise Program_Error; end case; end loop; if Version_Option then Show_Version; return; end if; if Timeout /= Config.Network_Receive_Timeout then Config.Network_Receive_Timeout := Timeout; end if; declare Command : Commands.Command_Type; Command_Id : constant String := GNAT.Command_Line.Get_Argument; Network_Device_Name : constant String := Switch_Parameter_Map (I_Key); PLA_MAC_Address : constant MAC_Addresses.MAC_Address_Type := (if Switch_Parameter_Map (P_Key) = "" then MAC_Addresses.Broadcast_MAC_Address else Get_PLA_MAC_Address (MAC_Address_Image => Switch_Parameter_Map (P_Key))); begin if Switch_Parameter_Map (P_Key) /= "" and then not PLA_MAC_Address.Is_Unicast then raise Syntax_Error with Message_Invalid_PLA_Address; end if; if Command_Id = "" then raise Syntax_Error with Message_Missing_Command; end if; Command := To_Command (Source => Command_Id); case Command is when Commands.Check_DAK => declare Passphrase : constant String := GNAT.Command_Line.Get_Argument; begin if Passphrase = "" then raise Syntax_Error with Message_Missing_Passphrase; end if; Check_DAK (Network_Device_Name => Network_Device_Name, Passphrase => Passphrase, PLA_MAC_Address => PLA_MAC_Address); end; when Commands.Check_NMK => declare Passphrase : constant String := GNAT.Command_Line.Get_Argument; begin if Passphrase = "" then raise Syntax_Error with Message_Missing_Passphrase; end if; Check_NMK (Network_Device_Name => Network_Device_Name, Passphrase => Passphrase, PLA_MAC_Address => PLA_MAC_Address); end; when Commands.Discover => Discover (Network_Device_Name => Network_Device_Name, PLA_MAC_Address => PLA_MAC_Address); when Commands.Get_Capabilities => Get_Capabilities (Network_Device_Name => Network_Device_Name, PLA_MAC_Address => PLA_MAC_Address); when Commands.Get_Discover_List => Get_Discover_List (Network_Device_Name => Network_Device_Name, PLA_MAC_Address => PLA_MAC_Address); when Commands.Get_HFID => declare HFID_Level_Text : constant String := GNAT.Command_Line.Get_Argument; begin Get_HFID (Network_Device_Name => Network_Device_Name, HFID_Level => (if HFID_Level_Text = "" then Commands.User else Get_HFID_Level (HFID_Level_Text => HFID_Level_Text)), PLA_MAC_Address => PLA_MAC_Address); end; when Commands.Get_Id_Info => Get_Id_Info (Network_Device_Name => Network_Device_Name, PLA_MAC_Address => PLA_MAC_Address); when Commands.Get_Network_Info => declare Network_Scope_Text : constant String := GNAT.Command_Line.Get_Argument; begin Get_Network_Info (Network_Device_Name => Network_Device_Name, Network_Scope => (if Network_Scope_Text = "" then Commands.Member else Get_Network_Scope (Network_Scope_Text => Network_Scope_Text)), PLA_MAC_Address => PLA_MAC_Address); end; when Commands.Get_Network_Stats => Get_Network_Stats (Network_Device_Name => Network_Device_Name, PLA_MAC_Address => PLA_MAC_Address); when Commands.Get_Station_Info => Get_Station_Info (Network_Device_Name => Network_Device_Name, PLA_MAC_Address => PLA_MAC_Address); when Commands.Reset => Reset (Network_Device_Name => Network_Device_Name, PLA_MAC_Address => PLA_MAC_Address); when Commands.Restart => Restart (Network_Device_Name => Network_Device_Name, PLA_MAC_Address => PLA_MAC_Address); when Commands.Set_HFID => declare HFID : constant String := GNAT.Command_Line.Get_Argument; begin if HFID = "" then raise Syntax_Error with Message_Missing_HFID; end if; Set_HFID (Network_Device_Name => Network_Device_Name, HFID => HFID, PLA_MAC_Address => PLA_MAC_Address); end; when Commands.Set_NMK => declare Passphrase : constant String := GNAT.Command_Line.Get_Argument; begin if Passphrase = "" then raise Syntax_Error with Message_Missing_Passphrase; end if; Set_NMK (Network_Device_Name => Network_Device_Name, Passphrase => Passphrase, PLA_MAC_Address => PLA_MAC_Address); end; end case; end; exception when GNAT.Command_Line.Exit_From_Command_Line => Show_Help; when Error : Syntax_Error | GNAT.Command_Line.Invalid_Switch => Ada.Text_IO.Put_Line (File => Ada.Text_IO.Standard_Error, Item => App_Name & ": " & Ada.Exceptions.Exception_Message (X => Error)); GNAT.Command_Line.Try_Help; Ada.Command_Line.Set_Exit_Status (Code => Ada.Command_Line.Failure); when GNAT.Command_Line.Invalid_Parameter => Ada.Text_IO.Put_Line (File => Ada.Text_IO.Standard_Error, Item => App_Name & ": Missing parameter for '-" & GNAT.Command_Line.Full_Switch & "'"); GNAT.Command_Line.Try_Help; Ada.Command_Line.Set_Exit_Status (Code => Ada.Command_Line.Failure); when Error : Commands.Command_Error | Power_Line_Adapters.Adapter_Error | MAC_Addresses.MAC_Address_Error => Ada.Text_IO.Put_Line (File => Ada.Text_IO.Standard_Error, Item => App_Name & ": " & Ada.Exceptions.Exception_Message (X => Error)); Ada.Command_Line.Set_Exit_Status (Code => Ada.Command_Line.Failure); when others => Ada.Command_Line.Set_Exit_Status (Code => Ada.Command_Line.Failure); raise; end Process_Command_Line;