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 }