+int avahi_service_name_join(char *p, size_t size, const char *name, const char *type, const char *domain) {
+ char escaped_name[AVAHI_LABEL_MAX*4];
+ char normalized_type[AVAHI_DOMAIN_NAME_MAX];
+ char normalized_domain[AVAHI_DOMAIN_NAME_MAX];
+
+ assert(p);
+
+ /* Validity checks */
+
+ if ((name && !avahi_is_valid_service_name(name)))
+ return AVAHI_ERR_INVALID_SERVICE_NAME;
+
+ if (!avahi_is_valid_service_type_generic(type))
+ return AVAHI_ERR_INVALID_SERVICE_TYPE;
+
+ if (!avahi_is_valid_domain_name(domain))
+ return AVAHI_ERR_INVALID_DOMAIN_NAME;
+
+ /* Preparation */
+
+ if (name) {
+ size_t l = sizeof(escaped_name);
+ char *e = escaped_name, *r;
+ r = avahi_escape_label(name, strlen(name), &e, &l);
+ assert(r);
+ }
+
+ if (!(avahi_normalize_name(type, normalized_type, sizeof(normalized_type))))
+ return AVAHI_ERR_INVALID_SERVICE_TYPE;
+
+ if (!(avahi_normalize_name(domain, normalized_domain, sizeof(normalized_domain))))
+ return AVAHI_ERR_INVALID_DOMAIN_NAME;
+
+ /* Concatenation */
+
+ snprintf(p, size, "%s%s%s.%s", name ? escaped_name : "", name ? "." : "", normalized_type, normalized_domain);
+
+ return AVAHI_OK;
+}
+
+#ifndef HAVE_STRLCPY
+
+static size_t strlcpy(char *dest, const char *src, size_t n) {
+ assert(dest);
+ assert(src);
+
+ if (n > 0) {
+ strncpy(dest, src, n-1);
+ dest[n-1] = 0;
+ }
+
+ return strlen(src);
+}
+
+#endif
+
+int avahi_service_name_split(const char *p, char *name, size_t name_size, char *type, size_t type_size, char *domain, size_t domain_size) {
+ enum {
+ NAME,
+ TYPE,
+ DOMAIN
+ } state;
+ int type_empty = 1, domain_empty = 1;
+
+ assert(p);
+ assert(type);
+ assert(type_size > 0);