sway/sway/swaynag.c
M Stoeckl 1211a81aad Replace wlr_log with sway_log
This commit mostly duplicates the wlr_log functions, although
with a sway_* prefix. (This is very similar to PR #2009.)
However, the logging function no longer needs to be replaceable,
so sway_log_init's second argument is used to set the exit
callback for sway_abort.

wlr_log_init is still invoked in sway/main.c

This commit makes it easier to remove the wlroots dependency for
the helper programs swaymsg, swaybg, swaybar, and swaynag.
2019-01-21 12:59:42 +01:00

104 lines
2.1 KiB
C

#define _POSIX_C_SOURCE 200809L
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include "log.h"
#include "sway/swaynag.h"
bool swaynag_spawn(const char *swaynag_command,
struct swaynag_instance *swaynag) {
if (!swaynag_command) {
return true;
}
if (swaynag->detailed) {
if (pipe(swaynag->fd) != 0) {
sway_log(SWAY_ERROR, "Failed to create pipe for swaynag");
return false;
}
fcntl(swaynag->fd[1], F_SETFD, FD_CLOEXEC);
}
pid_t pid;
if ((pid = fork()) == 0) {
if (swaynag->detailed) {
close(swaynag->fd[1]);
dup2(swaynag->fd[0], STDIN_FILENO);
close(swaynag->fd[0]);
}
size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2;
char *cmd = malloc(length);
snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args);
execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
_exit(0);
} else if (pid < 0) {
sway_log(SWAY_ERROR, "Failed to create fork for swaynag");
if (swaynag->detailed) {
close(swaynag->fd[0]);
close(swaynag->fd[1]);
}
return false;
}
if (swaynag->detailed) {
close(swaynag->fd[0]);
}
swaynag->pid = pid;
return true;
}
void swaynag_kill(struct swaynag_instance *swaynag) {
if (swaynag->pid > 0) {
kill(swaynag->pid, SIGTERM);
swaynag->pid = -1;
}
}
void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
const char *fmt, ...) {
if (!swaynag_command) {
return;
}
if (!swaynag->detailed) {
sway_log(SWAY_ERROR, "Attempting to write to non-detailed swaynag inst");
return;
}
if (swaynag->pid <= 0 && !swaynag_spawn(swaynag_command, swaynag)) {
return;
}
va_list args;
va_start(args, fmt);
size_t length = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args);
char *temp = malloc(length + 1);
if (!temp) {
sway_log(SWAY_ERROR, "Failed to allocate buffer for swaynag log entry.");
return;
}
va_start(args, fmt);
vsnprintf(temp, length, fmt, args);
va_end(args);
write(swaynag->fd[1], temp, length);
free(temp);
}
void swaynag_show(struct swaynag_instance *swaynag) {
if (swaynag->detailed && swaynag->pid > 0) {
close(swaynag->fd[1]);
}
}