Revert "Revert "Add the appcmd protocol for product extended routine.""
[sdk/target/sdbd.git] / src / services.c
index 739e36f..5d40ce9 100644 (file)
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include <stdlib.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
@@ -24,6 +24,8 @@
 #include "sysdeps.h"
 
 #define  TRACE_TAG  TRACE_SERVICES
+#include "log.h"
+
 #include "sdb.h"
 #include "file_sync_service.h"
 
@@ -49,6 +51,9 @@
 #include <termios.h>
 #include <sys/ioctl.h>
 
+#include "sdbd_plugin.h"
+#include "plugin.h"
+
 typedef struct stinfo stinfo;
 
 struct stinfo {
@@ -57,7 +62,6 @@ struct stinfo {
     void *cookie;
 };
 
-
 void *service_bootstrap_func(void *x)
 {
     stinfo *sti = x;
@@ -90,7 +94,7 @@ static void dns_service(int fd, void *cookie)
 
 static int is_support_interactive_shell()
 {
-    return (!strncmp(g_capabilities.intershell_support, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED)));
+    return (!strncmp(g_capabilities.intershell_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
 }
 
 #if 0
@@ -175,7 +179,7 @@ void restart_tcp_service(int fd, void *cookie)
 
 static int is_support_rootonoff()
 {
-    return (!strncmp(g_capabilities.rootonoff_support, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED)));
+    return (!strncmp(g_capabilities.rootonoff_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
 }
 
 void rootshell_service(int fd, void *cookie)
@@ -186,7 +190,7 @@ void rootshell_service(int fd, void *cookie)
     if (!strcmp(mode, "on")) {
         if (getuid() == 0) {
             if (rootshell_mode == 1) {
-                //snprintf(buf, sizeof(buf), "Already changed to developer mode\n");
+                //snprintf(buf, sizeof(buf), "Already changed to sdk user mode\n");
                 // do not show message
             } else {
                 if (is_support_rootonoff()) {
@@ -207,18 +211,47 @@ void rootshell_service(int fd, void *cookie)
     } else if (!strcmp(mode, "off")) {
         if (rootshell_mode == 1) {
             rootshell_mode = 0;
-            snprintf(buf, sizeof(buf), "Switched to 'developer' account mode\n");
+            snprintf(buf, sizeof(buf), "Switched to 'sdk user' account mode\n");
             writex(fd, buf, strlen(buf));
         }
     } else {
        snprintf(buf, sizeof(buf), "Unknown command option : %s\n", mode);
         writex(fd, buf, strlen(buf));
     }
-    D("set rootshell to %s\n", rootshell_mode == 1 ? "root" : "developer");
+    D("set rootshell to %s\n", rootshell_mode == 1 ? "root" : SDK_USER_NAME);
     free(mode);
     sdb_close(fd);
 }
 
+enum tzplatform_get_env_error_status {
+    NO_ERROR_TZPLATFORM_ENV = 0,
+    ERROR_TZPLATFORM_ENV_GENERAL = 1,
+    ERROR_TZPLATFORM_ENV_INVALID_VARIABLES = 2,
+};
+
+void get_tzplatform_env(int fd, void *cookie) {
+    char buf[PATH_MAX] = { 0, };
+    char *env_name = (char*) cookie;
+    D("environment variable name: %s\n", env_name);
+    enum tzplatform_variable env_id = tzplatform_getid(env_name);
+    if (env_id != _TZPLATFORM_VARIABLES_INVALID_) {
+        const char *env_value = tzplatform_getenv(env_id);
+        if (env_value) {
+            D("environment value : %s\n", env_value);
+            snprintf(buf, sizeof(buf), "%d%s", NO_ERROR_TZPLATFORM_ENV, env_value);
+        } else {
+            D("failed to get environment value using tzplatform_getenv");
+            snprintf(buf, sizeof(buf), "%d", ERROR_TZPLATFORM_ENV_GENERAL);
+        }
+    } else {
+        D("environment name (%s) is invalid\n", env_name);
+        snprintf(buf, sizeof(buf), "%d", ERROR_TZPLATFORM_ENV_INVALID_VARIABLES);
+    }
+    writex(fd, buf, strlen(buf));
+    free(env_name);
+    sdb_close(fd);
+}
+
 void restart_usb_service(int fd, void *cookie)
 {
     char buf[100];
@@ -264,7 +297,7 @@ void reboot_service(int fd, void *arg)
 #if !SDB_HOST
 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
 #define BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )
-#define CS_PATH     tzplatform_mkpath(TZ_USER_SHARE,"crash/report")
+#define CS_PATH     tzplatform_getenv(TZ_SYS_CRASH)
 
 void inoti_service(int fd, void *arg)
 {
@@ -277,10 +310,17 @@ void inoti_service(int fd, void *arg)
 
     if ( ifd < 0 ) {
         D( "inotify_init failed\n");
+        sdb_close(fd);
         return;
     }
 
     wd = inotify_add_watch( ifd, CS_PATH, IN_CREATE);
+    if ( wd < 0 ) {
+        D("inotify_add_watch failed (errno :%d)\n", errno);
+        sdb_close(ifd);
+        sdb_close(fd);
+        return;
+    }
 
     for ( ; ; ) {
         int length, i = 0;
@@ -387,7 +427,7 @@ static int create_service_thread(void (*func)(int, void *), void *cookie)
 
 #if !SDB_HOST
 
-static void redirect_and_exec(int pts, const char *cmd, const char *argv[], const char *envp[])
+static void redirect_and_exec(int pts, const char *cmd, char * const argv[], char * const envp[])
 {
     dup2(pts, 0);
     dup2(pts, 1);
@@ -398,7 +438,7 @@ static void redirect_and_exec(int pts, const char *cmd, const char *argv[], cons
     execve(cmd, argv, envp);
 }
 
-static int create_subprocess(const char *cmd, pid_t *pid, const char *argv[], const char *envp[])
+int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * const envp[])
 {
     char devname[64];
     int ptm;
@@ -455,11 +495,14 @@ static int create_subprocess(const char *cmd, pid_t *pid, const char *argv[], co
         }
 
         if (should_drop_privileges()) {
-            if (argv[2] != NULL && getuid() == 0 && request_plugin_verification(SDBD_CMD_VERIFY_ROOTCMD, argv[2])) {
+            if (argv[2] != NULL && getuid() == 0 && request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_ROOTCMD, argv[2])) {
                 // do nothing
                 D("sdb: executes root commands!!:%s\n", argv[2]);
             } else {
-                set_developer_privileges();
+                if (getuid() != g_sdk_user_id && set_sdk_user_privileges() < 0) {
+                    fprintf(stderr, "failed to set SDK user privileges\n");
+                    exit(-1);
+                }
             }
         }
         redirect_and_exec(pts, cmd, argv, envp);
@@ -476,9 +519,7 @@ static int create_subprocess(const char *cmd, pid_t *pid, const char *argv[], co
 }
 #endif  /* !SDB_HOST */
 
-#define SHELL_COMMAND "/bin/sh"
 #define LOGIN_COMMAND "/bin/login"
-#define SDK_USER      "developer"
 #define SUPER_USER    "root"
 #define LOGIN_CONFIG  "/etc/login.defs"
 
@@ -514,11 +555,10 @@ static void subproc_waiter_service(int fd, void *cookie)
     }
 }
 
-static void get_env(char *key, char **env)
+void get_env(char *key, char **env)
 {
     FILE *fp;
     char buf[1024];
-    int i;
     char *s, *e, *value;
 
     fp = fopen (LOGIN_CONFIG, "r");
@@ -531,7 +571,7 @@ static void get_env(char *key, char **env)
         e = buf + (strlen(buf) - 1);
 
         // trim string
-        while(*e == ' ' ||  *e == '\n' || *e == '\t') {
+        while( (e > s) && (*e == ' ' ||  *e == '\n' || *e == '\t')) {
             e--;
         }
         *(e+1) ='\0';
@@ -565,28 +605,29 @@ static int create_subproc_thread(const char *name, int lines, int columns)
     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));
 
-    char *envp[] = {
-        "TERM=linux", /* without this, some programs based on screen can't work, e.g. top */
-        "DISPLAY=:0", /* without this, some programs based on without launchpad can't work */
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL
-    };
+    envp[envp_cnt++] = strdup("TERM=linux");
+    envp[envp_cnt++] = strdup("DISPLAY=:0");
 
     if (should_drop_privileges()) {
-         envp[2] = "HOME=/home/developer";
-         get_env("ENV_PATH", &value);
-     } else {
-         get_env("ENV_SUPATH", &value);
-         if(value == NULL) {
-             get_env("ENV_ROOTPATH", &value);
-         }
-         envp[2] = "HOME=/root";
-     }
+        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) {
@@ -596,19 +637,39 @@ static int create_subproc_thread(const char *name, int lines, int columns)
             } else {
                 snprintf(path, sizeof(path), "%s", trim_value);
             }
-            envp[3] = path;
+            envp[envp_cnt++] = strdup(path);
         } else {
             snprintf(path, sizeof(path), "%s", value);
-            envp[3] = path;
+            envp[envp_cnt++] = strdup(path);
         }
         free(value);
     }
 
-    D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]);
+    /* get environment variables from plugin */
+    char *envp_plugin = NULL;
+    envp_plugin = malloc(SDBD_PLUGIN_OUTBUF_MAX);
+    if (envp_plugin == NULL) {
+        D("Cannot allocate the shell commnad buffer.");
+        return -1;
+    }
+    memset(envp_plugin, 0, SDBD_PLUGIN_OUTBUF_MAX);
+    if (!request_plugin_cmd(SDBD_CMD_SHELL_ENVVAR, "", envp_plugin, SDBD_PLUGIN_OUTBUF_MAX)) {
+        D("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_plugin_verification(SDBD_CMD_VERIFY_SHELLCMD, name)) {
+        if (!request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_SHELLCMD, name)) {
             D("This shell command is invalid. (%s)\n", name);
             return -1;
         }
@@ -622,7 +683,7 @@ static int create_subproc_thread(const char *name, int lines, int columns)
         }
 
         memset(new_cmd, 0, SDBD_SHELL_CMD_MAX);
-        if(!request_plugin_cmd(SDBD_CMD_CONV_SHELLCMD, name, new_cmd, SDBD_SHELL_CMD_MAX)) {
+        if(!request_conversion_to_plugin(PLUGIN_SYNC_CMD_CONVERT_SHELLCMD, name, new_cmd, SDBD_SHELL_CMD_MAX)) {
             D("Failed to convert the shell command. (%s)\n", name);
             free(new_cmd);
             return -1;
@@ -638,7 +699,7 @@ static int create_subproc_thread(const char *name, int lines, int columns)
         };
         args[2] = new_cmd;
 
-        ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
+        ret_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp);
         free(new_cmd);
     } else { // in case of shell interactively
         // Check the capability for interactive shell support.
@@ -647,12 +708,12 @@ static int create_subproc_thread(const char *name, int lines, int columns)
             return -1;
         }
 
-        char *args[] = {
+        char * const args[] = {
                 SHELL_COMMAND,
                 "-",
                 NULL,
         };
-        ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
+        ret_fd = create_subprocess(SHELL_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[] = {
@@ -672,6 +733,18 @@ static int create_subproc_thread(const char *name, int lines, int columns)
         }
 #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) {
@@ -745,7 +818,6 @@ static int create_sync_subprocess(void (*func)(int, void *), void* cookie) {
     if(sdb_thread_create( &t, service_bootstrap_func, sti)){
         free(sti);
         sdb_close(s[0]);
-        sdb_close(s[1]);
         printf("cannot create service monitor thread\n");
         return -1;
     }
@@ -770,7 +842,6 @@ static int create_syncproc_thread()
 
     return ret_fd;
 }
-
 #endif
 
 static void get_platforminfo(int fd, void *cookie) {
@@ -866,6 +937,10 @@ static void get_capability(int fd, void *cookie) {
     offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
                                 "sockproto_support", g_capabilities.sockproto_support);
 
+    // Window size synchronization support
+    offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
+                                "syncwinsz_support", g_capabilities.syncwinsz_support);
+
     // Root command support
     offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
                                 "rootonoff_support", g_capabilities.rootonoff_support);
@@ -882,6 +957,10 @@ static void get_capability(int fd, void *cookie) {
     offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
                                 "cpu_arch", g_capabilities.cpu_arch);
 
+    // SDK Tool path
+    offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
+                                "sdk_toolpath", g_capabilities.sdk_toolpath);
+
     // Profile name
     offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
                                 "profile_name", g_capabilities.profile_name);
@@ -890,6 +969,10 @@ static void get_capability(int fd, void *cookie) {
     offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
                                 "vendor_name", g_capabilities.vendor_name);
 
+    // Target name of the launch possible
+    offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
+                                "can_launch", g_capabilities.can_launch);
+
     // Platform version
     offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
                                 "platform_version", g_capabilities.platform_version);
