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) {
99 char *buf = p_info->shell_cmd;
100 int len = sizeof(p_info->shell_cmd);
102 if (p_info->args_cnt != 2) {
103 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
107 pkgid = p_info->args[1];
109 D("args: pkgid=%s\n", pkgid);
111 snprintf(buf, len, "pkgcmd -u -q -n %s", pkgid);
116 static int appcmd_runapp_gen_shellcmd(appcmd_info* p_info) {
118 char *buf = p_info->shell_cmd;
119 int len = sizeof(p_info->shell_cmd);
121 if (p_info->args_cnt != 2) {
122 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
126 appid = p_info->args[1];
128 D("args: appid=%s\n", appid);
130 snprintf(buf, len, "/usr/bin/app_launcher --start %s", appid);
135 static int appcmd_rununittestapp_gen_shellcmd(appcmd_info* p_info) {
137 char *usr_args = NULL;
138 char *buf = p_info->shell_cmd;
139 int len = sizeof(p_info->shell_cmd);
141 char *p_service = NULL;
142 char *p_appid = NULL;
144 free_strings(p_info->args, p_info->args_cnt);
146 p_service = strtok_r(p_info->raw_command, ":", &ptr);
147 p_appid = strtok_r(NULL, ":", &ptr);
148 if (p_service == NULL || p_appid == NULL) {
149 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
153 p_info->args_cnt = 3;
154 p_info->args[0] = strdup(p_service);
155 p_info->args[1] = strdup(p_appid);
156 p_info->args[2] = strdup(ptr);
158 appid = p_info->args[1];
159 usr_args = p_info->args[2];
161 D("args: appid=%s, usr_args=%s\n", appid, usr_args);
163 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);
168 static int appcmd_killapp_gen_shellcmd(appcmd_info* p_info) {
170 char *buf = p_info->shell_cmd;
171 int len = sizeof(p_info->shell_cmd);
173 if (p_info->args_cnt != 2) {
174 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
178 appid = p_info->args[1];
180 D("args: appid=%s\n", appid);
182 snprintf(buf, len, "/usr/bin/app_launcher --kill %s", appid);
187 static int appcmd_packagelist_gen_shellcmd(appcmd_info* p_info) {
189 char *buf = p_info->shell_cmd;
190 int len = sizeof(p_info->shell_cmd);
192 if (p_info->args_cnt != 2) {
193 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
197 type = p_info->args[1];
199 D("args: type=%s\n", type);
201 snprintf(buf, len, "/usr/bin/pkgcmd -l -t %s", type);
206 static int appcmd_debugwebapp_gen_shellcmd(appcmd_info* p_info) {
208 char *buf = p_info->shell_cmd;
209 int len = sizeof(p_info->shell_cmd);
211 if (p_info->args_cnt != 2) {
212 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
216 appid = p_info->args[1];
218 D("args: appid=%s\n", appid);
220 snprintf(buf, len, "/usr/bin/app_launcher --start %s -w", appid);
225 static int appcmd_debugnativeapp_gen_shellcmd(appcmd_info* p_info) {
226 char *debug_port = NULL;
228 char *pid_str = NULL;
229 char *gdbserver_path = NULL;
230 char *buf = p_info->shell_cmd;
232 int len = sizeof(p_info->shell_cmd);
234 if (p_info->args_cnt != 5) {
235 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
239 debug_port = p_info->args[1];
240 appid= p_info->args[2];
241 pid_str = p_info->args[3];
242 gdbserver_path = p_info->args[4]; // not used. for 3.0 platform.
245 D("args: debug_port=%s, appid=%s, pid=%d, gdbserver_path=%s\n", debug_port, appid, pid, gdbserver_path);
248 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);
251 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);
257 static int appcmd_appinfo_gen_shellcmd(appcmd_info* p_info) {
259 char *buf = p_info->shell_cmd;
260 int len = sizeof(p_info->shell_cmd);
262 if (p_info->args_cnt != 2) {
263 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
267 pkgid = p_info->args[1];
269 D("args: pkgid=%s\n", pkgid);
271 snprintf(buf, len, "/usr/bin/pkginfo --list %s", pkgid);
276 static void appcmd_receiver_debugwebapp(int fd_in, int fd_out)
278 char buf[4096] = {0,};
279 char port_str[32] = {0,};
280 char out_buf[128] = {0,};
281 char* sub_str = NULL;
285 memset(buf, 0, sizeof(buf));
286 r = read_line(fd_in, buf, sizeof(buf));
290 if (errno == EINTR) {
297 D("debug webapp output : %s\n", buf);
298 sub_str = strstr(buf, "port: ");
299 if (sub_str != NULL && sscanf(sub_str, "port: %s", port_str) == 1) {
300 snprintf(out_buf, sizeof(out_buf), "\n%s:%s\n", MESSAGE_PREFIX_APPCMD_RETURN, port_str);
301 writex(fd_out, out_buf, strlen(out_buf)+1);
307 static void appcmd_receiver_default(int fd_in, int fd_out)
309 char buf[4096] = {0,};
313 memset(buf, 0, sizeof(buf));
314 r = sdb_read(fd_in, buf, sizeof(buf));
318 if (errno == EINTR) {
325 writex(fd_out, buf, strlen(buf)+1);
329 static void appcmd_receiver_packagelist(int fd_in, int fd_out)
331 char buf[4096] = {0,};
332 char out_buf[4096] = {0,};
336 snprintf(out_buf, sizeof(out_buf), "\n%s", MESSAGE_PREFIX_APPCMD_RETURN);
337 out_ptr = strlen(out_buf);
340 memset(buf, 0, sizeof(buf));
341 r = read_line(fd_in, buf, sizeof(buf));
345 if (errno == EINTR) {
352 D("pkgcmd output : %s\n", buf);
355 sub1 = strstr(buf, "pkgid [");
357 sub1 = strstr(sub1, "[")+1;
358 sub2 = strstr(sub1, "]");
361 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", sub1);
362 out_ptr += strlen(sub1)+1;
366 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, "\n");
368 D("package list: %s\n", out_buf);
369 writex(fd_out, out_buf, strlen(out_buf)+1);
372 static void appcmd_receiver_appinfo(int fd_in, int fd_out)
374 char buf[4096] = {0,};
375 char out_buf[4096] = {0,};
376 char appid[128] = {0,};
377 char apptype[128] = {0,};
381 snprintf(out_buf, sizeof(out_buf), "\n%s", MESSAGE_PREFIX_APPCMD_RETURN);
382 out_ptr = strlen(out_buf);
385 memset(buf, 0, sizeof(buf));
386 r = read_line(fd_in, buf, sizeof(buf));
390 if (errno == EINTR) {
397 D("pkginfo output : %s\n", buf);
399 if (!strncmp(buf, "Appid: ", 7)) {
400 memset(appid, 0, sizeof(appid));
401 sscanf(buf, "Appid: %s", appid);
403 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", appid);
404 out_ptr += strlen(appid)+1;
405 } else if (!strncmp(buf, "Apptype: ", 9)) {
406 memset(apptype, 0, sizeof(apptype));
407 sscanf(buf, "Apptype: %s", apptype);
409 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, ":%s", apptype);
410 out_ptr += strlen(apptype)+1;
414 snprintf(out_buf+out_ptr, sizeof(out_buf)-out_ptr, "\n");
416 D("app info: %s\n", out_buf);
417 writex(fd_out, out_buf, strlen(out_buf)+1);
420 static int exec_appcmd_shell_process(appcmd_info* p_info) {
424 char *trim_value = NULL;
426 memset(path, 0, sizeof(path));
429 "TERM=linux", /* without this, some programs based on screen can't work, e.g. top */
430 "DISPLAY=:0", /* without this, some programs based on without launchpad can't work */
438 // For the SDK user privilege.
439 envp[2] = "HOME=/home/developer";
440 get_env("ENV_PATH", &value);
442 trim_value = str_trim(value);
443 if (trim_value != NULL) {
444 // if string is not including 'PATH=', append it.
445 if (strncmp(trim_value, "PATH", 4)) {
446 snprintf(path, sizeof(path), "PATH=%s", trim_value);
448 snprintf(path, sizeof(path), "%s", trim_value);
457 D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]);
465 args[2] = p_info->shell_cmd;
467 ptm_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp);
468 D("create_subprocess() ptm_fd=%d pid=%d\n", ptm_fd, pid);
470 D("cannot create service thread\n");
474 if (p_info->receiver_func != NULL) {
475 p_info->receiver_func(ptm_fd, p_info->fd);
478 // wait for shell process
481 pid_t p = waitpid(pid, &status, 0);
483 D("fd=%d, post waitpid(pid=%d) status=%04x\n", p_info->fd, p, status);
485 if (WIFEXITED(status)) {
486 p_info->exitcode = WEXITSTATUS(status);
487 D("*** Exit code %d\n", p_info->exitcode);
492 D("shell exited fd=%d of pid=%d err=%d\n", p_info->fd, pid, errno);
497 #if APPCMD_USING_PKGMGR
498 static int get_pkg_info(char* pkgid, char* pkginfo_buf, int buf_size) {
499 pkgmgrinfo_pkginfo_h handle;
500 pkgmgr_client* pc = NULL;
501 char* pkgname = NULL;
503 bool is_removable = 0;
508 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
510 D("failed to get pkginfo handle.\n");
514 ret = pkgmgrinfo_pkginfo_get_mainappid(handle, &pkgname);
516 D("failed to get pkg name\n");
520 ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
522 D("failed to get pkg type.\n");
526 ret = pkgmgrinfo_pkginfo_is_removable(handle, &is_removable);
528 D("failed to get removable info.\n");
532 pc = pkgmgr_client_new(PC_REQUEST);
534 D("failed to create pkgmgr client.\n");
538 ret = pkgmgr_client_request_service(PM_REQUEST_CHECK_APP, 0, pc, NULL, pkgid, NULL, NULL, &pid);
540 D("failed to get running state.\n");
543 is_running = ((pid > 0) ? 1:0);
545 D("pkginfo: pkgname=%s, type=%s, is_removagle=%d, is_running=%d, pid=%d\n", pkgname, type, is_removable, is_running, pid);
546 snprintf(pkginfo_buf, buf_size, "%s:%s:%d:%d", pkgname, type, is_removable, is_running);
550 static void run_appcmd_packageinfo(appcmd_info* p_info) {
551 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
552 char pkginfo_buf[256] = {0,};
556 p_info->exitcode = -1;
558 if (p_info->args_cnt != 3) {
559 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
563 type = p_info->args[1];
564 pkgid= p_info->args[2];
566 D("args: type=%s, pkgid=%s\n", type, pkgid);
568 if (get_pkg_info(pkgid, pkginfo_buf, sizeof(pkginfo_buf)) == 0) {
569 D("success to get pkginfo. (%s)\n", pkginfo_buf);
570 p_info->exitcode = 0;
571 snprintf(result_buf, sizeof(result_buf), "\n%s:%s\n", MESSAGE_PREFIX_APPCMD_RETURN, pkginfo_buf);
572 writex(p_info->fd, result_buf, strlen(result_buf));
574 D("failed to get pkginfo.\n");
578 static int appcmd_packageinfo_gen_shellcmd(appcmd_info* p_info) {
580 char *buf = p_info->shell_cmd;
581 int len = sizeof(p_info->shell_cmd);
583 if (p_info->args_cnt != 2) {
584 D("failed to parse appcmd.(cnt=%d)\n", p_info->args_cnt);
588 pkgid = p_info->args[1];
590 D("args: pkgid=%s\n", pkgid);
592 snprintf(buf, len, "/usr/bin/pkginfo --pkg %s;/usr/bin/pkgcmd -C -n %s", pkgid, pkgid);
597 static void appcmd_receiver_packageinfo(int fd_in, int fd_out)
599 char buf[4096] = {0,};
600 char mainapp_id[128] = {0,};
601 char type[128] = {0,};
602 int is_removable = 0;
607 memset(buf, 0, sizeof(buf));
608 r = read_line(fd_in, buf, sizeof(buf));
612 if (errno == EINTR) {
619 if (!strncmp(buf, "mainappid : ", 12)) {
620 sscanf(buf, "mainappid : %s", mainapp_id);
621 } else if (!strncmp(buf, "Type: ", 6)) {
622 sscanf(buf, "Type: %s", type);
623 } else if (!strncmp(buf, "Removable: ", 11)) {
624 sscanf(buf, "Removable: %d", &is_removable);
625 } else if (strstr(buf, " is Running") != NULL) {
630 memset(buf, 0, sizeof(buf));
631 snprintf(buf, sizeof(buf), "\n%s:%s:%s:%d:%d\n",
632 MESSAGE_PREFIX_APPCMD_RETURN, mainapp_id, type, is_removable, is_running);
634 D("package info: %s\n", buf);
635 writex(fd_out, buf, strlen(buf)+1);
639 static void run_appcmd_appinstallpath(appcmd_info* p_info) {
640 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
642 p_info->exitcode = -1;
644 const char* path = tzplatform_getenv(TZ_SDK_HOME);
646 p_info->exitcode = 0;
647 snprintf(result_buf, sizeof(result_buf), "\n%s:%s/apps_rw/\n", MESSAGE_PREFIX_APPCMD_RETURN, path);
648 writex(p_info->fd, result_buf, strlen(result_buf));
650 D("failed to get application install path from tzplatform_getenv.");
654 static void run_appcmd_with_shell_process(appcmd_info* p_info) {
657 if (p_info == NULL) {
658 D("Invalid arguments. p_info is null\n");
662 if (p_info->gen_cmd_func == NULL) {
663 D("Invalid arguments.\n");
664 p_info->exitcode = -1;
668 ret = p_info->gen_cmd_func(p_info);
670 D("failed to generate install shell command.\n");
671 p_info->exitcode = -1;
673 ret = exec_appcmd_shell_process(p_info);
674 D("exec_appcmd_shell_process: ret=%d, exitcode=%d\n", ret, p_info->exitcode);
676 D("failed to run shell process\n");
677 p_info->exitcode = -1;
682 int appcmd_service( parameters* in, int out_fd ) {
684 char result_buf[APPCMD_RESULT_BUFSIZE] = {0,};
685 char* service_name = NULL;
686 char* command = NULL;
688 if (in == NULL || in->number_of_parameter != 1 || in->array_of_parameter == NULL
689 || in->array_of_parameter[0].type != type_string) {
690 D ( "Invalid argument\n" );
691 return PLUGIN_CMD_FAIL;
694 command = in->array_of_parameter[0].v_string.data;
695 D("command=%s(FD:%d)\n", command, out_fd);
697 memset(&info, 0, sizeof(info));
699 /* appcmd parameter data map
700 * "service name:arg1:arg2:...:argN" */
701 info.args_cnt = tokenize(command, ":", info.args, MAX_TOKENS);
702 D("args_cnt=%d\n", info.args_cnt);
703 if (info.args_cnt < 1) {
704 D("failed to parse appcmd for install. (%s)\n", command);
711 info.raw_command = command;
713 service_name = info.args[0];
714 D("service name=%s\n", service_name);
716 if (strncmp(service_name, "install", 7) == 0) {
717 info.receiver_func = appcmd_receiver_default;
718 info.gen_cmd_func = appcmd_install_gen_shellcmd;
719 run_appcmd_with_shell_process(&info);
721 if (info.args[2] != NULL) {
722 sdb_unlink(info.args[2]);
724 } else if (strncmp(service_name, "uninstall", 9) == 0) {
725 info.receiver_func = appcmd_receiver_default;
726 info.gen_cmd_func = appcmd_uninstall_gen_shellcmd;
727 run_appcmd_with_shell_process(&info);
728 } else if (strncmp(service_name, "appinfo", 7) == 0) {
729 info.gen_cmd_func = appcmd_appinfo_gen_shellcmd;
730 info.receiver_func = appcmd_receiver_appinfo;
731 run_appcmd_with_shell_process(&info);
732 } else if (strncmp(service_name, "packageinfo", 11) == 0) {
733 #if APPCMD_USING_PKGMGR
734 run_appcmd_packageinfo(&info);
736 info.gen_cmd_func = appcmd_packageinfo_gen_shellcmd;
737 info.receiver_func = appcmd_receiver_packageinfo;
738 run_appcmd_with_shell_process(&info);
740 } else if (strncmp(service_name, "packagelist", 11) == 0) {
741 info.gen_cmd_func = appcmd_packagelist_gen_shellcmd;
742 info.receiver_func = appcmd_receiver_packagelist;
743 run_appcmd_with_shell_process(&info);
744 } else if (strncmp(service_name, "appinstallpath", 14) == 0) {
745 run_appcmd_appinstallpath(&info);
746 } else if (strncmp(service_name, "runapp", 6) == 0) {
747 info.receiver_func = appcmd_receiver_default;
748 info.gen_cmd_func = appcmd_runapp_gen_shellcmd;
749 run_appcmd_with_shell_process(&info);
750 } else if (strncmp(service_name, "rununittestapp", 14) == 0) {
751 info.receiver_func = appcmd_receiver_default;
752 info.gen_cmd_func = appcmd_rununittestapp_gen_shellcmd;
753 run_appcmd_with_shell_process(&info);
754 } else if (strncmp(service_name, "killapp", 7) == 0) {
755 info.receiver_func = appcmd_receiver_default;
756 info.gen_cmd_func = appcmd_killapp_gen_shellcmd;
757 run_appcmd_with_shell_process(&info);
758 } else if (strncmp(service_name, "debugwebapp", 11) == 0) {
759 info.gen_cmd_func = appcmd_debugwebapp_gen_shellcmd;
760 info.receiver_func = appcmd_receiver_debugwebapp;
761 run_appcmd_with_shell_process(&info);
762 } else if (strncmp(service_name, "debugnativeapp", 14) == 0) {
763 info.gen_cmd_func = appcmd_debugnativeapp_gen_shellcmd;
764 run_appcmd_with_shell_process(&info);
766 D("not supported appcmd service. (%s)\n", service_name);
772 free_strings(info.args, info.args_cnt);
774 snprintf(result_buf, sizeof(result_buf), "\n%s:%d\n", MESSAGE_PREFIX_APPCMD_EXITCODE, info.exitcode);
775 writex(out_fd, result_buf, strlen(result_buf));
777 if (info.exitcode != 0) {
778 return PLUGIN_CMD_FAIL;
781 return PLUGIN_CMD_SUCCESS;