Svace issues fixes
[sdk/target/sdbd.git] / src / sdb.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 //#define  TRACE_TAG   TRACE_SDB
18 #define LOG_TAG "SDBD_TRACE_SDB"
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <stdarg.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <time.h>
27 #include <sys/time.h>
28 #include <signal.h>
29 #include <grp.h>
30 #include <pwd.h>
31 #include <netdb.h>
32 #include <tzplatform_config.h>
33 #include <pthread.h>
34 #include <dlfcn.h>
35 #include <sys/smack.h>
36
37 #include "sysdeps.h"
38 #include "log.h"
39 #include "sdb.h"
40 #include "strutils.h"
41 #include "commandline_sdbd.h"
42 #include "utils.h"
43 #include "sdktools.h"
44 #include "plugin.h"
45 #include "sdbd_plugin.h"
46 #include "sdb_systemd.h"
47
48 #ifdef SUPPORT_ENCRYPT
49 #include "plugin_encrypt.h"
50 #endif
51
52 #include <linux/prctl.h>
53 #define SDB_PIDPATH "/tmp/.sdbd.pid"
54 #include <system_info.h>
55 #include <vconf.h>
56 #include <glib.h>
57
58 #define PROC_CMDLINE_PATH "/proc/cmdline"
59 #define USB_SERIAL_PATH "/sys/class/usb_mode/usb0/iSerial"
60 #define APPID2PID_PATH  "/usr/bin/appid2pid"
61
62 #include <sys/ioctl.h>
63 #include <net/if.h>
64 #include <netinet/in.h>
65 #include <arpa/inet.h>
66 #define GUEST_IP_INTERFACE "eth0"
67
68 SDB_MUTEX_DEFINE(zone_check_lock);
69 #if SDB_TRACE
70 SDB_MUTEX_DEFINE( D_lock );
71 #endif
72
73 #define SDB_LOGCONF_PATH "/tmp/.sdbdlog.conf"
74
75 int HOST = 0;
76
77 // sdk user
78 uid_t g_sdk_user_id;
79 gid_t g_sdk_group_id;
80 char* g_sdk_home_dir = NULL;
81 char* g_sdk_home_dir_env = NULL;
82 pcap g_capabilities;
83 int rootshell_mode; // 0: sdk user, 1: root
84 int booting_done; // 0: platform booting is in progess 1: platform booting is done
85
86 // root user
87 uid_t g_root_user_id;
88 gid_t g_root_group_id;
89 char* g_root_home_dir = NULL;
90 char* g_root_home_dir_env = NULL;
91
92 struct group_info
93 {
94     const char *name;
95     gid_t gid;
96 };
97 struct group_info g_default_groups[] = {
98     {"priv_externalstorage", -1},
99     {"priv_externalstorage_appdata", -1},
100     {"priv_mediastorage", -1},
101     {"log", -1},
102     {NULL, -1}
103 };
104
105 #define SDB_DEFAULT_GROUPS_CNT  ((sizeof(g_default_groups)/sizeof(g_default_groups[0]))-1)
106 #define BUF_SIZE 4096
107
108 int is_init_sdk_userinfo = 0;
109 int is_pwlocked = 0;    // 0 if unlocked, 1 otherwise
110
111 SdbdCommandlineArgs sdbd_commandline_args;
112
113 static int is_support_usbproto();
114 static int is_support_sockproto();
115
116 void (*usb_init)() = NULL;
117 void (*usb_cleanup)() = NULL;
118 int (*usb_write)(usb_handle *h, const void *data, int len) = NULL;
119 int (*usb_read)(usb_handle *h, void *data, size_t  len) = NULL;
120 int (*usb_close)(usb_handle *h) = NULL;
121 void (*usb_kick)(usb_handle *h) = NULL;
122
123 int g_is_emulator = -1;
124 int is_emulator(void) {
125     if (g_is_emulator >= 0) {
126         return g_is_emulator;
127     } else {
128         D("failed to initialize check emulator\n");
129     }
130
131     return sdbd_commandline_args.emulator.host != NULL;
132 }
133
134 int is_appid2pid_supported(void) {
135
136     if (access(APPID2PID_PATH, F_OK) == 0) {
137         /* It is necessary to confirm that it is possible
138          * to run "appid2pid" in the sdk user/group privileges. */
139         struct stat st;
140         if (stat(APPID2PID_PATH, &st) == 0) {
141             D("appid2pid uid=%d, gid=%d, mode=0x%x.\n", st.st_uid, st.st_gid, st.st_mode);
142             if ( (st.st_uid == STATIC_SDK_USER_ID && st.st_mode & S_IXUSR)
143                 || (st.st_gid == STATIC_SDK_GROUP_ID && st.st_mode & S_IXGRP)
144                 || (st.st_mode & S_IXOTH) ) {
145                 D("appid2pid is supported.\n");
146                 return 1;
147             }
148         }
149     } else {
150         D("failed to access appid2pid file: %d\n", errno);
151     }
152
153     D("appid2pid is NOT supported.\n");
154     return 0;
155 }
156
157 int is_netcoredbg_supported(void) {
158
159     FILE *fp = fopen(NETCOREDBG_LOCATION, "r");
160     if (fp) {
161         size_t len;
162         ssize_t num;
163         char *line = NULL;
164
165         while ((num = getline(&line, &len, fp)) != -1) {
166             if (strstr(line, "NETCOREDBG") != NULL) {
167                 snprintf(g_capabilities.netcoredbg_support, sizeof(g_capabilities.netcoredbg_support),
168                          "%s", ENABLED);
169                 free(line);
170                 return 1;
171             }
172             free(line);
173             line = NULL;
174         }
175         fclose(fp);
176     }
177     return 0;
178 }
179
180 int is_container_enabled(void) {
181     bool value;
182     int ret;
183     ret = system_info_get_platform_bool("tizen.org/feature/container", &value);
184     if (ret != SYSTEM_INFO_ERROR_NONE) {
185         E("failed to get container information: %d\n", errno);
186         return 0;
187     } else {
188         D("tizen container: %d\n", value);
189         if (value == true)
190             return 1;
191         else
192             return 0;
193     }
194 }
195
196 void handle_sig_term(int sig) {
197 #ifdef SDB_PIDPATH
198     if (access(SDB_PIDPATH, F_OK) == 0)
199         sdb_unlink(SDB_PIDPATH);
200 #endif
201 }
202
203 static const char *sdb_device_banner = "device";
204
205 void fatal(const char *fmt, ...)
206 {
207     va_list ap;
208     va_start(ap, fmt);
209     fprintf(stderr, "error: ");
210     vfprintf(stderr, fmt, ap);
211     fprintf(stderr, "\n");
212     va_end(ap);
213     exit(-1);
214 }
215
216 void fatal_errno(const char *fmt, ...)
217 {
218     va_list ap;
219     va_start(ap, fmt);
220     fprintf(stderr, "errno: %d: ", errno);
221     vfprintf(stderr, fmt, ap);
222     fprintf(stderr, "\n");
223     va_end(ap);
224     exit(-1);
225 }
226
227 static char* get_sdb_log_conf(const char* key)
228 {
229     int fd;
230     char line[256] = {0,};
231     char value[256] = {0,};
232
233     if (access(SDB_LOGCONF_PATH, F_OK)) {
234         return NULL;
235     }
236
237     fd = unix_open(SDB_LOGCONF_PATH, O_RDONLY);
238     if (fd < 0) {
239         E("failed to open '%s' file: %d\n", SDB_LOGCONF_PATH, errno);
240         return NULL;
241     }
242
243     if (read_line(fd, line, sizeof(line)) > 0) {
244         char* start = strstr(line, key);
245         if (start != NULL) {
246             // move one more character to remove '=',
247             // including the length of the key string
248             start = start + strlen(key) + 1;
249             char* end = strstr(start, " ");
250             if (end != NULL) {
251                 strncpy(value, start, end - start);
252             } else {
253                 strncpy(value, start, sizeof(value));
254             }
255         } else {
256             sdb_close(fd);
257             return NULL;
258         }
259     }
260     sdb_close(fd);
261     return strdup(value);
262 }
263
264 static int is_enable_sdbd_log()
265 {
266     return (!strncmp(g_capabilities.log_enable, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
267 }
268
269 int   sdb_trace_mask;
270
271 /* read a comma/space/colum/semi-column separated list of tags
272  * from the SDB_TRACE environment variable and build the trace
273  * mask from it. note that '1' and 'all' are special cases to
274  * enable all tracing
275  */
276 void  sdb_trace_init(void)
277 {
278     char*  ptr = get_sdb_log_conf("SDB_TRACE");
279     const char*  p;
280     const char*  q;
281
282     static const struct {
283         const char*  tag;
284         int           flag;
285     } tags[] = {
286         { "1", 0 },
287         { "all", 0 },
288         { "sdb", TRACE_SDB },
289         { "sockets", TRACE_SOCKETS },
290         { "packets", TRACE_PACKETS },
291         { "rwx", TRACE_RWX },
292         { "usb", TRACE_USB },
293         { "sync", TRACE_SYNC },
294         { "sysdeps", TRACE_SYSDEPS },
295         { "transport", TRACE_TRANSPORT },
296         { "jdwp", TRACE_JDWP },
297         { "services", TRACE_SERVICES },
298         { "properties", TRACE_PROPERTIES },
299         { "sdktools", TRACE_SDKTOOLS },
300         { "appcmd", TRACE_APPCMD },
301         { NULL, 0 }
302     };
303
304     if (ptr == NULL) {
305         if (is_enable_sdbd_log())
306             p = "all";
307         else
308             return;
309     } else {
310         p = ptr;
311     }
312
313     /* use a comma/column/semi-colum/space separated list */
314     while (*p) {
315         int  len, tagn;
316
317         q = strpbrk(p, " ,:;");
318         if (q == NULL) {
319             q = p + strlen(p);
320         }
321         len = q - p;
322
323         for (tagn = 0; tags[tagn].tag != NULL; tagn++)
324         {
325             int  taglen = strlen(tags[tagn].tag);
326
327             if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
328             {
329                 int  flag = tags[tagn].flag;
330                 if (flag == 0) {
331                     sdb_trace_mask = ~0;
332                     free(ptr);
333                     return;
334                 }
335                 sdb_trace_mask |= (1 << flag);
336                 break;
337             }
338         }
339         p = q;
340         if (*p)
341             p++;
342     }
343     free(ptr);
344 }
345
346 /*
347  * Implements SDB tracing inside the emulator.
348  */
349
350 #include <stdarg.h>
351
352 /*
353  * Redefine open and write for qemu_pipe.h that contains inlined references
354  * to those routines. We will redifine them back after qemu_pipe.h inclusion.
355  */
356
357 #undef open
358 #undef write
359 #define open    sdb_open
360 #define write   sdb_write
361 #include "qemu_pipe.h"
362 #undef open
363 #undef write
364 #define open    ___xxx_open
365 #define write   ___xxx_write
366
367 /* A handle to sdb-debug qemud service in the emulator. */
368 int   sdb_debug_qemu = -1;
369
370 apacket *get_apacket(void)
371 {
372     apacket *p = malloc(sizeof(apacket));
373     if(p == 0) fatal("failed to allocate an apacket");
374     memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
375     return p;
376 }
377
378 void put_apacket(apacket *p)
379 {
380     if (p != NULL) {
381         free(p);
382         p = NULL;
383     }
384 }
385
386 void handle_online(void)
387 {
388     I("sdb: online\n");
389 }
390
391 void handle_offline(atransport *t)
392 {
393     I("sdb: offline\n");
394     //Close the associated usb
395     run_transport_disconnects(t);
396 }
397
398 #if TRACE_PACKETS
399 #define DUMPMAX 32
400 void print_packet(const char *label, apacket *p)
401 {
402     char *tag;
403     char *x;
404     unsigned count;
405
406     switch(p->msg.command){
407     case A_SYNC: tag = "SYNC"; break;
408     case A_CNXN: tag = "CNXN" ; break;
409     case A_OPEN: tag = "OPEN"; break;
410     case A_OKAY: tag = "OKAY"; break;
411     case A_CLSE: tag = "CLSE"; break;
412     case A_WRTE: tag = "WRTE"; break;
413     default: tag = "????"; break;
414     }
415
416     fprintf(stderr, "%s: %s %08x %08x %04x \"",
417             label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
418     count = p->msg.data_length;
419     x = (char*) p->data;
420     if(count > DUMPMAX) {
421         count = DUMPMAX;
422         tag = "\n";
423     } else {
424         tag = "\"\n";
425     }
426     while(count-- > 0){
427         if((*x >= ' ') && (*x < 127)) {
428             fputc(*x, stderr);
429         } else {
430             fputc('.', stderr);
431         }
432         x++;
433     }
434     fprintf(stderr, tag);
435 }
436 #endif
437
438 #ifdef SUPPORT_ENCRYPT
439 /*
440 desc. : 암호화 실패 메시지 전송
441 parameter : [in] apacket* p : sdbd로 들어온 메시지
442             [in] atransport *t : 현재 연결에 대한 atransport
443             [in] unsigned failed_value : 실패 값
444 */
445 void send_encr_fail(apacket* p, atransport *t, unsigned failed_value){
446     apacket* enc_p;
447     enc_p = get_apacket();
448     enc_p->msg.command = A_ENCR; // 암호화 메시지
449     enc_p->msg.arg0 = failed_value; // 실패값
450     enc_p->msg.arg1 = p->msg.arg1;
451     send_packet(enc_p, t);
452     //put_apacket(enc_p);
453 }
454
455 /*
456 desc. : 암호화 메시지 핸들링
457 parameter : [in] apacket* p : sdbd로 들어온 메시지
458             [in/out] atransport *t : 현재 연결에 대한 atransport
459 ret : 0 : 정상적으로 메시지 전송
460       -1: 메시지 전송 실패
461 */
462 int handle_encr_packet(apacket* p, atransport *t){
463     static int sessionID = 0;
464     int retVal = 0;
465     apacket* enc_p = NULL;
466
467     if(p->msg.arg0 == ENCR_SET_ON_REQ){ // hello 메시지인 경우
468         t->sessionID = sessionID;
469         if((retVal = security_init(t->sessionID, NULL)) == 1){ // 암호화 handshaking을 위한 init
470             if(security_parse_server_hello(t->sessionID, p) == 1){ // hello 메시지 파싱
471                 I("security_parse_server_hello success\n");
472                 enc_p = get_apacket();
473                 if(security_gen_client_hello(t->sessionID, enc_p) == 1){ // hello 메시지 생성
474                     I("security_gen_client_hello success\n");
475                     enc_p->msg.command = A_ENCR;
476                     enc_p->msg.arg0 = ENCR_SET_ON_REQ;
477                     enc_p->msg.arg1 = p->msg.arg1;
478                     sessionID++;
479                     send_packet(enc_p, t);
480                 }
481                 else { // hello 메시지 생성 실패
482                     E("security_gen_client_hello error\n");
483                     send_encr_fail(p, t, ENCR_ON_FAIL); // 암호화 on 실패 메시지 전송
484                     t->encryption = ENCR_OFF; // 암호화 모드는 off
485                     security_deinit(t->sessionID);
486                     return -1;
487                 }
488             }
489             else{ // hello 메시지 파싱 실패
490                 E("security_parse_server_hello error\n");
491                 send_encr_fail(p, t, ENCR_ON_FAIL);
492                 t->encryption = ENCR_OFF;
493                 security_deinit(t->sessionID);
494
495                 return -1;
496             }
497         } else { // init 실패
498             E("security_init error\n");
499             send_encr_fail(p, t, ENCR_ON_FAIL);
500             t->encryption = ENCR_OFF;
501             if (retVal == 0)
502             {
503                 security_deinit(t->sessionID);
504             }
505             //here!! do security_deinit(), but when plugin pointer is null -> not deinit
506             return -1;
507         }
508     }
509     else if(p->msg.arg0 == ENCR_SET_ON_OK){ // ack 메시지인 경우
510         if(security_parse_server_ack(t->sessionID, p) == 1){    // ack 메시지 파싱
511             enc_p = get_apacket();
512             if(security_gen_client_ack(t->sessionID, enc_p) == 1){ // ack 메시지 생성
513                 I("security_gen_client_ack success\n");
514                 enc_p->msg.command = A_ENCR;
515                 enc_p->msg.arg0 = ENCR_SET_ON_OK;
516                 enc_p->msg.arg1 = p->msg.arg1;
517                 t->encryption = ENCR_ON;
518                 send_packet(enc_p, t);
519             }
520             else { // ack 메시지 생성에 실패한 경우
521                 E("security_gen_client_ack error\n");
522                 send_encr_fail(p, t, ENCR_ON_FAIL);
523                 t->encryption = ENCR_OFF;
524                 security_deinit(t->sessionID);
525                 return -1;
526             }
527         }
528         else { // ack 메시지 파싱에 실패한 경우
529             E("security_parse_server_ack error\n");
530             send_encr_fail(p, t, ENCR_ON_FAIL);
531             t->encryption = ENCR_OFF;
532             security_deinit(t->sessionID);
533             return -1;
534         }
535     }
536     else if(p->msg.arg0 == ENCR_SET_OFF){ // 암호화 모드 off 요청 메시지
537         if(t->encryption == ENCR_ON && security_deinit(t->sessionID) == 1){ // 현재 암호화 모드가 on 상태인 경우
538             enc_p = get_apacket();
539             t->encryption = ENCR_OFF; // 현재 연결에 대한 암호화 모드 off
540             enc_p->msg.command = A_ENCR;
541             enc_p->msg.arg0 = ENCR_SET_OFF;
542             enc_p->msg.arg1 = p->msg.arg1;
543             send_packet(enc_p, t);
544         }
545         else { // 암호화 모드 off에 실패한 경우
546             E("security_deinit error\n");
547             send_encr_fail(p, t, ENCR_OFF_FAIL); // 암호화 모드 off 실패 메시지 전송
548             return -1;
549         }
550     }
551     else if(p->msg.arg0 == ENCR_GET){ // 암호화 모드의 상태 요청 메시지인 경우
552         enc_p = get_apacket();
553         enc_p->msg.command = A_ENCR;
554         enc_p->msg.arg0 = ENCR_GET; // 암호화 모드 status get메시지
555         enc_p->msg.arg1 = p->msg.arg1;
556         if(t->encryption == ENCR_ON){ // 암호화 모드가 on인 경우
557             enc_p->msg.data_length = 13;
558             strncpy((char*)enc_p->data, "encryption:on", enc_p->msg.data_length); // encryption:on 메시지 전송
559         } else if(t->encryption == ENCR_OFF){ // 암호화 모드가 off인 경우
560             enc_p->msg.data_length = 14;
561             strncpy((char*)enc_p->data, "encryption:off", enc_p->msg.data_length); // encryption:off 메시지 전송
562         }
563         send_packet(enc_p, t);
564     }
565     else if (p->msg.arg0 == ENCR_ON_FAIL) // 암호화 모드를 on 하는 도중 실패한 경우 받는 메시지
566     {
567         t->encryption = ENCR_OFF; // 암호화 모드를 다시 off
568         E("encryption on failed\n");
569     }
570     else if (p->msg.arg0 == ENCR_OFF_FAIL) // 암호화 모드를 off하는 도중 실패한 경우 받는 메시지
571     {
572         //t->encryption = ENCR_ON;
573         E("encryption off failed\n");
574     }
575     //put_apacket(enc_p);
576     return 0;
577
578 }
579 #endif
580
581
582 static void send_ready(unsigned local, unsigned remote, atransport *t)
583 {
584     I("Calling send_ready \n");
585     apacket *p = get_apacket();
586     p->msg.command = A_OKAY;
587     p->msg.arg0 = local;
588     p->msg.arg1 = remote;
589     send_packet(p, t);
590 }
591
592 static void send_close(unsigned local, unsigned remote, atransport *t)
593 {
594     I("Calling send_close \n");
595     apacket *p = get_apacket();
596     p->msg.command = A_CLSE;
597     p->msg.arg0 = local;
598     p->msg.arg1 = remote;
599     send_packet(p, t);
600 }
601
602 static void send_connect(atransport *t)
603 {
604     I("Calling send_connect \n");
605     apacket *cp = get_apacket();
606     cp->msg.command = A_CNXN;
607     cp->msg.arg0 = A_VERSION;
608 #ifdef SUPPORT_ENCRYPT
609    cp->msg.arg1 = MAX_PAYLOAD - 100; // connection 시, sdb server의 패킷 크기를 암호화 오버로드 만큼 줄임
610 #else
611     cp->msg.arg1 = MAX_PAYLOAD;
612 #endif
613     char device_name[256]={0,};
614     int r = 0;
615     int status = 0;
616     if (request_lock_state_to_plugin(LOCKTYPE_PASSWORD) == 1) {
617         status = 1;
618         t->connection_state = CS_PWLOCK;
619     }
620
621     if (is_emulator()) {
622         r = get_emulator_name(device_name, sizeof device_name);
623     } else {
624         r = get_device_name(device_name, sizeof device_name);
625     }
626     if (r < 0) {
627         snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, DEFAULT_DEVICENAME, status);
628     } else {
629         snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, device_name, status);
630     }
631
632     if (extcmd != NULL) {
633         char extbuf[BUF_SIZE] = {0,};
634         snprintf(extbuf, sizeof extbuf, "::%s", extcmd);
635         strncat((char*) cp->data, extbuf, sizeof(cp->data) - strlen(cp->data)- 1);
636     }
637     cp->msg.data_length = strlen((char*) cp->data) + 1;
638     D("CNXN data: %s\n", (char*)cp->data);
639
640     send_packet(cp, t);
641 }
642
643 void send_device_status()
644 {
645     I("broadcast device status\n");
646     apacket* cp = get_apacket();
647     cp->msg.command = A_STAT;
648     cp->msg.arg0 = is_pwlocked;
649     cp->msg.arg1 = 0;
650
651     broadcast_transport(cp);
652
653     //all broadcasted packets are memory copied
654     //so, we should call put_apacket
655     put_apacket(cp);
656 }
657
658 static char *connection_state_name(atransport *t)
659 {
660     if (t == NULL) {
661         return "unknown";
662     }
663
664     switch(t->connection_state) {
665     case CS_BOOTLOADER:
666         return "bootloader";
667     case CS_DEVICE:
668         return "device";
669     case CS_OFFLINE:
670         return "offline";
671     default:
672         return "unknown";
673     }
674 }
675
676 static int get_str_cmdline(char *src, char *dest, char str[], int str_size) {
677     char *s = strstr(src, dest);
678     if (s == NULL) {
679         return -1;
680     }
681     char *e = strstr(s, " ");
682     if (e == NULL) {
683         return -1;
684     }
685
686     int len = e-s-strlen(dest);
687
688     if (len >= str_size) {
689         E("buffer size(%d) should be bigger than %d\n", str_size, len+1);
690         return -1;
691     }
692
693     strncpy(str, s + strlen(dest), len);
694     str[len]='\0';
695     return len;
696 }
697
698 int get_emulator_forward_port() {
699     SdbdCommandlineArgs *sdbd_args = &sdbd_commandline_args; /* alias */
700
701     if (sdbd_args->emulator.host == NULL) {
702         return -1;
703     }
704
705     return sdbd_args->emulator.port;
706 }
707
708 int get_emulator_name(char str[], int str_size) {
709     SdbdCommandlineArgs *sdbd_args = &sdbd_commandline_args; /* alias */
710
711     if (sdbd_args->emulator.host == NULL) {
712         return -1;
713     }
714
715     s_strncpy(str, sdbd_args->emulator.host, str_size);
716     return 0;
717 }
718
719 int get_device_name(char str[], int str_size) {
720     char *value = NULL;
721     int r = system_info_get_platform_string("http://tizen.org/system/model_name", &value);
722     if (r != SYSTEM_INFO_ERROR_NONE) {
723         E("fail to get system model:%d\n", errno);
724         return -1;
725     } else {
726         s_strncpy(str, value, str_size);
727         D("returns model_name:%s\n", value);
728         if (value != NULL) {
729             free(value);
730         }
731         return 0;
732     }
733     /*
734     int fd = unix_open(USB_SERIAL_PATH, O_RDONLY);
735     if (fd < 0) {
736         D("fail to read:%s (%d)\n", USB_SERIAL_PATH, errno);
737         return -1;
738     }
739
740     if(read_line(fd, str, str_size)) {
741         D("device serial name: %s\n", str);
742         sdb_close(fd);
743         return 0;
744     }
745     sdb_close(fd);
746     */
747     return -1;
748 }
749
750 static int get_cmdline_value(char *split, char str[], int str_size) {
751     char cmdline[512];
752     int fd = unix_open(PROC_CMDLINE_PATH, O_RDONLY);
753
754     if (fd < 0) {
755         E("fail to read /proc/cmdline\n");
756         return -1;
757     }
758     if(read_line(fd, cmdline, sizeof(cmdline))) {
759         D("qemu cmd: %s\n", cmdline);
760         if (get_str_cmdline(cmdline, split, str, str_size) < 1) {
761             E("could not get the (%s) value from cmdline\n", split);
762             sdb_close(fd);
763             return -1;
764         }
765     }
766     sdb_close(fd);
767     return 0;
768 }
769
770 int get_emulator_hostip(char str[], int str_size) {
771     return get_cmdline_value("host_ip=", str, str_size);
772 }
773
774 int get_emulator_guestip(char str[], int str_size) {
775     int           s;
776     struct ifreq ifr;
777     struct sockaddr_in *sin;
778
779     s = socket(AF_INET, SOCK_DGRAM, 0);
780     if(s < 0) {
781         E("socket error\n");
782         return -1;
783     }
784
785     snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", GUEST_IP_INTERFACE);
786     if(ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
787         E("ioctl hwaddr error\n");
788         sdb_close(s);
789         return -1;
790     }
791
792     if(ioctl(s, SIOCGIFADDR, &ifr) < 0) {
793         E("ioctl addr error\n");
794         sdb_close(s);
795         return -1;
796     }
797     sin = (struct sockaddr_in *)&ifr.ifr_addr;
798     snprintf(str, str_size, "%s", inet_ntoa(sin->sin_addr));
799     sdb_close(s);
800
801     return 0;
802 }
803
804 void parse_banner(char *banner, atransport *t)
805 {
806     char *type, *product, *end;
807
808     D("parse_banner: %s\n", banner);
809     type = banner;
810     product = strchr(type, ':');
811     if(product) {
812         *product++ = 0;
813     } else {
814         product = "";
815     }
816
817         /* remove trailing ':' */
818     end = strchr(product, ':');
819     if(end) *end = 0;
820
821         /* save product name in device structure */
822     if (t->product == NULL) {
823         t->product = strdup(product);
824     } else if (strcmp(product, t->product) != 0) {
825         free(t->product);
826         t->product = strdup(product);
827     }
828
829     if(!strcmp(type, "bootloader")){
830         I("setting connection_state to CS_BOOTLOADER\n");
831         t->connection_state = CS_BOOTLOADER;
832         update_transports();
833         return;
834     }
835
836     if(!strcmp(type, "device")) {
837         I("setting connection_state to CS_DEVICE\n");
838         t->connection_state = CS_DEVICE;
839         update_transports();
840         return;
841     }
842
843     if(!strcmp(type, "recovery")) {
844         I("setting connection_state to CS_RECOVERY\n");
845         t->connection_state = CS_RECOVERY;
846         update_transports();
847         return;
848     }
849
850     if(!strcmp(type, "sideload")) {
851         I("setting connection_state to CS_SIDELOAD\n");
852         t->connection_state = CS_SIDELOAD;
853         update_transports();
854         return;
855     }
856
857     t->connection_state = CS_HOST;
858 }
859
860 static void update_version(atransport *t, int version, size_t payload)
861 {
862 #ifdef SUPPORT_ENCRYPT
863     size_t max_payload = MAX_PAYLOAD - 100;
864 #else
865     size_t max_payload = MAX_PAYLOAD;
866 #endif
867     t->protocol_version = min(version, A_VERSION);
868     t->max_payload = min(payload, max_payload);
869     D("update transport version. version=%x, max_payload=%zu\n", t->protocol_version, t->max_payload);
870 }
871
872 void handle_packet(apacket *p, atransport *t)
873 {
874     // Verify pointer p
875     int result = access((const char *) p, F_OK);
876     if ((result == -1) && (errno == EFAULT)) {
877         fatal("Invalid apacket = [0x%p]", p);
878     }
879
880     asocket *s;
881
882 //    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
883 //                ((char*) (&(p->msg.command)))[1],
884 //                ((char*) (&(p->msg.command)))[2],
885 //                ((char*) (&(p->msg.command)))[3]);
886
887     print_packet("recv", p);
888
889     switch(p->msg.command){
890     case A_SYNC:
891         if(p->msg.arg0){
892             send_packet(p, t);
893             if(HOST) send_connect(t);
894         } else {
895             t->connection_state = CS_OFFLINE;
896             handle_offline(t);
897             send_packet(p, t);
898         }
899         return;
900
901     case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
902             /* XXX verify version, etc */
903         if(t->connection_state != CS_OFFLINE) {
904             t->connection_state = CS_OFFLINE;
905             handle_offline(t);
906         }
907         update_version(t, p->msg.arg0, p->msg.arg1);
908         parse_banner((char*) p->data, t);
909         handle_online();
910         if(!HOST) send_connect(t);
911         break;
912
913     case A_OPEN: /* OPEN(local-id, 0, "destination") */
914         if (request_lock_state_to_plugin(LOCKTYPE_PASSWORD) == 1 && t->connection_state == CS_PWLOCK) {
915             // in case of already locked before get A_CNXN
916             E("open failed due to password locked before get A_CNXN:%d\n", t->connection_state);
917             send_close(0, p->msg.arg0, t);
918         } else {
919             if(t->connection_state != CS_OFFLINE) {
920                 char *name = (char*) p->data;
921                 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
922                 s = create_local_service_socket(name);
923                 if(s == 0) {
924                     send_close(0, p->msg.arg0, t);
925                 } else {
926                     s->peer = create_remote_socket(p->msg.arg0, t);
927                     s->peer->peer = s;
928                     send_ready(s->id, s->peer->id, t);
929                     s->ready(s);
930                 }
931             }
932         }
933         break;
934
935     case A_OKAY: /* READY(local-id, remote-id, "") */
936         if(t->connection_state != CS_OFFLINE) {
937             if((s = find_local_socket(p->msg.arg1))) {
938                 if(s->peer == 0) {
939                     s->peer = create_remote_socket(p->msg.arg0, t);
940                     s->peer->peer = s;
941                 }
942                 s->ready(s);
943             }
944         }
945         break;
946
947     case A_CLSE: /* CLOSE(local-id, remote-id, "") */
948         if(t->connection_state != CS_OFFLINE) {
949             if((s = find_local_socket(p->msg.arg1))) {
950                 s->close(s);
951             }
952         }
953         break;
954
955     case A_WRTE:
956         if(t->connection_state != CS_OFFLINE) {
957             if((s = find_local_socket(p->msg.arg1))) {
958                 unsigned rid = p->msg.arg0;
959                 p->len = p->msg.data_length;
960
961                 if(s->enqueue(s, p) == 0) {
962                     I("Enqueue the socket\n");
963                     send_ready(s->id, rid, t);
964                 }
965                 return;
966             }
967         }
968         break;
969 #ifdef SUPPORT_ENCRYPT
970     case A_ENCR: // 암호화 메시지인 경우
971         if(t->connection_state != CS_OFFLINE) {
972             handle_encr_packet(p, t);
973         }
974         break;
975 #endif
976
977     default:
978         printf("handle_packet: what is %08x?!\n", p->msg.command);
979     }
980
981     put_apacket(p);
982 }
983
984 alistener listener_list = {
985     .next = &listener_list,
986     .prev = &listener_list,
987 };
988
989 static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
990 {
991     asocket *s;
992     int ret = -1;
993
994     if(ev & FDE_READ) {
995         struct sockaddr addr;
996         socklen_t alen;
997         int fd;
998
999         alen = sizeof(addr);
1000         fd = sdb_socket_accept(_fd, &addr, &alen);
1001         if(fd < 0) return;
1002
1003         ret = sdb_socket_setbufsize(fd, CHUNK_SIZE);
1004         if (ret == -1) {
1005             D("sdbd: sdb_socket_setbufsize failed (%d)\n", ret);
1006         }
1007
1008         s = create_local_socket(fd);
1009         if(s) {
1010             connect_to_smartsocket(s);
1011             return;
1012         }
1013
1014         sdb_close(fd);
1015     }
1016 }
1017
1018 static void listener_event_func(int _fd, unsigned ev, void *_l)
1019 {
1020     alistener *l = _l;
1021     asocket *s;
1022
1023     if(ev & FDE_READ) {
1024         struct sockaddr addr;
1025         socklen_t alen;
1026         int fd;
1027
1028         alen = sizeof(addr);
1029         fd = sdb_socket_accept(_fd, &addr, &alen);
1030         if(fd < 0) return;
1031
1032         s = create_local_socket(fd);
1033         if(s) {
1034             s->transport = l->transport;
1035             connect_to_remote(s, l->connect_to);
1036             return;
1037         }
1038
1039         sdb_close(fd);
1040     }
1041 }
1042
1043 static void  free_listener(alistener*  l)
1044 {
1045     if (l->next) {
1046         l->next->prev = l->prev;
1047         l->prev->next = l->next;
1048         l->next = l->prev = l;
1049     }
1050
1051     // closes the corresponding fd
1052     fdevent_remove(&l->fde);
1053
1054     if (l->local_name)
1055         free((char*)l->local_name);
1056
1057     if (l->connect_to)
1058         free((char*)l->connect_to);
1059
1060     if (l->transport) {
1061         remove_transport_disconnect(l->transport, &l->disconnect);
1062     }
1063     free(l);
1064 }
1065
1066 static void listener_disconnect(void*  _l, atransport*  t)
1067 {
1068     alistener*  l = _l;
1069
1070     free_listener(l);
1071 }
1072
1073 int local_name_to_fd(const char *name)
1074 {
1075     int port;
1076
1077     if(!strncmp("tcp:", name, 4)){
1078         int  ret;
1079         port = atoi(name + 4);
1080         ret = socket_loopback_server(port, SOCK_STREAM);
1081         return ret;
1082     }
1083 #ifndef HAVE_WIN32_IPC  /* no Unix-domain sockets on Win32 */
1084     // It's non-sensical to support the "reserved" space on the sdb host side
1085     if(!strncmp(name, "local:", 6)) {
1086         return socket_local_server(name + 6,
1087                 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1088     } else if(!strncmp(name, "localabstract:", 14)) {
1089         return socket_local_server(name + 14,
1090                 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1091     } else if(!strncmp(name, "localfilesystem:", 16)) {
1092         return socket_local_server(name + 16,
1093                 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
1094     }
1095
1096 #endif
1097     printf("unknown local portname '%s'\n", name);
1098     return -1;
1099 }
1100
1101 static int remove_listener(const char *local_name, const char *connect_to, atransport* transport)
1102 {
1103     alistener *l;
1104
1105     for (l = listener_list.next; l != &listener_list; l = l->next) {
1106         if (!strcmp(local_name, l->local_name) &&
1107             !strcmp(connect_to, l->connect_to) &&
1108             l->transport && l->transport == transport) {
1109
1110             listener_disconnect(l, transport);
1111             return 0;
1112         }
1113     }
1114
1115     return -1;
1116 }
1117
1118 static int install_listener(const char *local_name, const char *connect_to, atransport* transport)
1119 {
1120     alistener *l;
1121
1122     //printf("install_listener('%s','%s')\n", local_name, connect_to);
1123
1124     for(l = listener_list.next; l != &listener_list; l = l->next){
1125         if(strcmp(local_name, l->local_name) == 0) {
1126             char *cto;
1127
1128                 /* can't repurpose a smartsocket */
1129             if(l->connect_to[0] == '*') {
1130                 return -1;
1131             }
1132
1133             cto = strdup(connect_to);
1134             if(cto == 0) {
1135                 return -1;
1136             }
1137
1138             //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
1139             free((void*) l->connect_to);
1140             l->connect_to = cto;
1141             if (l->transport != transport) {
1142                 remove_transport_disconnect(l->transport, &l->disconnect);
1143                 l->transport = transport;
1144                 add_transport_disconnect(l->transport, &l->disconnect);
1145             }
1146             return 0;
1147         }
1148     }
1149
1150     if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
1151     if((l->local_name = strdup(local_name)) == 0) goto nomem;
1152     if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
1153
1154
1155     l->fd = local_name_to_fd(local_name);
1156     if(l->fd < 0) {
1157         free((void*) l->local_name);
1158         free((void*) l->connect_to);
1159         free(l);
1160         printf("cannot bind '%s'\n", local_name);
1161         return -2;
1162     }
1163
1164     if (close_on_exec(l->fd) < 0) {
1165         E("fail to close fd exec:%d\n",l->fd);
1166     }
1167     if(!strcmp(l->connect_to, "*smartsocket*")) {
1168         fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
1169     } else {
1170         fdevent_install(&l->fde, l->fd, listener_event_func, l);
1171     }
1172     fdevent_set(&l->fde, FDE_READ);
1173
1174     l->next = &listener_list;
1175     l->prev = listener_list.prev;
1176     l->next->prev = l;
1177     l->prev->next = l;
1178     l->transport = transport;
1179
1180     if (transport) {
1181         l->disconnect.opaque = l;
1182         l->disconnect.func   = listener_disconnect;
1183         add_transport_disconnect(transport, &l->disconnect);
1184     }
1185     return 0;
1186
1187 nomem:
1188     fatal("cannot allocate listener");
1189     return 0;
1190 }
1191
1192 static void sdb_cleanup(void)
1193 {
1194     clear_sdbd_commandline_args(&sdbd_commandline_args);
1195
1196     if (is_support_usbproto()) {
1197         usb_cleanup();
1198     }
1199 //    if(required_pid > 0) {
1200 //        kill(required_pid, SIGKILL);
1201 //    }
1202
1203     unload_sdbd_plugin();
1204 }
1205
1206 void start_device_log(void)
1207 {
1208     int fd;
1209     char    path[PATH_MAX] = {0, };
1210     char    path_folder[PATH_MAX] = {0, };
1211     char    path_file[PATH_MAX] = {0, };
1212     struct tm now;
1213     time_t t;
1214
1215     // read the trace mask from persistent property persist.sdb.trace_mask
1216     // give up if the property is not set or cannot be parsed
1217     char* p_trace = get_sdb_log_conf("SDB_TRACE");
1218     if ((p_trace == NULL ) && !is_enable_sdbd_log()) {
1219         return;
1220     } else {
1221         free(p_trace);
1222     }
1223     char* p_path = get_sdb_log_conf("SDBD_LOG_PATH");
1224     if (p_path) {
1225         snprintf(path_folder, sizeof(path_folder), "%s", p_path);
1226         free(p_path);
1227     } else if (g_capabilities.log_path[0] != '\0') {
1228         snprintf(path_folder, sizeof(path_folder), "%s", g_capabilities.log_path);
1229     } else {
1230         return;
1231     }
1232
1233     tzset();
1234     time(&t);
1235     localtime_r(&t, &now);
1236
1237     strftime(path_file, sizeof(path_file),
1238                     "sdbd-%Y-%m-%d-%H-%M-%S.txt",
1239                     &now);
1240
1241     snprintf(path, sizeof(path), "%s/%s", path_folder, path_file);
1242
1243     fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1244     if (fd < 0) {
1245         return;
1246     }
1247
1248     // redirect stdout and stderr to the log file
1249     dup2(fd, 1);
1250     dup2(fd, 2);
1251     fprintf(stderr,"--- sdbd starting (pid %d) ---\n", getpid());
1252     sdb_close(fd);
1253
1254     fd = unix_open("/dev/null", O_RDONLY);
1255     if (fd < 0) {
1256         // hopefully not gonna happen
1257         return;
1258     }
1259     dup2(fd, 0);
1260     sdb_close(fd);
1261 }
1262
1263 /* Constructs a local name of form tcp:port.
1264  * target_str points to the target string, it's content will be overwritten.
1265  * target_size is the capacity of the target string.
1266  * server_port is the port number to use for the local name.
1267  */
1268 void build_local_name(char* target_str, size_t target_size, int server_port)
1269 {
1270   snprintf(target_str, target_size, "tcp:%d", server_port);
1271 }
1272
1273 static void init_drop_privileges() {
1274 #ifdef _DROP_PRIVILEGE
1275     rootshell_mode = 0;
1276 #else
1277     rootshell_mode = 1;
1278 #endif
1279 }
1280
1281 int should_drop_privileges() {
1282     if (rootshell_mode == 1) { // if root, then don't drop
1283         return 0;
1284     }
1285     return 1;
1286 }
1287
1288 #include <gio/gio.h>
1289
1290 #define DEVICED_BUS            "org.tizen.system.deviced"
1291 #define DEVICED_CORE_PATH      "/Org/Tizen/System/DeviceD/Core"
1292 #define BOOTING_DONE_SIGNAL    "BootingDone"
1293 #define DEVICED_CORE_INTERFACE "org.tizen.system.deviced.core"
1294 #define SDBD_BOOT_INFO_FILE    "/tmp/sdbd_boot_info"
1295
1296 static GMainLoop *g_mainloop;
1297
1298 static void booting_done_signal_subscriber(GDBusConnection *connection,
1299     const gchar *sender, const gchar *path, const gchar *interface,
1300     const gchar *signal, GVariant *parameters, gpointer user_data)
1301 {
1302     if (g_strcmp0(signal, BOOTING_DONE_SIGNAL) != 0) {
1303         D("received signal(%s) does not match the desired signal(%s)\n",
1304           signal, BOOTING_DONE_SIGNAL);
1305         return;
1306     }
1307
1308     D("received the \"%s\" signal\n", signal);
1309
1310     booting_done = 1;
1311     if (access(SDBD_BOOT_INFO_FILE, F_OK) == 0) {
1312         I("booting is already done\n");
1313     } else {
1314         FILE *info_file = fopen(SDBD_BOOT_INFO_FILE, "w");
1315         if (info_file != NULL) {
1316             fprintf(info_file, "%d", 1);
1317             fclose(info_file);
1318         }
1319         I("booting is done\n");
1320     }
1321
1322     I("handled the booting done signal\n");
1323     g_main_loop_quit(g_mainloop);
1324 }
1325
1326 static void *bootdone_cb(void *args)
1327 {
1328     GError *error = NULL;
1329     GDBusConnection *connection = NULL;
1330     guint id;
1331
1332     connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1333     if (connection == NULL) {
1334         if (error != NULL) {
1335             E("failed to connect to the system bus: %s\n", error->message);
1336             g_error_free(error);
1337         } else {
1338             E("failed to connect to the system bus\n");
1339         }
1340         return NULL;
1341     }
1342
1343     g_mainloop = g_main_loop_new(NULL, false);
1344     if (g_mainloop == NULL) {
1345         E("failed to create a g_main_loop\n");
1346         goto bootdone_out;
1347     }
1348
1349     id = g_dbus_connection_signal_subscribe(connection,
1350         DEVICED_BUS, DEVICED_CORE_INTERFACE, BOOTING_DONE_SIGNAL,
1351         DEVICED_CORE_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
1352         booting_done_signal_subscriber, NULL, NULL);
1353     if (id == 0) {
1354         E("failed to subscribe to the booting done signal\n");
1355         goto bootdone_out;
1356     }
1357
1358     I("wait for the booting done signal\n");
1359     g_main_loop_run(g_mainloop);
1360
1361     g_dbus_connection_signal_unsubscribe(connection, id);
1362
1363 bootdone_out:
1364     if (g_mainloop != NULL) {
1365         g_main_loop_unref(g_mainloop);
1366     }
1367     if (connection != NULL) {
1368         g_object_unref(connection);
1369     }
1370     I("exit the bootdone_cb thread\n");
1371
1372     return NULL;
1373 }
1374
1375 void register_bootdone_cb()
1376 {
1377     sdb_thread_t t;
1378     if (sdb_thread_create(&t, bootdone_cb, NULL)) {
1379         E("can not create a service thread to check the booting done\n");
1380         return;
1381     }
1382     I("created the bootdone_cb thread\n");
1383 }
1384
1385 static int sdbd_set_groups(const char *name, int gid, struct group_info default_groups[], int default_groups_size) {
1386     gid_t *group_ids = NULL;
1387     int ngroups = 0;
1388     int i, j = 0;
1389     int group_match = 0;
1390     int added_group_cnt = 0;
1391
1392     if (getgrouplist(name, gid, NULL, &ngroups) == -1) {
1393         D("group list : ngroups = %d\n", ngroups);
1394     }
1395     group_ids = malloc((ngroups + default_groups_size) * sizeof(gid_t));
1396     if (group_ids == NULL) {
1397         E("failed to allocate group_ids(%zu)\n", (ngroups + default_groups_size) * sizeof(gid_t));
1398         return -1;
1399     }
1400     if (getgrouplist(name, gid, group_ids, &ngroups) == -1) {
1401         E("failed to getgrouplist(), ngroups = %d\n", ngroups);
1402         free(group_ids);
1403         return -1;
1404     }
1405     if(default_groups_size >= 1) {
1406         for (i = 0; default_groups[i].name != NULL; i++) {
1407             for (j = 0; j < ngroups; j++) {
1408                 if (group_ids[j] == default_groups[i].gid) {
1409                     group_match = 1;
1410                     break;
1411                 }
1412             }
1413             if (group_match == 0 && default_groups[i].gid != -1) {
1414                 group_ids[ngroups + added_group_cnt] = default_groups[i].gid;
1415                 added_group_cnt ++;
1416             }
1417             group_match = 0;
1418         }
1419     }
1420     if (setgroups(ngroups+added_group_cnt, group_ids) != 0) {
1421         E("failed to setgroups().\n");
1422         free(group_ids);
1423         return -1;
1424     }
1425
1426     free(group_ids);
1427     return 0;
1428 }
1429
1430 static int sdbd_get_user_pwd(const char* user_name, struct passwd* pwd, char* buf, size_t bufsize) {
1431     struct passwd *result = NULL;
1432     int ret = 0;
1433
1434     ret = getpwnam_r(user_name, pwd, buf, bufsize, &result);
1435     if (result == NULL) {
1436         if (ret == 0) {
1437             E("Not found passwd : username(%s)\n", user_name);
1438         } else {
1439             errno = ret;
1440             E("failed to getpwnam_r\n");
1441         }
1442         return -1;
1443     }
1444
1445     return 0;
1446 }
1447
1448 static int sdbd_get_group(const char* group_name, struct group* grp, char* buf, size_t bufsize) {
1449     struct group *result = NULL;
1450     int ret = 0;
1451
1452     ret = getgrnam_r(group_name, grp, buf, bufsize, &result);
1453     if (result == NULL) {
1454         if (ret == 0) {
1455             E("Not found group : groupname(%s)\n", group_name);
1456         } else {
1457             errno = ret;
1458             E("failed to getgrnam_r\n");
1459         }
1460         return -1;
1461     }
1462
1463     return 0;
1464 }
1465
1466 int set_sdk_user_privileges(int is_drop_capability_after_fork) {
1467     if (!is_init_sdk_userinfo) {
1468         E("failed to init sdk user information.\n");
1469         return -1;
1470     }
1471
1472     /*
1473     * If a process switches its real, effective, or saved uids from at least one being 0 to all being non-zero,
1474     * then both the permitted and effective capabilities are cleared.
1475     */
1476     if(is_drop_capability_after_fork) {
1477
1478         if (setuid(g_root_user_id) != 0) {
1479             E("set root user id failed (errno: %d)\n", errno);
1480             return -1;
1481         }
1482     }
1483
1484     if (sdbd_set_groups(SDK_USER_NAME, g_sdk_group_id, g_default_groups, SDB_DEFAULT_GROUPS_CNT) < 0) {
1485         E("set groups failed (errno: %d)\n", errno);
1486         return -1;
1487     }
1488
1489     if (setgid(g_sdk_group_id) != 0) {
1490         E("set group id failed (errno: %d)\n", errno);
1491         return -1;
1492     }
1493
1494     if (setuid(g_sdk_user_id) != 0) {
1495         E("set user id failed (errno: %d)\n", errno);
1496         return -1;
1497 //        if(is_drop_capability_after_fork) {
1498 //            return -1;
1499 //        }
1500     }
1501
1502     if (chdir(g_sdk_home_dir) < 0) {
1503         E("unable to change working directory to %s\n", g_sdk_home_dir);
1504     }
1505
1506     // TODO: use pam later
1507     if (g_sdk_home_dir_env) {
1508         putenv(g_sdk_home_dir_env);
1509     }
1510
1511     return 0;
1512 }
1513
1514 int set_root_privileges() {
1515
1516     if (sdbd_set_groups(ROOT_USER_NAME, g_root_group_id, NULL, 0) < 0) {
1517         E("set root groups failed (errno: %d)\n", errno);
1518     }
1519
1520     if (setgid(g_root_group_id) != 0) {
1521         E("set root group id failed (errno: %d)\n", errno);
1522     }
1523
1524     if (setuid(g_root_user_id) != 0) {
1525         E("set root user id failed (errno: %d)\n", errno);
1526     }
1527
1528     if (chdir(g_root_home_dir) < 0) {
1529         E("unable to change root working directory to %s\n", g_sdk_home_dir);
1530     }
1531
1532     // TODO: use pam later
1533     if (g_root_home_dir_env) {
1534         putenv(g_root_home_dir_env);
1535     }
1536
1537     return 0;
1538 }
1539
1540 #define SDB_PW_GR_DEFAULT_SIZE  (16*1024)
1541 static long get_passwd_bufsize() {
1542     long bufsize = 0;
1543
1544     bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
1545     if(bufsize < 0) {
1546         bufsize = SDB_PW_GR_DEFAULT_SIZE;
1547     }
1548
1549     return bufsize;
1550 }
1551
1552 static long get_group_bufsize() {
1553     long bufsize = 0;
1554
1555     bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
1556     if(bufsize < 0) {
1557         bufsize = SDB_PW_GR_DEFAULT_SIZE;
1558     }
1559
1560     return bufsize;
1561 }
1562
1563 static int init_sdb_default_groups() {
1564     struct group grp;
1565     char *buf = NULL;
1566     long bufsize = 0;
1567     int i = 0;
1568
1569     bufsize = get_group_bufsize();
1570     buf = malloc(bufsize);
1571     if (buf == NULL) {
1572         E("failed to allocate gruop buf(%ld)\n", bufsize);
1573         return -1;
1574     }
1575
1576     for (i = 0; g_default_groups[i].name != NULL; i++) {
1577         memset(buf, 0, bufsize);
1578         if (sdbd_get_group(g_default_groups[i].name, &grp, buf, bufsize) == 0) {
1579             g_default_groups[i].gid = grp.gr_gid;
1580         } else {
1581             E("failed get group info.(errno: %d)\n", errno);
1582         }
1583     }
1584
1585     free(buf);
1586     return 0;
1587 }
1588
1589 static void set_static_root_userinfo() {
1590     g_root_user_id = STATIC_ROOT_USER_ID;
1591     g_root_group_id = STATIC_ROOT_GROUP_ID;
1592     g_root_home_dir = STATIC_ROOT_HOME_DIR;
1593 }
1594
1595 static void set_static_sdk_userinfo() {
1596     g_sdk_user_id = STATIC_SDK_USER_ID;
1597     g_sdk_group_id = STATIC_SDK_GROUP_ID;
1598     g_sdk_home_dir = STATIC_SDK_HOME_DIR;
1599 }
1600
1601 static int init_root_userinfo() {
1602     struct passwd pwd;
1603     char *buf = NULL;
1604     long bufsize = 0;
1605
1606     bufsize = get_passwd_bufsize();
1607     buf = malloc(bufsize);
1608     if (buf == NULL) {
1609         E("failed to allocate passwd buf(%ld)\n", bufsize);
1610         set_static_root_userinfo();
1611     } else {
1612         if (sdbd_get_user_pwd(ROOT_USER_NAME, &pwd, buf, bufsize) < 0) {
1613             E("failed to get root user passwd info.(errno: %d)\n", errno);
1614             set_static_root_userinfo();
1615         } else {
1616             D("username=%s, uid=%d, gid=%d, dir=%s\n", pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_dir);
1617
1618             g_root_user_id = pwd.pw_uid;
1619             g_root_group_id = pwd.pw_gid;
1620             g_root_home_dir = strdup(pwd.pw_dir);
1621         }
1622         free(buf);
1623     }
1624
1625     int env_size = strlen("HOME=") + strlen(g_root_home_dir) + 1;
1626     g_root_home_dir_env = malloc(env_size);
1627     if(g_root_home_dir_env == NULL) {
1628         E("failed to allocate for home dir env string\n");
1629     } else {
1630         snprintf(g_root_home_dir_env, env_size, "HOME=%s", g_root_home_dir);
1631     }
1632
1633     return 0;
1634 }
1635
1636 static int init_sdk_userinfo() {
1637     struct passwd pwd;
1638     char *buf = NULL;
1639     long bufsize = 0;
1640
1641     if (is_init_sdk_userinfo) {
1642         return 0;
1643     }
1644
1645     if (init_sdb_default_groups() < 0) {
1646         E("failed to initialize default groups.\n");
1647     }
1648
1649     bufsize = get_passwd_bufsize();
1650     buf = malloc(bufsize);
1651     if (buf == NULL) {
1652         E("failed to allocate passwd buf(%ld)\n", bufsize);
1653         set_static_sdk_userinfo();
1654     } else {
1655         if (sdbd_get_user_pwd(SDK_USER_NAME, &pwd, buf, bufsize) < 0) {
1656             E("get user passwd info.(errno: %d)\n", errno);
1657             set_static_sdk_userinfo();
1658         } else {
1659             D("username=%s, uid=%d, gid=%d, dir=%s\n", pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_dir);
1660
1661             g_sdk_user_id = pwd.pw_uid;
1662             g_sdk_group_id = pwd.pw_gid;
1663             g_sdk_home_dir = strdup(pwd.pw_dir);
1664         }
1665         free(buf);
1666     }
1667
1668     int env_size = strlen("HOME=") + strlen(g_sdk_home_dir) + 1;
1669     g_sdk_home_dir_env = malloc(env_size);
1670     if(g_sdk_home_dir_env == NULL) {
1671         E("failed to allocate for home dir env string\n");
1672     } else {
1673         snprintf(g_sdk_home_dir_env, env_size, "HOME=%s", g_sdk_home_dir);
1674     }
1675
1676     is_init_sdk_userinfo = 1;
1677     return 0;
1678 }
1679
1680 static int safe_system(char *cmd, char *argv[], char *envp[]) {
1681     pid_t pid;
1682     int status;
1683
1684     pid = fork();
1685     switch (pid) {
1686         case -1:
1687             return -1;
1688         case 0:
1689             execve(cmd, argv, envp);
1690             E("- exec '%s' failed: (errno:%d) -\n", cmd, errno);
1691             exit(-1);
1692         default:
1693             for (;;) {
1694                 pid_t p = waitpid(pid, &status, 0);
1695                 if (p == pid) {
1696                     break;
1697                 }
1698             }
1699     }
1700     return 0;
1701 }
1702
1703 static void init_sdk_requirements() {
1704     struct stat st;
1705
1706     // set env variable for temporary
1707     // TODO: should use pam instead later!!
1708     putenv("TERM=linux");
1709     putenv("HOME=/root");
1710
1711     init_sdk_userinfo();
1712     init_root_userinfo();
1713
1714     if (g_sdk_home_dir != NULL && stat(g_sdk_home_dir, &st) == 0) {
1715         if (st.st_uid != g_sdk_user_id || st.st_gid != g_sdk_group_id) {
1716             char* cmd = "/usr/bin/chown";
1717             char params[128];
1718             char* envp[128];
1719             int envp_cnt = 0;
1720             int i = 0;
1721
1722             envp[envp_cnt++] = g_strdup("TERM=linux");
1723             envp[envp_cnt++] = g_strdup("DISPLAY=:0");
1724             envp[envp_cnt] = NULL;
1725
1726             snprintf(params, sizeof(params), "%s %s:%s %s -R", cmd, SDK_USER_NAME, SDK_USER_NAME, g_sdk_home_dir);
1727
1728             char* args[] = {
1729                 cmd,
1730                 params,
1731                 NULL,
1732             };
1733             if (safe_system(cmd, args, envp) < 0) {
1734                 E("failed to change ownership to sdk user to %s\n", g_sdk_home_dir);
1735             }
1736
1737             /* free environment variables */
1738             if (envp_cnt > 0) {
1739                 for (i = 0; i < envp_cnt; i++) {
1740                     if (envp[i]) {
1741                         g_free(envp[i]);
1742                     }
1743                 }
1744             }
1745         }
1746     }
1747
1748     if (is_emulator()) {
1749         register_bootdone_cb();
1750     }
1751 }
1752
1753 static void init_capabilities(void) {
1754     int ret = -1;
1755     char *value = NULL;
1756
1757     memset(&g_capabilities, 0, sizeof(g_capabilities));
1758
1759     // CPU Architecture of model
1760     ret = system_info_get_platform_string("http://tizen.org/feature/platform.core.cpu.arch", &value);
1761     if (ret != SYSTEM_INFO_ERROR_NONE) {
1762         snprintf(g_capabilities.cpu_arch, sizeof(g_capabilities.cpu_arch),
1763                     "%s", UNKNOWN);
1764         E("fail to get the CPU architecture of model:%d\n", errno);
1765     } else {
1766         snprintf(g_capabilities.cpu_arch, sizeof(g_capabilities.cpu_arch),
1767                     "%s", value);
1768         if (value != NULL) {
1769             free(value);
1770         }
1771     }
1772
1773
1774     // Secure protocol support
1775     if(!request_capability_to_plugin(CAPABILITY_SECURE, g_capabilities.secure_protocol,
1776                             sizeof(g_capabilities.secure_protocol))) {
1777         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_SECURE);
1778         snprintf(g_capabilities.secure_protocol, sizeof(g_capabilities.secure_protocol),
1779                     "%s", DISABLED);
1780     }
1781
1782
1783     // Interactive shell support
1784     if(!request_capability_to_plugin(CAPABILITY_INTER_SHELL, g_capabilities.intershell_support,
1785                             sizeof(g_capabilities.intershell_support))) {
1786         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_INTER_SHELL);
1787         snprintf(g_capabilities.intershell_support, sizeof(g_capabilities.intershell_support),
1788                     "%s", DISABLED);
1789     }
1790
1791
1792     // File push/pull support
1793     if(!request_capability_to_plugin(CAPABILITY_FILESYNC, g_capabilities.filesync_support,
1794                             sizeof(g_capabilities.filesync_support))) {
1795         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_FILESYNC);
1796         snprintf(g_capabilities.filesync_support, sizeof(g_capabilities.filesync_support),
1797                     "%s", DISABLED);
1798     }
1799
1800
1801     // USB protocol support
1802     if(!request_capability_to_plugin(CAPABILITY_USB_PROTOCOL, g_capabilities.usbproto_support,
1803                             sizeof(g_capabilities.usbproto_support))) {
1804         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_USB_PROTOCOL);
1805         snprintf(g_capabilities.usbproto_support, sizeof(g_capabilities.usbproto_support),
1806                     "%s", DISABLED);
1807     }
1808
1809
1810     // Socket protocol support
1811     if(!request_capability_to_plugin(CAPABILITY_SOCK_PROTOCOL, g_capabilities.sockproto_support,
1812                             sizeof(g_capabilities.sockproto_support))) {
1813         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_SOCK_PROTOCOL);
1814         snprintf(g_capabilities.sockproto_support, sizeof(g_capabilities.sockproto_support),
1815                     "%s", DISABLED);
1816     }
1817
1818     // Sdbd root permission
1819     snprintf(g_capabilities.root_permission, sizeof(g_capabilities.root_permission),
1820                 "%s", DISABLED);
1821
1822     // Root command support
1823     if(!request_capability_to_plugin(CAPABILITY_ROOT_ONOFF, g_capabilities.rootonoff_support,
1824                             sizeof(g_capabilities.rootonoff_support))) {
1825         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_ROOT_ONOFF);
1826         snprintf(g_capabilities.rootonoff_support, sizeof(g_capabilities.rootonoff_support),
1827                     "%s", DISABLED);
1828     }
1829
1830
1831     // Encryption support
1832     if(!request_capability_to_plugin(CAPABILITY_ENCRYPTION, g_capabilities.encryption_support,
1833                             sizeof(g_capabilities.encryption_support))) {
1834         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_ENCRYPTION);
1835         snprintf(g_capabilities.encryption_support, sizeof(g_capabilities.encryption_support),
1836                     "%s", DISABLED);
1837     }
1838
1839
1840     // Zone support
1841     ret = is_container_enabled();
1842     snprintf(g_capabilities.zone_support, sizeof(g_capabilities.zone_support),
1843                 "%s", ret == 1 ? ENABLED : DISABLED);
1844
1845     // Multi-User support
1846     // XXX: There is no clear way to determine whether multi-user support.
1847     // Since TZ_SYS_DEFAULT_USER is set to "owner" for multi-user support,
1848     // guess whether multiuser support through that information.
1849     const char* sys_default_user = tzplatform_getenv(TZ_SYS_DEFAULT_USER);
1850     if (sys_default_user != NULL && !strcmp(sys_default_user, "owner")) {
1851         snprintf(g_capabilities.multiuser_support, sizeof(g_capabilities.multiuser_support),
1852                     "%s", ENABLED);
1853     } else {
1854         snprintf(g_capabilities.multiuser_support, sizeof(g_capabilities.multiuser_support),
1855                     "%s", DISABLED);
1856     }
1857
1858     // Window size synchronization support
1859     snprintf(g_capabilities.syncwinsz_support, sizeof(g_capabilities.syncwinsz_support),
1860                 "%s", ENABLED);
1861
1862     // SDK Tool path
1863     if (SDK_TOOL_PATH == NULL) {
1864         E("fail to get SDK tool path.\n");
1865         snprintf(g_capabilities.sdk_toolpath, sizeof(g_capabilities.sdk_toolpath),
1866                     "%s", UNKNOWN);
1867     } else {
1868         snprintf(g_capabilities.sdk_toolpath, sizeof(g_capabilities.sdk_toolpath),
1869                     "%s", SDK_TOOL_PATH);
1870     }
1871
1872     // Profile name
1873     ret = system_info_get_platform_string("http://tizen.org/feature/profile", &value);
1874     if (ret != SYSTEM_INFO_ERROR_NONE) {
1875         snprintf(g_capabilities.profile_name, sizeof(g_capabilities.profile_name),
1876                     "%s", UNKNOWN);
1877         E("fail to get profile name:%d\n", errno);
1878     } else {
1879         snprintf(g_capabilities.profile_name, sizeof(g_capabilities.profile_name),
1880                     "%s", value);
1881         if (value != NULL) {
1882             free(value);
1883         }
1884     }
1885
1886
1887     // Vendor name
1888     ret = system_info_get_platform_string("http://tizen.org/system/manufacturer", &value);
1889     if (ret != SYSTEM_INFO_ERROR_NONE) {
1890         snprintf(g_capabilities.vendor_name, sizeof(g_capabilities.vendor_name),
1891                     "%s", UNKNOWN);
1892         E("fail to get the Vendor name:%d\n", errno);
1893     } else {
1894         snprintf(g_capabilities.vendor_name, sizeof(g_capabilities.vendor_name),
1895                     "%s", value);
1896         if (value != NULL) {
1897             free(value);
1898         }
1899     }
1900
1901
1902     // Target name of the launch possible
1903     if(!request_capability_to_plugin(CAPABILITY_CAN_LAUNCH, g_capabilities.can_launch,
1904                             sizeof(g_capabilities.can_launch))) {
1905         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_CAN_LAUNCH);
1906         snprintf(g_capabilities.can_launch, sizeof(g_capabilities.can_launch),
1907                     "%s", UNKNOWN);
1908     }
1909
1910
1911     // Device name
1912     value = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
1913     if(value) {
1914         snprintf(g_capabilities.device_name, sizeof(g_capabilities.device_name),
1915                 "%s", value);
1916         if (value != NULL) {
1917             free(value);
1918         }
1919     } else {
1920         snprintf(g_capabilities.device_name, sizeof(g_capabilities.device_name),
1921                 "%s", UNKNOWN);
1922         E("fail to get the Device name:%d\n", errno);
1923     }
1924
1925
1926     // Platform version
1927     ret = system_info_get_platform_string("http://tizen.org/feature/platform.version", &value);
1928     if (ret != SYSTEM_INFO_ERROR_NONE) {
1929         snprintf(g_capabilities.platform_version, sizeof(g_capabilities.platform_version),
1930                     "%s", UNKNOWN);
1931         E("fail to get platform version:%d\n", errno);
1932     } else {
1933         snprintf(g_capabilities.platform_version, sizeof(g_capabilities.platform_version),
1934                     "%s", value);
1935         if (value != NULL) {
1936             free(value);
1937         }
1938     }
1939
1940
1941     // Product version
1942     if(!request_capability_to_plugin(CAPABILITY_PRODUCT_VER, g_capabilities.product_version,
1943                             sizeof(g_capabilities.product_version))) {
1944         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_PRODUCT_VER);
1945         snprintf(g_capabilities.product_version, sizeof(g_capabilities.product_version),
1946                     "%s", UNKNOWN);
1947     }
1948
1949
1950     // Sdbd version
1951     snprintf(g_capabilities.sdbd_version, sizeof(g_capabilities.sdbd_version),
1952                 "%d.%d.%d", SDB_VERSION_MAJOR, SDB_VERSION_MINOR, SDB_VERSION_PATCH);
1953
1954
1955     // Sdbd plugin version
1956     if(!request_capability_to_plugin(CAPABILITY_PLUGIN_VER, g_capabilities.sdbd_plugin_version,
1957                             sizeof(g_capabilities.sdbd_plugin_version))) {
1958         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_PLUGIN_VER);
1959         snprintf(g_capabilities.sdbd_plugin_version, sizeof(g_capabilities.sdbd_plugin_version),
1960                     "%s", UNKNOWN);
1961     }
1962
1963
1964     // sdbd log enable
1965     if(!request_capability_to_plugin(CAPABILITY_LOG_ENABLE, g_capabilities.log_enable,
1966                                sizeof(g_capabilities.log_enable))) {
1967            E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_LOG_ENABLE);
1968            snprintf(g_capabilities.log_enable, sizeof(g_capabilities.log_enable),
1969                        "%s", DISABLED);
1970     }
1971
1972     // sdbd log path
1973     if(!request_capability_to_plugin(CAPABILITY_LOG_PATH, g_capabilities.log_path,
1974                                sizeof(g_capabilities.log_path))) {
1975            E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_LOG_PATH);
1976            snprintf(g_capabilities.log_path, sizeof(g_capabilities.log_path),
1977                        "%s", UNKNOWN);
1978     }
1979
1980     // Application command support
1981     if(!request_capability_to_plugin(CAPABILITY_APPCMD, g_capabilities.appcmd_support,
1982                                sizeof(g_capabilities.appcmd_support))) {
1983            E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_APPCMD);
1984            snprintf(g_capabilities.appcmd_support, sizeof(g_capabilities.appcmd_support),
1985                        "%s", UNKNOWN);
1986     }
1987
1988     // appid2pid support
1989     ret = is_appid2pid_supported();
1990     snprintf(g_capabilities.appid2pid_support, sizeof(g_capabilities.appid2pid_support),
1991                 "%s", ret == 1 ? ENABLED : DISABLED);
1992
1993     // pkgcmd debug mode support
1994     if(!request_capability_to_plugin(CAPABILITY_DEBUGMODE, g_capabilities.pkgcmd_debugmode,
1995                 sizeof(g_capabilities.pkgcmd_debugmode))) {
1996         E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_DEBUGMODE);
1997         snprintf(g_capabilities.pkgcmd_debugmode, sizeof(g_capabilities.pkgcmd_debugmode),
1998                 "%s", ENABLED);
1999     }
2000
2001     // netcore debugger support
2002     ret = is_netcoredbg_supported();
2003     snprintf(g_capabilities.netcoredbg_support, sizeof(g_capabilities.netcoredbg_support),
2004              "%s", ret == 1 ? ENABLED : DISABLED);
2005
2006     // Capability version
2007     snprintf(g_capabilities.sdbd_cap_version, sizeof(g_capabilities.sdbd_cap_version),
2008                 "%d.%d", SDBD_CAP_VERSION_MAJOR, SDBD_CAP_VERSION_MINOR);
2009 }
2010
2011 static int is_support_usbproto()
2012 {
2013     return (!strncmp(g_capabilities.usbproto_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
2014 }
2015
2016 static int is_support_sockproto()
2017 {
2018     return (!strncmp(g_capabilities.sockproto_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
2019 }
2020
2021 #define EMULATOR_MODEL_NAME     "Emulator"
2022 static void check_emulator_or_device()
2023 {
2024     char model_name[256]={0,};
2025     int ret = -1;
2026
2027     // Get the model name from model_config.xml
2028     ret = get_device_name(model_name, sizeof model_name);
2029     if (ret == 0) {
2030         if(!strncmp(model_name, EMULATOR_MODEL_NAME, sizeof(EMULATOR_MODEL_NAME))){
2031             g_is_emulator = 1;
2032             I("This target type is Emulator\n");
2033         } else {
2034             g_is_emulator = 0;
2035             I("This target type is Device\n");
2036         }
2037     } else {
2038         g_is_emulator = -1;
2039         E("failed to get the model name.\n");
2040     }
2041 }
2042
2043 static void fork_prepare_handler(void)
2044 {
2045     sdb_mutex_lock(&D_lock);
2046 }
2047
2048 static void fork_parent_handler(void)
2049 {
2050     sdb_mutex_unlock(&D_lock);
2051 }
2052
2053 static void fork_child_handler(void)
2054 {
2055     sdb_mutex_unlock(&D_lock);
2056 }
2057
2058 int sdb_main(int server_port)
2059 {
2060     check_emulator_or_device();
2061
2062     load_sdbd_plugin();
2063
2064     init_capabilities();
2065
2066     //sdb_trace_init();
2067     //start_device_log();
2068
2069     init_drop_privileges();
2070     init_sdk_requirements();
2071     if (!request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_LAUNCH, NULL)) {
2072         E("sdbd should be launched in develop mode.\n");
2073         return -1;
2074     }
2075
2076     umask(000);
2077
2078     pthread_atfork(fork_prepare_handler, fork_parent_handler, fork_child_handler);
2079
2080     atexit(sdb_cleanup);
2081 #if defined(HAVE_FORKEXEC)
2082     // No SIGCHLD. Let the service subproc handle its children.
2083     signal(SIGPIPE, SIG_IGN);
2084 #endif
2085
2086     init_transport_registration();
2087
2088     /* don't listen on a port (default 5037) if running in secure mode */
2089     /* don't run as root if we are running in secure mode */
2090
2091     if (should_drop_privileges()) {
2092 # if 0
2093         struct __user_cap_header_struct header;
2094         struct __user_cap_data_struct cap;
2095
2096         if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
2097             exit(1);
2098         }
2099         /* add extra groups:
2100         ** SID_TTY to access /dev/ptmx
2101         */
2102         gid_t groups[] = { SID_TTY, SID_APP_LOGGING, SID_SYS_LOGGING };
2103         if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
2104             exit(1);
2105         }
2106         /* then switch user and group to "developer" */
2107         if (setgid(GID_DEVELOPER) != 0) {
2108             fprintf(stderr, "set group id failed errno: %d\n", errno);
2109             exit(1);
2110         }
2111         if (setuid(SID_DEVELOPER) != 0) {
2112             fprintf(stderr, "set user id failed errno: %d\n", errno);
2113             exit(1);
2114         }
2115
2116         /* set CAP_SYS_BOOT capability, so "sdb reboot" will succeed */
2117         header.version = _LINUX_CAPABILITY_VERSION;
2118         header.pid = 0;
2119         cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
2120         cap.inheritable = 0;
2121         capset(&header, &cap);
2122 #endif
2123         I("Local port disabled\n");
2124     } else {
2125         char local_name[30];
2126         build_local_name(local_name, sizeof(local_name), server_port);
2127         if(install_listener(local_name, "*smartsocket*", NULL)) {
2128             exit(1);
2129         }
2130     }
2131
2132     /* choose the usb gadget backend */
2133     if (access(USB_NODE_FILE, F_OK) == 0) {
2134         /* legacy kernel-based sdb gadget */
2135         usb_init =    &linux_usb_init;
2136         usb_cleanup = &linux_usb_cleanup;
2137         usb_write =   &linux_usb_write;
2138         usb_read =    &linux_usb_read;
2139         usb_close =   &linux_usb_close;
2140         usb_kick =    &linux_usb_kick;
2141     } else {
2142         /* functionfs based gadget */
2143         usb_init =    &ffs_usb_init;
2144         usb_cleanup = &ffs_usb_cleanup;
2145         usb_write =   &ffs_usb_write;
2146         usb_read =    &ffs_usb_read;
2147         usb_close =   &ffs_usb_close;
2148         usb_kick =    &ffs_usb_kick;
2149     }
2150
2151     if (is_support_usbproto()) {
2152         // listen on USB
2153         usb_init();
2154     }
2155     if (is_support_sockproto()) {
2156         /* by default don't listen on local transport but
2157          * listen if suitable command line argument has been provided */
2158         if (sdbd_commandline_args.sdbd_port >= 0) {
2159             local_init(sdbd_commandline_args.sdbd_port);
2160         } else {
2161             local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT);
2162         }
2163     }
2164
2165 #if 0 /* tizen specific */
2166     D("sdb_main(): pre init_jdwp()\n");
2167     init_jdwp();
2168     D("sdb_main(): post init_jdwp()\n");
2169 #endif
2170
2171     sdb_notify_startup(0, "READY=1");
2172
2173     I("Event loop starting\n");
2174
2175     fdevent_loop();
2176
2177     if (is_support_usbproto()) {
2178         usb_cleanup();
2179     }
2180
2181     return 0;
2182 }
2183
2184 int copy_packet(apacket* dest, apacket* src) {
2185
2186     if(dest == NULL) {
2187         E("dest packet is NULL\n");
2188         return -1;
2189     }
2190
2191     if(src == NULL) {
2192         E("src packet is NULL\n");
2193         return -1;
2194     }
2195
2196     dest->next = src->next;
2197     dest->ptr = src->ptr;
2198     dest->len = src->len;
2199
2200     int data_length = src->msg.data_length;
2201     if(data_length > MAX_PAYLOAD) {
2202         data_length = MAX_PAYLOAD;
2203     }
2204     memcpy(&(dest->msg), &(src->msg), sizeof(amessage) + data_length);
2205
2206     return 0;
2207 }
2208
2209 int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
2210 {
2211     atransport *transport = NULL;
2212     char buf[4096];
2213
2214     if(!strcmp(service, "kill")) {
2215         fprintf(stderr,"sdb server killed by remote request\n");
2216         fflush(stdout);
2217         sdb_write(reply_fd, "OKAY", 4);
2218         if (is_support_usbproto()) {
2219             usb_cleanup();
2220         }
2221         exit(0);
2222     }
2223
2224     if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) {
2225         char *local, *remote, *err;
2226         int r;
2227         atransport *transport;
2228
2229         int createForward = strncmp(service,"kill",4);
2230
2231         local = service + (createForward ? 8 : 12);
2232         remote = strchr(local,';');
2233         if(remote == 0) {
2234             sendfailmsg(reply_fd, "malformed forward spec");
2235             return 0;
2236         }
2237
2238         *remote++ = 0;
2239         if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
2240             sendfailmsg(reply_fd, "malformed forward spec");
2241             return 0;
2242         }
2243
2244         transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
2245         if (!transport) {
2246             sendfailmsg(reply_fd, err);
2247             return 0;
2248         }
2249
2250         if (createForward) {
2251             r = install_listener(local, remote, transport);
2252         } else {
2253             r = remove_listener(local, remote, transport);
2254         }
2255         if(r == 0) {
2256                 /* 1st OKAY is connect, 2nd OKAY is status */
2257             writex(reply_fd, "OKAYOKAY", 8);
2258             return 0;
2259         }
2260
2261         if (createForward) {
2262             sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket");
2263         } else {
2264             sendfailmsg(reply_fd, "cannot remove listener");
2265         }
2266         return 0;
2267     }
2268
2269     if(!strncmp(service,"get-state",strlen("get-state"))) {
2270         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
2271         char *state = connection_state_name(transport);
2272         snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state);
2273         writex(reply_fd, buf, strlen(buf));
2274         return 0;
2275     }
2276     return -1;
2277 }
2278
2279 int recovery_mode = 0;
2280
2281 int main(int argc, char **argv)
2282 {
2283     /* If sdbd runs inside the emulator this will enable sdb tracing via
2284      * sdb-debug qemud service in the emulator. */
2285 #if 0 /* tizen specific */
2286     sdb_qemu_trace_init();
2287     if((argc > 1) && (!strcmp(argv[1],"recovery"))) {
2288         sdb_device_banner = "recovery";
2289         recovery_mode = 1;
2290     }
2291 #endif
2292
2293     apply_sdbd_commandline_defaults(&sdbd_commandline_args);
2294     int parse_ret = parse_sdbd_commandline(&sdbd_commandline_args, argc, argv);
2295
2296     // TODO: Add detailed error messages
2297     // TODO: Add individual messages for help and usage
2298     if(parse_ret != SDBD_COMMANDLINE_SUCCESS) {
2299         if (parse_ret == SDBD_COMMANDLINE_HELP
2300                 || parse_ret == SDBD_COMMANDLINE_USAGE) {
2301             // User requested help or usage
2302             print_sdbd_usage_message(stdout);
2303             return EXIT_SUCCESS;
2304         }
2305
2306         // Print usage message because of invalid options
2307         print_sdbd_usage_message(stderr);
2308         return EXIT_FAILURE;
2309     }
2310
2311     I("Handling main()\n");
2312
2313     //sdbd will never die on emulator!
2314     signal(SIGTERM, handle_sig_term); /* tizen specific */
2315     return sdb_main(DEFAULT_SDB_PORT);
2316 }