hashtable* plugin_cmd_hashtable = NULL;
+char* extcmd = NULL;
+
typedef struct _async_parameter {
int cmd;
parameters* in;
return 1;
}
+void readxml() {
+ char * buffer = NULL;
+ long length;
+ FILE * fptr = fopen(PLUGIN_XML_PATH, "rb");
+
+ if (fptr == NULL) {
+ E("failed to open commands.xml\n");
+ return;
+ }
+
+ fseek(fptr, 0, SEEK_END);
+ length = ftell(fptr);
+ fseek(fptr, 0, SEEK_SET);
+ buffer = malloc(length);
+ if (buffer) {
+ fread(buffer, 1, length, fptr);
+ }
+ fclose(fptr);
+ if (buffer) {
+ D("command xml data: %s\n", buffer);
+ extcmd = buffer;
+ }
+}
+
void load_sdbd_plugin()
{
int ret;
D ( "using sdbd plugin interface.(%s)\n", PLUGIN_PATH );
plugin_init_proc ( plugin_event_handler, plugin_register_command );
+ readxml();
}
// use default plugin feature for the commands or events that are not supported by plugin
dlclose ( g_plugin_handle );
g_plugin_handle = NULL;
}
+
+ if (extcmd) {
+ free(extcmd);
+ extcmd = NULL;
+ }
}
// return 1 if plugin support given command
return s[0];
}
+static void *async_proc_extcmd_bootstrap_func(void *x)
+{
+ async_parameter *p = x;
+ plugin_async_proc(p->cmd, p->in, p->out_fd);
+ release_parameters(p->in);
+ free(p->in);
+ sdb_close(p->out_fd);
+ free(p);
+ return 0;
+}
+
+int create_async_extcmd_proc_thread( int cmd, parameters* in )
+{
+ async_parameter* async_param;
+ sdb_thread_t t;
+ int s[2];
+
+ if (sdb_socketpair(s)) {
+ release_parameters(in);
+ free(in);
+ E("cannot create extcmd async proc socket pair\n");
+ return -1;
+ }
+
+ async_param = (async_parameter*)malloc(sizeof(async_parameter));
+ if (async_param == NULL) {
+ release_parameters(in);
+ free(in);
+ fatal("cannot allocate async_parameter");
+ return -1;
+ }
+
+ async_param->cmd = cmd;
+ async_param->in = in;
+ async_param->out_fd = s[1];
+
+ if (sdb_thread_create(&t, async_proc_extcmd_bootstrap_func, async_param)) {
+ free(async_param);
+ sdb_close(s[0]);
+ sdb_close(s[1]);
+ release_parameters(in);
+ free(in);
+ E("cannot create extcmd async proc thread\n");
+ return -1;
+ }
+
+ D("extcmd async proc thread started, %d:%d\n",s[0], s[1]);
+ return s[0];
+}
+
// return 1 if succeed to get capability from plugin
// return 0 otherwise
int request_capability_to_plugin ( int cap, char* out_buf, unsigned int out_len )
return success;
}
+// return 1 if allowed by plugin (valid)
+// return 0 if disallowed by plugin (invalid)
+int request_extcmd_validity_to_plugin ( int cmd, const char* in_buf)
+{
+ int success = 0;
+ int ret;
+ parameters in, out;
+
+ if ( in_buf != NULL ) {
+ in.number_of_parameter = 1;
+ in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+ if (in.array_of_parameter == NULL) {
+ D("failed to allocate memory for the parameter\n");
+ return success;
+ }
+ in.array_of_parameter[0].type = type_string;
+ in.array_of_parameter[0].v_string.length = strlen ( in_buf );
+ in.array_of_parameter[0].v_string.data = strdup ( in_buf );
+ } else {
+ in.number_of_parameter = 0;
+ in.array_of_parameter = NULL;
+ }
+
+ D ("requested validity : %d, %s\n", cmd, in_buf);
+
+ out.number_of_parameter = 0;
+ out.array_of_parameter = NULL;
+ ret = plugin_sync_proc ( cmd, &in, &out );
+ if ( ret == PLUGIN_CMD_SUCCESS ) {
+ success = ( out.array_of_parameter[0].v_int32 == PLUGIN_RET_VALID ) ? 1 : 0;
+ release_parameters ( &out );
+
+ D ("request validity success : %d\n", success);
+ }
+
+ release_parameters ( &in );
+ return success;
+}
+
// return 1 if succeed to convert
// return 0 otherwise
int request_conversion_to_plugin ( int cmd, const char* in_buf, char* out_buf, unsigned int out_len )
return success;
}
+// return 1 if succeed to convert
+// return 0 otherwise
+int request_extcmd_conversion_to_plugin ( int cmd, const char* in_buf, char* out_buf, unsigned int out_len )
+{
+ int success = 0;
+ int ret;
+ parameters in, out;
+
+ if ( in_buf != NULL ) {
+ in.number_of_parameter = 1;
+ in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+ if (in.array_of_parameter == NULL) {
+ E("failed to allocate memory for the parameter\n");
+ return success;
+ }
+ in.array_of_parameter[0].type = type_string;
+ in.array_of_parameter[0].v_string.length = strlen ( in_buf );
+ in.array_of_parameter[0].v_string.data = strdup ( in_buf );
+ } else {
+ in.number_of_parameter = 0;
+ in.array_of_parameter = NULL;
+ }
+
+ out.number_of_parameter = 0;
+ out.array_of_parameter = NULL;
+
+ ret = plugin_sync_proc ( cmd, &in, &out );
+ if ( ret == PLUGIN_CMD_SUCCESS ) {
+ strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
+ out_buf[out_len - 1] = '\0';
+ success = 1;
+ release_parameters ( &out );
+ }
+
+ release_parameters ( &in );
+ return success;
+}
+
// return 1 if locked
// return 0 if unlocked
// return -1 if request failed
return ret_fd;
}
+static int create_extcmd_subproc_thread(const char *name, int lines, int columns)
+{
+ stinfo *sti;
+ sdb_thread_t t;
+ int ret_fd;
+ pid_t pid;
+ char *value = NULL;
+ char *trim_value = NULL;
+ char path[PATH_MAX];
+ char *envp[MAX_TOKENS];
+ int envp_cnt = 0;
+
+ memset(path, 0, sizeof(path));
+ memset(envp, 0, sizeof(envp));
+
+ envp[envp_cnt++] = strdup("TERM=linux");
+ envp[envp_cnt++] = strdup("DISPLAY=:0");
+
+ if (should_drop_privileges()) {
+ if (g_sdk_home_dir_env) {
+ envp[envp_cnt++] = strdup(g_sdk_home_dir_env);
+ } else {
+ envp[envp_cnt++] = strdup("HOME=/home/owner");
+ }
+ get_env("ENV_PATH", &value);
+ } else {
+ get_env("ENV_SUPATH", &value);
+ if(value == NULL) {
+ get_env("ENV_ROOTPATH", &value);
+ }
+ envp[envp_cnt++] = strdup("HOME=/root");
+ }
+ if (value != NULL) {
+ trim_value = str_trim(value);
+ if (trim_value != NULL) {
+ // if string is not including 'PATH=', append it.
+ if (strncmp(trim_value, "PATH", 4)) {
+ snprintf(path, sizeof(path), "PATH=%s", trim_value);
+ } else {
+ snprintf(path, sizeof(path), "%s", trim_value);
+ }
+ envp[envp_cnt++] = strdup(path);
+ } else {
+ snprintf(path, sizeof(path), "%s", value);
+ envp[envp_cnt++] = strdup(path);
+ }
+ free(value);
+ }
+
+ /* get environment variables from plugin */
+ char *envp_plugin = NULL;
+ envp_plugin = malloc(ENV_BUF_MAX);
+ if (envp_plugin == NULL) {
+ E("Cannot allocate the shell commnad buffer.");
+ return -1;
+ }
+ memset(envp_plugin, 0, ENV_BUF_MAX);
+ if (!request_extcmd_conversion_to_plugin(PLUGIN_SYNC_CMD_GET_SHELL_ENV, NULL,
+ envp_plugin, ENV_BUF_MAX)) {
+ E("Failed to convert the shell command. (%s)\n", name);
+ free(envp_plugin);
+ return -1;
+ } else {
+ if(envp_plugin[0] != '\0') {
+ envp_cnt = tokenize_append(envp_plugin, "\n", envp, MAX_TOKENS, envp_cnt);
+ }
+ }
+ free(envp_plugin);
+
+ /* Last element of envp must be the NULL-terminator to prevent execvp fail */
+ envp[envp_cnt] = NULL;
+
+ if(name) { // in case of shell execution directly
+ // Check the shell command validation.
+ if (!request_extcmd_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_SHELLCMD, name)) {
+ E("This extcmd command is invalid. (%s)\n", name);
+ return -1;
+ }
+
+ // Convert the shell command.
+ char *new_cmd = NULL;
+ new_cmd = malloc(SDBD_SHELL_CMD_MAX);
+ if(new_cmd == NULL) {
+ E("Cannot allocate the shell commnad buffer.");
+ return -1;
+ }
+
+ memset(new_cmd, 0, SDBD_SHELL_CMD_MAX);
+ if(!request_extcmd_conversion_to_plugin(PLUGIN_SYNC_CMD_CONVERT_SHELLCMD, name, new_cmd, SDBD_SHELL_CMD_MAX)) {
+ E("Failed to convert the shell command. (%s)\n", name);
+ free(new_cmd);
+ return -1;
+ }
+
+ D("converted cmd : %s\n", new_cmd);
+
+ char *args[] = {
+ USER_DAEMON_COMMAND,
+ "-c",
+ NULL,
+ NULL,
+ };
+ args[2] = new_cmd;
+
+ ret_fd = create_userprocess(USER_DAEMON_COMMAND, &pid, (char * const*)args, (char * const*)envp);
+ free(new_cmd);
+ } else { // in case of shell interactively
+ // Check the capability for interactive shell support.
+ if (!is_support_interactive_shell()) {
+ E("This platform dose NOT support the interactive shell\n");
+ return -1;
+ }
+
+ char * const args[] = {
+ USER_DAEMON_COMMAND,
+ "-",
+ NULL,
+ };
+ ret_fd = create_userprocess(USER_DAEMON_COMMAND, &pid, (char * const*)args, (char * const*)envp);
+#if 0 // FIXME: should call login command instead of /bin/sh
+ if (should_drop_privileges()) {
+ char *args[] = {
+ USER_DAEMON_COMMAND,
+ "-",
+ NULL,
+ };
+ ret_fd = create_userprocess(USER_DAEMON_COMMAND, &pid, args, envp);
+ } else {
+ char *args[] = {
+ LOGIN_COMMAND,
+ "-f",
+ SUPER_USER,
+ NULL,
+ };
+ ret_fd = create_subprocess(LOGIN_COMMAND, &pid, args, envp);
+ }
+#endif
+ }
+
+ /* free environment variables */
+ int i = 0;
+ if(envp_cnt > 0) {
+ for(i = 0; i < envp_cnt; i++) {
+ if(envp[i]) {
+ D("envp[%d] = %s\n", i, envp[i]);
+ free(envp[i]);
+ }
+ }
+ }
+
+ D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid);
+
+ if (ret_fd < 0) {
+ E("cannot create service thread\n");
+ return -1;
+ }
+
+ if (lines > 0 && columns > 0) {
+ D("shell size lines=%d, columns=%d\n", lines, columns);
+ struct winsize win_sz;
+ win_sz.ws_row = lines;
+ win_sz.ws_col = columns;
+
+ if (ioctl(ret_fd, TIOCSWINSZ, &win_sz) < 0) {
+ E("failed to sync window size.\n");
+ }
+ }
+
+ sti = malloc(sizeof(stinfo));
+ if(sti == 0) fatal("cannot allocate stinfo");
+ sti->func = subproc_waiter_service;
+ sti->cookie = (void*)((intptr_t)pid);
+ sti->fd = ret_fd;
+
+ if(sdb_thread_create( &t, service_bootstrap_func, sti)){
+ free(sti);
+ sdb_close(ret_fd);
+ E("cannot create service thread\n");
+ return -1;
+ }
+
+ D("service thread started, fd=%d pid=%d\n",ret_fd, pid);
+ return ret_fd;
+}
+
static void get_platforminfo(int fd, void *cookie) {
pinfo sysinfo;
sdb_close(fd);
}
+int request_extcmd_to_plugin(const char* in_buf) {
+ char full_cmd[ENV_BUF_MAX] = {0,};
+ char *tokens[MAX_TOKENS];
+ int args_cnt = tokenize(in_buf, ":", tokens, MAX_TOKENS);
+ if (args_cnt < 3) {
+ E("failed to parse extcmd.\n");
+ return 0;
+ }
+
+ char* cmd_name = tokens[0];
+ char* cmd_no = tokens[args_cnt - 2];
+ int cmd = atoi(cmd_no);
+ char* exec_type = tokens[args_cnt - 1];
+
+ strcat(full_cmd, cmd_name);
+ int i = 1;
+ for(;i < args_cnt - 2;i++) {
+ strcat(full_cmd, " ");
+ strcat(full_cmd, tokens[i]);
+ }
+ D("full extcmd: %s\n", full_cmd);
+ if (!strcmp(exec_type, "sync")) {
+ return create_extcmd_subproc_thread(full_cmd, 0, 0);
+ }
+
+ else if (!strcmp(exec_type, "async")) {
+ parameters* in;
+ int fd;
+
+ in = (parameters*) malloc(sizeof(parameters));
+ if (in == NULL) {
+ E("failed to allocate memory for the parameters\n");
+ return -1;
+ }
+
+ if (full_cmd != NULL) {
+ in->number_of_parameter = 1;
+ in->array_of_parameter = (parameter*) malloc(sizeof(parameter));
+ if (in->array_of_parameter == NULL) {
+ free(in);
+ E("failed to allocate memory for the parameter\n");
+ return -1;
+ }
+ in->array_of_parameter[0].type = type_string;
+ in->array_of_parameter[0].v_string.length = strlen(full_cmd);
+ in->array_of_parameter[0].v_string.data = strdup(full_cmd);
+ } else {
+ in->number_of_parameter = 0;
+ in->array_of_parameter = NULL;
+ }
+
+ fd = create_async_extcmd_proc_thread(cmd, in);
+
+ return fd;
+ }
+
+ return 0;
+}
+
int service_to_fd(const char *name)
{
int ret = -1;
ret = create_service_thread(handle_grantfile, (void*)name+10);
} else if(!strncmp(name, "appcmd:", 7)){
ret = request_appcmd_to_plugin(name+7);
+ } else if(!strncmp(name, "extcmd:", 7)) {
+ ret = request_extcmd_to_plugin(name+7);
}
if (ret >= 0) {