Try to fix "infinite loop" warning on AIX and other compilers. (We
[rsync/rsync.git] / socket.c
index 9a61951..ad208ef 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -1,5 +1,6 @@
-/* 
-   Copyright (C) Andrew Tridgell 1998
+/* -*- c-file-style: "linux" -*-
+   
+   Copyright (C) 1998-2001 by Andrew Tridgell 
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "rsync.h"
 
 
-/* establish a proxy connection on an open socket to a web roxy by using the CONNECT
  method */
+/* Establish a proxy connection on an open socket to a web roxy by
* using the CONNECT method. */
 static int establish_proxy_connection(int fd, char *host, int port)
 {
        char buffer[1024];
        char *cp;
 
-       slprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
+       snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
        if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
-               rprintf(FERROR, "failed to write to proxy - %s\n",
+               rprintf(FERROR, "failed to write to proxy: %s\n",
                        strerror(errno));
                return -1;
        }
 
        for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
                if (read(fd, cp, 1) != 1) {
-                       rprintf(FERROR, "failed to read from proxy\n");
+                       rprintf(FERROR, "failed to read from proxy: %s\n",
+                               strerror(errno));
                        return -1;
                }
                if (*cp == '\n')
@@ -71,7 +73,8 @@ static int establish_proxy_connection(int fd, char *host, int port)
                for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
                     cp++) {
                        if (read(fd, cp, 1) != 1) {
-                               rprintf(FERROR, "failed to read from proxy\n");
+                               rprintf(FERROR, "failed to read from proxy: %s\n",
+                                       strerror(errno));
                                return -1;
                        }
                        if (*cp == '\n')
@@ -102,8 +105,9 @@ int open_socket_out(char *host, int port, struct in_addr *address)
        char buffer[1024];
        char *cp;
 
-       /* if we have a RSYNC_PROXY env variable then redirect our connetcion via a web proxy
-          at the given address. The format is hostname:port */
+       /* if we have a RSYNC_PROXY env variable then redirect our
+        * connetcion via a web proxy at the given address. The format
+        * is hostname:port */
        h = getenv("RSYNC_PROXY");
        proxied = (h != NULL) && (*h != '\0');
 
@@ -111,7 +115,8 @@ int open_socket_out(char *host, int port, struct in_addr *address)
                strlcpy(buffer, h, sizeof(buffer));
                cp = strchr(buffer, ':');
                if (cp == NULL) {
-                       rprintf(FERROR, "invalid proxy specification\n");
+                       rprintf(FERROR,
+                               "invalid proxy specification: should be HOST:PORT\n");
                        return -1;
                }
                *cp++ = '\0';
@@ -194,7 +199,8 @@ static int open_socket_in(int type, int port, struct in_addr *address)
        }
        res = socket(hp->h_addrtype, type, 0);
        if (res == -1) { 
-               rprintf(FERROR,"socket failed\n"); 
+               rprintf(FERROR,"socket failed: %s\n",
+                       strerror(errno)); 
                return -1; 
        }
 
@@ -202,7 +208,12 @@ static int open_socket_in(int type, int port, struct in_addr *address)
 
        /* now we've got a socket - we need to bind it */
        if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { 
-               rprintf(FERROR,"bind failed on port %d\n", port);
+               rprintf(FERROR,"bind failed on port %d: %s\n", port,
+                       strerror(errno));
+               if (errno == EACCES && port < 1024) {
+                       rprintf(FERROR, "Note: you must be root to bind "
+                               "to low-numbered ports");
+               }
                close(res); 
                return -1;
        }
@@ -211,13 +222,27 @@ static int open_socket_in(int type, int port, struct in_addr *address)
 }
 
 
-/****************************************************************************
-determine if a file descriptor is in fact a socket
-****************************************************************************/
+/*
+ * Determine if a file descriptor is in fact a socket
+ */
 int is_a_socket(int fd)
 {
-       int v,l;
+       int v, l;
        l = sizeof(int);
+
+        /* Parameters to getsockopt, setsockopt etc are very
+         * unstandardized across platforms, so don't be surprised if
+         * there are compiler warnings on e.g. SCO OpenSwerver.  It
+         * seems they all eventually get the right idea.
+         *
+         * Debian says: ``The fifth argument of getsockopt and
+         * setsockopt is in reality an int [*] (and this is what BSD
+         * 4.* and libc4 and libc5 have).  Some POSIX confusion
+         * resulted in the present socklen_t.  The draft standard has
+         * not been adopted yet, but glibc2 already follows it and
+         * also has socklen_t [*]. See also accept(2).''
+         *
+         * We now return to your regularly scheduled programming.  */
        return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
 }
 
@@ -247,6 +272,11 @@ void start_accept_loop(int port, int (*fn)(int ))
                struct sockaddr addr;
                int in_addrlen = sizeof(addr);
 
+               /* close log file before the potentially very long select so
+                  file can be trimmed by another process instead of growing
+                  forever */
+               log_close();
+
                FD_ZERO(&fds);
                FD_SET(s, &fds);
 
@@ -256,6 +286,7 @@ void start_accept_loop(int port, int (*fn)(int ))
 
                if(!FD_ISSET(s, &fds)) continue;
 
+                /* See note above prototypes. */
                fd = accept(s,&addr,&in_addrlen);
 
                if (fd == -1) continue;
@@ -272,6 +303,10 @@ void start_accept_loop(int port, int (*fn)(int ))
                if (fork()==0) {
                        close(s);
 
+                       /* open log file in child before possibly giving
+                          up privileges  */
+                       log_open();
+
                        _exit(fn(fd));
                }
 
@@ -377,7 +412,8 @@ void set_socket_options(int fd, char *options)
                }
                
                if (ret != 0)
-                       rprintf(FERROR,"Failed to set socket option %s\n",tok);
+                       rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
+                               strerror(errno));
        }
 
        free(options);