commit d0f26ec93b305edd594fee40e43ccb23b7f8d406
parent a3e8dd750e830d79b09f52874c47c4a9f93cdf6a
Author: cowmonk <cowmonk@based.pt>
Date: Tue, 6 Oct 2026 12:30:13 -0700
added conditional _POSIX_C_SOURCE definition and changed handling of services
Specifically, `request()` handles one command and one socket connection.
`main()` now sends a separate request for each given service name (e.g.
`svc -s foo bar` queries both services instead of looking for one
service named `foo bar`).
Diffstat:
| M | svc.c | | | 100 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
1 file changed, 62 insertions(+), 38 deletions(-)
diff --git a/svc.c b/svc.c
@@ -1,10 +1,15 @@
/* svc: control client for ssv */
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
#include "arg.h"
#include "util.h"
#include <sys/socket.h>
#include <sys/un.h>
+#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -19,16 +24,59 @@ usage(void)
eprintf("usage: %s [-udrkts] [-a] [service...]\n", argv0);
}
-int
-main(int argc, char *argv[])
+static int
+request(int action, const char *name)
{
- int sock, aflag, action, i, n;
+ int sock, len;
struct sockaddr_un addr;
- char buf[4096], resp[4096];
- size_t off;
+ char buf[4096], resp[4096], prefix[5];
+ ssize_t n;
+ size_t have = 0, chunk;
+
+ if (strchr(name, '\n') || strchr(name, '\r'))
+ eprintf("invalid service name\n");
+ len = snprintf(buf, sizeof(buf), "%c %s\n", action, name);
+ if (len < 0 || (size_t)len >= sizeof(buf))
+ eprintf("command too long\n");
+
+ /* connect to ssv control socket */
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ eprintf("socket:");
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (strlcpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
+ eprintf("socket path too long: %s\n", SOCK_PATH);
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ eprintf("connect %s:", SOCK_PATH);
- aflag = 0;
- action = 0;
+ /* send command, print response */
+ if (writeall(sock, buf, len) != len)
+ eprintf("write socket:");
+ if (shutdown(sock, SHUT_WR) < 0)
+ eprintf("shutdown socket:");
+ for (;;) {
+ n = read(sock, resp, sizeof(resp));
+ if (n < 0 && errno == EINTR)
+ continue;
+ if (n < 0)
+ eprintf("read socket:");
+ if (n == 0)
+ break;
+ chunk = MIN((size_t)n, sizeof(prefix) - have);
+ memcpy(prefix + have, resp, chunk);
+ have += chunk;
+ if (writeall(STDOUT_FILENO, resp, n) != n)
+ eprintf("write stdout:");
+ }
+ close(sock);
+ return have == sizeof(prefix) && memcmp(prefix, "ERR: ", sizeof(prefix)) == 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int aflag = 0, action = 0, ret = 0, i;
ARGBEGIN {
case 'u': action = 'u'; break;
@@ -41,42 +89,18 @@ main(int argc, char *argv[])
default: usage();
} ARGEND
- if (!action)
+ if (!action || (action != 's' && !aflag && argc == 0))
usage();
- if (action != 's' && !aflag && argc == 0)
+ if (aflag && (argc != 0 || (action != 'u' && action != 'd')))
usage();
- /* connect to ssv control socket */
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0)
- eprintf("socket:");
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- strlcpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path));
- if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
- eprintf("connect %s:", SOCK_PATH);
-
- /* build command line */
- if (action == 's' && argc == 0) {
- strlcpy(buf, "s\n", sizeof(buf));
- } else if (aflag) {
- snprintf(buf, sizeof(buf), "%c a\n", action);
- } else {
- off = snprintf(buf, sizeof(buf), "%c", action);
+ if (aflag || argc == 0)
+ ret = request(action, aflag ? "a" : "");
+ else
for (i = 0; i < argc; i++)
- off += snprintf(buf + off, sizeof(buf) - off,
- " %s", argv[i]);
- off += snprintf(buf + off, sizeof(buf) - off, "\n");
- }
-
- /* send command, print response */
- writeall(sock, buf, strlen(buf));
- shutdown(sock, SHUT_WR);
- while ((n = read(sock, resp, sizeof(resp))) > 0)
- writeall(STDOUT_FILENO, resp, n);
- close(sock);
+ ret |= request(action, argv[i]);
if (fshut(stdout, "<stdout>"))
return 2;
- return 0;
+ return ret;
}