/* pop.c: client routines for talking to a POP3-protocol post-office server
- Copyright (c) 1991,1993 Free Software Foundation, Inc.
+ Copyright (c) 1991, 1993, 1996 Free Software Foundation, Inc.
Written by Jonathan Kamens, jik@security.ov.com.
This file is part of GNU Emacs.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
-#define NO_SHORTNAMES /* Tell config not to load remap.h */
+#ifdef HAVE_CONFIG_H
+#define NO_SHORTNAMES /* Tell config not to load remap.h */
#include <../src/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"
+#include <winsock.h>
+#undef SOCKET_ERROR
+#define RECV(s,buf,len,flags) recv(s,buf,len,flags)
+#define SEND(s,buf,len,flags) send(s,buf,len,flags)
+#define CLOSESOCKET(s) closesocket(s)
+#else
#include <netinet/in.h>
#include <sys/socket.h>
+#define RECV(s,buf,len,flags) read(s,buf,len)
+#define SEND(s,buf,len,flags) write(s,buf,len)
+#define CLOSESOCKET(s) close(s)
+#endif
#include <pop.h>
+
#ifdef sun
#include <malloc.h>
-#endif
-#endif
+#endif /* sun */
+
#ifdef HESIOD
#include <hesiod.h>
/*
*/
extern struct servent *hes_getservbyname (/* char *, char * */);
#endif
+
#include <pwd.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
+
#ifdef KERBEROS
#ifndef KRB5
+#ifndef SOLARIS2
#include <des.h>
#include <krb.h>
+#else /* not SOLARIS2 */
+#include <kerberos/des.h>
+#include <kerberos/krb.h>
+#endif /* not SOLARIS2 */
#else /* KRB5 */
#include <krb5/krb5.h>
#include <krb5/ext-proto.h>
#include <ctype.h>
#endif /* KRB5 */
+#endif /* KERBEROS */
extern char *getenv (/* char * */);
extern char *getlogin (/* void */);
extern char *getpass (/* char * */);
extern char *strerror (/* int */);
+extern char *index ();
#ifdef KERBEROS
+#ifndef KRB5
extern int krb_sendauth (/* long, int, KTEXT, char *, char *, char *,
- u_long, MSG_DAT *, CREDENTIALS *, Key_schedule,
- struct sockaddr_in *, struct sockaddr_in *,
- char * */);
+ u_long, MSG_DAT *, CREDENTIALS *, Key_schedule,
+ struct sockaddr_in *, struct sockaddr_in *,
+ char * */);
extern char *krb_realmofhost (/* char * */);
-#endif
+#endif /* ! KRB5 */
+#endif /* KERBEROS */
-#ifndef HAVE_H_ERRNO
+#ifndef WINDOWSNT
+#if !defined(HAVE_H_ERRNO) || !defined(HAVE_CONFIG_H)
extern int h_errno;
#endif
+#endif
static int socket_connection (/* char *, int */);
static char *getline (/* popserver */);
static int gettermination (/* popserver */);
#endif
static void pop_trash (/* popserver */);
-
-static char *my_strstr ();
+static char *find_crlf (/* char * */);
#define ERROR_MAX 80 /* a pretty arbitrary size */
#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
#ifdef KRB5
#define KPOP_SERVICE "k5pop";
server->buffer_index = 0;
server->buffer_size = GETLINE_MIN;
server->in_multi = 0;
+ server->trash_started = 0;
if (getok (server))
return (0);
* allocate more space for them below.
*/
bufsize = sizes[0] + (markfrom ? 5 : 0);
- ptr = malloc (bufsize);
+ ptr = (char *)malloc (bufsize);
free ((char *) IDs);
free ((char *) sizes);
if (++fromcount == 5)
{
bufsize += 5;
- ptr = realloc (ptr, bufsize);
+ ptr = (char *)realloc (ptr, bufsize);
if (! ptr)
{
strcpy (pop_error, "Out of memory in pop_retrieve");
* Return value: 0 for success, non-zero otherwise with error in
* pop_error.
*
- * Side Effects: The popserver passed in is unuseable after this
+ * Side Effects: The popserver passed in is unusable after this
* function is called, even if an error occurs.
*/
int
return (ret);
}
+#ifdef WINDOWSNT
+static int have_winsock = 0;
+#endif
+
/*
* Function: socket_connection
*
int try_count = 0;
+#ifdef WINDOWSNT
+ {
+ WSADATA winsockData;
+ if (WSAStartup (0x101, &winsockData) == 0)
+ have_winsock = 1;
+ }
+#endif
+
do
{
hostent = gethostbyname (host);
if (! *hostent->h_addr_list)
{
- (void) close (sock);
+ CLOSESOCKET (sock);
strcpy (pop_error, CONNECT_ERROR);
strncat (pop_error, strerror (errno),
ERROR_MAX - sizeof (CONNECT_ERROR));
strcpy (pop_error, KRB_ERROR);
strncat (pop_error, error_message (rem),
ERROR_MAX - sizeof(KRB_ERROR));
- (void) close (sock);
+ CLOSESOCKET (sock);
return (-1);
}
if (err_ret)
krb5_free_error (err_ret);
- (void) close (sock);
+ CLOSESOCKET (sock);
return (-1);
}
#else /* ! KRB5 */
strcpy (pop_error, KRB_ERROR);
strncat (pop_error, krb_err_txt[rem],
ERROR_MAX - sizeof (KRB_ERROR));
- (void) close (sock);
+ CLOSESOCKET (sock);
return (-1);
}
#endif /* KRB5 */
#define GETLINE_ERROR "Error reading from server: "
int ret;
-
+ int search_offset = 0;
+
if (server->data)
{
- char *cp = my_strstr (server->buffer + server->buffer_index, "\r\n");
+ char *cp = find_crlf (server->buffer + server->buffer_index);
if (cp)
{
int found;
{
bcopy (server->buffer + server->buffer_index,
server->buffer, server->data);
+ /* Record the fact that we've searched the data already in
+ the buffer for a CRLF, so that when we search below, we
+ don't have to search the same data twice. There's a "-
+ 1" here to account for the fact that the last character
+ of the data we have may be the CR of a CRLF pair, of
+ which we haven't read the second half yet, so we may have
+ to search it again when we read more data. */
+ search_offset = server->data - 1;
server->buffer_index = 0;
}
}
while (1)
{
- if (server->data == server->buffer_size)
+ /* There's a "- 1" here to leave room for the null that we put
+ at the end of the read data below. We put the null there so
+ that find_crlf knows where to stop when we call it. */
+ if (server->data == server->buffer_size - 1)
{
server->buffer_size += GETLINE_INCR;
- server->buffer = realloc (server->buffer, server->buffer_size);
+ server->buffer = (char *)realloc (server->buffer, server->buffer_size);
if (! server->buffer)
{
strcpy (pop_error, "Out of memory in getline");
return (0);
}
}
- ret = read (server->file, server->buffer + server->data,
- server->buffer_size - server->data - 1);
+ ret = RECV (server->file, server->buffer + server->data,
+ server->buffer_size - server->data - 1, 0);
if (ret < 0)
{
strcpy (pop_error, GETLINE_ERROR);
server->data += ret;
server->buffer[server->data] = '\0';
- cp = my_strstr (server->buffer, "\r\n");
+ cp = find_crlf (server->buffer + search_offset);
if (cp)
{
int data_used = (cp + 2) - server->buffer;
fprintf (stderr, "<<< %s\n", server->buffer);
return (server->buffer);
}
+ search_offset += ret;
}
}
int ret;
cp = buf;
- while ((ret = write (fd, cp, nbytes)) > 0)
+ while ((ret = SEND (fd, cp, nbytes, 0)) > 0)
{
cp += ret;
nbytes -= ret;
*
* Returns: 0 for success, else for failure and puts error in pop_error.
*
- * Side effects: On failure, may make the connection unuseable.
+ * Side effects: On failure, may make the connection unusable.
*/
static int
getok (server)
* try to get the server to quit, but ignoring any responses that
* are received.
*
- * Side effects: The server is unuseable after this function returns.
+ * Side effects: The server is unusable after this function returns.
* Changes made to the maildrop since the session was started (or
* since the last pop_reset) may be lost.
*/
{
if (server->file >= 0)
{
+ /* avoid recursion; sendline can call pop_trash */
+ if (server->trash_started)
+ return;
+ server->trash_started = 1;
+
sendline (server, "RSET");
sendline (server, "QUIT");
- close (server->file);
+ CLOSESOCKET (server->file);
server->file = -1;
if (server->buffer)
{
server->buffer = 0;
}
}
+
+#ifdef WINDOWSNT
+ if (have_winsock)
+ WSACleanup ();
+#endif
}
-/* Search in STRING for an occurrence of SUBSTRING
- and return a pointer to that occurrence.
- Return 0 if SUBSTRING does not occur in STRING. */
+/* Return a pointer to the first CRLF in IN_STRING,
+ or 0 if it does not contain one. */
static char *
-my_strstr (string, substring)
- char *string, *substring;
+find_crlf (in_string)
+ char *in_string;
{
- char *p = string;
-
- while (*p)
+ while (1)
{
- if (!strcmp (p, substring))
- return p;
- p++;
+ if (! *in_string)
+ return (0);
+ else if (*in_string == '\r')
+ {
+ if (*++in_string == '\n')
+ return (in_string - 1);
+ }
+ else
+ in_string++;
}
- return 0;
+ /* NOTREACHED */
}
#endif /* MAIL_USE_POP */