SLPError SLPOpen(const char *pcLang, SLPBoolean isAsync, SLPHandle *phSLP) { slp_handle_impl_t *hp; if (!pcLang || !phSLP) { return (SLP_PARAMETER_BAD); } /* allocate the handle */ if (!(hp = malloc(sizeof (*hp)))) { slp_err(LOG_CRIT, 0, "SLPOpen", "out of memory"); return (SLP_MEMORY_ALLOC_FAILED); } /* initialize outcall synchronization */ hp->pending_outcall = SLP_FALSE; (void) mutex_init(&(hp->outcall_lock), NULL, NULL); (void) cond_init(&(hp->outcall_cv), NULL, NULL); hp->close_on_end = SLP_FALSE; hp->consumer_tid = 0; /* locale property overrides argument */ if (!(hp->locale = SLPGetProperty(SLP_CONFIG_LOCALE))) { hp->locale = pcLang; } /* Make sure the language string is under our ownership */ if (!(hp->locale = strdup(hp->locale))) { free(hp); slp_err(LOG_CRIT, 0, "SLPOpen", "out of memory"); return (SLP_MEMORY_ALLOC_FAILED); } hp->cancel = 0; /* Asynchronous operation? */ if (isAsync) hp->async = SLP_TRUE; else hp->async = SLP_FALSE; /* TCP vars -- these are NULL until actually needed */ hp->tcp_lock = NULL; hp->tcp_wait = NULL; hp->tcp_ref_cnt = 0; /* Consumer / Producer pipe */ hp->q = NULL; /* Interface info, loaded on demand */ hp->ifinfo = NULL; /* force multicast, false by default */ hp->force_multicast = SLP_FALSE; /* internal call, false by default */ hp->internal_call = SLP_FALSE; *phSLP = hp; return (SLP_OK); }
/* * performs like strcasecmp, but also folds white space before comparing, * and will handle UTF-8 comparisons (including case). Note that the * application's locale must have been set to a UTF-8 locale for this * to work properly. */ int slp_strcasecmp(const char *s1, const char *s2) { int diff = -1; char *p1, *p2; size_t wcslen1, wcslen2; wchar_t *wcs1, *wcs2; p1 = p2 = NULL; wcs1 = wcs2 = NULL; /* optimization: try simple case first */ if (strcasecmp(s1, s2) == 0) return (0); /* fold white space, and try again */ p1 = slp_fold_space(s1); p2 = slp_fold_space(s2); if (!p1 || !p2) goto cleanup; if ((diff = strcasecmp(p1, p2)) == 0) goto cleanup; /* * try converting to wide char -- we must be in a locale which * supports the UTF8 codeset for this to work. */ if ((wcslen1 = mbstowcs(NULL, p1, 0)) == (size_t)-1) goto cleanup; if (!(wcs1 = malloc(sizeof (*wcs1) * (wcslen1 + 1)))) { slp_err(LOG_CRIT, 0, "slp_strcasecmp", "out of memory"); goto cleanup; } if ((wcslen2 = mbstowcs(NULL, p2, 0)) == (size_t)-1) goto cleanup; if (!(wcs2 = malloc(sizeof (*wcs2) * (wcslen2 + 1)))) { slp_err(LOG_CRIT, 0, "slp_strcasecmp", "out of memory"); goto cleanup; } if (mbstowcs(wcs1, p1, wcslen1 + 1) == (size_t)-1) goto cleanup; if (mbstowcs(wcs2, p2, wcslen2 + 1) == (size_t)-1) goto cleanup; diff = wscasecmp(wcs1, wcs2); cleanup: if (p1) free(p1); if (p2) free(p2); if (wcs1) free(wcs1); if (wcs2) free(wcs2); return (diff); }
/* * Adds item to *list if it is not already on it. If *list == NULL, * creates a new list. When it grows the list, it will free *list, * so *list must not be on the caller's stack. 'check_onlist' specifies * whether to look to item on the current list. This is a small * optimization for callers which are that item is not on *list, or * which don't care about duplicates. */ void slp_add2list(const char *item, char **list, SLPBoolean check_onlist) { if (!(*list)) { if (!(*list = strdup(item))) slp_err(LOG_CRIT, 0, "slp_add2list", "out of memory"); return; } if (check_onlist) /* no duplicates */ if (slp_onlist(item, *list)) return; if (!(*list = realloc(*list, strlen(*list) + strlen(item) + 2))) { slp_err(LOG_CRIT, 0, "slp_add2list", "out of memory"); return; } (void) strcat(*list, ","); (void) strcat(*list, item); }
static void collate_attrs(char *attrs, void **collator, int *numResults, int maxResults) { char *start, *end; struct attr_node *n, **res; for (start = attrs; start && *start && *numResults != maxResults; start = end) { if (*start == ',') start++; if (*start == '(') { /* form of (tag=val,val) */ if (!(end = slp_utf_strchr(start, ')'))) return; /* skip bad attr */ parens_attr(start, collator, numResults); end++; continue; } end = slp_utf_strchr(start, ','); if (end) *end++ = 0; /* create a new node with the tag only */ if (!(n = malloc(sizeof (*n)))) { slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); return; } if (!(n->tag = strdup(start))) { free(n); slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); return; } n->val = NULL; res = slp_tsearch(n, collator, compare_tags); if (*res != n) { /* already in the tree, so just free resources */ free(n->tag); free(n); } (*numResults)++; } }
static void parens_attr(char *attr, void **collator, int *numResults) { char *open_paren, *close_paren, *equals; struct attr_node *n, **res; open_paren = attr + 1; close_paren = slp_utf_strchr(open_paren, ')'); if (!close_paren) return; /* skip bad attr list */ *close_paren = 0; if (!(equals = slp_utf_strchr(open_paren, '='))) return; *equals++ = 0; if (!(n = malloc(sizeof (*n)))) { slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); return; } if (!(n->tag = strdup(open_paren))) { free(n); slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); return; } n->val = NULL; res = slp_tsearch(n, collator, compare_tags); if (*res != n) { merge_attrs(*res, equals); free(n->tag); free(n); } else { /* not found; populate new attr node */ (*numResults)++; if (!(n->val = strdup(equals))) { slp_err(LOG_CRIT, 0, "collate_attrs", "out of memory"); return; } } }
/*ARGSUSED*/ static void collect_attrs(void *node, VISIT order, int level, void *cookie) { struct attr_node *n; char *attr, *p, **answer = (char **)cookie; if (order == endorder || order == leaf) { n = *(struct attr_node **)node; if (!n->val) { /* no values, so no parens */ if (!(attr = malloc(strlen(n->tag) + 1))) { slp_err(LOG_CRIT, 0, "collect_attrs", "out of memory"); return; } (void) strcpy(attr, n->tag); } else { if (!(attr = malloc(1 + strlen(n->tag) + 1 + strlen(n->val) + 2))) { slp_err(LOG_CRIT, 0, "collect_attrs", "out of memory"); return; } /* build attr string */ p = attr; *p++ = '('; (void) strcpy(p, n->tag); p += strlen(n->tag); *p++ = '='; (void) strcpy(p, n->val); p += strlen(n->val); *p++ = ')'; *p = 0; } slp_add2list(attr, answer, SLP_FALSE); free(attr); free(n->tag); if (n->val) free(n->val); free(n); free(node); } }
unsigned short SLPGetRefreshInterval() { slp_handle_impl_t *hp; /* SLP handle for this request */ SLPError err; /* any SLPError */ char *reply = NULL; /* reply from slpd */ void *collator = NULL; /* attr collation handle */ int mr = 0; /* max results placeholder */ unsigned short max = 0; /* max interval result cookie */ char *msg = NULL; /* attrrqst msg */ char hostname[MAXHOSTNAMELEN]; /* name of this host */ if ((err = SLPOpen("en", SLP_FALSE, (void **)&hp)) != SLP_OK) { slp_err(LOG_INFO, 0, "SLPGetRefreshInterval", "Could not get SLPHandle: %s", slp_strerror(err)); return (0); } /* tag this as an internal call */ hp->internal_call = SLP_TRUE; /* scope is name of this host */ (void) gethostname(hostname, MAXHOSTNAMELEN); if (slp_packAttrRqst_single(SLP_SUN_DA_TYPE, hostname, "min-refresh-interval", &msg, "en") != SLP_OK) { goto done; } if (slp_send2slpd(msg, &reply) != SLP_OK) { goto done; } (void) slp_UnpackAttrReply(hp, reply, refresh_interval_cb, &max, &collator, &mr); /* clean up by invoking last call */ (void) slp_UnpackAttrReply(hp, NULL, refresh_interval_cb, &max, &collator, &mr); done: if (msg) free(msg); if (reply) free(reply); SLPClose(hp); return (max); }
/* * folds white space around and in between words. * " aa bb " becomes "aa bb". * returns NULL if it couldn't allocate memory. The caller must free * the result when done. */ static char *slp_fold_space(const char *s) { int len; char *folded, *f; if (!(folded = malloc(strlen(s) + 1))) { slp_err(LOG_CRIT, 0, "slp_fold_space", "out of memory"); return (NULL); } f = folded; for (;;) { /* step 1: skip white space */ for (; *s; s++) { len = mblen(s, MB_CUR_MAX); if (len != 1) break; if (!isspace(*s)) break; } if (!*s) { /* end of string */ *f = 0; return (folded); } /* if we are in between words, keep one space */ if (f != folded) *f++ = ' '; /* step 2: copy into folded until we hit more white space */ while (*s) { int i; len = mblen(s, MB_CUR_MAX); if (len == 1 && isspace(*s)) break; for (i = 0; i < len; i++) *f++ = *s++; } *f = *s; if (!*s++) return (folded); } }
SLPError slp_packAttrRqst_single(const char *url, const char *scopes, const char *ids, char **msg, const char *lang) { SLPError err; size_t len, msgLen; msgLen = SLP_HDRLEN + strlen(lang) + 2 + 2 + strlen(url) + 2 + strlen(scopes) + 2 + strlen(ids) + 2; /* No SPI string for internal calls */ if (!(*msg = calloc(msgLen, 1))) { slp_err(LOG_CRIT, 0, "slp_packAttrRqst_single", "out of memory"); return (SLP_MEMORY_ALLOC_FAILED); } len = 0; err = slp_add_header(lang, *msg, msgLen, ATTRRQST, msgLen, &len); len += 2; /* empty PR list */ if (err == SLP_OK) { err = slp_add_string(*msg, msgLen, url, &len); } if (err == SLP_OK) { err = slp_add_string(*msg, msgLen, scopes, &len); } if (err == SLP_OK) { err = slp_add_string(*msg, msgLen, ids, &len); } /* empty SPI */ if (err == SLP_OK) { err = slp_add_string(*msg, msgLen, "", &len); } return (err); }
static SLPError slp_packAttrRqst(slp_handle_impl_t *hp, const char *url, const char *ids) { SLPError err; size_t len, tmplen, msgLen; slp_msg_t *msg = &(hp->msg); char *spi = NULL; if (slp_get_security_on()) { spi = (char *)SLPGetProperty(SLP_CONFIG_SPI); } if (!spi || !*spi) { spi = ""; } /* * Allocate iovec for the messge. An AttrRqst is layed out thus: * 0: header * 1: prlist length * 2: prlist (filled in later by networking code) * 3: URL string * 4: scopes length * 5: scopes (filled in later by networking code) * 6: tag list string and SPI string */ if (!(msg->iov = calloc(7, sizeof (*(msg->iov))))) { slp_err(LOG_CRIT, 0, "slp_packAttrRqst", "out of memory"); return (SLP_MEMORY_ALLOC_FAILED); } msg->iovlen = 7; /* calculate msg length */ msgLen = 2 + /* prlist length */ 2 + strlen(url) + /* URL */ 2 + /* scope list length */ 2 + strlen(ids) + /* tag list */ 2 + strlen(spi); /* SPI string */ if (!(msg->msg = calloc(1, msgLen))) { free(msg->iov); slp_err(LOG_CRIT, 0, "slp_packAttrRqst", "out of memory"); return (SLP_MEMORY_ALLOC_FAILED); } /* set pointer to PR list and scope list length spaces */ msg->prlistlen.iov_base = msg->msg; msg->prlistlen.iov_len = 2; msg->iov[1].iov_base = msg->msg; msg->iov[1].iov_len = 2; msg->scopeslen.iov_base = msg->msg + 2; msg->scopeslen.iov_len = 2; msg->iov[4].iov_base = msg->msg + 2; msg->iov[4].iov_len = 2; /* set up the scopes and prlist pointers into iov */ msg->prlist = &(msg->iov[2]); msg->scopes = &(msg->iov[5]); len = 4; /* Add URL string */ msg->iov[3].iov_base = msg->msg + len; tmplen = len; err = slp_add_string(msg->msg, msgLen, url, &len); msg->iov[3].iov_len = len - tmplen; if (err != SLP_OK) goto error; /* Add tag list */ msg->iov[6].iov_base = msg->msg + len; tmplen = len; err = slp_add_string(msg->msg, msgLen, ids, &len); if (err != SLP_OK) goto error; /* SPI string */ err = slp_add_string(msg->msg, msgLen, spi, &len); msg->iov[6].iov_len = len - tmplen; hp->fid = ATTRRQST; if (err == SLP_OK) { return (SLP_OK); } /* else error */ error: free(msg->iov); free(msg->msg); return (err); }