/* * client.c -- connect to a server * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include int client (char *server, char *service, char *response, int len_response, int debug) { int sd, rc; struct addrinfo hints, *res, *ai; if (!server || *server == '\0') { snprintf(response, len_response, "Internal error: NULL server name " "passed to client()"); return NOTOK; } memset(&hints, 0, sizeof(hints)); #ifdef AI_ADDRCONFIG hints.ai_flags = AI_ADDRCONFIG; #endif hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (debug) { fprintf(stderr, "Trying to connect to \"%s\" ...\n", server); } rc = getaddrinfo(server, service, &hints, &res); if (rc) { snprintf(response, len_response, "Lookup of \"%s\" failed: %s", server, gai_strerror(rc)); return NOTOK; } for (ai = res; ai != NULL; ai = ai->ai_next) { if (debug) { char address[NI_MAXHOST]; char port[NI_MAXSERV]; rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, address, sizeof(address), port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV); fprintf(stderr, "Connecting to %s:%s...\n", rc ? "unknown" : address, rc ? "--" : port); } sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sd < 0) { if (debug) fprintf(stderr, "socket() failed: %s\n", strerror(errno)); rc = errno; continue; } if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) { freeaddrinfo(res); return sd; } rc = errno; if (debug) { fprintf(stderr, "Connection failed: %s\n", strerror(errno)); } close(sd); } /* * Improve error handling a bit. If we were given multiple IP addresses * then return the old "no servers available" error, but point the user * to -snoop (hopefully that's universal). Otherwise report a specific * error. */ if (res->ai_next) snprintf(response, len_response, "no servers available (use -snoop " "for details"); else snprintf(response, len_response, "Connection to \"%s\" failed: %s", server, strerror(errno)); freeaddrinfo(res); return NOTOK; }