manual: Fix the references section title
[tig.git] / io.c
blobb94d0061888d57cf7a3f3e291acd22a18a65f4e1
1 /* Copyright (c) 2006-2010 Jonas Fonseca <fonseca@diku.dk>
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.
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.
14 #include "tig.h"
15 #include "io.h"
17 static inline int
18 get_arg_valuelen(const char *arg, bool *quoted)
20 if (*arg == '"' || *arg == '\'') {
21 const char *end = *arg == '"' ? "\"" : "'";
22 int valuelen = strcspn(arg + 1, end);
24 if (quoted)
25 *quoted = TRUE;
26 return valuelen > 0 ? valuelen + 2 : strlen(arg);
27 } else {
28 return strcspn(arg, " \t");
32 static bool
33 split_argv_string(const char *argv[SIZEOF_ARG], int *argc, char *cmd, bool remove_quotes)
35 while (*cmd && *argc < SIZEOF_ARG) {
36 bool quoted = FALSE;
37 int valuelen = get_arg_valuelen(cmd, &quoted);
38 bool advance = cmd[valuelen] != 0;
39 int quote_offset = !!(quoted && remove_quotes);
41 cmd[valuelen - quote_offset] = 0;
42 argv[(*argc)++] = chomp_string(cmd + quote_offset);
43 cmd = chomp_string(cmd + valuelen + advance);
46 if (*argc < SIZEOF_ARG)
47 argv[*argc] = NULL;
48 return *argc < SIZEOF_ARG;
51 bool
52 argv_from_string_no_quotes(const char *argv[SIZEOF_ARG], int *argc, char *cmd)
54 return split_argv_string(argv, argc, cmd, TRUE);
57 bool
58 argv_from_string(const char *argv[SIZEOF_ARG], int *argc, char *cmd)
60 return split_argv_string(argv, argc, cmd, FALSE);
63 bool
64 argv_from_env(const char **argv, const char *name)
66 char *env = argv ? getenv(name) : NULL;
67 int argc = 0;
69 if (env && *env)
70 env = strdup(env);
71 return !env || argv_from_string(argv, &argc, env);
74 void
75 argv_free(const char *argv[])
77 int argc;
79 if (!argv)
80 return;
81 for (argc = 0; argv[argc]; argc++)
82 free((void *) argv[argc]);
83 argv[0] = NULL;
86 size_t
87 argv_size(const char **argv)
89 int argc = 0;
91 while (argv && argv[argc])
92 argc++;
94 return argc;
97 DEFINE_ALLOCATOR(argv_realloc, const char *, SIZEOF_ARG)
99 bool
100 argv_append(const char ***argv, const char *arg)
102 size_t argc = argv_size(*argv);
104 if (!*arg && argc > 0)
105 return TRUE;
107 if (!argv_realloc(argv, argc, 2))
108 return FALSE;
110 (*argv)[argc++] = strdup(arg);
111 (*argv)[argc] = NULL;
112 return TRUE;
115 bool
116 argv_append_array(const char ***dst_argv, const char *src_argv[])
118 int i;
120 for (i = 0; src_argv && src_argv[i]; i++)
121 if (!argv_append(dst_argv, src_argv[i]))
122 return FALSE;
123 return TRUE;
126 bool
127 argv_copy(const char ***dst, const char *src[])
129 int argc;
131 argv_free(*dst);
132 for (argc = 0; src[argc]; argc++)
133 if (!argv_append(dst, src[argc]))
134 return FALSE;
135 return TRUE;
140 * Executing external commands.
143 static void
144 io_init(struct io *io)
146 memset(io, 0, sizeof(*io));
147 io->pipe = -1;
150 bool
151 io_open(struct io *io, const char *fmt, ...)
153 char name[SIZEOF_STR] = "";
154 int retval;
156 io_init(io);
158 FORMAT_BUFFER(name, sizeof(name), fmt, retval);
159 if (retval < 0) {
160 io->error = ENAMETOOLONG;
161 return FALSE;
164 io->pipe = *name ? open(name, O_RDONLY) : dup(STDIN_FILENO);
165 if (io->pipe == -1)
166 io->error = errno;
167 return io->pipe != -1;
170 bool
171 io_kill(struct io *io)
173 return io->pid == 0 || kill(io->pid, SIGKILL) != -1;
176 bool
177 io_done(struct io *io)
179 pid_t pid = io->pid;
181 if (io->pipe != -1)
182 close(io->pipe);
183 free(io->buf);
184 io_init(io);
186 while (pid > 0) {
187 int status;
188 pid_t waiting = waitpid(pid, &status, 0);
190 if (waiting < 0) {
191 if (errno == EINTR)
192 continue;
193 io->error = errno;
194 return FALSE;
197 return waiting == pid &&
198 !WIFSIGNALED(status) &&
199 WIFEXITED(status) &&
200 !WEXITSTATUS(status);
203 return TRUE;
206 bool
207 io_run(struct io *io, enum io_type type, const char *dir, const char *argv[], ...)
209 int pipefds[2] = { -1, -1 };
210 va_list args;
212 io_init(io);
214 if (dir && !strcmp(dir, argv[0]))
215 return io_open(io, "%s%s", dir, argv[1]);
217 if ((type == IO_RD || type == IO_WR) && pipe(pipefds) < 0) {
218 io->error = errno;
219 return FALSE;
220 } else if (type == IO_AP) {
221 va_start(args, argv);
222 pipefds[1] = va_arg(args, int);
223 va_end(args);
226 if ((io->pid = fork())) {
227 if (io->pid == -1)
228 io->error = errno;
229 if (pipefds[!(type == IO_WR)] != -1)
230 close(pipefds[!(type == IO_WR)]);
231 if (io->pid != -1) {
232 io->pipe = pipefds[!!(type == IO_WR)];
233 return TRUE;
236 } else {
237 if (type != IO_FG) {
238 int devnull = open("/dev/null", O_RDWR);
239 int readfd = type == IO_WR ? pipefds[0] : devnull;
240 int writefd = (type == IO_RD || type == IO_AP)
241 ? pipefds[1] : devnull;
243 dup2(readfd, STDIN_FILENO);
244 dup2(writefd, STDOUT_FILENO);
245 dup2(devnull, STDERR_FILENO);
247 close(devnull);
248 if (pipefds[0] != -1)
249 close(pipefds[0]);
250 if (pipefds[1] != -1)
251 close(pipefds[1]);
254 if (dir && *dir && chdir(dir) == -1)
255 exit(errno);
257 execvp(argv[0], (char *const*) argv);
258 exit(errno);
261 if (pipefds[!!(type == IO_WR)] != -1)
262 close(pipefds[!!(type == IO_WR)]);
263 return FALSE;
266 bool
267 io_complete(enum io_type type, const char **argv, const char *dir, int fd)
269 struct io io;
271 return io_run(&io, type, dir, argv, fd) && io_done(&io);
274 bool
275 io_run_bg(const char **argv)
277 return io_complete(IO_BG, argv, NULL, -1);
280 bool
281 io_run_fg(const char **argv, const char *dir)
283 return io_complete(IO_FG, argv, dir, -1);
286 bool
287 io_run_append(const char **argv, int fd)
289 return io_complete(IO_AP, argv, NULL, fd);
292 bool
293 io_eof(struct io *io)
295 return io->eof;
299 io_error(struct io *io)
301 return io->error;
304 char *
305 io_strerror(struct io *io)
307 return strerror(io->error);
310 bool
311 io_can_read(struct io *io, bool can_block)
313 struct timeval tv = { 0, 500 };
314 fd_set fds;
316 FD_ZERO(&fds);
317 FD_SET(io->pipe, &fds);
319 return select(io->pipe + 1, &fds, NULL, NULL, can_block ? NULL : &tv) > 0;
322 ssize_t
323 io_read(struct io *io, void *buf, size_t bufsize)
325 do {
326 ssize_t readsize = read(io->pipe, buf, bufsize);
328 if (readsize < 0 && (errno == EAGAIN || errno == EINTR))
329 continue;
330 else if (readsize == -1)
331 io->error = errno;
332 else if (readsize == 0)
333 io->eof = 1;
334 return readsize;
335 } while (1);
338 DEFINE_ALLOCATOR(io_realloc_buf, char, BUFSIZ)
340 char *
341 io_get(struct io *io, int c, bool can_read)
343 char *eol;
344 ssize_t readsize;
346 while (TRUE) {
347 if (io->bufsize > 0) {
348 eol = memchr(io->bufpos, c, io->bufsize);
349 if (eol) {
350 char *line = io->bufpos;
352 *eol = 0;
353 io->bufpos = eol + 1;
354 io->bufsize -= io->bufpos - line;
355 return line;
359 if (io_eof(io)) {
360 if (io->bufsize) {
361 io->bufpos[io->bufsize] = 0;
362 io->bufsize = 0;
363 return io->bufpos;
365 return NULL;
368 if (!can_read)
369 return NULL;
371 if (io->bufsize > 0 && io->bufpos > io->buf)
372 memmove(io->buf, io->bufpos, io->bufsize);
374 if (io->bufalloc == io->bufsize) {
375 if (!io_realloc_buf(&io->buf, io->bufalloc, BUFSIZ))
376 return NULL;
377 io->bufalloc += BUFSIZ;
380 io->bufpos = io->buf;
381 readsize = io_read(io, io->buf + io->bufsize, io->bufalloc - io->bufsize);
382 if (io_error(io))
383 return NULL;
384 io->bufsize += readsize;
388 bool
389 io_write(struct io *io, const void *buf, size_t bufsize)
391 size_t written = 0;
393 while (!io_error(io) && written < bufsize) {
394 ssize_t size;
396 size = write(io->pipe, buf + written, bufsize - written);
397 if (size < 0 && (errno == EAGAIN || errno == EINTR))
398 continue;
399 else if (size == -1)
400 io->error = errno;
401 else
402 written += size;
405 return written == bufsize;
408 bool
409 io_printf(struct io *io, const char *fmt, ...)
411 char buf[SIZEOF_STR] = "";
412 int retval;
414 FORMAT_BUFFER(buf, sizeof(buf), fmt, retval);
415 if (retval < 0) {
416 io->error = ENAMETOOLONG;
417 return FALSE;
420 return io_write(io, buf, retval);
423 bool
424 io_read_buf(struct io *io, char buf[], size_t bufsize)
426 char *result = io_get(io, '\n', TRUE);
428 if (result) {
429 result = chomp_string(result);
430 string_ncopy_do(buf, bufsize, result, strlen(result));
433 return io_done(io) && result;
436 bool
437 io_run_buf(const char **argv, char buf[], size_t bufsize)
439 struct io io;
441 return io_run(&io, IO_RD, NULL, argv) && io_read_buf(&io, buf, bufsize);
445 io_load(struct io *io, const char *separators,
446 io_read_fn read_property, void *data)
448 char *name;
449 int state = OK;
451 while (state == OK && (name = io_get(io, '\n', TRUE))) {
452 char *value;
453 size_t namelen;
454 size_t valuelen;
456 name = chomp_string(name);
457 namelen = strcspn(name, separators);
459 if (name[namelen]) {
460 name[namelen] = 0;
461 value = chomp_string(name + namelen + 1);
462 valuelen = strlen(value);
464 } else {
465 value = "";
466 valuelen = 0;
469 state = read_property(name, namelen, value, valuelen, data);
472 if (state != ERR && io_error(io))
473 state = ERR;
474 io_done(io);
476 return state;
480 io_run_load(const char **argv, const char *separators,
481 io_read_fn read_property, void *data)
483 struct io io;
485 if (!io_run(&io, IO_RD, NULL, argv))
486 return ERR;
487 return io_load(&io, separators, read_property, data);