tizen 2.3.1 release
[framework/system/sdbd.git] / src / services.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <grp.h>
23
24 #include "sysdeps.h"
25
26 #define  TRACE_TAG  TRACE_SERVICES
27 #include "sdb.h"
28 #include "file_sync_service.h"
29
30 #if SDB_HOST
31 #  ifndef HAVE_WINSOCK
32 #    include <netinet/in.h>
33 #    include <netdb.h>
34 #    include <sys/ioctl.h>
35 #  endif
36 #else
37 #   include <sys/inotify.h>
38 #   include "sdktools.h"
39 #endif
40
41 #include "strutils.h"
42 #include <system_info_internal.h>
43 #include <vconf.h>
44 #include <limits.h>
45
46 typedef struct stinfo stinfo;
47
48 struct stinfo {
49     void (*func)(int fd, void *cookie);
50     int fd;
51     void *cookie;
52 };
53
54
55 void *service_bootstrap_func(void *x)
56 {
57     stinfo *sti = x;
58     sti->func(sti->fd, sti->cookie);
59     free(sti);
60     return 0;
61 }
62
63 #if SDB_HOST
64 SDB_MUTEX_DEFINE( dns_lock );
65
66 static void dns_service(int fd, void *cookie)
67 {
68     char *hostname = cookie;
69     struct hostent *hp;
70     unsigned zero = 0;
71
72     sdb_mutex_lock(&dns_lock);
73     hp = gethostbyname(hostname);
74     free(cookie);
75     if(hp == 0) {
76         writex(fd, &zero, 4);
77     } else {
78         writex(fd, hp->h_addr, 4);
79     }
80     sdb_mutex_unlock(&dns_lock);
81     sdb_close(fd);
82 }
83 #else
84
85 #if 0
86 extern int recovery_mode;
87
88 static void recover_service(int s, void *cookie)
89 {
90     unsigned char buf[4096];
91     unsigned count = (unsigned) cookie;
92     int fd;
93
94     fd = sdb_creat("/tmp/update", 0644);
95     if(fd < 0) {
96         sdb_close(s);
97         return;
98     }
99
100     while(count > 0) {
101         unsigned xfer = (count > 4096) ? 4096 : count;
102         if(readx(s, buf, xfer)) break;
103         if(writex(fd, buf, xfer)) break;
104         count -= xfer;
105     }
106
107     if(count == 0) {
108         writex(s, "OKAY", 4);
109     } else {
110         writex(s, "FAIL", 4);
111     }
112     sdb_close(fd);
113     sdb_close(s);
114
115     fd = sdb_creat("/tmp/update.begin", 0644);
116     sdb_close(fd);
117 }
118
119 void restart_root_service(int fd, void *cookie)
120 {
121     char buf[100];
122     char value[PROPERTY_VALUE_MAX];
123
124     if (getuid() == 0) {
125         snprintf(buf, sizeof(buf), "sdbd is already running as root\n");
126         writex(fd, buf, strlen(buf));
127         sdb_close(fd);
128     } else {
129         property_get("ro.debuggable", value, "");
130         if (strcmp(value, "1") != 0) {
131             snprintf(buf, sizeof(buf), "sdbd cannot run as root in production builds\n");
132             writex(fd, buf, strlen(buf));
133             sdb_close(fd);
134             return;
135         }
136
137         property_set("service.sdb.root", "1");
138         snprintf(buf, sizeof(buf), "restarting sdbd as root\n");
139         writex(fd, buf, strlen(buf));
140         sdb_close(fd);
141     }
142 }
143 #endif
144
145 void rootshell_service(int fd, void *cookie)
146 {
147     char buf[100];
148     char *mode = (char*) cookie;
149
150     if (!strcmp(mode, "on")) {
151         if (rootshell_mode == 1) {
152             //snprintf(buf, sizeof(buf), "Already changed to developer mode\n");
153             // do not show message
154         } else {
155             if (access("/bin/su", F_OK) == 0) {
156                 rootshell_mode = 1;
157                 //allows a permitted user to execute a command as the superuser
158                 snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n");
159             } else {
160                 snprintf(buf, sizeof(buf), "Permission denied\n");
161             }
162             writex(fd, buf, strlen(buf));
163         }
164     } else if (!strcmp(mode, "off")) {
165         if (rootshell_mode == 1) {
166             rootshell_mode = 0;
167             snprintf(buf, sizeof(buf), "Switched to 'developer' account mode\n");
168             writex(fd, buf, strlen(buf));
169         }
170     } else {
171         snprintf(buf, sizeof(buf), "Unknown command option\n");
172         writex(fd, buf, strlen(buf));
173     }
174     D("set rootshell to %s\n", rootshell_mode == 1 ? "root" : "developer");
175     free(mode);
176     sdb_close(fd);
177 }
178
179 void reboot_service(int fd, void *arg)
180 {
181 #if 0
182     char buf[100];
183     int pid, ret;
184
185     sync();
186
187     /* Attempt to unmount the SD card first.
188      * No need to bother checking for errors.
189      */
190     pid = fork();
191     if (pid == 0) {
192         /* ask vdc to unmount it */
193         // prevent: Use of untrusted string value (TAINTED_STRING)
194         execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount",
195                 getenv("EXTERNAL_STORAGE"), "force", NULL);
196     } else if (pid > 0) {
197         /* wait until vdc succeeds or fails */
198         waitpid(pid, &ret, 0);
199     }
200
201     ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
202     if (ret < 0) {
203         snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
204         writex(fd, buf, strlen(buf));
205     }
206     free(arg);
207     sdb_close(fd);
208 #endif
209 }
210
211 #if !SDB_HOST
212 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
213 #define BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )
214 #define CS_PATH     "/opt/usr/share/crash/report"
215
216 void inoti_service(int fd, void *arg)
217 {
218     int wd;
219     int ifd;
220     char buffer[BUF_LEN];
221
222     D( "inoti_service start\n");
223     ifd = inotify_init();
224
225     if ( ifd < 0 ) {
226         D( "inotify_init failed\n");
227         return;
228     }
229
230     wd = inotify_add_watch( ifd, CS_PATH, IN_CREATE);
231
232     for ( ; ; ) {
233         int length, i = 0;
234         length = sdb_read( ifd, buffer, BUF_LEN );
235
236         if ( length < 0 ) {
237             D( "inoti read failed\n");
238             goto done;
239         }
240         while (i >= 0 && i <= (length - EVENT_SIZE)) {
241             struct inotify_event *event = (struct inotify_event *) &buffer[i];
242             if (event->len) {
243                 if (event->mask & IN_CREATE) {
244                     if (!(event->mask & IN_ISDIR)) {
245                         char *cspath = NULL;
246                         int len = asprintf(&cspath, "%s/%s", CS_PATH,
247                                 event->name);
248                         D( "The file %s was created.\n", cspath);
249                         writex(fd, cspath, len);
250                         if (cspath != NULL) {
251                             free(cspath);
252                         }
253                     }
254                 }
255             }
256             if (i + EVENT_SIZE + event->len < event->len) { // in case of integer overflow
257                 break;
258             }
259             i += EVENT_SIZE + event->len;
260         }
261     }
262
263 done:
264     inotify_rm_watch( ifd, wd );
265     sdb_close(ifd);
266     sdb_close(fd);
267     D( "inoti_service end\n");
268 }
269 #endif
270 #endif
271
272 void rndis_config_service(int fd, void *cookie)
273 {
274     char buf[100];
275     int val = 0;
276     char* mode = (char*) cookie;
277
278     usb_mode = 0;
279     if (vconf_get_int(DEBUG_MODE_KEY, &val)) {
280         D("Failed to get debug mode\n");
281         sdb_close(fd);
282         free(mode);
283         return;
284     }
285     if (!strcmp(mode, "on")) {
286         if (val != 6) {
287             usb_mode = 6;
288             sdb_sleep_ms(500);
289             if (vconf_set_int(DEBUG_MODE_KEY, 6)) {
290                 D("Failed to set rndis %s\n", mode);
291                 snprintf(buf, sizeof(buf), "Failed to set rndis %s\n", mode);
292                 writex(fd, buf, strlen(buf));
293             }
294         }
295     } else if (!strcmp(mode, "off")) {
296         if (val != 2) {
297             usb_mode = 2;
298             sdb_sleep_ms(500);
299             if (vconf_set_int(DEBUG_MODE_KEY, 2)) {
300                 D("Failed to set rndis %s\n", mode);
301                 snprintf(buf, sizeof(buf), "Failed to set rndis %s\n", mode);
302                 writex(fd, buf, strlen(buf));
303             }
304         }
305     } else {
306         D("Unknown command option:(rndis %s)\n", mode);
307         snprintf(buf, sizeof(buf), "Unknown command option:(rndis %s)\n", mode);
308         writex(fd, buf, strlen(buf));
309     }
310     free(mode);
311     sdb_close(fd);
312 }
313
314 #if 0
315 static void echo_service(int fd, void *cookie)
316 {
317     char buf[4096];
318     int r;
319     char *p;
320     int c;
321
322     for(;;) {
323         r = read(fd, buf, 4096);
324         if(r == 0) goto done;
325         if(r < 0) {
326             if(errno == EINTR) continue;
327             else goto done;
328         }
329
330         c = r;
331         p = buf;
332         while(c > 0) {
333             r = write(fd, p, c);
334             if(r > 0) {
335                 c -= r;
336                 p += r;
337                 continue;
338             }
339             if((r < 0) && (errno == EINTR)) continue;
340             goto done;
341         }
342     }
343 done:
344     close(fd);
345 }
346 #endif
347
348 static int create_service_thread(void (*func)(int, void *), void *cookie)
349 {
350     stinfo *sti;
351     sdb_thread_t t;
352     int s[2];
353
354     if(sdb_socketpair(s)) {
355         D("cannot create service socket pair\n");
356         return -1;
357     }
358
359     sti = malloc(sizeof(stinfo));
360     if(sti == 0) fatal("cannot allocate stinfo");
361     sti->func = func;
362     sti->cookie = cookie;
363     sti->fd = s[1];
364
365     if(sdb_thread_create( &t, service_bootstrap_func, sti)){
366         free(sti);
367         sdb_close(s[0]);
368         sdb_close(s[1]);
369         D("cannot create service thread\n");
370         return -1;
371     }
372
373     D("service thread started, %d:%d\n",s[0], s[1]);
374     return s[0];
375 }
376
377 #if !SDB_HOST
378
379 static void redirect_and_exec(int pts, const char *cmd, const char *argv[], const char *envp[])
380 {
381     dup2(pts, 0);
382     dup2(pts, 1);
383     dup2(pts, 2);
384
385     sdb_close(pts);
386
387     execve(cmd, argv, envp);
388 }
389
390 static int create_subprocess(const char *cmd, pid_t *pid, const char *argv[], const char *envp[])
391 {
392     char *devname;
393     int ptm;
394
395     ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
396     if(ptm < 0){
397         D("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
398         return -1;
399     }
400     if (fcntl(ptm, F_SETFD, FD_CLOEXEC) < 0) {
401         D("[ cannot set cloexec to /dev/ptmx - %s ]\n",strerror(errno));
402     }
403
404     if(grantpt(ptm) || unlockpt(ptm) ||
405        ((devname = (char*) ptsname(ptm)) == 0)){
406         D("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
407         sdb_close(ptm);
408         return -1;
409     }
410
411     *pid = fork();
412     if(*pid < 0) {
413         D("- fork failed: %s -\n", strerror(errno));
414         sdb_close(ptm);
415         return -1;
416     }
417
418     if(*pid == 0){
419         int pts;
420
421         setsid();
422
423         pts = unix_open(devname, O_RDWR);
424         if(pts < 0) {
425             fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
426             exit(-1);
427         }
428
429         sdb_close(ptm);
430
431         // set OOM adjustment to zero
432         {
433             char text[64];
434             snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
435             int fd = sdb_open(text, O_WRONLY);
436             if (fd >= 0) {
437                 sdb_write(fd, "0", 1);
438                 sdb_close(fd);
439             } else {
440                // FIXME: not supposed to be here
441                D("sdb: unable to open %s due to %s\n", text, strerror(errno));
442             }
443         }
444
445         if (should_drop_privileges()) {
446             if (argv[2] != NULL && verify_root_commands(argv[2])) {
447                 // do nothing
448                 D("sdb: executes root commands!!:%s\n", argv[2]);
449             } else {
450                 set_developer_privileges();
451             }
452         }
453
454         redirect_and_exec(pts, cmd, argv, envp);
455         fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n",
456                 cmd, errno);
457         exit(-1);
458     } else {
459         // Don't set child's OOM adjustment to zero.
460         // Let the child do it itself, as sometimes the parent starts
461         // running before the child has a /proc/pid/oom_adj.
462         // """sdb: unable to open /proc/644/oom_adj""" seen in some logs.
463         return ptm;
464     }
465 }
466 #endif  /* !SDB_HOST */
467
468 #define SHELL_COMMAND "/bin/sh"
469 #define LOGIN_COMMAND "/bin/login"
470 #define SDK_USER      "developer"
471 #define SUPER_USER    "root"
472 #define LOGIN_CONFIG  "/etc/login.defs"
473
474 #if !SDB_HOST
475 static void subproc_waiter_service(int fd, void *cookie)
476 {
477     pid_t pid = (pid_t)cookie;
478
479     D("entered. fd=%d of pid=%d\n", fd, pid);
480     for (;;) {
481         int status;
482         pid_t p = waitpid(pid, &status, 0);
483         if (p == pid) {
484             D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
485
486             if (WIFEXITED(status)) {
487                 D("*** Exit code %d\n", WEXITSTATUS(status));
488                 break;
489             } else if (WIFSIGNALED(status)) {
490                 D("*** Killed by signal %d\n", WTERMSIG(status));
491                 break;
492             } else {
493                 D("*** Killed by unknown code %d\n", status);
494                 break;
495             }
496          }
497     }
498     D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
499     if (SHELL_EXIT_NOTIFY_FD >=0) {
500       int res;
501       res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
502       D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
503         SHELL_EXIT_NOTIFY_FD, pid, res, errno);
504     }
505 }
506
507 static void get_env(char *key, char **env)
508 {
509     FILE *fp;
510     char buf[1024];
511     int i;
512     char *s, *e, *value;
513
514     fp = fopen (LOGIN_CONFIG, "r");
515     if (NULL == fp) {
516         return;
517     }
518
519     while (fgets(buf, (int) sizeof (buf), fp) != NULL) {
520         s = buf;
521         e = buf + (strlen(buf) - 1);
522
523         while(*e == ' ' ||  *e == '\n' || *e == '\t') {
524             e--;
525         }
526         *(e+1) ='\0';
527
528         while(*s != '\0' && (*s == ' ' || *s == '\t' || *s == '\n')) {
529             s++;
530         }
531
532         if (*s == '#' || *s == '\0') {
533             continue;
534         }
535         value = s + strcspn(s, " \t");
536         *value++ = '\0';
537
538         if(!strcmp(buf, key)) {
539             *env = value;
540             break;
541         }
542     }
543
544     fclose(fp);
545 }
546
547 static int create_subproc_thread(const char *name, int lines, int columns)
548 {
549     stinfo *sti;
550     sdb_thread_t t;
551     int ret_fd;
552     pid_t pid;
553     char *value = NULL;
554     char lines_str[20] = {'\0',};
555     char columns_str[20] = {'\0',};
556
557     char *envp[] = {
558         "TERM=linux", /* without this, some programs based on screen can't work, e.g. top */
559         "DISPLAY=:0", /* without this, some programs based on without launchpad can't work */
560         NULL,
561         NULL,
562         NULL,
563         NULL,
564         NULL
565     };
566     if (should_drop_privileges()) {
567         envp[2] = "HOME=/home/developer";
568         get_env("ENV_PATH", &value);
569     } else {
570         get_env("ENV_SUPATH", &value);
571         envp[2] = "HOME=/root";
572     }
573     if (value != NULL) {
574         envp[3] = value;
575     }
576
577     D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]);
578
579     if (lines > 0 && columns > 0) {
580         snprintf(lines_str, sizeof(lines_str), "LINES=%d", lines);
581         snprintf(columns_str, sizeof(columns_str), "COLUMNS=%d", columns);
582         envp[4] = lines_str;
583         envp[5] = columns_str;
584         D("shell size env:%s,%s\n", envp[4], envp[5]);
585     }
586
587     if(name) { // in case of shell execution directly
588         char *args[] = {
589             SHELL_COMMAND,
590             "-c",
591             NULL,
592             "-l",
593             SUPER_USER,
594             NULL,
595         };
596         args[2] = name;
597
598         ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
599     } else { // in case of shell interactively
600         char *args[] = {
601                 SHELL_COMMAND,
602                 "-",
603                 NULL,
604         };
605         ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
606 #if 0   // FIXME: should call login command instead of /bin/sh
607         if (should_drop_privileges()) {
608             char *args[] = {
609                 SHELL_COMMAND,
610                 "-",
611                 NULL,
612             };
613             ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
614         } else {
615             char *args[] = {
616                 LOGIN_COMMAND,
617                 "-f",
618                 SUPER_USER,
619                 NULL,
620             };
621             ret_fd = create_subprocess(LOGIN_COMMAND, &pid, args, envp);
622         }
623 #endif
624     }
625     D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid);
626
627     if (ret_fd < 0) {
628         D("cannot create service thread\n");
629         return -1;
630     }
631     sti = malloc(sizeof(stinfo));
632     if(sti == 0) fatal("cannot allocate stinfo");
633     sti->func = subproc_waiter_service;
634     sti->cookie = (void*)pid;
635     sti->fd = ret_fd;
636
637     if(sdb_thread_create( &t, service_bootstrap_func, sti)){
638         free(sti);
639         sdb_close(ret_fd);
640         D("cannot create service thread\n");
641         return -1;
642     }
643
644     D("service thread started, fd=%d pid=%d\n",ret_fd, pid);
645     return ret_fd;
646 }
647
648 static int create_sync_subprocess(void (*func)(int, void *), void* cookie) {
649     stinfo *sti;
650     sdb_thread_t t;
651     int s[2];
652
653     if(sdb_socketpair(s)) {
654         D("cannot create service socket pair\n");
655         return -1;
656     }
657
658     pid_t pid = fork();
659
660     if (pid == 0) {
661         sdb_close(s[0]);
662         func(s[1], cookie);
663         exit(-1);
664     } else if (pid > 0) {
665         sdb_close(s[1]);
666         // FIXME: do not wait child process hear
667         //waitpid(pid, &ret, 0);
668     }
669     if (pid < 0) {
670         D("- fork failed: (errno:%d) -\n", errno);
671         sdb_close(s[0]);
672         sdb_close(s[1]);
673         D("cannot create sync service sub process\n");
674         return -1;
675     }
676
677     sti = malloc(sizeof(stinfo));
678     if(sti == 0) fatal("cannot allocate stinfo");
679     sti->func = subproc_waiter_service;
680     sti->cookie = (void*)pid;
681     sti->fd = s[0];
682
683     if(sdb_thread_create( &t, service_bootstrap_func, sti)){
684         free(sti);
685         sdb_close(s[0]);
686         sdb_close(s[1]);
687         printf("cannot create service monitor thread\n");
688         return -1;
689     }
690
691     D("service process started, fd=%d pid=%d\n",s[0], pid);
692     return s[0];
693 }
694
695 static int create_syncproc_thread()
696 {
697     int ret_fd;
698
699     ret_fd = create_sync_subprocess(file_sync_service, NULL);
700     // FIXME: file missing bug when root on mode
701     /*
702     if (should_drop_privileges()) {
703         ret_fd = create_sync_subprocess(file_sync_service, NULL);
704     } else {
705         ret_fd = create_service_thread(file_sync_service, NULL);
706     }
707     */
708
709     return ret_fd;
710 }
711
712 #endif
713
714 #define UNKNOWN "unknown"
715 #define INFOBUF_MAXLEN 64
716 #define INFO_VERSION "2.2.0"
717 typedef struct platform_info {
718
719     char platform_info_version[INFOBUF_MAXLEN];
720     char model_name[INFOBUF_MAXLEN]; // Emulator
721     char platform_name[INFOBUF_MAXLEN]; // Tizen
722     char platform_version[INFOBUF_MAXLEN]; // 2.2.1
723     char profile_name[INFOBUF_MAXLEN]; // 2.2.1
724 } pinfo;
725
726 static void get_platforminfo(int fd, void *cookie) {
727     pinfo sysinfo;
728
729     char *value = NULL;
730     s_strncpy(sysinfo.platform_info_version, INFO_VERSION, strlen(INFO_VERSION));
731
732     int r = system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &value);
733     if (r != SYSTEM_INFO_ERROR_NONE) {
734         s_strncpy(sysinfo.model_name, UNKNOWN, strlen(UNKNOWN));
735         D("fail to get system model:%d\n", errno);
736     } else {
737         s_strncpy(sysinfo.model_name, value, sizeof(sysinfo.model_name));
738         D("returns model_name:%s\n", value);
739         if (value != NULL) {
740             free(value);
741         }
742     }
743
744     r = system_info_get_value_string(SYSTEM_INFO_KEY_PLATFORM_NAME, &value);
745     if (r != SYSTEM_INFO_ERROR_NONE) {
746         s_strncpy(sysinfo.platform_name, UNKNOWN, strlen(UNKNOWN));
747         D("fail to get platform name:%d\n", errno);
748     } else {
749         s_strncpy(sysinfo.platform_name, value, sizeof(sysinfo.platform_name));
750         D("returns platform_name:%s\n", value);
751         if (value != NULL) {
752             free(value);
753         }
754
755     }
756
757     // FIXME: the result is different when using SYSTEM_INFO_KEY_TIZEN_VERSION_NAME
758     r = system_info_get_platform_string("tizen.org/feature/platform.version", &value);
759     if (r != SYSTEM_INFO_ERROR_NONE) {
760         s_strncpy(sysinfo.platform_version, UNKNOWN, strlen(UNKNOWN));
761         D("fail to get platform version:%d\n", errno);
762     } else {
763         s_strncpy(sysinfo.platform_version, value, sizeof(sysinfo.platform_version));
764         D("returns platform_version:%s\n", value);
765         if (value != NULL) {
766             free(value);
767         }
768     }
769
770     r = system_info_get_platform_string("tizen.org/feature/profile", &value);
771     if (r != SYSTEM_INFO_ERROR_NONE) {
772         s_strncpy(sysinfo.profile_name, UNKNOWN, strlen(UNKNOWN));
773         D("fail to get profile name:%d\n", errno);
774     } else {
775         s_strncpy(sysinfo.profile_name, value, sizeof(sysinfo.profile_name));
776         D("returns profile name:%s\n", value);
777         if (value != NULL) {
778             free(value);
779         }
780     }
781
782     writex(fd, &sysinfo, sizeof(pinfo));
783
784     sdb_close(fd);
785 }
786
787 int service_to_fd(const char *name)
788 {
789     int ret = -1;
790
791     if(!strncmp(name, "tcp:", 4)) {
792         int port = atoi(name + 4);
793         name = strchr(name + 4, ':');
794         if(name == 0) {
795             if (is_emulator()){
796                 ret = socket_ifr_client(port , SOCK_STREAM, "eth0");
797             } else {
798                 ret = socket_ifr_client(port , SOCK_STREAM, "usb0");
799                 if (ret < 0) {
800                     if (ifconfig(SDB_FORWARD_IFNAME, SDB_FORWARD_INTERNAL_IP, SDB_FORWARD_INTERNAL_MASK, 1) == 0) {
801                         ret = socket_ifr_client(port , SOCK_STREAM, SDB_FORWARD_IFNAME);
802                     }
803                 }
804             }
805             if (ret < 0) {
806                 ret = socket_loopback_client(port, SOCK_STREAM);
807             }
808             if (ret >= 0) {
809                 if (disable_tcp_nagle(ret) < 0) {
810                     D("failed to disable_tcp_nagle\n");
811                 }
812             }
813         } else {
814 #if SDB_HOST
815             sdb_mutex_lock(&dns_lock);
816             ret = socket_network_client(name + 1, port, SOCK_STREAM);
817             sdb_mutex_unlock(&dns_lock);
818 #else
819             return -1;
820 #endif
821         }
822 #ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
823     } else if(!strncmp(name, "local:", 6)) {
824         ret = socket_local_client(name + 6,
825                 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
826     } else if(!strncmp(name, "localreserved:", 14)) {
827         ret = socket_local_client(name + 14,
828                 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
829     } else if(!strncmp(name, "localabstract:", 14)) {
830         ret = socket_local_client(name + 14,
831                 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
832     } else if(!strncmp(name, "localfilesystem:", 16)) {
833         ret = socket_local_client(name + 16,
834                 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
835 #endif
836 #if SDB_HOST
837     } else if(!strncmp("dns:", name, 4)){
838         char *n = strdup(name + 4);
839         if(n == 0) return -1;
840         ret = create_service_thread(dns_service, n);
841 #else /* !SDB_HOST */
842     }/* else if(!strncmp("dev:", name, 4)) {// tizen specific
843         ret = unix_open(name + 4, O_RDWR);
844     } else if(!strncmp(name, "framebuffer:", 12)) {
845         ret = create_service_thread(framebuffer_service, 0);
846     } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
847         ret = create_service_thread(recover_service, (void*) atoi(name + 8));
848     } else if (!strncmp(name, "jdwp:", 5)) {
849         ret = create_jdwp_connection_fd(atoi(name+5));
850     } else if (!strncmp(name, "log:", 4)) {
851         ret = create_service_thread(log_service, get_log_file_path(name + 4));
852     }*/ else if(!HOST && !strncmp(name, "shell:", 6)) {
853         if(name[6]) {
854             ret = create_subproc_thread(name + 6, 0, 0);
855         } else {
856             ret = create_subproc_thread(NULL, 0, 0);
857         }
858     } else if(!strncmp(name, "eshell:", 7)) {
859         int lines, columns;
860         if (sscanf(name+7, "%d:%d", &lines, &columns) == 2) {
861             ret = create_subproc_thread(NULL, lines, columns);
862         }
863     } else if(!strncmp(name, "sync:", 5)) {
864         //ret = create_service_thread(file_sync_service, NULL);
865         ret = create_syncproc_thread();
866     }/*  else if(!strncmp(name, "remount:", 8)) {
867         ret = create_service_thread(remount_service, NULL);
868     } else if(!strncmp(name, "reboot:", 7)) {
869         void* arg = strdup(name + 7);
870         if(arg == 0) return -1;
871         ret = create_service_thread(reboot_service, arg);
872     } else if(!strncmp(name, "root:", 5)) {
873         ret = create_service_thread(restart_root_service, NULL);
874     } else if(!strncmp(name, "backup:", 7)) {
875         char* arg = strdup(name+7);
876         if (arg == NULL) return -1;
877         ret = backup_service(BACKUP, arg);
878     } else if(!strncmp(name, "restore:", 8)) {
879         ret = backup_service(RESTORE, NULL);
880     }*/ else if(!strncmp(name, "root:", 5)) {
881         char* service_name = NULL;
882
883         service_name = strdup(name+5);
884         ret = create_service_thread(rootshell_service, (void *)(service_name));
885     } else if(!strncmp(name, "cs:", 5)) {
886         ret = create_service_thread(inoti_service, NULL);
887 #endif
888     } else if(!strncmp(name, "sysinfo:", 8)){
889         ret = create_service_thread(get_platforminfo, 0);
890     } else if(!strncmp(name, "rndis:", 6)){
891         char *service_name = NULL;
892
893         service_name = strdup(name+6);
894         ret = create_service_thread(rndis_config_service, (void *)(service_name));
895     }
896     if (ret >= 0) {
897         if (close_on_exec(ret) < 0) {
898             D("failed to close fd exec\n");
899         }
900     }
901     return ret;
902 }
903
904 #if SDB_HOST
905 struct state_info {
906     transport_type transport;
907     char* serial;
908     int state;
909 };
910
911 static void wait_for_state(int fd, void* cookie)
912 {
913     struct state_info* sinfo = cookie;
914     char* err = "unknown error";
915
916     D("wait_for_state %d\n", sinfo->state);
917
918     atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
919     if(t != 0) {
920         writex(fd, "OKAY", 4);
921     } else {
922         sendfailmsg(fd, err);
923     }
924
925     if (sinfo->serial)
926         free(sinfo->serial);
927     free(sinfo);
928     sdb_close(fd);
929     D("wait_for_state is done\n");
930 }
931 #endif
932
933 #if SDB_HOST
934 asocket*  host_service_to_socket(const char*  name, const char *serial)
935 {
936     if (!strcmp(name,"track-devices")) {
937         return create_device_tracker();
938     } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
939         struct state_info* sinfo = malloc(sizeof(struct state_info));
940
941         if (serial)
942             sinfo->serial = strdup(serial);
943         else
944             sinfo->serial = NULL;
945
946         name += strlen("wait-for-");
947
948         if (!strncmp(name, "local", strlen("local"))) {
949             sinfo->transport = kTransportLocal;
950             sinfo->state = CS_DEVICE;
951         } else if (!strncmp(name, "usb", strlen("usb"))) {
952             sinfo->transport = kTransportUsb;
953             sinfo->state = CS_DEVICE;
954         } else if (!strncmp(name, "any", strlen("any"))) {
955             sinfo->transport = kTransportAny;
956             sinfo->state = CS_DEVICE;
957         } else {
958             free(sinfo);
959             return NULL;
960         }
961
962         int fd = create_service_thread(wait_for_state, sinfo);
963         return create_local_socket(fd);
964     }
965     return NULL;
966 }
967 #endif /* SDB_HOST */