parent
f9a6407111
commit
a7f7d4a488
@ -0,0 +1,33 @@
|
||||
#ifndef _SWAY_SWAYNAG_H
|
||||
#define _SWAY_SWAYNAG_H
|
||||
|
||||
struct swaynag_instance {
|
||||
const char *args;
|
||||
pid_t pid;
|
||||
int fd[2];
|
||||
bool detailed;
|
||||
};
|
||||
|
||||
// Copy all fields of one instance to another
|
||||
void swaynag_clone(struct swaynag_instance *dest,
|
||||
struct swaynag_instance *src);
|
||||
|
||||
// Spawn swaynag. If swaynag->detailed, then swaynag->fd[1] will left open
|
||||
// so it can be written to. Call swaynag_show when done writing. This will
|
||||
// be automatically called by swaynag_log if the instance is not spawned and
|
||||
// swaynag->detailed is true.
|
||||
bool swaynag_spawn(const char *swaynag_command,
|
||||
struct swaynag_instance *swaynag);
|
||||
|
||||
// Kill the swaynag instance
|
||||
void swaynag_kill(struct swaynag_instance *swaynag);
|
||||
|
||||
// Write a log message to swaynag->fd[1]. This will fail when swaynag->detailed
|
||||
// is false.
|
||||
void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
|
||||
const char *fmt, ...);
|
||||
|
||||
// If swaynag->detailed, close swaynag->fd[1] so swaynag displays
|
||||
void swaynag_show(struct swaynag_instance *swaynag);
|
||||
|
||||
#endif
|
@ -0,0 +1,20 @@
|
||||
#include <string.h>
|
||||
#include "sway/commands.h"
|
||||
#include "log.h"
|
||||
#include "stringop.h"
|
||||
|
||||
struct cmd_results *cmd_swaynag_command(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "swaynag_command", EXPECTED_AT_LEAST, 1))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (config->swaynag_command) {
|
||||
free(config->swaynag_command);
|
||||
}
|
||||
config->swaynag_command = join_args(argv, argc);
|
||||
wlr_log(WLR_DEBUG, "Using custom swaynag command: %s",
|
||||
config->swaynag_command);
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
#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"
|
||||
|
||||
void swaynag_clone(struct swaynag_instance *dest,
|
||||
struct swaynag_instance *src) {
|
||||
dest->args = src->args;
|
||||
dest->pid = src->pid;
|
||||
dest->fd[0] = src->fd[0];
|
||||
dest->fd[1] = src->fd[1];
|
||||
dest->detailed = src->detailed;
|
||||
}
|
||||
|
||||
bool swaynag_spawn(const char *swaynag_command,
|
||||
struct swaynag_instance *swaynag) {
|
||||
if (swaynag->detailed) {
|
||||
if (pipe(swaynag->fd) != 0) {
|
||||
wlr_log(WLR_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) {
|
||||
wlr_log(WLR_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->detailed) {
|
||||
wlr_log(WLR_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) {
|
||||
wlr_log(WLR_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]);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in new issue