Code

Move view splitting code to separate split_view
[tig.git] / io.c
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;
108 /*
109  * Executing external commands.
110  */
112 static void
113 io_init(struct io *io)
115         memset(io, 0, sizeof(*io));
116         io->pipe = -1;
119 bool
120 io_open(struct io *io, const char *fmt, ...)
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;
142 bool
143 io_kill(struct io *io)
145         return io->pid == 0 || kill(io->pid, SIGKILL) != -1;
148 bool
149 io_done(struct io *io)
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;
178 bool
179 io_run(struct io *io, enum io_type type, const char *dir, const char *argv[], ...)
181         int pipefds[2] = { -1, -1 };
182         va_list args;
184         io_init(io);
186         if ((type == IO_RD || type == IO_WR) && pipe(pipefds) < 0) {
187                 io->error = errno;
188                 return FALSE;
189         } else if (type == IO_AP) {
190                 va_start(args, argv);
191                 pipefds[1] = va_arg(args, int);
192                 va_end(args);
193         }
195         if ((io->pid = fork())) {
196                 if (io->pid == -1)
197                         io->error = errno;
198                 if (pipefds[!(type == IO_WR)] != -1)
199                         close(pipefds[!(type == IO_WR)]);
200                 if (io->pid != -1) {
201                         io->pipe = pipefds[!!(type == IO_WR)];
202                         return TRUE;
203                 }
205         } else {
206                 if (type != IO_FG) {
207                         int devnull = open("/dev/null", O_RDWR);
208                         int readfd  = type == IO_WR ? pipefds[0] : devnull;
209                         int writefd = (type == IO_RD || type == IO_AP)
210                                                         ? pipefds[1] : devnull;
212                         dup2(readfd,  STDIN_FILENO);
213                         dup2(writefd, STDOUT_FILENO);
214                         dup2(devnull, STDERR_FILENO);
216                         close(devnull);
217                         if (pipefds[0] != -1)
218                                 close(pipefds[0]);
219                         if (pipefds[1] != -1)
220                                 close(pipefds[1]);
221                 }
223                 if (dir && *dir && chdir(dir) == -1)
224                         exit(errno);
226                 execvp(argv[0], (char *const*) argv);
227                 exit(errno);
228         }
230         if (pipefds[!!(type == IO_WR)] != -1)
231                 close(pipefds[!!(type == IO_WR)]);
232         return FALSE;
235 bool
236 io_complete(enum io_type type, const char **argv, const char *dir, int fd)
238         struct io io;
240         return io_run(&io, type, dir, argv, fd) && io_done(&io);
243 bool
244 io_run_bg(const char **argv)
246         return io_complete(IO_BG, argv, NULL, -1);
249 bool
250 io_run_fg(const char **argv, const char *dir)
252         return io_complete(IO_FG, argv, dir, -1);
255 bool
256 io_run_append(const char **argv, int fd)
258         return io_complete(IO_AP, argv, NULL, fd);
261 bool
262 io_eof(struct io *io)
264         return io->eof;
267 int
268 io_error(struct io *io)
270         return io->error;
273 char *
274 io_strerror(struct io *io)
276         return strerror(io->error);
279 bool
280 io_can_read(struct io *io, bool can_block)
282         struct timeval tv = { 0, 500 };
283         fd_set fds;
285         FD_ZERO(&fds);
286         FD_SET(io->pipe, &fds);
288         return select(io->pipe + 1, &fds, NULL, NULL, can_block ? NULL : &tv) > 0;
291 ssize_t
292 io_read(struct io *io, void *buf, size_t bufsize)
294         do {
295                 ssize_t readsize = read(io->pipe, buf, bufsize);
297                 if (readsize < 0 && (errno == EAGAIN || errno == EINTR))
298                         continue;
299                 else if (readsize == -1)
300                         io->error = errno;
301                 else if (readsize == 0)
302                         io->eof = 1;
303                 return readsize;
304         } while (1);
307 DEFINE_ALLOCATOR(io_realloc_buf, char, BUFSIZ)
309 char *
310 io_get(struct io *io, int c, bool can_read)
312         char *eol;
313         ssize_t readsize;
315         while (TRUE) {
316                 if (io->bufsize > 0) {
317                         eol = memchr(io->bufpos, c, io->bufsize);
318                         if (eol) {
319                                 char *line = io->bufpos;
321                                 *eol = 0;
322                                 io->bufpos = eol + 1;
323                                 io->bufsize -= io->bufpos - line;
324                                 return line;
325                         }
326                 }
328                 if (io_eof(io)) {
329                         if (io->bufsize) {
330                                 io->bufpos[io->bufsize] = 0;
331                                 io->bufsize = 0;
332                                 return io->bufpos;
333                         }
334                         return NULL;
335                 }
337                 if (!can_read)
338                         return NULL;
340                 if (io->bufsize > 0 && io->bufpos > io->buf)
341                         memmove(io->buf, io->bufpos, io->bufsize);
343                 if (io->bufalloc == io->bufsize) {
344                         if (!io_realloc_buf(&io->buf, io->bufalloc, BUFSIZ))
345                                 return NULL;
346                         io->bufalloc += BUFSIZ;
347                 }
349                 io->bufpos = io->buf;
350                 readsize = io_read(io, io->buf + io->bufsize, io->bufalloc - io->bufsize);
351                 if (io_error(io))
352                         return NULL;
353                 io->bufsize += readsize;
354         }
357 bool
358 io_write(struct io *io, const void *buf, size_t bufsize)
360         size_t written = 0;
362         while (!io_error(io) && written < bufsize) {
363                 ssize_t size;
365                 size = write(io->pipe, buf + written, bufsize - written);
366                 if (size < 0 && (errno == EAGAIN || errno == EINTR))
367                         continue;
368                 else if (size == -1)
369                         io->error = errno;
370                 else
371                         written += size;
372         }
374         return written == bufsize;
377 bool
378 io_read_buf(struct io *io, char buf[], size_t bufsize)
380         char *result = io_get(io, '\n', TRUE);
382         if (result) {
383                 result = chomp_string(result);
384                 string_ncopy_do(buf, bufsize, result, strlen(result));
385         }
387         return io_done(io) && result;
390 bool
391 io_run_buf(const char **argv, char buf[], size_t bufsize)
393         struct io io;
395         return io_run(&io, IO_RD, NULL, argv) && io_read_buf(&io, buf, bufsize);
398 int
399 io_load(struct io *io, const char *separators,
400         io_read_fn read_property, void *data)
402         char *name;
403         int state = OK;
405         while (state == OK && (name = io_get(io, '\n', TRUE))) {
406                 char *value;
407                 size_t namelen;
408                 size_t valuelen;
410                 name = chomp_string(name);
411                 namelen = strcspn(name, separators);
413                 if (name[namelen]) {
414                         name[namelen] = 0;
415                         value = chomp_string(name + namelen + 1);
416                         valuelen = strlen(value);
418                 } else {
419                         value = "";
420                         valuelen = 0;
421                 }
423                 state = read_property(name, namelen, value, valuelen, data);
424         }
426         if (state != ERR && io_error(io))
427                 state = ERR;
428         io_done(io);
430         return state;
433 int
434 io_run_load(const char **argv, const char *separators,
435             io_read_fn read_property, void *data)
437         struct io io;
439         if (!io_run(&io, IO_RD, NULL, argv))
440                 return ERR;
441         return io_load(&io, separators, read_property, data);