#include #include #include #include #include #include #include #include #include #include #include #include #include extern char **argvec; #include "utils.h" #include "config.h" #include "strings.h" #include "hostname.h" #if defined(HOSTNAMES) && !defined(SYNC_HOSTNAMES) int hostname_fd; int hostname_px; void fork_hostname_process(void) { int p[2]; int pid; int npend; #define MAXPEND 1024 int pend[MAXPEND]; int npoll; struct pollfd pfds[MAXPEND+1]; int npfds; int i; int j; struct rlimit rl; if (getrlimit(RLIMIT_NOFILE,&rl) == 0) { rl.rlim_cur = rl.rlim_max; setrlimit(RLIMIT_NOFILE,&rl); } socketpair(AF_UNIX,SOCK_STREAM,0,&p[0]); pid = fork(); if (pid) { hostname_fd = p[0]; close(p[1]); return; } signal(SIGINT,SIG_IGN); hostname_fd = p[1]; close(p[0]); for (i=getdtablesize()-1;i>=0;i--) { if ((i != hostname_fd) && (i != 2)) close(i); } npend = 0; while (1) { while (1) { pid = wait3(0,WNOHANG,0); if (pid <= 0) break; } j = 0; for (i=0;i= 0) { if (j != i) pend[j] = pend[i]; pfds[j].fd = pend[j]; pfds[j].events = POLLIN | POLLRDNORM; j ++; } } npend = j; npoll = j; if (npoll < MAXPEND) { pfds[j].fd = hostname_fd; pfds[j].events = POLLIN | POLLRDNORM; j ++; } npfds = j; i = poll(&pfds[0],npfds,INFTIM); if (i < 0) { if (errno == EINTR) continue; fprintf(stderr,"%s: poll: %s\n",argvec[0],strerror(errno)); exit(0); } if ((npoll < MAXPEND) && (pfds[npoll].revents & (POLLIN|POLLRDNORM|POLLERR|POLLHUP))) #define RQLEN (sizeof(int) + sizeof(struct sockaddr_storage)) { unsigned char buf[RQLEN]; int al; struct sockaddr_storage ss; if (Read(hostname_fd,&buf[0],RQLEN) < 0) exit(0); bcopy(&buf[0],&al,sizeof(int)); if ((al < 1) || (al > sizeof(ss))) { fprintf(stderr,"hostname process: unreasonable length %d\n",al); exit(1); } bcopy(&buf[sizeof(int)],&ss,al); socketpair(AF_UNIX,SOCK_STREAM,0,&p[0]); pend[npend++] = p[0]; pid = fork(); if (pid == 0) { int gnirv; int ilen; unsigned char uclen; char host[NI_MAXHOST]; struct iovec iov[4]; close(hostname_fd); for (i=npend-1;i>=0;i--) close(pend[i]); gnirv = getnameinfo((struct sockaddr *)&ss,al,&host[0],NI_MAXHOST,0,0,0); if (gnirv) { const char *s; s = gai_strerror(gnirv); sprintf(&host[0],"(%.*s)",NI_MAXHOST-3,s); } iov[0].iov_base = &al; iov[0].iov_len = sizeof(int); iov[1].iov_base = &ss; iov[1].iov_len = sizeof(struct sockaddr_storage); ilen = strlen(&host[0]); uclen = (ilen > 255) ? 255 : ilen; iov[2].iov_base = &uclen; iov[2].iov_len = 1; iov[3].iov_base = &host[0]; iov[3].iov_len = uclen; writev(p[1],&iov[0],4); exit(0); } close(p[1]); } for (i=npoll-1;i>=0;i--) { if (pfds[i].revents & (POLLIN|POLLRDNORM|POLLERR|POLLHUP)) #define PRESTRING ( sizeof(int) + \ sizeof(struct sockaddr_storage) ) { unsigned char buf[PRESTRING+1+255]; #define SETERR(s) (buf[PRESTRING]=strlen(strcpy(&buf[PRESTRING+1],(s)))) if (Read(pend[i],&buf[0],PRESTRING+1) == 0) { if (Read(pend[i],&buf[PRESTRING+1],buf[PRESTRING]) == 0) { } else { SETERR("(error A)"); } } else { SETERR("(error B)"); } write(hostname_fd,&buf[0],PRESTRING+1+buf[PRESTRING]); #undef SETERR #undef PRESTRING close(pend[i]); pend[i] = -1; } } } } #endif