regex: updates from neatvi
[neatmail.git] / util.c
blob147a16fe216f9a8493ad4ce176de04526a951022
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <poll.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/wait.h>
9 #include "mail.h"
11 long xread(int fd, void *buf, long len)
13 int nr = 0;
14 while (nr < len) {
15 int ret = read(fd, buf + nr, len - nr);
16 if (ret == -1 && (errno == EAGAIN || errno == EINTR))
17 continue;
18 if (ret <= 0)
19 break;
20 nr += ret;
22 return nr;
25 long xwrite(int fd, void *buf, long len)
27 int nw = 0;
28 while (nw < len) {
29 int ret = write(fd, buf + nw, len - nw);
30 if (ret == -1 && (errno == EAGAIN || errno == EINTR))
31 continue;
32 if (ret < 0)
33 break;
34 nw += ret;
36 return nw;
39 static int xpipe_make(char **argv, int *ifd, int *ofd)
41 int pid;
42 int pipefds0[2];
43 int pipefds1[2];
44 if (ifd)
45 pipe(pipefds0);
46 if (ofd)
47 pipe(pipefds1);
48 if (!(pid = fork())) {
49 if (ifd) { /* setting up stdin */
50 close(0);
51 dup(pipefds0[0]);
52 close(pipefds0[1]);
53 close(pipefds0[0]);
55 if (ofd) { /* setting up stdout */
56 close(1);
57 dup(pipefds1[1]);
58 close(pipefds1[0]);
59 close(pipefds1[1]);
61 execvp(argv[0], argv);
62 exit(1);
64 if (ifd)
65 close(pipefds0[0]);
66 if (ofd)
67 close(pipefds1[1]);
68 if (pid < 0) {
69 if (ifd)
70 close(pipefds0[1]);
71 if (ofd)
72 close(pipefds1[0]);
73 return -1;
75 if (ifd)
76 *ifd = pipefds0[1];
77 if (ofd)
78 *ofd = pipefds1[0];
79 return pid;
82 int xpipe(char *cmd, char *ibuf, long ilen, char **obuf, long *olen)
84 char *argv[] = {"/bin/sh", "-c", cmd, NULL};
85 struct pollfd fds[2];
86 struct sbuf *sb = NULL;
87 char buf[512];
88 int ifd = -1, ofd = -1;
89 int nw = 0;
90 int pid = xpipe_make(argv, ibuf ? &ifd : NULL, obuf ? &ofd : NULL);
91 if (pid <= 0)
92 return 1;
93 if (obuf)
94 sb = sbuf_make();
95 fcntl(ifd, F_SETFL, fcntl(ifd, F_GETFL, 0) | O_NONBLOCK);
96 fds[0].fd = ofd;
97 fds[0].events = POLLIN;
98 fds[1].fd = ifd;
99 fds[1].events = POLLOUT;
100 while ((fds[0].fd >= 0 || fds[1].fd >= 0) && poll(fds, 2, 200) >= 0) {
101 if (fds[0].revents & POLLIN) {
102 int ret = read(fds[0].fd, buf, sizeof(buf));
103 if (ret > 0)
104 sbuf_mem(sb, buf, ret);
105 if (ret <= 0) {
106 close(fds[0].fd);
107 fds[0].fd = -1;
109 } else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
110 fds[0].fd = -1;
112 if (fds[1].revents & POLLOUT) {
113 int ret = write(fds[1].fd, ibuf + nw, ilen - nw);
114 if (ret > 0)
115 nw += ret;
116 if (ret <= 0 || nw == ilen) {
117 close(fds[1].fd);
118 fds[1].fd = -1;
120 } else if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
121 fds[1].fd = -1;
124 close(ifd);
125 close(ofd);
126 waitpid(pid, NULL, 0);
127 if (obuf) {
128 *olen = sbuf_len(sb);
129 *obuf = sbuf_done(sb);
131 return 0;