(mouse-move-drag-overlay): New function.
[bpt/emacs.git] / lib-src / pop.c
index d74d16f..9bc73e9 100644 (file)
@@ -1,5 +1,6 @@
 /* pop.c: client routines for talking to a POP3-protocol post-office server
-   Copyright (c) 1991, 1993, 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1991, 1993, 1996, 1997, 1999, 2002, 2003, 2004,
+                 2005 Free Software Foundation, Inc.
    Written by Jonathan Kamens, jik@security.ov.com.
 
 This file is part of GNU Emacs.
@@ -16,26 +17,18 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #ifdef HAVE_CONFIG_H
 #define NO_SHORTNAMES  /* Tell config not to load remap.h */
-#include <../src/config.h>
+#include <config.h>
 #else
 #define MAIL_USE_POP
 #endif
 
 #ifdef MAIL_USE_POP
 
-#ifdef HAVE_CONFIG_H
-/* Cancel these substitutions made in config.h */
-#undef open
-#undef read
-#undef write
-#undef close
-#endif
-
 #include <sys/types.h>
 #ifdef WINDOWSNT
 #include "ntlib.h"
@@ -76,9 +69,6 @@ extern struct servent *hes_getservbyname (/* char *, char * */);
 #include <string.h>
 #define index strchr
 #endif
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#endif
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -87,17 +77,6 @@ extern struct servent *hes_getservbyname (/* char *, char * */);
 # ifdef HAVE_KRB5_H
 #  include <krb5.h>
 # endif
-# ifdef HAVE_DES_H
-#  include <des.h>
-# else
-#  ifdef HAVE_KERBEROSIV_DES_H
-#   include <kerberosIV/des.h>
-#  else
-#   ifdef HAVE_KERBEROS_DES_H
-#    include <kerberos/des.h>
-#   endif
-#  endif
-# endif
 # ifdef HAVE_KRB_H
 #  include <krb.h>
 # else
@@ -130,33 +109,31 @@ extern int h_errno;
 #endif
 #endif
 
-#ifndef _P
+#ifndef __P
 # ifdef __STDC__
-#  define _P(a) a
+#  define __P(a) a
 # else
-#  define _P(a) ()
+#  define __P(a) ()
 # endif /* __STDC__ */
 #endif /* ! __P */
 
-static int socket_connection _P((char *, int));
-static int getline _P((popserver, char **));
-static int sendline _P((popserver, char *));
-static int fullwrite _P((int, char *, int));
-static int getok _P((popserver));
+static int socket_connection __P((char *, int));
+static int pop_getline __P((popserver, char **));
+static int sendline __P((popserver, char *));
+static int fullwrite __P((int, char *, int));
+static int getok __P((popserver));
 #if 0
-static int gettermination _P((popserver));
+static int gettermination __P((popserver));
 #endif
-static void pop_trash _P((popserver));
-static char *find_crlf _P((char *, int));
+static void pop_trash __P((popserver));
+static char *find_crlf __P((char *, int));
 
-#define ERROR_MAX 80           /* a pretty arbitrary size */
+#define ERROR_MAX 160          /* a pretty arbitrary size, but needs
+                                  to be bigger than the original
+                                  value of 80 */
 #define POP_PORT 110
 #define KPOP_PORT 1109
-#ifdef WINDOWSNT
 #define POP_SERVICE "pop3"     /* we don't want the POP2 port! */
-#else
-#define POP_SERVICE "pop"
-#endif
 #ifdef KERBEROS
 #define KPOP_SERVICE "kpop"
 #endif
@@ -274,7 +251,7 @@ pop_open (host, username, password, flags)
 #else
 #define DONT_NEED_PASSWORD 0
 #endif
+
   if ((! password) && (! DONT_NEED_PASSWORD))
     {
       if (! (flags & POP_NO_GETPASS))
@@ -309,7 +286,7 @@ pop_open (host, username, password, flags)
       free ((char *) server);
       return (0);
     }
-         
+
   server->file = sock;
   server->data = 0;
   server->buffer_index = 0;
@@ -380,8 +357,8 @@ pop_stat (server, count, size)
       strcpy (pop_error, "In multi-line query in pop_stat");
       return (-1);
     }
-     
-  if (sendline (server, "STAT") || (getline (server, &fromserver) < 0))
+
+  if (sendline (server, "STAT") || (pop_getline (server, &fromserver) < 0))
     return (-1);
 
   if (strncmp (fromserver, "+OK ", 4))
@@ -400,7 +377,7 @@ pop_stat (server, count, size)
     }
 
   *count = atoi (&fromserver[4]);
-     
+
   fromserver = index (&fromserver[4], ' ');
   if (! fromserver)
     {
@@ -477,7 +454,7 @@ pop_list (server, message, IDs, sizes)
          free ((char *) *sizes);
          return (-1);
        }
