X-Git-Url: https://git.saurik.com/apple/libinfo.git/blobdiff_plain/03fb6eb005e0e1ca66f0422cb7821f0a2ad2d381..d90e699ca2566289cddc68cd0862d05780b54551:/nis.subproj/yp_bind.c diff --git a/nis.subproj/yp_bind.c b/nis.subproj/yp_bind.c index a8b9c9d..14b20bb 100644 --- a/nis.subproj/yp_bind.c +++ b/nis.subproj/yp_bind.c @@ -71,8 +71,12 @@ static char *rcsid = "$OpenBSD: yp_bind.c,v 1.9 1997/04/29 21:25:20 deraadt Exp #include #include #include +#include +#include #include "ypinternal.h" +extern int notify_register_plain(char *, int *); + struct dom_binding *_ypbindlist = NULL; char _yp_domain[MAXHOSTNAMELEN] = { '\0' }; @@ -84,7 +88,6 @@ _yp_dobind(dom, ypdb) struct dom_binding **ypdb; { static int pid = -1; - char path[MAXPATHLEN]; struct dom_binding *ysd, *ysd2; struct ypbind_resp ypbr; struct timeval tv; @@ -92,141 +95,141 @@ _yp_dobind(dom, ypdb) struct ypbind_binding *bn; int clnt_sock, fd, gpid; CLIENT *client; - int new = 0, r; + int new = 0, r, proto; int count = 0; u_short port; + int status, notify_token; + uint64_t abort; + char *notify_name; /* * test if YP is running or not */ - if ((fd = open(YPBINDLOCK, O_RDONLY)) == -1) - return YPERR_YPBIND; - if (!(flock(fd, LOCK_EX | LOCK_NB) == -1 && errno == EWOULDBLOCK)) { - (void)close(fd); + if ((fd = open(YPBINDLOCK, O_RDONLY)) == -1) return YPERR_YPBIND; + + if (!((flock(fd, LOCK_EX | LOCK_NB) == -1) && (errno == EWOULDBLOCK))) + { + close(fd); return YPERR_YPBIND; } - (void)close(fd); + + close(fd); gpid = getpid(); - if (!(pid == -1 || pid == gpid)) { + if (!((pid == -1) || (pid == gpid))) + { ysd = _ypbindlist; - while (ysd) { - if (ysd->dom_client) - clnt_destroy(ysd->dom_client); + while (ysd) + { + if (ysd->dom_client) clnt_destroy(ysd->dom_client); ysd2 = ysd->dom_pnext; free(ysd); ysd = ysd2; } + _ypbindlist = NULL; } + pid = gpid; - if (ypdb != NULL) - *ypdb = NULL; + if (ypdb != NULL) *ypdb = NULL; - if (dom == NULL || strlen(dom) == 0) - return YPERR_BADARGS; + if ((dom == NULL) || (strlen(dom) == 0)) return YPERR_BADARGS; for (ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext) - if (strcmp(dom, ysd->dom_domain) == 0) - break; - if (ysd == NULL) { - if ((ysd = malloc(sizeof *ysd)) == NULL) - return YPERR_YPERR; - (void)memset(ysd, 0, sizeof *ysd); + { + if (strcmp(dom, ysd->dom_domain) == 0) break; + } + + if (ysd == NULL) + { + ysd = calloc(1, sizeof(struct dom_binding)); + if (ysd == NULL) return YPERR_YPERR; ysd->dom_socket = -1; ysd->dom_vers = 0; new = 1; } -again: - if (ysd->dom_vers == 0) { - (void) snprintf(path, sizeof(path), "%s/%s.%d", - BINDINGDIR, dom, 2); - if ((fd = open(path, O_RDONLY)) == -1) { - /* - * no binding file, YP is dead, or not yet fully - * alive. - */ - goto trynet; - } - if (flock(fd, LOCK_EX | LOCK_NB) == -1 && - errno == EWOULDBLOCK) { - struct iovec iov[2]; - u_short ypb_port; - /* - * we fetch the ypbind port number, but do - * nothing with it. - */ - iov[0].iov_base = (caddr_t) &ypb_port; - iov[0].iov_len = sizeof ypb_port; - iov[1].iov_base = (caddr_t) &ypbr; - iov[1].iov_len = sizeof ypbr; - - r = readv(fd, iov, 2); - if (r != iov[0].iov_len + iov[1].iov_len) { - (void)close(fd); - ysd->dom_vers = -1; - goto again; - } - (void)close(fd); - goto gotdata; - } else { - /* no lock on binding file, YP is dead. */ - (void)close(fd); - if (new) - free(ysd); + /* + * Get notification token + * we use a self-notification token to allow a caller + * to signal the thread doing this bind call to quit. + */ + notify_name = NULL; + notify_token = -1; + + asprintf(¬ify_name, "self.thread.%lu", (unsigned long)pthread_self()); + if (notify_name != NULL) + { + status = notify_register_plain(notify_name, ¬ify_token); + free(notify_name); + } + +again: + if (notify_token != -1) + { + abort = 0; + status = notify_get_state(notify_token, &abort); + if (abort == ThreadStateExitRequested) + { + if (new) free(ysd); + notify_cancel(notify_token); return YPERR_YPBIND; } } -trynet: - if (ysd->dom_vers == -1 || ysd->dom_vers == 0) { - (void)memset(&clnt_sin, 0, sizeof clnt_sin); + + proto = YP_BIND_UDP; + if (ysd->dom_vers == YP_BIND_TCP) proto = YP_BIND_TCP; + + if ((ysd->dom_vers == 0) || (ysd->dom_vers == YP_BIND_UDP) || (ysd->dom_vers == YP_BIND_TCP)) + { + memset(&clnt_sin, 0, sizeof clnt_sin); clnt_sin.sin_len = sizeof(struct sockaddr_in); clnt_sin.sin_family = AF_INET; clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); clnt_sock = RPC_ANYSOCK; - client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, - &clnt_sock, 0, 0); - if (client == NULL) { + client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, &clnt_sock, 0, 0); + if (client == NULL) + { clnt_pcreateerror("clnttcp_create"); - if (new) - free(ysd); + if (new) free(ysd); + if (notify_token != -1) notify_cancel(notify_token); return YPERR_YPBIND; } - if (ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED || - ntohs(clnt_sin.sin_port) == 20) { + + if ((ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED) || (ntohs(clnt_sin.sin_port) == 20)) + { /* * YP was not running, but someone has registered * ypbind with portmap -- this simply means YP is * not running. */ clnt_destroy(client); - if (new) - free(ysd); + if (new) free(ysd); + if (notify_token != -1) notify_cancel(notify_token); return YPERR_YPBIND; } + tv.tv_sec = _yplib_timeout; tv.tv_usec = 0; - r = clnt_call(client, YPBINDPROC_DOMAIN, xdr_domainname, - &dom, xdr_ypbind_resp, &ypbr, tv); - if (r != RPC_SUCCESS) { - if (new == 0 || count) - fprintf(stderr, - "YP server for domain %s not responding, still trying\n", - dom); + + r = clnt_call(client, YPBINDPROC_DOMAIN, (xdrproc_t)xdr_domainname, &dom, (xdrproc_t)xdr_ypbind_resp, &ypbr, tv); + if (r != RPC_SUCCESS) + { + if (new == 0 || count) fprintf(stderr, "YP server for domain %s not responding, still trying\n", dom); count++; clnt_destroy(client); - ysd->dom_vers = -1; + ysd->dom_vers = proto; goto again; } + clnt_destroy(client); -gotdata: + bn = &ypbr.ypbind_resp_u.ypbind_bindinfo; memcpy(&port, &bn->ypbind_binding_port, sizeof port); - if (ntohs(port) >= IPPORT_RESERVED || - ntohs(port) == 20) { + if ((ntohs(port) >= IPPORT_RESERVED) || (ntohs(port) == 20)) + { /* * This is bogus -- the ypbind wants me to * communicate to an insecure ypserv. We are @@ -234,46 +237,51 @@ gotdata: * but for now we'll simply ignore it; real YP * is obviously not running. */ - if (new) - free(ysd); + if (new) free(ysd); + if (notify_token != -1) notify_cancel(notify_token); return YPERR_YPBIND; } - (void)memset(&ysd->dom_server_addr, 0, - sizeof ysd->dom_server_addr); + + memset(&ysd->dom_server_addr, 0, sizeof ysd->dom_server_addr); ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in); ysd->dom_server_addr.sin_family = AF_INET; - memcpy(&ysd->dom_server_addr.sin_port, - &bn->ypbind_binding_port, - sizeof(ysd->dom_server_addr.sin_port)); - memcpy(&ysd->dom_server_addr.sin_addr.s_addr, - &bn->ypbind_binding_addr, - sizeof(ysd->dom_server_addr.sin_addr.s_addr)); + memcpy(&ysd->dom_server_addr.sin_port, &bn->ypbind_binding_port, sizeof(ysd->dom_server_addr.sin_port)); + memcpy(&ysd->dom_server_addr.sin_addr.s_addr, &bn->ypbind_binding_addr, sizeof(ysd->dom_server_addr.sin_addr.s_addr)); ysd->dom_server_port = ysd->dom_server_addr.sin_port; ysd->dom_vers = YPVERS; - (void)strncpy(ysd->dom_domain, dom, sizeof ysd->dom_domain-1); + strncpy(ysd->dom_domain, dom, sizeof ysd->dom_domain-1); ysd->dom_domain[sizeof ysd->dom_domain-1] = '\0'; } + tv.tv_sec = _yplib_timeout / 2; tv.tv_usec = 0; - if (ysd->dom_client) - clnt_destroy(ysd->dom_client); + + if (ysd->dom_client) clnt_destroy(ysd->dom_client); ysd->dom_socket = RPC_ANYSOCK; - ysd->dom_client = clntudp_create(&ysd->dom_server_addr, - YPPROG, YPVERS, tv, &ysd->dom_socket); - if (ysd->dom_client == NULL) { - clnt_pcreateerror("clntudp_create"); - ysd->dom_vers = -1; + + if (proto == YP_BIND_UDP) ysd->dom_client = clntudp_create(&ysd->dom_server_addr, YPPROG, YPVERS, tv, &ysd->dom_socket); + else ysd->dom_client = clnttcp_create(&ysd->dom_server_addr, YPPROG, YPVERS, &ysd->dom_socket, 0, 0); + + if (ysd->dom_client == NULL) + { + if (proto == YP_BIND_UDP) clnt_pcreateerror("clntudp_create"); + else clnt_pcreateerror("clnttcp_create"); + ysd->dom_vers = proto; goto again; } + + if (notify_token != -1) notify_cancel(notify_token); + if (fcntl(ysd->dom_socket, F_SETFD, 1) == -1) perror("fcntl: F_SETFD"); - if (new) { + if (new != 0) + { ysd->dom_pnext = _ypbindlist; _ypbindlist = ysd; } - if (ypdb != NULL) - *ypdb = ysd; + + if (ypdb != NULL) *ypdb = ysd; return 0; }