Beispiel #1
0
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);
}
Beispiel #2
0
/*
 * 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);
}
Beispiel #3
0
/*
 * 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);
}
Beispiel #4
0
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)++;
	}
}
Beispiel #5
0
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;
		}
	}
}
Beispiel #6
0
/*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);
}
Beispiel #8
0
/*
 * 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);
	}
}
Beispiel #9
0
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);
}
Beispiel #10
0
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);
}