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