aboutsummaryrefslogtreecommitdiffstats
path: root/sway/swaynag.c
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-04-14 00:27:47 -0400
committerLibravatar Simon Ser <contact@emersion.fr>2019-04-14 12:41:59 +0300
commit6961bf2e4ce2c116e41a8db158691f6c993707ce (patch)
treea381146599a5f19e565006cafeb23edc04247d2b /sway/swaynag.c
parentswaynag: fix pointer management (diff)
downloadsway-6961bf2e4ce2c116e41a8db158691f6c993707ce.tar.gz
sway-6961bf2e4ce2c116e41a8db158691f6c993707ce.tar.zst
sway-6961bf2e4ce2c116e41a8db158691f6c993707ce.zip
Spawn swaynag as a wayland client
This spawns swaynag as a wayland client similar to how swaybar and swaybg are already done
Diffstat (limited to 'sway/swaynag.c')
-rw-r--r--sway/swaynag.c124
1 files changed, 95 insertions, 29 deletions
diff --git a/sway/swaynag.c b/sway/swaynag.c
index 49027f5d..0fca6c71 100644
--- a/sway/swaynag.c
+++ b/sway/swaynag.c
@@ -1,16 +1,32 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <fcntl.h>
3#include <signal.h> 2#include <signal.h>
4#include <stdbool.h> 3#include <stdbool.h>
5#include <stdlib.h> 4#include <stdlib.h>
6#include <stdio.h> 5#include <stdio.h>
6#include <sys/socket.h>
7#include <sys/types.h> 7#include <sys/types.h>
8#include <sys/wait.h>
8#include <unistd.h> 9#include <unistd.h>
9#include "log.h" 10#include "log.h"
11#include "sway/server.h"
10#include "sway/swaynag.h" 12#include "sway/swaynag.h"
13#include "util.h"
14
15static void handle_swaynag_client_destroy(struct wl_listener *listener,
16 void *data) {
17 struct swaynag_instance *swaynag =
18 wl_container_of(listener, swaynag, client_destroy);
19 wl_list_remove(&swaynag->client_destroy.link);
20 wl_list_init(&swaynag->client_destroy.link);
21 swaynag->client = NULL;
22}
11 23
12bool swaynag_spawn(const char *swaynag_command, 24bool swaynag_spawn(const char *swaynag_command,
13 struct swaynag_instance *swaynag) { 25 struct swaynag_instance *swaynag) {
26 if (swaynag->client != NULL) {
27 wl_client_destroy(swaynag->client);
28 }
29
14 if (!swaynag_command) { 30 if (!swaynag_command) {
15 return true; 31 return true;
16 } 32 }
@@ -20,44 +36,94 @@ bool swaynag_spawn(const char *swaynag_command,
20 sway_log(SWAY_ERROR, "Failed to create pipe for swaynag"); 36 sway_log(SWAY_ERROR, "Failed to create pipe for swaynag");
21 return false; 37 return false;
22 } 38 }
23 fcntl(swaynag->fd[1], F_SETFD, FD_CLOEXEC); 39 if (!set_cloexec(swaynag->fd[1], true)) {
40 goto failed;
41 }
24 } 42 }
25 43
26 pid_t pid; 44 int sockets[2];
27 if ((pid = fork()) == 0) { 45 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) {
28 if (swaynag->detailed) { 46 sway_log_errno(SWAY_ERROR, "socketpair failed");
29 close(swaynag->fd[1]); 47 goto failed;
30 dup2(swaynag->fd[0], STDIN_FILENO); 48 }
31 close(swaynag->fd[0]); 49 if (!set_cloexec(sockets[0], true) || !set_cloexec(sockets[1], true)) {
32 } 50 goto failed;
51 }
33 52
34 size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2; 53 swaynag->client = wl_client_create(server.wl_display, sockets[0]);
35 char *cmd = malloc(length); 54 if (swaynag->client == NULL) {
36 snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args); 55 sway_log_errno(SWAY_ERROR, "wl_client_create failed");
37 execl("/bin/sh", "/bin/sh", "-c", cmd, NULL); 56 goto failed;
38 _exit(0); 57 }
39 } else if (pid < 0) { 58
59 swaynag->client_destroy.notify = handle_swaynag_client_destroy;
60 wl_client_add_destroy_listener(swaynag->client, &swaynag->client_destroy);
61
62 pid_t pid = fork();
63 if (pid < 0) {
40 sway_log(SWAY_ERROR, "Failed to create fork for swaynag"); 64 sway_log(SWAY_ERROR, "Failed to create fork for swaynag");
41 if (swaynag->detailed) { 65 goto failed;
42 close(swaynag->fd[0]); 66 } else if (pid == 0) {
43 close(swaynag->fd[1]); 67 pid = fork();
68 if (pid < 0) {
69 sway_log_errno(SWAY_ERROR, "fork failed");
70 _exit(EXIT_FAILURE);
71 } else if (pid == 0) {
72 if (!set_cloexec(sockets[1], false)) {
73 _exit(EXIT_FAILURE);
74 }
75
76 if (swaynag->detailed) {
77 close(swaynag->fd[1]);
78 dup2(swaynag->fd[0], STDIN_FILENO);
79 close(swaynag->fd[0]);
80 }
81
82 char wayland_socket_str[16];
83 snprintf(wayland_socket_str, sizeof(wayland_socket_str),
84 "%d", sockets[1]);
85 setenv("WAYLAND_SOCKET", wayland_socket_str, true);
86
87 size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2;
88 char *cmd = malloc(length);
89 snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args);
90 execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
91 sway_log_errno(SWAY_ERROR, "execl failed");
92 _exit(EXIT_FAILURE);
44 } 93 }
45 return false; 94 _exit(EXIT_SUCCESS);
46 } 95 }
47 96
48 if (swaynag->detailed) { 97 if (swaynag->detailed) {
49 close(swaynag->fd[0]); 98 if (close(swaynag->fd[0]) != 0) {
99 sway_log_errno(SWAY_ERROR, "close failed");
100 return false;
101 }
50 } 102 }
51 swaynag->pid = pid;
52 return true;
53}
54 103
104 if (close(sockets[1]) != 0) {
105 sway_log_errno(SWAY_ERROR, "close failed");
106 return false;
107 }
108
109 if (waitpid(pid, NULL, 0) < 0) {
110 sway_log_errno(SWAY_ERROR, "waitpid failed");
111 return false;
112 }
55 113
56void swaynag_kill(struct swaynag_instance *swaynag) { 114 return true;
57 if (swaynag->pid > 0) { 115
58 kill(swaynag->pid, SIGTERM); 116failed:
59 swaynag->pid = -1; 117 if (swaynag->detailed) {
118 if (close(swaynag->fd[0]) != 0) {
119 sway_log_errno(SWAY_ERROR, "close failed");
120 return false;
121 }
122 if (close(swaynag->fd[1]) != 0) {
123 sway_log_errno(SWAY_ERROR, "close failed");
124 }
60 } 125 }
126 return false;
61} 127}
62 128
63void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag, 129void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
@@ -71,7 +137,7 @@ void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
71 return; 137 return;
72 } 138 }
73 139
74 if (swaynag->pid <= 0 && !swaynag_spawn(swaynag_command, swaynag)) { 140 if (swaynag->client == NULL && !swaynag_spawn(swaynag_command, swaynag)) {
75 return; 141 return;
76 } 142 }
77 143
@@ -96,7 +162,7 @@ void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
96} 162}
97 163
98void swaynag_show(struct swaynag_instance *swaynag) { 164void swaynag_show(struct swaynag_instance *swaynag) {
99 if (swaynag->detailed && swaynag->pid > 0) { 165 if (swaynag->detailed && swaynag->client != NULL) {
100 close(swaynag->fd[1]); 166 close(swaynag->fd[1]);
101 } 167 }
102} 168}