1 /* vdagent.c xorg-client to vdagentd (daemon).
3 Copyright 2010 Red Hat, Inc.
6 Hans de Goede <hdegoede@redhat.com>
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
33 #include <sys/select.h>
35 #include <spice/vd_agent.h>
38 #include "vdagentd-proto.h"
39 #include "vdagentd-proto-strings.h"
40 #include "vdagent-x11.h"
42 static const char *portdev
= "/dev/virtio-ports/com.redhat.spice.0";
43 static int verbose
= 0;
44 static struct vdagent_x11
*x11
= NULL
;
45 static struct udscs_connection
*client
= NULL
;
46 static FILE *logfile
= NULL
;
48 static int version_mismatch
= 0;
50 void daemon_read_complete(struct udscs_connection
**connp
,
51 struct udscs_message_header
*header
, uint8_t *data
)
53 switch (header
->type
) {
54 case VDAGENTD_MONITORS_CONFIG
:
55 vdagent_x11_set_monitor_config(x11
, (VDAgentMonitorsConfig
*)data
);
58 case VDAGENTD_CLIPBOARD_REQUEST
:
59 vdagent_x11_clipboard_request(x11
, header
->arg1
, header
->arg2
);
62 case VDAGENTD_CLIPBOARD_GRAB
:
63 vdagent_x11_clipboard_grab(x11
, header
->arg1
, (uint32_t *)data
,
64 header
->size
/ sizeof(uint32_t));
67 case VDAGENTD_CLIPBOARD_DATA
:
68 vdagent_x11_clipboard_data(x11
, header
->arg1
, header
->arg2
,
70 /* vdagent_x11_clipboard_data takes ownership of the data (or frees
73 case VDAGENTD_CLIPBOARD_RELEASE
:
74 vdagent_x11_clipboard_release(x11
, header
->arg1
);
77 case VDAGENTD_VERSION
:
78 if (strcmp(data
, VERSION
) != 0) {
80 "Fatal vdagentd version mismatch: got %s expected %s\n",
82 udscs_destroy_connection(connp
);
88 fprintf(logfile
, "Unknown message from vdagentd type: %d\n",
94 int client_setup(int reconnect
)
97 client
= udscs_connect(VDAGENTD_SOCKET
, daemon_read_complete
, NULL
,
98 vdagentd_messages
, VDAGENTD_NO_MESSAGES
,
99 verbose
? logfile
: NULL
, logfile
);
100 if (client
|| !reconnect
|| quit
) {
105 return client
== NULL
;
108 static void usage(FILE *fp
)
111 "vdagent -- spice agent xorg client\n"
113 " -h print this text\n"
114 " -d log debug messages\n"
115 " -s <port> set virtio serial port [%s]\n"
116 " -x don't daemonize (and log to logfile)\n",
120 static void quit_handler(int sig
)
129 /* detach from terminal */
132 close(0); close(1); close(2);
134 x
= open("/dev/null", O_RDWR
); dup(x
); dup(x
);
137 fprintf(logfile
, "fork: %s\n", strerror(errno
));
140 if (logfile
!= stderr
)
146 static int file_test(const char *path
)
150 return stat(path
, &buffer
);
153 int main(int argc
, char *argv
[])
155 fd_set readfds
, writefds
;
156 int c
, n
, nfds
, x11_fd
, retval
= 0;
157 int do_daemonize
= 1;
158 char *home
, filename
[1024];
159 struct sigaction act
;
162 if (-1 == (c
= getopt(argc
, argv
, "-dxhs:")))
183 memset(&act
, 0, sizeof(act
));
184 act
.sa_flags
= SA_RESTART
;
185 act
.sa_handler
= quit_handler
;
186 sigaction(SIGINT
, &act
, NULL
);
187 sigaction(SIGHUP
, &act
, NULL
);
188 sigaction(SIGTERM
, &act
, NULL
);
189 sigaction(SIGQUIT
, &act
, NULL
);
192 home
= getenv("HOME");
194 snprintf(filename
, sizeof(filename
), "%s/.spice-vdagent", home
);
195 n
= mkdir(filename
, 0755);
196 snprintf(filename
, sizeof(filename
), "%s/.spice-vdagent/log", home
);
198 logfile
= fopen(filename
, "w");
200 fprintf(stderr
, "Error opening %s: %s\n", filename
,
206 fprintf(stderr
, "Could not get home directory, logging to stderr\n");
209 if (file_test(portdev
) != 0) {
210 fprintf(logfile
, "Missing virtio device: %s\n",
211 portdev
, strerror(errno
));
220 if (version_mismatch
) {
221 fprintf(logfile
, "Version mismatch, restarting\n");
222 if (logfile
!= stderr
)
225 execvp(argv
[0], argv
);
228 if (client_setup(do_daemonize
)) {
233 x11
= vdagent_x11_create(client
, logfile
, verbose
);
235 udscs_destroy_connection(&client
);
240 while (client
&& !quit
) {
244 nfds
= udscs_client_fill_fds(client
, &readfds
, &writefds
);
245 x11_fd
= vdagent_x11_get_fd(x11
);
246 FD_SET(x11_fd
, &readfds
);
250 n
= select(nfds
, &readfds
, &writefds
, NULL
, NULL
);
254 fprintf(logfile
, "Fatal error select: %s\n", strerror(errno
));
259 if (FD_ISSET(x11_fd
, &readfds
))
260 vdagent_x11_do_read(x11
);
261 udscs_client_handle_fds(&client
, &readfds
, &writefds
);
265 vdagent_x11_destroy(x11
);
266 udscs_destroy_connection(&client
);
271 if (logfile
!= stderr
)