1

We wanted to use socat to make a process available that is line-based:

socat SYSTEM:"echo \$\$;sed -u /^%/s/foo/bar/" \
  TCP-L:1234,fork,reuseaddr,readbytes=21,bind=localhost

This works but only until the readbytes limit is reached because the last "line" is cut short and the left side ("SYSTEM") does not get a newline until the next line. For example:

$ echo %foo | socat - tcp:localhost:1234
13047
%bar
$ echo foo w/o ^% | socat - tcp:localhost:1234
foo w/o ^%
$ echo %foo, here is a too long line | socat - tcp:localhost:1234
$ echo %foo | socat - tcp:localhost:1234
%bar, here is a too l%foo

The echo \$\$ is there to demonstrate that socat starts the left side only once and keeps it running for multiple clients. That's what we need. But is there a way to e.g. pass a newline to the left side when the right side was cut short due to readbytes?

Update 2019-03-15 00:05 UTC:

One will probably want to add ,pty,rawer to the left side, however, this does not help with the case where the readbytes limit is reached.

socat is 1.7.3.1, running on Debian 9, Linux 4.9.144.

xebeche
  • 363
  • 3
  • 13

1 Answers1

0

One way to work around the issue is to count bytes and append a final newline if the limit is reached. In Bash this could be done for instance with (here including the SYSTEM: part from the question):

!/bin/bash
readbytes=21 # the number used in the question
echo $$
while :; do
   read -r -N 1 || break
   count=$((count+1))
   echo "byte $count is '$REPLY'" >&2
   printf '%s' "$REPLY"
   ((count<readbytes)) || { [[ $REPLY == $'\n' ]] || printf '\n'; count=0; }
   [[ $REPLY != $'\n' ]] || count=0
done \
|sed -u /^%/s/foo/bar/

Now, if we run socat using this script as in

socat EXEC:./script  TCP-L:1234,fork,reuseaddr,readbytes=21,bind=localhost

the too long line will get a newline appended, so it can be handled by sed:

$ echo %foo | socat - tcp:localhost:1234
3811702
%bar
$ echo foo w/o ^% | socat - tcp:localhost:1234
foo w/o ^%
$ echo %foo, here is a too long line | socat - tcp:localhost:1234
%bar, here is a too l
$ echo %foo | socat - tcp:localhost:1234
%bar
xebeche
  • 363
  • 3
  • 13