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>
52 #include <sys/ioctl.h>
54 #include "sdbd_plugin.h"
57 #define ENV_BUF_MAX 4096
59 typedef struct stinfo stinfo;
62 void (*func)(int fd, void *cookie);
67 void *service_bootstrap_func(void *x)
70 sti->func(sti->fd, sti->cookie);
76 SDB_MUTEX_DEFINE( dns_lock );
78 static void dns_service(int fd, void *cookie)
80 char *hostname = cookie;
84 sdb_mutex_lock(&dns_lock);
85 hp = gethostbyname(hostname);
90 writex(fd, hp->h_addr, 4);
92 sdb_mutex_unlock(&dns_lock);
97 static int is_support_interactive_shell()
99 return (!strncmp(g_capabilities.intershell_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
103 extern int recovery_mode;
105 static void recover_service(int s, void *cookie)
107 unsigned char buf[4096];
108 unsigned count = (unsigned) cookie;
111 fd = sdb_creat("/tmp/update", 0644);
118 unsigned xfer = (count > 4096) ? 4096 : count;
119 if(readx(s, buf, xfer)) break;
120 if(writex(fd, buf, xfer)) break;
125 writex(s, "OKAY", 4);
127 writex(s, "FAIL", 4);
132 fd = sdb_creat("/tmp/update.begin", 0644);
136 void restart_root_service(int fd, void *cookie)
139 char value[PROPERTY_VALUE_MAX];
142 snprintf(buf, sizeof(buf), "sdbd is already running as root\n");
143 writex(fd, buf, strlen(buf));
146 property_get("ro.debuggable", value, "");
147 if (strcmp(value, "1") != 0) {
148 snprintf(buf, sizeof(buf), "sdbd cannot run as root in production builds\n");
149 writex(fd, buf, strlen(buf));
154 property_set("service.sdb.root", "1");
155 snprintf(buf, sizeof(buf), "restarting sdbd as root\n");
156 writex(fd, buf, strlen(buf));
162 void restart_tcp_service(int fd, void *cookie)
165 char value[PROPERTY_VALUE_MAX];
166 int port = (int)cookie;
169 snprintf(buf, sizeof(buf), "invalid port\n");
170 writex(fd, buf, strlen(buf));
175 snprintf(value, sizeof(value), "%d", port);
176 property_set("service.sdb.tcp.port", value);
177 snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
178 writex(fd, buf, strlen(buf));
182 static int is_support_rootonoff()
184 return (!strncmp(g_capabilities.rootonoff_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
187 void rootshell_service(int fd, void *cookie)
190 char *mode = (char*) cookie;
192 if (!strcmp(mode, "on")) {
194 if (rootshell_mode == 1) {
195 //snprintf(buf, sizeof(buf), "Already changed to sdk user mode\n");
196 // do not show message
198 if (is_support_rootonoff()) {
200 //allows a permitted user to execute a command as the superuser
201 snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n");
203 snprintf(buf, sizeof(buf), "Permission denied\n");
205 writex(fd, buf, strlen(buf));
208 D("need root permission for root shell: %d\n", getuid());
210 snprintf(buf, sizeof(buf), "Permission denied\n");
211 writex(fd, buf, strlen(buf));
213 } else if (!strcmp(mode, "off")) {
214 if (rootshell_mode == 1) {
216 snprintf(buf, sizeof(buf), "Switched to 'sdk user' account mode\n");
217 writex(fd, buf, strlen(buf));
220 snprintf(buf, sizeof(buf), "Unknown command option : %s\n", mode);
221 writex(fd, buf, strlen(buf));
223 D("set rootshell to %s\n", rootshell_mode == 1 ? "root" : SDK_USER_NAME);
228 enum tzplatform_get_env_error_status {
229 NO_ERROR_TZPLATFORM_ENV = 0,
230 ERROR_TZPLATFORM_ENV_GENERAL = 1,
231 ERROR_TZPLATFORM_ENV_INVALID_VARIABLES = 2,
234 void get_tzplatform_env(int fd, void *cookie) {
235 char buf[PATH_MAX] = { 0, };
236 char *env_name = (char*) cookie;
237 D("environment variable name: %s\n", env_name);
238 enum tzplatform_variable env_id = tzplatform_getid(env_name);
239 if (env_id != _TZPLATFORM_VARIABLES_INVALID_) {
240 const char *env_value = tzplatform_getenv(env_id);
242 D("environment value : %s\n", env_value);
243 snprintf(buf, sizeof(buf), "%d%s", NO_ERROR_TZPLATFORM_ENV, env_value);
245 D("failed to get environment value using tzplatform_getenv");
246 snprintf(buf, sizeof(buf), "%d", ERROR_TZPLATFORM_ENV_GENERAL);
249 D("environment name (%s) is invalid\n", env_name);
250 snprintf(buf, sizeof(buf), "%d", ERROR_TZPLATFORM_ENV_INVALID_VARIABLES);
252 writex(fd, buf, strlen(buf));
257 void restart_usb_service(int fd, void *cookie)
261 property_set("service.sdb.tcp.port", "0");
262 snprintf(buf, sizeof(buf), "restarting in USB mode\n");
263 writex(fd, buf, strlen(buf));
267 void reboot_service(int fd, void *arg)
275 /* Attempt to unmount the SD card first.
276 * No need to bother checking for errors.
280 /* ask vdc to unmount it */
281 // prevent: Use of untrusted string value (TAINTED_STRING)
282 execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount",
283 getenv("EXTERNAL_STORAGE"), "force", NULL);
284 } else if (pid > 0) {
285 /* wait until vdc succeeds or fails */
286 waitpid(pid, &ret, 0);
289 ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
291 snprintf(buf, sizeof(buf), "reboot failed: %s errno:%d\n", errno);
292 writex(fd, buf, strlen(buf));
300 #define EVENT_SIZE ( sizeof (struct inotify_event) )
301 #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
302 #define CS_PATH tzplatform_getenv(TZ_SYS_CRASH)
304 void inoti_service(int fd, void *arg)
308 char buffer[BUF_LEN];
310 D( "inoti_service start\n");
311 ifd = inotify_init();
314 D( "inotify_init failed\n");
319 wd = inotify_add_watch( ifd, CS_PATH, IN_CREATE);
321 D("inotify_add_watch failed (errno :%d)\n", errno);
329 length = sdb_read( ifd, buffer, BUF_LEN );
332 D( "inoti read failed\n");
335 while (i >= 0 && i <= (length - EVENT_SIZE)) {
336 struct inotify_event *event = (struct inotify_event *) &buffer[i];
338 if (event->mask & IN_CREATE) {
339 if (!(event->mask & IN_ISDIR)) {
341 int len = asprintf(&cspath, "%s/%s", CS_PATH,
343 D( "The file %s was created.\n", cspath);
344 writex(fd, cspath, len);
345 if (cspath != NULL) {
351 if (i + EVENT_SIZE + event->len < event->len) { // in case of integer overflow
354 i += EVENT_SIZE + event->len;
359 inotify_rm_watch( ifd, wd );
362 D( "inoti_service end\n");
368 static void echo_service(int fd, void *cookie)
376 r = read(fd, buf, 4096);
377 if(r == 0) goto done;
379 if(errno == EINTR) continue;
392 if((r < 0) && (errno == EINTR)) continue;
401 static int create_service_thread(void (*func)(int, void *), void *cookie)
407 if(sdb_socketpair(s)) {
408 D("cannot create service socket pair\n");
412 sti = malloc(sizeof(stinfo));
413 if(sti == 0) fatal("cannot allocate stinfo");
415 sti->cookie = cookie;
418 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
422 D("cannot create service thread\n");
426 D("service thread started, %d:%d\n",s[0], s[1]);
432 static void redirect_and_exec(int pts, const char *cmd, char * const argv[], char * const envp[])
440 execve(cmd, argv, envp);
443 int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * const envp[])
448 ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
450 D("[ cannot open /dev/ptmx - errno:%d ]\n",errno);
453 if (fcntl(ptm, F_SETFD, FD_CLOEXEC) < 0) {
454 D("[ cannot set cloexec to /dev/ptmx - errno:%d ]\n",errno);
457 if(grantpt(ptm) || unlockpt(ptm) ||
458 ptsname_r(ptm, devname, sizeof(devname)) != 0 ){
459 D("[ trouble with /dev/ptmx - errno:%d ]\n", errno);
466 D("- fork failed: errno:%d -\n", errno);
476 pts = unix_open(devname, O_RDWR);
478 fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
484 // set OOM adjustment to zero
487 //snprintf(text, sizeof text, "/proc/%d/oom_score_adj", getpid());
488 snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
489 int fd = sdb_open(text, O_WRONLY);
491 sdb_write(fd, "0", 1);
494 // FIXME: not supposed to be here
495 D("sdb: unable to open %s due to errno:%d\n", text, errno);
499 if (should_drop_privileges()) {
500 if (argv[2] != NULL && getuid() == 0 && request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_ROOTCMD, argv[2])) {
502 D("sdb: executes root commands!!:%s\n", argv[2]);
504 if (getuid() != g_sdk_user_id && set_sdk_user_privileges() < 0) {
505 fprintf(stderr, "failed to set SDK user privileges\n");
510 redirect_and_exec(pts, cmd, argv, envp);
511 fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n",
515 // Don't set child's OOM adjustment to zero.
516 // Let the child do it itself, as sometimes the parent starts
517 // running before the child has a /proc/pid/oom_adj.
518 // """sdb: unable to open /proc/644/oom_adj""" seen in some logs.
522 #endif /* !SDB_HOST */
524 #define LOGIN_COMMAND "/bin/login"
525 #define SUPER_USER "root"
526 #define LOGIN_CONFIG "/etc/login.defs"
529 static void subproc_waiter_service(int fd, void *cookie)
531 pid_t pid = (pid_t)cookie;
533 D("entered. fd=%d of pid=%d\n", fd, pid);
536 pid_t p = waitpid(pid, &status, 0);
538 D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
539 if (WIFEXITED(status)) {
540 D("*** Exit code %d\n", WEXITSTATUS(status));
542 } else if (WIFSIGNALED(status)) {
543 D("*** Killed by signal %d\n", WTERMSIG(status));
546 D("*** Killed by unknown code %d\n", status);
551 D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
552 if (SHELL_EXIT_NOTIFY_FD >=0) {
554 res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
555 D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
556 SHELL_EXIT_NOTIFY_FD, pid, res, errno);
560 void get_env(char *key, char **env)
566 fp = fopen (LOGIN_CONFIG, "r");
571 while (fgets(buf, (int) sizeof (buf), fp) != NULL) {
573 e = buf + (strlen(buf) - 1);
576 while( (e > s) && (*e == ' ' || *e == '\n' || *e == '\t')) {
581 while(*s != '\0' && (*s == ' ' || *s == '\t' || *s == '\n')) {
585 // skip comment or null string
586 if (*s == '#' || *s == '\0') {
589 value = s + strcspn(s, " \t");
592 if(!strcmp(buf, key)) {
593 *env = strdup(value);
601 static int create_subproc_thread(const char *name, int lines, int columns)
608 char *trim_value = NULL;
610 char *envp[MAX_TOKENS];
613 memset(path, 0, sizeof(path));
614 memset(envp, 0, sizeof(envp));
616 envp[envp_cnt++] = strdup("TERM=linux");
617 envp[envp_cnt++] = strdup("DISPLAY=:0");
619 if (should_drop_privileges()) {
620 if (g_sdk_home_dir_env) {
621 envp[envp_cnt++] = strdup(g_sdk_home_dir_env);
623 envp[envp_cnt++] = strdup("HOME=/home/owner");
625 get_env("ENV_PATH", &value);
627 get_env("ENV_SUPATH", &value);
629 get_env("ENV_ROOTPATH", &value);
631 envp[envp_cnt++] = strdup("HOME=/root");
634 trim_value = str_trim(value);
635 if (trim_value != NULL) {
636 // if string is not including 'PATH=', append it.
637 if (strncmp(trim_value, "PATH", 4)) {
638 snprintf(path, sizeof(path), "PATH=%s", trim_value);
640 snprintf(path, sizeof(path), "%s", trim_value);
642 envp[envp_cnt++] = strdup(path);
644 snprintf(path, sizeof(path), "%s", value);
645 envp[envp_cnt++] = strdup(path);
650 /* get environment variables from plugin */
651 char *envp_plugin = NULL;
652 envp_plugin = malloc(ENV_BUF_MAX);
653 if (envp_plugin == NULL) {
654 D("Cannot allocate the shell commnad buffer.");
657 memset(envp_plugin, 0, ENV_BUF_MAX);
658 if (!request_conversion_to_plugin(PLUGIN_SYNC_CMD_GET_SHELL_ENV, NULL,
659 envp_plugin, ENV_BUF_MAX)) {
660 D("Failed to convert the shell command. (%s)\n", name);
664 if(envp_plugin[0] != '\0') {
665 envp_cnt = tokenize_append(envp_plugin, "\n", envp, MAX_TOKENS, envp_cnt);
670 /* Last element of envp must be the NULL-terminator to prevent execvp fail */
671 envp[envp_cnt] = NULL;
673 if(name) { // in case of shell execution directly
674 // Check the shell command validation.
675 if (!request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_SHELLCMD, name)) {
676 D("This shell command is invalid. (%s)\n", name);
680 // Convert the shell command.
681 char *new_cmd = NULL;
682 new_cmd = malloc(SDBD_SHELL_CMD_MAX);
683 if(new_cmd == NULL) {
684 D("Cannot allocate the shell commnad buffer.");
688 memset(new_cmd, 0, SDBD_SHELL_CMD_MAX);
689 if(!request_conversion_to_plugin(PLUGIN_SYNC_CMD_CONVERT_SHELLCMD, name, new_cmd, SDBD_SHELL_CMD_MAX)) {
690 D("Failed to convert the shell command. (%s)\n", name);
695 D("converted cmd : %s\n", new_cmd);
705 ret_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp);
707 } else { // in case of shell interactively
708 // Check the capability for interactive shell support.
709 if (!is_support_interactive_shell()) {
710 D("This platform dose NOT support the interactive shell\n");
714 char * const args[] = {
719 ret_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp);
720 #if 0 // FIXME: should call login command instead of /bin/sh
721 if (should_drop_privileges()) {
727 ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
735 ret_fd = create_subprocess(LOGIN_COMMAND, &pid, args, envp);
740 /* free environment variables */
743 for(i = 0; i < envp_cnt; i++) {
745 D("envp[%d] = %s\n", i, envp[i]);
751 D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid);
754 D("cannot create service thread\n");
758 if (lines > 0 && columns > 0) {
759 D("shell size lines=%d, columns=%d\n", lines, columns);
760 struct winsize win_sz;
761 win_sz.ws_row = lines;
762 win_sz.ws_col = columns;
764 if (ioctl(ret_fd, TIOCSWINSZ, &win_sz) < 0) {
765 D("failed to sync window size.\n");
769 sti = malloc(sizeof(stinfo));
770 if(sti == 0) fatal("cannot allocate stinfo");
771 sti->func = subproc_waiter_service;
772 sti->cookie = (void*)pid;
775 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
778 D("cannot create service thread\n");
782 D("service thread started, fd=%d pid=%d\n",ret_fd, pid);
786 static int create_sync_subprocess(void (*func)(int, void *), void* cookie) {
791 if(sdb_socketpair(s)) {
792 D("cannot create service socket pair\n");
802 } else if (pid > 0) {
804 // FIXME: do not wait child process hear
805 //waitpid(pid, &ret, 0);
808 D("- fork failed: errno:%d -\n", errno);
811 D("cannot create sync service sub process\n");
815 sti = malloc(sizeof(stinfo));
816 if(sti == 0) fatal("cannot allocate stinfo");
817 sti->func = subproc_waiter_service;
818 sti->cookie = (void*)pid;
821 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
824 printf("cannot create service monitor thread\n");
828 D("service process started, fd=%d pid=%d\n",s[0], pid);
832 static int create_syncproc_thread()
836 ret_fd = create_sync_subprocess(file_sync_service, NULL);
837 // FIXME: file missing bug when root on mode
839 if (should_drop_privileges()) {
840 ret_fd = create_sync_subprocess(file_sync_service, NULL);
842 ret_fd = create_service_thread(file_sync_service, NULL);
850 static void get_platforminfo(int fd, void *cookie) {
854 s_strncpy(sysinfo.platform_info_version, INFO_VERSION, strlen(INFO_VERSION));
856 int r = system_info_get_platform_string("http://tizen.org/system/model_name", &value);
857 if (r != SYSTEM_INFO_ERROR_NONE) {
858 s_strncpy(sysinfo.model_name, UNKNOWN, strlen(UNKNOWN));
859 D("fail to get system model:%d\n", errno);
861 s_strncpy(sysinfo.model_name, value, sizeof(sysinfo.model_name));
862 D("returns model_name:%s\n", value);
868 r = system_info_get_platform_string("http://tizen.org/system/platform.name", &value);
869 if (r != SYSTEM_INFO_ERROR_NONE) {
870 s_strncpy(sysinfo.platform_name, UNKNOWN, strlen(UNKNOWN));
871 D("fail to get platform name:%d\n", errno);
873 s_strncpy(sysinfo.platform_name, value, sizeof(sysinfo.platform_name));
874 D("returns platform_name:%s\n", value);
881 // FIXME: the result is different when using SYSTEM_INFO_KEY_TIZEN_VERSION_NAME
882 r = system_info_get_platform_string("tizen.org/feature/platform.version", &value);
883 if (r != SYSTEM_INFO_ERROR_NONE) {
884 s_strncpy(sysinfo.platform_version, UNKNOWN, strlen(UNKNOWN));
885 D("fail to get platform version:%d\n", errno);
887 s_strncpy(sysinfo.platform_version, value, sizeof(sysinfo.platform_version));
888 D("returns platform_version:%s\n", value);
894 r = system_info_get_platform_string("tizen.org/feature/profile", &value);
895 if (r != SYSTEM_INFO_ERROR_NONE) {
896 s_strncpy(sysinfo.profile_name, UNKNOWN, strlen(UNKNOWN));
897 D("fail to get profile name:%d\n", errno);
899 s_strncpy(sysinfo.profile_name, value, sizeof(sysinfo.profile_name));
900 D("returns profile name:%s\n", value);
906 writex(fd, &sysinfo, sizeof(pinfo));
911 static int put_key_value_string(char* buf, int offset, int buf_size, char* key, char* value) {
913 if ((len = snprintf(buf+offset, buf_size-offset, "%s:%s\n", key, value)) > 0) {
919 static void get_capability(int fd, void *cookie) {
920 char cap_buffer[CAPBUF_SIZE] = {0,};
923 // Secure protocol support
924 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
925 "secure_protocol", g_capabilities.secure_protocol);
927 // Interactive shell support
928 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
929 "intershell_support", g_capabilities.intershell_support);
931 // File push/pull support
932 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
933 "filesync_support", g_capabilities.filesync_support);
935 // USB protocol support
936 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
937 "usbproto_support", g_capabilities.usbproto_support);
939 // Socket protocol support
940 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
941 "sockproto_support", g_capabilities.sockproto_support);
943 // Window size synchronization support
944 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
945 "syncwinsz_support", g_capabilities.syncwinsz_support);
947 // Root command support
948 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
949 "rootonoff_support", g_capabilities.rootonoff_support);
952 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
953 "zone_support", g_capabilities.zone_support);
955 // Multi-User support
956 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
957 "multiuser_support", g_capabilities.multiuser_support);
959 // CPU Architecture of model
960 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
961 "cpu_arch", g_capabilities.cpu_arch);
964 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
965 "sdk_toolpath", g_capabilities.sdk_toolpath);
968 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
969 "profile_name", g_capabilities.profile_name);
972 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
973 "vendor_name", g_capabilities.vendor_name);
975 // Target name of the launch possible
976 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
977 "can_launch", g_capabilities.can_launch);
980 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
981 "platform_version", g_capabilities.platform_version);
984 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
985 "product_version", g_capabilities.product_version);
988 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
989 "sdbd_version", g_capabilities.sdbd_version);
991 // Sdbd plugin version
992 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
993 "sdbd_plugin_version", g_capabilities.sdbd_plugin_version);
995 // Capability version
996 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
997 "sdbd_cap_version", g_capabilities.sdbd_cap_version);
1000 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1001 "log_enable", g_capabilities.log_enable);
1004 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1005 "log_path", g_capabilities.log_path);
1007 // Application command support
1008 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
1009 "appcmd_support", g_capabilities.appcmd_support);
1011 offset++; // for '\0' character
1013 writex(fd, &offset, sizeof(uint16_t));
1014 writex(fd, cap_buffer, offset);
1019 static void sync_windowsize(int fd, void *cookie) {
1020 int id, lines, columns;
1021 char *size_info = cookie;
1024 if (sscanf(size_info, "%d:%d:%d", &id, &lines, &columns) == 3) {
1025 D("window size information: id=%d, lines=%d, columns=%d\n", id, lines, columns);
1027 if((s = find_local_socket(id))) {
1028 struct winsize win_sz;
1029 win_sz.ws_row = lines;
1030 win_sz.ws_col = columns;
1032 if (ioctl(s->fd, TIOCSWINSZ, &win_sz) < 0) {
1033 D("failed to sync window size.\n");
1036 D("success to sync window size.\n");
1040 const unsigned COMMAND_TIMEOUT = 10000;
1041 void get_boot(int fd, void *cookie) {
1042 char buf[2] = { 0, };
1044 int interval = 1000;
1045 while (time < COMMAND_TIMEOUT) {
1046 if (booting_done == 1) {
1047 D("get_boot:platform booting is done\n");
1048 snprintf(buf, sizeof(buf), "%s", "1");
1051 D("get_boot:platform booting is in progress\n");
1052 sdb_sleep_ms(interval);
1055 writex(fd, buf, strlen(buf));
1059 int service_to_fd(const char *name)
1063 if(!strncmp(name, "tcp:", 4)) {
1064 int port = atoi(name + 4);
1065 name = strchr(name + 4, ':');
1068 ret = socket_ifr_client(port , SOCK_STREAM, "eth0");
1070 ret = socket_ifr_client(port , SOCK_STREAM, "usb0");
1072 if (ifconfig(SDB_FORWARD_IFNAME, SDB_FORWARD_INTERNAL_IP, SDB_FORWARD_INTERNAL_MASK, 1) == 0) {
1073 ret = socket_ifr_client(port , SOCK_STREAM, SDB_FORWARD_IFNAME);
1078 ret = socket_loopback_client(port, SOCK_STREAM);
1081 disable_tcp_nagle(ret);
1085 sdb_mutex_lock(&dns_lock);
1086 ret = socket_network_client(name + 1, port, SOCK_STREAM);
1087 sdb_mutex_unlock(&dns_lock);
1092 #ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */
1093 } else if(!strncmp(name, "local:", 6)) {
1094 ret = socket_local_client(name + 6,
1095 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
1096 } else if(!strncmp(name, "localreserved:", 14)) {
1097 ret = socket_local_client(name + 14,
1098 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
1099 } else if(!strncmp(name, "localabstract:", 14)) {
1100 ret = socket_local_client(name + 14,
1101 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1102 } else if(!strncmp(name, "localfilesystem:", 16)) {
1103 ret = socket_local_client(name + 16,
1104 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
1107 } else if(!strncmp("dns:", name, 4)){
1108 char *n = strdup(name + 4);
1109 if(n == 0) return -1;
1110 ret = create_service_thread(dns_service, n);
1111 #else /* !SDB_HOST */
1112 }/* else if(!strncmp("dev:", name, 4)) {// tizen specific
1113 ret = unix_open(name + 4, O_RDWR);
1114 } else if(!strncmp(name, "framebuffer:", 12)) {
1115 ret = create_service_thread(framebuffer_service, 0);
1116 } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
1117 ret = create_service_thread(recover_service, (void*) atoi(name + 8));
1118 } else if (!strncmp(name, "jdwp:", 5)) {
1119 ret = create_jdwp_connection_fd(atoi(name+5));
1120 } else if (!strncmp(name, "log:", 4)) {
1121 ret = create_service_thread(log_service, get_log_file_path(name + 4));
1122 }*/ else if(!HOST && !strncmp(name, "shell:", 6)) {
1124 ret = create_subproc_thread(name + 6, 0, 0);
1126 ret = create_subproc_thread(NULL, 0, 0);
1128 } else if(!strncmp(name, "eshell:", 7)) {
1130 if (sscanf(name+7, "%d:%d", &lines, &columns) == 2) {
1131 ret = create_subproc_thread(NULL, lines, columns);
1133 } else if(!strncmp(name, "sync:", 5)) {
1134 //ret = create_service_thread(file_sync_service, NULL);
1135 ret = create_syncproc_thread();
1136 }/* else if(!strncmp(name, "remount:", 8)) {
1137 ret = create_service_thread(remount_service, NULL);
1138 } else if(!strncmp(name, "reboot:", 7)) {
1139 void* arg = strdup(name + 7);
1140 if(arg == 0) return -1;
1141 ret = create_service_thread(reboot_service, arg);
1142 } else if(!strncmp(name, "root:", 5)) {
1143 ret = create_service_thread(restart_root_service, NULL);
1144 } else if(!strncmp(name, "backup:", 7)) {
1145 char* arg = strdup(name+7);
1146 if (arg == NULL) return -1;
1147 ret = backup_service(BACKUP, arg);
1148 } else if(!strncmp(name, "restore:", 8)) {
1149 ret = backup_service(RESTORE, NULL);
1150 }*/ else if(!strncmp(name, "root:", 5)) {
1151 char* service_name = NULL;
1153 service_name = strdup(name+5);
1154 ret = create_service_thread(rootshell_service, (void *)(service_name));
1155 } else if(!strncmp(name, "cs:", 5)) {
1156 ret = create_service_thread(inoti_service, NULL);
1158 } else if(!strncmp(name, "sysinfo:", 8)){
1159 ret = create_service_thread(get_platforminfo, 0);
1160 } else if(!strncmp(name, "capability:", 11)){
1161 ret = create_service_thread(get_capability, 0);
1162 } else if(!strncmp(name, "boot:", 5)){
1163 if (is_emulator()) {
1164 ret = create_service_thread(get_boot, 0);
1166 } else if(!strncmp(name, "shellconf:", 10)){
1167 if(!strncmp(name+10, "syncwinsz:", 10)){
1168 ret = create_service_thread(sync_windowsize, (void *)name+20);
1170 } else if(!strncmp(name, "tzplatformenv:", 14)) {
1171 char* env_variable = NULL;
1172 env_variable = strdup(name+14);
1173 ret = create_service_thread(get_tzplatform_env, (void *)(env_variable));
1174 } else if(!strncmp(name, "appcmd:", 7)){
1175 ret = request_appcmd_to_plugin(name+7);
1179 if (close_on_exec(ret) < 0) {
1180 D("failed to close fd exec\n");
1188 transport_type transport;
1193 static void wait_for_state(int fd, void* cookie)
1195 struct state_info* sinfo = cookie;
1196 char* err = "unknown error";
1198 D("wait_for_state %d\n", sinfo->state);
1200 atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
1202 writex(fd, "OKAY", 4);
1204 sendfailmsg(fd, err);
1208 free(sinfo->serial);
1211 D("wait_for_state is done\n");
1216 asocket* host_service_to_socket(const char* name, const char *serial)
1218 if (!strcmp(name,"track-devices")) {
1219 return create_device_tracker();
1220 } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
1221 struct state_info* sinfo = malloc(sizeof(struct state_info));
1224 sinfo->serial = strdup(serial);
1226 sinfo->serial = NULL;
1228 name += strlen("wait-for-");
1230 if (!strncmp(name, "local", strlen("local"))) {
1231 sinfo->transport = kTransportLocal;
1232 sinfo->state = CS_DEVICE;
1233 } else if (!strncmp(name, "usb", strlen("usb"))) {
1234 sinfo->transport = kTransportUsb;
1235 sinfo->state = CS_DEVICE;
1236 } else if (!strncmp(name, "any", strlen("any"))) {
1237 sinfo->transport = kTransportAny;
1238 sinfo->state = CS_DEVICE;
1244 int fd = create_service_thread(wait_for_state, sinfo);
1245 return create_local_socket(fd);
1249 #endif /* SDB_HOST */