diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-06-12 19:23:39 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-06-12 19:29:45 +0300 |
commit | 85563afeac954a50de7e4c207f43b57a4e63e474 (patch) | |
tree | 967054eb92014811e067f1d56c99e12c268f1824 /tests/nt.c | |
parent | f5c72b5e74ea7aaf1375f763f977e3249c6b7fc4 (diff) | |
download | pies-85563afeac954a50de7e4c207f43b57a4e63e474.tar.gz pies-85563afeac954a50de7e4c207f43b57a4e63e474.tar.bz2 |
More tests for built-in services
* tests/builtin.at: Check tcpmux services.
* tests/nt.c: Add tcpmux support, improve error checking.
* tests/chargen.c: Improve error checking.
Diffstat (limited to 'tests/nt.c')
-rw-r--r-- | tests/nt.c | 137 |
1 files changed, 121 insertions, 16 deletions
@@ -136,7 +136,7 @@ netcat_stream_read (netcat_server_t *srv) if (errno == EINTR) return 0; grecs_error (NULL, errno, "%s: read", srv->id); - srv->pollfd->events &= ~POLLIN; + netcat_stream_disconnect (srv, POLLIN); return -1; } if (n == 0 || !peer_is_state (srv, POLLOUT)) @@ -185,11 +185,12 @@ netcat_stream_write (netcat_server_t *srv) if (errno == EINTR) return 0; grecs_error (NULL, errno, "%s: write", srv->id); + netcat_stream_disconnect (srv, POLLOUT); return -1; } if (n == 0) { - // FIXME: eof + netcat_stream_disconnect (srv, POLLOUT); return -1; } return 0; @@ -220,8 +221,99 @@ disconnect_stdout (netcat_server_t *srv) exit (0); } +void +fd_write (int fd, char const *str, size_t len) +{ + while (len) + { + ssize_t n = write (fd, str, len); + if (n == -1) + { + perror ("socket write"); + exit (1); + } + if (n == 0) + { + fprintf (stderr, "zero write\n"); + exit (1); + } + len -= n; + str += n; + } +} + +void +fd_writeln (int fd, char const *str) +{ + fd_write (fd, str, strlen (str)); + fd_write (fd, "\r\n", 2); +} + +int +fd_getc (int fd) +{ + char c; + ssize_t n = read (fd, &c, 1); + if (n == -1) + { + perror ("socket read"); + exit (1); + } + if (n == 0) + c = EOF; + return c; +} + +static void +tcpmux_init (int fd, char const *service) +{ + int c; + + fd_writeln (fd, service); + + if (strcmp (service, "help") == 0) + { + while ((c = fd_getc (fd)) != EOF) + { + fputc (c, stdout); + } + close (fd); + exit (0); + } + + c = fd_getc (fd); + if (c == 0) + { + fprintf (stderr, "socket read: unexpected eof\n"); + exit (1); + } + if (c == '+') + { + while ((c = fd_getc (fd)) != '\n') + { + if (c == EOF) + { + fprintf (stderr, "socket read: unexpected eof\n"); + exit (1); + } + } + } + else + { + fprintf (stderr, "service rejected: "); + do + { + if (c != '\r') + fputc (c, stderr); + } + while ((c = fd_getc (fd)) != 0 && c != '\n'); + fputc ('\n', stderr); + exit (1); + } +} + static int -netcat (char const *urlstr) +netcat (char const *urlstr, char const *tcpmux_service) { int fd; struct pies_url *url; @@ -239,6 +331,9 @@ netcat (char const *urlstr) if (fd == -1) return 1; + if (tcpmux_service) + tcpmux_init (fd, tcpmux_service); + pfd[0].fd = 0; pfd[0].events = 0; srvin = netcat_server_create ("stdin", &pfd[0], POLLIN, disconnect_stdin, NULL); @@ -265,25 +360,26 @@ netcat (char const *urlstr) for (srv = server_head; srv; ) { netcat_server_t *next = srv->next; - int events; - events = (srv->pollfd->events|POLLHUP) - & (srv->pollfd->revents - & (srv->state | ((srv->state & POLLOUT) ? POLLHUP : 0))); - if (events) - { - if (events & POLLIN) + if ((srv->pollfd->revents & srv->state) & POLLIN) netcat_stream_read (srv); - if (events & POLLOUT) + if ((srv->pollfd->revents & srv->state) & POLLOUT) netcat_stream_write (srv); - if (events & POLLHUP) + if ((srv->state & POLLOUT) && (srv->pollfd->revents & POLLHUP)) { //grecs_error (NULL, 0, "HUP on %s", srv->id); netcat_stream_disconnect (srv, srv->state); } - } if (srv->state == 0 || srv->pollfd->fd == -1) + { + netcat_server_t *peer = srv->peer; + if (peer && peer->pollfd->events == 0) + { + netcat_stream_disconnect (peer, peer->state); + netcat_server_remove (peer); + } netcat_server_remove (srv); + } srv = next; } } @@ -311,17 +407,22 @@ redirect (int sfd, char const *name) static void usage (FILE *fp) { - fprintf (fp, "usage: nt [-i IFILE] [-o OFILE] URL\n"); + fprintf (fp, "usage: nt [-i IFILE] [-o OFILE] [-t SERVICE] URL\n"); fprintf (fp, "Reads data from stdin (or IFILE) and sends them to URL.\n"); fprintf (fp, "Reads replies from URL and sends them to stdout (or OFILE).\n"); + fprintf (fp, "\nOPTIONS\n\n"); + fprintf (fp, " -t SERVICE use TCPMUX service\n"); + fprintf (fp, " -i IFILE read input from IFILE\n"); + fprintf (fp, " -o OFILE write output to OFILE\n"); } int main (int argc, char **argv) { int c; + char const *tcpmux_service = NULL; - while ((c = getopt (argc, argv, "i:o:")) != EOF) + while ((c = getopt (argc, argv, "i:o:t:")) != EOF) { switch (c) { @@ -333,6 +434,10 @@ main (int argc, char **argv) redirect (1, optarg); break; + case 't': + tcpmux_service = optarg; + break; + default: exit (64); } @@ -347,5 +452,5 @@ main (int argc, char **argv) exit (64); } - return netcat (argv[0]); + return netcat (argv[0], tcpmux_service); } |