]>
Commit | Line | Data |
---|---|---|
e92958ad | 1 | /* |
c9d3f842 | 2 | * "$Id$" |
e92958ad | 3 | * |
4 | * HTTP address routines for the Common UNIX Printing System (CUPS). | |
5 | * | |
c9d3f842 | 6 | * Copyright 1997-2005 by Easy Software Products, all rights reserved. |
e92958ad | 7 | * |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
17 | * 44141 Airport View Drive, Suite 204 | |
c9d3f842 | 18 | * Hollywood, Maryland 20636 USA |
e92958ad | 19 | * |
c4dcf3cc | 20 | * Voice: (301) 373-9600 |
e92958ad | 21 | * EMail: cups-info@cups.org |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * Contents: | |
25 | * | |
0f71c41e | 26 | * httpAddrAny() - Check for the "any" address. |
e92958ad | 27 | * httpAddrEqual() - Compare two addresses. |
28 | * httpAddrLoad() - Load a host entry address into an HTTP address. | |
29 | * httpAddrLocalhost() - Check for the local loopback address. | |
30 | * httpAddrLookup() - Lookup the hostname associated with the address. | |
31 | * httpAddrString() - Convert an IP address to a dotted string. | |
365cfbcc | 32 | * httpGetHostByName() - Lookup a hostname or IP address, and return |
33 | * address records for the specified name. | |
e92958ad | 34 | */ |
35 | ||
36 | /* | |
37 | * Include necessary headers... | |
38 | */ | |
39 | ||
03f61bf3 | 40 | #include "globals.h" |
e92958ad | 41 | #include "debug.h" |
7c298ddc | 42 | #include <stdlib.h> |
e92958ad | 43 | |
44 | ||
0f71c41e | 45 | /* |
46 | * 'httpAddrAny()' - Check for the "any" address. | |
47 | */ | |
48 | ||
49 | int /* O - 1 if "any", 0 otherwise */ | |
50 | httpAddrAny(const http_addr_t *addr) /* I - Address to check */ | |
51 | { | |
52 | #ifdef AF_INET6 | |
53 | if (addr->addr.sa_family == AF_INET6 && | |
54 | IN6_IS_ADDR_UNSPECIFIED(&(addr->ipv6.sin6_addr))) | |
55 | return (1); | |
56 | #endif /* AF_INET6 */ | |
57 | ||
58 | if (addr->addr.sa_family == AF_INET && | |
59 | ntohl(addr->ipv4.sin_addr.s_addr) == 0x00000000) | |
60 | return (1); | |
61 | ||
62 | return (0); | |
63 | } | |
64 | ||
65 | ||
e92958ad | 66 | /* |
67 | * 'httpAddrEqual()' - Compare two addresses. | |
68 | */ | |
69 | ||
70 | int /* O - 1 if equal, 0 if != */ | |
71 | httpAddrEqual(const http_addr_t *addr1, /* I - First address */ | |
72 | const http_addr_t *addr2) /* I - Second address */ | |
73 | { | |
74 | if (addr1->addr.sa_family != addr2->addr.sa_family) | |
75 | return (0); | |
76 | ||
928c0377 | 77 | #ifdef AF_LOCAL |
78 | if (addr1->addr.sa_family == AF_LOCAL) | |
79 | return (!strcmp(addr1->un.sun_path, addr2->un.sun_path)); | |
80 | #endif /* AF_LOCAL */ | |
81 | ||
e92958ad | 82 | #ifdef AF_INET6 |
83 | if (addr1->addr.sa_family == AF_INET6) | |
84 | return (memcmp(&(addr1->ipv6.sin6_addr), &(addr2->ipv6.sin6_addr), 16) == 0); | |
85 | #endif /* AF_INET6 */ | |
86 | ||
87 | return (addr1->ipv4.sin_addr.s_addr == addr2->ipv4.sin_addr.s_addr); | |
88 | } | |
89 | ||
90 | ||
a36f3f3d | 91 | /* |
92 | * 'httpAddrLength()' - Return the length of the address in bytes. | |
93 | */ | |
94 | ||
95 | int /* O - Length in bytes */ | |
96 | httpAddrLength(const http_addr_t *addr) /* I - Address */ | |
97 | { | |
98 | #ifdef AF_INET6 | |
99 | if (addr->addr.sa_family == AF_INET6) | |
100 | return (sizeof(addr->ipv6)); | |
101 | else | |
102 | #endif /* AF_INET6 */ | |
103 | #ifdef AF_LOCAL | |
104 | if (addr->addr.sa_family == AF_LOCAL) | |
105 | return (sizeof(addr->un.sun_family) + strlen(addr->un.sun_path)); | |
106 | else | |
107 | #endif /* AF_LOCAL */ | |
108 | if (addr->addr.sa_family == AF_INET) | |
109 | return (sizeof(addr->ipv4)); | |
110 | else | |
111 | return (0); | |
112 | ||
113 | } | |
114 | ||
115 | ||
e92958ad | 116 | /* |
117 | * 'httpAddrLoad()' - Load a host entry address into an HTTP address. | |
118 | */ | |
119 | ||
120 | void | |
121 | httpAddrLoad(const struct hostent *host, /* I - Host entry */ | |
122 | int port, /* I - Port number */ | |
123 | int n, /* I - Index into host entry */ | |
124 | http_addr_t *addr) /* O - Address to load */ | |
125 | { | |
126 | #ifdef AF_INET6 | |
127 | if (host->h_addrtype == AF_INET6) | |
128 | { | |
129 | # ifdef WIN32 | |
130 | addr->ipv6.sin6_port = htons((u_short)port); | |
131 | # else | |
132 | addr->ipv6.sin6_port = htons(port); | |
133 | # endif /* WIN32 */ | |
134 | ||
135 | memcpy((char *)&(addr->ipv6.sin6_addr), host->h_addr_list[n], | |
136 | host->h_length); | |
ed093015 | 137 | addr->ipv6.sin6_family = AF_INET6; |
e92958ad | 138 | } |
139 | else | |
140 | #endif /* AF_INET6 */ | |
1fcc120e | 141 | #ifdef AF_LOCAL |
142 | if (host->h_addrtype == AF_LOCAL) | |
143 | { | |
144 | addr->un.sun_family = AF_LOCAL; | |
145 | strlcpy(addr->un.sun_path, host->h_addr_list[n], sizeof(addr->un.sun_path)); | |
146 | } | |
147 | else | |
148 | #endif /* AF_LOCAL */ | |
149 | if (host->h_addrtype == AF_INET) | |
e92958ad | 150 | { |
151 | # ifdef WIN32 | |
152 | addr->ipv4.sin_port = htons((u_short)port); | |
153 | # else | |
154 | addr->ipv4.sin_port = htons(port); | |
155 | # endif /* WIN32 */ | |
156 | ||
157 | memcpy((char *)&(addr->ipv4.sin_addr), host->h_addr_list[n], | |
158 | host->h_length); | |
ed093015 | 159 | addr->ipv4.sin_family = AF_INET; |
e92958ad | 160 | } |
161 | } | |
162 | ||
163 | ||
164 | /* | |
165 | * 'httpAddrLocalhost()' - Check for the local loopback address. | |
166 | */ | |
167 | ||
0f71c41e | 168 | int /* O - 1 if local host, 0 otherwise */ |
169 | httpAddrLocalhost(const http_addr_t *addr) | |
170 | /* I - Address to check */ | |
e92958ad | 171 | { |
172 | #ifdef AF_INET6 | |
173 | if (addr->addr.sa_family == AF_INET6 && | |
7c298ddc | 174 | (IN6_IS_ADDR_LOOPBACK(&(addr->ipv6.sin6_addr)) || |
175 | IN6_IS_ADDR_UNSPECIFIED(&(addr->ipv6.sin6_addr)))) | |
e92958ad | 176 | return (1); |
177 | #endif /* AF_INET6 */ | |
178 | ||
8eba4f2f | 179 | #ifdef AF_LOCAL |
c6075312 | 180 | if (addr->addr.sa_family == AF_LOCAL) |
181 | return (1); | |
8eba4f2f | 182 | #endif /* AF_LOCAL */ |
c6075312 | 183 | |
e92958ad | 184 | if (addr->addr.sa_family == AF_INET && |
185 | ntohl(addr->ipv4.sin_addr.s_addr) == 0x7f000001) | |
186 | return (1); | |
187 | ||
188 | return (0); | |
189 | } | |
190 | ||
191 | ||
192 | #ifdef __sgi | |
193 | # define ADDR_CAST (struct sockaddr *) | |
194 | #else | |
195 | # define ADDR_CAST (char *) | |
196 | #endif /* __sgi */ | |
197 | ||
198 | ||
199 | /* | |
200 | * 'httpAddrLookup()' - Lookup the hostname associated with the address. | |
201 | */ | |
202 | ||
203 | char * /* O - Host name */ | |
204 | httpAddrLookup(const http_addr_t *addr, /* I - Address to lookup */ | |
205 | char *name, /* I - Host name buffer */ | |
206 | int namelen) /* I - Size of name buffer */ | |
207 | { | |
208 | struct hostent *host; /* Host from name service */ | |
209 | ||
210 | ||
8eba4f2f | 211 | DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n", |
212 | addr, name, namelen)); | |
213 | ||
e92958ad | 214 | #ifdef AF_INET6 |
215 | if (addr->addr.sa_family == AF_INET6) | |
216 | host = gethostbyaddr(ADDR_CAST &(addr->ipv6.sin6_addr), | |
217 | sizeof(struct in6_addr), AF_INET6); | |
218 | else | |
219 | #endif /* AF_INET6 */ | |
1fcc120e | 220 | #ifdef AF_LOCAL |
221 | if (addr->addr.sa_family == AF_LOCAL) | |
222 | { | |
223 | strlcpy(name, addr->un.sun_path, namelen); | |
224 | return (name); | |
225 | } | |
226 | else | |
227 | #endif /* AF_LOCAL */ | |
e92958ad | 228 | if (addr->addr.sa_family == AF_INET) |
229 | host = gethostbyaddr(ADDR_CAST &(addr->ipv4.sin_addr), | |
230 | sizeof(struct in_addr), AF_INET); | |
231 | else | |
232 | host = NULL; | |
233 | ||
234 | if (host == NULL) | |
235 | { | |
236 | httpAddrString(addr, name, namelen); | |
237 | return (NULL); | |
238 | } | |
239 | ||
1fcc120e | 240 | strlcpy(name, host->h_name, namelen); |
e92958ad | 241 | |
242 | return (name); | |
243 | } | |
244 | ||
245 | ||
246 | /* | |
247 | * 'httpAddrString()' - Convert an IP address to a dotted string. | |
248 | */ | |
249 | ||
250 | char * /* O - IP string */ | |
251 | httpAddrString(const http_addr_t *addr, /* I - Address to convert */ | |
252 | char *s, /* I - String buffer */ | |
253 | int slen) /* I - Length of string */ | |
254 | { | |
8eba4f2f | 255 | DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n", |
256 | addr, s, slen)); | |
257 | ||
e92958ad | 258 | #ifdef AF_INET6 |
259 | if (addr->addr.sa_family == AF_INET6) | |
7c298ddc | 260 | snprintf(s, slen, "[%x:%x:%x:%x]", |
e92958ad | 261 | ntohl(addr->ipv6.sin6_addr.s6_addr32[0]), |
262 | ntohl(addr->ipv6.sin6_addr.s6_addr32[1]), | |
263 | ntohl(addr->ipv6.sin6_addr.s6_addr32[2]), | |
264 | ntohl(addr->ipv6.sin6_addr.s6_addr32[3])); | |
265 | else | |
266 | #endif /* AF_INET6 */ | |
c6075312 | 267 | #ifdef AF_LOCAL |
268 | if (addr->addr.sa_family == AF_LOCAL) | |
269 | strlcpy(s, addr->un.sun_path, slen); | |
270 | else | |
271 | #endif /* AF_LOCAL */ | |
e92958ad | 272 | if (addr->addr.sa_family == AF_INET) |
273 | { | |
274 | unsigned temp; /* Temporary address */ | |
275 | ||
276 | ||
277 | temp = ntohl(addr->ipv4.sin_addr.s_addr); | |
278 | ||
279 | snprintf(s, slen, "%d.%d.%d.%d", (temp >> 24) & 255, | |
280 | (temp >> 16) & 255, (temp >> 8) & 255, temp & 255); | |
281 | } | |
282 | else | |
c6075312 | 283 | strlcpy(s, "UNKNOWN", slen); |
e92958ad | 284 | |
8eba4f2f | 285 | DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s)); |
286 | ||
e92958ad | 287 | return (s); |
288 | } | |
289 | ||
290 | ||
291 | /* | |
365cfbcc | 292 | * 'httpGetHostByName()' - Lookup a hostname or IP address, and return |
293 | * address records for the specified name. | |
294 | */ | |
295 | ||
296 | struct hostent * /* O - Host entry */ | |
297 | httpGetHostByName(const char *name) /* I - Hostname or IP address */ | |
298 | { | |
7c298ddc | 299 | int i; /* Looping var */ |
365cfbcc | 300 | const char *nameptr; /* Pointer into name */ |
301 | unsigned ip[4]; /* IP address components */ | |
2625096f | 302 | _cups_globals_t *cg = _cupsGlobals(); |
03f61bf3 | 303 | /* Pointer to library globals */ |
365cfbcc | 304 | |
6db7190f | 305 | |
8eba4f2f | 306 | DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name)); |
307 | ||
03f61bf3 | 308 | /* |
309 | * Avoid lookup delays and configuration problems when connecting | |
310 | * to the localhost address... | |
311 | */ | |
312 | ||
7c298ddc | 313 | if (!strcmp(name, "localhost")) |
03f61bf3 | 314 | name = "127.0.0.1"; |
365cfbcc | 315 | |
316 | /* | |
317 | * This function is needed because some operating systems have a | |
318 | * buggy implementation of gethostbyname() that does not support | |
319 | * IP addresses. If the first character of the name string is a | |
320 | * number, then sscanf() is used to extract the IP components. | |
321 | * We then pack the components into an IPv4 address manually, | |
322 | * since the inet_aton() function is deprecated. We use the | |
323 | * htonl() macro to get the right byte order for the address. | |
1fcc120e | 324 | * |
325 | * We also support domain sockets when supported by the underlying | |
326 | * OS... | |
365cfbcc | 327 | */ |
328 | ||
1fcc120e | 329 | #ifdef AF_LOCAL |
330 | if (name[0] == '/') | |
331 | { | |
332 | /* | |
333 | * A domain socket address, so make an AF_LOCAL entry and return it... | |
334 | */ | |
335 | ||
03f61bf3 | 336 | cg->hostent.h_name = (char *)name; |
337 | cg->hostent.h_aliases = NULL; | |
338 | cg->hostent.h_addrtype = AF_LOCAL; | |
339 | cg->hostent.h_length = strlen(name) + 1; | |
340 | cg->hostent.h_addr_list = cg->ip_ptrs; | |
341 | cg->ip_ptrs[0] = (char *)name; | |
342 | cg->ip_ptrs[1] = NULL; | |
1fcc120e | 343 | |
8eba4f2f | 344 | DEBUG_puts("httpGetHostByName: returning domain socket address..."); |
345 | ||
03f61bf3 | 346 | return (&cg->hostent); |
1fcc120e | 347 | } |
348 | #endif /* AF_LOCAL */ | |
7c298ddc | 349 | #ifdef AF_INET6 |
350 | if (name[0] == '[') | |
351 | { | |
352 | /* | |
353 | * A raw 128-bit IPv6 address of the form "[xxxx:xxxx:xxxx:xxxx]" | |
354 | */ | |
355 | ||
03f61bf3 | 356 | cg->hostent.h_name = (char *)name; |
357 | cg->hostent.h_aliases = NULL; | |
358 | cg->hostent.h_addrtype = AF_INET6; | |
359 | cg->hostent.h_length = 16; | |
360 | cg->hostent.h_addr_list = cg->ip_ptrs; | |
361 | cg->ip_ptrs[0] = (char *)(cg->ip_addrs[0]); | |
362 | cg->ip_ptrs[1] = NULL; | |
7c298ddc | 363 | |
364 | for (i = 0, nameptr = name + 1; *nameptr && i < 4; i ++) | |
365 | { | |
366 | if (*nameptr == ']') | |
367 | break; | |
368 | else if (*nameptr == ':') | |
03f61bf3 | 369 | cg->ip_addrs[0][i] = 0; |
7c298ddc | 370 | else |
03f61bf3 | 371 | cg->ip_addrs[0][i] = htonl(strtoul(nameptr, (char **)&nameptr, 16)); |
7c298ddc | 372 | |
373 | if (*nameptr == ':' || *nameptr == ']') | |
374 | nameptr ++; | |
375 | } | |
376 | ||
377 | while (i < 4) | |
378 | { | |
03f61bf3 | 379 | cg->ip_addrs[0][i] = 0; |
7c298ddc | 380 | i ++; |
381 | } | |
382 | ||
383 | if (*nameptr) | |
384 | return (NULL); | |
385 | ||
386 | DEBUG_puts("httpGetHostByName: returning IPv6 address..."); | |
387 | ||
03f61bf3 | 388 | return (&cg->hostent); |
7c298ddc | 389 | } |
390 | #endif /* AF_INET6 */ | |
1fcc120e | 391 | |
64bbab09 | 392 | for (nameptr = name; isdigit(*nameptr & 255) || *nameptr == '.'; nameptr ++); |
365cfbcc | 393 | |
394 | if (!*nameptr) | |
395 | { | |
396 | /* | |
7c298ddc | 397 | * We have an IPv4 address; break it up and provide the host entry |
398 | * to the caller. | |
365cfbcc | 399 | */ |
400 | ||
401 | if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) != 4) | |
c5b73e9f | 402 | return (NULL); /* Must have 4 numbers */ |
403 | ||
404 | if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255) | |
405 | return (NULL); /* Invalid byte ranges! */ | |
365cfbcc | 406 | |
03f61bf3 | 407 | cg->ip_addrs[0][0] = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | |
7c298ddc | 408 | ip[3])); |
365cfbcc | 409 | |
410 | /* | |
411 | * Fill in the host entry and return it... | |
412 | */ | |
413 | ||
03f61bf3 | 414 | cg->hostent.h_name = (char *)name; |
415 | cg->hostent.h_aliases = NULL; | |
416 | cg->hostent.h_addrtype = AF_INET; | |
417 | cg->hostent.h_length = 4; | |
418 | cg->hostent.h_addr_list = cg->ip_ptrs; | |
419 | cg->ip_ptrs[0] = (char *)cg->ip_addrs[0]; | |
420 | cg->ip_ptrs[1] = NULL; | |
365cfbcc | 421 | |
8eba4f2f | 422 | DEBUG_puts("httpGetHostByName: returning IPv4 address..."); |
423 | ||
03f61bf3 | 424 | return (&cg->hostent); |
365cfbcc | 425 | } |
426 | else | |
7c298ddc | 427 | #ifdef HAVE_GETADDRINFO |
428 | { | |
429 | /* | |
430 | * Use the getaddrinfo() function to get the IP address for the | |
431 | * name... | |
432 | */ | |
433 | ||
434 | struct addrinfo hints, /* Address lookup hints */ | |
435 | *results, /* Address lookup results */ | |
436 | *current; /* Current result */ | |
437 | http_addr_t *address; /* Current address */ | |
438 | ||
439 | ||
440 | memset(&hints, 0, sizeof(hints)); | |
441 | hints.ai_family = PF_UNSPEC; | |
442 | hints.ai_socktype = SOCK_STREAM; | |
443 | hints.ai_flags = AI_CANONNAME; | |
444 | ||
445 | if (getaddrinfo(name, NULL, &hints, &results)) | |
446 | { | |
447 | /* | |
448 | * If getaddrinfo() fails, try gethostbyname()... | |
449 | */ | |
450 | ||
451 | return (gethostbyname(name)); | |
452 | } | |
453 | ||
454 | /* | |
455 | * Initialize hostent structure, preferring the IPv6 address... | |
456 | */ | |
457 | ||
458 | for (current = results; current; current = current->ai_next) | |
459 | if (current->ai_family == AF_INET6) | |
460 | break; | |
461 | ||
462 | if (!current) | |
463 | { | |
464 | for (current = results; current; current = current->ai_next) | |
465 | if (current->ai_family == AF_INET) | |
466 | break; | |
467 | ||
468 | if (!current) | |
469 | { | |
470 | /* | |
471 | * No IPv4 or IPv6 addresses, try gethostbyname()... | |
472 | */ | |
473 | ||
474 | freeaddrinfo(results); | |
475 | ||
476 | return (gethostbyname(name)); | |
477 | } | |
478 | } | |
479 | ||
03f61bf3 | 480 | strlcpy(cg->hostname, current->ai_canonname, sizeof(cg->hostname)); |
7c298ddc | 481 | |
03f61bf3 | 482 | cg->hostent.h_name = cg->hostname; |
483 | cg->hostent.h_aliases = NULL; | |
484 | cg->hostent.h_addrtype = current->ai_family; | |
485 | cg->hostent.h_addr_list = cg->ip_ptrs; | |
7c298ddc | 486 | |
f5f4dd62 | 487 | if (current->ai_family == AF_INET6) |
03f61bf3 | 488 | cg->hostent.h_length = 16; |
f5f4dd62 | 489 | else |
03f61bf3 | 490 | cg->hostent.h_length = 4; |
f5f4dd62 | 491 | |
7c298ddc | 492 | /* |
493 | * Convert the address info to a hostent structure... | |
494 | */ | |
495 | ||
03f61bf3 | 496 | for (i = 0, current = results; |
497 | i < CUPS_MAX_ADDRS && current; | |
498 | current = current->ai_next) | |
499 | if (current->ai_family == cg->hostent.h_addrtype) | |
7c298ddc | 500 | { |
501 | /* | |
502 | * Copy this address... | |
503 | */ | |
504 | ||
505 | address = (http_addr_t *)(current->ai_addr); | |
506 | ||
507 | if (current->ai_family == AF_INET) | |
03f61bf3 | 508 | memcpy((char *)cg->ip_addrs[i], (char *)&(address->ipv4.sin_addr), 4); |
7c298ddc | 509 | else |
03f61bf3 | 510 | memcpy((char *)cg->ip_addrs[i], (char *)&(address->ipv6.sin6_addr), 16); |
7c298ddc | 511 | |
03f61bf3 | 512 | cg->ip_ptrs[i] = (char *)cg->ip_addrs[i]; |
7c298ddc | 513 | i ++; |
514 | } | |
515 | ||
03f61bf3 | 516 | cg->ip_ptrs[i] = NULL; |
7c298ddc | 517 | |
518 | /* | |
519 | * Free the getaddrinfo() results and return the hostent structure... | |
520 | */ | |
521 | ||
522 | freeaddrinfo(results); | |
523 | ||
03f61bf3 | 524 | return (&cg->hostent); |
7c298ddc | 525 | } |
526 | #else | |
365cfbcc | 527 | { |
528 | /* | |
529 | * Use the gethostbyname() function to get the IP address for | |
530 | * the name... | |
531 | */ | |
532 | ||
8eba4f2f | 533 | DEBUG_puts("httpGetHostByName: returning domain lookup address(es)..."); |
534 | ||
365cfbcc | 535 | return (gethostbyname(name)); |
536 | } | |
7c298ddc | 537 | #endif /* HAVE_GETADDRINFO */ |
365cfbcc | 538 | } |
539 | ||
540 | ||
0a283777 | 541 | /* |
542 | * 'httpGetHostname()' - Get the FQDN for the local system. | |
543 | * | |
544 | * This function uses both gethostname() and gethostbyname() to | |
545 | * get the local hostname with domain. | |
546 | */ | |
547 | ||
548 | const char * /* O - FQDN for this system */ | |
549 | httpGetHostname(char *s, /* I - String buffer for name */ | |
550 | int slen) /* I - Size of buffer */ | |
551 | { | |
552 | struct hostent *host; /* Host entry to get FQDN */ | |
553 | ||
554 | ||
555 | /* | |
556 | * Get the hostname... | |
557 | */ | |
558 | ||
559 | gethostname(s, slen); | |
560 | ||
561 | if (!strchr(s, '.')) | |
562 | { | |
563 | /* | |
564 | * The hostname is not a FQDN, so look it up... | |
565 | */ | |
566 | ||
567 | if ((host = gethostbyname(s)) != NULL) | |
568 | strlcpy(s, host->h_name, slen); | |
569 | } | |
570 | ||
571 | /* | |
572 | * Return the hostname with as much domain info as we have... | |
573 | */ | |
574 | ||
575 | return (s); | |
576 | } | |
577 | ||
578 | ||
365cfbcc | 579 | /* |
c9d3f842 | 580 | * End of "$Id$". |
e92958ad | 581 | */ |