Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / host_port.c
blobec6b512d2892494251a312fef233e90aaf5cad21
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* host_port 3
6 /* SUMMARY
7 /* split string into host and port, destroy string
8 /* SYNOPSIS
9 /* #include <host_port.h>
11 /* const char *host_port(string, host, def_host, port, def_service)
12 /* char *string;
13 /* char **host;
14 /* char *def_host;
15 /* char **port;
16 /* char *def_service;
17 /* DESCRIPTION
18 /* host_port() splits a string into substrings with the host
19 /* name or address, and the service name or port number.
20 /* The input string is modified.
22 /* The following input formats are understood (null means
23 /* a null pointer argument):
25 /* When def_service is not null, and def_host is null:
27 /* [host]:port, [host]:, [host]
29 /* host:port, host:, host
31 /* When def_host is not null, and def_service is null:
33 /* :port, port
35 /* Other combinations of def_service and def_host are
36 /* not supported and produce undefined results.
37 /* DIAGNOSTICS
38 /* The result is a null pointer in case of success.
39 /* In case of problems the result is a string pointer with
40 /* the problem type.
41 /* CLIENT EXAMPLE
42 /* .ad
43 /* .fi
44 /* Typical client usage allows the user to omit the service port,
45 /* in which case the client connects to a pre-determined default
46 /* port:
47 /* .nf
48 /* .na
50 /* buf = mystrdup(endpoint);
51 /* if ((parse_error = host_port(buf, &host, NULL, &port, defport)) != 0)
52 /* msg_fatal("%s in \"%s\"", parse_error, endpoint);
53 /* if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res)) != 0)
54 /* msg_fatal("%s: %s", endpoint, MAI_STRERROR(aierr));
55 /* myfree(buf);
56 /* SERVER EXAMPLE
57 /* .ad
58 /* .fi
59 /* Typical server usage allows the user to omit the host, meaning
60 /* listen on all available network addresses:
61 /* .nf
62 /* .na
64 /* buf = mystrdup(endpoint);
65 /* if ((parse_error = host_port(buf, &host, "", &port, NULL)) != 0)
66 /* msg_fatal("%s in \"%s\"", parse_error, endpoint);
67 /* if (*host == 0)
68 /* host = 0;
69 /* if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res)) != 0)
70 /* msg_fatal("%s: %s", endpoint, MAI_STRERROR(aierr));
71 /* myfree(buf);
72 /* LICENSE
73 /* .ad
74 /* .fi
75 /* The Secure Mailer license must be distributed with this software.
76 /* AUTHOR(S)
77 /* Wietse Venema
78 /* IBM T.J. Watson Research
79 /* P.O. Box 704
80 /* Yorktown Heights, NY 10598, USA
81 /*--*/
83 /* System library. */
85 #include <sys_defs.h>
86 #include <string.h>
87 #include <ctype.h>
89 /* Utility library. */
91 #include <msg.h>
92 #include <split_at.h>
93 #include <stringops.h>
94 #include <valid_hostname.h>
96 /* Global library. */
98 #include <host_port.h>
100 /* host_port - parse string into host and port, destroy string */
102 const char *host_port(char *buf, char **host, char *def_host,
103 char **port, char *def_service)
105 char *cp = buf;
108 * [host]:port, [host]:, [host].
110 if (*cp == '[') {
111 *host = ++cp;
112 if ((cp = split_at(cp, ']')) == 0)
113 return ("missing \"]\"");
114 if (*cp && *cp++ != ':')
115 return ("garbage after \"]\"");
116 *port = *cp ? cp : def_service;
120 * host:port, host:, host, :port, port.
122 else {
123 if ((cp = split_at_right(buf, ':')) != 0) {
124 *host = *buf ? buf : def_host;
125 *port = *cp ? cp : def_service;
126 } else {
127 *host = def_host ? def_host : (*buf ? buf : 0);
128 *port = def_service ? def_service : (*buf ? buf : 0);
131 if (*host == 0)
132 return ("missing host information");
133 if (*port == 0)
134 return ("missing service information");
137 * Final sanity checks. We're still sloppy, allowing bare numerical
138 * network addresses instead of requiring proper [ipaddress] forms.
140 if (*host != def_host && !valid_hostname(*host, DONT_GRIPE)
141 && !valid_hostaddr(*host, DONT_GRIPE))
142 return ("valid hostname or network address required");
143 if (*port != def_service && ISDIGIT(**port) && !alldig(*port))
144 return ("garbage after numerical service");
145 return (0);
148 #ifdef TEST
150 #include <vstream.h>
151 #include <vstring.h>
152 #include <vstring_vstream.h>
154 #define STR(x) vstring_str(x)
156 int main(int unused_argc, char **unused_argv)
158 VSTRING *in_buf = vstring_alloc(10);
159 VSTRING *parse_buf = vstring_alloc(10);
160 char *host;
161 char *port;
162 const char *err;
164 while (vstring_fgets_nonl(in_buf, VSTREAM_IN)) {
165 vstream_printf(">> %s\n", STR(in_buf));
166 vstream_fflush(VSTREAM_OUT);
167 if (*STR(in_buf) == '#')
168 continue;
169 vstring_strcpy(parse_buf, STR(in_buf));
170 if ((err = host_port(STR(parse_buf), &host, (char *) 0, &port, "default-service")) != 0) {
171 msg_warn("%s in %s", err, STR(in_buf));
172 } else {
173 vstream_printf("host %s port %s\n", host, port);
174 vstream_fflush(VSTREAM_OUT);
177 vstring_free(in_buf);
178 vstring_free(parse_buf);
179 return (0);
182 #endif