/*++ /* NAME /* host_port 3 /* SUMMARY /* split string into host and port, destroy string /* SYNOPSIS /* #include /* /* const char *host_port(string, host, port, def_service) /* char *string; /* char **host; /* char **port; /* char *def_service; /* DESCRIPTION /* host_port() splits a string into substrings with the host /* name or address, and the service name or port number. /* The input string is modified. /* DIAGNOSTICS /* The result is a null pointer in case of success. /* In case of problems the result is a string pointer with /* the problem type. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include #include #include /* Utility library. */ #include #include #include #include /* Global library. */ #include /* host_port - parse string into host and port, destroy string */ const char *host_port(char *buf, char **host, char **port, char *def_service) { char *cp = buf; /* * [host]:port, [host]:, [host]. */ if (*cp == '[') { *host = ++cp; if ((cp = split_at(cp, ']')) == 0) return ("missing \"]\""); if (*cp && *cp++ != ':') return ("garbage after \"]\""); if (*cp == 0) *port = def_service; else *port = cp; /* * [host:port], [host:]. These conflict with IPV6 address literals. */ #if 1 if (strchr(*host, ':')) { msg_warn("old-style address form: [%s]", *host); msg_warn("support for [host:port] forms will go away"); msg_warn("specify [host]:port instead"); return (host_port(buf + 1, host, port, def_service)); } #endif } /* * host:port, host:, host. */ else { *host = cp; if ((cp = split_at_right(cp, ':')) == 0 || *cp == 0) *port = def_service; else *port = cp; } /* * Final sanity checks. We're still sloppy, allowing bare numerical * network addresses instead of requiring proper [ipaddress] forms. */ if (!valid_hostname(*host, DONT_GRIPE) && !valid_hostaddr(*host, DONT_GRIPE)) return ("valid hostname or network address required"); if (ISDIGIT(**port) && !alldig(*port)) return ("garbage after numerical service"); return (0); } #ifdef TEST #include #include #include #define STR(x) vstring_str(x) int main(int unused_argc, char **unused_argv) { VSTRING *in_buf = vstring_alloc(10); VSTRING *parse_buf = vstring_alloc(10); char *host; char *port; const char *err; while (vstring_fgets_nonl(in_buf, VSTREAM_IN)) { vstream_printf(">> %s\n", STR(in_buf)); vstream_fflush(VSTREAM_OUT); vstring_strcpy(parse_buf, STR(in_buf)); if ((err = host_port(STR(parse_buf), &host, &port, "default-service")) != 0) { msg_warn("%s in %s", err, STR(in_buf)); } else { vstream_printf("host %s port %s\n", host, port); vstream_fflush(VSTREAM_OUT); } } vstring_free(in_buf); vstring_free(parse_buf); return (0); } #endif