-      if (getline (server, &fromserver) < 0)
+      if (pop_getline (server, &fromserver) < 0)
        {
          free ((char *) *IDs);
          free ((char *) *sizes);
@@ -573,7 +550,7 @@ pop_list (server, message, IDs, sizes)
  *             of lines with '>'.
  *     msg_buf Output parameter to which a buffer containing the
  *             message is assigned.
- * 
+ *
  * Return value: The number of bytes in msg_buf, which may contain
  *     embedded nulls, not including its final null, or -1 on error
  *     with pop_error set.
@@ -656,7 +633,7 @@ pop_retrieve (server, message, markfrom, msg_buf)
 
   free (ptr);
   return (-1);
-}     
+}
 
 int
 pop_retrieve_first (server, message, response)
@@ -737,7 +714,7 @@ pop_multi_first (server, command, response)
       return (-1);
     }
 
-  if (sendline (server, command) || (getline (server, response) < 0))
+  if (sendline (server, command) || (pop_getline (server, response) < 0))
     {
       return (-1);
     }
@@ -784,7 +761,7 @@ pop_multi_next (server, line)
       return (-1);
     }
 
-  if ((ret = getline (server, &fromserver)) < 0)
+  if ((ret = pop_getline (server, &fromserver)) < 0)
     {
       return (-1);
     }
@@ -909,7 +886,7 @@ pop_last (server)
      popserver server;
 {
   char *fromserver;
-     
+
   if (server->in_multi)
     {
       strcpy (pop_error, "In multi-line query in pop_last");
@@ -919,7 +896,7 @@ pop_last (server)
   if (sendline (server, "LAST"))
     return (-1);
 
-  if (getline (server, &fromserver) < 0)
+  if (pop_getline (server, &fromserver) < 0)
     return (-1);
 
   if (! strncmp (fromserver, "-ERR", 4))
@@ -1022,7 +999,7 @@ static int have_winsock = 0;
  * Arguments:
  *     host    The host to which to connect.
  *     flags   Option flags.
- *     
+ *
  * Return value: A file descriptor indicating the connection, or -1
  *     indicating failure, in which case an error has been copied
  *     into pop_error.
@@ -1067,17 +1044,6 @@ socket_connection (host, flags)
   }
 #endif
 
-  do
-    {
-      hostent = gethostbyname (host);
-      try_count++;
-      if ((! hostent) && ((h_errno != TRY_AGAIN) || (try_count == 5)))
-       {
-         strcpy (pop_error, "Could not determine POP server's address");
-         return (-1);
-       }
-    } while (! hostent);
-
   bzero ((char *) &addr, sizeof (addr));
   addr.sin_family = AF_INET;
 
@@ -1125,9 +1091,20 @@ socket_connection (host, flags)
       strncat (pop_error, strerror (errno),
               ERROR_MAX - sizeof (POP_SOCKET_ERROR));
       return (-1);
-         
+
     }
 
+  do
+    {
+      hostent = gethostbyname (host);
+      try_count++;
+      if ((! hostent) && ((h_errno != TRY_AGAIN) || (try_count == 5)))
+       {
+         strcpy (pop_error, "Could not determine POP server's address");
+         return (-1);
+       }
+    } while (! hostent);
+
   while (*hostent->h_addr_list)
     {
       bcopy (*hostent->h_addr_list, (char *) &addr.sin_addr,
@@ -1138,7 +1115,7 @@ socket_connection (host, flags)
     }
 
 #define CONNECT_ERROR "Could not connect to POP server: "
-     
+
   if (! *hostent->h_addr_list)
     {
       CLOSESOCKET (sock);
@@ -1146,7 +1123,7 @@ socket_connection (host, flags)
       strncat (pop_error, strerror (errno),
               ERROR_MAX - sizeof (CONNECT_ERROR));
       return (-1);
-         
+
     }
 
 #ifdef KERBEROS
@@ -1170,7 +1147,7 @@ socket_connection (host, flags)
 
       if ((rem = krb5_auth_con_init (kcontext, &auth_context)))
        goto krb5error;
-      
+
       if (rem = krb5_cc_default (kcontext, &ccdef))
        goto krb5error;
 
@@ -1228,7 +1205,7 @@ socket_connection (host, flags)
          CLOSESOCKET (sock);
          return (-1);
        }
