PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tig-1.0/io.c

#
C | 579 lines | 449 code | 112 blank | 18 comment | 146 complexity | b4e1d157e10b41b7b756239b763d44a9 MD5 | raw file
Possible License(s): GPL-2.0
  1. /* Copyright (c) 2006-2012 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. */
  13. #include "tig.h"
  14. #include "io.h"
  15. static inline int
  16. get_arg_valuelen(const char *arg, bool *quoted)
  17. {
  18. if (*arg == '"' || *arg == '\'') {
  19. const char *end = *arg == '"' ? "\"" : "'";
  20. int valuelen = strcspn(arg + 1, end);
  21. if (quoted)
  22. *quoted = TRUE;
  23. return valuelen > 0 ? valuelen + 2 : strlen(arg);
  24. } else {
  25. return strcspn(arg, " \t");
  26. }
  27. }
  28. static bool
  29. split_argv_string(const char *argv[SIZEOF_ARG], int *argc, char *cmd, bool remove_quotes)
  30. {
  31. while (*cmd && *argc < SIZEOF_ARG) {
  32. bool quoted = FALSE;
  33. int valuelen = get_arg_valuelen(cmd, &quoted);
  34. bool advance = cmd[valuelen] != 0;
  35. int quote_offset = !!(quoted && remove_quotes);
  36. cmd[valuelen - quote_offset] = 0;
  37. argv[(*argc)++] = chomp_string(cmd + quote_offset);
  38. cmd = chomp_string(cmd + valuelen + advance);
  39. }
  40. if (*argc < SIZEOF_ARG)
  41. argv[*argc] = NULL;
  42. return *argc < SIZEOF_ARG;
  43. }
  44. bool
  45. argv_from_string_no_quotes(const char *argv[SIZEOF_ARG], int *argc, char *cmd)
  46. {
  47. return split_argv_string(argv, argc, cmd, TRUE);
  48. }
  49. bool
  50. argv_from_string(const char *argv[SIZEOF_ARG], int *argc, char *cmd)
  51. {
  52. return split_argv_string(argv, argc, cmd, FALSE);
  53. }
  54. bool
  55. argv_from_env(const char **argv, const char *name)
  56. {
  57. char *env = argv ? getenv(name) : NULL;
  58. int argc = 0;
  59. if (env && *env)
  60. env = strdup(env);
  61. return !env || argv_from_string(argv, &argc, env);
  62. }
  63. void
  64. argv_free(const char *argv[])
  65. {
  66. int argc;
  67. if (!argv)
  68. return;
  69. for (argc = 0; argv[argc]; argc++)
  70. free((void *) argv[argc]);
  71. argv[0] = NULL;
  72. }
  73. size_t
  74. argv_size(const char **argv)
  75. {
  76. int argc = 0;
  77. while (argv && argv[argc])
  78. argc++;
  79. return argc;
  80. }
  81. DEFINE_ALLOCATOR(argv_realloc, const char *, SIZEOF_ARG)
  82. bool
  83. argv_append(const char ***argv, const char *arg)
  84. {
  85. size_t argc = argv_size(*argv);
  86. if (!*arg && argc > 0)
  87. return TRUE;
  88. if (!argv_realloc(argv, argc, 2))
  89. return FALSE;
  90. (*argv)[argc++] = strdup(arg);
  91. (*argv)[argc] = NULL;
  92. return TRUE;
  93. }
  94. bool
  95. argv_append_array(const char ***dst_argv, const char *src_argv[])
  96. {
  97. int i;
  98. for (i = 0; src_argv && src_argv[i]; i++)
  99. if (!argv_append(dst_argv, src_argv[i]))
  100. return FALSE;
  101. return TRUE;
  102. }
  103. bool
  104. argv_copy(const char ***dst, const char *src[])
  105. {
  106. int argc;
  107. argv_free(*dst);
  108. for (argc = 0; src[argc]; argc++)
  109. if (!argv_append(dst, src[argc]))
  110. return FALSE;
  111. return TRUE;
  112. }
  113. /*
  114. * Encoding conversion.
  115. */
  116. struct encoding {
  117. struct encoding *next;
  118. iconv_t cd;
  119. char fromcode[1];
  120. };
  121. static struct encoding *encodings;
  122. struct encoding *
  123. encoding_open(const char *fromcode)
  124. {
  125. struct encoding *encoding;
  126. size_t len = strlen(fromcode);
  127. if (!*fromcode)
  128. return NULL;
  129. for (encoding = encodings; encoding; encoding = encoding->next) {
  130. if (!strcasecmp(encoding->fromcode, fromcode))
  131. return encoding;
  132. }
  133. encoding = calloc(1, sizeof(*encoding) + len);
  134. strncpy(encoding->fromcode, fromcode, len);
  135. encoding->cd = iconv_open(ENCODING_UTF8, fromcode);
  136. if (encoding->cd == ICONV_NONE) {
  137. free(encoding);
  138. return NULL;
  139. }
  140. encoding->next = encodings;
  141. encodings = encoding;
  142. return encoding;
  143. }
  144. char *
  145. encoding_convert(struct encoding *encoding, char *line)
  146. {
  147. static char out_buffer[BUFSIZ * 2];
  148. ICONV_CONST char *inbuf = line;
  149. size_t inlen = strlen(line) + 1;
  150. char *outbuf = out_buffer;
  151. size_t outlen = sizeof(out_buffer);
  152. size_t ret = iconv(encoding->cd, &inbuf, &inlen, &outbuf, &outlen);
  153. return (ret != (size_t) -1) ? out_buffer : line;
  154. }
  155. /*
  156. * Executing external commands.
  157. */
  158. static void
  159. io_init(struct io *io)
  160. {
  161. memset(io, 0, sizeof(*io));
  162. io->pipe = -1;
  163. }
  164. bool
  165. io_open(struct io *io, const char *fmt, ...)
  166. {
  167. char name[SIZEOF_STR] = "";
  168. int retval;
  169. io_init(io);
  170. FORMAT_BUFFER(name, sizeof(name), fmt, retval, FALSE);
  171. if (retval < 0) {
  172. io->error = ENAMETOOLONG;
  173. return FALSE;
  174. }
  175. io->pipe = *name ? open(name, O_RDONLY) : dup(STDIN_FILENO);
  176. if (io->pipe == -1)
  177. io->error = errno;
  178. return io->pipe != -1;
  179. }
  180. bool
  181. io_kill(struct io *io)
  182. {
  183. return io->pid == 0 || kill(io->pid, SIGKILL) != -1;
  184. }
  185. bool
  186. io_done(struct io *io)
  187. {
  188. pid_t pid = io->pid;
  189. if (io->pipe != -1)
  190. close(io->pipe);
  191. free(io->buf);
  192. io_init(io);
  193. while (pid > 0) {
  194. int status;
  195. pid_t waiting = waitpid(pid, &status, 0);
  196. if (waiting < 0) {
  197. if (errno == EINTR)
  198. continue;
  199. io->error = errno;
  200. return FALSE;
  201. }
  202. if (WEXITSTATUS(status)) {
  203. io->status = WEXITSTATUS(status);
  204. }
  205. return waiting == pid &&
  206. !WIFSIGNALED(status) &&
  207. !io->status;
  208. }
  209. return TRUE;
  210. }
  211. static int
  212. open_trace(int devnull, const char *argv[])
  213. {
  214. static const char *trace_file;
  215. if (!trace_file) {
  216. trace_file = getenv("TIG_TRACE");
  217. if (!trace_file)
  218. trace_file = "";
  219. }
  220. if (*trace_file) {
  221. int fd = open(trace_file, O_RDWR | O_CREAT | O_APPEND, 0666);
  222. int i;
  223. for (i = 0; argv[i]; i++) {
  224. if (write(fd, argv[i], strlen(argv[i])) == -1
  225. || write(fd, " ", 1) == -1)
  226. break;
  227. }
  228. if (argv[i] || write(fd, "\n", 1) == -1) {
  229. close(fd);
  230. return devnull;
  231. }
  232. return fd;
  233. }
  234. return devnull;
  235. }
  236. bool
  237. io_run(struct io *io, enum io_type type, const char *dir, const char *argv[], ...)
  238. {
  239. int pipefds[2] = { -1, -1 };
  240. va_list args;
  241. io_init(io);
  242. if (dir && !strcmp(dir, argv[0]))
  243. return io_open(io, "%s%s", dir, argv[1]);
  244. if ((type == IO_RD || type == IO_WR) && pipe(pipefds) < 0) {
  245. io->error = errno;
  246. return FALSE;
  247. } else if (type == IO_AP) {
  248. va_start(args, argv);
  249. pipefds[1] = va_arg(args, int);
  250. va_end(args);
  251. }
  252. if ((io->pid = fork())) {
  253. if (io->pid == -1)
  254. io->error = errno;
  255. if (pipefds[!(type == IO_WR)] != -1)
  256. close(pipefds[!(type == IO_WR)]);
  257. if (io->pid != -1) {
  258. io->pipe = pipefds[!!(type == IO_WR)];
  259. return TRUE;
  260. }
  261. } else {
  262. if (type != IO_FG) {
  263. int devnull = open("/dev/null", O_RDWR);
  264. int readfd = type == IO_WR ? pipefds[0] : devnull;
  265. int writefd = (type == IO_RD || type == IO_AP)
  266. ? pipefds[1] : devnull;
  267. int errorfd = open_trace(devnull, argv);
  268. dup2(readfd, STDIN_FILENO);
  269. dup2(writefd, STDOUT_FILENO);
  270. dup2(errorfd, STDERR_FILENO);
  271. if (devnull != errorfd)
  272. close(errorfd);
  273. close(devnull);
  274. if (pipefds[0] != -1)
  275. close(pipefds[0]);
  276. if (pipefds[1] != -1)
  277. close(pipefds[1]);
  278. }
  279. if (dir && *dir && chdir(dir) == -1)
  280. exit(errno);
  281. execvp(argv[0], (char *const*) argv);
  282. exit(errno);
  283. }
  284. if (pipefds[!!(type == IO_WR)] != -1)
  285. close(pipefds[!!(type == IO_WR)]);
  286. return FALSE;
  287. }
  288. bool
  289. io_complete(enum io_type type, const char **argv, const char *dir, int fd)
  290. {
  291. struct io io;
  292. return io_run(&io, type, dir, argv, fd) && io_done(&io);
  293. }
  294. bool
  295. io_run_bg(const char **argv)
  296. {
  297. return io_complete(IO_BG, argv, NULL, -1);
  298. }
  299. bool
  300. io_run_fg(const char **argv, const char *dir)
  301. {
  302. return io_complete(IO_FG, argv, dir, -1);
  303. }
  304. bool
  305. io_run_append(const char **argv, int fd)
  306. {
  307. return io_complete(IO_AP, argv, NULL, fd);
  308. }
  309. bool
  310. io_eof(struct io *io)
  311. {
  312. return io->eof;
  313. }
  314. int
  315. io_error(struct io *io)
  316. {
  317. return io->error;
  318. }
  319. char *
  320. io_strerror(struct io *io)
  321. {
  322. return strerror(io->error);
  323. }
  324. bool
  325. io_can_read(struct io *io, bool can_block)
  326. {
  327. struct timeval tv = { 0, 500 };
  328. fd_set fds;
  329. FD_ZERO(&fds);
  330. FD_SET(io->pipe, &fds);
  331. return select(io->pipe + 1, &fds, NULL, NULL, can_block ? NULL : &tv) > 0;
  332. }
  333. ssize_t
  334. io_read(struct io *io, void *buf, size_t bufsize)
  335. {
  336. do {
  337. ssize_t readsize = read(io->pipe, buf, bufsize);
  338. if (readsize < 0 && (errno == EAGAIN || errno == EINTR))
  339. continue;
  340. else if (readsize == -1)
  341. io->error = errno;
  342. else if (readsize == 0)
  343. io->eof = 1;
  344. return readsize;
  345. } while (1);
  346. }
  347. DEFINE_ALLOCATOR(io_realloc_buf, char, BUFSIZ)
  348. char *
  349. io_get(struct io *io, int c, bool can_read)
  350. {
  351. char *eol;
  352. ssize_t readsize;
  353. while (TRUE) {
  354. if (io->bufsize > 0) {
  355. eol = memchr(io->bufpos, c, io->bufsize);
  356. if (eol) {
  357. char *line = io->bufpos;
  358. *eol = 0;
  359. io->bufpos = eol + 1;
  360. io->bufsize -= io->bufpos - line;
  361. return line;
  362. }
  363. }
  364. if (io_eof(io)) {
  365. if (io->bufsize) {
  366. io->bufpos[io->bufsize] = 0;
  367. io->bufsize = 0;
  368. return io->bufpos;
  369. }
  370. return NULL;
  371. }
  372. if (!can_read)
  373. return NULL;
  374. if (io->bufsize > 0 && io->bufpos > io->buf)
  375. memmove(io->buf, io->bufpos, io->bufsize);
  376. if (io->bufalloc == io->bufsize) {
  377. if (!io_realloc_buf(&io->buf, io->bufalloc, BUFSIZ))
  378. return NULL;
  379. io->bufalloc += BUFSIZ;
  380. }
  381. io->bufpos = io->buf;
  382. readsize = io_read(io, io->buf + io->bufsize, io->bufalloc - io->bufsize);
  383. if (io_error(io))
  384. return NULL;
  385. io->bufsize += readsize;
  386. }
  387. }
  388. bool
  389. io_write(struct io *io, const void *buf, size_t bufsize)
  390. {
  391. size_t written = 0;
  392. while (!io_error(io) && written < bufsize) {
  393. ssize_t size;
  394. size = write(io->pipe, buf + written, bufsize - written);
  395. if (size < 0 && (errno == EAGAIN || errno == EINTR))
  396. continue;
  397. else if (size == -1)
  398. io->error = errno;
  399. else
  400. written += size;
  401. }
  402. return written == bufsize;
  403. }
  404. bool
  405. io_printf(struct io *io, const char *fmt, ...)
  406. {
  407. char buf[SIZEOF_STR] = "";
  408. int retval;
  409. FORMAT_BUFFER(buf, sizeof(buf), fmt, retval, FALSE);
  410. if (retval < 0) {
  411. io->error = ENAMETOOLONG;
  412. return FALSE;
  413. }
  414. return io_write(io, buf, retval);
  415. }
  416. bool
  417. io_read_buf(struct io *io, char buf[], size_t bufsize)
  418. {
  419. char *result = io_get(io, '\n', TRUE);
  420. if (result) {
  421. result = chomp_string(result);
  422. string_ncopy_do(buf, bufsize, result, strlen(result));
  423. }
  424. return io_done(io) && result;
  425. }
  426. bool
  427. io_run_buf(const char **argv, char buf[], size_t bufsize)
  428. {
  429. struct io io;
  430. return io_run(&io, IO_RD, NULL, argv) && io_read_buf(&io, buf, bufsize);
  431. }
  432. int
  433. io_load(struct io *io, const char *separators,
  434. io_read_fn read_property, void *data)
  435. {
  436. char *name;
  437. int state = OK;
  438. while (state == OK && (name = io_get(io, '\n', TRUE))) {
  439. char *value;
  440. size_t namelen;
  441. size_t valuelen;
  442. name = chomp_string(name);
  443. namelen = strcspn(name, separators);
  444. if (name[namelen]) {
  445. name[namelen] = 0;
  446. value = chomp_string(name + namelen + 1);
  447. valuelen = strlen(value);
  448. } else {
  449. value = "";
  450. valuelen = 0;
  451. }
  452. state = read_property(name, namelen, value, valuelen, data);
  453. }
  454. if (state != ERR && io_error(io))
  455. state = ERR;
  456. io_done(io);
  457. return state;
  458. }
  459. int
  460. io_run_load(const char **argv, const char *separators,
  461. io_read_fn read_property, void *data)
  462. {
  463. struct io io;
  464. if (!io_run(&io, IO_RD, NULL, argv))
  465. return ERR;
  466. return io_load(&io, separators, read_property, data);
  467. }