s6

Mirror/fork of https://skarnet.org/software/s6/
git clone https://ccx.te2000.cz/git/s6
Log | Files | Refs | README | LICENSE

commit c7f5b86a804ae16ab3a4bcda9593a49bce81791c
parent f72709512d2412c417c15d2a513d3ac1ec342718
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date:   Thu,  9 Feb 2023 15:45:54 +0000

 Autodetect socket endpoints in s6-ioconnect, deprecate -0167

Signed-off-by: Laurent Bercot <ska@appnovation.com>

Diffstat:
Mdoc/s6-ioconnect.html | 22+++++++---------------
Msrc/conn-tools/s6-ioconnect.c | 45++++++++++++++++++++++++++++-----------------
2 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/doc/s6-ioconnect.html b/doc/s6-ioconnect.html @@ -26,7 +26,7 @@ between two sets of open file descriptors. <h2> Interface </h2> <pre> - s6-ioconnect [ -t <em>millisecs</em> ] [ -r <em>fdr</em> ] [ -w <em>fdw</em> ] [ -0 ] [ -1 ] [ -6 ] [ -7 ] + s6-ioconnect [ -t <em>millisecs</em> ] [ -r <em>fdr</em> ] [ -w <em>fdw</em> ] </pre> <ul> @@ -49,25 +49,17 @@ closes the connection on both ends and exits 1. By default, "remote" reading instead of fd 6. </li> <li> <tt>-w&nbsp;<em>fdw</em></tt>&nbsp;: Use fd <em>fdw</em> for "remote" writing instead of fd 7. </li> - <li> <tt>-0</tt>: assume stdin is a socket and needs to be shut down -for reading after an EOF. </li> - <li> <tt>-1</tt>: assume stdout is a socket and needs to be shut down -for writing to correctly transmit an EOF. </li> - <li> <tt>-6</tt>: assume the remote reading fd is a socket and needs to be shut down -for reading after an EOF. </li> - <li> <tt>-7</tt>: assume the remote writing fd is a socket and needs to be shut down -for writing to correctly transmit an EOF. </li> + <li> The <tt>-0</tt>, <tt>-1</tt>, <tt>-6</tt> and <tt>-7</tt> options +are still recognized for compatibility, but do nothing; they are +deprecated. They were previously used to tell +s6-ioconnect that the local reading, local writing, remote reading and +remote writing endpoints, respectively, were sockets &mdash; but this is +now autodetected. </li> </ul> <h2> Notes </h2> <ul> - <li> Transmitting EOF across full-duplex sockets -<a href="https://cr.yp.to/tcpip/twofd.html">is ugly</a>. The right thing -in every case cannot be automatically determined, so it is up to the user -to mention that a socket must be shut down. Most of the time, though, -shutting down sockets after EOF <em>is</em> the right thing to do, so -<tt>s6-ioconnect -67</tt> should be the common use case. </li> <li> The point of s6-ioconnect is to be used together with <a href="//skarnet.org/software/s6-networking/s6-tcpclient.html">s6-tcpclient</a> or <a href="s6-ipcclient.html">s6-ipcclient</a> to establish a full- diff --git a/src/conn-tools/s6-ioconnect.c b/src/conn-tools/s6-ioconnect.c @@ -2,6 +2,7 @@ #include <errno.h> #include <signal.h> +#include <sys/stat.h> #include <skalibs/types.h> #include <skalibs/allreadwrite.h> @@ -15,7 +16,7 @@ #include <skalibs/iopause.h> #include <skalibs/djbunix.h> -#define USAGE "s6-ioconnect [ -t timeout ] [ -r fdr ] [ -w fdw ] [ -0 ] [ -1 ] [ -6 ] [ -7 ]" +#define USAGE "s6-ioconnect [ -t timeout ] [ -r fdr ] [ -w fdw ]" #define dieusage() strerr_dieusage(100, USAGE) #define BSIZE 8192 @@ -32,12 +33,12 @@ static char buf[2][BSIZE] = { { '\0' }, { '\0' } } ; static ioblah a[2][2] = { { - { .b = BUFFER_INIT(&buffer_read, 0, buf[0], BSIZE), .xindex = 5, .flagsocket = 0 }, - { .b = BUFFER_INIT(&buffer_write, 7, buf[0], BSIZE), .xindex = 5, .flagsocket = 0 } + { .b = BUFFER_INIT(&buffer_read, 0, buf[0], BSIZE), .xindex = 5 }, + { .b = BUFFER_INIT(&buffer_write, 7, buf[0], BSIZE), .xindex = 5 } }, { - { .b = BUFFER_INIT(&buffer_read, 6, buf[1], BSIZE), .xindex = 5, .flagsocket = 0 }, - { .b = BUFFER_INIT(&buffer_write, 1, buf[1], BSIZE), .xindex = 5, .flagsocket = 0 } + { .b = BUFFER_INIT(&buffer_read, 6, buf[1], BSIZE), .xindex = 5 }, + { .b = BUFFER_INIT(&buffer_write, 1, buf[1], BSIZE), .xindex = 5 } } } ; static iopause_fd x[5] = { [0] = { .fd = -1, .events = IOPAUSE_READ } } ; @@ -99,10 +100,10 @@ int main (int argc, char const *const *argv) if (opt < 0) break ; switch (opt) { - case '0' : a[0][0].flagsocket = 1 ; break ; - case '1' : a[1][1].flagsocket = 1 ; break ; - case '6' : a[1][0].flagsocket = 1 ; break ; - case '7' : a[0][1].flagsocket = 1 ; break ; + case '0' : break ; /* these options are deprecated */ + case '1' : break ; /* only there for compatibility */ + case '6' : break ; /* flagsocket is autodetected now */ + case '7' : break ; case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; case 'r' : if (!int0_scan(l.arg, &buffer_fd(&a[1][0].b))) dieusage() ; break ; case 'w' : if (!int0_scan(l.arg, &buffer_fd(&a[0][1].b))) dieusage() ; break ; @@ -113,14 +114,24 @@ int main (int argc, char const *const *argv) argc -= l.ind ; argv += l.ind ; } if ((buffer_fd(&a[0][1].b) < 3) || (buffer_fd(&a[1][0].b) < 3)) dieusage() ; - for (i = 0 ; i < 2 ; i++) - for (j = 0 ; j < 2 ; j++) - if (ndelay_on(buffer_fd(&a[i][j].b)) == -1) - { - char fmt[INT_FMT] ; - fmt[int_fmt(fmt, buffer_fd(&a[i][j].b))] = 0 ; - strerr_diefu3sys(111, "set fd ", fmt, " non-blocking") ; - } + for (i = 0 ; i < 2 ; i++) for (j = 0 ; j < 2 ; j++) + { + int fd = buffer_fd(&a[i][j].b) ; + struct stat st ; + if (fstat(fd, &st) == -1) + { + char fmt[INT_FMT] ; + fmt[int_fmt(fmt, fd)] = 0 ; + strerr_diefu2sys(111, "fstat fd ", fmt) ; + } + a[i][j].flagsocket = !!S_ISSOCK(st.st_mode) ; + if (ndelay_on(fd) == -1) + { + char fmt[INT_FMT] ; + fmt[int_fmt(fmt, fd)] = 0 ; + strerr_diefu3sys(111, "set fd ", fmt, " non-blocking") ; + } + } if (!sig_ignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ; tain_now_set_stopwatch_g() ; x[0].fd = selfpipe_init() ;