diff options
Diffstat (limited to 'src/telnet-probe/telnet-probe.c')
-rw-r--r-- | src/telnet-probe/telnet-probe.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/telnet-probe/telnet-probe.c b/src/telnet-probe/telnet-probe.c new file mode 100644 index 0000000..3754a2d --- /dev/null +++ b/src/telnet-probe/telnet-probe.c @@ -0,0 +1,184 @@ +/* + * Lightweight telnet clone for shping and espping PMDAs. + * + * Usage: telnet-probe [-v] host port + * + * Once telnet connection is established: + * read stdin until EOF, writing to telnet connection + * read telnet until EOF, discarding data + * -c (connect only) flag skips the send-receive processing + * + * Exit status is 1 in the case of any errors, else 0. + */ + +#include "pmapi.h" +#include "impl.h" + +int +main(int argc, char *argv[]) +{ + __pmFdSet wfds; + __pmSockAddr *myAddr; + __pmHostEnt *servInfo; + void *enumIx; + int flags = 0; + char *endnum; + int port = 0; + int s; + int errflag = 0; + int cflag = 0; + int vflag = 0; + int sts = 1; + ssize_t bytes; + int ret; + struct timeval canwait = { 5, 000000 }; + struct timeval stv; + struct timeval *pstv; + int c; + + while ((c = getopt(argc, argv, "cv?")) != EOF) { + switch (c) { + case 'c': + cflag = 1; + break; + case 'v': + vflag = 1; + break; + case '?': + default: + errflag++; + break; + } + } + + if (optind+2 != argc) { + fprintf(stderr, "%s: requires two arguments\n", argv[0]); + errflag++; + } + else { + port = (int)strtol(argv[optind+1], &endnum, 10); + if (*endnum != '\0' || port < 0) { + fprintf(stderr, "%s: port must be a positive number\n", argv[0]); + errflag++; + } + } + if (errflag) { + fprintf(stderr, "Usage: %s [-c] [-v] host port\n", argv[0]); + goto done; + } + + if ((servInfo = __pmGetAddrInfo(argv[optind])) == NULL) { + if (vflag) + fprintf(stderr, "__pmGetAddrInfo: %s\n", hoststrerror()); + goto done; + } + + s = -1; + enumIx = NULL; + for (myAddr = __pmHostEntGetSockAddr(servInfo, &enumIx); + myAddr != NULL; + myAddr = __pmHostEntGetSockAddr(servInfo, &enumIx)) { + /* Create a socket */ + if (__pmSockAddrIsInet(myAddr)) + s = __pmCreateSocket(); + else if (__pmSockAddrIsIPv6(myAddr)) + s = __pmCreateIPv6Socket(); + else + continue; + if (s < 0) { + __pmSockAddrFree(myAddr); + continue; /* Try the next address */ + } + + /* Attempt to connect */ + flags = __pmConnectTo(s, myAddr, port); + __pmSockAddrFree(myAddr); + + if (flags < 0) { + /* + * Mark failure in case we fall out the end of the loop + * and try next address. s has been closed in __pmConnectTo(). + */ + setoserror(ECONNREFUSED); + s = -1; + continue; + } + + /* FNDELAY and we're in progress - wait on select */ + stv = canwait; + pstv = (stv.tv_sec || stv.tv_usec) ? &stv : NULL; + __pmFD_ZERO(&wfds); + __pmFD_SET(s, &wfds); + ret = __pmSelectWrite(s+1, &wfds, pstv); + + /* Was the connection successful? */ + if (ret == 0) + setoserror(ETIMEDOUT); + else if (ret > 0) { + ret = __pmConnectCheckError(s); + if (ret == 0) + break; + setoserror(ret); + } + + /* Unsuccessful connection. */ + __pmCloseSocket(s); + s = -1; + } /* loop over addresses */ + + __pmHostEntFree(servInfo); + + if (s != -1) + s = __pmConnectRestoreFlags(s, flags); + if (s < 0) { + if (vflag) + fprintf(stderr, "connect: %s\n", netstrerror()); + goto done; + } + + if (cflag) { + /* skip send-recv exercise */ + sts = 0; + goto done; + } + + if (vflag) + fprintf(stderr, "send ...\n"); + while ((c = getc(stdin)) != EOF) { + if (vflag) { + fputc(c, stderr); + fflush(stderr); + } + if (__pmWrite(s, &c, sizeof(c)) != sizeof(c)) { + if (vflag) + fprintf(stderr, "telnet write: %s\n", osstrerror()); + goto done; + } + } + + if (vflag) + fprintf(stderr, "recv ...\n"); + while ((bytes = __pmRead(s, &c, sizeof(c))) == sizeof(c)) { + if (vflag) { + fputc(c, stderr); + fflush(stderr); + } + } + if (bytes < 0) { + /* + * If __pmSocketClosed(), then treat it as EOF. + */ + if (! __pmSocketClosed()) { + if (vflag) + fprintf(stderr, "telnet read: %s\n", osstrerror()); + goto done; + } + } + + sts = 0; + +done: + if (vflag) + fprintf(stderr, "exit: %d\n", sts); + exit(sts); +} |