2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
26 #define TRACE_TAG TRACE_SERVICES
30 #include "file_sync_service.h"
34 # include <netinet/in.h>
36 # include <sys/ioctl.h>
39 # include <sys/inotify.h>
40 # include "sdktools.h"
45 #include <system_info.h>
46 #include <tzplatform_config.h>
47 #include <sys/smack.h>
53 #include <sys/ioctl.h>
55 #include "sdbd_plugin.h"
58 #define ENV_BUF_MAX 4096
60 typedef struct stinfo stinfo;
63 void (*func)(int fd, void *cookie);
68 void *service_bootstrap_func(void *x)
71 sti->func(sti->fd, sti->cookie);
77 SDB_MUTEX_DEFINE( dns_lock );
79 static void dns_service(int fd, void *cookie)
81 char *hostname = cookie;
85 sdb_mutex_lock(&dns_lock);
86 hp = gethostbyname(hostname);
91 writex(fd, hp->h_addr, 4);
93 sdb_mutex_unlock(&dns_lock);
98 static int is_support_interactive_shell()
100 return (!strncmp(g_capabilities.intershell_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
104 extern int recovery_mode;
106 static void recover_service(int s, void *cookie)
108 unsigned char buf[4096];
109 unsigned count = (unsigned) cookie;
112 fd = sdb_creat("/tmp/update", 0644);
119 unsigned xfer = (count > 4096) ? 4096 : count;
120 if(readx(s, buf, xfer)) break;
121 if(writex(fd, buf, xfer)) break;
126 writex(s, "OKAY", 4);
128 writex(s, "FAIL", 4);
133 fd = sdb_creat("/tmp/update.begin", 0644);
137 void restart_root_service(int fd, void *cookie)
140 char value[PROPERTY_VALUE_MAX];
143 snprintf(buf, sizeof(buf), "sdbd is already running as root\n");
144 writex(fd, buf, strlen(buf));
147 property_get("ro.debuggable", value, "");
148 if (strcmp(value, "1") != 0) {
149 snprintf(buf, sizeof(buf), "sdbd cannot run as root in production builds\n");
150 writex(fd, buf, strlen(buf));
155 property_set("service.sdb.root", "1");
156 snprintf(buf, sizeof(buf), "restarting sdbd as root\n");
157 writex(fd, buf, strlen(buf));
163 void restart_tcp_service(int fd, void *cookie)
166 char value[PROPERTY_VALUE_MAX];
167 int port = (int)cookie;
170 snprintf(buf, sizeof(buf), "invalid port\n");
171 writex(fd, buf, strlen(buf));
176 snprintf(value, sizeof(value), "%d", port);
177 property_set("service.sdb.tcp.port", value);
178 snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
179 writex(fd, buf, strlen(buf));
183 static int is_support_rootonoff()
185 return (!strncmp(g_capabilities.rootonoff_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
188 void rootshell_service(int fd, void *cookie)
191 char *mode = (char*) cookie;
193 if (!strcmp(mode, "on")) {
195 if (rootshell_mode == 1) {
196 //snprintf(buf, sizeof(buf), "Already changed to sdk user mode\n");
197 // do not show message
199 if (is_support_rootonoff()) {
201 //allows a permitted user to execute a command as the superuser
202 snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n");
204 snprintf(buf, sizeof(buf), "Permission denied\n");
206 writex(fd, buf, strlen(buf));
209 D("need root permission for root shell: %d\n", getuid());
211 snprintf(buf, sizeof(buf), "Permission denied\n");
212 writex(fd, buf, strlen(buf));
214 } else if (!strcmp(mode, "off")) {
215 if (rootshell_mode == 1) {
217 snprintf(buf, sizeof(buf), "Switched to 'sdk user' account mode\n");
218 writex(fd, buf, strlen(buf));
221 snprintf(buf, sizeof(buf), "Unknown command option : %s\n", mode);
222 writex(fd, buf, strlen(buf));
224 D("set rootshell to %s\n", rootshell_mode == 1 ? "root" : SDK_USER_NAME);
229 enum tzplatform_get_env_error_status {
230 NO_ERROR_TZPLATFORM_ENV = 0,
231 ERROR_TZPLATFORM_ENV_GENERAL = 1,
232 ERROR_TZPLATFORM_ENV_INVALID_VARIABLES = 2,
235 void get_tzplatform_env(int fd, void *cookie) {
236 char buf[PATH_MAX] = { 0, };
237 char *env_name = (char*) cookie;
238 D("environment variable name: %s\n", env_name);
239 enum tzplatform_variable env_id = tzplatform_getid(env_name);
240 if (env_id != _TZPLATFORM_VARIABLES_INVALID_) {
241 const char *env_value = tzplatform_getenv(env_id);
243 D("environment value : %s\n", env_value);
244 snprintf(buf, sizeof(buf), "%d%s", NO_ERROR_TZPLATFORM_ENV, env_value);
246 D("failed to get environment value using tzplatform_getenv");
247 snprintf(buf, sizeof(buf), "%d", ERROR_TZPLATFORM_ENV_GENERAL);
250 D("environment name (%s) is invalid\n", env_name);
251 snprintf(buf, sizeof(buf), "%d", ERROR_TZPLATFORM_ENV_INVALID_VARIABLES);
253 writex(fd, buf, strlen(buf));
258 void restart_usb_service(int fd, void *cookie)
262 property_set("service.sdb.tcp.port", "0");
263 snprintf(buf, sizeof(buf), "restarting in USB mode\n");
264 writex(fd, buf, strlen(buf));
268 void reboot_service(int fd, void *arg)
276 /* Attempt to unmount the SD card first.
277 * No need to bother checking for errors.
281 /* ask vdc to unmount it */
282 // prevent: Use of untrusted string value (TAINTED_STRING)
283 execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount",
284 getenv("EXTERNAL_STORAGE"), "force", NULL);
285 } else if (pid > 0) {
286 /* wait until vdc succeeds or fails */
287 waitpid(pid, &ret, 0);
290 ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
292 snprintf(buf, sizeof(buf), "reboot failed: %s errno:%d\n", errno);
293 writex(fd, buf, strlen(buf));
301 #define EVENT_SIZE ( sizeof (struct inotify_event) )
302 #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
303 #define CS_PATH tzplatform_getenv(TZ_SYS_CRASH)
305 void inoti_service(int fd, void *arg)
309 char buffer[BUF_LEN];
311 D( "inoti_service start\n");
312 ifd = inotify_init();
315 D( "inotify_init failed\n");
320 wd = inotify_add_watch( ifd, CS_PATH, IN_CREATE);
322 D("inotify_add_watch failed (errno :%d)\n", errno);
330 length = sdb_read( ifd, buffer, BUF_LEN );
333 D( "inoti read failed\n");
336 while (i >= 0 && i <= (length - EVENT_SIZE)) {
337 struct inotify_event *event = (struct inotify_event *) &buffer[i];
339 if (event->mask & IN_CREATE) {
340 if (!(event->mask & IN_ISDIR)) {
342 int len = asprintf(&cspath, "%s/%s", CS_PATH,
344 D( "The file %s was created.\n", cspath);
345 writex(fd, cspath, len);
346 if (cspath != NULL) {
352 if (i + EVENT_SIZE + event->len < event->len) { // in case of integer overflow
355 i += EVENT_SIZE + event->len;
360 inotify_rm_watch( ifd, wd );
363 D( "inoti_service end\n");
369 static void echo_service(int fd, void *cookie)
377 r = read(fd, buf, 4096);
378 if(r == 0) goto done;
380 if(errno == EINTR) continue;
393 if((r < 0) && (errno == EINTR)) continue;
402 static int create_service_thread(void (*func)(int, void *), void *cookie)
408 if(sdb_socketpair(s)) {
409 D("cannot create service socket pair\n");
413 sti = malloc(sizeof(stinfo));
414 if(sti == 0) fatal("cannot allocate stinfo");
416 sti->cookie = cookie;
419 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
423 D("cannot create service thread\n");
427 D("service thread started, %d:%d\n",s[0], s[1]);
433 static void redirect_and_exec(int pts, const char *cmd, char * const argv[], char * const envp[])
441 execve(cmd, argv, envp);
444 int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * const envp[])
449 ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
451 D("[ cannot open /dev/ptmx - errno:%d ]\n",errno);
454 if (fcntl(ptm, F_SETFD, FD_CLOEXEC) < 0) {
455 D("[ cannot set cloexec to /dev/ptmx - errno:%d ]\n",errno);
458 if(grantpt(ptm) || unlockpt(ptm) ||
459 ptsname_r(ptm, devname, sizeof(devname)) != 0 ){
460 D("[ trouble with /dev/ptmx - errno:%d ]\n", errno);
465 if (smack_setlabel(devname, SDK_SHELL_LABEL_NAME, SMACK_LABEL_ACCESS) == -1) {
466 D("unable to set sdk shell smack label %s due to (errno:%d)\n", SDK_SHELL_LABEL_NAME, errno);
473 D("- fork failed: errno:%d -\n", errno);
483 pts = unix_open(devname, O_RDWR);
485 fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
491 // set OOM adjustment to zero
494 //snprintf(text, sizeof text, "/proc/%d/oom_score_adj", getpid());
495 snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
496 int fd = sdb_open(text, O_WRONLY);
498 sdb_write(fd, "0", 1);
501 // FIXME: not supposed to be here
502 D("sdb: unable to open %s due to errno:%d\n", text, errno);
506 if (should_drop_privileges()) {
507 if (argv[2] != NULL && getuid() == 0 && request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_ROOTCMD, argv[2])) {
509 D("sdb: executes root commands!!:%s\n", argv[2]);
511 if (getuid() != g_sdk_user_id && set_sdk_user_privileges() < 0) {
512 fprintf(stderr, "failed to set SDK user privileges\n");
517 redirect_and_exec(pts, cmd, argv, envp);
518 fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n",
522 // Don't set child's OOM adjustment to zero.
523 // Let the child do it itself, as sometimes the parent starts
524 // running before the child has a /proc/pid/oom_adj.
525 // """sdb: unable to open /proc/644/oom_adj""" seen in some logs.
529 #endif /* !SDB_HOST */
531 #define SHELL_COMMAND "/bin/sh-user"
532 #define LOGIN_COMMAND "/bin/login"
533 #define SUPER_USER "root"
534 #define LOGIN_CONFIG "/etc/login.defs"
537 static void subproc_waiter_service(int fd, void *cookie)
539 pid_t pid = (pid_t)cookie;
541 D("entered. fd=%d of pid=%d\n", fd, pid);
544 pid_t p = waitpid(pid, &status, 0);
546 D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
547 if (WIFEXITED(status)) {
548 D("*** Exit code %d\n", WEXITSTATUS(status));
550 } else if (WIFSIGNALED(status)) {
551 D("*** Killed by signal %d\n", WTERMSIG(status));
554 D("*** Killed by unknown code %d\n", status);
559 D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
560 if (SHELL_EXIT_NOTIFY_FD >=0) {
562 res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
563 D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
564 SHELL_EXIT_NOTIFY_FD, pid, res, errno);
568 void get_env(char *key, char **env)
574 fp = fopen (LOGIN_CONFIG, "r");
579 while (fgets(buf, (int) sizeof (buf), fp) != NULL) {
581 e = buf + (strlen(buf) - 1);
584 while( (e > s) && (*e == ' ' || *e == '\n' || *e == '\t')) {
589 while(*s != '\0' && (*s == ' ' || *s == '\t' || *s == '\n')) {
593 // skip comment or null string
594 if (*s == '#' || *s == '\0') {
597 value = s + strcspn(s, " \t");
600 if(!strcmp(buf, key)) {
601 *env = strdup(value);
609 static int create_subproc_thread(const char *name, int lines, int columns)
616 char *trim_value = NULL;
618 char *envp[MAX_TOKENS];
621 memset(path, 0, sizeof(path));
622 memset(envp, 0, sizeof(envp));
624 envp[envp_cnt++] = strdup("TERM=linux");
625 envp[envp_cnt++] = strdup("DISPLAY=:0");
627 if (should_drop_privileges()) {
628 if (g_sdk_home_dir_env) {
629 envp[envp_cnt++] = strdup(g_sdk_home_dir_env);
631 envp[envp_cnt++] = strdup("HOME=/home/owner");
633 get_env("ENV_PATH", &value);
635 get_env("ENV_SUPATH", &value);
637 get_env("ENV_ROOTPATH", &value);
639 envp[envp_cnt++] = strdup("HOME=/root");
642 trim_value = str_trim(value);
643 if (trim_value != NULL) {
644 // if string is not including 'PATH=', append it.
645 if (strncmp(trim_value, "PATH", 4)) {
646 snprintf(path, sizeof(path), "PATH=%s", trim_value);
648 snprintf(path, sizeof(path), "%s", trim_value);
650 envp[envp_cnt++] = strdup(path);
652 snprintf(path, sizeof(path), "%s", value);
653 envp[envp_cnt++] = strdup(path);
658 /* get environment variables from plugin */
659 char *envp_plugin = NULL;
660 envp_plugin = malloc(ENV_BUF_MAX);
661 if (envp_plugin == NULL) {
662 D("Cannot allocate the shell commnad buffer.");
665 memset(envp_plugin, 0, ENV_BUF_MAX);
666 if (!request_conversion_to_plugin(PLUGIN_SYNC_CMD_GET_SHELL_ENV, NULL,
667 envp_plugin, ENV_BUF_MAX)) {
668 D("Failed to convert the shell command. (%s)\n", name);
672 if(envp_plugin[0] != '\0') {
673 envp_cnt = tokenize_append(envp_plugin, "\n", envp, MAX_TOKENS, envp_cnt);
678 /* Last element of envp must be the NULL-terminator to prevent execvp fail */
679 envp[envp_cnt] = NULL;
681 if(name) { // in case of shell execution directly
682 // Check the shell command validation.
683 if (!request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_SHELLCMD, name)) {
684 D("This shell command is invalid. (%s)\n", name);
688 // Convert the shell command.
689 char *new_cmd = NULL;
690 new_cmd = malloc(SDBD_SHELL_CMD_MAX);
691 if(new_cmd == NULL) {
692 D("Cannot allocate the shell commnad buffer.");
696 memset(new_cmd, 0, SDBD_SHELL_CMD_MAX);
697 if(!request_conversion_to_plugin(PLUGIN_SYNC_CMD_CONVERT_SHELLCMD, name, new_cmd, SDBD_SHELL_CMD_MAX)) {
698 D("Failed to convert the shell command. (%s)\n", name);
703 D("converted cmd : %s\n", new_cmd);
713 ret_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp);
715 } else { // in case of shell interactively
716 // Check the capability for interactive shell support.
717 if (!is_support_interactive_shell()) {
718 D("This platform dose NOT support the interactive shell\n");
722 char * const args[] = {
727 ret_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp);
728 #if 0 // FIXME: should call login command instead of /bin/sh
729 if (should_drop_privileges()) {
735 ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
743 ret_fd = create_subprocess(LOGIN_COMMAND, &pid, args, envp);
748 /* free environment variables */
751 for(i = 0; i < envp_cnt; i++) {
753 D("envp[%d] = %s\n", i, envp[i]);
759 D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid);
762 D("cannot create service thread\n");
766 if (lines > 0 && columns > 0) {
767 D("shell size lines=%d, columns=%d\n", lines, columns);
768 struct winsize win_sz;
769 win_sz.ws_row = lines;
770 win_sz.ws_col = columns;
772 if (ioctl(ret_fd, TIOCSWINSZ, &win_sz) < 0) {
773 D("failed to sync window size.\n");
777 sti = malloc(sizeof(stinfo));
778 if(sti == 0) fatal("cannot allocate stinfo");
779 sti->func = subproc_waiter_service;
780 sti->cookie = (void*)pid;
783 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
786 D("cannot create service thread\n");
790 D("service thread started, fd=%d pid=%d\n",ret_fd, pid);
794 static int create_sync_subprocess(void (*func)(int, void *), void* cookie) {
799 if(sdb_socketpair(s)) {
800 D("cannot create service socket pair\n");
810 } else if (pid > 0) {
812 // FIXME: do not wait child process hear
813 //waitpid(pid, &ret, 0);
816 D("- fork failed: errno:%d -\n", errno);
819 D("cannot create sync service sub process\n");
823 sti = malloc(sizeof(stinfo));
824 if(sti == 0) fatal("cannot allocate stinfo");
825 sti->func = subproc_waiter_service;
826 sti->cookie = (void*)pid;
829 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
832 printf("cannot create service monitor thread\n");
836 D("service process started, fd=%d pid=%d\n",s[0], pid);
840 static int create_syncproc_thread()
844 ret_fd = create_sync_subprocess(file_sync_service, NULL);
845 // FIXME: file missing bug when root on mode
847 if (should_drop_privileges()) {
848 ret_fd = create_sync_subprocess(file_sync_service, NULL);
850 ret_fd = create_service_thread(file_sync_service, NULL);
858 static void get_platforminfo(int fd, void *cookie) {
862 s_strncpy(sysinfo.platform_info_version, INFO_VERSION, strlen(INFO_VERSION));
864 int r = system_info_get_platform_string("http://tizen.org/system/model_name", &value);
865 if (r != SYSTEM_INFO_ERROR_NONE) {
866 s_strncpy(sysinfo.model_name, UNKNOWN, strlen(UNKNOWN));
867 D("fail to get system model:%d\n", errno);
869 s_strncpy(sysinfo.model_name, value, sizeof(sysinfo.model_name));
870 D("returns model_name:%s\n", value);
876 r = system_info_get_platform_string("http://tizen.org/system/platform.name", &value);
877 if (r != SYSTEM_INFO_ERROR_NONE) {
878 s_strncpy(sysinfo.platform_name, UNKNOWN, strlen(UNKNOWN));
879 D("fail to get platform name:%d\n", errno);
881 s_strncpy(sysinfo.platform_name, value, sizeof(sysinfo.platform_name));
882 D("returns platform_name:%s\n", value);
889 // FIXME: the result is different when using SYSTEM_INFO_KEY_TIZEN_VERSION_NAME
890 r = system_info_get_platform_string("tizen.org/feature/platform.version", &value);
891 if (r != SYSTEM_INFO_ERROR_NONE) {
892 s_strncpy(sysinfo.platform_version, UNKNOWN, strlen(UNKNOWN));
893 D("fail to get platform version:%d\n", errno);
895 s_strncpy(sysinfo.platform_version, value, sizeof(sysinfo.platform_version));
896 D("returns platform_version:%s\n", value);
902 r = system_info_get_platform_string("tizen.org/feature/profile", &value);
903 if (r != SYSTEM_INFO_ERROR_NONE) {
904 s_strncpy(sysinfo.profile_name, UNKNOWN, strlen(UNKNOWN));
905 D("fail to get profile name:%d\n", errno);
907 s_strncpy(sysinfo.profile_name, value, sizeof(sysinfo.profile_name));
908 D("returns profile name:%s\n", value);
914 writex(fd, &sysinfo, sizeof(pinfo));
919 static int put_key_value_string(char* buf, int offset, int buf_size, char* key, char* value) {
921 if ((len = snprintf(buf+offset, buf_size-offset, "%s:%s\n", key, value)) > 0) {
927 static void get_capability(int fd, void *cookie) {
928 char cap_buffer[CAPBUF_SIZE] = {0,};
931 // Secure protocol support
932 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
933 "secure_protocol", g_capabilities.secure_protocol);
935 // Interactive shell support
936 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
937 "intershell_support", g_capabilities.intershell_support);
939 // File push/pull support
940 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
941 "filesync_support", g_capabilities.filesync_support);
943 // USB protocol support
944 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
945 "usbproto_support", g_capabilities.usbproto_support);
947 // Socket protocol support
948 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
949 "sockproto_support", g_capabilities.sockproto_support);
951 // Window size synchronization support
952 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
953 "syncwinsz_support", g_capabilities.syncwinsz_support);
955 // Root command support
956 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
957 "rootonoff_support", g_capabilities.rootonoff_support);
959 // Encryption support
960 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
961 "encryption_support", g_capabilities.encryption_support);
964 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
965 "zone_support", g_capabilities.zone_support);
967 // Multi-User support
968 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
969 "multiuser_support", g_capabilities.multiuser_support);
971 // CPU Architecture of model
972 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
973 "cpu_arch", g_capabilities.cpu_arch);
976 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
977 "sdk_toolpath", g_capabilities.sdk_toolpath);
980 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
981 "profile_name", g_capabilities.profile_name);
984 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
985 "vendor_name", g_capabilities.vendor_name);
987 // Target name of the launch possible
988 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
989 "can_launch", g_capabilities.can_launch);
992 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
993 "platform_version", g_capabilities.platform_version);
996 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
997 "product_version", g_capabilities.product_version);
1000 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1001 "sdbd_version", g_capabilities.sdbd_version);
1003 // Sdbd plugin version
1004 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1005 "sdbd_plugin_version", g_capabilities.sdbd_plugin_version);
1007 // Capability version
1008 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1009 "sdbd_cap_version", g_capabilities.sdbd_cap_version);
1012 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1013 "log_enable", g_capabilities.log_enable);
1016 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1017 "log_path", g_capabilities.log_path);
1019 // Application command support
1020 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1021 "appcmd_support", g_capabilities.appcmd_support);
1023 // appid2pid support
1024 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1025 "appid2pid_support", g_capabilities.appid2pid_support);
1027 // pkgcmd debug mode support
1028 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1029 "pkgcmd_debugmode", g_capabilities.pkgcmd_debugmode);
1031 offset++; // for '\0' character
1033 writex(fd, &offset, sizeof(uint16_t));
1034 writex(fd, cap_buffer, offset);
1039 static void sync_windowsize(int fd, void *cookie) {
1040 int id, lines, columns;
1041 char *size_info = cookie;
1044 if (sscanf(size_info, "%d:%d:%d", &id, &lines, &columns) == 3) {
1045 D("window size information: id=%d, lines=%d, columns=%d\n", id, lines, columns);
1047 if((s = find_local_socket(id))) {
1048 struct winsize win_sz;
1049 win_sz.ws_row = lines;
1050 win_sz.ws_col = columns;
1052 if (ioctl(s->fd, TIOCSWINSZ, &win_sz) < 0) {
1053 D("failed to sync window size.\n");
1056 D("success to sync window size.\n");
1060 const unsigned COMMAND_TIMEOUT = 10000;
1061 void get_boot(int fd, void *cookie) {
1062 char buf[2] = { 0, };
1064 int interval = 1000;
1065 while (time < COMMAND_TIMEOUT) {
1066 if (booting_done == 1) {
1067 D("get_boot:platform booting is done\n");
1068 snprintf(buf, sizeof(buf), "%s", "1");
1071 D("get_boot:platform booting is in progress\n");
1072 sdb_sleep_ms(interval);
1075 writex(fd, buf, strlen(buf));
1079 int service_to_fd(const char *name)
1083 if(!strncmp(name, "tcp:", 4)) {
1084 int port = atoi(name + 4);
1085 name = strchr(name + 4, ':');
1088 ret = socket_ifr_client(port , SOCK_STREAM, "eth0");
1090 ret = socket_ifr_client(port , SOCK_STREAM, "usb0");
1092 if (ifconfig(SDB_FORWARD_IFNAME, SDB_FORWARD_INTERNAL_IP, SDB_FORWARD_INTERNAL_MASK, 1) == 0) {
1093 ret = socket_ifr_client(port , SOCK_STREAM, SDB_FORWARD_IFNAME);
1098 ret = socket_loopback_client(port, SOCK_STREAM);
1101 disable_tcp_nagle(ret);
1105 sdb_mutex_lock(&dns_lock);
1106 ret = socket_network_client(name + 1, port, SOCK_STREAM);
1107 sdb_mutex_unlock(&dns_lock);
1112 #ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */
1113 } else if(!strncmp(name, "local:", 6)) {
1114 ret = socket_local_client(name + 6,
1115 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
1116 } else if(!strncmp(name, "localreserved:", 14)) {
1117 ret = socket_local_client(name + 14,
1118 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
1119 } else if(!strncmp(name, "localabstract:", 14)) {
1120 ret = socket_local_client(name + 14,
1121 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1122 } else if(!strncmp(name, "localfilesystem:", 16)) {
1123 ret = socket_local_client(name + 16,
1124 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
1127 } else if(!strncmp("dns:", name, 4)){
1128 char *n = strdup(name + 4);
1129 if(n == 0) return -1;
1130 ret = create_service_thread(dns_service, n);
1131 #else /* !SDB_HOST */
1132 }/* else if(!strncmp("dev:", name, 4)) {// tizen specific
1133 ret = unix_open(name + 4, O_RDWR);
1134 } else if(!strncmp(name, "framebuffer:", 12)) {
1135 ret = create_service_thread(framebuffer_service, 0);
1136 } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
1137 ret = create_service_thread(recover_service, (void*) atoi(name + 8));
1138 } else if (!strncmp(name, "jdwp:", 5)) {
1139 ret = create_jdwp_connection_fd(atoi(name+5));
1140 } else if (!strncmp(name, "log:", 4)) {
1141 ret = create_service_thread(log_service, get_log_file_path(name + 4));
1142 }*/ else if(!HOST && !strncmp(name, "shell:", 6)) {
1144 ret = create_subproc_thread(name + 6, 0, 0);
1146 ret = create_subproc_thread(NULL, 0, 0);
1148 } else if(!strncmp(name, "eshell:", 7)) {
1150 if (sscanf(name+7, "%d:%d", &lines, &columns) == 2) {
1151 ret = create_subproc_thread(NULL, lines, columns);
1153 } else if(!strncmp(name, "sync:", 5)) {
1154 //ret = create_service_thread(file_sync_service, NULL);
1155 ret = create_syncproc_thread();
1156 }/* else if(!strncmp(name, "remount:", 8)) {
1157 ret = create_service_thread(remount_service, NULL);
1158 } else if(!strncmp(name, "reboot:", 7)) {
1159 void* arg = strdup(name + 7);
1160 if(arg == 0) return -1;
1161 ret = create_service_thread(reboot_service, arg);
1162 } else if(!strncmp(name, "root:", 5)) {
1163 ret = create_service_thread(restart_root_service, NULL);
1164 } else if(!strncmp(name, "backup:", 7)) {
1165 char* arg = strdup(name+7);
1166 if (arg == NULL) return -1;
1167 ret = backup_service(BACKUP, arg);
1168 } else if(!strncmp(name, "restore:", 8)) {
1169 ret = backup_service(RESTORE, NULL);
1170 }*/ else if(!strncmp(name, "root:", 5)) {
1171 char* service_name = NULL;
1173 service_name = strdup(name+5);
1174 ret = create_service_thread(rootshell_service, (void *)(service_name));
1175 } else if(!strncmp(name, "cs:", 5)) {
1176 ret = create_service_thread(inoti_service, NULL);
1178 } else if(!strncmp(name, "sysinfo:", 8)){
1179 ret = create_service_thread(get_platforminfo, 0);
1180 } else if(!strncmp(name, "capability:", 11)){
1181 ret = create_service_thread(get_capability, 0);
1182 } else if(!strncmp(name, "boot:", 5)){
1183 if (is_emulator()) {
1184 ret = create_service_thread(get_boot, 0);
1186 } else if(!strncmp(name, "shellconf:", 10)){
1187 if(!strncmp(name+10, "syncwinsz:", 10)){
1188 ret = create_service_thread(sync_windowsize, (void *)name+20);
1190 } else if(!strncmp(name, "tzplatformenv:", 14)) {
1191 char* env_variable = NULL;
1192 env_variable = strdup(name+14);
1193 ret = create_service_thread(get_tzplatform_env, (void *)(env_variable));
1194 } else if(!strncmp(name, "appcmd:", 7)){
1195 ret = request_appcmd_to_plugin(name+7);
1199 if (close_on_exec(ret) < 0) {
1200 D("failed to close fd exec\n");
1208 transport_type transport;
1213 static void wait_for_state(int fd, void* cookie)
1215 struct state_info* sinfo = cookie;
1216 char* err = "unknown error";
1218 D("wait_for_state %d\n", sinfo->state);
1220 atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
1222 writex(fd, "OKAY", 4);
1224 sendfailmsg(fd, err);
1228 free(sinfo->serial);
1231 D("wait_for_state is done\n");
1236 asocket* host_service_to_socket(const char* name, const char *serial)
1238 if (!strcmp(name,"track-devices")) {
1239 return create_device_tracker();
1240 } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
1241 struct state_info* sinfo = malloc(sizeof(struct state_info));
1244 sinfo->serial = strdup(serial);
1246 sinfo->serial = NULL;
1248 name += strlen("wait-for-");
1250 if (!strncmp(name, "local", strlen("local"))) {
1251 sinfo->transport = kTransportLocal;
1252 sinfo->state = CS_DEVICE;
1253 } else if (!strncmp(name, "usb", strlen("usb"))) {
1254 sinfo->transport = kTransportUsb;
1255 sinfo->state = CS_DEVICE;
1256 } else if (!strncmp(name, "any", strlen("any"))) {
1257 sinfo->transport = kTransportAny;
1258 sinfo->state = CS_DEVICE;
1264 int fd = create_service_thread(wait_for_state, sinfo);
1265 return create_local_socket(fd);
1269 #endif /* SDB_HOST */