diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-10-19 17:20:55 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-10-19 17:20:55 (GMT) |
commit | 78f907d61539e0f313d070ab1d3524ba6dc043ee (patch) | |
tree | a4ed2ed37addb4379dcfc45b11792f718f217ba0 /checkdns.C | |
download | blt-78f907d61539e0f313d070ab1d3524ba6dc043ee.zip blt-78f907d61539e0f313d070ab1d3524ba6dc043ee.tar.gz blt-78f907d61539e0f313d070ab1d3524ba6dc043ee.tar.bz2 |
Squashed 'tclcheckdns/' content from commit 3cf3e91
git-subtree-dir: tclcheckdns
git-subtree-split: 3cf3e919ea92aca6598df3beec77bab053868da7
Diffstat (limited to 'checkdns.C')
-rw-r--r-- | checkdns.C | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/checkdns.C b/checkdns.C new file mode 100644 index 0000000..f3c0590 --- /dev/null +++ b/checkdns.C @@ -0,0 +1,174 @@ +// Copyright (C) 1999-2015 +// Smithsonian Astrophysical Observatory, Cambridge, MA, USA +// For conditions of distribution and use, see copyright notice in "copyright" + +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <setjmp.h> +#include <netdb.h> + +#include <iostream> +#include <sstream> +#include <iomanip> +using namespace std; + +#include <tcl.h> + +#define SZ_LINE 2048 +static int debug =0; + +// alarm signal handler +static sigjmp_buf alarmbuf; +static void alarmHandler(int dummy) +{ + siglongjmp(alarmbuf, 1); +} + +extern "C" { + int Tclcheckdns_Init(void *vinterp); +}; + +static int checkdns(char *name, int delay, int cflag) +{ + int result =0; + + // get temp name, look for port + char tbuf[SZ_LINE]; + unsigned int port=80; + if (name && *name) { + char* ss=NULL; + strncpy(tbuf, name, SZ_LINE-1); + if ((ss=strchr(tbuf, ':'))) { + *ss = '\0'; + port = atoi(ss+1); + } + } + else + *tbuf = '\0'; + + // start the alarm, if necessary + struct sigaction sigact, osigact; + if (delay>0) { + if (sigsetjmp(alarmbuf, 1)) { + if (debug) + cerr << "alarm activated" << endl; + + result= 1; + goto done; + } + else { + sigact.sa_handler = alarmHandler; + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigaction(SIGALRM, &sigact, &osigact); + + alarm(delay); + } + } + + // get name of host we are interested in + char host[SZ_LINE]; + if (*tbuf) + strncpy(host, tbuf, SZ_LINE-1); + else { + // use current host + if (gethostname(host, SZ_LINE) < 0) { + result =2; + goto done; + } + else if (debug) + cerr << "gethostname: " << host << endl; + } + + // try to get info on this host + struct hostent* h; + if (!(h=gethostbyname(host))) { + result =3; + goto done; + } + else if (debug) + cerr << "gethostbyname: " << h->h_name << '(' << port << ')' << endl; + + // connect, if necessary + if (cflag) { + unsigned int ip; + memcpy(&ip, h->h_addr_list[0], (size_t)h->h_length); + ip = ntohl(ip); + int fd; + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + result =4; + goto done; + } + struct sockaddr_in sock_in; + memset((char *)&sock_in, 0, sizeof(sock_in)); + sock_in.sin_family = AF_INET; + sock_in.sin_addr.s_addr = htonl(ip); + sock_in.sin_port = htons(port); + int got = connect(fd, (struct sockaddr *)&sock_in, sizeof(sock_in)); + close(fd); + if (got < 0) { + result =5; + goto done; + } + else if (debug) + cerr << "connect succeeded" << endl; + } + + done: + if (delay) { + alarm(0); + sigaction(SIGALRM, &osigact, NULL); + } + + return result; +} + +static int TclcheckdnsCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "host delay [connect]"); + return TCL_ERROR; + } + + char* host =NULL; + char* ss = Tcl_GetStringFromObj(objv[1], NULL); + if (ss && *ss) + host = ss; + + int delay=5; + char* tt = Tcl_GetStringFromObj(objv[2], NULL); + if (tt && *tt) + delay = atoi(tt); + + int cflag=0; + if (objc >= 4) { + char* uu = Tcl_GetStringFromObj(objv[3], NULL); + if (uu && *uu) + cflag = atoi(uu); + } + + ostringstream str; + str << checkdns(host, delay, cflag) << ends; + Tcl_AppendResult(interp, str.str().c_str(), NULL); + + return TCL_OK; +} + +int Tclcheckdns_Init(void *vinterp) +{ + Tcl_Interp *interp = (Tcl_Interp *)vinterp; + + if (Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0) == NULL) + return TCL_ERROR; + + Tcl_CreateObjCommand(interp, "checkdns", TclcheckdnsCmd, + (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); + + if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION) != TCL_OK) + return TCL_ERROR; + + return TCL_OK; +} |