#include <sys/sysinfo.h>
#ifdef CONFIG_SPICE
#include <dirent.h>
+#include "hw/virtio/maru_virtio_evdi.h"
#endif
MULTI_DEBUG_CHANNEL(emulator, osutil);
#ifdef CONFIG_SPICE
#define PID_MAX_COUNT 256
+#define countof(X) ( (size_t) ( sizeof(X)/sizeof*(X) ) )
const char *execution_file_websocket = "websockify.py";
const char *execution_file_node = "node";
const char *node_proc_name = "emulator-x86-web";
+static const char *sdb_push_path = "/home/developer/";
+static const char *must_have_pkgs[] = {"emuld", "spice-protocol", "spice-vdagent"};
+static const char *systemd_services[] = {"spice-vdagent.service", "spice-vdagentd.service"};
void get_process_id(char const *process_name, char *first_param, int *pid, int *pscount)
{
if (strstr(mptr, process_name) != NULL) {
if (!first_param || strstr(&cmdline[current_len + 1], first_param) != NULL) {
if (sizeof(pid) < *pscount + 1) {
- WARN("PID array size is not enough.\n");
+ ERR("PID array size is not enough.\n");
return;
}
pid[*pscount] = atoi(dir_entry_p->d_name);
ret = execl(websocket_path, execution_file_websocket, websocket_port, local_port, (char *)0);
if (ret == 127) {
- WARN("Can't execute websocket.\n");
+ ERR("Can't execute websocket.\n");
} else if (ret == -1) {
- WARN("Fork error!\n");
+ ERR("Fork error!\n");
}
}
ret = execl(nodejs_path, execution_file_node, webviewer_script, (char *)0);
if (ret == 127) {
- WARN("Can't execute node server.\n");
+ ERR("Can't execute node server.\n");
} else if (ret == -1) {
- WARN("Fork error!\n");
+ ERR("Fork error!\n");
}
}
get_process_id("spicevmc", NULL, pid, &pscount);
if (pscount == 1) {
INFO("Detected the last spice emulator.\n");
- pid[0] = 0;
+ memset(pid, 0, sizeof(pid));
pscount = 0;
get_process_id(node_proc_name, NULL, pid, &pscount);
for (i = 0; i < pscount; i++) {
INFO("Will be killed %s, PID: %d\n", node_proc_name, pid[i]);
- kill(pid[i], SIGTERM);
+ kill(pid[i], SIGKILL);
}
}
}
INFO("Aleady running node server.\n");
}
}
+
+static int get_pkg_install_cnt(char const *pkg)
+{
+ FILE *fp;
+ char buf[255];
+ int pkg_cnt = 0;
+ char const *bin_dir = get_bin_path();
+ char const *relative_path = "../../sdb";
+ char cmd[strlen(bin_dir) + strlen(relative_path) + strlen(pkg) + 80];
+
+ /* check rpm pkg in guest */
+ sprintf(cmd, "%s%s -s emulator-%d shell \"rpm -qa | grep %s | wc -l\" 2>/dev/null",
+ bin_dir, relative_path, get_device_serial_number(), pkg);
+ fp = popen(cmd, "r");
+ if (fp == NULL) {
+ ERR("%s failed\n", cmd);
+ return -1;
+ }
+
+ /* The last output line is pkg cnt. */
+ memset(buf, 0, sizeof(buf));
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (strlen(buf) == 0) {
+ pclose(fp);
+ return -1;
+ }
+ }
+ pclose(fp);
+ pkg_cnt = atoi(buf);
+
+ return pkg_cnt;
+}
+
+static bool send_cmd(char const *cmd)
+{
+ int sndlen = 15; /* HEADER(CMD + LENGTH + GROUP + ACTION) + 1 */
+ char* sndbuf;
+ bool ret = false;
+ short length = strlen(cmd);
+
+ sndlen += strlen(cmd);
+ sndbuf = (char*) g_malloc0(sndlen);
+ if (!sndbuf) {
+ ERR("g_malloc0 failed!\n");
+ return false;
+ }
+
+ memset(sndbuf, 0, sndlen);
+ memcpy(sndbuf, "cmd", 3);
+ memcpy(sndbuf + 10, &length, 2);
+ memcpy(sndbuf + 14, cmd, strlen(cmd));
+
+ TRACE("send to evdi: %s, %s\n", sndbuf, sndbuf + 14);
+
+ ret = send_to_evdi(route_ij, sndbuf, sndlen);
+ g_free(sndbuf);
+
+ if (!ret) {
+ ERR("send to evdi failed!\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool install_pkg(char const *pkg, char *installed_pkg)
+{
+ char const *bin_dir = get_bin_path();
+ char const *remote_bin_dir = get_remote_bin_path();
+ char const *relative_path = "../../sdb";
+ char pkg_fname[255];
+ char cmd[strlen(bin_dir) + strlen(relative_path) + sizeof(pkg_fname) + 48];
+ DIR *dir_p;
+ struct dirent *dir_entry_p;
+
+ /* to find a file, including pkg name */
+ dir_p = opendir(remote_bin_dir);
+ memset(pkg_fname, 0, sizeof(pkg_fname));
+ while (NULL != (dir_entry_p = readdir(dir_p))) {
+ if (strncmp(dir_entry_p->d_name, pkg, strlen(pkg)) == 0) {
+ strncpy(pkg_fname, dir_entry_p->d_name, strlen(dir_entry_p->d_name));
+ break;
+ }
+ }
+ closedir(dir_p);
+
+ if (strlen(pkg_fname) == 0) {
+ ERR("%s package is not exist in %s\n", pkg, remote_bin_dir);
+ return false;
+ }
+
+ /* sdb push pkg to guest */
+ memset(cmd, 0, sizeof(cmd));
+ sprintf(cmd, "%s%s -s emulator-%d push %s%s %s 2>/dev/null", bin_dir, relative_path,
+ get_device_serial_number(), remote_bin_dir, pkg_fname, sdb_push_path);
+ int ret = system(cmd);
+ if (ret == 127) {
+ ERR("%s can't execute /bin/sh!\n", cmd);
+ return false;
+ } else if(ret == -1) {
+ ERR("%s fork error!\n", cmd);
+ return false;
+ }
+
+ /* install pkg */
+ memset(cmd, 0, sizeof(cmd));
+ sprintf(cmd, "rpm -i %s%s\n", sdb_push_path, pkg_fname);
+ if (send_cmd(cmd) == false) {
+ ERR("%s install failed\n", pkg_fname);
+ return false;
+ }
+
+ strncpy(installed_pkg, pkg_fname, strlen(pkg_fname));
+
+ return true;
+}
+
+static void* pkg_check_thread(void *args)
+{
+ int i = 0;
+ int repeat_cnt = 0;
+ int repeat_period = 500000; /* 0.5 sec */
+ int repeat_max = 40;
+ int install_cnt = 0;
+ bool is_pkg_pushed = false;
+ char const *bin_dir = get_bin_path();
+ char const *relative_path = "../../sdb";
+ char cmd[strlen(bin_dir) + strlen(relative_path) + 80];
+ char installed_pkgs[countof(must_have_pkgs) - 1][255];
+
+ /* check sdb connection */
+ INFO("Waiting sdb connection...\n");
+ while (get_pkg_install_cnt(must_have_pkgs[0]) < 1) {
+ usleep(repeat_period);
+ if (++repeat_cnt == repeat_max) {
+ ERR("SDB connection failed\n");
+ pthread_exit(NULL);
+ }
+ }
+ INFO("SDB connected.\n");
+
+ /* pkg push and install */
+ for (i = 1; i < countof(must_have_pkgs); i++) {
+ if (get_pkg_install_cnt(must_have_pkgs[i]) < 1) {
+ INFO("Installing %s...\n", must_have_pkgs[i]);
+ memset(installed_pkgs[i - 1], 0, sizeof(installed_pkgs[i - 1]));
+ if (install_pkg(must_have_pkgs[i], installed_pkgs[i - 1]) == false) {
+ ERR("Install %s failed\n", must_have_pkgs[i]);
+ pthread_exit(NULL);
+ }
+
+ /* To make sure pkg is completely installed. */
+ repeat_cnt = 0;
+ while (get_pkg_install_cnt(must_have_pkgs[i]) < 1) {
+ usleep(repeat_period);
+ if (++repeat_cnt == repeat_max) {
+ ERR("Install %s failed\n", must_have_pkgs[i]);
+ pthread_exit(NULL);
+ }
+ }
+
+ install_cnt++;
+ is_pkg_pushed = true;
+ INFO("Installed %s\n", must_have_pkgs[i]);
+ } else {
+ INFO("Already installed %s\n", must_have_pkgs[i]);
+ }
+ }
+
+ /* start vdagent */
+ for (i = 0; i < countof(systemd_services); i++) {
+ memset(cmd, 0, sizeof(cmd));
+ sprintf(cmd, "systemctl start %s\n", systemd_services[i]);
+ if (send_cmd(cmd) == false) {
+ ERR("%s failed\n", cmd);
+ } else {
+ INFO("Started %s\n", systemd_services[i]);
+ }
+ }
+
+ /* delete vdagent pkgs */
+ if (is_pkg_pushed) {
+ for (; install_cnt > 0; install_cnt--) {
+ sprintf(cmd, "rm %s%s", sdb_push_path, installed_pkgs[install_cnt - 1]);
+ if (send_cmd(cmd) == false) {
+ ERR("%s%s delete failed\n", sdb_push_path, installed_pkgs[install_cnt - 1]);
+ } else {
+ TRACE("%s%s delete succeed\n", sdb_push_path, installed_pkgs[install_cnt - 1]);
+ }
+ }
+ }
+
+ pthread_exit(NULL);
+}
+
+void spice_pkg_install(void) {
+ QemuThread check_thread_id;
+ qemu_thread_create(&check_thread_id, "pkg_check_thread", pkg_check_thread, (void *)
+ NULL, QEMU_THREAD_DETACHED);
+}
#endif
bool make_sdcard_lock_os(char *sdcard)