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
28 #include "file_sync_service.h"
32 # include <netinet/in.h>
34 # include <sys/ioctl.h>
37 # include <sys/inotify.h>
38 # include "sdktools.h"
43 #include <system_info.h>
44 #include <tzplatform_config.h>
50 #include <sys/ioctl.h>
52 typedef struct stinfo stinfo;
55 void (*func)(int fd, void *cookie);
61 void *service_bootstrap_func(void *x)
64 sti->func(sti->fd, sti->cookie);
70 SDB_MUTEX_DEFINE( dns_lock );
72 static void dns_service(int fd, void *cookie)
74 char *hostname = cookie;
78 sdb_mutex_lock(&dns_lock);
79 hp = gethostbyname(hostname);
84 writex(fd, hp->h_addr, 4);
86 sdb_mutex_unlock(&dns_lock);
91 static int is_support_interactive_shell()
93 return (!strncmp(g_capabilities.intershell_support, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED)));
97 extern int recovery_mode;
99 static void recover_service(int s, void *cookie)
101 unsigned char buf[4096];
102 unsigned count = (unsigned) cookie;
105 fd = sdb_creat("/tmp/update", 0644);
112 unsigned xfer = (count > 4096) ? 4096 : count;
113 if(readx(s, buf, xfer)) break;
114 if(writex(fd, buf, xfer)) break;
119 writex(s, "OKAY", 4);
121 writex(s, "FAIL", 4);
126 fd = sdb_creat("/tmp/update.begin", 0644);
130 void restart_root_service(int fd, void *cookie)
133 char value[PROPERTY_VALUE_MAX];
136 snprintf(buf, sizeof(buf), "sdbd is already running as root\n");
137 writex(fd, buf, strlen(buf));
140 property_get("ro.debuggable", value, "");
141 if (strcmp(value, "1") != 0) {
142 snprintf(buf, sizeof(buf), "sdbd cannot run as root in production builds\n");
143 writex(fd, buf, strlen(buf));
148 property_set("service.sdb.root", "1");
149 snprintf(buf, sizeof(buf), "restarting sdbd as root\n");
150 writex(fd, buf, strlen(buf));
156 void restart_tcp_service(int fd, void *cookie)
159 char value[PROPERTY_VALUE_MAX];
160 int port = (int)cookie;
163 snprintf(buf, sizeof(buf), "invalid port\n");
164 writex(fd, buf, strlen(buf));
169 snprintf(value, sizeof(value), "%d", port);
170 property_set("service.sdb.tcp.port", value);
171 snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
172 writex(fd, buf, strlen(buf));
176 static int is_support_rootonoff()
178 return (!strncmp(g_capabilities.rootonoff_support, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED)));
181 void rootshell_service(int fd, void *cookie)
184 char *mode = (char*) cookie;
186 if (!strcmp(mode, "on")) {
188 if (rootshell_mode == 1) {
189 //snprintf(buf, sizeof(buf), "Already changed to sdk user mode\n");
190 // do not show message
192 if (is_support_rootonoff()) {
194 //allows a permitted user to execute a command as the superuser
195 snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n");
197 snprintf(buf, sizeof(buf), "Permission denied\n");
199 writex(fd, buf, strlen(buf));
202 D("need root permission for root shell: %d\n", getuid());
204 snprintf(buf, sizeof(buf), "Permission denied\n");
205 writex(fd, buf, strlen(buf));
207 } else if (!strcmp(mode, "off")) {
208 if (rootshell_mode == 1) {
210 snprintf(buf, sizeof(buf), "Switched to 'sdk user' account mode\n");
211 writex(fd, buf, strlen(buf));
214 snprintf(buf, sizeof(buf), "Unknown command option : %s\n", mode);
215 writex(fd, buf, strlen(buf));
217 D("set rootshell to %s\n", rootshell_mode == 1 ? "root" : SDK_USER_NAME);
222 void restart_usb_service(int fd, void *cookie)
226 property_set("service.sdb.tcp.port", "0");
227 snprintf(buf, sizeof(buf), "restarting in USB mode\n");
228 writex(fd, buf, strlen(buf));
232 void reboot_service(int fd, void *arg)
240 /* Attempt to unmount the SD card first.
241 * No need to bother checking for errors.
245 /* ask vdc to unmount it */
246 // prevent: Use of untrusted string value (TAINTED_STRING)
247 execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount",
248 getenv("EXTERNAL_STORAGE"), "force", NULL);
249 } else if (pid > 0) {
250 /* wait until vdc succeeds or fails */
251 waitpid(pid, &ret, 0);
254 ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
256 snprintf(buf, sizeof(buf), "reboot failed: %s errno:%d\n", errno);
257 writex(fd, buf, strlen(buf));
265 #define EVENT_SIZE ( sizeof (struct inotify_event) )
266 #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
267 #define CS_PATH tzplatform_mkpath(TZ_USER_SHARE,"crash/report")
269 void inoti_service(int fd, void *arg)
273 char buffer[BUF_LEN];
275 D( "inoti_service start\n");
276 ifd = inotify_init();
279 D( "inotify_init failed\n");
283 wd = inotify_add_watch( ifd, CS_PATH, IN_CREATE);
287 length = sdb_read( ifd, buffer, BUF_LEN );
290 D( "inoti read failed\n");
293 while (i >= 0 && i <= (length - EVENT_SIZE)) {
294 struct inotify_event *event = (struct inotify_event *) &buffer[i];
296 if (event->mask & IN_CREATE) {
297 if (!(event->mask & IN_ISDIR)) {
299 int len = asprintf(&cspath, "%s/%s", CS_PATH,
301 D( "The file %s was created.\n", cspath);
302 writex(fd, cspath, len);
303 if (cspath != NULL) {
309 if (i + EVENT_SIZE + event->len < event->len) { // in case of integer overflow
312 i += EVENT_SIZE + event->len;
317 inotify_rm_watch( ifd, wd );
320 D( "inoti_service end\n");
326 static void echo_service(int fd, void *cookie)
334 r = read(fd, buf, 4096);
335 if(r == 0) goto done;
337 if(errno == EINTR) continue;
350 if((r < 0) && (errno == EINTR)) continue;
359 static int create_service_thread(void (*func)(int, void *), void *cookie)
365 if(sdb_socketpair(s)) {
366 D("cannot create service socket pair\n");
370 sti = malloc(sizeof(stinfo));
371 if(sti == 0) fatal("cannot allocate stinfo");
373 sti->cookie = cookie;
376 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
380 D("cannot create service thread\n");
384 D("service thread started, %d:%d\n",s[0], s[1]);
390 static void redirect_and_exec(int pts, const char *cmd, const char *argv[], const char *envp[])
398 execve(cmd, argv, envp);
401 static int create_subprocess(const char *cmd, pid_t *pid, const char *argv[], const char *envp[])
406 ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
408 D("[ cannot open /dev/ptmx - errno:%d ]\n",errno);
411 if (fcntl(ptm, F_SETFD, FD_CLOEXEC) < 0) {
412 D("[ cannot set cloexec to /dev/ptmx - errno:%d ]\n",errno);
415 if(grantpt(ptm) || unlockpt(ptm) ||
416 ptsname_r(ptm, devname, sizeof(devname)) != 0 ){
417 D("[ trouble with /dev/ptmx - errno:%d ]\n", errno);
424 D("- fork failed: errno:%d -\n", errno);
434 pts = unix_open(devname, O_RDWR);
436 fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
442 // set OOM adjustment to zero
445 //snprintf(text, sizeof text, "/proc/%d/oom_score_adj", getpid());
446 snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
447 int fd = sdb_open(text, O_WRONLY);
449 sdb_write(fd, "0", 1);
452 // FIXME: not supposed to be here
453 D("sdb: unable to open %s due to errno:%d\n", text, errno);
457 if (should_drop_privileges()) {
458 if (argv[2] != NULL && getuid() == 0 && request_plugin_verification(SDBD_CMD_VERIFY_ROOTCMD, argv[2])) {
460 D("sdb: executes root commands!!:%s\n", argv[2]);
462 set_sdk_user_privileges();
465 redirect_and_exec(pts, cmd, argv, envp);
466 fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n",
470 // Don't set child's OOM adjustment to zero.
471 // Let the child do it itself, as sometimes the parent starts
472 // running before the child has a /proc/pid/oom_adj.
473 // """sdb: unable to open /proc/644/oom_adj""" seen in some logs.
477 #endif /* !SDB_HOST */
479 #define SHELL_COMMAND "/bin/sh"
480 #define LOGIN_COMMAND "/bin/login"
481 #define SUPER_USER "root"
482 #define LOGIN_CONFIG "/etc/login.defs"
485 static void subproc_waiter_service(int fd, void *cookie)
487 pid_t pid = (pid_t)cookie;
489 D("entered. fd=%d of pid=%d\n", fd, pid);
492 pid_t p = waitpid(pid, &status, 0);
494 D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
495 if (WIFEXITED(status)) {
496 D("*** Exit code %d\n", WEXITSTATUS(status));
498 } else if (WIFSIGNALED(status)) {
499 D("*** Killed by signal %d\n", WTERMSIG(status));
502 D("*** Killed by unknown code %d\n", status);
507 D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
508 if (SHELL_EXIT_NOTIFY_FD >=0) {
510 res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
511 D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
512 SHELL_EXIT_NOTIFY_FD, pid, res, errno);
516 static void get_env(char *key, char **env)
523 fp = fopen (LOGIN_CONFIG, "r");
528 while (fgets(buf, (int) sizeof (buf), fp) != NULL) {
530 e = buf + (strlen(buf) - 1);
533 while(*e == ' ' || *e == '\n' || *e == '\t') {
538 while(*s != '\0' && (*s == ' ' || *s == '\t' || *s == '\n')) {
542 // skip comment or null string
543 if (*s == '#' || *s == '\0') {
546 value = s + strcspn(s, " \t");
549 if(!strcmp(buf, key)) {
550 *env = strdup(value);
558 static int create_subproc_thread(const char *name, int lines, int columns)
565 char *trim_value = NULL;
567 memset(path, 0, sizeof(path));
570 "TERM=linux", /* without this, some programs based on screen can't work, e.g. top */
571 "DISPLAY=:0", /* without this, some programs based on without launchpad can't work */
579 if (should_drop_privileges()) {
580 if (g_sdk_home_dir_env) {
581 envp[2] = g_sdk_home_dir_env;
583 envp[2] = "HOME=/home/owner";
585 get_env("ENV_PATH", &value);
587 get_env("ENV_SUPATH", &value);
589 get_env("ENV_ROOTPATH", &value);
591 envp[2] = "HOME=/root";
594 trim_value = str_trim(value);
595 if (trim_value != NULL) {
596 // if string is not including 'PATH=', append it.
597 if (strncmp(trim_value, "PATH", 4)) {
598 snprintf(path, sizeof(path), "PATH=%s", trim_value);
600 snprintf(path, sizeof(path), "%s", trim_value);
604 snprintf(path, sizeof(path), "%s", value);
610 D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]);
612 if(name) { // in case of shell execution directly
613 // Check the shell command validation.
614 if (!request_plugin_verification(SDBD_CMD_VERIFY_SHELLCMD, name)) {
615 D("This shell command is invalid. (%s)\n", name);
619 // Convert the shell command.
620 char *new_cmd = NULL;
621 new_cmd = malloc(SDBD_SHELL_CMD_MAX);
622 if(new_cmd == NULL) {
623 D("Cannot allocate the shell commnad buffer.");
627 memset(new_cmd, 0, SDBD_SHELL_CMD_MAX);
628 if(!request_plugin_cmd(SDBD_CMD_CONV_SHELLCMD, name, new_cmd, SDBD_SHELL_CMD_MAX)) {
629 D("Failed to convert the shell command. (%s)\n", name);
634 D("converted cmd : %s\n", new_cmd);
644 ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
646 } else { // in case of shell interactively
647 // Check the capability for interactive shell support.
648 if (!is_support_interactive_shell()) {
649 D("This platform dose NOT support the interactive shell\n");
658 ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
659 #if 0 // FIXME: should call login command instead of /bin/sh
660 if (should_drop_privileges()) {
666 ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
674 ret_fd = create_subprocess(LOGIN_COMMAND, &pid, args, envp);
678 D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid);
681 D("cannot create service thread\n");
685 if (lines > 0 && columns > 0) {
686 D("shell size lines=%d, columns=%d\n", lines, columns);
687 struct winsize win_sz;
688 win_sz.ws_row = lines;
689 win_sz.ws_col = columns;
691 if (ioctl(ret_fd, TIOCSWINSZ, &win_sz) < 0) {
692 D("failed to sync window size.\n");
696 sti = malloc(sizeof(stinfo));
697 if(sti == 0) fatal("cannot allocate stinfo");
698 sti->func = subproc_waiter_service;
699 sti->cookie = (void*)pid;
702 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
705 D("cannot create service thread\n");
709 D("service thread started, fd=%d pid=%d\n",ret_fd, pid);
713 static int create_sync_subprocess(void (*func)(int, void *), void* cookie) {
718 if(sdb_socketpair(s)) {
719 D("cannot create service socket pair\n");
729 } else if (pid > 0) {
731 // FIXME: do not wait child process hear
732 //waitpid(pid, &ret, 0);
735 D("- fork failed: errno:%d -\n", errno);
738 D("cannot create sync service sub process\n");
742 sti = malloc(sizeof(stinfo));
743 if(sti == 0) fatal("cannot allocate stinfo");
744 sti->func = subproc_waiter_service;
745 sti->cookie = (void*)pid;
748 if(sdb_thread_create( &t, service_bootstrap_func, sti)){
752 printf("cannot create service monitor thread\n");
756 D("service process started, fd=%d pid=%d\n",s[0], pid);
760 static int create_syncproc_thread()
764 ret_fd = create_sync_subprocess(file_sync_service, NULL);
765 // FIXME: file missing bug when root on mode
767 if (should_drop_privileges()) {
768 ret_fd = create_sync_subprocess(file_sync_service, NULL);
770 ret_fd = create_service_thread(file_sync_service, NULL);
779 static void get_platforminfo(int fd, void *cookie) {
783 s_strncpy(sysinfo.platform_info_version, INFO_VERSION, strlen(INFO_VERSION));
785 int r = system_info_get_platform_string("http://tizen.org/system/model_name", &value);
786 if (r != SYSTEM_INFO_ERROR_NONE) {
787 s_strncpy(sysinfo.model_name, UNKNOWN, strlen(UNKNOWN));
788 D("fail to get system model:%d\n", errno);
790 s_strncpy(sysinfo.model_name, value, sizeof(sysinfo.model_name));
791 D("returns model_name:%s\n", value);
797 r = system_info_get_platform_string("http://tizen.org/system/platform.name", &value);
798 if (r != SYSTEM_INFO_ERROR_NONE) {
799 s_strncpy(sysinfo.platform_name, UNKNOWN, strlen(UNKNOWN));
800 D("fail to get platform name:%d\n", errno);
802 s_strncpy(sysinfo.platform_name, value, sizeof(sysinfo.platform_name));
803 D("returns platform_name:%s\n", value);
810 // FIXME: the result is different when using SYSTEM_INFO_KEY_TIZEN_VERSION_NAME
811 r = system_info_get_platform_string("tizen.org/feature/platform.version", &value);
812 if (r != SYSTEM_INFO_ERROR_NONE) {
813 s_strncpy(sysinfo.platform_version, UNKNOWN, strlen(UNKNOWN));
814 D("fail to get platform version:%d\n", errno);
816 s_strncpy(sysinfo.platform_version, value, sizeof(sysinfo.platform_version));
817 D("returns platform_version:%s\n", value);
823 r = system_info_get_platform_string("tizen.org/feature/profile", &value);
824 if (r != SYSTEM_INFO_ERROR_NONE) {
825 s_strncpy(sysinfo.profile_name, UNKNOWN, strlen(UNKNOWN));
826 D("fail to get profile name:%d\n", errno);
828 s_strncpy(sysinfo.profile_name, value, sizeof(sysinfo.profile_name));
829 D("returns profile name:%s\n", value);
835 writex(fd, &sysinfo, sizeof(pinfo));
840 static int put_key_value_string(char* buf, int offset, int buf_size, char* key, char* value) {
842 if ((len = snprintf(buf+offset, buf_size-offset, "%s:%s\n", key, value)) > 0) {
848 static void get_capability(int fd, void *cookie) {
849 char cap_buffer[CAPBUF_SIZE] = {0,};
852 // Secure protocol support
853 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
854 "secure_protocol", g_capabilities.secure_protocol);
856 // Interactive shell support
857 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
858 "intershell_support", g_capabilities.intershell_support);
860 // File push/pull support
861 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
862 "filesync_support", g_capabilities.filesync_support);
864 // USB protocol support
865 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
866 "usbproto_support", g_capabilities.usbproto_support);
868 // Socket protocol support
869 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
870 "sockproto_support", g_capabilities.sockproto_support);
872 // Root command support
873 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
874 "rootonoff_support", g_capabilities.rootonoff_support);
877 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
878 "zone_support", g_capabilities.zone_support);
880 // Multi-User support
881 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
882 "multiuser_support", g_capabilities.multiuser_support);
884 // CPU Architecture of model
885 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
886 "cpu_arch", g_capabilities.cpu_arch);
889 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
890 "profile_name", g_capabilities.profile_name);
893 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
894 "vendor_name", g_capabilities.vendor_name);
897 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
898 "platform_version", g_capabilities.platform_version);
901 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
902 "product_version", g_capabilities.product_version);
905 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
906 "sdbd_version", g_capabilities.sdbd_version);
908 // Sdbd plugin version
909 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
910 "sdbd_plugin_version", g_capabilities.sdbd_plugin_version);
912 // Window size synchronization support
913 offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE,
914 "syncwinsz_support", g_capabilities.syncwinsz_support);
917 offset++; // for '\0' character
919 writex(fd, &offset, sizeof(uint16_t));
920 writex(fd, cap_buffer, offset);
925 static void sync_windowsize(int fd, void *cookie) {
926 int id, lines, columns;
927 char *size_info = cookie;
930 if (sscanf(size_info, "%d:%d:%d", &id, &lines, &columns) == 3) {
931 D("window size information: id=%d, lines=%d, columns=%d\n", id, lines, columns);
933 if((s = find_local_socket(id))) {
934 struct winsize win_sz;
935 win_sz.ws_row = lines;
936 win_sz.ws_col = columns;
938 if (ioctl(s->fd, TIOCSWINSZ, &win_sz) < 0) {
939 D("failed to sync window size.\n");
942 D("success to sync window size.\n");
946 const unsigned COMMAND_TIMEOUT = 10000;
947 void get_boot(int fd, void *cookie) {
948 char buf[2] = { 0, };
949 char *mode = (char*) cookie;
952 while (time < COMMAND_TIMEOUT) {
953 if (booting_done == 1) {
954 D("get_boot:platform booting is done\n");
955 snprintf(buf, sizeof(buf), "%s", "1");
958 D("get_boot:platform booting is in progress\n");
959 sdb_sleep_ms(interval);
962 writex(fd, buf, strlen(buf));
966 int service_to_fd(const char *name)
970 if(!strncmp(name, "tcp:", 4)) {
971 int port = atoi(name + 4);
972 name = strchr(name + 4, ':');
975 ret = socket_ifr_client(port , SOCK_STREAM, "eth0");
977 ret = socket_ifr_client(port , SOCK_STREAM, "usb0");
979 if (ifconfig(SDB_FORWARD_IFNAME, SDB_FORWARD_INTERNAL_IP, SDB_FORWARD_INTERNAL_MASK, 1) == 0) {
980 ret = socket_ifr_client(port , SOCK_STREAM, SDB_FORWARD_IFNAME);
985 ret = socket_loopback_client(port, SOCK_STREAM);
988 disable_tcp_nagle(ret);
992 sdb_mutex_lock(&dns_lock);
993 ret = socket_network_client(name + 1, port, SOCK_STREAM);
994 sdb_mutex_unlock(&dns_lock);
999 #ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */
1000 } else if(!strncmp(name, "local:", 6)) {
1001 ret = socket_local_client(name + 6,
1002 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
1003 } else if(!strncmp(name, "localreserved:", 14)) {
1004 ret = socket_local_client(name + 14,
1005 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
1006 } else if(!strncmp(name, "localabstract:", 14)) {
1007 ret = socket_local_client(name + 14,
1008 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1009 } else if(!strncmp(name, "localfilesystem:", 16)) {
1010 ret = socket_local_client(name + 16,
1011 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
1014 } else if(!strncmp("dns:", name, 4)){
1015 char *n = strdup(name + 4);
1016 if(n == 0) return -1;
1017 ret = create_service_thread(dns_service, n);
1018 #else /* !SDB_HOST */
1019 }/* else if(!strncmp("dev:", name, 4)) {// tizen specific
1020 ret = unix_open(name + 4, O_RDWR);
1021 } else if(!strncmp(name, "framebuffer:", 12)) {
1022 ret = create_service_thread(framebuffer_service, 0);
1023 } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
1024 ret = create_service_thread(recover_service, (void*) atoi(name + 8));
1025 } else if (!strncmp(name, "jdwp:", 5)) {
1026 ret = create_jdwp_connection_fd(atoi(name+5));
1027 } else if (!strncmp(name, "log:", 4)) {
1028 ret = create_service_thread(log_service, get_log_file_path(name + 4));
1029 }*/ else if(!HOST && !strncmp(name, "shell:", 6)) {
1031 ret = create_subproc_thread(name + 6, 0, 0);
1033 ret = create_subproc_thread(NULL, 0, 0);
1035 } else if(!strncmp(name, "eshell:", 7)) {
1037 if (sscanf(name+7, "%d:%d", &lines, &columns) == 2) {
1038 ret = create_subproc_thread(NULL, lines, columns);
1040 } else if(!strncmp(name, "sync:", 5)) {
1041 //ret = create_service_thread(file_sync_service, NULL);
1042 ret = create_syncproc_thread();
1043 }/* else if(!strncmp(name, "remount:", 8)) {
1044 ret = create_service_thread(remount_service, NULL);
1045 } else if(!strncmp(name, "reboot:", 7)) {
1046 void* arg = strdup(name + 7);
1047 if(arg == 0) return -1;
1048 ret = create_service_thread(reboot_service, arg);
1049 } else if(!strncmp(name, "root:", 5)) {
1050 ret = create_service_thread(restart_root_service, NULL);
1051 } else if(!strncmp(name, "backup:", 7)) {
1052 char* arg = strdup(name+7);
1053 if (arg == NULL) return -1;
1054 ret = backup_service(BACKUP, arg);
1055 } else if(!strncmp(name, "restore:", 8)) {
1056 ret = backup_service(RESTORE, NULL);
1057 }*/ else if(!strncmp(name, "root:", 5)) {
1058 char* service_name = NULL;
1060 service_name = strdup(name+5);
1061 ret = create_service_thread(rootshell_service, (void *)(service_name));
1062 } else if(!strncmp(name, "cs:", 5)) {
1063 ret = create_service_thread(inoti_service, NULL);
1065 } else if(!strncmp(name, "sysinfo:", 8)){
1066 ret = create_service_thread(get_platforminfo, 0);
1067 } else if(!strncmp(name, "capability:", 11)){
1068 ret = create_service_thread(get_capability, 0);
1069 } else if(!strncmp(name, "boot:", 5)){
1070 if (is_emulator()) {
1071 ret = create_service_thread(get_boot, 0);
1073 } else if(!strncmp(name, "shellconf:", 10)){
1074 if(!strncmp(name+10, "syncwinsz:", 10)){
1075 ret = create_service_thread(sync_windowsize, name+20);
1080 if (close_on_exec(ret) < 0) {
1081 D("failed to close fd exec\n");
1089 transport_type transport;
1094 static void wait_for_state(int fd, void* cookie)
1096 struct state_info* sinfo = cookie;
1097 char* err = "unknown error";
1099 D("wait_for_state %d\n", sinfo->state);
1101 atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
1103 writex(fd, "OKAY", 4);
1105 sendfailmsg(fd, err);
1109 free(sinfo->serial);
1112 D("wait_for_state is done\n");
1117 asocket* host_service_to_socket(const char* name, const char *serial)
1119 if (!strcmp(name,"track-devices")) {
1120 return create_device_tracker();
1121 } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
1122 struct state_info* sinfo = malloc(sizeof(struct state_info));
1125 sinfo->serial = strdup(serial);
1127 sinfo->serial = NULL;
1129 name += strlen("wait-for-");
1131 if (!strncmp(name, "local", strlen("local"))) {
1132 sinfo->transport = kTransportLocal;
1133 sinfo->state = CS_DEVICE;
1134 } else if (!strncmp(name, "usb", strlen("usb"))) {
1135 sinfo->transport = kTransportUsb;
1136 sinfo->state = CS_DEVICE;
1137 } else if (!strncmp(name, "any", strlen("any"))) {
1138 sinfo->transport = kTransportAny;
1139 sinfo->state = CS_DEVICE;
1145 int fd = create_service_thread(wait_for_state, sinfo);
1146 return create_local_socket(fd);
1150 #endif /* SDB_HOST */