#include <stdio.h>
#include <stdbool.h>
#include <glib.h>
-#include <gio/gio.h>
#include <getopt.h>
#include <termios.h>
#include <syslog.h>
#include "signal.h"
#include "qerror.h"
#include "error_int.h"
+#include "qapi/qmp-core.h"
#define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0"
#define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
struct GAState {
JSONMessageParser parser;
GMainLoop *main_loop;
- GSocket *conn_sock;
GIOChannel *conn_channel;
- GSocket *listen_sock;
GIOChannel *listen_channel;
const char *path;
const char *method;
static void quit_handler(int sig)
{
- g_debug("recieved signal num %d, quitting", sig);
+ g_debug("received signal num %d, quitting", sig);
if (g_main_loop_is_running(ga_state->main_loop)) {
g_main_loop_quit(ga_state->main_loop);
" -v, --verbose log extra debugging information\n"
" -V, --version print version information and exit\n"
" -d, --daemonize become a daemon\n"
+" -b, --blacklist comma-seperated list of RPCs to disable (no spaces, \"?\""
+" to list available RPCs)\n"
" -h, --help display this help and exit\n"
"\n"
}
level &= G_LOG_LEVEL_MASK;
- if (g_strcmp0(domain, "syslog") == 0) {
+ if (domain && strcmp(domain, "syslog") == 0) {
syslog(LOG_INFO, "%s: %s", level_str, msg);
} else if (level & s->log_level) {
g_get_current_time(&time);
GIOCondition condition, gpointer data)
{
GAState *s = data;
- GError *err = NULL;
g_assert(channel != NULL);
- int ret;
+ int ret, conn_fd;
bool accepted = false;
+ struct sockaddr_un addr;
+ socklen_t addrlen = sizeof(addr);
- s->conn_sock = g_socket_accept(s->listen_sock, NULL, &err);
- if (err != NULL) {
- g_warning("error converting fd to gsocket: %s", err->message);
- g_error_free(err);
+ conn_fd = qemu_accept(g_io_channel_unix_get_fd(s->listen_channel),
+ (struct sockaddr *)&addr, &addrlen);
+ if (conn_fd == -1) {
+ g_warning("error converting fd to gsocket: %s", strerror(errno));
goto out;
}
- ret = conn_channel_add(s, g_socket_get_fd(s->conn_sock));
+ fcntl(conn_fd, F_SETFL, O_NONBLOCK);
+ ret = conn_channel_add(s, conn_fd);
if (ret) {
g_warning("error setting up connection");
goto out;
*/
static int listen_channel_add(GAState *s, int listen_fd, bool new)
{
- GError *err = NULL;
-
if (new) {
s->listen_channel = g_io_channel_unix_new(listen_fd);
- if (s->listen_sock) {
- g_object_unref(s->listen_sock);
- }
- s->listen_sock = g_socket_new_from_fd(listen_fd, &err);
- if (err != NULL) {
- g_warning("error converting fd to gsocket: %s", err->message);
- g_error_free(err);
- return -1;
- }
}
g_io_add_watch(s->listen_channel, G_IO_IN,
listen_channel_accept, s);
{
if (strcmp(s->method, "unix-listen") == 0) {
g_io_channel_shutdown(s->conn_channel, true, NULL);
- g_object_unref(s->conn_sock);
- s->conn_sock = NULL;
listen_channel_add(s, 0, false);
} else if (strcmp(s->method, "virtio-serial") == 0) {
/* we spin on EOF for virtio-serial, so back off a bit. also,
int main(int argc, char **argv)
{
- const char *sopt = "hVvdm:p:l:f:";
+ const char *sopt = "hVvdm:p:l:f:b:";
const char *method = NULL, *path = NULL, *pidfile = QGA_PIDFILE_DEFAULT;
const struct option lopt[] = {
{ "help", 0, NULL, 'h' },
{ "method", 0, NULL, 'm' },
{ "path", 0, NULL, 'p' },
{ "daemonize", 0, NULL, 'd' },
+ { "blacklist", 0, NULL, 'b' },
{ NULL, 0, NULL, 0 }
};
- int opt_ind = 0, ch, daemonize = 0;
+ int opt_ind = 0, ch, daemonize = 0, i, j, len;
GLogLevelFlags log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
FILE *log_file = stderr;
GAState *s;
+ module_call_init(MODULE_INIT_QAPI);
+
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
switch (ch) {
case 'm':
case 'd':
daemonize = 1;
break;
+ case 'b': {
+ char **list_head, **list;
+ if (*optarg == '?') {
+ list_head = list = qmp_get_command_list();
+ while (*list != NULL) {
+ printf("%s\n", *list);
+ g_free(*list);
+ list++;
+ }
+ g_free(list_head);
+ return 0;
+ }
+ for (j = 0, i = 0, len = strlen(optarg); i < len; i++) {
+ if (optarg[i] == ',') {
+ optarg[i] = 0;
+ qmp_disable_command(&optarg[j]);
+ g_debug("disabling command: %s", &optarg[j]);
+ j = i + 1;
+ }
+ }
+ if (j < i) {
+ qmp_disable_command(&optarg[j]);
+ g_debug("disabling command: %s", &optarg[j]);
+ }
+ break;
+ }
case 'h':
usage(argv[0]);
return 0;
become_daemon(pidfile);
}
- g_type_init();
- g_thread_init(NULL);
-
- s = qemu_mallocz(sizeof(GAState));
+ s = g_malloc0(sizeof(GAState));
s->conn_channel = NULL;
s->path = path;
s->method = method;
ga_command_state_init_all(s->command_state);
ga_state = s;
- module_call_init(MODULE_INIT_QAPI);
init_guest_agent(ga_state);
register_signal_handlers();