]> diplodocus.org Git - nmh/blobdiff - sbr/client.c
Fix invalid pointer arithmetic.
[nmh] / sbr / client.c
index b75f0e29f3a5614a378b0b3008ad4615e9eba12c..a64461bc109c514cbcdc4ff1e91059fc1d4df76c 100644 (file)
@@ -1,6 +1,4 @@
-
-/*
- * client.c -- connect to a server
+/* 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
 #include <netinet/in.h>
 #include <netdb.h>
 #include <arpa/inet.h>
-
-#define        MAXARGS   1000
-
-/*
- * static prototypes
- */
-
-/* client's own static version of several nmh subroutines */
-static char **client_brkstring (char *, char *, char *);
-static int client_brkany (char, char *);
-static char **client_copyip (char **, char **, int);
-static void client_freelist(char **);
+#include <errno.h>
 
 
 int
-client (char *args, char *service, char *response, int len_response, int debug)
+client (char *server, char *service, char *response, int len_response,
+       int debug)
 {
     int sd, rc;
-    char **ap, *arguments[MAXARGS];
     struct addrinfo hints, *res, *ai;
 
-    ap = arguments;
-    if (args != NULL && *args != 0) {
-       ap = client_copyip (client_brkstring (getcpy(args), " ", "\n"),
-               ap, MAXARGS);
-    } else {
-       if (servers != NULL && *servers != 0)
-           ap = client_copyip (client_brkstring (getcpy(servers), " ", "\n"),
-               ap, MAXARGS);
-    }
-    if (ap == arguments) {
-       *ap++ = mh_xstrdup("localhost");
-       *ap = NULL;
+    if (!server || *server == '\0') {
+       snprintf(response, len_response, "Internal error: NULL server name "
+                "passed to client()");
+       return NOTOK;
     }
 
-    memset(&hints, 0, sizeof(hints));
+    ZERO(&hints);
 #ifdef AI_ADDRCONFIG
     hints.ai_flags = AI_ADDRCONFIG;
 #endif
     hints.ai_family = PF_UNSPEC;
     hints.ai_socktype = SOCK_STREAM;
 
-    for (ap = arguments; *ap; ap++) {
-
-       if (debug) {
-           fprintf(stderr, "Trying to connect to \"%s\" ...\n", *ap);
-       }
-
-       rc = getaddrinfo(*ap, service, &hints, &res);
-
-       if (rc) {
-           if (debug) {
-               fprintf(stderr, "Lookup of \"%s\" failed: %s\n", *ap,
-                       gai_strerror(rc));
-           }
-           continue;
-       }
-
-       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));
-               continue;
-           }
-
-           if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) {
-               freeaddrinfo(res);
-               client_freelist(arguments);
-               return sd;
-           }
-
-           if (debug) {
-               fprintf(stderr, "Connection failed: %s\n", strerror(errno));
-           }
+    if (debug) {
+       fprintf(stderr, "Trying to connect to \"%s\" ...\n", server);
+    }
 
-           close(sd);
-       }
+    rc = getaddrinfo(server, service, &hints, &res);
 
-       freeaddrinfo(res);
+    if (rc) {
+       snprintf(response, len_response, "Lookup of \"%s\" failed: %s",
+                server, gai_strerror(rc));
+       return NOTOK;
     }
 
-    client_freelist(arguments);
-    strncpy (response, "no servers available", len_response);
-    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);
 
-/*
- * Free a list of strings
- */
+           fprintf(stderr, "Connecting to %s:%s...\n",
+                   rc ? "unknown" : address, rc ? "--" : port);
+       }
 
-static void
-client_freelist(char **list)
-{
-    free(*list);
-}
+       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;
+       }
 
-/*
- * static copies of three nmh subroutines
- */
+       if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) {
+           freeaddrinfo(res);
+           return sd;
+       }
 
-static char *broken[MAXARGS + 1];
+       rc = errno;
 
-static char **
-client_brkstring (char *strg, char *brksep, char *brkterm)
-{
-    int bi;
-    char c, *sp;
-
-    sp = strg;
-
-    for (bi = 0; bi < MAXARGS; bi++) {
-       while (client_brkany (c = *sp, brksep))
-           *sp++ = 0;
-       if (!c || client_brkany (c, brkterm)) {
-           *sp = 0;
-           broken[bi] = 0;
-           return broken;
+       if (debug) {
+           fprintf(stderr, "Connection failed: %s\n", strerror(errno));
        }
 
-       broken[bi] = sp;
-       while ((c = *++sp) && !client_brkany (c, brksep) && !client_brkany (c, brkterm))
-           continue;
+       close(sd);
     }
-    broken[MAXARGS] = 0;
 
-    return broken;
-}
-
-
-/*
- * returns 1 if chr in strg, 0 otherwise
- */
-static int
-client_brkany (char chr, char *strg)
-{
-    char *sp;
+    /*
+     * 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 (strg)
-       for (sp = strg; *sp; sp++)
-           if (chr == *sp)
-               return 1;
-    return 0;
-}
+    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);
 
-/*
- * copy a string array and return pointer to end
- */
-static char **
-client_copyip (char **p, char **q, int len_q)
-{
-    while (*p && --len_q > 0)
-       *q++ = *p++;
-
-    *q = NULL;
-
-    return q;
+    return NOTOK;
 }