12 #include <sys/ioctl.h>
15 #include <sys/types.h>
17 #include <sys/socket.h>
36 vfprintf (stderr,
msg, args);
40 fprintf (stderr,
": %s", strerror (errno));
53 struct termios termios;
54 if (tcgetattr (fd, &termios) < 0)
56 termios.c_lflag &= ~(ICANON | ECHO);
57 termios.c_cc[VMIN] = vmin;
58 termios.c_cc[VTIME] = vtime;
59 if (tcsetattr (fd, TCSANOW, &termios) < 0)
69 int flags = fcntl (fd, F_GETFL);
76 if (fcntl (fd, F_SETFL, flags) < 0)
86 handle_error (ssize_t retval,
int *fd,
bool fd_is_sock,
const char *call)
114 struct pipe pipes[2];
129 memset (pipes, 0,
sizeof pipes);
135 while (pipes[0].in != -1 || pipes[1].in != -1
136 || (pipes[1].size && pipes[1].out != -1))
138 fd_set read_fds, write_fds;
144 FD_ZERO (&write_fds);
145 for (i = 0; i < 2; i++)
147 struct pipe *p = &pipes[i];
152 if (i == 0 && !pipes[1].active)
155 if (p->in != -1 && p->size + p->ofs <
sizeof p->buf)
156 FD_SET (p->in, &read_fds);
157 if (p->out != -1 && p->size > 0)
158 FD_SET (p->out, &write_fds);
160 sigemptyset (&empty_set);
161 retval = pselect (FD_SETSIZE, &read_fds, &write_fds,
NULL,
NULL,
168 struct pipe *p = &pipes[1];
179 n =
write (p->out, p->buf + p->ofs, p->size);
189 p->size = n =
read (p->in, p->buf,
sizeof p->buf);
197 for (i = 0; i < 2; i++)
199 struct pipe *p = &pipes[i];
200 if (p->in != -1 && FD_ISSET (p->in, &read_fds))
202 ssize_t n =
read (p->in, p->buf + p->ofs + p->size,
203 sizeof p->buf - p->ofs - p->size);
208 if (p->size == BUFSIZ && p->ofs != 0)
210 memmove (p->buf, p->buf + p->ofs, p->size);
214 else if (!
handle_error (n, &p->in, p->in == sock,
"read"))
217 if (p->out != -1 && FD_ISSET (p->out, &write_fds))
219 ssize_t n =
write (p->out, p->buf + p->ofs, p->size);
227 else if (!
handle_error (n, &p->out, p->out == sock,
"write"))
244 struct itimerval zero_itimerval;
245 struct sockaddr_un sun;
246 sigset_t sigchld_set;
252 "usage: squish-unix SOCKET COMMAND [ARG]...\n"
253 "Squishes both stdin and stdout into a single Unix domain\n"
254 "socket named SOCKET, and runs COMMAND as a subprocess.\n");
259 sock = socket (PF_LOCAL, SOCK_STREAM, 0);
264 sun.sun_family = AF_LOCAL;
265 strncpy (sun.sun_path, argv[1],
sizeof sun.sun_path);
266 sun.sun_path[
sizeof sun.sun_path - 1] =
'\0';
267 if (unlink (sun.sun_path) < 0 && errno != ENOENT)
269 if (bind (sock, (
struct sockaddr *) &sun,
270 (
offsetof (
struct sockaddr_un, sun_path)
271 +
strlen (sun.sun_path) + 1)) < 0)
275 if (listen (sock, 1) < 0)
279 sigemptyset (&sigchld_set);
280 sigaddset (&sigchld_set, SIGCHLD);
281 if (sigprocmask (SIG_BLOCK, &sigchld_set,
NULL) < 0)
289 memset (&zero_itimerval, 0,
sizeof zero_itimerval);
290 if (setitimer (ITIMER_VIRTUAL, &zero_itimerval,
NULL) < 0)
309 FD_SET (sock, &read_fds);
310 sigemptyset (&empty_set);
311 retval = pselect (sock + 1, &read_fds,
NULL,
NULL,
NULL, &empty_set);
333 if (
close (sock) < 0)
335 execvp (argv[2], argv + 2);