mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-07 03:01:47 -04:00
156 lines
No EOL
4.9 KiB
C
156 lines
No EOL
4.9 KiB
C
#define _GNU_SOURCE
|
||
#include <stdbool.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <sys/socket.h>
|
||
#include <sys/un.h>
|
||
#include <unistd.h>
|
||
|
||
static void usage(void) {
|
||
printf("Usage: mmsg <command> [args...]\n\n");
|
||
printf("One-shot queries (get):\n");
|
||
printf(
|
||
" get version Show compositor version\n");
|
||
printf(" get keymode Show current keymode\n");
|
||
printf(" get keyboardlayout Show current keyboard "
|
||
"layout\n");
|
||
printf(" get last_open_surface [monitor] Show last open surface "
|
||
"(default focused monitor)\n");
|
||
printf(" get monitor <name> Show monitor details\n");
|
||
printf(" get focusing-client Show focused client "
|
||
"details\n");
|
||
printf(" get client <id> Show client details by "
|
||
"ID\n");
|
||
printf(" get tag <monitor> <index> Show tag details "
|
||
"(1‑based index)\n");
|
||
printf(" get all-clients List all clients\n");
|
||
printf(" get all-monitors List all monitors\n");
|
||
printf(" get all-tags List all tags (all "
|
||
"monitors)\n");
|
||
printf(
|
||
" get tags <monitor> List tags for a monitor\n");
|
||
printf(" dispatch <func>[,arg...] [client,<id>] Call a compositor "
|
||
"function\n");
|
||
printf(" <func> and arguments are separated by commas.\n");
|
||
printf(" Add 'client,<id>' at the beginning or end to target a "
|
||
"specific client.\n");
|
||
printf(" Examples:\n");
|
||
printf(" dispatch togglefloating\n");
|
||
printf(" dispatch movewin,10,100\n");
|
||
printf(" dispatch movewin,10,100 client,4\n");
|
||
printf("Persistent streams (watch):\n");
|
||
printf(
|
||
" watch monitor <name> Stream monitor changes\n");
|
||
printf(" watch focusing-client Stream focused client "
|
||
"changes\n");
|
||
printf(
|
||
" watch client <id> Stream client changes\n");
|
||
printf(" watch tags <monitor> Stream tag changes for "
|
||
"a monitor\n");
|
||
printf(" watch all-monitors Stream all monitors "
|
||
"changes\n");
|
||
printf(
|
||
" watch all-tags Stream all tags changes\n");
|
||
printf(" watch all-clients Stream all clients "
|
||
"changes\n");
|
||
printf(
|
||
" watch keymode Stream keymode changes\n");
|
||
printf(" watch keyboardlayout Stream keyboard layout "
|
||
"changes\n");
|
||
printf(" watch last_open_surface [monitor] Stream last open "
|
||
"surface changes\n\n");
|
||
printf("Environment:\n");
|
||
printf(" MANGO_INSTANCE_SIGNATURE IPC socket path (set by the "
|
||
"compositor)\n\n");
|
||
printf("Run 'mmsg --help', '-h' or 'help' to see this message.\n");
|
||
}
|
||
|
||
int main(int argc, char *argv[]) {
|
||
if (argc >= 2 &&
|
||
(strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ||
|
||
strcmp(argv[1], "help") == 0)) {
|
||
usage();
|
||
return EXIT_SUCCESS;
|
||
}
|
||
|
||
if (argc < 2) {
|
||
fprintf(stderr, "Usage: mmsg <command> [args...]\n");
|
||
fprintf(stderr, " get <type> ... one-shot request\n");
|
||
fprintf(stderr, " watch <type> ... persistent stream\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
const char *socket_path = getenv("MANGO_INSTANCE_SIGNATURE");
|
||
if (!socket_path) {
|
||
fprintf(stderr, "Error: MANGO_INSTANCE_SIGNATURE is not set. Did you "
|
||
"run 'mmsg' in mango?\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||
if (sock < 0) {
|
||
perror("socket");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
||
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
||
|
||
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||
perror("connect");
|
||
close(sock);
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
char cmd[4096] = {0};
|
||
int offset = 0;
|
||
for (int i = 1; i < argc; i++) {
|
||
int n = snprintf(cmd + offset, sizeof(cmd) - offset, "%s%s", argv[i],
|
||
(i == argc - 1) ? "" : " ");
|
||
if (n < 0 || n >= (int)(sizeof(cmd) - offset)) {
|
||
fprintf(stderr, "Error: command too long.\n");
|
||
close(sock);
|
||
return EXIT_FAILURE;
|
||
}
|
||
offset += n;
|
||
}
|
||
|
||
int n = snprintf(cmd + offset, sizeof(cmd) - offset, "\n");
|
||
if (n < 0 || n >= (int)(sizeof(cmd) - offset)) {
|
||
fprintf(stderr, "Error: command too long to append newline.\n");
|
||
close(sock);
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
if (send(sock, cmd, strlen(cmd), MSG_NOSIGNAL) < 0) {
|
||
perror("send");
|
||
close(sock);
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
FILE *stream = fdopen(sock, "r");
|
||
if (!stream) {
|
||
perror("fdopen");
|
||
close(sock);
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
char *line = NULL;
|
||
size_t len = 0;
|
||
while (getline(&line, &len, stream) != -1) {
|
||
printf("%s", line);
|
||
fflush(stdout);
|
||
}
|
||
|
||
if (ferror(stream)) {
|
||
perror("recv");
|
||
free(line);
|
||
fclose(stream);
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
free(line);
|
||
fclose(stream);
|
||
return EXIT_SUCCESS;
|
||
} |