tcmd.c - neatvi - [fork] simple vi-type editor with UTF-8 support
(HTM) git clone git://src.adamsgaard.dk/neatvi
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
tcmd.c (2808B)
---
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"
10
11 static int cmd_make(char **argv, int *ifd, int *ofd)
12 {
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]);
26 }
27 if (ofd) { /* setting up stdout */
28 close(1);
29 dup(pipefds1[1]);
30 close(pipefds1[0]);
31 close(pipefds1[1]);
32 }
33 execvp(argv[0], argv);
34 exit(1);
35 }
36 if (ifd)
37 close(pipefds0[0]);
38 if (ofd)
39 close(pipefds1[1]);
40 if (pid < 0) {
41 if (ifd)
42 close(pipefds0[1]);
43 if (ofd)
44 close(pipefds1[0]);
45 return -1;
46 }
47 if (ifd)
48 *ifd = pipefds0[1];
49 if (ofd)
50 *ofd = pipefds1[0];
51 return pid;
52 }
53
54 /* execute a command; process input if iproc and process output if oproc */
55 char *cmd_pipe(char *cmd, char *ibuf, int iproc, int oproc)
56 {
57 char *argv[] = {"/bin/sh", "-c", cmd, NULL};
58 struct pollfd fds[3];
59 struct sbuf *sb = NULL;
60 char buf[512];
61 int ifd = -1, ofd = -1;
62 int slen = iproc ? strlen(ibuf) : 0;
63 int nw = 0;
64 int pid = cmd_make(argv, iproc ? &ifd : NULL, oproc ? &ofd : NULL);
65 if (pid <= 0)
66 return NULL;
67 if (oproc)
68 sb = sbuf_make();
69 if (!iproc) {
70 signal(SIGINT, SIG_IGN);
71 term_done();
72 }
73 fcntl(ifd, F_SETFL, fcntl(ifd, F_GETFL, 0) | O_NONBLOCK);
74 fds[0].fd = ofd;
75 fds[0].events = POLLIN;
76 fds[1].fd = ifd;
77 fds[1].events = POLLOUT;
78 fds[2].fd = iproc ? 0 : -1;
79 fds[2].events = POLLIN;
80 while ((fds[0].fd >= 0 || fds[1].fd >= 0) && poll(fds, 3, 200) >= 0) {
81 if (fds[0].revents & POLLIN) {
82 int ret = read(fds[0].fd, buf, sizeof(buf));
83 if (ret > 0)
84 sbuf_mem(sb, buf, ret);
85 if (ret <= 0) {
86 close(fds[0].fd);
87 fds[0].fd = -1;
88 }
89 continue;
90 }
91 if (fds[1].revents & POLLOUT) {
92 int ret = write(fds[1].fd, ibuf + nw, slen - nw);
93 if (ret > 0)
94 nw += ret;
95 if (ret <= 0 || nw == slen) {
96 close(fds[1].fd);
97 fds[1].fd = -1;
98 }
99 continue;
100 }
101 if (fds[2].revents & POLLIN) {
102 int ret = read(fds[2].fd, buf, sizeof(buf));
103 int i;
104 for (i = 0; i < ret; i++)
105 if ((unsigned char) buf[i] == TK_CTL('c'))
106 kill(pid, SIGINT);
107 }
108 if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
109 close(fds[0].fd);
110 fds[0].fd = -1;
111 }
112 if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
113 close(fds[1].fd);
114 fds[1].fd = -1;
115 }
116 if (fds[2].revents & (POLLERR | POLLHUP | POLLNVAL))
117 fds[2].fd = -1;
118 }
119 close(fds[0].fd);
120 close(fds[1].fd);
121 waitpid(pid, NULL, 0);
122 if (!iproc) {
123 term_init();
124 signal(SIGINT, SIG_DFL);
125 }
126 if (oproc)
127 return sbuf_done(sb);
128 return NULL;
129 }
130
131 int cmd_exec(char *cmd)
132 {
133 cmd_pipe(cmd, NULL, 0, 0);
134 return 0;
135 }