1 /* Copyright (c) 2006-2010 Jonas Fonseca <fonseca@diku.dk>
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
14 #include "tig.h"
15 #include "io.h"
17 bool
18 argv_from_string(const char *argv[SIZEOF_ARG], int *argc, char *cmd)
19 {
20 int valuelen;
22 while (*cmd && *argc < SIZEOF_ARG && (valuelen = strcspn(cmd, " \t"))) {
23 bool advance = cmd[valuelen] != 0;
25 cmd[valuelen] = 0;
26 argv[(*argc)++] = chomp_string(cmd);
27 cmd = chomp_string(cmd + valuelen + advance);
28 }
30 if (*argc < SIZEOF_ARG)
31 argv[*argc] = NULL;
32 return *argc < SIZEOF_ARG;
33 }
35 bool
36 argv_from_env(const char **argv, const char *name)
37 {
38 char *env = argv ? getenv(name) : NULL;
39 int argc = 0;
41 if (env && *env)
42 env = strdup(env);
43 return !env || argv_from_string(argv, &argc, env);
44 }
46 void
47 argv_free(const char *argv[])
48 {
49 int argc;
51 if (!argv)
52 return;
53 for (argc = 0; argv[argc]; argc++)
54 free((void *) argv[argc]);
55 argv[0] = NULL;
56 }
58 size_t
59 argv_size(const char **argv)
60 {
61 int argc = 0;
63 while (argv && argv[argc])
64 argc++;
66 return argc;
67 }
69 DEFINE_ALLOCATOR(argv_realloc, const char *, SIZEOF_ARG)
71 bool
72 argv_append(const char ***argv, const char *arg)
73 {
74 size_t argc = argv_size(*argv);
76 if (!argv_realloc(argv, argc, 2))
77 return FALSE;
79 (*argv)[argc++] = strdup(arg);
80 (*argv)[argc] = NULL;
81 return TRUE;
82 }
84 bool
85 argv_append_array(const char ***dst_argv, const char *src_argv[])
86 {
87 int i;
89 for (i = 0; src_argv && src_argv[i]; i++)
90 if (!argv_append(dst_argv, src_argv[i]))
91 return FALSE;
92 return TRUE;
93 }
95 bool
96 argv_copy(const char ***dst, const char *src[])
97 {
98 int argc;
100 argv_free(*dst);
101 for (argc = 0; src[argc]; argc++)
102 if (!argv_append(dst, src[argc]))
103 return FALSE;
104 return TRUE;
105 }
108 /*
109 * Executing external commands.
110 */
112 static void
113 io_init(struct io *io)
114 {
115 memset(io, 0, sizeof(*io));
116 io->pipe = -1;
117 }
119 bool
120 io_open(struct io *io, const char *fmt, ...)
121 {
122 char name[SIZEOF_STR] = "";
123 bool fits;
124 va_list args;
126 io_init(io);
128 va_start(args, fmt);
129 fits = vsnprintf(name, sizeof(name), fmt, args) < sizeof(name);
130 va_end(args);
132 if (!fits) {
133 io->error = ENAMETOOLONG;
134 return FALSE;
135 }
136 io->pipe = *name ? open(name, O_RDONLY) : STDIN_FILENO;
137 if (io->pipe == -1)
138 io->error = errno;
139 return io->pipe != -1;
140 }
142 bool
143 io_kill(struct io *io)
144 {
145 return io->pid == 0 || kill(io->pid, SIGKILL) != -1;
146 }
148 bool
149 io_done(struct io *io)
150 {
151 pid_t pid = io->pid;
153 if (io->pipe != -1)
154 close(io->pipe);
155 free(io->buf);
156 io_init(io);
158 while (pid > 0) {
159 int status;
160 pid_t waiting = waitpid(pid, &status, 0);
162 if (waiting < 0) {
163 if (errno == EINTR)
164 continue;
165 io->error = errno;
166 return FALSE;
167 }
169 return waiting == pid &&
170 !WIFSIGNALED(status) &&
171 WIFEXITED(status) &&
172 !WEXITSTATUS(status);
173 }
175 return TRUE;
176 }
178 bool
179 io_run(struct io *io, enum io_type type, const char *dir, const char *argv[], ...)
180 {
181 int pipefds[2] = { -1, -1 };
182 va_list args;
184 io_init(io);
186 if (dir && !strcmp(dir, argv[0]))
187 return io_open(io, "%s%s", dir, argv[1]);
189 if ((type == IO_RD || type == IO_WR) && pipe(pipefds) < 0) {
190 io->error = errno;
191 return FALSE;
192 } else if (type == IO_AP) {
193 va_start(args, argv);
194 pipefds[1] = va_arg(args, int);
195 va_end(args);
196 }
198 if ((io->pid = fork())) {
199 if (io->pid == -1)
200 io->error = errno;
201 if (pipefds[!(type == IO_WR)] != -1)
202 close(pipefds[!(type == IO_WR)]);
203 if (io->pid != -1) {
204 io->pipe = pipefds[!!(type == IO_WR)];
205 return TRUE;
206 }
208 } else {
209 if (type != IO_FG) {
210 int devnull = open("/dev/null", O_RDWR);
211 int readfd = type == IO_WR ? pipefds[0] : devnull;
212 int writefd = (type == IO_RD || type == IO_AP)
213 ? pipefds[1] : devnull;
215 dup2(readfd, STDIN_FILENO);
216 dup2(writefd, STDOUT_FILENO);
217 dup2(devnull, STDERR_FILENO);
219 close(devnull);
220 if (pipefds[0] != -1)
221 close(pipefds[0]);
222 if (pipefds[1] != -1)
223 close(pipefds[1]);
224 }
226 if (dir && *dir && chdir(dir) == -1)
227 exit(errno);
229 execvp(argv[0], (char *const*) argv);
230 exit(errno);
231 }
233 if (pipefds[!!(type == IO_WR)] != -1)
234 close(pipefds[!!(type == IO_WR)]);
235 return FALSE;
236 }
238 bool
239 io_complete(enum io_type type, const char **argv, const char *dir, int fd)
240 {
241 struct io io;
243 return io_run(&io, type, dir, argv, fd) && io_done(&io);
244 }
246 bool
247 io_run_bg(const char **argv)
248 {
249 return io_complete(IO_BG, argv, NULL, -1);
250 }
252 bool
253 io_run_fg(const char **argv, const char *dir)
254 {
255 return io_complete(IO_FG, argv, dir, -1);
256 }
258 bool
259 io_run_append(const char **argv, int fd)
260 {
261 return io_complete(IO_AP, argv, NULL, fd);
262 }
264 bool
265 io_eof(struct io *io)
266 {
267 return io->eof;
268 }
270 int
271 io_error(struct io *io)
272 {
273 return io->error;
274 }
276 char *
277 io_strerror(struct io *io)
278 {
279 return strerror(io->error);
280 }
282 bool
283 io_can_read(struct io *io, bool can_block)
284 {
285 struct timeval tv = { 0, 500 };
286 fd_set fds;
288 FD_ZERO(&fds);
289 FD_SET(io->pipe, &fds);
291 return select(io->pipe + 1, &fds, NULL, NULL, can_block ? NULL : &tv) > 0;
292 }
294 ssize_t
295 io_read(struct io *io, void *buf, size_t bufsize)
296 {
297 do {
298 ssize_t readsize = read(io->pipe, buf, bufsize);
300 if (readsize < 0 && (errno == EAGAIN || errno == EINTR))
301 continue;
302 else if (readsize == -1)
303 io->error = errno;
304 else if (readsize == 0)
305 io->eof = 1;
306 return readsize;
307 } while (1);
308 }
310 DEFINE_ALLOCATOR(io_realloc_buf, char, BUFSIZ)
312 char *
313 io_get(struct io *io, int c, bool can_read)
314 {
315 char *eol;
316 ssize_t readsize;
318 while (TRUE) {
319 if (io->bufsize > 0) {
320 eol = memchr(io->bufpos, c, io->bufsize);
321 if (eol) {
322 char *line = io->bufpos;
324 *eol = 0;
325 io->bufpos = eol + 1;
326 io->bufsize -= io->bufpos - line;
327 return line;
328 }
329 }
331 if (io_eof(io)) {
332 if (io->bufsize) {
333 io->bufpos[io->bufsize] = 0;
334 io->bufsize = 0;
335 return io->bufpos;
336 }
337 return NULL;
338 }
340 if (!can_read)
341 return NULL;
343 if (io->bufsize > 0 && io->bufpos > io->buf)
344 memmove(io->buf, io->bufpos, io->bufsize);
346 if (io->bufalloc == io->bufsize) {
347 if (!io_realloc_buf(&io->buf, io->bufalloc, BUFSIZ))
348 return NULL;
349 io->bufalloc += BUFSIZ;
350 }
352 io->bufpos = io->buf;
353 readsize = io_read(io, io->buf + io->bufsize, io->bufalloc - io->bufsize);
354 if (io_error(io))
355 return NULL;
356 io->bufsize += readsize;
357 }
358 }
360 bool
361 io_write(struct io *io, const void *buf, size_t bufsize)
362 {
363 size_t written = 0;
365 while (!io_error(io) && written < bufsize) {
366 ssize_t size;
368 size = write(io->pipe, buf + written, bufsize - written);
369 if (size < 0 && (errno == EAGAIN || errno == EINTR))
370 continue;
371 else if (size == -1)
372 io->error = errno;
373 else
374 written += size;
375 }
377 return written == bufsize;
378 }
380 bool
381 io_read_buf(struct io *io, char buf[], size_t bufsize)
382 {
383 char *result = io_get(io, '\n', TRUE);
385 if (result) {
386 result = chomp_string(result);
387 string_ncopy_do(buf, bufsize, result, strlen(result));
388 }
390 return io_done(io) && result;
391 }
393 bool
394 io_run_buf(const char **argv, char buf[], size_t bufsize)
395 {
396 struct io io;
398 return io_run(&io, IO_RD, NULL, argv) && io_read_buf(&io, buf, bufsize);
399 }
401 int
402 io_load(struct io *io, const char *separators,
403 io_read_fn read_property, void *data)
404 {
405 char *name;
406 int state = OK;
408 while (state == OK && (name = io_get(io, '\n', TRUE))) {
409 char *value;
410 size_t namelen;
411 size_t valuelen;
413 name = chomp_string(name);
414 namelen = strcspn(name, separators);
416 if (name[namelen]) {
417 name[namelen] = 0;
418 value = chomp_string(name + namelen + 1);
419 valuelen = strlen(value);
421 } else {
422 value = "";
423 valuelen = 0;
424 }
426 state = read_property(name, namelen, value, valuelen, data);
427 }
429 if (state != ERR && io_error(io))
430 state = ERR;
431 io_done(io);
433 return state;
434 }
436 int
437 io_run_load(const char **argv, const char *separators,
438 io_read_fn read_property, void *data)
439 {
440 struct io io;
442 if (!io_run(&io, IO_RD, NULL, argv))
443 return ERR;
444 return io_load(&io, separators, read_property, data);
445 }