int yp_match(const char *indomain, const char *inmap, const char *inkey, int inkeylen, char **outval, int *outvallen) { struct dom_binding *ysd; struct ypresp_val yprv; struct ypreq_key yprk; int r, nerrs = 0; if (outval == NULL || outvallen == NULL) return YPERR_BADARGS; *outval = NULL; *outvallen = 0; if (_yp_invalid_domain(indomain)) return YPERR_BADARGS; if (inmap == NULL || *inmap == '\0' || strlen(inmap) > YPMAXMAP) return YPERR_BADARGS; if (inkey == NULL || inkeylen == 0) return YPERR_BADARGS; again: if (_yp_dobind(indomain, &ysd) != 0) return YPERR_DOMAIN; #ifdef YPMATCHCACHE if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, inkeylen, &yprv.valdat.dptr, &yprv.valdat.dsize)) { *outvallen = yprv.valdat.dsize; if ((*outval = malloc((size_t)(*outvallen + 1))) == NULL) return YPERR_YPERR; (void)memcpy(*outval, yprv.valdat.dptr, (size_t)*outvallen); (*outval)[*outvallen] = '\0'; return 0; } #endif yprk.domain = indomain; yprk.map = inmap; yprk.keydat.dptr = __UNCONST(inkey); yprk.keydat.dsize = inkeylen; memset(&yprv, 0, sizeof yprv); r = clnt_call(ysd->dom_client, (rpcproc_t)YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, &yprk, (xdrproc_t)xdr_ypresp_val, &yprv, _yplib_timeout); if (r != RPC_SUCCESS) { if (_yplib_bindtries <= 0 && ++nerrs == _yplib_nerrs) { clnt_perror(ysd->dom_client, "yp_match: clnt_call"); nerrs = 0; } else if (_yplib_bindtries > 0 && ++nerrs == _yplib_bindtries) { return YPERR_YPSERV; } ysd->dom_vers = -1; goto again; } if (!(r = ypprot_err(yprv.status))) { *outvallen = yprv.valdat.dsize; if ((*outval = malloc((size_t)(*outvallen + 1))) == NULL) return YPERR_YPERR; (void)memcpy(*outval, yprv.valdat.dptr, (size_t)*outvallen); (*outval)[*outvallen] = '\0'; #ifdef YPMATCHCACHE if (strcmp(_yp_domain, indomain) == 0) if (!ypmatch_add(inmap, inkey, inkeylen, *outval, *outvallen)) r = YPERR_RESRC; #endif } xdr_free((xdrproc_t)xdr_ypresp_val, (char *)(void *)&yprv); __yp_unbind(ysd); if (r != 0) { if (*outval) { free(*outval); *outval = NULL; } } return r; }
int yp_match(const char *indomain, const char *inmap, const char *inkey, int inkeylen, char **outval, int *outvallen) { struct dom_binding *ysd; struct ypresp_val yprv; struct timeval tv; struct ypreq_key yprk; int tries = 0, r; if (indomain == NULL || *indomain == '\0' || strlen(indomain) > YPMAXDOMAIN || inmap == NULL || *inmap == '\0' || strlen(inmap) > YPMAXMAP || inkey == NULL || inkeylen == 0 || inkeylen >= YPMAXRECORD) return YPERR_BADARGS; *outval = NULL; *outvallen = 0; again: if (_yp_dobind(indomain, &ysd) != 0) return YPERR_DOMAIN; #ifdef YPMATCHCACHE if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, inkeylen, &yprv.val.valdat_val, &yprv.val.valdat_len)) { *outvallen = yprv.val.valdat_len; if ((*outval = malloc(*outvallen + 1)) == NULL) { _yp_unbind(ysd); return YPERR_RESRC; } (void)memcpy(*outval, yprv.val.valdat_val, *outvallen); (*outval)[*outvallen] = '\0'; _yp_unbind(ysd); return 0; } #endif tv.tv_sec = _yplib_timeout; tv.tv_usec = 0; yprk.domain = (char *)indomain; yprk.map = (char *)inmap; yprk.key.keydat_val = (char *) inkey; yprk.key.keydat_len = inkeylen; memset(&yprv, 0, sizeof yprv); r = clnt_call(ysd->dom_client, YPPROC_MATCH, xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv); if (r != RPC_SUCCESS) { if (tries++) clnt_perror(ysd->dom_client, "yp_match: clnt_call"); ysd->dom_vers = -1; goto again; } if (!(r = ypprot_err(yprv.stat))) { *outvallen = yprv.val.valdat_len; if ((*outval = malloc(*outvallen + 1)) == NULL) { r = YPERR_RESRC; goto out; } (void)memcpy(*outval, yprv.val.valdat_val, *outvallen); (*outval)[*outvallen] = '\0'; #ifdef YPMATCHCACHE if (strcmp(_yp_domain, indomain) == 0) (void)ypmatch_add(inmap, inkey, inkeylen, *outval, *outvallen); #endif } out: xdr_free(xdr_ypresp_val, (char *) &yprv); _yp_unbind(ysd); return r; }