Mercurial > sci
view 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 source
#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; }