Shell Network Features

Kare Nuorteva
Blog by Kare Nuorteva
2 min readOct 28, 2016

--

Both Zsh and Bash provide an option to connect to a TCP port and read/write data. Lets take a look at the details!

Zsh network feature

Open a TCP connection to google.com with session ID ‘sid’ and request front page of google.com. Read in the response and print out HTTP headers and HTML page (discarding Zsh TCP session ID in output).

#!/bin/zshautoload -U tcp_open
TCP_SILENT=1
tcp_open -q google.com 80 sid
tcp_send -q -s sid -- "GET / HTTP/1.1"
tcp_send -q -s sid -- "host: google.com"
tcp_send -q -s sid -- "connection: close"
tcp_send -q -s sid -- ""
tcp_read -b -d -s sid
tcp_close -q -s sid
for line in $tcp_lines; do
echo ${line/*<-\[sid\] /}
done

Tcp_* functions are plain Zsh scripts and are wrappers around the Zsh tcp module system. Another way to achieve same effect would be to open a file descriptor ($FD) and write HTTP request and read HTTP response from this file descriptor.

Reading and writing a TCP stream from a file descriptor is shown below:

#!/bin/zshzmodload zsh/net/tcpFD=9
ztcp -d $FD google.com 80
print "GET / HTTP/1.1\r\n" >&$FD
print "host: google.com\r\n" >&$FD
print "connection: close\r\n\r\n" >&$FD
read -r line <&$FD
echo $line
while read -u $FD -r -e -t; do;
done
ztcp -d $FD -c

Bash network file system feature

Get date and time from an NTP server:

$ cat < /dev/tcp/time.nist.gov/1357686 16–10–25 21:38:47 13 0 0 123.6 UTC(NIST) *

Download google.com HTML page:

#!/bin/bashFD=9
exec 9<> /dev/tcp/google.com/80
printf "GET / HTTP/1.1\r\n" >& $FD
printf "host: google.com\r\n" >& $FD
printf "connection: close\r\n\r\n" >& $FD
cat <& $FD

Bash reads and writes from a file descriptor, but opens file descriptor from a file system path.

Conclusion

Initially Zsh and Bash TCP features were inspired by Plan 9's web file server.

However, today their implementations differ. Bash still has TCP implemented as a device file and Zsh has moved away from a device file and implemented it as a plain file descriptor.

File descriptors (and processes) are the uniform approach in UNIX. Almost everything in UNIX is a file descriptor. Sockets and pipes to name a few. Opening a TCP connection through a device file doesn’t seem much of an improvement. Perhaps more of an obscurity. It’s probably easier to use other tools such as curl or netcat to achieve same results.

--

--