commit c541c95146f7b072b56df2c0970953e0896ad1de
parent aa3afe5769604feb4ea5b39c4e7d9aabd354b5eb
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date: Wed, 14 Jul 2021 04:44:37 -0700
Allow any line length
This won't have much effect on memory usage since most of the
server's buffers were already dynamically allocated (excepting the
buffer's buffers, which were fixed), nor can I see anyone needing
a line longer than (PATH_MAX * 2), but now it doesn't have to be
thought about by the client.
Also the pplay functions logic was significantly simplified.
Diffstat:
10 files changed, 74 insertions(+), 60 deletions(-)
diff --git a/apc/apc.c b/apc/apc.c
@@ -19,6 +19,7 @@
#include <sys/socket.h>
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,6 +34,20 @@
#include "config.h"
int
+mksend(int sock, char **argv, int argc)
+{
+ char buf[ARG_MAX];
+ unsigned int len;
+
+ len = apc_genbuf(buf, sizeof(buf), argv, argc);
+ if (len == 0) {
+ errno = E2BIG;
+ return 0;
+ }
+ return send(sock, buf, len, 0) != len;
+}
+
+int
run(FILE *bfd, char **argv, int argc)
{
char *buf;
@@ -45,7 +60,7 @@ run(FILE *bfd, char **argv, int argc)
return 1;
}
- if (apc_send(fileno(bfd), argv, argc))
+ if (mksend(fileno(bfd), argv, argc))
return 1;
buf = NULL;
diff --git a/aps/aps.c b/aps/aps.c
@@ -65,6 +65,7 @@ aps_close(struct aps *aps)
aps_drop(aps, i);
apclose(aps->con);
pstop(&aps->player);
+ free(aps->player.path);
}
int
diff --git a/aps/command.c b/aps/command.c
@@ -221,11 +221,13 @@ int
aps_command(struct aps *aps, int s)
{
char *next;
- char bufbuf[AP_LINE_MAX];
+ char *status;
struct buf *buf;
char *argv[AP_ARGV_MAX];
int i;
int len;
+ char *(*command)(struct aps *, int, int, char **);
+
struct command {
char *name;
char *(*func)(struct aps *, int, int, char **);
@@ -247,23 +249,25 @@ aps_command(struct aps *aps, int s)
return 0;
buf = aps->clients[s].request;
- len = next - (char *)buf->data;
- memcpy(bufbuf, buf->data, len);
- memmove(buf->data, buf->data + len, buf->len - len);
- buf->len -= len;
- len = split(argv, LEN(argv), bufbuf, AP_ARG_SEPS);
+ len = split(argv, LEN(argv), buf->data, AP_ARG_SEPS);
if (len == 0)
return respfinish(aps, s, "No command");
if (len < 0)
return respfinish(aps, s, earg);
- for (i = 0; i < LEN(commands); ++i) {
- if (strcmp(*argv, commands[i].name) == 0) {
- return respfinish(aps, s,
- commands[i].func(aps, s, len - 1, argv + 1));
- }
- }
+ for (command = NULL, i = 0; command == NULL && i < LEN(commands); ++i)
+ if (strcmp(*argv, commands[i].name) == 0)
+ command = commands[i].func;
+
+ if (command == NULL)
+ status = "Command not found";
+ else
+ status = command(aps, s, len - 1, argv + 1);
+
+ len = next - (char *)buf->data;
+ memmove(buf->data, buf->data + len, buf->len - len);
+ buf->len -= len;
- return respfinish(aps, s, "Command not found");
+ return respfinish(aps, s, status);
}
diff --git a/aps/main.c b/aps/main.c
@@ -69,10 +69,6 @@ main(int argc, char *argv[])
signal(SIGINT, sigclose);
signal(SIGTERM, sigclose);
- for (i = 1; player[i]; ++i)
- if (!player[i][0])
- player[i] = aps->player.path;
-
if (aps_next(aps, -1, LEN(next), next))
die("aps_next");
diff --git a/aps/player.c b/aps/player.c
@@ -19,9 +19,9 @@
#include <sys/wait.h>
#include <errno.h>
-#include <limits.h>
#include <signal.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -30,6 +30,8 @@
int
pstart(struct player *p)
{
+ int i;
+
if (p->state & (RUNNING | SUSPENDED)) {
errno = EALREADY;
return 1;
@@ -43,6 +45,9 @@ pstart(struct player *p)
return 0;
}
+ for (i = 0; p->argv[i] != NULL; ++i)
+ if (p->argv[i][0] == '\0')
+ p->argv[i] = p->path;
execvp(p->prog, p->argv);
perror(p->prog);
_exit(1);
@@ -92,25 +97,29 @@ pcontinue(struct player *p)
int
pplay(struct player *p, char *path)
{
- if (path == NULL && !*p->path) {
+ if (path == NULL && p->path == NULL) {
errno = ENOENT;
return 1;
- } else if (path && strcmp(p->path, path) != 0) {
- if (p->state & (RUNNING | SUSPENDED) && pstop(p))
- return 1;
- if (strlcpy(p->path, path, sizeof(p->path)) >= sizeof(p->path)) {
- errno = ENAMETOOLONG;
- return 1;
- }
- } else {
+ }
+
+ if (path == NULL ||
+ (p->path != NULL && strcmp(p->path, path) == 0)) {
+ if (p->state == SUSPENDED)
+ return pcontinue(p);
if (p->state == RUNNING) {
errno = EALREADY;
return 1;
}
- if (p->state == SUSPENDED)
- return pcontinue(p);
}
+ if (p->state & (SUSPENDED | RUNNING) && pstop(p))
+ return 1;
+
+ free(p->path);
+ p->path = strdup(path);
+ if (p->path == NULL)
+ return 1;
+
return pstart(p);
}
diff --git a/aps/player.h b/aps/player.h
@@ -7,8 +7,8 @@ enum pstate {
struct player {
char **argv;
+ char *path;
char *prog;
- char path[PATH_MAX];
enum pstate state;
pid_t pid;
};
diff --git a/aps/response.c b/aps/response.c
@@ -54,36 +54,27 @@ respfree(struct aps *aps, int fd)
int
respadd(struct aps *aps, int fd, char *item)
{
- char buf[AP_LINE_MAX];
- int n;
-
- n = snprintf(buf, sizeof(buf), "%s\n", item);
- if (n >= sizeof(buf)) {
- errno = EMSGSIZE;
+ if (bufappend(RESP->buf, item, strlen(item)) ||
+ bufappend(RESP->buf, "\n", 1))
return 1;
- }
- return bufappend(aps->clients[fd].resp->buf, buf, n);
+ return 0;
}
int
respfinish(struct aps *aps, int fd, char *error)
{
- char buf[AP_LINE_MAX];
- int len;
-
- if (error) {
- len = snprintf(buf, sizeof(buf), "error: %s\n", error);
- if (len >= sizeof(buf)) {
- errno = EMSGSIZE;
+ if (error == NULL) {
+ /* NOTE: Perhaps it should return an error? */
+ if (respadd(aps, fd, "ok"))
+ respfinish(aps, fd, strerror(errno));
+ } else {
+ aps->clients[fd].resp->buf->len = 0;
+ if (bufappend(RESP->buf, "error: ", 7) ||
+ bufappend(RESP->buf, error, strlen(error)) ||
+ bufappend(RESP->buf, "\n", 1))
return 1;
- }
- } else {
- len = 3;
- memcpy(buf, "ok\n", len);
}
- if (bufappend(aps->clients[fd].resp->buf, buf, len))
- return 1;
aps->clients[fd].resp->lock = 1;
return 0;
}
diff --git a/include/ap/ap.h b/include/ap/ap.h
@@ -1,4 +1,3 @@
-#define AP_LINE_MAX (PATH_MAX * 2)
#define AP_ARGV_MAX 128
#define AP_ARG_SEPS "\t"
diff --git a/include/ap/client.h b/include/ap/client.h
@@ -1,2 +1,2 @@
-int apc_send(int, char **, unsigned int);
+size_t apc_genbuf(void *, size_t, char **, unsigned int);
char * apc_status(char *);
diff --git a/lib/ap/client.c b/lib/ap/client.c
@@ -63,20 +63,19 @@ apc_strjoin(char *buf, size_t size, char *fs, char **strings, unsigned int nstri
return apc_memcat(buf, size, len, "", 1);
}
-int
-apc_send(int s, char **argv, unsigned int argc)
+size_t
+apc_genbuf(void *buf, size_t size, char **argv, unsigned int argc)
{
- char buf[AP_LINE_MAX];
char sep[2];
size_t len;
strlcpy(sep, AP_ARG_SEPS, sizeof(sep));
- len = apc_strjoin(buf, sizeof(buf), sep, argv, argc);
+ len = apc_strjoin(buf, size, sep, argv, argc);
if (len == 0)
return 1;
- buf[len - 1] = '\n';
- return send(s, buf, len, 0) != len;
+ ((char *)buf)[len - 1] = '\n';
+ return len;
}
char *