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 SHELL_COMMAND "/bin/sh"
42 #define APPCMD_RESULT_BUFSIZE (4096)
44 typedef struct appcmd_info appcmd_info;
45 typedef int (*appcmd_gen_shellcmd)(appcmd_info*);
46 typedef void (*appcmd_receiver)(int, int);
50 char* args[MAX_TOKENS];
54 appcmd_gen_shellcmd gen_cmd_func;
55 appcmd_receiver receiver_func;
57 char shell_cmd[SDBD_SHELL_CMD_MAX];
62 static int appcmd_install_gen_shellcmd(appcmd_info* p_info) {
67 char *buf = p_info->shell_cmd;
68 int len = sizeof(p_info->shell_cmd);
70 if (p_info->args_cnt != 5) {
71 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
75 type = p_info->args[1];
76 pkgpath = p_info->args[2];
77 pkgid = p_info->args[3];
78 teppath = p_info->args[4];
80 D("args: type=%s, pkgpath=%s, pkgid=%s, teppath=%s\n", type, pkgpath, pkgid, teppath);
82 if (strncmp(pkgid, "null", 4) == 0) {
83 if (strncmp(teppath, "null", 4) == 0) {
84 /* Normal install case */
85 snprintf(buf, len, "pkgcmd -i -q -t %s -p %s -G", type, pkgpath);
87 /* TEP install case */
88 snprintf(buf, len, "pkgcmd -i -q -p %s -e %s -G", pkgpath, teppath);
92 snprintf(buf, len, "pkgcmd -r -q -t %s -n %s", type, pkgid);
98 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 != 2) {
104 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
108 pkgid = p_info->args[1];
110 D("args: pkgid=%s\n", pkgid);
112 snprintf(buf, len, "pkgcmd -u -q -n %s", pkgid);
117 static int appcmd_runapp_gen_shellcmd(appcmd_info* p_info) {
119 char *buf = p_info->shell_cmd;
120 int len = sizeof(p_info->shell_cmd);
122 if (p_info->args_cnt != 2) {
123 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
127 appid = p_info->args[1];
129 D("args: appid=%s\n", appid);
131 snprintf(buf, len, "/usr/bin/app_launcher --start %s", appid);
136 static int appcmd_rununittestapp_gen_shellcmd(appcmd_info* p_info) {
138 char *usr_args = NULL;
139 char *buf = p_info->shell_cmd;
140 int len = sizeof(p_info->shell_cmd);
142 char *p_service = NULL;
143 char *p_appid = NULL;
145 free_strings(p_info->args, p_info->args_cnt);
147 p_service = strtok_r(p_info->raw_command, ":", &ptr);
148 p_appid = strtok_r(NULL, ":", &ptr);
149 if (p_service == NULL || p_appid == NULL) {
150 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
154 p_info->args_cnt = 3;
155 p_info->args[0] = strdup(p_service);
156 p_info->args[1] = strdup(p_appid);
157 p_info->args[2] = strdup(ptr);
159 appid = p_info->args[1];
160 usr_args = p_info->args[2];
162 D("args: appid=%s, usr_args=%s\n", appid, usr_args);
164 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);
169 static int appcmd_killapp_gen_shellcmd(appcmd_info* p_info) {
171 char *buf = p_info->shell_cmd;
172 int len = sizeof(p_info->shell_cmd);
174 if (p_info->args_cnt != 2) {
175 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
179 appid = p_info->args[1];
181 D("args: appid=%s\n", appid);
183 snprintf(buf, len, "/usr/bin/app_launcher --kill %s", appid);
188 static int appcmd_packagelist_gen_shellcmd(appcmd_info* p_info) {
190 char *buf = p_info->shell_cmd;
191 int len = sizeof(p_info->shell_cmd);
193 if (p_info->args_cnt != 2) {
194 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
198 type = p_info->args[1];
200 D("args: type=%s\n", type);
202 snprintf(buf, len, "/usr/bin/pkgcmd -l -t %s", type);
207 static int appcmd_debugwebapp_gen_shellcmd(appcmd_info* p_info) {
209 char *buf = p_info->shell_cmd;
210 int len = sizeof(p_info->shell_cmd);
212 if (p_info->args_cnt != 2) {
213 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
217 appid = p_info->args[1];
219 D("args: appid=%s\n", appid);
221 snprintf(buf, len, "/usr/bin/app_launcher --start %s -w", appid);
226 static int appcmd_debugnativeapp_gen_shellcmd(appcmd_info* p_info) {
227 char *debug_port = NULL;
229 char *pid_str = NULL;
230 char *gdbserver_path = NULL;
231 char *buf = p_info->shell_cmd;
233 int len = sizeof(p_info->shell_cmd);
235 if (p_info->args_cnt != 5) {
236 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
240 debug_port = p_info->args[1];
241 appid= p_info->args[2];
242 pid_str = p_info->args[3];
243 gdbserver_path = p_info->args[4]; // not used. for 3.0 platform.
246 D("args: debug_port=%s, appid=%s, pid=%d, gdbserver_path=%s\n", debug_port, appid, pid, gdbserver_path);
249 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);
252 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);
258 static int appcmd_appinfo_gen_shellcmd(appcmd_info* p_info) {
260 char *buf = p_info->shell_cmd;
261 int len = sizeof(p_info->shell_cmd);
263 if (p_info->args_cnt != 2) {
264 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
268 pkgid = p_info->args[1];
270 D("args: pkgid=%s\n", pkgid);
272 snprintf(buf, len, "/usr/bin/pkginfo --list %s", pkgid);
277 static void appcmd_receiver_debugwebapp(int fd_in, int fd_out)
279 char buf[4096] = {0,};
280 char port_str[32] = {0,};
281 char out_buf[128] = {0,};
282 char* sub_str = NULL;
286 memset(buf, 0, sizeof(buf));
287 r = read_line(fd_in, buf, sizeof(buf));
291 if (errno == EINTR) {
298 D("debug webapp output : %s\n", buf);
299 sub_str = strstr(buf, "port: ");
300 if (sub_str != NULL && sscanf(sub_str, "port: %s", port_str) == 1) {
301 snprintf(out_buf, sizeof(out_buf), "\n%s:%s\n", MESSAGE_PREFIX_APPCMD_RETURN, port_str);
302 writex(fd_out, out_buf, strlen(out_buf)+1);
308 static void appcmd_receiver_default(int fd_in, int fd_out)
310 char buf[4096] = {0,};
314 memset(buf, 0, sizeof(buf));
315 r = sdb_read(fd_in, buf, sizeof(buf));
319 if (errno == EINTR) {
326 writex(fd_out, buf, strlen(buf)+1);
330 static void appcmd_receiver_packagelist(int fd_in, int fd_out)
332 char buf[4096] = {0,};
333 char out_buf[4096] = {0,};
337 snprintf(out_buf, sizeof(out_buf), "\n%s", MESSAGE_PREFIX_APPCMD_RETURN);
338 out_ptr = strlen(out_buf);
341 memset(buf, 0, sizeof(buf));
342 r = read_line(fd_in, buf, sizeof(buf));
346 if (errno == EINTR) {
353 D("pkgcmd output : %s\n", buf);
356 sub1 = strstr(buf, "pkgid [");
358 sub1 = strstr(sub1, "[")+1;
359 sub2 = strstr(sub1, "]");
362 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", sub1);
363 out_ptr += strlen(sub1)+1;
367 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, "\n");
369 D("package list: %s\n", out_buf);
370 writex(fd_out, out_buf, strlen(out_buf)+1);
373 static void appcmd_receiver_appinfo(int fd_in, int fd_out)
375 char buf[4096] = {0,};
376 char out_buf[4096] = {0,};
377 char appid[128] = {0,};
378 char apptype[128] = {0,};
382 snprintf(out_buf, sizeof(out_buf), "\n%s", MESSAGE_PREFIX_APPCMD_RETURN);
383 out_ptr = strlen(out_buf);
386 memset(buf, 0, sizeof(buf));
387 r = read_line(fd_in, buf, sizeof(buf));
391 if (errno == EINTR) {
398 D("pkginfo output : %s\n", buf);
400 if (!strncmp(buf, "Appid: ", 7)) {
401 memset(appid, 0, sizeof(appid));
402 sscanf(buf, "Appid: %s", appid);
404 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", appid);
405 out_ptr += strlen(appid)+1;
406 } else if (!strncmp(buf, "Apptype: ", 9)) {
407 memset(apptype, 0, sizeof(apptype));
408 sscanf(buf, "Apptype: %s", apptype);
410 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", apptype);
411 out_ptr += strlen(apptype)+1;
415 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, "\n");
417 D("app info: %s\n", out_buf);
418 writex(fd_out, out_buf, strlen(out_buf)+1);
421 static int exec_appcmd_shell_process(appcmd_info* p_info) {
425 char *trim_value = NULL;
427 memset(path, 0, sizeof(path));
430 "TERM=linux", /* without this, some programs based on screen can't work, e.g. top */
431 "DISPLAY=:0", /* without this, some programs based on without launchpad can't work */
439 // For the SDK user privilege.
440 envp[2] = "HOME=/home/developer";
441 get_env("ENV_PATH", &value);
443 trim_value = str_trim(value);
444 if (trim_value != NULL) {
445 // if string is not including 'PATH=', append it.
446 if (strncmp(trim_value, "PATH", 4)) {
447 snprintf(path, sizeof(path), "PATH=%s", trim_value);
449 snprintf(path, sizeof(path), "%s", trim_value);
458 D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]);
466 args[2] = p_info->shell_cmd;
468 ptm_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp);
469 D("create_subprocess() ptm_fd=%d pid=%d\n", ptm_fd, pid);
471 D("cannot create service thread\n");
475 if (p_info->receiver_func != NULL) {
476 p_info->receiver_func(ptm_fd, p_info->fd);
479 // wait for shell process
482 pid_t p = waitpid(pid, &status, 0);
484 D("fd=%d, post waitpid(pid=%d) status=%04x\n", p_info->fd, p, status);
486 if (WIFEXITED(status)) {
487 p_info->exitcode = WEXITSTATUS(status);
488 D("*** Exit code %d\n", p_info->exitcode);
493 D("shell exited fd=%d of pid=%d err=%d\n", p_info->fd, pid, errno);
498 #if APPCMD_USING_PKGMGR
499 static int get_pkg_info(char* pkgid, char* pkginfo_buf, int buf_size) {
500 pkgmgrinfo_pkginfo_h handle;
501 pkgmgr_client* pc = NULL;
502 char* pkgname = NULL;
504 bool is_removable = 0;
509 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
511 D("failed to get pkginfo handle.\n");
515 ret = pkgmgrinfo_pkginfo_get_mainappid(handle, &pkgname);
517 D("failed to get pkg name\n");
521 ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
523 D("failed to get pkg type.\n");
527 ret = pkgmgrinfo_pkginfo_is_removable(handle, &is_removable);
529 D("failed to get removable info.\n");
533 pc = pkgmgr_client_new(PC_REQUEST);
535 D("failed to create pkgmgr client.\n");
539 ret = pkgmgr_client_request_service(PM_REQUEST_CHECK_APP, 0, pc, NULL, pkgid, NULL, NULL, &pid);
541 D("failed to get running state.\n");
544 is_running = ((pid > 0) ? 1:0);
546 D("pkginfo: pkgname=%s, type=%s, is_removagle=%d, is_running=%d, pid=%d\n", pkgname, type, is_removable, is_running, pid);
547 snprintf(pkginfo_buf, buf_size, "%s:%s:%d:%d", pkgname, type, is_removable, is_running);
551 static void run_appcmd_packageinfo(appcmd_info* p_info) {
552 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
553 char pkginfo_buf[256] = {0,};
557 p_info->exitcode = -1;
559 if (p_info->args_cnt != 3) {
560 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
564 type = p_info->args[1];
565 pkgid= p_info->args[2];
567 D("args: type=%s, pkgid=%s\n", type, pkgid);
569 if (get_pkg_info(pkgid, pkginfo_buf, sizeof(pkginfo_buf)) == 0) {
570 D("success to get pkginfo. (%s)\n", pkginfo_buf);
571 p_info->exitcode = 0;
572 snprintf(result_buf, sizeof(result_buf), "\n%s:%s\n", MESSAGE_PREFIX_APPCMD_RETURN, pkginfo_buf);
573 writex(p_info->fd, result_buf, strlen(result_buf));
575 D("failed to get pkginfo.\n");
579 static int appcmd_packageinfo_gen_shellcmd(appcmd_info* p_info) {
581 char *buf = p_info->shell_cmd;
582 int len = sizeof(p_info->shell_cmd);
584 if (p_info->args_cnt != 2) {
585 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
589 pkgid = p_info->args[1];
591 D("args: pkgid=%s\n", pkgid);
593 snprintf(buf, len, "/usr/bin/pkginfo --pkg %s;/usr/bin/pkgcmd -C -n %s", pkgid, pkgid);
598 static void appcmd_receiver_packageinfo(int fd_in, int fd_out)
600 char buf[4096] = {0,};
601 char mainapp_id[128] = {0,};
602 char type[128] = {0,};
603 int is_removable = 0;
608 memset(buf, 0, sizeof(buf));
609 r = read_line(fd_in, buf, sizeof(buf));
613 if (errno == EINTR) {
620 if (!strncmp(buf, "mainappid : ", 12)) {
621 sscanf(buf, "mainappid : %s", mainapp_id);
622 } else if (!strncmp(buf, "Type: ", 6)) {
623 sscanf(buf, "Type: %s", type);
624 } else if (!strncmp(buf, "Removable: ", 11)) {
625 sscanf(buf, "Removable: %d", &is_removable);
626 } else if (strstr(buf, " is Running") != NULL) {
631 memset(buf, 0, sizeof(buf));
632 snprintf(buf, sizeof(buf), "\n%s:%s:%s:%d:%d\n",
633 MESSAGE_PREFIX_APPCMD_RETURN, mainapp_id, type, is_removable, is_running);
635 D("package info: %s\n", buf);
636 writex(fd_out, buf, strlen(buf)+1);
640 static void run_appcmd_appinstallpath(appcmd_info* p_info) {
641 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
643 p_info->exitcode = -1;
645 const char* path = tzplatform_getenv(TZ_SDK_TOOLS);
647 p_info->exitcode = 0;
648 snprintf(result_buf, sizeof(result_buf), "\n%s:%s\n", MESSAGE_PREFIX_APPCMD_RETURN, path);
649 writex(p_info->fd, result_buf, strlen(result_buf));
651 D("failed to get application install path from tzplatform_getenv.");
655 static void run_appcmd_with_shell_process(appcmd_info* p_info) {
658 if (p_info == NULL) {
659 D("Invalid arguments. p_info is null\n");
663 if (p_info->gen_cmd_func == NULL) {
664 D("Invalid arguments.\n");
665 p_info->exitcode = -1;
669 ret = p_info->gen_cmd_func(p_info);
671 D("failed to generate install shell command.\n");
672 p_info->exitcode = -1;
674 ret = exec_appcmd_shell_process(p_info);
675 D("exec_appcmd_shell_process: ret=%d, exitcode=%d\n", ret, p_info->exitcode);
677 D("failed to run shell process\n");
678 p_info->exitcode = -1;
683 int appcmd_service( parameters* in, int out_fd ) {
685 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
686 char* service_name = NULL;
687 char* command = NULL;
689 if (in == NULL || in->number_of_parameter != 1 || in->array_of_parameter == NULL
690 || in->array_of_parameter[0].type != type_string) {
691 D ( "Invalid argument\n" );
692 return PLUGIN_CMD_FAIL;
695 command = in->array_of_parameter[0].v_string.data;
696 D("command=%s(FD:%d)\n", command, out_fd);
698 memset(&info, 0, sizeof(info));
700 /* appcmd parameter data map
701 * "service name:arg1:arg2:...:argN" */
702 info.args_cnt = tokenize(command, ":", info.args, MAX_TOKENS);
703 D("args_cnt=%d\n", info.args_cnt);
704 if (info.args_cnt < 1) {
705 D("failed to parse appcmd for install. (%s)\n", command);
712 info.raw_command = command;
714 service_name = info.args[0];
715 D("service name=%s\n", service_name);
717 if (strncmp(service_name, "install", 7) == 0) {
718 info.receiver_func = appcmd_receiver_default;
719 info.gen_cmd_func = appcmd_install_gen_shellcmd;
720 run_appcmd_with_shell_process(&info);
722 if (info.args[2] != NULL) {
723 sdb_unlink(info.args[2]);
725 } else if (strncmp(service_name, "uninstall", 9) == 0) {
726 info.receiver_func = appcmd_receiver_default;
727 info.gen_cmd_func = appcmd_uninstall_gen_shellcmd;
728 run_appcmd_with_shell_process(&info);
729 } else if (strncmp(service_name, "appinfo", 7) == 0) {
730 info.gen_cmd_func = appcmd_appinfo_gen_shellcmd;
731 info.receiver_func = appcmd_receiver_appinfo;
732 run_appcmd_with_shell_process(&info);
733 } else if (strncmp(service_name, "packageinfo", 11) == 0) {
734 #if APPCMD_USING_PKGMGR
735 run_appcmd_packageinfo(&info);
737 info.gen_cmd_func = appcmd_packageinfo_gen_shellcmd;
738 info.receiver_func = appcmd_receiver_packageinfo;
739 run_appcmd_with_shell_process(&info);
741 } else if (strncmp(service_name, "packagelist", 11) == 0) {
742 info.gen_cmd_func = appcmd_packagelist_gen_shellcmd;
743 info.receiver_func = appcmd_receiver_packagelist;
744 run_appcmd_with_shell_process(&info);
745 } else if (strncmp(service_name, "appinstallpath", 14) == 0) {
746 run_appcmd_appinstallpath(&info);
747 } else if (strncmp(service_name, "runapp", 6) == 0) {
748 info.receiver_func = appcmd_receiver_default;
749 info.gen_cmd_func = appcmd_runapp_gen_shellcmd;
750 run_appcmd_with_shell_process(&info);
751 } else if (strncmp(service_name, "rununittestapp", 14) == 0) {
752 info.receiver_func = appcmd_receiver_default;
753 info.gen_cmd_func = appcmd_rununittestapp_gen_shellcmd;
754 run_appcmd_with_shell_process(&info);
755 } else if (strncmp(service_name, "killapp", 7) == 0) {
756 info.receiver_func = appcmd_receiver_default;
757 info.gen_cmd_func = appcmd_killapp_gen_shellcmd;
758 run_appcmd_with_shell_process(&info);
759 } else if (strncmp(service_name, "debugwebapp", 11) == 0) {
760 info.gen_cmd_func = appcmd_debugwebapp_gen_shellcmd;
761 info.receiver_func = appcmd_receiver_debugwebapp;
762 run_appcmd_with_shell_process(&info);
763 } else if (strncmp(service_name, "debugnativeapp", 14) == 0) {
764 info.gen_cmd_func = appcmd_debugnativeapp_gen_shellcmd;
765 run_appcmd_with_shell_process(&info);
767 D("not supported appcmd service. (%s)\n", service_name);
773 free_strings(info.args, info.args_cnt);
775 snprintf(result_buf, sizeof(result_buf), "\n%s:%d\n", MESSAGE_PREFIX_APPCMD_EXITCODE, info.exitcode);
776 writex(out_fd, result_buf, strlen(result_buf));
778 if (info.exitcode != 0) {
779 return PLUGIN_CMD_FAIL;
782 return PLUGIN_CMD_SUCCESS;