Mailer
/* $Id$ */
							/* Copyright (c) 2015-2018 Pierre Pronchery <khorben@defora.org> */
							/* This file is part of DeforaOS Desktop Mailer */
							/* All rights reserved.
							 *
							 * Redistribution and use in source and binary forms, with or without
							 * modification, are permitted provided that the following conditions are
							 * met:
							 *
							 * 1. Redistributions of source code must retain the above copyright
							 *    notice, this list of conditions and the following disclaimer.
							 *
							 * 2. Redistributions in binary form must reproduce the above copyright
							 *    notice, this list of conditions and the following disclaimer in the
							 *    documentation and/or other materials provided with the distribution.
							 *
							 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
							 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
							 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
							 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
							 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
							 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
							 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
							 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
							 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
							 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
							 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
							#include <string.h>
							#include <netdb.h>
							/* prototypes */
							static int _common_lookup(char const * hostname, uint16_t port,
									struct addrinfo ** ai);
							/* functions */
							/* common_lookup */
							static int _common_lookup(char const * hostname, uint16_t port,
									struct addrinfo ** ai)
							{
								struct addrinfo hints;
								int res;
								char buf[6];
								if(hostname == NULL)
									return -error_set_code(1, "%s", strerror(errno));
								memset(&hints, 0, sizeof(hints));
								hints.ai_family = AF_UNSPEC;
								hints.ai_socktype = SOCK_STREAM;
								hints.ai_protocol = IPPROTO_TCP;
								hints.ai_flags = AI_NUMERICSERV;
								snprintf(buf, sizeof(buf), "%hu", port);
								if((res = getaddrinfo(hostname, buf, &hints, ai)) != 0)
									return -error_set_code(1, "%s", gai_strerror(res));
								return 0;
							}
							/* common_lookup_print */
							static char * _common_lookup_print(struct addrinfo * ai)
							{
								char buf[128];
								char buf2[128];
								struct sockaddr_in * sin;
								struct sockaddr_in6 * sin6;
								switch(ai->ai_family)
								{
									case AF_INET:
										sin = (struct sockaddr_in *)ai->ai_addr;
										if(inet_ntop(ai->ai_family, &sin->sin_addr, buf,
													sizeof(buf)) == NULL)
											return NULL;
										snprintf(buf2, sizeof(buf2), "%s:%hu", buf,
												ntohs(sin->sin_port));
										break;
									case AF_INET6:
										sin6 = (struct sockaddr_in6 *)ai->ai_addr;
										if(inet_ntop(ai->ai_family, &sin6->sin6_addr, buf,
													sizeof(buf)) == NULL)
											return NULL;
										snprintf(buf2, sizeof(buf2), "[%s]:%hu", buf,
												ntohs(sin6->sin6_port));
										break;
									default:
										return NULL;
								}
								return strdup(buf2);
							}
							