#include <libnet.h>
#include <sys/poll.h>
+int copy_data(int fromfd, int tofd, int events)
+{
+ char buf[16384];
+ int open = 1;
+
+ if (events & POLLIN)
+ {
+ long nread;
+ if ((nread = read(fromfd, buf, sizeof(buf))) > 0)
+ {
+ write(tofd, buf, nread);
+ }
+ else
+ {
+ open = 0;
+ }
+ }
+
+ if (!open || (events & (POLLHUP|POLLERR)))
+ {
+ perror("close():");
+ close(fromfd);
+ open = 0;
+ }
+
+ return open;
+}
+
int main(int argc, char** argv)
{
if (argc < 2)
return 1;
}
- int sockfd = netdial(argv[1]);
-
- char buf[8192];
- struct pollfd fds[] = {
- { .fd = sockfd, .events = POLLIN },
- { .fd = STDIN_FILENO, .events = POLLIN },
- };
-
- while(1)
+ int running = 1;
+ int sockfd = netdial(argv[1]);
+ int cmdinfd = STDIN_FILENO;
+ int cmdoutfd = STDOUT_FILENO;
+ if (argc > 2)
{
- if (poll(fds, nelem(fds), -1) < 0)
- {
- fatal("poll():");
- }
-
- if (fds[0].revents & POLLIN)
+ cmdinfd = fork_exec(&argv[2]);
+ cmdoutfd = cmdinfd;
+ if (cmdinfd < 0)
{
- write(fds[1].fd, buf, read(fds[0].fd, buf, sizeof(buf)));
- fds[0].revents = 0;
+ fatal("fork_exec():");
}
+ }
- if (fds[1].revents & POLLIN)
+ while (running)
+ {
+ struct pollfd fds[] = {
+ { .fd = sockfd, .events = POLLIN },
+ { .fd = cmdinfd, .events = POLLIN },
+ };
+ if (poll(fds, nelem(fds), -1) < 0)
{
- write(fds[0].fd, buf, read(fds[1].fd, buf, sizeof(buf)));
- fds[0].revents = 0;
+ fatal("poll():");
}
+ running = running && copy_data(sockfd, cmdoutfd, fds[0].revents);
+ running = running && copy_data(cmdinfd, sockfd, fds[1].revents);
}
close(sockfd);
typedef char unique_id[( expr )?1:-1]
#endif
-
-
void fatal(const char* fmt, ...);
void warn(const char* fmt, ...);
void esignal(int sig, void (*func)(int));
FILE* efopen(const char* filename, const char* mode);
char* efreadline(FILE* input);
char* estrdup(const char *s);
+int fork_exec(char** cmd);
--- /dev/null
+#include <liba.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+int fork_exec(char** cmd)
+{
+ int pid, fds[2] = {-1,-1};
+ /* create the sockets */
+ if (!socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
+ {
+ /* create the process */
+ if ((pid = fork()) < 0)
+ {
+ close(fds[0]), close(fds[1]), fds[0] = -1;
+ }
+ else if (0 == pid)
+ {
+ /* redirect child process's io to the pipes */
+ if ((dup2(fds[1], 0) < 0) || (dup2(fds[1], 1) < 0) || (dup2(fds[1], 2) < 0))
+ {
+ fatal("failed to pipe");
+ }
+ /* execute the process */
+ close(fds[0]);
+ exit(execvp(cmd[0], cmd));
+ }
+ else
+ {
+ close(fds[1]);
+ fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL, 0) | O_NONBLOCK);
+ }
+ }
+ return fds[0];
+}