1 /* vdagentd.c vdagentd (daemon) code
3 Copyright 2010-2013 Red Hat, Inc.
6 Hans de Goede <hdegoede@redhat.com>
7 Gerd Hoffmann <kraxel@redhat.com>
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
34 #include <sys/select.h>
36 #include <spice/vd_agent.h>
40 #include "vdagentd-proto.h"
41 #include "vdagentd-proto-strings.h"
42 #include "vdagentd-uinput.h"
43 #include "vdagentd-xorg-conf.h"
44 #include "vdagent-virtio-port.h"
45 #include "session-info.h"
51 struct vdagentd_guest_xorg_resolution *screen_info;
56 static const char *pidfilename = "/opt/var/run/spice-vdagentd/spice-vdagentd.pid";
57 static const char *portdev = "/dev/virtio-ports/com.redhat.spice.0";
58 static const char *vdagentd_socket = VDAGENTD_SOCKET;
59 static const char *uinput_device = "/dev/uinput";
61 static int uinput_fake = 0;
62 static struct udscs_server *server = NULL;
63 static struct vdagent_virtio_port *virtio_port = NULL;
64 static GHashTable *active_xfers = NULL;
65 static struct session_info *session_info = NULL;
66 static struct vdagentd_uinput *uinput = NULL;
67 static VDAgentMonitorsConfig *mon_config = NULL;
68 static uint32_t *capabilities = NULL;
69 static int capabilities_size = 0;
70 static const char *active_session = NULL;
71 static unsigned int session_count = 0;
72 static struct udscs_connection *active_session_conn = NULL;
73 static int agent_owns_clipboard[256] = { 0, };
75 static int retval = 0;
76 static int client_connected = 0;
78 /* utility functions */
79 /* vdagentd <-> spice-client communication handling */
80 static void send_capabilities(struct vdagent_virtio_port *vport,
83 VDAgentAnnounceCapabilities *caps;
86 size = sizeof(*caps) + VD_AGENT_CAPS_BYTES;
87 caps = calloc(1, size);
89 syslog(LOG_ERR, "out of memory allocating capabilities array (write)");
93 caps->request = request;
94 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MOUSE_STATE);
95 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG);
96 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_REPLY);
97 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
98 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION);
99 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG);
100 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF);
102 vdagent_virtio_port_write(vport, VDP_CLIENT_PORT,
103 VD_AGENT_ANNOUNCE_CAPABILITIES, 0,
104 (uint8_t *)caps, size);
108 static void do_client_disconnect(void)
110 if (client_connected) {
111 udscs_server_write_all(server, VDAGENTD_CLIENT_DISCONNECTED, 0, 0,
113 client_connected = 0;
117 static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr,
118 VDAgentMessage *message_header, VDAgentMonitorsConfig *new_monitors)
123 /* Store monitor config to send to agents when they connect */
124 size = sizeof(VDAgentMonitorsConfig) +
125 new_monitors->num_of_monitors * sizeof(VDAgentMonConfig);
126 if (message_header->size != size) {
127 syslog(LOG_ERR, "invalid message size for VDAgentMonitorsConfig");
131 vdagentd_write_xorg_conf(new_monitors);
134 mon_config->num_of_monitors != new_monitors->num_of_monitors) {
136 mon_config = malloc(size);
138 syslog(LOG_ERR, "out of memory allocating monitors config");
142 memcpy(mon_config, new_monitors, size);
144 /* Send monitor config to currently active agent */
145 if (active_session_conn)
146 udscs_write(active_session_conn, VDAGENTD_MONITORS_CONFIG, 0, 0,
147 (uint8_t *)mon_config, size);
149 /* Acknowledge reception of monitors config to spice server / client */
150 reply.type = VD_AGENT_MONITORS_CONFIG;
151 reply.error = VD_AGENT_SUCCESS;
152 vdagent_virtio_port_write(vport, port_nr, VD_AGENT_REPLY, 0,
153 (uint8_t *)&reply, sizeof(reply));
156 static void do_client_capabilities(struct vdagent_virtio_port *vport,
157 VDAgentMessage *message_header,
158 VDAgentAnnounceCapabilities *caps)
160 int new_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(message_header->size);
162 if (capabilities_size != new_size) {
163 capabilities_size = new_size;
165 capabilities = malloc(capabilities_size * sizeof(uint32_t));
167 syslog(LOG_ERR, "oom allocating capabilities array (read)");
168 capabilities_size = 0;
172 memcpy(capabilities, caps->caps, capabilities_size * sizeof(uint32_t));
174 /* Report the previous client has disconneced. */
175 do_client_disconnect();
177 syslog(LOG_DEBUG, "New client connected");
178 client_connected = 1;
179 send_capabilities(vport, 0);
183 static void do_client_clipboard(struct vdagent_virtio_port *vport,
184 VDAgentMessage *message_header, uint8_t *data)
186 uint32_t msg_type = 0, data_type = 0, size = message_header->size;
187 uint8_t selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD;
189 if (!active_session_conn) {
191 "Could not find an agent connection belonging to the "
192 "active session, ignoring client clipboard request");
196 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
197 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
203 switch (message_header->type) {
204 case VD_AGENT_CLIPBOARD_GRAB:
205 msg_type = VDAGENTD_CLIPBOARD_GRAB;
206 agent_owns_clipboard[selection] = 0;
208 case VD_AGENT_CLIPBOARD_REQUEST: {
209 VDAgentClipboardRequest *req = (VDAgentClipboardRequest *)data;
210 msg_type = VDAGENTD_CLIPBOARD_REQUEST;
211 data_type = req->type;
216 case VD_AGENT_CLIPBOARD: {
217 VDAgentClipboard *clipboard = (VDAgentClipboard *)data;
218 msg_type = VDAGENTD_CLIPBOARD_DATA;
219 data_type = clipboard->type;
220 size = size - sizeof(VDAgentClipboard);
221 data = clipboard->data;
224 case VD_AGENT_CLIPBOARD_RELEASE:
225 msg_type = VDAGENTD_CLIPBOARD_RELEASE;
231 udscs_write(active_session_conn, msg_type, selection, data_type,
235 static void cancel_file_xfer(struct vdagent_virtio_port *vport,
236 const char *msg, uint32_t id)
238 VDAgentFileXferStatusMessage status = {
240 .result = VD_AGENT_FILE_XFER_STATUS_CANCELLED,
242 syslog(LOG_WARNING, msg, id);
244 vdagent_virtio_port_write(vport, VDP_CLIENT_PORT,
245 VD_AGENT_FILE_XFER_STATUS, 0,
246 (uint8_t *)&status, sizeof(status));
249 static void do_client_file_xfer(struct vdagent_virtio_port *vport,
250 VDAgentMessage *message_header,
253 uint32_t msg_type, id;
254 struct udscs_connection *conn;
256 switch (message_header->type) {
257 case VD_AGENT_FILE_XFER_START: {
258 VDAgentFileXferStartMessage *s = (VDAgentFileXferStartMessage *)data;
259 if (!active_session_conn) {
260 cancel_file_xfer(vport,
261 "Could not find an agent connnection belonging to the "
262 "active session, cancelling client file-xfer request %u",
266 udscs_write(active_session_conn, VDAGENTD_FILE_XFER_START, 0, 0,
267 data, message_header->size);
270 case VD_AGENT_FILE_XFER_STATUS: {
271 VDAgentFileXferStatusMessage *s = (VDAgentFileXferStatusMessage *)data;
272 msg_type = VDAGENTD_FILE_XFER_STATUS;
276 case VD_AGENT_FILE_XFER_DATA: {
277 VDAgentFileXferDataMessage *d = (VDAgentFileXferDataMessage *)data;
278 msg_type = VDAGENTD_FILE_XFER_DATA;
284 conn = g_hash_table_lookup(active_xfers, GUINT_TO_POINTER(id));
287 syslog(LOG_DEBUG, "Could not find file-xfer %u (cancelled?)", id);
290 udscs_write(conn, msg_type, 0, 0, data, message_header->size);
293 int virtio_port_read_complete(
294 struct vdagent_virtio_port *vport,
296 VDAgentMessage *message_header,
299 uint32_t min_size = 0;
301 if (message_header->protocol != VD_AGENT_PROTOCOL) {
302 syslog(LOG_ERR, "message with wrong protocol version ignoring");
306 switch (message_header->type) {
307 case VD_AGENT_MOUSE_STATE:
308 if (message_header->size != sizeof(VDAgentMouseState))
310 vdagentd_uinput_do_mouse(&uinput, (VDAgentMouseState *)data);
312 /* Try to re-open the tablet */
313 struct agent_data *agent_data =
314 udscs_get_user_data(active_session_conn);
316 uinput = vdagentd_uinput_create(uinput_device,
319 agent_data->screen_info,
320 agent_data->screen_count,
324 syslog(LOG_CRIT, "Fatal uinput error");
330 case VD_AGENT_MONITORS_CONFIG:
331 if (message_header->size < sizeof(VDAgentMonitorsConfig))
333 do_client_monitors(vport, port_nr, message_header,
334 (VDAgentMonitorsConfig *)data);
336 case VD_AGENT_ANNOUNCE_CAPABILITIES:
337 if (message_header->size < sizeof(VDAgentAnnounceCapabilities))
339 do_client_capabilities(vport, message_header,
340 (VDAgentAnnounceCapabilities *)data);
342 case VD_AGENT_CLIPBOARD_GRAB:
343 case VD_AGENT_CLIPBOARD_REQUEST:
344 case VD_AGENT_CLIPBOARD:
345 case VD_AGENT_CLIPBOARD_RELEASE:
346 switch (message_header->type) {
347 case VD_AGENT_CLIPBOARD_GRAB:
348 min_size = sizeof(VDAgentClipboardGrab); break;
349 case VD_AGENT_CLIPBOARD_REQUEST:
350 min_size = sizeof(VDAgentClipboardRequest); break;
351 case VD_AGENT_CLIPBOARD:
352 min_size = sizeof(VDAgentClipboard); break;
354 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
355 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
358 if (message_header->size < min_size) {
361 do_client_clipboard(vport, message_header, data);
363 case VD_AGENT_FILE_XFER_START:
364 case VD_AGENT_FILE_XFER_STATUS:
365 case VD_AGENT_FILE_XFER_DATA:
366 do_client_file_xfer(vport, message_header, data);
368 case VD_AGENT_CLIENT_DISCONNECTED:
369 vdagent_virtio_port_reset(vport, VDP_CLIENT_PORT);
370 do_client_disconnect();
373 syslog(LOG_WARNING, "unknown message type %d, ignoring",
374 message_header->type);
380 syslog(LOG_ERR, "read: invalid message size: %u for message type: %u",
381 message_header->size, message_header->type);
385 /* vdagentd <-> vdagent communication handling */
386 int do_agent_clipboard(struct udscs_connection *conn,
387 struct udscs_message_header *header, const uint8_t *data)
389 uint8_t selection = header->arg1;
390 uint32_t msg_type = 0, data_type = -1, size = header->size;
392 if (!VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
393 VD_AGENT_CAP_CLIPBOARD_BY_DEMAND))
396 /* Check that this agent is from the currently active session */
397 if (conn != active_session_conn) {
399 syslog(LOG_DEBUG, "%p clipboard req from agent which is not in "
400 "the active session?", conn);
405 syslog(LOG_ERR, "Clipboard req from agent but no client connection");
409 if (!VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
410 VD_AGENT_CAP_CLIPBOARD_SELECTION) &&
411 selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
415 switch (header->type) {
416 case VDAGENTD_CLIPBOARD_GRAB:
417 msg_type = VD_AGENT_CLIPBOARD_GRAB;
418 agent_owns_clipboard[selection] = 1;
420 case VDAGENTD_CLIPBOARD_REQUEST:
421 msg_type = VD_AGENT_CLIPBOARD_REQUEST;
422 data_type = header->arg2;
425 case VDAGENTD_CLIPBOARD_DATA:
426 msg_type = VD_AGENT_CLIPBOARD;
427 data_type = header->arg2;
429 case VDAGENTD_CLIPBOARD_RELEASE:
430 msg_type = VD_AGENT_CLIPBOARD_RELEASE;
432 agent_owns_clipboard[selection] = 0;
436 if (size != header->size) {
438 "unexpected extra data in clipboard msg, disconnecting agent");
442 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
443 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
446 if (data_type != -1) {
450 vdagent_virtio_port_write_start(virtio_port, VDP_CLIENT_PORT, msg_type,
453 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
454 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
455 uint8_t sel[4] = { selection, 0, 0, 0 };
456 vdagent_virtio_port_write_append(virtio_port, sel, 4);
458 if (data_type != -1) {
459 vdagent_virtio_port_write_append(virtio_port, (uint8_t*)&data_type, 4);
462 vdagent_virtio_port_write_append(virtio_port, data, header->size);
467 if (header->type == VDAGENTD_CLIPBOARD_REQUEST) {
468 /* Let the agent know no answer is coming */
469 udscs_write(conn, VDAGENTD_CLIPBOARD_DATA,
470 selection, VD_AGENT_CLIPBOARD_NONE, NULL, 0);
475 /* When we open the vdagent virtio channel, the server automatically goes into
476 client mouse mode, so we can only have the channel open when we know the
477 active session resolution. This function checks that we have an agent in the
478 active session, and that it has told us its resolution. If these conditions
479 are met it sets the uinput tablet device's resolution and opens the virtio
480 channel (if it is not already open). If these conditions are not met, it
482 static void check_xorg_resolution(void)
484 struct agent_data *agent_data = udscs_get_user_data(active_session_conn);
486 if (agent_data && agent_data->screen_info) {
488 uinput = vdagentd_uinput_create(uinput_device,
491 agent_data->screen_info,
492 agent_data->screen_count,
496 vdagentd_uinput_update_size(&uinput,
499 agent_data->screen_info,
500 agent_data->screen_count);
502 syslog(LOG_CRIT, "Fatal uinput error");
509 syslog(LOG_INFO, "opening vdagent virtio channel");
510 virtio_port = vdagent_virtio_port_create(portdev,
511 virtio_port_read_complete,
514 syslog(LOG_CRIT, "Fatal error opening vdagent virtio channel");
519 send_capabilities(virtio_port, 1);
522 #ifndef WITH_STATIC_UINPUT
523 vdagentd_uinput_destroy(&uinput);
526 vdagent_virtio_port_flush(&virtio_port);
527 vdagent_virtio_port_destroy(&virtio_port);
528 syslog(LOG_INFO, "closed vdagent virtio channel");
533 static int connection_matches_active_session(struct udscs_connection **connp,
536 struct udscs_connection **conn_ret = (struct udscs_connection **)priv;
537 struct agent_data *agent_data = udscs_get_user_data(*connp);
539 /* Check if this connection matches the currently active session */
540 if (!agent_data->session || !active_session)
542 if (strcmp(agent_data->session, active_session))
549 void release_clipboards(void)
553 for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; ++sel) {
554 if (agent_owns_clipboard[sel] && virtio_port) {
555 vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT,
556 VD_AGENT_CLIPBOARD_RELEASE, 0, &sel, 1);
558 agent_owns_clipboard[sel] = 0;
562 void update_active_session_connection(struct udscs_connection *new_conn)
567 active_session = session_info_get_active_session(session_info);
568 session_count = udscs_server_for_all_clients(server,
569 connection_matches_active_session,
578 if (new_conn && session_count != 1) {
579 syslog(LOG_ERR, "multiple agents in one session, "
580 "disabling agent to avoid potential information leak");
584 if (new_conn == active_session_conn)
587 active_session_conn = new_conn;
589 syslog(LOG_DEBUG, "%p is now the active session", new_conn);
590 if (active_session_conn && mon_config)
591 udscs_write(active_session_conn, VDAGENTD_MONITORS_CONFIG, 0, 0,
592 (uint8_t *)mon_config, sizeof(VDAgentMonitorsConfig) +
593 mon_config->num_of_monitors * sizeof(VDAgentMonConfig));
595 release_clipboards();
597 check_xorg_resolution();
600 gboolean remove_active_xfers(gpointer key, gpointer value, gpointer conn)
603 cancel_file_xfer(virtio_port, "Agent disc; cancelling file-xfer %u",
604 GPOINTER_TO_UINT(key));
610 void agent_connect(struct udscs_connection *conn)
612 struct agent_data *agent_data;
614 agent_data = calloc(1, sizeof(*agent_data));
616 syslog(LOG_ERR, "Out of memory allocating agent data, disconnecting");
617 udscs_destroy_connection(&conn);
622 uint32_t pid = udscs_get_peer_cred(conn).pid;
623 agent_data->session = session_info_session_for_pid(session_info, pid);
626 udscs_set_user_data(conn, (void *)agent_data);
627 udscs_write(conn, VDAGENTD_VERSION, 0, 0,
628 (uint8_t *)VERSION, strlen(VERSION) + 1);
629 update_active_session_connection(conn);
632 void agent_disconnect(struct udscs_connection *conn)
634 struct agent_data *agent_data = udscs_get_user_data(conn);
636 g_hash_table_foreach_remove(active_xfers, remove_active_xfers, conn);
638 free(agent_data->session);
639 agent_data->session = NULL;
640 update_active_session_connection(NULL);
645 void agent_read_complete(struct udscs_connection **connp,
646 struct udscs_message_header *header, uint8_t *data)
648 struct agent_data *agent_data = udscs_get_user_data(*connp);
650 switch (header->type) {
651 case VDAGENTD_GUEST_XORG_RESOLUTION: {
652 struct vdagentd_guest_xorg_resolution *res;
653 int n = header->size / sizeof(*res);
655 /* Detect older version session agent, but don't disconnect, as
656 that stops it from getting the VDAGENTD_VERSION message, and then
657 it will never re-exec the new version... */
658 if (header->arg1 == 0 && header->arg2 == 0) {
659 syslog(LOG_INFO, "got old session agent xorg resolution message, "
665 if (header->size != n * sizeof(*res)) {
666 syslog(LOG_ERR, "guest xorg resolution message has wrong size, "
667 "disconnecting agent");
668 udscs_destroy_connection(connp);
673 free(agent_data->screen_info);
674 res = malloc(n * sizeof(*res));
676 syslog(LOG_ERR, "out of memory allocating screen info");
679 memcpy(res, data, n * sizeof(*res));
680 agent_data->width = header->arg1;
681 agent_data->height = header->arg2;
682 agent_data->screen_info = res;
683 agent_data->screen_count = n;
685 check_xorg_resolution();
688 case VDAGENTD_CLIPBOARD_GRAB:
689 case VDAGENTD_CLIPBOARD_REQUEST:
690 case VDAGENTD_CLIPBOARD_DATA:
691 case VDAGENTD_CLIPBOARD_RELEASE:
692 if (do_agent_clipboard(*connp, header, data)) {
693 udscs_destroy_connection(connp);
698 case VDAGENTD_FILE_XFER_STATUS:{
699 VDAgentFileXferStatusMessage status;
700 status.id = header->arg1;
701 status.result = header->arg2;
702 vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT,
703 VD_AGENT_FILE_XFER_STATUS, 0,
704 (uint8_t *)&status, sizeof(status));
705 if (status.result == VD_AGENT_FILE_XFER_STATUS_CAN_SEND_DATA)
706 g_hash_table_insert(active_xfers, GUINT_TO_POINTER(status.id),
709 g_hash_table_remove(active_xfers, GUINT_TO_POINTER(status.id));
714 syslog(LOG_ERR, "unknown message from vdagent: %u, ignoring",
722 static void usage(FILE *fp)
725 "Usage: spice-vdagentd [OPTIONS]\n\n"
726 "Spice guest agent daemon, version %s.\n\n"
728 " -h print this text\n"
729 " -d log debug messages (use twice for extra info)\n"
730 " -s <port> set virtio serial port [%s]\n"
731 " -S <filename> set udcs socket [%s]\n"
732 " -u <dev> set uinput device [%s]\n"
733 " -x don't daemonize\n"
734 #ifdef HAVE_CONSOLE_KIT
735 " -X Disable console kit integration\n"
737 #ifdef HAVE_LIBSYSTEMD_LOGIN
738 " -X Disable systemd-logind integration\n"
740 ,VERSION, portdev, vdagentd_socket, uinput_device);
748 /* detach from terminal */
751 close(0); close(1); close(2);
753 x = open("/dev/null", O_RDWR); x = dup(x); x = dup(x);
754 pidfile = fopen(pidfilename, "w");
756 fprintf(pidfile, "%d\n", (int)getpid());
761 syslog(LOG_ERR, "fork: %m");
764 udscs_destroy_server(server);
771 fd_set readfds, writefds;
779 nfds = udscs_server_fill_fds(server, &readfds, &writefds);
780 n = vdagent_virtio_port_fill_fds(virtio_port, &readfds, &writefds);
785 ck_fd = session_info_get_fd(session_info);
786 FD_SET(ck_fd, &readfds);
791 n = select(nfds, &readfds, &writefds, NULL, NULL);
795 syslog(LOG_CRIT, "Fatal error select: %m");
800 udscs_server_handle_fds(server, &readfds, &writefds);
803 vdagent_virtio_port_handle_fds(&virtio_port, &readfds, &writefds);
805 int old_client_connected = client_connected;
807 "AIIEEE lost spice client connection, reconnecting");
808 virtio_port = vdagent_virtio_port_create(portdev,
809 virtio_port_read_complete,
813 "Fatal error opening vdagent virtio channel");
817 do_client_disconnect();
818 client_connected = old_client_connected;
822 if (session_info && FD_ISSET(ck_fd, &readfds)) {
823 active_session = session_info_get_active_session(session_info);
824 update_active_session_connection(NULL);
829 static void quit_handler(int sig)
834 int main(int argc, char *argv[])
837 int do_daemonize = 1;
838 int want_session_info = 1;
839 struct sigaction act;
842 if (-1 == (c = getopt(argc, argv, "-dhxXs:u:S:")))
852 vdagentd_socket = optarg;
855 uinput_device = optarg;
861 want_session_info = 0;
873 if (strncmp(uinput_device, "/dev", 4) != 0) {
874 syslog(LOG_INFO, "using fake uinput");
878 memset(&act, 0, sizeof(act));
879 act.sa_flags = SA_RESTART;
880 act.sa_handler = quit_handler;
881 sigaction(SIGINT, &act, NULL);
882 sigaction(SIGHUP, &act, NULL);
883 sigaction(SIGTERM, &act, NULL);
884 sigaction(SIGQUIT, &act, NULL);
886 openlog("spice-vdagentd", do_daemonize ? 0 : LOG_PERROR, LOG_USER);
888 /* Setup communication with vdagent process(es) */
889 server = udscs_create_server(vdagentd_socket, agent_connect,
890 agent_read_complete, agent_disconnect,
891 vdagentd_messages, VDAGENTD_NO_MESSAGES,
894 syslog(LOG_CRIT, "Fatal could not create server socket %s",
898 if (chmod(vdagentd_socket, 0666)) {
899 syslog(LOG_CRIT, "Fatal could not change permissions on %s: %m",
901 udscs_destroy_server(server);
908 #ifdef WITH_STATIC_UINPUT
909 uinput = vdagentd_uinput_create(uinput_device, 1024, 768, NULL, 0,
910 debug > 1, uinput_fake);
912 udscs_destroy_server(server);
917 if (want_session_info)
918 session_info = session_info_create(debug);
920 syslog(LOG_WARNING, "no session info, max 1 session agent allowed");
922 active_xfers = g_hash_table_new(g_direct_hash, g_direct_equal);
925 release_clipboards();
927 vdagentd_uinput_destroy(&uinput);
928 vdagent_virtio_port_flush(&virtio_port);
929 vdagent_virtio_port_destroy(&virtio_port);
930 session_info_destroy(session_info);
931 udscs_destroy_server(server);
932 if (unlink(vdagentd_socket) != 0)
933 syslog(LOG_ERR, "unlink %s: %s", vdagentd_socket, strerror(errno));
934 syslog(LOG_INFO, "vdagentd quiting, returning status %d", retval);