00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "autoconf.h"
00012 #include "config.h"
00013
00014 #include <netdb.h>
00015 #include <netinet/in.h>
00016 #include <sys/wait.h>
00017 #include <sys/file.h>
00018 #include <sys/ioctl.h>
00019 #include <signal.h>
00020 #include "slave.h"
00021 #include <arpa/inet.h>
00022
00023 #ifdef _SGI_SOURCE
00024 #define CAST_SIGNAL_FUNC (SIG_PF)
00025 #else
00026 #define CAST_SIGNAL_FUNC
00027 #endif
00028
00029 pid_t parent_pid;
00030
00031 #define MAX_STRING 1000
00032 char *arg_for_errors;
00033
00034 #ifndef INADDR_NONE
00035 #define INADDR_NONE ((in_addr_t)-1)
00036 #endif
00037
00038 char *format_inet_addr(char *dest, long addr)
00039 {
00040 sprintf(dest, "%ld.%ld.%ld.%ld",
00041 (addr & 0xFF000000) >> 24,
00042 (addr & 0x00FF0000) >> 16,
00043 (addr & 0x0000FF00) >> 8,
00044 (addr & 0x000000FF));
00045 return (dest + strlen(dest));
00046 }
00047
00048
00049
00050
00051 char *stpcpy(char *dest, const char *src)
00052 {
00053 while ((*dest = *src))
00054 {
00055 ++dest;
00056 ++src;
00057 }
00058 return (dest);
00059 }
00060
00061 RETSIGTYPE child_timeout_signal(int iSig)
00062 {
00063 exit(1);
00064 }
00065
00066 int query(char *ip, char *orig_arg)
00067 {
00068 char *comma;
00069 char *port_pair;
00070 struct hostent *hp;
00071 struct sockaddr_in sin;
00072 int s;
00073 FILE *f;
00074 char result[MAX_STRING];
00075 char buf[MAX_STRING * 2];
00076 char buf2[MAX_STRING * 2];
00077 char buf3[MAX_STRING * 4];
00078 char arg[MAX_STRING];
00079 size_t len;
00080 char *p;
00081 in_addr_t addr;
00082
00083 addr = inet_addr(ip);
00084 if (addr == INADDR_NONE)
00085 {
00086 return -1;
00087 }
00088 const char *pHName = ip;
00089 hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
00090 if ( hp
00091 && strlen(hp->h_name) < MAX_STRING)
00092 {
00093 pHName = hp->h_name;
00094 }
00095 p = stpcpy(buf, ip);
00096 *p++ = ' ';
00097 p = stpcpy(p, pHName);
00098 *p++ = '\n';
00099 *p++ = '\0';
00100
00101 arg_for_errors = orig_arg;
00102 strcpy(arg, orig_arg);
00103 comma = (char *)strrchr(arg, ',');
00104 if (comma == NULL)
00105 {
00106 return -1;
00107 }
00108 *comma = 0;
00109 port_pair = (char *)strrchr(arg, ',');
00110 if (port_pair == NULL)
00111 {
00112 return -1;
00113 }
00114 *port_pair++ = 0;
00115 *comma = ',';
00116
00117 hp = gethostbyname(arg);
00118 if (hp == NULL)
00119 {
00120 static struct hostent def;
00121 static struct in_addr defaddr;
00122 static char *alist[1];
00123 static char namebuf[MAX_STRING];
00124
00125 defaddr.s_addr = inet_addr(arg);
00126 if (defaddr.s_addr == INADDR_NONE)
00127 {
00128 return -1;
00129 }
00130 strcpy(namebuf, arg);
00131 def.h_name = namebuf;
00132 def.h_addr_list = alist;
00133 def.h_addr = (char *)&defaddr;
00134 def.h_length = sizeof(struct in_addr);
00135
00136 def.h_addrtype = AF_INET;
00137 def.h_aliases = 0;
00138 hp = &def;
00139 }
00140 sin.sin_family = hp->h_addrtype;
00141 bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
00142 sin.sin_port = htons(113);
00143 s = socket(hp->h_addrtype, SOCK_STREAM, 0);
00144 if (s < 0)
00145 {
00146 return -1;
00147 }
00148 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
00149 if ( errno != ECONNREFUSED
00150 && errno != ETIMEDOUT
00151 && errno != ENETUNREACH
00152 && errno != EHOSTUNREACH)
00153 {
00154 close(s);
00155 return -1;
00156 }
00157 buf2[0] = '\0';
00158 }
00159 else
00160 {
00161 len = strlen(port_pair);
00162 if ((size_t)write(s, port_pair, len) != len)
00163 {
00164 close(s);
00165 return (-1);
00166 }
00167 if (write(s, "\r\n", 2) != 2)
00168 {
00169 close(s);
00170 return (-1);
00171 }
00172 f = fdopen(s, "r");
00173 {
00174 int c;
00175
00176 p = result;
00177 while ((c = fgetc(f)) != EOF)
00178 {
00179 if (c == '\n')
00180 {
00181 break;
00182 }
00183 if (0x20 <= c && c <= 0x7E)
00184 {
00185 *p++ = c;
00186 if (p - result == MAX_STRING - 1)
00187 {
00188 break;
00189 }
00190 }
00191 }
00192 *p = '\0';
00193 }
00194 fclose(f);
00195 p = (char *)format_inet_addr(buf2, ntohl(sin.sin_addr.s_addr));
00196 *p++ = ' ';
00197 p = stpcpy(p, result);
00198 *p++ = '\n';
00199 *p++ = '\0';
00200 }
00201 sprintf(buf3, "%s%s", buf, buf2);
00202 write(1, buf3, strlen(buf3));
00203 return 0;
00204 }
00205
00206 RETSIGTYPE alarm_signal(int iSig)
00207 {
00208 struct itimerval itime;
00209 struct timeval interval;
00210
00211 if (getppid() != parent_pid)
00212 {
00213 exit(1);
00214 }
00215 signal(SIGALRM, CAST_SIGNAL_FUNC alarm_signal);
00216 interval.tv_sec = 120;
00217 interval.tv_usec = 0;
00218 itime.it_interval = interval;
00219 itime.it_value = interval;
00220 setitimer(ITIMER_REAL, &itime, 0);
00221 }
00222
00223 #define MAX_CHILDREN 20
00224 volatile int nChildrenStarted = 0;
00225 volatile int nChildrenEndedSIGCHLD = 0;
00226 volatile int nChildrenEndedMain = 0;
00227
00228 RETSIGTYPE child_signal(int iSig)
00229 {
00230
00231
00232 while (waitpid(0, NULL, WNOHANG) > 0)
00233 {
00234 int nChildren = nChildrenStarted - nChildrenEndedSIGCHLD
00235 - nChildrenEndedMain;
00236 if (0 < nChildren)
00237 {
00238 nChildrenEndedSIGCHLD++;
00239 }
00240 }
00241
00242 signal(SIGCHLD, CAST_SIGNAL_FUNC child_signal);
00243 }
00244
00245 int main(int argc, char *argv[])
00246 {
00247 char arg[MAX_STRING];
00248 char *p;
00249 int len;
00250 pid_t child;
00251
00252 parent_pid = getppid();
00253 if (parent_pid == 1)
00254 {
00255
00256
00257
00258 exit(1);
00259 }
00260
00261 alarm_signal(SIGALRM);
00262 signal(SIGCHLD, CAST_SIGNAL_FUNC child_signal);
00263 signal(SIGPIPE, SIG_DFL);
00264
00265 for (;;)
00266 {
00267 len = read(0, arg, MAX_STRING - 1);
00268 if (len == 0)
00269 {
00270 break;
00271 }
00272 if (len < 0)
00273 {
00274 if (errno == EINTR)
00275 {
00276 errno = 0;
00277 continue;
00278 }
00279 break;
00280 }
00281 arg[len] = '\0';
00282 p = strchr(arg, '\n');
00283 if (p)
00284 {
00285 *p = '\0';
00286 }
00287 child = fork();
00288 switch (child)
00289 {
00290 case -1:
00291 exit(1);
00292 break;
00293
00294 case 0:
00295 {
00296
00297
00298 struct itimerval itime;
00299 struct timeval interval;
00300
00301 interval.tv_sec = 300;
00302 interval.tv_usec = 0;
00303 itime.it_interval = interval;
00304 itime.it_value = interval;
00305 signal(SIGALRM, CAST_SIGNAL_FUNC child_timeout_signal);
00306 setitimer(ITIMER_REAL, &itime, 0);
00307 }
00308 exit(query(arg, p + 1) != 0);
00309 break;
00310 }
00311 if (child > 0)
00312 {
00313 nChildrenStarted++;
00314 }
00315
00316 int nChildren = nChildrenStarted - nChildrenEndedSIGCHLD
00317 - nChildrenEndedMain;
00318
00319
00320
00321 while (waitpid(0, NULL, (nChildren < MAX_CHILDREN) ? WNOHANG : 0) > 0)
00322 {
00323 if (0 < nChildren)
00324 {
00325 nChildrenEndedMain++;
00326 }
00327 }
00328 }
00329 exit(0);
00330 }