2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #define TRACE_TAG TRACE_APPCMD
31 #include "parameter.h"
32 #include "sdbd_plugin.h"
34 #if APPCMD_USING_PKGMGR
35 #include <pkgmgr-info.h>
36 #include <package-manager.h>
39 #include <tzplatform_config.h>
41 #define APPCMD_RESULT_BUFSIZE (4096)
43 typedef struct appcmd_info appcmd_info;
44 typedef int (*appcmd_gen_shellcmd)(appcmd_info*);
45 typedef void (*appcmd_receiver)(int, int);
49 char* args[MAX_TOKENS];
53 appcmd_gen_shellcmd gen_cmd_func;
54 appcmd_receiver receiver_func;
56 char shell_cmd[SDBD_SHELL_CMD_MAX];
61 static int appcmd_install_gen_shellcmd(appcmd_info* p_info) {
66 char *buf = p_info->shell_cmd;
67 int len = sizeof(p_info->shell_cmd);
69 if (p_info->args_cnt != 5) {
70 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
74 type = p_info->args[1];
75 pkgpath = p_info->args[2];
76 pkgid = p_info->args[3];
77 teppath = p_info->args[4];
79 D("args: type=%s, pkgpath=%s, pkgid=%s, teppath=%s\n", type, pkgpath, pkgid, teppath);
81 if (strncmp(pkgid, "null", 4) == 0) {
82 if (strncmp(teppath, "null", 4) == 0) {
83 /* Normal install case */
84 snprintf(buf, len, "pkgcmd -i -q -t %s -p %s -G", type, pkgpath);
86 /* TEP install case */
87 snprintf(buf, len, "pkgcmd -i -q -p %s -e %s -G", pkgpath, teppath);
91 snprintf(buf, len, "pkgcmd -r -q -t %s -n %s", type, pkgid);
97 static int appcmd_uninstall_gen_shellcmd(appcmd_info* p_info) {
100 char *buf = p_info->shell_cmd;
101 int len = sizeof(p_info->shell_cmd);
103 if (p_info->args_cnt != 3) {
104 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
108 type = p_info->args[1];
109 pkgid = p_info->args[2];
111 D("args: type=%s, pkgid=%s\n", type, pkgid);
113 snprintf(buf, len, "pkgcmd -u -q -t %s -n %s", type, pkgid);
118 static int appcmd_runapp_gen_shellcmd(appcmd_info* p_info) {
120 char *buf = p_info->shell_cmd;
121 int len = sizeof(p_info->shell_cmd);
123 if (p_info->args_cnt != 2) {
124 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
128 appid = p_info->args[1];
130 D("args: appid=%s\n", appid);
132 snprintf(buf, len, "/usr/bin/app_launcher --start %s", appid);
137 static int appcmd_rununittestapp_gen_shellcmd(appcmd_info* p_info) {
139 char *usr_args = NULL;
140 char *buf = p_info->shell_cmd;
141 int len = sizeof(p_info->shell_cmd);
143 char *p_service = NULL;
144 char *p_appid = NULL;
146 free_strings(p_info->args, p_info->args_cnt);
148 p_service = strtok_r(p_info->raw_command, ":", &ptr);
149 p_appid = strtok_r(NULL, ":", &ptr);
150 if (p_service == NULL || p_appid == NULL) {
151 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
155 p_info->args_cnt = 3;
156 p_info->args[0] = strdup(p_service);
157 p_info->args[1] = strdup(p_appid);
158 p_info->args[2] = strdup(ptr);
160 appid = p_info->args[1];
161 usr_args = p_info->args[2];
163 D("args: appid=%s, usr_args=%s\n", appid, usr_args);
165 snprintf(buf, len, "/usr/bin/app_launcher -s %s __AUL_SDK__ UNIT_TEST __LAUNCH_APP_MODE__ SYNC __DLP_UNIT_TEST_ARG__ \'%s\'", appid, usr_args);
170 static int appcmd_killapp_gen_shellcmd(appcmd_info* p_info) {
172 char *buf = p_info->shell_cmd;
173 int len = sizeof(p_info->shell_cmd);
175 if (p_info->args_cnt != 2) {
176 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
180 appid = p_info->args[1];
182 D("args: appid=%s\n", appid);
184 snprintf(buf, len, "/usr/bin/app_launcher --kill %s", appid);
189 static int appcmd_packagelist_gen_shellcmd(appcmd_info* p_info) {
191 char *buf = p_info->shell_cmd;
192 int len = sizeof(p_info->shell_cmd);
194 if (p_info->args_cnt != 2) {
195 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
199 type = p_info->args[1];
201 D("args: type=%s\n", type);
203 snprintf(buf, len, "/usr/bin/pkgcmd -l -t %s", type);
208 static int appcmd_debugwebapp_gen_shellcmd(appcmd_info* p_info) {
210 char *buf = p_info->shell_cmd;
211 int len = sizeof(p_info->shell_cmd);
213 if (p_info->args_cnt != 2) {
214 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
218 appid = p_info->args[1];
220 D("args: appid=%s\n", appid);
222 snprintf(buf, len, "/usr/bin/app_launcher --start %s -w", appid);
227 static int appcmd_debugnativeapp_gen_shellcmd(appcmd_info* p_info) {
228 char *debug_port = NULL;
230 char *pid_str = NULL;
231 char *gdbserver_path = NULL;
232 char *buf = p_info->shell_cmd;
234 int len = sizeof(p_info->shell_cmd);
236 if (p_info->args_cnt != 5) {
237 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
241 debug_port = p_info->args[1];
242 appid= p_info->args[2];
243 pid_str = p_info->args[3];
244 gdbserver_path = p_info->args[4]; // not used. for 3.0 platform.
247 D("args: debug_port=%s, appid=%s, pid=%d, gdbserver_path=%s\n", debug_port, appid, pid, gdbserver_path);
250 snprintf(buf, len, "/usr/bin/app_launcher --start %s __AUL_SDK__ DEBUG __DLP_DEBUG_ARG__ :%s __DLP_GDBSERVER_PATH__ %s", appid, debug_port, gdbserver_path);
253 snprintf(buf, len, "/usr/bin/launch_debug %s __AUL_SDK__ ATTACH __DLP_GDBSERVER_PATH__ %s __DLP_ATTACH_ARG__ --attach,:%s,%d", appid, gdbserver_path, debug_port, pid);
259 static int appcmd_appinfo_gen_shellcmd(appcmd_info* p_info) {
261 char *buf = p_info->shell_cmd;
262 int len = sizeof(p_info->shell_cmd);
264 if (p_info->args_cnt != 2) {
265 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
269 pkgid = p_info->args[1];
271 D("args: pkgid=%s\n", pkgid);
273 snprintf(buf, len, "/usr/bin/pkginfo --list %s", pkgid);
278 static void appcmd_receiver_debugwebapp(int fd_in, int fd_out)
280 char buf[4096] = {0,};
281 char port_str[32] = {0,};
282 char out_buf[128] = {0,};
283 char* sub_str = NULL;
287 memset(buf, 0, sizeof(buf));
288 r = read_line(fd_in, buf, sizeof(buf));
292 if (errno == EINTR) {
299 D("debug webapp output : %s\n", buf);
300 sub_str = strstr(buf, "port: ");
301 if (sub_str != NULL && sscanf(sub_str, "port: %s", port_str) == 1) {
302 snprintf(out_buf, sizeof(out_buf), "\n%s:%s\n", MESSAGE_PREFIX_APPCMD_RETURN, port_str);
303 writex(fd_out, out_buf, strlen(out_buf)+1);
309 static void appcmd_receiver_default(int fd_in, int fd_out)
311 char buf[4096] = {0,};
315 memset(buf, 0, sizeof(buf));
316 r = sdb_read(fd_in, buf, sizeof(buf));
320 if (errno == EINTR) {
327 writex(fd_out, buf, strlen(buf)+1);
331 static void appcmd_receiver_packagelist(int fd_in, int fd_out)
333 char buf[4096] = {0,};
334 char out_buf[4096] = {0,};
338 snprintf(out_buf, sizeof(out_buf), "\n%s", MESSAGE_PREFIX_APPCMD_RETURN);
339 out_ptr = strlen(out_buf);
342 memset(buf, 0, sizeof(buf));
343 r = read_line(fd_in, buf, sizeof(buf));
347 if (errno == EINTR) {
354 D("pkgcmd output : %s\n", buf);
357 sub1 = strstr(buf, "pkgid [");
359 sub1 = strstr(sub1, "[")+1;
360 sub2 = strstr(sub1, "]");
363 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", sub1);
364 out_ptr += strlen(sub1)+1;
368 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, "\n");
370 D("package list: %s\n", out_buf);
371 writex(fd_out, out_buf, strlen(out_buf)+1);
374 static void appcmd_receiver_appinfo(int fd_in, int fd_out)
376 char buf[4096] = {0,};
377 char out_buf[4096] = {0,};
378 char appid[128] = {0,};
379 char apptype[128] = {0,};
383 snprintf(out_buf, sizeof(out_buf), "\n%s", MESSAGE_PREFIX_APPCMD_RETURN);
384 out_ptr = strlen(out_buf);
387 memset(buf, 0, sizeof(buf));
388 r = read_line(fd_in, buf, sizeof(buf));
392 if (errno == EINTR) {
399 D("pkginfo output : %s\n", buf);
401 if (!strncmp(buf, "Appid: ", 7)) {
402 memset(appid, 0, sizeof(appid));
403 sscanf(buf, "Appid: %s", appid);
405 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", appid);
406 out_ptr += strlen(appid)+1;
407 } else if (!strncmp(buf, "Apptype: ", 9)) {
408 memset(apptype, 0, sizeof(apptype));
409 sscanf(buf, "Apptype: %s", apptype);
411 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", apptype);
412 out_ptr += strlen(apptype)+1;
416 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, "\n");
418 D("app info: %s\n", out_buf);
419 writex(fd_out, out_buf, strlen(out_buf)+1);
422 static int exec_appcmd_shell_process(appcmd_info* p_info) {
426 char *trim_value = NULL;
428 memset(path, 0, sizeof(path));
431 "TERM=linux", /* without this, some programs based on screen can't work, e.g. top */
432 "DISPLAY=:0", /* without this, some programs based on without launchpad can't work */
440 // For the SDK user privilege.
441 envp[2] = "HOME=/home/developer";
442 get_env("ENV_PATH", &value);
444 trim_value = str_trim(value);
445 if (trim_value != NULL) {
446 // if string is not including 'PATH=', append it.
447 if (strncmp(trim_value, "PATH", 4)) {
448 snprintf(path, sizeof(path), "PATH=%s", trim_value);
450 snprintf(path, sizeof(path), "%s", trim_value);
459 D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]);
467 args[2] = p_info->shell_cmd;
469 ptm_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp);
470 D("create_subprocess() ptm_fd=%d pid=%d\n", ptm_fd, pid);
472 D("cannot create service thread\n");
476 if (p_info->receiver_func != NULL) {
477 p_info->receiver_func(ptm_fd, p_info->fd);
480 // wait for shell process
483 pid_t p = waitpid(pid, &status, 0);
485 D("fd=%d, post waitpid(pid=%d) status=%04x\n", p_info->fd, p, status);
487 if (WIFEXITED(status)) {
488 p_info->exitcode = WEXITSTATUS(status);
489 D("*** Exit code %d\n", p_info->exitcode);
494 D("shell exited fd=%d of pid=%d err=%d\n", p_info->fd, pid, errno);
499 #if APPCMD_USING_PKGMGR
500 static int get_pkg_info(char* pkgid, char* pkginfo_buf, int buf_size) {
501 pkgmgrinfo_pkginfo_h handle;
502 pkgmgr_client* pc = NULL;
503 char* pkgname = NULL;
505 bool is_removable = 0;
510 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
512 D("failed to get pkginfo handle.\n");
516 ret = pkgmgrinfo_pkginfo_get_mainappid(handle, &pkgname);
518 D("failed to get pkg name\n");
522 ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
524 D("failed to get pkg type.\n");
528 ret = pkgmgrinfo_pkginfo_is_removable(handle, &is_removable);
530 D("failed to get removable info.\n");
534 pc = pkgmgr_client_new(PC_REQUEST);
536 D("failed to create pkgmgr client.\n");
540 ret = pkgmgr_client_request_service(PM_REQUEST_CHECK_APP, 0, pc, NULL, pkgid, NULL, NULL, &pid);
542 D("failed to get running state.\n");
545 is_running = ((pid > 0) ? 1:0);
547 D("pkginfo: pkgname=%s, type=%s, is_removagle=%d, is_running=%d, pid=%d\n", pkgname, type, is_removable, is_running, pid);
548 snprintf(pkginfo_buf, buf_size, "%s:%s:%d:%d", pkgname, type, is_removable, is_running);
552 static void run_appcmd_packageinfo(appcmd_info* p_info) {
553 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
554 char pkginfo_buf[256] = {0,};
558 p_info->exitcode = -1;
560 if (p_info->args_cnt != 3) {
561 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
565 type = p_info->args[1];
566 pkgid= p_info->args[2];
568 D("args: type=%s, pkgid=%s\n", type, pkgid);
570 if (get_pkg_info(pkgid, pkginfo_buf, sizeof(pkginfo_buf)) == 0) {
571 D("success to get pkginfo. (%s)\n", pkginfo_buf);
572 p_info->exitcode = 0;
573 snprintf(result_buf, sizeof(result_buf), "\n%s:%s\n", MESSAGE_PREFIX_APPCMD_RETURN, pkginfo_buf);
574 writex(p_info->fd, result_buf, strlen(result_buf));
576 D("failed to get pkginfo.\n");
580 static int appcmd_packageinfo_gen_shellcmd(appcmd_info* p_info) {
582 char *buf = p_info->shell_cmd;
583 int len = sizeof(p_info->shell_cmd);
585 if (p_info->args_cnt != 2) {
586 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
590 pkgid = p_info->args[1];
592 D("args: pkgid=%s\n", pkgid);
594 snprintf(buf, len, "/usr/bin/pkginfo --pkg %s;/usr/bin/pkgcmd -C -n %s", pkgid, pkgid);
599 static void appcmd_receiver_packageinfo(int fd_in, int fd_out)
601 char buf[4096] = {0,};
602 char mainapp_id[128] = {0,};
603 char type[128] = {0,};
604 int is_removable = 0;
609 memset(buf, 0, sizeof(buf));
610 r = read_line(fd_in, buf, sizeof(buf));
614 if (errno == EINTR) {
621 if (!strncmp(buf, "mainappid : ", 12)) {
622 sscanf(buf, "mainappid : %s", mainapp_id);
623 } else if (!strncmp(buf, "Type: ", 6)) {
624 sscanf(buf, "Type: %s", type);
625 } else if (!strncmp(buf, "Removable: ", 11)) {
626 sscanf(buf, "Removable: %d", &is_removable);
627 } else if (strstr(buf, " is Running") != NULL) {
632 memset(buf, 0, sizeof(buf));
633 snprintf(buf, sizeof(buf), "\n%s:%s:%s:%d:%d\n",
634 MESSAGE_PREFIX_APPCMD_RETURN, mainapp_id, type, is_removable, is_running);
636 D("package info: %s\n", buf);
637 writex(fd_out, buf, strlen(buf)+1);
641 static void run_appcmd_appinstallpath(appcmd_info* p_info) {
642 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
644 p_info->exitcode = -1;
646 const char* path = tzplatform_getenv(TZ_SDK_HOME);
648 p_info->exitcode = 0;
649 snprintf(result_buf, sizeof(result_buf), "\n%s:%s/apps_rw/\n", MESSAGE_PREFIX_APPCMD_RETURN, path);
650 writex(p_info->fd, result_buf, strlen(result_buf));
652 D("failed to get application install path from tzplatform_getenv.");
656 static void run_appcmd_with_shell_process(appcmd_info* p_info) {
659 if (p_info == NULL || p_info->gen_cmd_func == NULL) {
660 D("Invalid arguments.\n");
661 p_info->exitcode = -1;
665 ret = p_info->gen_cmd_func(p_info);
667 D("failed to generate install shell command.\n");
668 p_info->exitcode = -1;
670 ret = exec_appcmd_shell_process(p_info);
671 D("exec_appcmd_shell_process: ret=%d, exitcode=%d\n", ret, p_info->exitcode);
673 D("failed to run shell process\n");
674 p_info->exitcode = -1;
679 int appcmd_service( parameters* in, int out_fd ) {
681 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
682 char* service_name = NULL;
683 char* command = NULL;
685 if (in == NULL || in->number_of_parameter != 1 || in->array_of_parameter == NULL
686 || in->array_of_parameter[0].type != type_string) {
687 D ( "Invalid argument\n" );
688 return PLUGIN_CMD_FAIL;
691 command = in->array_of_parameter[0].v_string.data;
692 D("command=%s(FD:%d)\n", command, out_fd);
694 memset(&info, 0, sizeof(info));
696 /* appcmd parameter data map
697 * "service name:arg1:arg2:...:argN" */
698 info.args_cnt = tokenize(command, ":", info.args, MAX_TOKENS);
699 D("args_cnt=%d\n", info.args_cnt);
700 if (info.args_cnt < 1) {
701 D("failed to parse appcmd for install. (%s)\n", command);
708 info.raw_command = command;
710 service_name = info.args[0];
711 D("service name=%s\n", service_name);
713 if (strncmp(service_name, "install", 7) == 0) {
714 info.receiver_func = appcmd_receiver_default;
715 info.gen_cmd_func = appcmd_install_gen_shellcmd;
716 run_appcmd_with_shell_process(&info);
718 if (info.args[2] != NULL) {
719 sdb_unlink(info.args[2]);
721 } else if (strncmp(service_name, "uninstall", 9) == 0) {
722 info.receiver_func = appcmd_receiver_default;
723 info.gen_cmd_func = appcmd_uninstall_gen_shellcmd;
724 run_appcmd_with_shell_process(&info);
725 } else if (strncmp(service_name, "appinfo", 7) == 0) {
726 info.gen_cmd_func = appcmd_appinfo_gen_shellcmd;
727 info.receiver_func = appcmd_receiver_appinfo;
728 run_appcmd_with_shell_process(&info);
729 } else if (strncmp(service_name, "packageinfo", 11) == 0) {
730 #if APPCMD_USING_PKGMGR
731 run_appcmd_packageinfo(&info);
733 info.gen_cmd_func = appcmd_packageinfo_gen_shellcmd;
734 info.receiver_func = appcmd_receiver_packageinfo;
735 run_appcmd_with_shell_process(&info);
737 } else if (strncmp(service_name, "packagelist", 11) == 0) {
738 info.gen_cmd_func = appcmd_packagelist_gen_shellcmd;
739 info.receiver_func = appcmd_receiver_packagelist;
740 run_appcmd_with_shell_process(&info);
741 } else if (strncmp(service_name, "appinstallpath", 14) == 0) {
742 run_appcmd_appinstallpath(&info);
743 } else if (strncmp(service_name, "runapp", 6) == 0) {
744 info.receiver_func = appcmd_receiver_default;
745 info.gen_cmd_func = appcmd_runapp_gen_shellcmd;
746 run_appcmd_with_shell_process(&info);
747 } else if (strncmp(service_name, "rununittestapp", 14) == 0) {
748 info.receiver_func = appcmd_receiver_default;
749 info.gen_cmd_func = appcmd_rununittestapp_gen_shellcmd;
750 run_appcmd_with_shell_process(&info);
751 } else if (strncmp(service_name, "killapp", 7) == 0) {
752 info.receiver_func = appcmd_receiver_default;
753 info.gen_cmd_func = appcmd_killapp_gen_shellcmd;
754 run_appcmd_with_shell_process(&info);
755 } else if (strncmp(service_name, "debugwebapp", 11) == 0) {
756 info.gen_cmd_func = appcmd_debugwebapp_gen_shellcmd;
757 info.receiver_func = appcmd_receiver_debugwebapp;
758 run_appcmd_with_shell_process(&info);
759 } else if (strncmp(service_name, "debugnativeapp", 14) == 0) {
760 info.gen_cmd_func = appcmd_debugnativeapp_gen_shellcmd;
761 run_appcmd_with_shell_process(&info);
763 D("not supported appcmd service. (%s)\n", service_name);
769 free_strings(info.args, info.args_cnt);
771 snprintf(result_buf, sizeof(result_buf), "\n%s:%d\n", MESSAGE_PREFIX_APPCMD_EXITCODE, info.exitcode);
772 writex(out_fd, result_buf, strlen(result_buf));
774 if (info.exitcode != 0) {
775 return PLUGIN_CMD_FAIL;
778 return PLUGIN_CMD_SUCCESS;