summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--meson.build10
-rw-r--r--src/commands.c10
-rw-r--r--src/commands.h4
-rw-r--r--src/d_bus.c129
-rw-r--r--src/d_bus.h40
-rw-r--r--src/d_bus_commands.c102
-rw-r--r--src/d_bus_commands.h48
-rw-r--r--src/d_bus_variant.c10
-rw-r--r--src/d_bus_variant.h20
-rw-r--r--src/host_commands.c101
-rw-r--r--src/host_commands.h8
-rw-r--r--src/main.c47
-rw-r--r--src/power_commands.c179
-rw-r--r--src/power_commands.h19
-rw-r--r--src/shell.c3
-rw-r--r--src/utils.h25
17 files changed, 753 insertions, 6 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <systemd/sd-bus.h>
+
+#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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "d_bus_commands.h"
+#include <d_bus_variant.h>
+
+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(&current->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 <stdbool.h>
+
+#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 <string.h>
+#include <stdio.h>
+
+#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 <stdbool.h>
+
+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 <stdio.h>
+#include <stdbool.h>
+
+#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 <shell.h>
#include <users.h>
+#include <power_commands.h>
+#include <host_commands.h>
+
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 = &top;
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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#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 <shell.h>
#include <users.h>
-
/* **************************************************************** */
/* */
/* 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 <systemd/sd-bus.h>");
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 <stdint.h>
+#include <stdlib.h>
#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
}