Add wayvncctl --wait option
Signed-off-by: Jim Ramsay <i.am@jimramsay.com>pull/186/head
parent
372b530d3a
commit
6e13974b27
|
@ -28,5 +28,6 @@ void* ctl_client_userdata(struct ctl_client*);
|
|||
|
||||
#define PRINT_JSON 0x00000001
|
||||
|
||||
int ctl_client_connect(struct ctl_client* self, int timeout);
|
||||
int ctl_client_run_command(struct ctl_client* self,
|
||||
int argc, char* argv[], unsigned flags);
|
||||
|
|
|
@ -20,8 +20,10 @@
|
|||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include "json-ipc.h"
|
||||
|
@ -39,11 +41,12 @@ static bool do_debug = false;
|
|||
if (do_debug) \
|
||||
fprintf(stderr, "[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__);
|
||||
|
||||
#define FAILED_TO(action) \
|
||||
WARN("Failed to " action ": %m");
|
||||
#define FAILED_TO(action, ...) \
|
||||
WARN("Failed to " action ": %m", ##__VA_ARGS__);
|
||||
|
||||
struct ctl_client {
|
||||
void* userdata;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
char read_buffer[512];
|
||||
size_t read_len;
|
||||
|
@ -65,37 +68,76 @@ struct ctl_client* ctl_client_new(const char* socket_path, void* userdata)
|
|||
struct ctl_client* new = calloc(1, sizeof(*new));
|
||||
new->userdata = userdata;
|
||||
|
||||
struct sockaddr_un addr = {
|
||||
.sun_family = AF_UNIX,
|
||||
};
|
||||
|
||||
if (strlen(socket_path) >= sizeof(addr.sun_path)) {
|
||||
if (strlen(socket_path) >= sizeof(new->addr.sun_path)) {
|
||||
errno = ENAMETOOLONG;
|
||||
FAILED_TO("create unix socket");
|
||||
goto socket_failure;
|
||||
}
|
||||
strcpy(addr.sun_path, socket_path);
|
||||
strcpy(new->addr.sun_path, socket_path);
|
||||
new->addr.sun_family = AF_UNIX;
|
||||
|
||||
new->fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (new->fd < 0) {
|
||||
FAILED_TO("create unix socket");
|
||||
goto socket_failure;
|
||||
}
|
||||
|
||||
if (connect(new->fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
|
||||
FAILED_TO("connect to unix socket");
|
||||
goto connect_failure;
|
||||
}
|
||||
|
||||
return new;
|
||||
|
||||
connect_failure:
|
||||
close(new->fd);
|
||||
socket_failure:
|
||||
free(new);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ctl_client_connect(struct ctl_client* self, int timeout)
|
||||
{
|
||||
// TODO: Support arbitrary timeouts?
|
||||
assert(timeout == 0 || timeout == -1);
|
||||
// TODO: Use inotify instead of polling stat()
|
||||
bool needs_log = true;
|
||||
struct stat sb;
|
||||
while (stat(self->addr.sun_path, &sb) != 0) {
|
||||
if (timeout == 0) {
|
||||
FAILED_TO("find socket path \"%s\"",
|
||||
self->addr.sun_path);
|
||||
goto stat_failure;
|
||||
}
|
||||
if (needs_log) {
|
||||
needs_log = false;
|
||||
DEBUG("Waiting for socket path \"%s\" to appear",
|
||||
self->addr.sun_path);
|
||||
}
|
||||
if (usleep(50000) == -1) {
|
||||
FAILED_TO("wait for socket path");
|
||||
goto stat_failure;
|
||||
}
|
||||
}
|
||||
if (S_ISSOCK(sb.st_mode)) {
|
||||
DEBUG("Found socket \"%s\"", self->addr.sun_path);
|
||||
} else {
|
||||
WARN("Path \"%s\" exists but is not a socket (0x%x)",
|
||||
self->addr.sun_path, sb.st_mode);
|
||||
goto stat_failure;
|
||||
}
|
||||
while (connect(self->fd, (struct sockaddr*)&self->addr,
|
||||
sizeof(self->addr)) != 0) {
|
||||
if (timeout == 0 || errno != ENOENT) {
|
||||
FAILED_TO("connect to unix socket \"%s\"",
|
||||
self->addr.sun_path);
|
||||
goto stat_failure;
|
||||
return 1;
|
||||
}
|
||||
if (usleep(50000) == -1) {
|
||||
FAILED_TO("wait for connect to succeed");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
stat_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ctl_client_destroy(struct ctl_client* self)
|
||||
{
|
||||
close(self->fd);
|
||||
|
@ -107,7 +149,7 @@ void* ctl_client_userdata(struct ctl_client* self)
|
|||
return self->userdata;
|
||||
}
|
||||
|
||||
static struct jsonipc_request* ctl_client_parse_args(struct ctl_client* self,
|
||||
static struct jsonipc_request* ctl_client_parse_args(struct ctl_client* self,
|
||||
int argc, char* argv[])
|
||||
{
|
||||
struct jsonipc_request* request = NULL;
|
||||
|
|
|
@ -53,6 +53,8 @@ static int wayvncctl_usage(FILE* stream, int rc)
|
|||
"Options:\n"
|
||||
" -S,--socket=<path> Wayvnc control socket path.\n"
|
||||
" Default: $XDG_RUNTIME_DIR/wayvncctl\n"
|
||||
" -w,--wait Wait for wayvnc to start up if it's\n"
|
||||
" not already running.\n"
|
||||
" -j,--json Output json on stdout.\n"
|
||||
" -V,--version Show version info.\n"
|
||||
" -v,--verbose Be more verbose.\n"
|
||||
|
@ -74,15 +76,17 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
struct wayvncctl self = { 0 };
|
||||
|
||||
static const char* shortopts = "+S:hVvj";
|
||||
static const char* shortopts = "+S:hVvjw";
|
||||
|
||||
bool verbose = false;
|
||||
const char* socket_path = NULL;
|
||||
int wait_for_socket = 0;
|
||||
|
||||
unsigned flags = 0;
|
||||
|
||||
static const struct option longopts[] = {
|
||||
{ "socket", required_argument, NULL, 'S' },
|
||||
{ "wait", no_argument, NULL, 'w' },
|
||||
{ "json", no_argument, NULL, 'j' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
|
@ -99,6 +103,9 @@ int main(int argc, char* argv[])
|
|||
case 'S':
|
||||
socket_path = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
wait_for_socket = -1;
|
||||
break;
|
||||
case 'j':
|
||||
flags |= PRINT_JSON;
|
||||
break;
|
||||
|
@ -117,12 +124,18 @@ int main(int argc, char* argv[])
|
|||
argv = &argv[optind];
|
||||
|
||||
ctl_client_debug_log(verbose);
|
||||
|
||||
self.ctl = ctl_client_new(socket_path, &self);
|
||||
if (!self.ctl)
|
||||
goto ctl_client_failure;
|
||||
|
||||
int result = ctl_client_run_command(self.ctl, argc, argv, flags);
|
||||
int result = ctl_client_connect(self.ctl, wait_for_socket);
|
||||
if (result != 0)
|
||||
goto socket_failure;
|
||||
|
||||
result = ctl_client_run_command(self.ctl, argc, argv, flags);
|
||||
|
||||
socket_failure:
|
||||
ctl_client_destroy(self.ctl);
|
||||
|
||||
return result;
|
||||
|
|
|
@ -14,6 +14,10 @@ wayvncctl - A command line control client for wayvnc(1)
|
|||
Set wayvnc control socket path. Default: $XDG_RUNTIME_DIR/wayvncctl
|
||||
or /tmp/wayvncctl-$UID
|
||||
|
||||
*-w, --wait*
|
||||
Wait for wayvnc to start up if it's not already running. Default: Exit
|
||||
immediately with an error if wayvnc is not running.
|
||||
|
||||
*-j, --json*
|
||||
Produce json output to stdout.
|
||||
|
||||
|
|
Loading…
Reference in New Issue