]> git.proxmox.com Git - qemu.git/blobdiff - qemu-ga.c
usb-bt: Return NAK instead of STALL when interrupt ep has no data
[qemu.git] / qemu-ga.c
index 216be39072b926c90d57eb324118c08a8dfdbba4..9b59a524619cab1f25ff3ae87a1ee2227785f1be 100644 (file)
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -28,7 +28,6 @@
 #include "module.h"
 #include "signal.h"
 #include "qerror.h"
-#include "error_int.h"
 #include "qapi/qmp-core.h"
 #include "qga/channel.h"
 #ifdef _WIN32
@@ -41,8 +40,8 @@
 #else
 #define QGA_VIRTIO_PATH_DEFAULT "\\\\.\\Global\\org.qemu.guest_agent.0"
 #endif
-#define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
-#define QGA_STATEDIR_DEFAULT "/tmp"
+#define QGA_STATEDIR_DEFAULT CONFIG_QEMU_LOCALSTATEDIR "/run"
+#define QGA_PIDFILE_DEFAULT QGA_STATEDIR_DEFAULT "/qemu-ga.pid"
 #define QGA_SENTINEL_BYTE 0xFF
 
 struct GAState {
@@ -104,16 +103,9 @@ static void quit_handler(int sig)
 }
 
 #ifndef _WIN32
-/* reap _all_ terminated children */
-static void child_handler(int sig)
-{
-    int status;
-    while (waitpid(-1, &status, WNOHANG) > 0) /* NOTHING */;
-}
-
 static gboolean register_signal_handlers(void)
 {
-    struct sigaction sigact, sigact_chld;
+    struct sigaction sigact;
     int ret;
 
     memset(&sigact, 0, sizeof(struct sigaction));
@@ -122,23 +114,30 @@ static gboolean register_signal_handlers(void)
     ret = sigaction(SIGINT, &sigact, NULL);
     if (ret == -1) {
         g_error("error configuring signal handler: %s", strerror(errno));
-        return false;
     }
     ret = sigaction(SIGTERM, &sigact, NULL);
     if (ret == -1) {
         g_error("error configuring signal handler: %s", strerror(errno));
-        return false;
     }
 
-    memset(&sigact_chld, 0, sizeof(struct sigaction));
-    sigact_chld.sa_handler = child_handler;
-    sigact_chld.sa_flags = SA_NOCLDSTOP;
-    ret = sigaction(SIGCHLD, &sigact_chld, NULL);
-    if (ret == -1) {
-        g_error("error configuring signal handler: %s", strerror(errno));
+    return true;
+}
+
+/* TODO: use this in place of all post-fork() fclose(std*) callers */
+void reopen_fd_to_null(int fd)
+{
+    int nullfd;
+
+    nullfd = open("/dev/null", O_RDWR);
+    if (nullfd < 0) {
+        return;
     }
 
-    return true;
+    dup2(nullfd, fd);
+
+    if (nullfd != fd) {
+        close(nullfd);
+    }
 }
 #endif
 
@@ -167,7 +166,7 @@ static void usage(const char *cmd)
 "  -h, --help        display this help and exit\n"
 "\n"
 "Report bugs to <mdroth@linux.vnet.ibm.com>\n"
-    , cmd, QGA_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
+    , cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
     QGA_STATEDIR_DEFAULT);
 }
 
@@ -246,6 +245,9 @@ static bool ga_open_pidfile(const char *pidfile)
     pidfd = open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
     if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) {
         g_critical("Cannot lock pid file, %s", strerror(errno));
+        if (pidfd != -1) {
+            close(pidfd);
+        }
         return false;
     }
 
@@ -253,7 +255,7 @@ static bool ga_open_pidfile(const char *pidfile)
         g_critical("Failed to truncate pid file");
         goto fail;
     }
-    sprintf(pidstr, "%d", getpid());
+    snprintf(pidstr, sizeof(pidstr), "%d\n", getpid());
     if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
         g_critical("Failed to write pid file");
         goto fail;
@@ -304,7 +306,7 @@ static void ga_disable_non_whitelisted(void)
     g_free(list_head);
 }
 
-/* [re-]enable all commands, except those explictly blacklisted by user */
+/* [re-]enable all commands, except those explicitly blacklisted by user */
 static void ga_enable_non_blacklisted(GList *blacklist)
 {
     char **list_head, **list;
@@ -428,13 +430,15 @@ static void become_daemon(const char *pidfile)
         goto fail;
     }
 
-    close(STDIN_FILENO);
-    close(STDOUT_FILENO);
-    close(STDERR_FILENO);
+    reopen_fd_to_null(STDIN_FILENO);
+    reopen_fd_to_null(STDOUT_FILENO);
+    reopen_fd_to_null(STDERR_FILENO);
     return;
 
 fail:
-    unlink(pidfile);
+    if (pidfile) {
+        unlink(pidfile);
+    }
     g_critical("failed to daemonize");
     exit(EXIT_FAILURE);
 #endif
@@ -488,8 +492,6 @@ static void process_command(GAState *s, QDict *req)
             g_warning("error sending response: %s", strerror(ret));
         }
         qobject_decref(rsp);
-    } else {
-        g_warning("error getting response");
     }
 }
 
@@ -515,7 +517,7 @@ static void process_event(JSONMessageParser *parser, QList *tokens)
         } else {
             g_warning("failed to parse event: %s", error_get_pretty(err));
         }
-        qdict_put_obj(qdict, "error", error_get_qobject(err));
+        qdict_put_obj(qdict, "error", qmp_build_error_object(err));
         error_free(err);
     } else {
         qdict = qobject_to_qdict(obj);
@@ -532,7 +534,7 @@ static void process_event(JSONMessageParser *parser, QList *tokens)
             qdict = qdict_new();
             g_warning("unrecognized payload format");
             error_set(&err, QERR_UNSUPPORTED);
-            qdict_put_obj(qdict, "error", error_get_qobject(err));
+            qdict_put_obj(qdict, "error", qmp_build_error_object(err));
             error_free(err);
         }
         ret = send_response(s, QOBJECT(qdict));
@@ -729,14 +731,14 @@ int main(int argc, char **argv)
             log_level = G_LOG_LEVEL_MASK;
             break;
         case 'V':
-            printf("QEMU Guest Agent %s\n", QGA_VERSION);
+            printf("QEMU Guest Agent %s\n", QEMU_VERSION);
             return 0;
         case 'd':
             daemonize = 1;
             break;
         case 'b': {
             char **list_head, **list;
-            if (*optarg == '?') {
+            if (is_help_option(optarg)) {
                 list_head = list = qmp_get_command_list();
                 while (*list != NULL) {
                     printf("%s\n", *list);
@@ -836,12 +838,13 @@ int main(int argc, char **argv)
             become_daemon(pid_filepath);
         }
         if (log_filepath) {
-            s->log_file = fopen(log_filepath, "a");
-            if (!s->log_file) {
+            FILE *log_file = fopen(log_filepath, "a");
+            if (!log_file) {
                 g_critical("unable to open specified log file: %s",
                            strerror(errno));
                 goto out_bad;
             }
+            s->log_file = log_file;
         }
     }