@@ -906,10 +989,21 @@ static void get_capability(int fd, void *cookie) {
     offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
                                 "sdbd_plugin_version", g_capabilities.sdbd_plugin_version);
 
-    // Window size synchronization support
+    // Capability version
     offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
-                                "syncwinsz_support", g_capabilities.syncwinsz_support);
+                                "sdbd_cap_version", g_capabilities.sdbd_cap_version);
+
+    // Sdbd log enable
+    offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
+            "log_enable", g_capabilities.log_enable);
 
+    // Sdbd log path
+    offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
+            "log_path", g_capabilities.log_path);
+
+    // Application command support
+    offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
+            "appcmd_support", g_capabilities.appcmd_support);
 
     offset++; // for '\0' character
 
@@ -943,7 +1037,6 @@ static void sync_windowsize(int fd, void *cookie) {
 const unsigned COMMAND_TIMEOUT = 10000;
 void get_boot(int fd, void *cookie) {
     char buf[2] = { 0, };
-    char *mode = (char*) cookie;
     int time = 0;
     int interval = 1000;
     while (time < COMMAND_TIMEOUT) {
@@ -1069,8 +1162,14 @@ int service_to_fd(const char *name)
         }
     } else if(!strncmp(name, "shellconf:", 10)){
         if(!strncmp(name+10, "syncwinsz:", 10)){
-            ret = create_service_thread(sync_windowsize, name+20);
+            ret = create_service_thread(sync_windowsize, (void *)name+20);
         }
+    } else if(!strncmp(name, "tzplatformenv:", 14)) {
+       char* env_variable = NULL;
+       env_variable = strdup(name+14);
+       ret = create_service_thread(get_tzplatform_env, (void *)(env_variable));
+    } else if(!strncmp(name, "appcmd:", 7)){
+        ret = request_appcmd_to_plugin(name+7);
     }
 
     if (ret >= 0) {