vdagent-x11: Add printing of selection to relevant log messages
[vd_agent.git] / src / vdagentd.c
blob204bba9bb36bf71bf9375f4c9e186bd10f223722
1 /* vdagentd.c vdagentd (daemon) code
3 Copyright 2010 Red Hat, Inc.
5 Red Hat Authors:
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/>.
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <sys/select.h>
34 #include <sys/stat.h>
35 #include <spice/vd_agent.h>
37 #include "udscs.h"
38 #include "vdagentd-proto.h"
39 #include "vdagentd-proto-strings.h"
40 #include "vdagentd-uinput.h"
41 #include "vdagent-virtio-port.h"
42 #include "console-kit.h"
44 struct agent_data {
45 char *session;
46 int width;
47 int height;
50 /* variables */
51 static const char *logfilename = "/var/log/spice-vdagentd/spice-vdagentd.log";
52 static const char *pidfilename = "/var/run/spice-vdagentd/spice-vdagentd.pid";
53 static const char *portdev = "/dev/virtio-ports/com.redhat.spice.0";
54 static const char *uinput_device = "/dev/uinput";
55 static int debug = 0;
56 static struct udscs_server *server = NULL;
57 static struct vdagent_virtio_port *virtio_port = NULL;
58 #ifdef HAVE_CONSOLE_KIT
59 static struct console_kit *console_kit = NULL;
60 #endif
61 static struct vdagentd_uinput *uinput = NULL;
62 static VDAgentMonitorsConfig *mon_config = NULL;
63 static uint32_t *capabilities = NULL;
64 static int capabilities_size = 0;
65 #ifdef HAVE_CONSOLE_KIT
66 static const char *active_session = NULL;
67 #else
68 static unsigned int session_count = 0;
69 #endif
70 static struct udscs_connection *active_session_conn = NULL;
71 static int agent_owns_clipboard[256] = { 0, };
72 static FILE *logfile = NULL;
73 static int quit = 0;
74 static int retval = 0;
76 /* utility functions */
77 /* vdagentd <-> spice-client communication handling */
78 static void send_capabilities(struct vdagent_virtio_port *vport,
79 uint32_t request)
81 VDAgentAnnounceCapabilities *caps;
82 uint32_t size;
84 size = sizeof(*caps) + VD_AGENT_CAPS_BYTES;
85 caps = calloc(1, size);
86 if (!caps) {
87 fprintf(logfile,
88 "out of memory allocating capabilities array (write)\n");
89 return;
92 caps->request = request;
93 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MOUSE_STATE);
94 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG);
95 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_REPLY);
96 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
97 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION);
99 vdagent_virtio_port_write(vport, VDP_CLIENT_PORT,
100 VD_AGENT_ANNOUNCE_CAPABILITIES, 0,
101 (uint8_t *)caps, size);
102 free(caps);
105 static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr,
106 VDAgentMessage *message_header, VDAgentMonitorsConfig *new_monitors)
108 VDAgentReply reply;
109 uint32_t size;
111 /* Store monitor config to send to agents when they connect */
112 size = sizeof(VDAgentMonitorsConfig) +
113 new_monitors->num_of_monitors * sizeof(VDAgentMonConfig);
114 if (message_header->size != size) {
115 fprintf(logfile, "invalid message size for VDAgentMonitorsConfig\n");
116 return;
119 if (!mon_config ||
120 mon_config->num_of_monitors != new_monitors->num_of_monitors) {
121 free(mon_config);
122 mon_config = malloc(size);
123 if (!mon_config) {
124 fprintf(logfile, "out of memory allocating monitors config\n");
125 return;
128 memcpy(mon_config, new_monitors, size);
130 /* Send monitor config to currently connected agents */
131 udscs_server_write_all(server, VDAGENTD_MONITORS_CONFIG, 0, 0,
132 (uint8_t *)mon_config, size);
134 /* Acknowledge reception of monitors config to spice server / client */
135 reply.type = VD_AGENT_MONITORS_CONFIG;
136 reply.error = VD_AGENT_SUCCESS;
137 vdagent_virtio_port_write(vport, port_nr, VD_AGENT_REPLY, 0,
138 (uint8_t *)&reply, sizeof(reply));
141 static void do_client_capabilities(struct vdagent_virtio_port *vport,
142 VDAgentMessage *message_header,
143 VDAgentAnnounceCapabilities *caps)
145 int new_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(message_header->size);
147 if (capabilities_size != new_size) {
148 capabilities_size = new_size;
149 free(capabilities);
150 capabilities = malloc(capabilities_size * sizeof(uint32_t));
151 if (!capabilities) {
152 fprintf(logfile,
153 "out of memory allocating capabilities array (read)\n");
154 capabilities_size = 0;
155 return;
158 memcpy(capabilities, caps->caps, capabilities_size * sizeof(uint32_t));
159 if (caps->request)
160 send_capabilities(vport, 0);
163 static void do_client_clipboard(struct vdagent_virtio_port *vport,
164 VDAgentMessage *message_header, uint8_t *data)
166 uint32_t msg_type = 0, data_type = 0, size = message_header->size;
167 uint8_t selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD;
169 if (!active_session_conn) {
170 fprintf(logfile,
171 "Could not find an agent connnection belonging to the "
172 "active session, ignoring client clipboard request\n");
173 return;
176 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
177 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
178 selection = data[0];
179 data += 4;
180 size -= 4;
183 switch (message_header->type) {
184 case VD_AGENT_CLIPBOARD_GRAB:
185 msg_type = VDAGENTD_CLIPBOARD_GRAB;
186 agent_owns_clipboard[selection] = 0;
187 break;
188 case VD_AGENT_CLIPBOARD_REQUEST: {
189 VDAgentClipboardRequest *req = (VDAgentClipboardRequest *)data;
190 msg_type = VDAGENTD_CLIPBOARD_REQUEST;
191 data_type = req->type;
192 data = NULL;
193 size = 0;
194 break;
196 case VD_AGENT_CLIPBOARD: {
197 VDAgentClipboard *clipboard = (VDAgentClipboard *)data;
198 msg_type = VDAGENTD_CLIPBOARD_DATA;
199 data_type = clipboard->type;
200 size = size - sizeof(VDAgentClipboard);
201 data = clipboard->data;
202 break;
204 case VD_AGENT_CLIPBOARD_RELEASE:
205 msg_type = VDAGENTD_CLIPBOARD_RELEASE;
206 data = NULL;
207 size = 0;
208 break;
211 udscs_write(active_session_conn, msg_type, selection, data_type,
212 data, size);
215 int virtio_port_read_complete(
216 struct vdagent_virtio_port *vport,
217 int port_nr,
218 VDAgentMessage *message_header,
219 uint8_t *data)
221 uint32_t min_size = 0;
223 if (message_header->protocol != VD_AGENT_PROTOCOL) {
224 fprintf(logfile, "message with wrong protocol version ignoring\n");
225 return 0;
228 switch (message_header->type) {
229 case VD_AGENT_MOUSE_STATE:
230 if (message_header->size != sizeof(VDAgentMouseState))
231 goto size_error;
232 vdagentd_uinput_do_mouse(&uinput, (VDAgentMouseState *)data);
233 if (!uinput) {
234 /* Try to re-open the tablet */
235 struct agent_data *agent_data =
236 udscs_get_user_data(active_session_conn);
237 if (agent_data)
238 uinput = vdagentd_uinput_create(uinput_device,
239 agent_data->width,
240 agent_data->height,
241 logfile, debug > 1);
242 if (!uinput) {
243 fprintf(logfile, "Fatal uinput error\n");
244 retval = 1;
245 quit = 1;
248 break;
249 case VD_AGENT_MONITORS_CONFIG:
250 if (message_header->size < sizeof(VDAgentMonitorsConfig))
251 goto size_error;
252 do_client_monitors(vport, port_nr, message_header,
253 (VDAgentMonitorsConfig *)data);
254 break;
255 case VD_AGENT_ANNOUNCE_CAPABILITIES:
256 if (message_header->size < sizeof(VDAgentAnnounceCapabilities))
257 goto size_error;
258 do_client_capabilities(vport, message_header,
259 (VDAgentAnnounceCapabilities *)data);
260 break;
261 case VD_AGENT_CLIPBOARD_GRAB:
262 case VD_AGENT_CLIPBOARD_REQUEST:
263 case VD_AGENT_CLIPBOARD:
264 case VD_AGENT_CLIPBOARD_RELEASE:
265 switch (message_header->type) {
266 case VD_AGENT_CLIPBOARD_GRAB:
267 min_size = sizeof(VDAgentClipboardGrab); break;
268 case VD_AGENT_CLIPBOARD_REQUEST:
269 min_size = sizeof(VDAgentClipboardRequest); break;
270 case VD_AGENT_CLIPBOARD:
271 min_size = sizeof(VDAgentClipboard); break;
273 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
274 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
275 min_size += 4;
277 if (message_header->size < min_size) {
278 goto size_error;
280 do_client_clipboard(vport, message_header, data);
281 break;
282 default:
283 if (debug)
284 fprintf(logfile, "unknown message type %d\n", message_header->type);
285 break;
288 return 0;
290 size_error:
291 fprintf(logfile, "read: invalid message size: %u for message type: %u\n",
292 message_header->size, message_header->type);
293 return 0;
296 /* vdagentd <-> vdagent communication handling */
297 int do_agent_clipboard(struct udscs_connection *conn,
298 struct udscs_message_header *header, const uint8_t *data)
300 const uint8_t *msg;
301 uint8_t *buf = NULL, selection = header->arg1;
302 uint32_t msg_type = 0, data_type = -1, size = header->size;
304 if (!VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
305 VD_AGENT_CAP_CLIPBOARD_BY_DEMAND))
306 goto error;
308 /* Check that this agent is from the currently active session */
309 if (conn != active_session_conn) {
310 fprintf(logfile, "Clipboard request from agent "
311 "which is not in the active session?\n");
312 goto error;
315 if (!virtio_port) {
316 fprintf(logfile,
317 "Clipboard request from agent but no client connection\n");
318 goto error;
321 if (!VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
322 VD_AGENT_CAP_CLIPBOARD_SELECTION) &&
323 selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
324 goto error;
327 switch (header->type) {
328 case VDAGENTD_CLIPBOARD_GRAB:
329 msg_type = VD_AGENT_CLIPBOARD_GRAB;
330 agent_owns_clipboard[selection] = 1;
331 break;
332 case VDAGENTD_CLIPBOARD_REQUEST:
333 msg_type = VD_AGENT_CLIPBOARD_REQUEST;
334 data_type = header->arg2;
335 size = 0;
336 break;
337 case VDAGENTD_CLIPBOARD_DATA:
338 msg_type = VD_AGENT_CLIPBOARD;
339 data_type = header->arg2;
340 break;
341 case VDAGENTD_CLIPBOARD_RELEASE:
342 msg_type = VD_AGENT_CLIPBOARD_RELEASE;
343 size = 0;
344 agent_owns_clipboard[selection] = 0;
345 break;
348 if (size != header->size) {
349 fprintf(logfile,
350 "unexpected extra data in clipboard msg, disconnecting agent\n");
351 return -1;
354 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
355 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
356 size += 4;
358 if (data_type != -1) {
359 size += 4;
361 if (size != header->size) {
362 uint8_t *p;
363 buf = p = malloc(size);
364 if (!buf) {
365 fprintf(logfile, "out of memory allocating clipboard (write)\n");
366 return -1;
368 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
369 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
370 p[0] = selection;
371 p[1] = 0;
372 p[2] = 0;
373 p[3] = 0;
374 p += 4;
376 if (data_type != -1) {
377 uint32_t *u = (uint32_t *)p;
378 u[0] = data_type;
379 p += 4;
381 memcpy(p, data, header->size);
382 msg = buf;
383 } else {
384 msg = data;
387 vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT, msg_type,
388 0, msg, size);
389 free(buf);
390 return 0;
392 error:
393 if (header->type == VDAGENTD_CLIPBOARD_REQUEST) {
394 /* Let the agent know no answer is coming */
395 udscs_write(conn, VDAGENTD_CLIPBOARD_DATA,
396 selection, VD_AGENT_CLIPBOARD_NONE, NULL, 0);
398 return 0;
401 /* When we open the vdagent virtio channel, the server automatically goes into
402 client mouse mode, so we can only have the channel open when we know the
403 active session resolution. This function checks that we have an agent in the
404 active session, and that it has told us its resolution. If these conditions
405 are met it sets the uinput tablet device's resolution and opens the virtio
406 channel (if it is not already open). If these conditions are not met, it
407 closes both. */
408 static void check_xorg_resolution(void)
410 struct agent_data *agent_data = udscs_get_user_data(active_session_conn);
412 if (agent_data && agent_data->width) {
413 if (!uinput)
414 uinput = vdagentd_uinput_create(uinput_device,
415 agent_data->width,
416 agent_data->height,
417 logfile, debug > 1);
418 else
419 vdagentd_uinput_update_size(&uinput, agent_data->width,
420 agent_data->height);
421 if (!uinput) {
422 fprintf(logfile, "Fatal uinput error\n");
423 retval = 1;
424 quit = 1;
425 return;
428 if (!virtio_port) {
429 fprintf(logfile, "opening vdagent virtio channel\n");
430 virtio_port = vdagent_virtio_port_create(portdev,
431 virtio_port_read_complete,
432 NULL, logfile);
433 if (!virtio_port) {
434 fprintf(logfile,
435 "Fatal error opening vdagent virtio channel\n");
436 retval = 1;
437 quit = 1;
438 return;
440 send_capabilities(virtio_port, 1);
442 } else {
443 vdagentd_uinput_destroy(&uinput);
444 if (virtio_port) {
445 vdagent_virtio_port_flush(&virtio_port);
446 vdagent_virtio_port_destroy(&virtio_port);
447 fprintf(logfile, "closed vdagent virtio channel\n");
452 #ifdef HAVE_CONSOLE_KIT
453 static int connection_matches_active_session(struct udscs_connection **connp,
454 void *priv)
456 struct udscs_connection **conn_ret = (struct udscs_connection **)priv;
457 struct agent_data *agent_data = udscs_get_user_data(*connp);
459 /* Check if this connection matches the currently active session */
460 if (!agent_data->session || !active_session)
461 return 0;
462 if (strcmp(agent_data->session, active_session))
463 return 0;
465 *conn_ret = *connp;
466 return 1;
469 void release_clipboards(void)
471 uint8_t sel;
473 for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; ++sel) {
474 if (agent_owns_clipboard[sel] && virtio_port) {
475 vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT,
476 VD_AGENT_CLIPBOARD_RELEASE, 0, &sel, 1);
478 agent_owns_clipboard[sel] = 0;
481 #endif
483 void update_active_session_connection(void)
485 struct udscs_connection *new_conn = NULL;
486 int n;
488 #ifdef HAVE_CONSOLE_KIT
489 if (!active_session)
490 active_session = console_kit_get_active_session(console_kit);
492 n = udscs_server_for_all_clients(server, connection_matches_active_session,
493 (void*)&new_conn);
494 if (n != 1)
495 new_conn = NULL;
497 if (new_conn == active_session_conn)
498 return;
500 active_session_conn = new_conn;
501 #endif
503 release_clipboards();
505 check_xorg_resolution();
508 void agent_connect(struct udscs_connection *conn)
510 uint32_t pid;
511 struct agent_data *agent_data;
513 agent_data = calloc(1, sizeof(*agent_data));
514 if (!agent_data) {
515 fprintf(logfile, "Out of memory allocating agent data, disconnecting\n");
516 udscs_destroy_connection(&conn);
517 return;
519 #ifdef HAVE_CONSOLE_KIT
520 pid = udscs_get_peer_cred(conn).pid;
521 agent_data->session = console_kit_session_for_pid(console_kit, pid);
522 #else
523 session_count++;
524 if (session_count == 1)
525 active_session_conn = conn;
526 else {
527 /* disable communication with agents when we've got multiple
528 * connections to the vdagentd and no consolekit since we can't
529 * know to which one we should send data
531 fprintf(logfile, "Trying to use multiple vdagent without ConsoleKit support, "
532 "disabling vdagent to avoid potential information leak\n");
533 active_session_conn = NULL;
536 #endif
537 udscs_set_user_data(conn, (void *)agent_data);
538 update_active_session_connection();
540 if (mon_config)
541 udscs_write(conn, VDAGENTD_MONITORS_CONFIG, 0, 0,
542 (uint8_t *)mon_config, sizeof(VDAgentMonitorsConfig) +
543 mon_config->num_of_monitors * sizeof(VDAgentMonConfig));
546 void agent_disconnect(struct udscs_connection *conn)
548 struct agent_data *agent_data = udscs_get_user_data(conn);
550 free(agent_data->session);
551 agent_data->session = NULL;
552 update_active_session_connection();
554 free(agent_data);
555 #ifndef HAVE_CONSOLE_KIT
556 session_count--;
557 #endif
560 void agent_read_complete(struct udscs_connection **connp,
561 struct udscs_message_header *header, uint8_t *data)
563 struct agent_data *agent_data = udscs_get_user_data(*connp);
565 switch (header->type) {
566 case VDAGENTD_GUEST_XORG_RESOLUTION: {
567 struct vdagentd_guest_xorg_resolution *res =
568 (struct vdagentd_guest_xorg_resolution *)data;
570 if (header->size != sizeof(*res)) {
571 fprintf(logfile,
572 "guest xorg resolution message has wrong size, disconnecting agent\n");
573 udscs_destroy_connection(connp);
574 return;
577 agent_data->width = res->width;
578 agent_data->height = res->height;
579 check_xorg_resolution();
580 break;
582 case VDAGENTD_CLIPBOARD_GRAB:
583 case VDAGENTD_CLIPBOARD_REQUEST:
584 case VDAGENTD_CLIPBOARD_DATA:
585 case VDAGENTD_CLIPBOARD_RELEASE:
586 if (do_agent_clipboard(*connp, header, data)) {
587 udscs_destroy_connection(connp);
588 return;
590 break;
591 default:
592 fprintf(logfile, "unknown message from vdagent: %u, ignoring\n",
593 header->type);
595 free(data);
598 /* main */
600 static void usage(FILE *fp)
602 fprintf(fp,
603 "vdagentd\n"
604 "options:\n"
605 " -h print this text\n"
606 " -d log debug messages (use twice for extra info)\n"
607 " -s <port> set virtio serial port [%s]\n"
608 " -u <dev> set uinput device [%s]\n"
609 " -x don't daemonize (and log to logfile)\n",
610 portdev, uinput_device);
613 void daemonize(void)
615 int x;
616 FILE *pidfile;
618 /* detach from terminal */
619 switch (fork()) {
620 case 0:
621 close(0); close(1); close(2);
622 setsid();
623 x = open("/dev/null", O_RDWR); dup(x); dup(x);
624 pidfile = fopen(pidfilename, "w");
625 if (pidfile) {
626 fprintf(pidfile, "%d\n", (int)getpid());
627 fclose(pidfile);
629 break;
630 case -1:
631 fprintf(logfile, "fork: %s\n", strerror(errno));
632 retval = 1;
633 default:
634 udscs_destroy_server(server);
635 if (logfile != stderr)
636 fclose(logfile);
637 exit(retval);
641 void main_loop(void)
643 fd_set readfds, writefds;
644 int n, nfds, ck_fd = 0;
646 while (!quit) {
647 FD_ZERO(&readfds);
648 FD_ZERO(&writefds);
650 nfds = udscs_server_fill_fds(server, &readfds, &writefds);
651 n = vdagent_virtio_port_fill_fds(virtio_port, &readfds, &writefds);
652 if (n >= nfds)
653 nfds = n + 1;
655 #ifdef HAVE_CONSOLE_KIT
656 ck_fd = console_kit_get_fd(console_kit);
657 FD_SET(ck_fd, &readfds);
658 if (ck_fd >= nfds)
659 nfds = ck_fd + 1;
660 #endif
662 n = select(nfds, &readfds, &writefds, NULL, NULL);
663 if (n == -1) {
664 if (errno == EINTR)
665 continue;
666 fprintf(logfile, "Fatal error select: %s\n", strerror(errno));
667 retval = 1;
668 break;
671 udscs_server_handle_fds(server, &readfds, &writefds);
673 if (virtio_port) {
674 vdagent_virtio_port_handle_fds(&virtio_port, &readfds, &writefds);
675 if (!virtio_port) {
676 fprintf(logfile,
677 "AIIEEE lost spice client connection, reconnecting\n");
678 virtio_port = vdagent_virtio_port_create(portdev,
679 virtio_port_read_complete,
680 NULL, logfile);
682 if (!virtio_port) {
683 fprintf(logfile,
684 "Fatal error opening vdagent virtio channel\n");
685 retval = 1;
686 break;
690 #ifdef HAVE_CONSOLE_KIT
691 if (FD_ISSET(ck_fd, &readfds)) {
692 active_session = console_kit_get_active_session(console_kit);
693 update_active_session_connection();
695 #endif
696 fflush(logfile);
700 static void quit_handler(int sig)
702 quit = 1;
705 int main(int argc, char *argv[])
707 int c;
708 int do_daemonize = 1;
709 struct sigaction act;
711 for (;;) {
712 if (-1 == (c = getopt(argc, argv, "-dhxs:u:")))
713 break;
714 switch (c) {
715 case 'd':
716 debug++;
717 break;
718 case 's':
719 portdev = optarg;
720 break;
721 case 'u':
722 uinput_device = optarg;
723 break;
724 case 'x':
725 do_daemonize = 0;
726 break;
727 case 'h':
728 usage(stdout);
729 return 0;
730 default:
731 usage(stderr);
732 return 1;
736 memset(&act, 0, sizeof(act));
737 act.sa_flags = SA_RESTART;
738 act.sa_handler = quit_handler;
739 sigaction(SIGINT, &act, NULL);
740 sigaction(SIGHUP, &act, NULL);
741 sigaction(SIGTERM, &act, NULL);
742 sigaction(SIGQUIT, &act, NULL);
744 if (do_daemonize) {
745 logfile = fopen(logfilename, "a");
746 if (!logfile) {
747 fprintf(stderr, "Error opening %s: %s\n", logfilename,
748 strerror(errno));
749 logfile = stderr;
751 } else
752 logfile = stderr;
754 /* Setup communication with vdagent process(es) */
755 server = udscs_create_server(VDAGENTD_SOCKET, agent_connect,
756 agent_read_complete, agent_disconnect,
757 vdagentd_messages, VDAGENTD_NO_MESSAGES,
758 debug? logfile:NULL, logfile);
759 if (!server) {
760 fprintf(logfile, "Fatal could not create server socket %s\n",
761 VDAGENTD_SOCKET);
762 if (logfile != stderr)
763 fclose(logfile);
764 return 1;
766 if (chmod(VDAGENTD_SOCKET, 0666)) {
767 fprintf(logfile, "Fatal could not change permissions on %s: %s\n",
768 VDAGENTD_SOCKET, strerror(errno));
769 udscs_destroy_server(server);
770 if (logfile != stderr)
771 fclose(logfile);
772 return 1;
775 if (do_daemonize)
776 daemonize();
778 #ifdef HAVE_CONSOLE_KIT
779 console_kit = console_kit_create(logfile);
780 if (!console_kit) {
781 fprintf(logfile, "Fatal could not connect to console kit\n");
782 udscs_destroy_server(server);
783 if (logfile != stderr)
784 fclose(logfile);
785 return 1;
787 #endif
789 main_loop();
791 release_clipboards();
793 vdagentd_uinput_destroy(&uinput);
794 vdagent_virtio_port_flush(&virtio_port);
795 vdagent_virtio_port_destroy(&virtio_port);
796 #ifdef HAVE_CONSOLE_KIT
797 console_kit_destroy(console_kit);
798 #endif
799 udscs_destroy_server(server);
800 if (unlink(VDAGENTD_SOCKET) != 0)
801 fprintf(logfile, "unlink %s: %s\n", VDAGENTD_SOCKET, strerror(errno));
802 fprintf(logfile, "vdagentd quiting, returning status %d\n", retval);
803 if (logfile != stderr)
804 fclose(logfile);
806 if (do_daemonize)
807 unlink(pidfilename);
809 return retval;