#include "autoconf.h"
#include "config.h"
#include <netdb.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <signal.h>
#include "slave.h"
#include <arpa/inet.h>
Include dependency graph for slave.cpp:
Go to the source code of this file.
Defines | |
#define | CAST_SIGNAL_FUNC |
#define | MAX_STRING 1000 |
#define | INADDR_NONE ((in_addr_t)-1) |
#define | MAX_CHILDREN 20 |
Functions | |
char * | format_inet_addr (char *dest, long addr) |
char * | stpcpy (char *dest, const char *src) |
RETSIGTYPE | child_timeout_signal (int iSig) |
int | query (char *ip, char *orig_arg) |
RETSIGTYPE | alarm_signal (int iSig) |
RETSIGTYPE | child_signal (int iSig) |
int | main (int argc, char *argv[]) |
Variables | |
pid_t | parent_pid |
char * | arg_for_errors |
volatile int | nChildrenStarted = 0 |
volatile int | nChildrenEndedSIGCHLD = 0 |
volatile int | nChildrenEndedMain = 0 |
RETSIGTYPE alarm_signal | ( | int | iSig | ) |
Definition at line 206 of file slave.cpp.
References CAST_SIGNAL_FUNC, and parent_pid.
Referenced by main().
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; // 2 minutes. 00217 interval.tv_usec = 0; 00218 itime.it_interval = interval; 00219 itime.it_value = interval; 00220 setitimer(ITIMER_REAL, &itime, 0); 00221 }
RETSIGTYPE child_signal | ( | int | iSig | ) |
Definition at line 228 of file slave.cpp.
References CAST_SIGNAL_FUNC, nChildrenEndedMain, nChildrenEndedSIGCHLD, and nChildrenStarted.
Referenced by main().
00229 { 00230 // Collect the children. 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 }
RETSIGTYPE child_timeout_signal | ( | int | iSig | ) |
char* format_inet_addr | ( | char * | dest, | |
long | addr | |||
) |
int main | ( | int | argc, | |
char * | argv[] | |||
) |
Definition at line 245 of file slave.cpp.
References alarm_signal(), CAST_SIGNAL_FUNC, child_signal(), child_timeout_signal(), MAX_CHILDREN, MAX_STRING, nChildrenEndedMain, nChildrenEndedSIGCHLD, nChildrenStarted, parent_pid, and query().
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 // Our real parent process is gone, and we have been inherited by the 00256 // init process. 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: // child. 00295 { 00296 // We don't want to try this for more than 5 minutes. 00297 // 00298 struct itimerval itime; 00299 struct timeval interval; 00300 00301 interval.tv_sec = 300; // 5 minutes. 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 // Collect the children. 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 }
int query | ( | char * | ip, | |
char * | orig_arg | |||
) |
Definition at line 66 of file slave.cpp.
References arg_for_errors, format_inet_addr(), INADDR_NONE, MAX_STRING, and stpcpy().
Referenced by main().
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); // ident port 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 }
char* stpcpy | ( | char * | dest, | |
const char * | src | |||
) |
char* arg_for_errors |
volatile int nChildrenEndedMain = 0 |
volatile int nChildrenEndedSIGCHLD = 0 |
volatile int nChildrenStarted = 0 |
pid_t parent_pid |