Show the title of the last commit in the branch view
[tig.git] / io.c
blob7991367407b3150d606521ba3a88e8e5b60e838d
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 static int
264 open_trace(int devnull, const char *argv[])
266 static const char *trace_file;
268 if (!trace_file) {
269 trace_file = getenv("TIG_TRACE");
270 if (!trace_file)
271 trace_file = "";
274 if (*trace_file) {
275 int fd = open(trace_file, O_RDWR | O_CREAT | O_APPEND, 0666);
276 int i;
278 for (i = 0; argv[i]; i++) {
279 if (write(fd, argv[i], strlen(argv[i])) == -1
280 || write(fd, " ", 1) == -1)
281 break;
283 if (argv[i] || write(fd, "\n", 1) == -1) {
284 close(fd);
285 return devnull;
288 return fd;
291 return devnull;
294 bool
295 io_run(struct io *io, enum io_type type, const char *dir, const char *argv[], ...)
297 int pipefds[2] = { -1, -1 };
298 va_list args;
300 io_init(io);
302 if (dir && !strcmp(dir, argv[0]))
303 return io_open(io, "%s%s", dir, argv[1]);
305 if ((type == IO_RD || type == IO_WR) && pipe(pipefds) < 0) {
306 io->error = errno;
307 return FALSE;
308 } else if (type == IO_AP) {
309 va_start(args, argv);
310 pipefds[1] = va_arg(args, int);
311 va_end(args);
314 if ((io->pid = fork())) {
315 if (io->pid == -1)
316 io->error = errno;
317 if (pipefds[!(type == IO_WR)] != -1)
318 close(pipefds[!(type == IO_WR)]);
319 if (io->pid != -1) {
320 io->pipe = pipefds[!!(type == IO_WR)];
321 return TRUE;
324 } else {
325 if (type != IO_FG) {
326 int devnull = open("/dev/null", O_RDWR);
327 int readfd = type == IO_WR ? pipefds[0] : devnull;
328 int writefd = (type == IO_RD || type == IO_AP)
329 ? pipefds[1] : devnull;
330 int errorfd = open_trace(devnull, argv);
332 dup2(readfd, STDIN_FILENO);
333 dup2(writefd, STDOUT_FILENO);
334 dup2(errorfd, STDERR_FILENO);
336 if (devnull != errorfd)
337 close(errorfd);
338 close(devnull);
339 if (pipefds[0] != -1)
340 close(pipefds[0]);
341 if (pipefds[1] != -1)
342 close(pipefds[1]);
345 if (dir && *dir && chdir(dir) == -1)
346 exit(errno);
348 execvp(argv[0], (char *const*) argv);
349 exit(errno);
352 if (pipefds[!!(type == IO_WR)] != -1)
353 close(pipefds[!!(type == IO_WR)]);
354 return FALSE;
357 bool
358 io_complete(enum io_type type, const char **argv, const char *dir, int fd)
360 struct io io;
362 return io_run(&io, type, dir, argv, fd) && io_done(&io);
365 bool
366 io_run_bg(const char **argv)
368 return io_complete(IO_BG, argv, NULL, -1);
371 bool
372 io_run_fg(const char **argv, const char *dir)
374 return io_complete(IO_FG, argv, dir, -1);
377 bool
378 io_run_append(const char **argv, int fd)
380 return io_complete(IO_AP, argv, NULL, fd);
383 bool
384 io_eof(struct io *io)
386 return io->eof;
390 io_error(struct io *io)
392 return io->error;
395 char *
396 io_strerror(struct io *io)
398 return strerror(io->error);
401 bool
402 io_can_read(struct io *io, bool can_block)
404 struct timeval tv = { 0, 500 };
405 fd_set fds;
407 FD_ZERO(&fds);
408 FD_SET(io->pipe, &fds);
410 return select(io->pipe + 1, &fds, NULL, NULL, can_block ? NULL : &tv) > 0;
413 ssize_t
414 io_read(struct io *io, void *buf, size_t bufsize)
416 do {
417 ssize_t readsize = read(io->pipe, buf, bufsize);
419 if (readsize < 0 && (errno == EAGAIN || errno == EINTR))
420 continue;
421 else if (readsize == -1)
422 io->error = errno;
423 else if (readsize == 0)
424 io->eof = 1;
425 return readsize;
426 } while (1);
429 DEFINE_ALLOCATOR(io_realloc_buf, char, BUFSIZ)
431 char *
432 io_get(struct io *io, int c, bool can_read)
434 char *eol;
435 ssize_t readsize;
437 while (TRUE) {
438 if (io->bufsize > 0) {
439 eol = memchr(io->bufpos, c, io->bufsize);
440 if (eol) {
441 char *line = io->bufpos;
443 *eol = 0;
444 io->bufpos = eol + 1;
445 io->bufsize -= io->bufpos - line;
446 return line;
450 if (io_eof(io)) {
451 if (io->bufsize) {
452 io->bufpos[io->bufsize] = 0;
453 io->bufsize = 0;
454 return io->bufpos;
456 return NULL;
459 if (!can_read)
460 return NULL;
462 if (io->bufsize > 0 && io->bufpos > io->buf)
463 memmove(io->buf, io->bufpos, io->bufsize);
465 if (io->bufalloc == io->bufsize) {
466 if (!io_realloc_buf(&io->buf, io->bufalloc, BUFSIZ))
467 return NULL;
468 io->bufalloc += BUFSIZ;
471 io->bufpos = io->buf;
472 readsize = io_read(io, io->buf + io->bufsize, io->bufalloc - io->bufsize);
473 if (io_error(io))
474 return NULL;
475 io->bufsize += readsize;
479 bool
480 io_write(struct io *io, const void *buf, size_t bufsize)
482 size_t written = 0;
484 while (!io_error(io) && written < bufsize) {
485 ssize_t size;
487 size = write(io->pipe, buf + written, bufsize - written);
488 if (size < 0 && (errno == EAGAIN || errno == EINTR))
489 continue;
490 else if (size == -1)
491 io->error = errno;
492 else
493 written += size;
496 return written == bufsize;
499 bool
500 io_printf(struct io *io, const char *fmt, ...)
502 char buf[SIZEOF_STR] = "";
503 int retval;
505 FORMAT_BUFFER(buf, sizeof(buf), fmt, retval, FALSE);
506 if (retval < 0) {
507 io->error = ENAMETOOLONG;
508 return FALSE;
511 return io_write(io, buf, retval);
514 bool
515 io_read_buf(struct io *io, char buf[], size_t bufsize)
517 char *result = io_get(io, '\n', TRUE);
519 if (result) {
520 result = chomp_string(result);
521 string_ncopy_do(buf, bufsize, result, strlen(result));
524 return io_done(io) && result;
527 bool
528 io_run_buf(const char **argv, char buf[], size_t bufsize)
530 struct io io;
532 return io_run(&io, IO_RD, NULL, argv) && io_read_buf(&io, buf, bufsize);
536 io_load(struct io *io, const char *separators,
537 io_read_fn read_property, void *data)
539 char *name;
540 int state = OK;
542 while (state == OK && (name = io_get(io, '\n', TRUE))) {
543 char *value;
544 size_t namelen;
545 size_t valuelen;
547 name = chomp_string(name);
548 namelen = strcspn(name, separators);
550 if (name[namelen]) {
551 name[namelen] = 0;
552 value = chomp_string(name + namelen + 1);
553 valuelen = strlen(value);
555 } else {
556 value = "";
557 valuelen = 0;
560 state = read_property(name, namelen, value, valuelen, data);
563 if (state != ERR && io_error(io))
564 state = ERR;
565 io_done(io);
567 return state;
571 io_run_load(const char **argv, const char *separators,
572 io_read_fn read_property, void *data)
574 struct io io;
576 if (!io_run(&io, IO_RD, NULL, argv))
577 return ERR;
578 return io_load(&io, separators, read_property, data);