From 4330d39c35cc44ab1fa5b1e6e1a35207c0635217 Mon Sep 17 00:00:00 2001 From: Evgeniy Alexeev Date: Wed, 12 Oct 2022 13:16:49 +0500 Subject: Add server commands Squashed commit of the following: commit 4ca788c95231709813bbe99220f93b4ef3e9c4ef Author: Evgeniy Alexeev Date: Wed Oct 12 12:19:45 2022 +0500 Add host boot commands, pooulate variant functions commit 21c36beefd0304a600a2f781a60559f647d569fb Author: Evgeniy Alexeev Date: Mon Oct 10 19:07:45 2022 +0500 Begin to add variant type commit b6f6416fa4dfbff9c677c4491fb42c5d3adb9d44 Author: Evgeniy Alexeev Date: Mon Oct 10 14:04:30 2022 +0500 Modify status commands in server commit 72405cee84fbddb8866a8a3d96350010266fc137 Author: Evgeniy Alexeev Date: Mon Oct 10 13:35:37 2022 +0500 Add power&policy status, get sdbus property func commit 81f88de144d6803bf4d53986193bf342772367eb Author: ironcaterpillar Date: Sat Oct 8 13:42:22 2022 +0500 Refactor d_bus_commands to separate file commit 224e5b8317e7e3ffbb04ada342447bf678297002 Author: Evgeniy Alexeev Date: Fri Oct 7 19:18:14 2022 +0500 Add power policy commands, refactor commit 94427ebcf778a2c0cc148c0344002491abdb052c Author: Evgeniy Alexeev Date: Thu Oct 6 18:23:42 2022 +0500 Add server power commands help commit 6888ffd32af65cb984792a47f65983207c00467e Author: Evgeniy Alexeev Date: Thu Oct 6 17:31:26 2022 +0500 Add unknown power command error message commit 5d1b4a2000820de903f10959b499c758eba383e0 Author: Evgeniy Alexeev Date: Thu Oct 6 15:54:37 2022 +0500 Fix host power dbus property name commit 49f8a15abdfb749427bd5769725b3ad54dc0583b Author: Evgeniy Alexeev Date: Thu Oct 6 13:27:37 2022 +0500 Add .gitignore commit 96569d5f9c7f245fd82545919a1910828c1058d9 Author: Evgeniy Alexeev Date: Thu Oct 6 13:27:10 2022 +0500 Add sdbus, server power commands --- .gitignore | 4 ++ meson.build | 10 ++- src/commands.c | 10 +++ src/commands.h | 4 +- src/d_bus.c | 129 +++++++++++++++++++++++++++++++++++++ src/d_bus.h | 40 ++++++++++++ src/d_bus_commands.c | 102 +++++++++++++++++++++++++++++ src/d_bus_commands.h | 48 ++++++++++++++ src/d_bus_variant.c | 10 +++ src/d_bus_variant.h | 20 ++++++ src/host_commands.c | 101 +++++++++++++++++++++++++++++ src/host_commands.h | 8 +++ src/main.c | 47 ++++++++++++++ src/power_commands.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/power_commands.h | 19 ++++++ src/shell.c | 3 +- src/utils.h | 25 ++++++- 17 files changed, 753 insertions(+), 6 deletions(-) create mode 100644 .gitignore create mode 100644 src/d_bus.c create mode 100644 src/d_bus.h create mode 100644 src/d_bus_commands.c create mode 100644 src/d_bus_commands.h create mode 100644 src/d_bus_variant.c create mode 100644 src/d_bus_variant.h create mode 100644 src/host_commands.c create mode 100644 src/host_commands.h create mode 100644 src/power_commands.c create mode 100644 src/power_commands.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6759909 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +/sila-shell.* +build +build/** diff --git a/meson.build b/meson.build index cdff7ab..55d1870 100644 --- a/meson.build +++ b/meson.build @@ -9,14 +9,20 @@ src = [ 'src/completion.c', 'src/utils.c', 'src/shell.c', - 'src/users.c' + 'src/users.c', + 'src/d_bus.c', + 'src/power_commands.c', + 'src/d_bus_commands.c', + 'src/d_bus_variant.c', + 'src/host_commands.c' ] readline = dependency('readline') +libsystemd = dependency('libsystemd') executable('sila-shell', sources : src, include_directories: incdir, - dependencies : readline, + dependencies : [ readline, libsystemd ], install : true, install_dir : '/bin' ) diff --git a/src/commands.c b/src/commands.c index b52a5a1..59e7988 100644 --- a/src/commands.c +++ b/src/commands.c @@ -125,6 +125,16 @@ int com_users( char *arg ) return( 0 ); } +int com_server( char *arg ) +{ + if( !arg ) arg = ""; + + current = &server; + + initialize_readline(); + return( 0 ); +} + int com_top( char *arg ) { if( !arg ) arg = ""; diff --git a/src/commands.h b/src/commands.h index 2c16c74..a378aad 100644 --- a/src/commands.h +++ b/src/commands.h @@ -27,6 +27,8 @@ extern COMMAND_LIST top; extern COMMAND_LIST shell; extern COMMAND_LIST users; +extern COMMAND_LIST server; + extern COMMAND_LIST *current; extern void too_dangerous( char *caller ); @@ -39,7 +41,7 @@ extern int com_quit( char *arg ); extern int com_shell( char *arg ); extern int com_users( char *arg ); extern int com_top( char *arg ); - +extern int com_server( char *arg ); #ifdef __cplusplus } diff --git a/src/d_bus.c b/src/d_bus.c new file mode 100644 index 0000000..76a84fc --- /dev/null +++ b/src/d_bus.c @@ -0,0 +1,129 @@ + +#include +#include +#include +#include + +#include + +#include "utils.h" +#include "d_bus_variant.h" +#include "d_bus.h" + + +int dbus_set_property_string(const string_quadruple_t* path, const char* value) +{ + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + _cleanup_bus_unref_ sd_bus *bus = NULL; + + int r; + + /* Connect to the system bus */ + r = sd_bus_open_system(&bus); + if (r >= 0) + { + + r = sd_bus_set_property( + bus, + path->first, + path->second, + path->third, + path->fourth, + &error, + "s", + value); + + } + if (r < 0) + { + fprintf(stderr, "Failed to issue dbus call: %d %s\n", r, error.message); + } + + return (r>0?(0):(r)); +} + +int dbus_set_property(const string_quadruple_t* path, dbus_value_variant_t value) +{ + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + _cleanup_bus_unref_ sd_bus *bus = NULL; + + int r; + + /* Connect to the system bus */ + r = sd_bus_open_system(&bus); + if (r >= 0) + { + + if(strcmp(value.type, "s") ==0 ) + { + + r = sd_bus_set_property( + bus, + path->first, + path->second, + path->third, + path->fourth, + &error, + value.type, + value.string); + } + else if(strcmp(value.type, "b") ==0 ) + { + + r = sd_bus_set_property( + bus, + path->first, + path->second, + path->third, + path->fourth, + &error, + value.type, + value.boolean); + } + else { + fprintf(stderr, "Failed to find type: %s\n", value.type); + return -EOPNOTSUPP; + } + } + if (r < 0) + { + fprintf(stderr, "Failed to issue dbus call: %d %s\n", r, error.message); + } + + return (r>0?(0):(r)); +} + + +char* dbus_get_property_string(const string_quadruple_t* path ) +{ + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + _cleanup_bus_unref_ sd_bus *bus = NULL; + char *state = NULL; + int r; + + /* Connect to the system bus */ + r = sd_bus_open_system(&bus); + if (r >= 0) + { + + r = sd_bus_get_property_string( + bus, + path->first, + path->second, + path->third, + path->fourth, + &error, + &state); + /* Issue the method call and store the respons message in m */ + } + if (r < 0) + { + fprintf(stderr, "Failed to issue dbus call: %d %s\n", r, error.message); + } + + return (r>=0?(state):(NULL)); +} + diff --git a/src/d_bus.h b/src/d_bus.h new file mode 100644 index 0000000..e6be821 --- /dev/null +++ b/src/d_bus.h @@ -0,0 +1,40 @@ +#ifndef __SD_BUS_COMMANDS_H +#define __SD_BUS_COMMANDS_H + +#include "d_bus_variant.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp) +#define _cleanup_bus_close_unref_ _cleanup_(sd_bus_close_unrefp) +#define _cleanup_bus_slot_unref_ _cleanup_(sd_bus_slot_unrefp) +#define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp) +#define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp) +#define _cleanup_bus_track_unref_ _cleanup_(sd_bus_slot_unrefp) +#define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free) + + +typedef struct +{ const char* first; + const char* second; +}string_pair_t; + +typedef struct +{ const char* first; + const char* second; + const char* third; + const char* fourth; +}string_quadruple_t; + +int cmd_get_string(); + +int dbus_set_property_string(const string_quadruple_t* path, const char* value); +char* dbus_get_property_string(const string_quadruple_t* path ); +int dbus_set_property(const string_quadruple_t* path, dbus_value_variant_t value); +#ifdef __cplusplus +} +#endif + +#endif //__SD_BUS_COMMANDS_H diff --git a/src/d_bus_commands.c b/src/d_bus_commands.c new file mode 100644 index 0000000..8ae2351 --- /dev/null +++ b/src/d_bus_commands.c @@ -0,0 +1,102 @@ +#include +#include +#include + +#include "d_bus_commands.h" +#include + +void print_command_help(const universal_command_t* cmds) +{ + printf("Power commands list: \n"); + for(const universal_command_t* current=cmds;current->name!=NULL;current++) + { + printf("\t %s - %s \n", current->name, current->help); + } +} + +int parse_command2enum(const char* command, const universal_command_t* cmds) +{ + int result = COMMAND_UNKNOWN; + for(const universal_command_t* current=cmds;current->name!=NULL;current++) + { + if(strcmp(command, current->name)==0) + result = current->command; + } + return result; +} + +const universal_command_t* get_command_by_enum(int cmd, const universal_command_t* cmds) +{ + for(const universal_command_t* cur_cmd = cmds; cur_cmd->name != NULL; cur_cmd++) + { + if(cur_cmd->command == cmd) + return cur_cmd; + } + return NULL; +} + +const string_quadruple_t* get_dbus_command_interface(int cmd, const command_dbus_path_t* pathes) +{ + for(const command_dbus_path_t* current = pathes; current->path!=NULL; current++) + { + if(current->command == cmd)return current->path; + } + return NULL; +} + + +const dbus_value_variant_t* get_dbus_command_member(int cmd, const command_dbus_member_t* values) +{ + for(const command_dbus_member_t* current = values; current->member.type != NULL; current++) + { + if(current->command == cmd)return &(current->member); + } + return NULL; +} + + +const char* get_dbus_command_member_string(int cmd, const command_dbus_member_t* values) +{ + for(const command_dbus_member_t* current = values; current->member.type != NULL; current++) + { + if(current->command == cmd)return dbus_variant_get_string(&(current->member)); + } + return NULL; +} + +const dbus_value_variant_t* get_dbus_command_member_variant(int cmd, const command_dbus_member_t* values) +{ + for(const command_dbus_member_t* current = values; current->member.type != NULL; current++) + { + if(current->command == cmd)return &(current->member); + } + return NULL; +} + +const command_dbus_member_t* get_dbus_command_by_member(const char* member, const command_dbus_member_t* values) +{ + for(const command_dbus_member_t* current = values; current->member.type != NULL; current++) + { + + if(strcmp(member, dbus_variant_get_string(¤t->member)) == 0 )return current; + } + return NULL; +} + +int com_dbus_property( char *arg, const universal_command_t* commands, const command_dbus_path_t* paths, const command_dbus_member_t* values) +{ + int cmd = parse_command2enum(arg, commands); + if(cmd==COMMAND_UNKNOWN) { + fprintf(stderr, "Unknown command: %s\n", arg); + print_command_help(commands); + return -EOPNOTSUPP; + } + const string_quadruple_t* dbus_power_interface = get_dbus_command_interface(cmd, paths); + if(!dbus_power_interface) + return -EOPNOTSUPP; + const dbus_value_variant_t* property_val = get_dbus_command_member_variant(cmd, values); + if(!property_val) + return -EOPNOTSUPP; + return dbus_set_property(dbus_power_interface, *property_val); + return 0; +} diff --git a/src/d_bus_commands.h b/src/d_bus_commands.h new file mode 100644 index 0000000..51ad2fe --- /dev/null +++ b/src/d_bus_commands.h @@ -0,0 +1,48 @@ +#ifndef D_BUS_COMMANDS_H +#define D_BUS_COMMANDS_H + +#include + +#include "d_bus.h" +#include "d_bus_variant.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define COMMAND_UNKNOWN -1 +typedef struct +{ + int command; + const string_quadruple_t * path; +}command_dbus_path_t; + + + +typedef struct +{ + int command; + dbus_value_variant_t member; +}command_dbus_member_t; + +typedef struct +{ + const char* name; + int command; + const char* help; +}universal_command_t; + +int parse_command2enum(const char* command, const universal_command_t* cmds); +const string_quadruple_t* get_dbus_command_interface(int cmd, const command_dbus_path_t* pathes); +const char* get_dbus_command_member_string(int cmd, const command_dbus_member_t* values); +const dbus_value_variant_t* get_dbus_command_member(int cmd, const command_dbus_member_t* values); +int com_dbus_property( char *arg, const universal_command_t* commands, const command_dbus_path_t* paths, const command_dbus_member_t* values); +void print_command_help(const universal_command_t* cmds); +const command_dbus_member_t* get_dbus_command_by_member(const char* member, const command_dbus_member_t* values); +const universal_command_t* get_command_by_enum(int cmd, const universal_command_t* cmds); + +#ifdef __cplusplus +} +#endif + +#endif // D_BUS_COMMANDS_H diff --git a/src/d_bus_variant.c b/src/d_bus_variant.c new file mode 100644 index 0000000..6218a49 --- /dev/null +++ b/src/d_bus_variant.c @@ -0,0 +1,10 @@ +#include +#include + +#include "d_bus_variant.h" + +const char* dbus_variant_get_string(const dbus_value_variant_t* val) +{ + if(strcmp(val->type, "s"))return NULL; + return val->string; +} diff --git a/src/d_bus_variant.h b/src/d_bus_variant.h new file mode 100644 index 0000000..e4f261b --- /dev/null +++ b/src/d_bus_variant.h @@ -0,0 +1,20 @@ +#ifndef D_BUS_VARIANT_H +#define D_BUS_VARIANT_H + +#include + +typedef struct +{ + //dbus coded type letter + const char* type; + union + { + const char* string; + int integer; + bool boolean; + }; +}dbus_value_variant_t; + +const char* dbus_variant_get_string(const dbus_value_variant_t* val); + +#endif // D_BUS_VARIANT_H diff --git a/src/host_commands.c b/src/host_commands.c new file mode 100644 index 0000000..d832ef8 --- /dev/null +++ b/src/host_commands.c @@ -0,0 +1,101 @@ +#include +#include + +#include "host_commands.h" + +static const string_quadruple_t boot_override_type_dbus = { + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/boot", + "xyz.openbmc_project.Control.Boot.Type", + "BootType"}; + +static const string_quadruple_t boot_override_mode_dbus = { + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/boot", + "xyz.openbmc_project.Control.Boot.Mode", + "BootMode"}; + +static const string_quadruple_t boot_override_source_dbus = { + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/boot", + "xyz.openbmc_project.Control.Boot.Source", + "BootSource"}; + +static const string_quadruple_t boot_override_enable_dbus = { + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/boot", + "xyz.openbmc_project.Object.Enable", + "Enabled"}; + +static const string_quadruple_t boot_override_once_dbus = { + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/boot/one_time", + "xyz.openbmc_project.Object.Enable", + "Enabled"}; + +typedef enum +{ + HOST_UNKNOWN=-1, + HOST_CD, + HOST_USB, + HOST_BOOT_OVERRIDE, + HOST_BOOT_NO_OVERRIDE, + HOST_BOOT_REGULAR, + HOST_BOOT_BIOS, + HOST_BOOT_SAFE, + HOST_ONE_TIME, + HOST_CONTINOUS, + HOST_LEGACY, + HOST_UEFI +}host_command_t; + +static universal_command_t host_commands[] = { + { "cd", HOST_CD, "Boot from virtual CD-ROM"}, + { "usb", HOST_USB, "Boot from virtual USB drive"}, + { "override", HOST_BOOT_OVERRIDE, "Override host chosen boot options"}, + { "no-override", HOST_BOOT_NO_OVERRIDE, "Don't override host chosen boot options"}, + { "regular", HOST_BOOT_REGULAR, "Regular boot type"}, + { "bios", HOST_BOOT_BIOS, "Boot into BIOS"}, + { "safe", HOST_BOOT_SAFE, "Boot in safe mode"}, + { "override-once", HOST_ONE_TIME, "Override only next boot"}, + { "override-always", HOST_CONTINOUS, "Override always"}, + { "legacy", HOST_LEGACY, "Legacy type boot"}, + { "uefi", HOST_UEFI, "UEFI boot"}, + { NULL, 0, NULL } +}; + +static const command_dbus_path_t host_command_paths[] = { + { HOST_CD, &boot_override_source_dbus }, + { HOST_USB, &boot_override_source_dbus }, + { HOST_BOOT_OVERRIDE, &boot_override_enable_dbus }, + { HOST_BOOT_NO_OVERRIDE, &boot_override_enable_dbus }, + { HOST_BOOT_REGULAR, &boot_override_mode_dbus }, + { HOST_BOOT_BIOS, &boot_override_mode_dbus }, + { HOST_BOOT_SAFE, &boot_override_mode_dbus }, + { HOST_ONE_TIME, &boot_override_once_dbus }, + { HOST_CONTINOUS, &boot_override_once_dbus }, + { HOST_LEGACY, &boot_override_type_dbus }, + { HOST_UEFI, &boot_override_type_dbus }, + { 0, NULL } +}; + +static const command_dbus_member_t host_command_values[] = { + { HOST_CD, { .type="s", .string="xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia"}}, + { HOST_USB, { .type="s", .string="xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia"}}, + { HOST_BOOT_OVERRIDE, { .type="b", .boolean=true}}, + { HOST_BOOT_NO_OVERRIDE, { .type="b", .boolean=false}}, + { HOST_BOOT_REGULAR, { .type="s", .string="xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"}}, + { HOST_BOOT_BIOS, { .type="s", .string="xyz.openbmc_project.Control.Boot.Mode.Modes.Setup"}}, + { HOST_BOOT_SAFE,{ .type="s", .string="xyz.openbmc_project.Control.Boot.Mode.Modes.Safe"}}, + { HOST_ONE_TIME, { .type="b", .boolean=true}}, + { HOST_CONTINOUS, { .type="b", .boolean=false}}, + { HOST_LEGACY, { .type="s", .string="xyz.openbmc_project.Control.Boot.Type.Types.Legacy"} }, + { HOST_UEFI, { .type="s", .string="xyz.openbmc_project.Control.Boot.Type.Types.EFI"} }, + { 0, {.type=NULL, .integer=0}} +}; + +int com_boot( char *arg ) +{ + //if(strcmp(arg, "status")==0)return power_status(); + return com_dbus_property(arg, host_commands, host_command_paths, host_command_values); +} diff --git a/src/host_commands.h b/src/host_commands.h new file mode 100644 index 0000000..daafda4 --- /dev/null +++ b/src/host_commands.h @@ -0,0 +1,8 @@ +#ifndef HOST_COMMANDS_H +#define HOST_COMMANDS_H + +#include "d_bus_commands.h" + +int com_boot( char *arg ); + +#endif // HOST_COMMANDS_H diff --git a/src/main.c b/src/main.c index e186215..bef33f5 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,9 @@ #include #include +#include +#include + char *progname; /* The name of this program, as taken from argv[0]. */ int done; /* When non-zero, this global means the user is done using this program. */ @@ -31,15 +34,18 @@ static sigset_t blockmask; COMMAND top_admin_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, + { "server", com_server, "Server commands" }, { "shell", com_shell, "Activate submenu shell" }, { "users", com_users, "Activate submenu users" }, { "quit", com_quit, "Quit using SILA Shell" }, + { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } }; COMMAND top_operator_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, + { "server", com_server, "Server commands" }, { "shell", com_shell, "Activate submenu shell" }, { "users", com_users, "Activate submenu users" }, { "quit", com_quit, "Quit using SILA Shell" }, @@ -49,6 +55,7 @@ COMMAND top_operator_list[] = { COMMAND top_user_list[] = { { "help", com_help, "Display this text" }, { "?", com_help, "Synonym for `help'" }, + { "server", com_server, "Server commands" }, { "shell", com_shell, "Activate submenu shell" }, { "users", com_users, "Activate submenu users" }, { "quit", com_quit, "Quit using SILA Shell" }, @@ -151,6 +158,42 @@ COMMAND users_user_list[] = { COMMAND_LIST users; +COMMAND server_admin_list[] = { + { "help", com_help, "Display this text" }, + { "?", com_help, "Synonym for `help'" }, + { "power", com_power, "Return to top menu" }, + { "restore-policy", com_power_policy, "Set power restore policy" }, + { "boot", com_boot, "Set host boot options" }, + { "..", com_top, "Return to top menu" }, + { "quit", com_quit, "Quit using SILA Shell" }, + { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } +}; + +COMMAND server_operator_list[] = { + { "help", com_help, "Display this text" }, + { "?", com_help, "Synonym for `help'" }, + { "power", com_power, "Run on/off/reset" }, + { "restore-policy", com_power_policy, "Set power restore policy" }, + { "boot", com_boot, "Set host boot options" }, + { "..", com_top, "Return to top menu" }, + { "quit", com_quit, "Quit using SILA Shell" }, + { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } +}; + +COMMAND server_user_list[] = { + { "help", com_help, "Display this text" }, + { "?", com_help, "Synonym for `help'" }, + { "power", com_power, "Return to top menu" }, + { "restore-policy", com_power_policy, "Set power restore policy" }, + { "boot", com_boot, "Set host boot options" }, + { "..", com_top, "Return to top menu" }, + { "quit", com_quit, "Quit using SILA Shell" }, + { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } +}; + + +COMMAND_LIST server = {"server", NULL}; + COMMAND_LIST *current; @@ -235,24 +278,28 @@ void cmd_lists_init( gid_t gid ) top.name = "top"; shell.name = "shell"; users.name = "users"; + server.name = "server"; if( privileges == ADMIN || gid == 0 ) { top.list = &top_admin_list[0]; shell.list = &shell_admin_list[0]; users.list = &users_admin_list[0]; + server.list = &server_admin_list[0]; } else if( privileges == OPERATOR ) { top.list = &top_operator_list[0]; shell.list = &shell_operator_list[0]; users.list = &users_operator_list[0]; + server.list = &server_operator_list[0]; } else { top.list = &top_user_list[0]; shell.list = &shell_user_list[0]; users.list = &users_user_list[0]; + server.list = &server_user_list[0]; } current = ⊤ diff --git a/src/power_commands.c b/src/power_commands.c new file mode 100644 index 0000000..e91b31d --- /dev/null +++ b/src/power_commands.c @@ -0,0 +1,179 @@ +#include +#include +#include + +#include "utils.h" + +#include "d_bus_commands.h" +#include "power_commands.h" + +static const string_quadruple_t chassis_dbus = { + "xyz.openbmc_project.State.Chassis", + "/xyz/openbmc_project/state/chassis0", + "xyz.openbmc_project.State.Chassis", + "RequestedPowerTransition"}; + +static const string_quadruple_t host_dbus = { + "xyz.openbmc_project.State.Host", + "/xyz/openbmc_project/state/host0", + "xyz.openbmc_project.State.Host", + "RequestedHostTransition"}; + +static const string_quadruple_t policy_dbus = { + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/power_restore_policy", + "xyz.openbmc_project.Control.Power.RestorePolicy", + "PowerRestorePolicy"}; + + +typedef enum +{ + POWER_UNKNOWN=-1, + POWER_ON_GRACEFUL=100, + POWER_ON_FORCE, + POWER_OFF_GRACEFUL, + POWER_OFF_FORCE, + POWER_RESET_GRACEFUL, + POWER_RESET_FORCE +}power_command_t; + +static const command_dbus_path_t power_command_paths[] = { + { POWER_ON_GRACEFUL, &host_dbus }, + { POWER_ON_FORCE, &host_dbus }, + { POWER_OFF_GRACEFUL, &host_dbus }, + { POWER_OFF_FORCE, &chassis_dbus }, + { POWER_RESET_GRACEFUL, &host_dbus }, + { POWER_RESET_FORCE, &host_dbus }, + { 0, NULL } +}; + +static const command_dbus_member_t power_command_values[] = { + { POWER_ON_GRACEFUL, {.type="s", .string="xyz.openbmc_project.State.Host.Transition.On" }}, + { POWER_ON_FORCE, {.type="s", .string="xyz.openbmc_project.State.Host.Transition.On" }}, + { POWER_OFF_GRACEFUL, {.type="s", .string="xyz.openbmc_project.State.Host.Transition.Off" }}, + { POWER_OFF_FORCE, {.type="s", .string="xyz.openbmc_project.State.Chassis.Transition.Off" }}, + { POWER_RESET_GRACEFUL, {.type="s", .string="xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot" }}, + { POWER_RESET_FORCE, {.type="s", .string="xyz.openbmc_project.State.Host.Transition.ForceWarmReboot" }}, + { 0, {.type=NULL, .integer=0}} +}; + +typedef enum +{ + POWER_POLICY_UNKNOWN=-1, + POWER_POLICY_ON=100, + POWER_POLICY_OFF, + POWER_POLICY_RESTORE + +}power_policy_command_t; + + +static universal_command_t power_commands[] = { + { "on-graceful", POWER_ON_GRACEFUL, "Graceful Power On" }, + { "on", POWER_ON_GRACEFUL, "Graceful Power On" }, + { "on-force", POWER_ON_FORCE, "Force Power On" }, + { "off-graceful", POWER_OFF_GRACEFUL, "Graceful Power Off" }, + { "off", POWER_OFF_GRACEFUL, "Graceful Power Off" }, + { "off-force", POWER_OFF_FORCE, "Force Power Off" }, + { "reset-graceful", POWER_RESET_GRACEFUL, "Graceful Reset" }, + { "reset", POWER_RESET_GRACEFUL, "Graceful Reset" }, + { "reset-force", POWER_RESET_FORCE, "Force Reset" }, + { NULL, 0, NULL } +}; + +static const universal_command_t power_policy_commands[] = { + {"always-on", POWER_POLICY_ON, "Server is always ON"}, + {"always-off", POWER_POLICY_OFF, "Server is always ON"}, + {"restore", POWER_POLICY_RESTORE, "Server restores previous state"}, + { NULL, 0, NULL } +}; + +static const command_dbus_path_t power_command_policy_paths[] = { + { POWER_POLICY_ON, &policy_dbus }, + { POWER_POLICY_OFF, &policy_dbus }, + { POWER_POLICY_RESTORE, &policy_dbus }, + { 0, NULL } +}; + +static const command_dbus_member_t power_command_policy_values[] = { + { POWER_POLICY_ON, {.type="s", .string="xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn" }}, + { POWER_POLICY_OFF, {.type="s", .string="xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff" }}, + { POWER_POLICY_RESTORE, {.type="s", .string="xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore" }}, + { 0, {.type=NULL, .integer=0 }} +}; + +int com_status(const universal_command_t *commands, const command_dbus_path_t * paths, const command_dbus_member_t * values) +{ + for(const command_dbus_path_t * cur_path = paths;cur_path->path !=NULL; cur_path++) + { + _cleanup_string_ char * value = dbus_get_property_string(cur_path->path); + if(!value)continue; + const command_dbus_member_t* member = get_dbus_command_by_member(value, values); + if(!member)continue; + const universal_command_t* cur_cmd = get_command_by_enum(member->command, commands); + if(!cur_cmd) + continue; + printf("Current status: %s - %s\n", cur_cmd->name, cur_cmd->help); + + } + return 0; +} + +static int power_status() +{ + + _cleanup_string_ char * host_value = dbus_get_property_string(&host_dbus); + if(!host_value) + return -EOPNOTSUPP; + const command_dbus_member_t* member = get_dbus_command_by_member(host_value, power_command_values); + if(!member) + return -EOPNOTSUPP; + const universal_command_t* cur_cmd = get_command_by_enum(member->command, power_commands); + if(!cur_cmd) + return -EOPNOTSUPP; + printf("Power status: \n"); + printf("\tHost: %s - %s\n", cur_cmd->name, cur_cmd->help); + _cleanup_string_ char * chassis_value = dbus_get_property_string(&chassis_dbus); + if(!host_value) + return -EOPNOTSUPP; + member = get_dbus_command_by_member(host_value, power_command_values); + if(!member) + return -EOPNOTSUPP; + cur_cmd = get_command_by_enum(member->command, power_commands); + if(!cur_cmd) + return -EOPNOTSUPP; + + printf("\tChassis: %s - %s\n", cur_cmd->name, cur_cmd->help); + + + return 0; +} + +static int power_policy_status() +{ + + _cleanup_string_ char * host_value = dbus_get_property_string(&host_dbus); + if(!host_value) + return -EOPNOTSUPP; + const command_dbus_member_t* member = get_dbus_command_by_member(host_value, power_command_values); + if(!member) + return -EOPNOTSUPP; + const universal_command_t* cur_cmd = get_command_by_enum(member->command, power_commands); + if(!cur_cmd) + return -EOPNOTSUPP; + printf("Power policy tatus: \n"); + printf("\tHost: %s - %s\n", cur_cmd->name, cur_cmd->help); + + return 0; +} + +int com_power( char *arg ) +{ + if(strcmp(arg, "status")==0)return power_status(); + return com_dbus_property(arg, power_commands, power_command_paths, power_command_values); +} + +int com_power_policy( char* arg ) +{ + if(strcmp(arg, "status")==0)return power_policy_status(); + return com_dbus_property(arg, power_policy_commands, power_command_policy_paths, power_command_policy_values); +} diff --git a/src/power_commands.h b/src/power_commands.h new file mode 100644 index 0000000..da5d979 --- /dev/null +++ b/src/power_commands.h @@ -0,0 +1,19 @@ +#ifndef POWER_H +#define POWER_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +int com_power( char *arg ); +int com_power_policy( char* arg ); + + +#ifdef __cplusplus +} +#endif + + +#endif // POWER_H diff --git a/src/shell.c b/src/shell.c index af5d649..94ad78c 100644 --- a/src/shell.c +++ b/src/shell.c @@ -21,7 +21,6 @@ #include #include - /* **************************************************************** */ /* */ /* SILA Shell Commands */ @@ -94,7 +93,7 @@ int com_stat( char *arg ) finfo.st_nlink, (finfo.st_nlink == 1) ? "" : "s", finfo.st_size, - (finfo.st_size == 1) ? "" : "s"); + (finfo.st_size == 1) ? "" : "s#include "); printf( "Inode Last Change at: %s", ctime( &finfo.st_ctime ) ); printf( " Last access at: %s", ctime( &finfo.st_atime ) ); printf( " Last modified at: %s", ctime( &finfo.st_mtime ) ); diff --git a/src/utils.h b/src/utils.h index e56fe14..32d8b4b 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,6 +2,8 @@ #ifndef __UTILS_H #define __UTILS_H +#include +#include #ifdef __cplusplus extern "C" { @@ -9,12 +11,33 @@ extern "C" { #define MAX_ERROR_MSG_SIZE PATH_MAX - extern void *xmalloc( size_t ); extern void *xrealloc( void *, size_t ); extern char *dupstr( char *s ); +static inline void freep(void **p) +{ + if (*p) + free(*p); +} + +static inline void string_freep(char **p) +{ + if (*p) + free(*p); +} + +#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \ + static inline void func##p(type *p) \ + { \ + if (*p) \ + *p = func(*p); \ + } + +#define _cleanup_(_some_) __attribute__((__cleanup__(_some_))) +#define _cleanup_free_ _cleanup_(freep) +#define _cleanup_string_ _cleanup_(string_freep) #ifdef __cplusplus } -- cgit v1.2.3