0
|
1 #define _BSD_SOURCE |
|
2 #include <sys/socket.h> |
|
3 #include <sys/time.h> |
|
4 #include <sys/un.h> |
|
5 #include <assert.h> |
|
6 #include <errno.h> |
|
7 #include <stdarg.h> |
|
8 #include <stdio.h> |
|
9 #include <string.h> |
|
10 #include <unistd.h> |
|
11 |
|
12 #include "req.h" |
|
13 #include "project.h" |
|
14 #include "worker.h" |
|
15 |
|
16 static int sock; |
|
17 |
|
18 static struct req |
|
19 ask(const char *fmt, ...) |
|
20 { |
|
21 assert(fmt); |
|
22 |
|
23 struct req res = {0}; |
|
24 char buf[1024], *p; |
|
25 va_list ap; |
|
26 ssize_t bufsz = 0, nr; |
|
27 |
|
28 va_start(ap, fmt); |
|
29 vsnprintf(buf, sizeof (buf), fmt, ap); |
|
30 va_end(ap); |
|
31 |
|
32 if (strlcat(buf, "\r\n\r\n", sizeof (buf)) >= sizeof (buf)) { |
|
33 res.status = EMSGSIZE; |
|
34 return res; |
|
35 } |
|
36 |
|
37 if (send(sock, buf, strlen(buf), MSG_NOSIGNAL) < 0) { |
|
38 res.status = errno; |
|
39 return res; |
|
40 } |
|
41 |
|
42 while ((nr = recv(sock, buf + bufsz, sizeof (buf) - bufsz, 0)) > 0) { |
|
43 bufsz += nr; |
|
44 |
|
45 if ((size_t)bufsz >= sizeof (buf)) { |
|
46 bufsz = 0; |
|
47 res.status = EMSGSIZE; |
|
48 break; |
|
49 } |
|
50 } |
|
51 |
|
52 buf[bufsz] = '\0'; |
|
53 |
|
54 /* Remove final '\r\n\r\n' */ |
|
55 if ((p = strstr(buf, "\r\n\r\n"))) |
|
56 *p = '\0'; |
|
57 |
|
58 /* Check and remove status. */ |
|
59 if (strncmp(buf, "ERR", 3) == 0) |
|
60 res.status = -1; |
|
61 if ((p = strchr(buf, '\n'))) |
|
62 ++p; |
|
63 else |
|
64 p = buf; |
|
65 |
|
66 strlcat(res.msg, p, sizeof (res.msg)); |
|
67 |
|
68 return res; |
|
69 } |
|
70 |
|
71 int |
|
72 req_connect(const char *path) |
|
73 { |
|
74 assert(path); |
|
75 |
|
76 struct sockaddr_un sun; |
|
77 struct timeval tv = { .tv_sec = 3 }; |
|
78 |
|
79 if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) |
|
80 return -1; |
|
81 |
|
82 sun.sun_family = PF_LOCAL; |
|
83 strlcpy(sun.sun_path, path, sizeof (sun.sun_path)); |
|
84 |
|
85 if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv)) < 0 || |
|
86 setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof (tv)) < 0) |
|
87 return -1; |
|
88 if (connect(sock, (const struct sockaddr *)&sun, sizeof (sun)) < 0) |
|
89 return -1; |
|
90 |
|
91 return 0; |
|
92 } |
|
93 |
|
94 struct req |
|
95 req_job_queue(const char *project, const char *tag) |
|
96 { |
|
97 assert(project); |
|
98 assert(tag); |
|
99 |
|
100 return ask("job-queue %s|%s", project, tag); |
|
101 } |
|
102 |
|
103 struct req |
|
104 req_project_add(const struct project *p) |
|
105 { |
|
106 assert(p); |
|
107 |
|
108 return ask("project-add %s|%s|%s|%s", p->name, p->desc, p->url, p->script); |
|
109 } |
|
110 |
|
111 struct req |
|
112 req_project_list(struct project *pc, size_t *pcsz) |
|
113 { |
|
114 assert(pc); |
|
115 assert(pcsz); |
|
116 |
|
117 struct req req; |
|
118 char fmt[128], *token, *p = req.msg; |
|
119 size_t tot = 0; |
|
120 |
|
121 if ((req = ask("project-list")).status) |
|
122 return req; |
|
123 |
|
124 snprintf(fmt, sizeof (fmt), "%%%zu[^|]|%%%zu[^|]|%%%zu[^|]|%%%zu[^\n]\n", |
|
125 sizeof (pc->name), sizeof (pc->desc), sizeof (pc->url), sizeof (pc->script)); |
|
126 |
|
127 while ((token = strtok_r(p, "\n", &p)) && tot < *pcsz) { |
|
128 if (sscanf(token, fmt, pc->name, pc->desc, pc->url, pc->script) == 4) { |
|
129 ++pc; |
|
130 ++tot; |
|
131 } |
|
132 } |
|
133 |
|
134 *pcsz = tot; |
|
135 |
|
136 return req; |
|
137 } |
|
138 |
|
139 struct req |
|
140 req_worker_add(const struct worker *w) |
|
141 { |
|
142 assert(w); |
|
143 |
|
144 return ask("worker-add %s|%s", w->name, w->desc); |
|
145 } |
|
146 |
|
147 struct req |
|
148 req_worker_list(struct worker *wk, size_t *wksz) |
|
149 { |
|
150 assert(wk); |
|
151 assert(wksz); |
|
152 |
|
153 struct req req; |
|
154 char fmt[128], *token, *p = req.msg; |
|
155 size_t tot = 0; |
|
156 |
|
157 if ((req = ask("worker-list")).status) |
|
158 return req; |
|
159 |
|
160 snprintf(fmt, sizeof (fmt), "%%%zu[^|]|%%%zu[^\n]\n", |
|
161 sizeof (wk->name), sizeof (wk->desc)); |
|
162 |
|
163 while ((token = strtok_r(p, "\n", &p)) && tot < *wksz) { |
|
164 if (sscanf(token, fmt, wk->name, wk->desc) == 2) { |
|
165 wk++; |
|
166 tot++; |
|
167 } |
|
168 } |
|
169 |
|
170 *wksz = tot; |
|
171 |
|
172 return req; |
|
173 } |
|
174 |
|
175 void |
|
176 req_finish(void) |
|
177 { |
|
178 close(sock); |
|
179 sock = 0; |
|
180 } |