-#else  /* ! KERBEROS5 */         
+#else  /* ! KERBEROS5 */
       ticket = (KTEXT) malloc (sizeof (KTEXT_ST));
       realhost = strdup (hostent->h_name);
       rem = krb_sendauth (0L, sock, ticket, "pop", realhost,
@@ -1255,7 +1232,7 @@ socket_connection (host, flags)
 } /* socket_connection */
 
 /*
- * Function: getline
+ * Function: pop_getline
  *
  * Purpose: Get a line of text from the connection and return a
  *     pointer to it.  The carriage return and linefeed at the end of
@@ -1271,14 +1248,14 @@ socket_connection (host, flags)
  *     error (in which case the contents of LINE are undefined.  In
  *     case of error, an error message is copied into pop_error.
  *
- * Notes: The line returned is overwritten with each call to getline.
+ * Notes: The line returned is overwritten with each call to pop_getline.
  *
  * Side effects: Closes the connection on error.
  *
  * THE RETURNED LINE MAY CONTAIN EMBEDDED NULLS!
  */
 static int
-getline (server, line)
+pop_getline (server, line)
      popserver server;
      char **line;
 {
@@ -1298,7 +1275,7 @@ getline (server, line)
 
          found = server->buffer_index;
          data_used = (cp + 2) - server->buffer - found;
-              
+
          *cp = '\0';           /* terminate the string to be returned */
          server->data -= data_used;
          server->buffer_index += data_used;
@@ -1341,7 +1318,7 @@ getline (server, line)
          server->buffer = (char *)realloc (server->buffer, server->buffer_size);
          if (! server->buffer)
            {
-             strcpy (pop_error, "Out of memory in getline");
+             strcpy (pop_error, "Out of memory in pop_getline");
              pop_trash (server);
              return (-1);
            }
@@ -1358,7 +1335,7 @@ getline (server, line)
        }
       else if (ret == 0)
        {
-         strcpy (pop_error, "Unexpected EOF from server in getline");
+         strcpy (pop_error, "Unexpected EOF from server in pop_getline");
          pop_trash (server);
          return (-1);
        }
@@ -1367,7 +1344,7 @@ getline (server, line)
          char *cp;
          server->data += ret;
          server->buffer[server->data] = '\0';
-              
+
          cp = find_crlf (server->buffer + search_offset,
                          server->data - search_offset);
          if (cp)
@@ -1416,12 +1393,24 @@ sendline (server, line)
 {
 #define SENDLINE_ERROR "Error writing to POP server: "
   int ret;
-
-  ret = fullwrite (server->file, line, strlen (line));
-  if (ret >= 0)
-    {                          /* 0 indicates that a blank line was written */
-      ret = fullwrite (server->file, "\r\n", 2);
-    }
+  char *buf;
+
+  /* Combine the string and the CR-LF into one buffer.  Otherwise, two
+     reasonable network stack optimizations, Nagle's algorithm and
+     delayed acks, combine to delay us a fraction of a second on every
+     message we send.  (Movemail writes line without \r\n, client
+     kernel sends packet, server kernel delays the ack to see if it
+     can combine it with data, movemail writes \r\n, client kernel
+     waits because it has unacked data already in its outgoing queue,
+     client kernel eventually times out and sends.)
+
+     This can be something like 0.2s per command, which can add up
+     over a few dozen messages, and is a big chunk of the time we
+     spend fetching mail from a server close by.  */
+  buf = alloca (strlen (line) + 3);
+  strcpy (buf, line);
+  strcat (buf, "\r\n");
+  ret = fullwrite (server->file, buf, strlen (buf));
 
   if (ret < 0)
     {
@@ -1474,7 +1463,7 @@ fullwrite (fd, buf, nbytes)
  *
  * Arguments:
  *     server  The server to read from.
- * 
+ *
  * Returns: 0 for success, else for failure and puts error in pop_error.
  *
  * Side effects: On failure, may make the connection unusable.
@@ -1485,7 +1474,7 @@ getok (server)
 {
   char *fromline;
 
-  if (getline (server, &fromline) < 0)
+  if (pop_getline (server, &fromline) < 0)
     {
       return (-1);
     }
@@ -1505,7 +1494,7 @@ getok (server)
       pop_trash (server);
       return (-1);
     }
-}        
+}
 
 #if 0
 /*
@@ -1524,7 +1513,7 @@ gettermination (server)
 {
   char *fromserver;
 
-  if (getline (server, &fromserver) < 0)
+  if (pop_getline (server, &fromserver) < 0)
     return (-1);
 
   if (strcmp (fromserver, "."))
@@ -1551,7 +1540,7 @@ gettermination (server)
  *     Changes made to the maildrop since the session was started (or
  *     since the last pop_reset) may be lost.
  */
-void 
+void
 pop_close (server)
      popserver server;
 {
@@ -1620,3 +1609,6 @@ find_crlf (in_string, len)
 }
 
 #endif /* MAIL_USE_POP */
+
+/* arch-tag: ceb37041-b7ad-49a8-a63d-286618b8367d
+   (do not change this comment) */