ex: preserve cursor position in :g
[neatvi.git] / cmd.c
blob851e6cdc89c07ba9dd5965bcb24df48d22d4516c
1 #include <poll.h>
2 #include <signal.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <sys/wait.h>
8 #include "vi.h"
10 static int cmd_make(char **argv, int *ifd, int *ofd)
12 int pid;
13 int pipefds0[2];
14 int pipefds1[2];
15 if (ifd)
16 pipe(pipefds0);
17 if (ofd)
18 pipe(pipefds1);
19 if (!(pid = fork())) {
20 if (ifd) { /* setting up stdin */
21 close(0);
22 dup(pipefds0[0]);
23 close(pipefds0[1]);
24 close(pipefds0[0]);
26 if (ofd) { /* setting up stdout */
27 close(1);
28 dup(pipefds1[1]);
29 close(pipefds1[0]);
30 close(pipefds1[1]);
32 execvp(argv[0], argv);
33 exit(1);
35 if (ifd)
36 close(pipefds0[0]);
37 if (ofd)
38 close(pipefds1[1]);
39 if (pid < 0) {
40 if (ifd)
41 close(pipefds0[1]);
42 if (ofd)
43 close(pipefds1[0]);
44 return -1;
46 if (ifd)
47 *ifd = pipefds0[1];
48 if (ofd)
49 *ofd = pipefds1[0];
50 return pid;
53 /* execute a command; process input if iproc and process output if oproc */
54 char *cmd_pipe(char *cmd, char *ibuf, int iproc, int oproc)
56 char *argv[] = {"/bin/sh", "-c", cmd, NULL};
57 struct pollfd fds[3];
58 struct sbuf *sb = NULL;
59 char buf[512];
60 int ifd = -1, ofd = -1;
61 int slen = iproc ? strlen(ibuf) : 0;
62 int nw = 0;
63 int pid = cmd_make(argv, iproc ? &ifd : NULL, oproc ? &ofd : NULL);
64 if (pid <= 0)
65 return NULL;
66 if (oproc)
67 sb = sbuf_make();
68 if (!iproc) {
69 signal(SIGINT, SIG_IGN);
70 term_done();
72 fds[0].fd = ofd;
73 fds[0].events = POLLIN;
74 fds[1].fd = ifd;
75 fds[1].events = POLLOUT;
76 fds[2].fd = iproc ? 0 : -1;
77 fds[2].events = POLLIN;
78 while ((fds[0].fd >= 0 || fds[1].fd >= 0) && poll(fds, 3, 200) >= 0) {
79 if (fds[0].revents & POLLIN) {
80 int ret = read(fds[0].fd, buf, sizeof(buf));
81 if (ret > 0)
82 sbuf_mem(sb, buf, ret);
83 if (ret < 0)
84 close(fds[0].fd);
85 } else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
86 fds[0].fd = -1;
88 if (fds[1].revents & POLLOUT) {
89 int ret = write(fds[1].fd, ibuf + nw, slen - nw);
90 if (ret > 0)
91 nw += ret;
92 if (ret <= 0 || nw == slen)
93 close(fds[1].fd);
94 } else if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
95 fds[1].fd = -1;
97 if (fds[2].revents & POLLIN) {
98 int ret = read(fds[2].fd, buf, sizeof(buf));
99 int i;
100 for (i = 0; i < ret; i++)
101 if ((unsigned char) buf[i] == TK_CTL('c'))
102 kill(pid, SIGINT);
103 } else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
104 fds[2].fd = -1;
107 close(ifd);
108 close(ofd);
109 waitpid(pid, NULL, 0);
110 if (!iproc) {
111 term_init();
112 signal(SIGINT, SIG_DFL);
114 if (oproc)
115 return sbuf_done(sb);
116 return NULL;
119 int cmd_exec(char *cmd)
121 cmd_pipe(cmd, NULL, 0, 0);
122 return 0;