Sanitize the width argument to draw_field to not include padding
[tig.git] / io.c
blob0c1a8f75229c7fe691e85ea7fb9b1913f6775a62
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 bool
18 argv_to_string(const char *argv[SIZEOF_ARG], char *buf, size_t buflen, const char *sep)
20 size_t bufpos, argc;
22 for (bufpos = 0, argc = 0; argv[argc]; argc++)
23 if (!string_nformat(buf, buflen, &bufpos, "%s%s",
24 argc ? sep : "", argv[argc]))
25 return FALSE;
27 return TRUE;
30 static inline int
31 get_arg_valuelen(const char *arg, bool *quoted)
33 if (*arg == '"' || *arg == '\'') {
34 const char *end = *arg == '"' ? "\"" : "'";
35 int valuelen = strcspn(arg + 1, end);
37 if (quoted)
38 *quoted = TRUE;
39 return valuelen > 0 ? valuelen + 2 : strlen(arg);
40 } else {
41 return strcspn(arg, " \t");
45 static bool
46 split_argv_string(const char *argv[SIZEOF_ARG], int *argc, char *cmd, bool remove_quotes)
48 while (*cmd && *argc < SIZEOF_ARG) {
49 bool quoted = FALSE;
50 int valuelen = get_arg_valuelen(cmd, &quoted);
51 bool advance = cmd[valuelen] != 0;
52 int quote_offset = !!(quoted && remove_quotes);
54 cmd[valuelen - quote_offset] = 0;
55 argv[(*argc)++] = chomp_string(cmd + quote_offset);
56 cmd = chomp_string(cmd + valuelen + advance);
59 if (*argc < SIZEOF_ARG)
60 argv[*argc] = NULL;
61 return *argc < SIZEOF_ARG;
64 bool
65 argv_from_string_no_quotes(const char *argv[SIZEOF_ARG], int *argc, char *cmd)
67 return split_argv_string(argv, argc, cmd, TRUE);
70 bool
71 argv_from_string(const char *argv[SIZEOF_ARG], int *argc, char *cmd)
73 return split_argv_string(argv, argc, cmd, FALSE);
76 bool
77 argv_from_env(const char **argv, const char *name)
79 char *env = argv ? getenv(name) : NULL;
80 int argc = 0;
82 if (env && *env)
83 env = strdup(env);
84 return !env || argv_from_string(argv, &argc, env);
87 void
88 argv_free(const char *argv[])
90 int argc;
92 if (!argv)
93 return;
94 for (argc = 0; argv[argc]; argc++)
95 free((void *) argv[argc]);
96 argv[0] = NULL;
99 size_t
100 argv_size(const char **argv)
102 int argc = 0;
104 while (argv && argv[argc])
105 argc++;
107 return argc;
110 DEFINE_ALLOCATOR(argv_realloc, const char *, SIZEOF_ARG)
112 bool
113 argv_append(const char ***argv, const char *arg)
115 size_t argc = argv_size(*argv);
117 if (!*arg && argc > 0)
118 return TRUE;
120 if (!argv_realloc(argv, argc, 2))
121 return FALSE;
123 (*argv)[argc++] = strdup(arg);
124 (*argv)[argc] = NULL;
125 return TRUE;
128 bool
129 argv_append_array(const char ***dst_argv, const char *src_argv[])
131 int i;
133 for (i = 0; src_argv && src_argv[i]; i++)
134 if (!argv_append(dst_argv, src_argv[i]))
135 return FALSE;
136 return TRUE;
139 bool
140 argv_copy(const char ***dst, const char *src[])
142 int argc;
144 argv_free(*dst);
145 for (argc = 0; src[argc]; argc++)
146 if (!argv_append(dst, src[argc]))
147 return FALSE;
148 return TRUE;
152 * Encoding conversion.
155 struct encoding {
156 struct encoding *next;
157 iconv_t cd;
158 char fromcode[1];
161 static struct encoding *encodings;
163 struct encoding *
164 encoding_open(const char *fromcode)
166 struct encoding *encoding;
167 size_t len = strlen(fromcode);
169 if (!*fromcode)
170 return NULL;
172 for (encoding = encodings; encoding; encoding = encoding->next) {
173 if (!strcasecmp(encoding->fromcode, fromcode))
174 return encoding;
177 encoding = calloc(1, sizeof(*encoding) + len);
178 strncpy(encoding->fromcode, fromcode, len);
179 encoding->cd = iconv_open(ENCODING_UTF8, fromcode);
180 if (encoding->cd == ICONV_NONE) {
181 free(encoding);
182 return NULL;
185 encoding->next = encodings;
186 encodings = encoding;
188 return encoding;
191 char *
192 encoding_convert(struct encoding *encoding, char *line)
194 static char out_buffer[BUFSIZ * 2];
195 ICONV_CONST char *inbuf = line;
196 size_t inlen = strlen(line) + 1;
198 char *outbuf = out_buffer;
199 size_t outlen = sizeof(out_buffer);
201 size_t ret = iconv(encoding->cd, &inbuf, &inlen, &outbuf, &outlen);
203 return (ret != (size_t) -1) ? out_buffer : line;
207 * Executing external commands.
210 static void
211 io_init(struct io *io)
213 memset(io, 0, sizeof(*io));
214 io->pipe = -1;
217 bool
218 io_open(struct io *io, const char *fmt, ...)
220 char name[SIZEOF_STR] = "";
221 int retval;
223 io_init(io);
225 FORMAT_BUFFER(name, sizeof(name), fmt, retval, FALSE);
226 if (retval < 0) {
227 io->error = ENAMETOOLONG;
228 return FALSE;
231 io->pipe = *name ? open(name, O_RDONLY) : dup(STDIN_FILENO);
232 if (io->pipe == -1)
233 io->error = errno;
234 return io->pipe != -1;
237 bool
238 io_kill(struct io *io)
240 return io->pid == 0 || kill(io->pid, SIGKILL) != -1;
243 bool
244 io_done(struct io *io)
246 pid_t pid = io->pid;
248 if (io->pipe != -1)
249 close(io->pipe);
250 free(io->buf);
251 io_init(io);
253 while (pid > 0) {
254 int status;
255 pid_t waiting = waitpid(pid, &status, 0);
257 if (waiting < 0) {
258 if (errno == EINTR)
259 continue;
260 io->error = errno;
261 return FALSE;
264 if (WEXITSTATUS(status)) {
265 io->status = WEXITSTATUS(status);
268 return waiting == pid &&
269 !WIFSIGNALED(status) &&
270 !io->status;
273 return TRUE;
276 static int
277 open_trace(int devnull, const char *argv[])
279 static const char *trace_file;
281 if (!trace_file) {
282 trace_file = getenv("TIG_TRACE");
283 if (!trace_file)
284 trace_file = "";
287 if (*trace_file) {
288 int fd = open(trace_file, O_RDWR | O_CREAT | O_APPEND, 0666);
289 int i;
291 for (i = 0; argv[i]; i++) {
292 if (write(fd, argv[i], strlen(argv[i])) == -1
293 || write(fd, " ", 1) == -1)
294 break;
296 if (argv[i] || write(fd, "\n", 1) == -1) {
297 close(fd);
298 return devnull;
301 return fd;
304 return devnull;
307 bool
308 io_run(struct io *io, enum io_type type, const char *dir, const char *argv[], ...)
310 int pipefds[2] = { -1, -1 };
311 va_list args;
313 io_init(io);
315 if (dir && !strcmp(dir, argv[0]))
316 return io_open(io, "%s%s", dir, argv[1]);
318 if ((type == IO_RD || type == IO_WR) && pipe(pipefds) < 0) {
319 io->error = errno;
320 return FALSE;
321 } else if (type == IO_AP) {
322 va_start(args, argv);
323 pipefds[1] = va_arg(args, int);
324 va_end(args);
327 if ((io->pid = fork())) {
328 if (io->pid == -1)
329 io->error = errno;
330 if (pipefds[!(type == IO_WR)] != -1)
331 close(pipefds[!(type == IO_WR)]);
332 if (io->pid != -1) {
333 io->pipe = pipefds[!!(type == IO_WR)];
334 return TRUE;
337 } else {
338 if (type != IO_FG) {
339 int devnull = open("/dev/null", O_RDWR);
340 int readfd = type == IO_WR ? pipefds[0] : devnull;
341 int writefd = (type == IO_RD || type == IO_AP)
342 ? pipefds[1] : devnull;
343 int errorfd = open_trace(devnull, argv);
345 dup2(readfd, STDIN_FILENO);
346 dup2(writefd, STDOUT_FILENO);
347 dup2(errorfd, STDERR_FILENO);
349 if (devnull != errorfd)
350 close(errorfd);
351 close(devnull);
352 if (pipefds[0] != -1)
353 close(pipefds[0]);
354 if (pipefds[1] != -1)
355 close(pipefds[1]);
358 if (dir && *dir && chdir(dir) == -1)
359 exit(errno);
361 execvp(argv[0], (char *const*) argv);
362 exit(errno);
365 if (pipefds[!!(type == IO_WR)] != -1)
366 close(pipefds[!!(type == IO_WR)]);
367 return FALSE;
370 bool
371 io_complete(enum io_type type, const char **argv, const char *dir, int fd)
373 struct io io;
375 return io_run(&io, type, dir, argv, fd) && io_done(&io);
378 bool
379 io_run_bg(const char **argv)
381 return io_complete(IO_BG, argv, NULL, -1);
384 bool
385 io_run_fg(const char **argv, const char *dir)
387 return io_complete(IO_FG, argv, dir, -1);
390 bool
391 io_run_append(const char **argv, int fd)
393 return io_complete(IO_AP, argv, NULL, fd);
396 bool
397 io_eof(struct io *io)
399 return io->eof;
403 io_error(struct io *io)
405 return io->error;
408 char *
409 io_strerror(struct io *io)
411 return strerror(io->error);
414 bool
415 io_can_read(struct io *io, bool can_block)
417 struct timeval tv = { 0, 500 };
418 fd_set fds;
420 FD_ZERO(&fds);
421 FD_SET(io->pipe, &fds);
423 return select(io->pipe + 1, &fds, NULL, NULL, can_block ? NULL : &tv) > 0;
426 ssize_t
427 io_read(struct io *io, void *buf, size_t bufsize)
429 do {
430 ssize_t readsize = read(io->pipe, buf, bufsize);
432 if (readsize < 0 && (errno == EAGAIN || errno == EINTR))
433 continue;
434 else if (readsize == -1)
435 io->error = errno;
436 else if (readsize == 0)
437 io->eof = 1;
438 return readsize;
439 } while (1);
442 DEFINE_ALLOCATOR(io_realloc_buf, char, BUFSIZ)
444 char *
445 io_get(struct io *io, int c, bool can_read)
447 char *eol;
448 ssize_t readsize;
450 while (TRUE) {
451 if (io->bufsize > 0) {
452 eol = memchr(io->bufpos, c, io->bufsize);
453 if (eol) {
454 char *line = io->bufpos;
456 *eol = 0;
457 io->bufpos = eol + 1;
458 io->bufsize -= io->bufpos - line;
459 return line;
463 if (io_eof(io)) {
464 if (io->bufsize) {
465 io->bufpos[io->bufsize] = 0;
466 io->bufsize = 0;
467 return io->bufpos;
469 return NULL;
472 if (!can_read)
473 return NULL;
475 if (io->bufsize > 0 && io->bufpos > io->buf)
476 memmove(io->buf, io->bufpos, io->bufsize);
478 if (io->bufalloc == io->bufsize) {
479 if (!io_realloc_buf(&io->buf, io->bufalloc, BUFSIZ))
480 return NULL;
481 io->bufalloc += BUFSIZ;
484 io->bufpos = io->buf;
485 readsize = io_read(io, io->buf + io->bufsize, io->bufalloc - io->bufsize);
486 if (io_error(io))
487 return NULL;
488 io->bufsize += readsize;
492 bool
493 io_write(struct io *io, const void *buf, size_t bufsize)
495 size_t written = 0;
497 while (!io_error(io) && written < bufsize) {
498 ssize_t size;
500 size = write(io->pipe, buf + written, bufsize - written);
501 if (size < 0 && (errno == EAGAIN || errno == EINTR))
502 continue;
503 else if (size == -1)
504 io->error = errno;
505 else
506 written += size;
509 return written == bufsize;
512 bool
513 io_printf(struct io *io, const char *fmt, ...)
515 char buf[SIZEOF_STR] = "";
516 int retval;
518 FORMAT_BUFFER(buf, sizeof(buf), fmt, retval, FALSE);
519 if (retval < 0) {
520 io->error = ENAMETOOLONG;
521 return FALSE;
524 return io_write(io, buf, retval);
527 bool
528 io_read_buf(struct io *io, char buf[], size_t bufsize)
530 char *result = io_get(io, '\n', TRUE);
532 if (result) {
533 result = chomp_string(result);
534 string_ncopy_do(buf, bufsize, result, strlen(result));
537 return io_done(io) && result;
540 bool
541 io_run_buf(const char **argv, char buf[], size_t bufsize)
543 struct io io;
545 return io_run(&io, IO_RD, NULL, argv) && io_read_buf(&io, buf, bufsize);
549 io_load(struct io *io, const char *separators,
550 io_read_fn read_property, void *data)
552 char *name;
553 int state = OK;
555 while (state == OK && (name = io_get(io, '\n', TRUE))) {
556 char *value;
557 size_t namelen;
558 size_t valuelen;
560 name = chomp_string(name);
561 namelen = strcspn(name, separators);
563 if (name[namelen]) {
564 name[namelen] = 0;
565 value = chomp_string(name + namelen + 1);
566 valuelen = strlen(value);
568 } else {
569 value = "";
570 valuelen = 0;
573 state = read_property(name, namelen, value, valuelen, data);
576 if (state != ERR && io_error(io))
577 state = ERR;
578 io_done(io);
580 return state;
584 io_run_load(const char **argv, const char *separators,
585 io_read_fn read_property, void *data)
587 struct io io;
589 if (!io_run(&io, IO_RD, NULL, argv))
590 return ERR;
591 return io_load(&io, separators, read_property, data);