Mercurial > sci
diff req.c @ 0:f1de39079243
misc: initial import
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 07 Jun 2021 09:41:37 +0200 |
parents | |
children | 5afdb14df924 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/req.c Mon Jun 07 09:41:37 2021 +0200 @@ -0,0 +1,180 @@ +#define _BSD_SOURCE +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/un.h> +#include <assert.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "req.h" +#include "project.h" +#include "worker.h" + +static int sock; + +static struct req +ask(const char *fmt, ...) +{ + assert(fmt); + + struct req res = {0}; + char buf[1024], *p; + va_list ap; + ssize_t bufsz = 0, nr; + + va_start(ap, fmt); + vsnprintf(buf, sizeof (buf), fmt, ap); + va_end(ap); + + if (strlcat(buf, "\r\n\r\n", sizeof (buf)) >= sizeof (buf)) { + res.status = EMSGSIZE; + return res; + } + + if (send(sock, buf, strlen(buf), MSG_NOSIGNAL) < 0) { + res.status = errno; + return res; + } + + while ((nr = recv(sock, buf + bufsz, sizeof (buf) - bufsz, 0)) > 0) { + bufsz += nr; + + if ((size_t)bufsz >= sizeof (buf)) { + bufsz = 0; + res.status = EMSGSIZE; + break; + } + } + + buf[bufsz] = '\0'; + + /* Remove final '\r\n\r\n' */ + if ((p = strstr(buf, "\r\n\r\n"))) + *p = '\0'; + + /* Check and remove status. */ + if (strncmp(buf, "ERR", 3) == 0) + res.status = -1; + if ((p = strchr(buf, '\n'))) + ++p; + else + p = buf; + + strlcat(res.msg, p, sizeof (res.msg)); + + return res; +} + +int +req_connect(const char *path) +{ + assert(path); + + struct sockaddr_un sun; + struct timeval tv = { .tv_sec = 3 }; + + if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) + return -1; + + sun.sun_family = PF_LOCAL; + strlcpy(sun.sun_path, path, sizeof (sun.sun_path)); + + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv)) < 0 || + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof (tv)) < 0) + return -1; + if (connect(sock, (const struct sockaddr *)&sun, sizeof (sun)) < 0) + return -1; + + return 0; +} + +struct req +req_job_queue(const char *project, const char *tag) +{ + assert(project); + assert(tag); + + return ask("job-queue %s|%s", project, tag); +} + +struct req +req_project_add(const struct project *p) +{ + assert(p); + + return ask("project-add %s|%s|%s|%s", p->name, p->desc, p->url, p->script); +} + +struct req +req_project_list(struct project *pc, size_t *pcsz) +{ + assert(pc); + assert(pcsz); + + struct req req; + char fmt[128], *token, *p = req.msg; + size_t tot = 0; + + if ((req = ask("project-list")).status) + return req; + + snprintf(fmt, sizeof (fmt), "%%%zu[^|]|%%%zu[^|]|%%%zu[^|]|%%%zu[^\n]\n", + sizeof (pc->name), sizeof (pc->desc), sizeof (pc->url), sizeof (pc->script)); + + while ((token = strtok_r(p, "\n", &p)) && tot < *pcsz) { + if (sscanf(token, fmt, pc->name, pc->desc, pc->url, pc->script) == 4) { + ++pc; + ++tot; + } + } + + *pcsz = tot; + + return req; +} + +struct req +req_worker_add(const struct worker *w) +{ + assert(w); + + return ask("worker-add %s|%s", w->name, w->desc); +} + +struct req +req_worker_list(struct worker *wk, size_t *wksz) +{ + assert(wk); + assert(wksz); + + struct req req; + char fmt[128], *token, *p = req.msg; + size_t tot = 0; + + if ((req = ask("worker-list")).status) + return req; + + snprintf(fmt, sizeof (fmt), "%%%zu[^|]|%%%zu[^\n]\n", + sizeof (wk->name), sizeof (wk->desc)); + + while ((token = strtok_r(p, "\n", &p)) && tot < *wksz) { + if (sscanf(token, fmt, wk->name, wk->desc) == 2) { + wk++; + tot++; + } + } + + *wksz = tot; + + return req; +} + +void +req_finish(void) +{ + close(sock); + sock = 0; +}