- * Returns 0 on success, otherwise a positive errno value. On success,
- * '*dirfdp' is either -1 or a nonnegative file descriptor that the caller
- * should close after using '*un' to bind or connect. On failure, '*dirfdp' is
- * -1. */
-static int
-make_sockaddr_un(const char *name, struct sockaddr_un *un, socklen_t *un_len,
- int *dirfdp)
-{
- enum { MAX_UN_LEN = sizeof un->sun_path - 1 };
-
- *dirfdp = -1;
- if (strlen(name) > MAX_UN_LEN) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-
- if (LINUX_DATAPATH) {
- /* 'name' is too long to fit in a sockaddr_un, but we have a
- * workaround for that on Linux: shorten it by opening a file
- * descriptor for the directory part of the name and indirecting
- * through /proc/self/fd/<dirfd>/<basename>. */
- char *dir, *base;
- char *short_name;
- int dirfd;
-
- dir = dir_name(name);
- base = base_name(name);
-
- dirfd = open(dir, O_DIRECTORY | O_RDONLY);
- if (dirfd < 0) {
- free(base);
- free(dir);
- return errno;
- }
-
- short_name = xasprintf("/proc/self/fd/%d/%s", dirfd, base);
- free(dir);
- free(base);
-
- if (strlen(short_name) <= MAX_UN_LEN) {
- make_sockaddr_un__(short_name, un, un_len);
- free(short_name);
- *dirfdp = dirfd;
- return 0;
- }
- free(short_name);
- close(dirfd);
-
- VLOG_WARN_RL(&rl, "Unix socket name %s is longer than maximum "
- "%d bytes (even shortened)", name, MAX_UN_LEN);
- } else {
- /* 'name' is too long and we have no workaround. */
- VLOG_WARN_RL(&rl, "Unix socket name %s is longer than maximum "
- "%d bytes", name, MAX_UN_LEN);
- }
-
- return ENAMETOOLONG;
+ * - The separator string is ":".
+ *
+ * - Square brackets [] quote ":" separators and are removed from the
+ * tokens. */
+static char *
+parse_bracketed_token(char **pp)
+{
+ char *p = *pp;
+
+ if (p == NULL) {
+ return NULL;
+ } else if (*p == '\0') {
+ *pp = NULL;
+ return p;
+ } else if (*p == '[') {
+ char *start = p + 1;
+ char *end = start + strcspn(start, "]");
+ *pp = (*end == '\0' ? NULL
+ : end[1] == ':' ? end + 2
+ : end + 1);
+ *end = '\0';
+ return start;