vdagentd: fix compilation without consolekit
[vd_agent.git] / src / vdagentd.c
blobbe6ef1f8ac99fdc60f6da355692907dc07fa8a1a
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 uint8_t selection = header->arg1;
301 uint32_t msg_type = 0, data_type = -1, size = header->size;
303 if (!VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
304 VD_AGENT_CAP_CLIPBOARD_BY_DEMAND))
305 goto error;
307 /* Check that this agent is from the currently active session */
308 if (conn != active_session_conn) {
309 fprintf(logfile, "Clipboard request from agent "
310 "which is not in the active session?\n");
311 goto error;
314 if (!virtio_port) {
315 fprintf(logfile,
316 "Clipboard request from agent but no client connection\n");
317 goto error;
320 if (!VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
321 VD_AGENT_CAP_CLIPBOARD_SELECTION) &&
322 selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
323 goto error;
326 switch (header->type) {
327 case VDAGENTD_CLIPBOARD_GRAB:
328 msg_type = VD_AGENT_CLIPBOARD_GRAB;
329 agent_owns_clipboard[selection] = 1;
330 break;
331 case VDAGENTD_CLIPBOARD_REQUEST:
332 msg_type = VD_AGENT_CLIPBOARD_REQUEST;
333 data_type = header->arg2;
334 size = 0;
335 break;
336 case VDAGENTD_CLIPBOARD_DATA:
337 msg_type = VD_AGENT_CLIPBOARD;
338 data_type = header->arg2;
339 break;
340 case VDAGENTD_CLIPBOARD_RELEASE:
341 msg_type = VD_AGENT_CLIPBOARD_RELEASE;
342 size = 0;
343 agent_owns_clipboard[selection] = 0;
344 break;
347 if (size != header->size) {
348 fprintf(logfile,
349 "unexpected extra data in clipboard msg, disconnecting agent\n");
350 return -1;
353 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
354 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
355 size += 4;
357 if (data_type != -1) {
358 size += 4;
361 vdagent_virtio_port_write_start(virtio_port, VDP_CLIENT_PORT, msg_type,
362 0, size);
364 if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
365 VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
366 uint8_t sel[4] = { selection, 0, 0, 0 };
367 vdagent_virtio_port_write_append(virtio_port, sel, 4);
369 if (data_type != -1) {
370 vdagent_virtio_port_write_append(virtio_port, (uint8_t*)&data_type, 4);
373 vdagent_virtio_port_write_append(virtio_port, data, header->size);
375 return 0;
377 error:
378 if (header->type == VDAGENTD_CLIPBOARD_REQUEST) {
379 /* Let the agent know no answer is coming */
380 udscs_write(conn, VDAGENTD_CLIPBOARD_DATA,
381 selection, VD_AGENT_CLIPBOARD_NONE, NULL, 0);
383 return 0;
386 /* When we open the vdagent virtio channel, the server automatically goes into
387 client mouse mode, so we can only have the channel open when we know the
388 active session resolution. This function checks that we have an agent in the
389 active session, and that it has told us its resolution. If these conditions
390 are met it sets the uinput tablet device's resolution and opens the virtio
391 channel (if it is not already open). If these conditions are not met, it
392 closes both. */
393 static void check_xorg_resolution(void)
395 struct agent_data *agent_data = udscs_get_user_data(active_session_conn);
397 if (agent_data && agent_data->width) {
398 if (!uinput)
399 uinput = vdagentd_uinput_create(uinput_device,
400 agent_data->width,
401 agent_data->height,
402 logfile, debug > 1);
403 else
404 vdagentd_uinput_update_size(&uinput, agent_data->width,
405 agent_data->height);
406 if (!uinput) {
407 fprintf(logfile, "Fatal uinput error\n");
408 retval = 1;
409 quit = 1;
410 return;
413 if (!virtio_port) {
414 fprintf(logfile, "opening vdagent virtio channel\n");
415 virtio_port = vdagent_virtio_port_create(portdev,
416 virtio_port_read_complete,
417 NULL, logfile);
418 if (!virtio_port) {
419 fprintf(logfile,
420 "Fatal error opening vdagent virtio channel\n");
421 retval = 1;
422 quit = 1;
423 return;
425 send_capabilities(virtio_port, 1);
427 } else {
428 vdagentd_uinput_destroy(&uinput);
429 if (virtio_port) {
430 vdagent_virtio_port_flush(&virtio_port);
431 vdagent_virtio_port_destroy(&virtio_port);
432 fprintf(logfile, "closed vdagent virtio channel\n");
437 #ifdef HAVE_CONSOLE_KIT
438 static int connection_matches_active_session(struct udscs_connection **connp,
439 void *priv)
441 struct udscs_connection **conn_ret = (struct udscs_connection **)priv;
442 struct agent_data *agent_data = udscs_get_user_data(*connp);
444 /* Check if this connection matches the currently active session */
445 if (!agent_data->session || !active_session)
446 return 0;
447 if (strcmp(agent_data->session, active_session))
448 return 0;
450 *conn_ret = *connp;
451 return 1;
453 #endif
455 void release_clipboards(void)
457 uint8_t sel;
459 for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; ++sel) {
460 if (agent_owns_clipboard[sel] && virtio_port) {
461 vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT,
462 VD_AGENT_CLIPBOARD_RELEASE, 0, &sel, 1);
464 agent_owns_clipboard[sel] = 0;
468 void update_active_session_connection(void)
470 struct udscs_connection *new_conn = NULL;
471 int n;
473 #ifdef HAVE_CONSOLE_KIT
474 if (!active_session)
475 active_session = console_kit_get_active_session(console_kit);
477 n = udscs_server_for_all_clients(server, connection_matches_active_session,
478 (void*)&new_conn);
479 if (n != 1)
480 new_conn = NULL;
482 if (new_conn == active_session_conn)
483 return;
485 active_session_conn = new_conn;
486 #endif
488 release_clipboards();
490 check_xorg_resolution();
493 void agent_connect(struct udscs_connection *conn)
495 uint32_t pid;
496 struct agent_data *agent_data;
498 agent_data = calloc(1, sizeof(*agent_data));
499 if (!agent_data) {
500 fprintf(logfile, "Out of memory allocating agent data, disconnecting\n");
501 udscs_destroy_connection(&conn);
502 return;
504 #ifdef HAVE_CONSOLE_KIT
505 pid = udscs_get_peer_cred(conn).pid;
506 agent_data->session = console_kit_session_for_pid(console_kit, pid);
507 #else
508 session_count++;
509 if (session_count == 1)
510 active_session_conn = conn;
511 else {
512 /* disable communication with agents when we've got multiple
513 * connections to the vdagentd and no consolekit since we can't
514 * know to which one we should send data
516 fprintf(logfile, "Trying to use multiple vdagent without ConsoleKit support, "
517 "disabling vdagent to avoid potential information leak\n");
518 active_session_conn = NULL;
521 #endif
522 udscs_set_user_data(conn, (void *)agent_data);
523 update_active_session_connection();
525 if (mon_config)
526 udscs_write(conn, VDAGENTD_MONITORS_CONFIG, 0, 0,
527 (uint8_t *)mon_config, sizeof(VDAgentMonitorsConfig) +
528 mon_config->num_of_monitors * sizeof(VDAgentMonConfig));
531 void agent_disconnect(struct udscs_connection *conn)
533 struct agent_data *agent_data = udscs_get_user_data(conn);
535 free(agent_data->session);
536 agent_data->session = NULL;
537 update_active_session_connection();
539 free(agent_data);
540 #ifndef HAVE_CONSOLE_KIT
541 session_count--;
542 #endif
545 void agent_read_complete(struct udscs_connection **connp,
546 struct udscs_message_header *header, uint8_t *data)
548 struct agent_data *agent_data = udscs_get_user_data(*connp);
550 switch (header->type) {
551 case VDAGENTD_GUEST_XORG_RESOLUTION: {
552 struct vdagentd_guest_xorg_resolution *res =
553 (struct vdagentd_guest_xorg_resolution *)data;
555 if (header->size != sizeof(*res)) {
556 fprintf(logfile,
557 "guest xorg resolution message has wrong size, disconnecting agent\n");
558 udscs_destroy_connection(connp);
559 return;
562 agent_data->width = res->width;
563 agent_data->height = res->height;
564 check_xorg_resolution();
565 break;
567 case VDAGENTD_CLIPBOARD_GRAB:
568 case VDAGENTD_CLIPBOARD_REQUEST:
569 case VDAGENTD_CLIPBOARD_DATA:
570 case VDAGENTD_CLIPBOARD_RELEASE:
571 if (do_agent_clipboard(*connp, header, data)) {
572 udscs_destroy_connection(connp);
573 return;
575 break;
576 default:
577 fprintf(logfile, "unknown message from vdagent: %u, ignoring\n",
578 header->type);
580 free(data);
583 /* main */
585 static void usage(FILE *fp)
587 fprintf(fp,
588 "vdagentd\n"
589 "options:\n"
590 " -h print this text\n"
591 " -d log debug messages (use twice for extra info)\n"
592 " -s <port> set virtio serial port [%s]\n"
593 " -u <dev> set uinput device [%s]\n"
594 " -x don't daemonize (and log to logfile)\n",
595 portdev, uinput_device);
598 void daemonize(void)
600 int x;
601 FILE *pidfile;
603 /* detach from terminal */
604 switch (fork()) {
605 case 0:
606 close(0); close(1); close(2);
607 setsid();
608 x = open("/dev/null", O_RDWR); dup(x); dup(x);
609 pidfile = fopen(pidfilename, "w");
610 if (pidfile) {
611 fprintf(pidfile, "%d\n", (int)getpid());
612 fclose(pidfile);
614 break;
615 case -1:
616 fprintf(logfile, "fork: %s\n", strerror(errno));
617 retval = 1;
618 default:
619 udscs_destroy_server(server);
620 if (logfile != stderr)
621 fclose(logfile);
622 exit(retval);
626 void main_loop(void)
628 fd_set readfds, writefds;
629 int n, nfds, ck_fd = 0;
631 while (!quit) {
632 FD_ZERO(&readfds);
633 FD_ZERO(&writefds);
635 nfds = udscs_server_fill_fds(server, &readfds, &writefds);
636 n = vdagent_virtio_port_fill_fds(virtio_port, &readfds, &writefds);
637 if (n >= nfds)
638 nfds = n + 1;
640 #ifdef HAVE_CONSOLE_KIT
641 ck_fd = console_kit_get_fd(console_kit);
642 FD_SET(ck_fd, &readfds);
643 if (ck_fd >= nfds)
644 nfds = ck_fd + 1;
645 #endif
647 n = select(nfds, &readfds, &writefds, NULL, NULL);
648 if (n == -1) {
649 if (errno == EINTR)
650 continue;
651 fprintf(logfile, "Fatal error select: %s\n", strerror(errno));
652 retval = 1;
653 break;
656 udscs_server_handle_fds(server, &readfds, &writefds);
658 if (virtio_port) {
659 vdagent_virtio_port_handle_fds(&virtio_port, &readfds, &writefds);
660 if (!virtio_port) {
661 fprintf(logfile,
662 "AIIEEE lost spice client connection, reconnecting\n");
663 virtio_port = vdagent_virtio_port_create(portdev,
664 virtio_port_read_complete,
665 NULL, logfile);
667 if (!virtio_port) {
668 fprintf(logfile,
669 "Fatal error opening vdagent virtio channel\n");
670 retval = 1;
671 break;
675 #ifdef HAVE_CONSOLE_KIT
676 if (FD_ISSET(ck_fd, &readfds)) {
677 active_session = console_kit_get_active_session(console_kit);
678 update_active_session_connection();
680 #endif
681 fflush(logfile);
685 static void quit_handler(int sig)
687 quit = 1;
690 int main(int argc, char *argv[])
692 int c;
693 int do_daemonize = 1;
694 struct sigaction act;
696 for (;;) {
697 if (-1 == (c = getopt(argc, argv, "-dhxs:u:")))
698 break;
699 switch (c) {
700 case 'd':
701 debug++;
702 break;
703 case 's':
704 portdev = optarg;
705 break;
706 case 'u':
707 uinput_device = optarg;
708 break;
709 case 'x':
710 do_daemonize = 0;
711 break;
712 case 'h':
713 usage(stdout);
714 return 0;
715 default:
716 usage(stderr);
717 return 1;
721 memset(&act, 0, sizeof(act));
722 act.sa_flags = SA_RESTART;
723 act.sa_handler = quit_handler;
724 sigaction(SIGINT, &act, NULL);
725 sigaction(SIGHUP, &act, NULL);
726 sigaction(SIGTERM, &act, NULL);
727 sigaction(SIGQUIT, &act, NULL);
729 if (do_daemonize) {
730 logfile = fopen(logfilename, "a");
731 if (!logfile) {
732 fprintf(stderr, "Error opening %s: %s\n", logfilename,
733 strerror(errno));
734 logfile = stderr;
736 } else
737 logfile = stderr;
739 /* Setup communication with vdagent process(es) */
740 server = udscs_create_server(VDAGENTD_SOCKET, agent_connect,
741 agent_read_complete, agent_disconnect,
742 vdagentd_messages, VDAGENTD_NO_MESSAGES,
743 debug? logfile:NULL, logfile);
744 if (!server) {
745 fprintf(logfile, "Fatal could not create server socket %s\n",
746 VDAGENTD_SOCKET);
747 if (logfile != stderr)
748 fclose(logfile);
749 return 1;
751 if (chmod(VDAGENTD_SOCKET, 0666)) {
752 fprintf(logfile, "Fatal could not change permissions on %s: %s\n",
753 VDAGENTD_SOCKET, strerror(errno));
754 udscs_destroy_server(server);
755 if (logfile != stderr)
756 fclose(logfile);
757 return 1;
760 if (do_daemonize)
761 daemonize();
763 #ifdef HAVE_CONSOLE_KIT
764 console_kit = console_kit_create(logfile);
765 if (!console_kit) {
766 fprintf(logfile, "Fatal could not connect to console kit\n");
767 udscs_destroy_server(server);
768 if (logfile != stderr)
769 fclose(logfile);
770 return 1;
772 #endif
774 main_loop();
776 release_clipboards();
778 vdagentd_uinput_destroy(&uinput);
779 vdagent_virtio_port_flush(&virtio_port);
780 vdagent_virtio_port_destroy(&virtio_port);
781 #ifdef HAVE_CONSOLE_KIT
782 console_kit_destroy(console_kit);
783 #endif
784 udscs_destroy_server(server);
785 if (unlink(VDAGENTD_SOCKET) != 0)
786 fprintf(logfile, "unlink %s: %s\n", VDAGENTD_SOCKET, strerror(errno));
787 fprintf(logfile, "vdagentd quiting, returning status %d\n", retval);
788 if (logfile != stderr)
789 fclose(logfile);
791 if (do_daemonize)
792 unlink(pidfilename);
794 return retval;