Force load the branch view log data
[tig.git] / io.c
blobd5362cc7b88e346c337e83bf6132a21ac28f99e0
1 /* Copyright (c) 2006-2012 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;
139 * Encoding conversion.
142 struct encoding {
143 struct encoding *next;
144 iconv_t cd;
145 char fromcode[1];
148 static struct encoding *encodings;
150 struct encoding *
151 encoding_open(const char *fromcode)
153 struct encoding *encoding;
154 size_t len = strlen(fromcode);
156 if (!*fromcode)
157 return NULL;
159 for (encoding = encodings; encoding; encoding = encoding->next) {
160 if (!strcasecmp(encoding->fromcode, fromcode))
161 return encoding;
164 encoding = calloc(1, sizeof(*encoding) + len);
165 strncpy(encoding->fromcode, fromcode, len);
166 encoding->cd = iconv_open(ENCODING_UTF8, fromcode);
167 if (encoding->cd == ICONV_NONE) {
168 free(encoding);
169 return NULL;
172 encoding->next = encodings;
173 encodings = encoding;
175 return encoding;
178 char *
179 encoding_convert(struct encoding *encoding, char *line)
181 static char out_buffer[BUFSIZ * 2];
182 ICONV_CONST char *inbuf = line;
183 size_t inlen = strlen(line) + 1;
185 char *outbuf = out_buffer;
186 size_t outlen = sizeof(out_buffer);
188 size_t ret = iconv(encoding->cd, &inbuf, &inlen, &outbuf, &outlen);
190 return (ret != (size_t) -1) ? out_buffer : line;
194 * Executing external commands.
197 static void
198 io_init(struct io *io)
200 memset(io, 0, sizeof(*io));
201 io->pipe = -1;
204 bool
205 io_open(struct io *io, const char *fmt, ...)
207 char name[SIZEOF_STR] = "";
208 int retval;
210 io_init(io);
212 FORMAT_BUFFER(name, sizeof(name), fmt, retval, FALSE);
213 if (retval < 0) {
214 io->error = ENAMETOOLONG;
215 return FALSE;
218 io->pipe = *name ? open(name, O_RDONLY) : dup(STDIN_FILENO);
219 if (io->pipe == -1)
220 io->error = errno;
221 return io->pipe != -1;
224 bool
225 io_kill(struct io *io)
227 return io->pid == 0 || kill(io->pid, SIGKILL) != -1;
230 bool
231 io_done(struct io *io)
233 pid_t pid = io->pid;
235 if (io->pipe != -1)
236 close(io->pipe);
237 free(io->buf);
238 io_init(io);
240 while (pid > 0) {
241 int status;
242 pid_t waiting = waitpid(pid, &status, 0);
244 if (waiting < 0) {
245 if (errno == EINTR)
246 continue;
247 io->error = errno;
248 return FALSE;
251 if (WEXITSTATUS(status)) {
252 io->status = WEXITSTATUS(status);
255 return waiting == pid &&
256 !WIFSIGNALED(status) &&
257 !io->status;
260 return TRUE;
263 bool
264 io_run(struct io *io, enum io_type type, const char *dir, const char *argv[], ...)
266 int pipefds[2] = { -1, -1 };
267 va_list args;
269 io_init(io);
271 if (dir && !strcmp(dir, argv[0]))
272 return io_open(io, "%s%s", dir, argv[1]);
274 if ((type == IO_RD || type == IO_WR) && pipe(pipefds) < 0) {
275 io->error = errno;
276 return FALSE;
277 } else if (type == IO_AP) {
278 va_start(args, argv);
279 pipefds[1] = va_arg(args, int);
280 va_end(args);
283 if ((io->pid = fork())) {
284 if (io->pid == -1)
285 io->error = errno;
286 if (pipefds[!(type == IO_WR)] != -1)
287 close(pipefds[!(type == IO_WR)]);
288 if (io->pid != -1) {
289 io->pipe = pipefds[!!(type == IO_WR)];
290 return TRUE;
293 } else {
294 if (type != IO_FG) {
295 int devnull = open("/dev/null", O_RDWR);
296 int readfd = type == IO_WR ? pipefds[0] : devnull;
297 int writefd = (type == IO_RD || type == IO_AP)
298 ? pipefds[1] : devnull;
300 dup2(readfd, STDIN_FILENO);
301 dup2(writefd, STDOUT_FILENO);
302 dup2(devnull, STDERR_FILENO);
304 close(devnull);
305 if (pipefds[0] != -1)
306 close(pipefds[0]);
307 if (pipefds[1] != -1)
308 close(pipefds[1]);
311 if (dir && *dir && chdir(dir) == -1)
312 exit(errno);
314 execvp(argv[0], (char *const*) argv);
315 exit(errno);
318 if (pipefds[!!(type == IO_WR)] != -1)
319 close(pipefds[!!(type == IO_WR)]);
320 return FALSE;
323 bool
324 io_complete(enum io_type type, const char **argv, const char *dir, int fd)
326 struct io io;
328 return io_run(&io, type, dir, argv, fd) && io_done(&io);
331 bool
332 io_run_bg(const char **argv)
334 return io_complete(IO_BG, argv, NULL, -1);
337 bool
338 io_run_fg(const char **argv, const char *dir)
340 return io_complete(IO_FG, argv, dir, -1);
343 bool
344 io_run_append(const char **argv, int fd)
346 return io_complete(IO_AP, argv, NULL, fd);
349 bool
350 io_eof(struct io *io)
352 return io->eof;
356 io_error(struct io *io)
358 return io->error;
361 char *
362 io_strerror(struct io *io)
364 return strerror(io->error);
367 bool
368 io_can_read(struct io *io, bool can_block)
370 struct timeval tv = { 0, 500 };
371 fd_set fds;
373 FD_ZERO(&fds);
374 FD_SET(io->pipe, &fds);
376 return select(io->pipe + 1, &fds, NULL, NULL, can_block ? NULL : &tv) > 0;
379 ssize_t
380 io_read(struct io *io, void *buf, size_t bufsize)
382 do {
383 ssize_t readsize = read(io->pipe, buf, bufsize);
385 if (readsize < 0 && (errno == EAGAIN || errno == EINTR))
386 continue;
387 else if (readsize == -1)
388 io->error = errno;
389 else if (readsize == 0)
390 io->eof = 1;
391 return readsize;
392 } while (1);
395 DEFINE_ALLOCATOR(io_realloc_buf, char, BUFSIZ)
397 char *
398 io_get(struct io *io, int c, bool can_read)
400 char *eol;
401 ssize_t readsize;
403 while (TRUE) {
404 if (io->bufsize > 0) {
405 eol = memchr(io->bufpos, c, io->bufsize);
406 if (eol) {
407 char *line = io->bufpos;
409 *eol = 0;
410 io->bufpos = eol + 1;
411 io->bufsize -= io->bufpos - line;
412 return line;
416 if (io_eof(io)) {
417 if (io->bufsize) {
418 io->bufpos[io->bufsize] = 0;
419 io->bufsize = 0;
420 return io->bufpos;
422 return NULL;
425 if (!can_read)
426 return NULL;
428 if (io->bufsize > 0 && io->bufpos > io->buf)
429 memmove(io->buf, io->bufpos, io->bufsize);
431 if (io->bufalloc == io->bufsize) {
432 if (!io_realloc_buf(&io->buf, io->bufalloc, BUFSIZ))
433 return NULL;
434 io->bufalloc += BUFSIZ;
437 io->bufpos = io->buf;
438 readsize = io_read(io, io->buf + io->bufsize, io->bufalloc - io->bufsize);
439 if (io_error(io))
440 return NULL;
441 io->bufsize += readsize;
445 bool
446 io_write(struct io *io, const void *buf, size_t bufsize)
448 size_t written = 0;
450 while (!io_error(io) && written < bufsize) {
451 ssize_t size;
453 size = write(io->pipe, buf + written, bufsize - written);
454 if (size < 0 && (errno == EAGAIN || errno == EINTR))
455 continue;
456 else if (size == -1)
457 io->error = errno;
458 else
459 written += size;
462 return written == bufsize;
465 bool
466 io_printf(struct io *io, const char *fmt, ...)
468 char buf[SIZEOF_STR] = "";
469 int retval;
471 FORMAT_BUFFER(buf, sizeof(buf), fmt, retval, FALSE);
472 if (retval < 0) {
473 io->error = ENAMETOOLONG;
474 return FALSE;
477 return io_write(io, buf, retval);
480 bool
481 io_read_buf(struct io *io, char buf[], size_t bufsize)
483 char *result = io_get(io, '\n', TRUE);
485 if (result) {
486 result = chomp_string(result);
487 string_ncopy_do(buf, bufsize, result, strlen(result));
490 return io_done(io) && result;
493 bool
494 io_run_buf(const char **argv, char buf[], size_t bufsize)
496 struct io io;
498 return io_run(&io, IO_RD, NULL, argv) && io_read_buf(&io, buf, bufsize);
502 io_load(struct io *io, const char *separators,
503 io_read_fn read_property, void *data)
505 char *name;
506 int state = OK;
508 while (state == OK && (name = io_get(io, '\n', TRUE))) {
509 char *value;
510 size_t namelen;
511 size_t valuelen;
513 name = chomp_string(name);
514 namelen = strcspn(name, separators);
516 if (name[namelen]) {
517 name[namelen] = 0;
518 value = chomp_string(name + namelen + 1);
519 valuelen = strlen(value);
521 } else {
522 value = "";
523 valuelen = 0;
526 state = read_property(name, namelen, value, valuelen, data);
529 if (state != ERR && io_error(io))
530 state = ERR;
531 io_done(io);
533 return state;
537 io_run_load(const char **argv, const char *separators,
538 io_read_fn read_property, void *data)
540 struct io io;
542 if (!io_run(&io, IO_RD, NULL, argv))
543 return ERR;
544 return io_load(&io, separators, read_property, data);