stag: allow multiple tag patterns for each extension
[neatvi.git] / cmd.c
blob17634ef0a99068d0c85036464ba872071f7b898c
1 #include <fcntl.h>
2 #include <poll.h>
3 #include <signal.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/wait.h>
9 #include "vi.h"
11 static int cmd_make(char **argv, int *ifd, int *ofd)
13 int pid;
14 int pipefds0[2];
15 int pipefds1[2];
16 if (ifd)
17 pipe(pipefds0);
18 if (ofd)
19 pipe(pipefds1);
20 if (!(pid = fork())) {
21 if (ifd) { /* setting up stdin */
22 close(0);
23 dup(pipefds0[0]);
24 close(pipefds0[1]);
25 close(pipefds0[0]);
27 if (ofd) { /* setting up stdout and stderr */
28 close(1);
29 dup(pipefds1[1]);
30 close(2);
31 dup(pipefds1[1]);
32 close(pipefds1[0]);
33 close(pipefds1[1]);
35 execvp(argv[0], argv);
36 exit(1);
38 if (ifd)
39 close(pipefds0[0]);
40 if (ofd)
41 close(pipefds1[1]);
42 if (pid < 0) {
43 if (ifd)
44 close(pipefds0[1]);
45 if (ofd)
46 close(pipefds1[0]);
47 return -1;
49 if (ifd)
50 *ifd = pipefds0[1];
51 if (ofd)
52 *ofd = pipefds1[0];
53 return pid;
57 * Execute a shell command.
59 * If ibuf is given, it is passed as standard input to the process.
60 * Otherwise, the process reads from the terminal.
62 * If oproc is 0, the process writes directly to the terminal. If it
63 * is 1, process' output is saved and returned. If it is 2, in addition
64 * to returning the output, it is written to the terminal.
66 char *cmd_pipe(char *cmd, char *ibuf, int oproc)
68 char *argv[] = {"/bin/sh", "-c", cmd, NULL};
69 struct pollfd fds[3];
70 struct sbuf *sb = NULL;
71 char buf[512];
72 int ifd = -1, ofd = -1;
73 int slen = ibuf != NULL ? strlen(ibuf) : 0;
74 int nw = 0;
75 int pid = cmd_make(argv, ibuf != NULL ? &ifd : NULL, oproc ? &ofd : NULL);
76 if (pid <= 0)
77 return NULL;
78 if (oproc)
79 sb = sbuf_make();
80 if (ibuf == NULL) {
81 signal(SIGINT, SIG_IGN);
82 term_done();
84 fcntl(ifd, F_SETFL, fcntl(ifd, F_GETFL, 0) | O_NONBLOCK);
85 fds[0].fd = ofd;
86 fds[0].events = POLLIN;
87 fds[1].fd = ifd;
88 fds[1].events = POLLOUT;
89 fds[2].fd = ibuf != NULL ? 0 : -1;
90 fds[2].events = POLLIN;
91 while ((fds[0].fd >= 0 || fds[1].fd >= 0) && poll(fds, 3, 200) >= 0) {
92 if (fds[0].revents & POLLIN) {
93 int ret = read(fds[0].fd, buf, sizeof(buf));
94 if (ret > 0 && oproc == 2)
95 write(1, buf, ret);
96 if (ret > 0)
97 sbuf_mem(sb, buf, ret);
98 if (ret <= 0) {
99 close(fds[0].fd);
100 fds[0].fd = -1;
102 } else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
103 close(fds[0].fd);
104 fds[0].fd = -1;
106 if (fds[1].revents & POLLOUT) {
107 int ret = write(fds[1].fd, ibuf + nw, slen - nw);
108 if (ret > 0)
109 nw += ret;
110 if (ret <= 0 || nw == slen) {
111 close(fds[1].fd);
112 fds[1].fd = -1;
114 } else if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
115 close(fds[1].fd);
116 fds[1].fd = -1;
118 if (fds[2].revents & POLLIN) {
119 int ret = read(fds[2].fd, buf, sizeof(buf));
120 int i;
121 for (i = 0; i < ret; i++)
122 if ((unsigned char) buf[i] == TK_CTL('c'))
123 kill(pid, SIGINT);
124 } else if (fds[2].revents & (POLLERR | POLLHUP | POLLNVAL)) {
125 fds[2].fd = -1;
128 close(fds[0].fd);
129 close(fds[1].fd);
130 waitpid(pid, NULL, 0);
131 if (ibuf == NULL) {
132 term_init();
133 signal(SIGINT, SIG_DFL);
135 if (oproc)
136 return sbuf_done(sb);
137 return NULL;
140 int cmd_exec(char *cmd)
142 cmd_pipe(cmd, NULL, 0);
143 return 0;