1 /* pop.c: client routines for talking to a POP3-protocol post-office server
2 Copyright (c) 1991, 1993, 1996, 1997 Free Software Foundation, Inc.
3 Written by Jonathan Kamens, jik@security.ov.com.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
23 #define NO_SHORTNAMES /* Tell config not to load remap.h */
24 #include <../src/config.h>
32 /* Cancel these substitutions made in config.h */
39 #include <sys/types.h>
44 #define RECV(s,buf,len,flags) recv(s,buf,len,flags)
45 #define SEND(s,buf,len,flags) send(s,buf,len,flags)
46 #define CLOSESOCKET(s) closesocket(s)
48 #include <netinet/in.h>
49 #include <sys/socket.h>
50 #define RECV(s,buf,len,flags) read(s,buf,len)
51 #define SEND(s,buf,len,flags) write(s,buf,len)
52 #define CLOSESOCKET(s) close(s)
63 * It really shouldn't be necessary to put this declaration here, but
64 * the version of hesiod.h that Athena has installed in release 7.2
65 * doesn't declare this function; I don't know if the 7.3 version of
68 extern struct servent
*hes_getservbyname (/* char *, char * */);
93 # ifdef HAVE_KERBEROSIV_DES_H
94 # include <kerberosIV/des.h>
96 # ifdef HAVE_KERBEROS_DES_H
97 # include <kerberos/des.h>
104 # ifdef HAVE_KERBEROSIV_KRB_H
105 # include <kerberosIV/krb.h>
107 # ifdef HAVE_KERBEROS_KRB_H
108 # include <kerberos/krb.h>
112 # ifdef HAVE_COM_ERR_H
113 # include <com_err.h>
115 #endif /* KERBEROS */
119 extern int krb_sendauth (/* long, int, KTEXT, char *, char *, char *,
120 u_long, MSG_DAT *, CREDENTIALS *, Key_schedule,
121 struct sockaddr_in *, struct sockaddr_in *,
123 extern char *krb_realmofhost (/* char * */);
124 #endif /* ! KERBEROS5 */
125 #endif /* KERBEROS */
128 #if !defined(HAVE_H_ERRNO) || !defined(HAVE_CONFIG_H)
138 # endif /* __STDC__ */
141 static int socket_connection
_P((char *, int));
142 static int pop_getline
_P((popserver
, char **));
143 static int sendline
_P((popserver
, char *));
144 static int fullwrite
_P((int, char *, int));
145 static int getok
_P((popserver
));
147 static int gettermination
_P((popserver
));
149 static void pop_trash
_P((popserver
));
150 static char *find_crlf
_P((char *, int));
152 #define ERROR_MAX 80 /* a pretty arbitrary size */
154 #define KPOP_PORT 1109
156 #define POP_SERVICE "pop3" /* we don't want the POP2 port! */
158 #define POP_SERVICE "pop"
161 #define KPOP_SERVICE "kpop"
164 char pop_error
[ERROR_MAX
];
168 #define min(a,b) (((a) < (b)) ? (a) : (b))
172 * Function: pop_open (char *host, char *username, char *password,
175 * Purpose: Establishes a connection with a post-office server, and
176 * completes the authorization portion of the session.
179 * host The server host with which the connection should be
180 * established. Optional. If omitted, internal
181 * heuristics will be used to determine the server host,
184 * The username of the mail-drop to access. Optional.
185 * If omitted, internal heuristics will be used to
186 * determine the username, if possible.
188 * The password to use for authorization. If omitted,
189 * internal heuristics will be used to determine the
190 * password, if possible.
191 * flags A bit mask containing flags controlling certain
192 * functions of the routine. Valid flags are defined in
195 * Return value: Upon successful establishment of a connection, a
196 * non-null popserver will be returned. Otherwise, null will be
197 * returned, and the string variable pop_error will contain an
198 * explanation of the error.
201 pop_open (host
, username
, password
, flags
)
210 /* Determine the user name */
213 username
= getenv ("USER");
214 if (! (username
&& *username
))
216 username
= getlogin ();
217 if (! (username
&& *username
))
219 struct passwd
*passwd
;
220 passwd
= getpwuid (getuid ());
221 if (passwd
&& passwd
->pw_name
&& *passwd
->pw_name
)
223 username
= passwd
->pw_name
;
227 strcpy (pop_error
, "Could not determine username");
235 * Determine the mail host.
240 host
= getenv ("MAILHOST");
244 if ((! host
) && (! (flags
& POP_NO_HESIOD
)))
246 struct hes_postoffice
*office
;
247 office
= hes_getmailhost (username
);
248 if (office
&& office
->po_type
&& (! strcmp (office
->po_type
, "POP"))
249 && office
->po_name
&& *office
->po_name
&& office
->po_host
252 host
= office
->po_host
;
253 username
= office
->po_name
;
267 strcpy (pop_error
, "Could not determine POP server");
271 /* Determine the password */
273 #define DONT_NEED_PASSWORD (! (flags & POP_NO_KERBEROS))
275 #define DONT_NEED_PASSWORD 0
278 if ((! password
) && (! DONT_NEED_PASSWORD
))
280 if (! (flags
& POP_NO_GETPASS
))
282 password
= getpass ("Enter POP password:");
286 strcpy (pop_error
, "Could not determine POP password");
291 flags
|= POP_NO_KERBEROS
;
295 sock
= socket_connection (host
, flags
);
299 server
= (popserver
) malloc (sizeof (struct _popserver
));
302 strcpy (pop_error
, "Out of memory in pop_open");
305 server
->buffer
= (char *) malloc (GETLINE_MIN
);
306 if (! server
->buffer
)
308 strcpy (pop_error
, "Out of memory in pop_open");
309 free ((char *) server
);
315 server
->buffer_index
= 0;
316 server
->buffer_size
= GETLINE_MIN
;
317 server
->in_multi
= 0;
318 server
->trash_started
= 0;
324 * I really shouldn't use the pop_error variable like this, but....
326 if (strlen (username
) > ERROR_MAX
- 6)
330 "Username too long; recompile pop.c with larger ERROR_MAX");
333 sprintf (pop_error
, "USER %s", username
);
335 if (sendline (server
, pop_error
) || getok (server
))
340 if (strlen (password
) > ERROR_MAX
- 6)
344 "Password too long; recompile pop.c with larger ERROR_MAX");
347 sprintf (pop_error
, "PASS %s", password
);
349 if (sendline (server
, pop_error
) || getok (server
))
360 * Purpose: Issue the STAT command to the server and return (in the
361 * value parameters) the number of messages in the maildrop and
362 * the total size of the maildrop.
364 * Return value: 0 on success, or non-zero with an error in pop_error
367 * Side effects: On failure, may make further operations on the
368 * connection impossible.
371 pop_stat (server
, count
, size
)
378 if (server
->in_multi
)
380 strcpy (pop_error
, "In multi-line query in pop_stat");
384 if (sendline (server
, "STAT") || (pop_getline (server
, &fromserver
) < 0))
387 if (strncmp (fromserver
, "+OK ", 4))
389 if (0 == strncmp (fromserver
, "-ERR", 4))
391 strncpy (pop_error
, fromserver
, ERROR_MAX
);
396 "Unexpected response from POP server in pop_stat");
402 *count
= atoi (&fromserver
[4]);
404 fromserver
= index (&fromserver
[4], ' ');
408 "Badly formatted response from server in pop_stat");
413 *size
= atoi (fromserver
+ 1);
421 * Purpose: Performs the POP "list" command and returns (in value
422 * parameters) two malloc'd zero-terminated arrays -- one of
423 * message IDs, and a parallel one of sizes.
426 * server The pop connection to talk to.
427 * message The number of the one message about which to get
428 * information, or 0 to get information about all
431 * Return value: 0 on success, non-zero with error in pop_error on
434 * Side effects: On failure, may make further operations on the
435 * connection impossible.
438 pop_list (server
, message
, IDs
, sizes
)
447 if (server
->in_multi
)
449 strcpy (pop_error
, "In multi-line query in pop_list");
458 if (pop_stat (server
, &count
, &size
))
463 *IDs
= (int *) malloc ((how_many
+ 1) * sizeof (int));
464 *sizes
= (int *) malloc ((how_many
+ 1) * sizeof (int));
465 if (! (*IDs
&& *sizes
))
467 strcpy (pop_error
, "Out of memory in pop_list");
473 sprintf (pop_error
, "LIST %d", message
);
474 if (sendline (server
, pop_error
))
476 free ((char *) *IDs
);
477 free ((char *) *sizes
);
480 if (pop_getline (server
, &fromserver
) < 0)
482 free ((char *) *IDs
);
483 free ((char *) *sizes
);
486 if (strncmp (fromserver
, "+OK ", 4))
488 if (! strncmp (fromserver
, "-ERR", 4))
489 strncpy (pop_error
, fromserver
, ERROR_MAX
);
493 "Unexpected response from server in pop_list");
496 free ((char *) *IDs
);
497 free ((char *) *sizes
);
500 (*IDs
)[0] = atoi (&fromserver
[4]);
501 fromserver
= index (&fromserver
[4], ' ');
505 "Badly formatted response from server in pop_list");
507 free ((char *) *IDs
);
508 free ((char *) *sizes
);
511 (*sizes
)[0] = atoi (fromserver
);
512 (*IDs
)[1] = (*sizes
)[1] = 0;
517 if (pop_multi_first (server
, "LIST", &fromserver
))
519 free ((char *) *IDs
);
520 free ((char *) *sizes
);
523 for (i
= 0; i
< how_many
; i
++)
525 if (pop_multi_next (server
, &fromserver
) <= 0)
527 free ((char *) *IDs
);
528 free ((char *) *sizes
);
531 (*IDs
)[i
] = atoi (fromserver
);
532 fromserver
= index (fromserver
, ' ');
536 "Badly formatted response from server in pop_list");
537 free ((char *) *IDs
);
538 free ((char *) *sizes
);
542 (*sizes
)[i
] = atoi (fromserver
);
544 if (pop_multi_next (server
, &fromserver
) < 0)
546 free ((char *) *IDs
);
547 free ((char *) *sizes
);
553 "Too many response lines from server in pop_list");
554 free ((char *) *IDs
);
555 free ((char *) *sizes
);
558 (*IDs
)[i
] = (*sizes
)[i
] = 0;
564 * Function: pop_retrieve
566 * Purpose: Retrieve a specified message from the maildrop.
569 * server The server to retrieve from.
570 * message The message number to retrieve.
572 * If true, then mark the string "From " at the beginning
574 * msg_buf Output parameter to which a buffer containing the
575 * message is assigned.
577 * Return value: The number of bytes in msg_buf, which may contain
578 * embedded nulls, not including its final null, or -1 on error
579 * with pop_error set.
581 * Side effects: May kill connection on error.
584 pop_retrieve (server
, message
, markfrom
, msg_buf
)
590 int *IDs
, *sizes
, bufsize
, fromcount
= 0, cp
= 0;
591 char *ptr
, *fromserver
;
594 if (server
->in_multi
)
596 strcpy (pop_error
, "In multi-line query in pop_retrieve");
600 if (pop_list (server
, message
, &IDs
, &sizes
))
603 if (pop_retrieve_first (server
, message
, &fromserver
))
609 * The "5" below is an arbitrary constant -- I assume that if
610 * there are "From" lines in the text to be marked, there
611 * probably won't be more than 5 of them. If there are, I
612 * allocate more space for them below.
614 bufsize
= sizes
[0] + (markfrom
? 5 : 0);
615 ptr
= (char *)malloc (bufsize
);
617 free ((char *) sizes
);
621 strcpy (pop_error
, "Out of memory in pop_retrieve");
622 pop_retrieve_flush (server
);
626 while ((ret
= pop_retrieve_next (server
, &fromserver
)) >= 0)
634 if (markfrom
&& fromserver
[0] == 'F' && fromserver
[1] == 'r' &&
635 fromserver
[2] == 'o' && fromserver
[3] == 'm' &&
636 fromserver
[4] == ' ')
638 if (++fromcount
== 5)
641 ptr
= (char *)realloc (ptr
, bufsize
);
644 strcpy (pop_error
, "Out of memory in pop_retrieve");
645 pop_retrieve_flush (server
);
652 bcopy (fromserver
, &ptr
[cp
], ret
);
662 pop_retrieve_first (server
, message
, response
)
667 sprintf (pop_error
, "RETR %d", message
);
668 return (pop_multi_first (server
, pop_error
, response
));
672 Returns a negative number on error, 0 to indicate that the data has
673 all been read (i.e., the server has returned a "." termination
674 line), or a positive number indicating the number of bytes in the
675 returned buffer (which is null-terminated and may contain embedded
676 nulls, but the returned bytecount doesn't include the final null).
680 pop_retrieve_next (server
, line
)
684 return (pop_multi_next (server
, line
));
688 pop_retrieve_flush (server
)
691 return (pop_multi_flush (server
));
695 pop_top_first (server
, message
, lines
, response
)
700 sprintf (pop_error
, "TOP %d %d", message
, lines
);
701 return (pop_multi_first (server
, pop_error
, response
));
705 Returns a negative number on error, 0 to indicate that the data has
706 all been read (i.e., the server has returned a "." termination
707 line), or a positive number indicating the number of bytes in the
708 returned buffer (which is null-terminated and may contain embedded
709 nulls, but the returned bytecount doesn't include the final null).
713 pop_top_next (server
, line
)
717 return (pop_multi_next (server
, line
));
721 pop_top_flush (server
)
724 return (pop_multi_flush (server
));
728 pop_multi_first (server
, command
, response
)
733 if (server
->in_multi
)
736 "Already in multi-line query in pop_multi_first");
740 if (sendline (server
, command
) || (pop_getline (server
, response
) < 0))
745 if (0 == strncmp (*response
, "-ERR", 4))
747 strncpy (pop_error
, *response
, ERROR_MAX
);
750 else if (0 == strncmp (*response
, "+OK", 3))
752 for (*response
+= 3; **response
== ' '; (*response
)++) /* empty */;
753 server
->in_multi
= 1;
759 "Unexpected response from server in pop_multi_first");
765 Read the next line of data from SERVER and place a pointer to it
766 into LINE. Return -1 on error, 0 if there are no more lines to read
767 (i.e., the server has returned a line containing only "."), or a
768 positive number indicating the number of bytes in the LINE buffer
769 (not including the final null). The data in that buffer may contain
770 embedded nulls, but does not contain the final CRLF. When returning
771 0, LINE is set to null. */
774 pop_multi_next (server
, line
)
781 if (! server
->in_multi
)
783 strcpy (pop_error
, "Not in multi-line query in pop_multi_next");
787 if ((ret
= pop_getline (server
, &fromserver
)) < 0)
792 if (fromserver
[0] == '.')
797 server
->in_multi
= 0;
802 *line
= fromserver
+ 1;
814 pop_multi_flush (server
)
820 if (! server
->in_multi
)
825 while ((ret
= pop_multi_next (server
, &line
)))
834 /* Function: pop_delete
836 * Purpose: Delete a specified message.
839 * server Server from which to delete the message.
840 * message Message to delete.
842 * Return value: 0 on success, non-zero with error in pop_error
846 pop_delete (server
, message
)
850 if (server
->in_multi
)
852 strcpy (pop_error
, "In multi-line query in pop_delete");
856 sprintf (pop_error
, "DELE %d", message
);
858 if (sendline (server
, pop_error
) || getok (server
))
867 * Purpose: Send a noop command to the server.
870 * server The server to send to.
872 * Return value: 0 on success, non-zero with error in pop_error
875 * Side effects: Closes connection on error.
881 if (server
->in_multi
)
883 strcpy (pop_error
, "In multi-line query in pop_noop");
887 if (sendline (server
, "NOOP") || getok (server
))
896 * Purpose: Find out the highest seen message from the server.
901 * Return value: If successful, the highest seen message, which is
902 * greater than or equal to 0. Otherwise, a negative number with
903 * the error explained in pop_error.
905 * Side effects: Closes the connection on error.
913 if (server
->in_multi
)
915 strcpy (pop_error
, "In multi-line query in pop_last");
919 if (sendline (server
, "LAST"))
922 if (pop_getline (server
, &fromserver
) < 0)
925 if (! strncmp (fromserver
, "-ERR", 4))
927 strncpy (pop_error
, fromserver
, ERROR_MAX
);
930 else if (strncmp (fromserver
, "+OK ", 4))
932 strcpy (pop_error
, "Unexpected response from server in pop_last");
938 return (atoi (&fromserver
[4]));
943 * Function: pop_reset
945 * Purpose: Reset the server to its initial connect state
950 * Return value: 0 for success, non-0 with error in pop_error
953 * Side effects: Closes the connection on error.
959 if (pop_retrieve_flush (server
))
964 if (sendline (server
, "RSET") || getok (server
))
973 * Purpose: Quit the connection to the server,
976 * server The server to quit.
978 * Return value: 0 for success, non-zero otherwise with error in
981 * Side Effects: The popserver passed in is unusable after this
982 * function is called, even if an error occurs.
990 if (server
->file
>= 0)
992 if (pop_retrieve_flush (server
))
997 if (sendline (server
, "QUIT") || getok (server
))
1002 close (server
->file
);
1006 free (server
->buffer
);
1007 free ((char *) server
);
1013 static int have_winsock
= 0;
1017 * Function: socket_connection
1019 * Purpose: Opens the network connection with the mail host, without
1020 * doing any sort of I/O with it or anything.
1023 * host The host to which to connect.
1024 * flags Option flags.
1026 * Return value: A file descriptor indicating the connection, or -1
1027 * indicating failure, in which case an error has been copied
1031 socket_connection (host
, flags
)
1035 struct hostent
*hostent
;
1036 struct servent
*servent
;
1037 struct sockaddr_in addr
;
1038 char found_port
= 0;
1043 krb5_error_code rem
;
1044 krb5_context kcontext
= 0;
1045 krb5_auth_context auth_context
= 0;
1047 krb5_principal client
, server
;
1048 krb5_error
*err_ret
;
1054 Key_schedule schedule
;
1057 #endif /* KERBEROS5 */
1058 #endif /* KERBEROS */
1064 WSADATA winsockData
;
1065 if (WSAStartup (0x101, &winsockData
) == 0)
1072 hostent
= gethostbyname (host
);
1074 if ((! hostent
) && ((h_errno
!= TRY_AGAIN
) || (try_count
== 5)))
1076 strcpy (pop_error
, "Could not determine POP server's address");
1079 } while (! hostent
);
1081 bzero ((char *) &addr
, sizeof (addr
));
1082 addr
.sin_family
= AF_INET
;
1085 service
= (flags
& POP_NO_KERBEROS
) ? POP_SERVICE
: KPOP_SERVICE
;
1087 service
= POP_SERVICE
;
1091 if (! (flags
& POP_NO_HESIOD
))
1093 servent
= hes_getservbyname (service
, "tcp");
1096 addr
.sin_port
= servent
->s_port
;
1103 servent
= getservbyname (service
, "tcp");
1106 addr
.sin_port
= servent
->s_port
;
1111 addr
.sin_port
= htons ((flags
& POP_NO_KERBEROS
) ?
1112 POP_PORT
: KPOP_PORT
);
1114 addr
.sin_port
= htons (POP_PORT
);
1119 #define POP_SOCKET_ERROR "Could not create socket for POP connection: "
1121 sock
= socket (PF_INET
, SOCK_STREAM
, 0);
1124 strcpy (pop_error
, POP_SOCKET_ERROR
);
1125 strncat (pop_error
, strerror (errno
),
1126 ERROR_MAX
- sizeof (POP_SOCKET_ERROR
));
1131 while (*hostent
->h_addr_list
)
1133 bcopy (*hostent
->h_addr_list
, (char *) &addr
.sin_addr
,
1135 if (! connect (sock
, (struct sockaddr
*) &addr
, sizeof (addr
)))
1137 hostent
->h_addr_list
++;
1140 #define CONNECT_ERROR "Could not connect to POP server: "
1142 if (! *hostent
->h_addr_list
)
1145 strcpy (pop_error
, CONNECT_ERROR
);
1146 strncat (pop_error
, strerror (errno
),
1147 ERROR_MAX
- sizeof (CONNECT_ERROR
));
1153 #define KRB_ERROR "Kerberos error connecting to POP server: "
1154 if (! (flags
& POP_NO_KERBEROS
))
1157 if ((rem
= krb5_init_context (&kcontext
)))
1161 krb5_auth_con_free (kcontext
, auth_context
);
1163 krb5_free_context (kcontext
);
1164 strcpy (pop_error
, KRB_ERROR
);
1165 strncat (pop_error
, error_message (rem
),
1166 ERROR_MAX
- sizeof(KRB_ERROR
));
1171 if ((rem
= krb5_auth_con_init (kcontext
, &auth_context
)))
1174 if (rem
= krb5_cc_default (kcontext
, &ccdef
))
1177 if (rem
= krb5_cc_get_principal (kcontext
, ccdef
, &client
))
1180 for (cp
= hostent
->h_name
; *cp
; cp
++)
1184 *cp
= tolower (*cp
);
1188 if (rem
= krb5_sname_to_principal (kcontext
, hostent
->h_name
,
1189 POP_SERVICE
, FALSE
, &server
))
1192 rem
= krb5_sendauth (kcontext
, &auth_context
,
1193 (krb5_pointer
) &sock
, "KPOPV1.0", client
, server
,
1194 AP_OPTS_MUTUAL_REQUIRED
,
1195 0, /* no checksum */
1196 0, /* no creds, use ccache instead */
1199 0, /* don't need subsession key */
1200 0); /* don't need reply */
1201 krb5_free_principal (kcontext
, server
);
1204 if (err_ret
&& err_ret
->text
.length
)
1206 strcpy (pop_error
, KRB_ERROR
);
1207 strncat (pop_error
, error_message (rem
),
1208 ERROR_MAX
- sizeof (KRB_ERROR
));
1209 strncat (pop_error
, " [server says '",
1210 ERROR_MAX
- strlen (pop_error
) - 1);
1211 strncat (pop_error
, err_ret
->text
.data
,
1212 min (ERROR_MAX
- strlen (pop_error
) - 1,
1213 err_ret
->text
.length
));
1214 strncat (pop_error
, "']",
1215 ERROR_MAX
- strlen (pop_error
) - 1);
1219 strcpy (pop_error
, KRB_ERROR
);
1220 strncat (pop_error
, error_message (rem
),
1221 ERROR_MAX
- sizeof (KRB_ERROR
));
1224 krb5_free_error (kcontext
, err_ret
);
1225 krb5_auth_con_free (kcontext
, auth_context
);
1226 krb5_free_context (kcontext
);
1231 #else /* ! KERBEROS5 */
1232 ticket
= (KTEXT
) malloc (sizeof (KTEXT_ST
));
1233 realhost
= strdup (hostent
->h_name
);
1234 rem
= krb_sendauth (0L, sock
, ticket
, "pop", realhost
,
1235 (char *) krb_realmofhost (realhost
),
1236 (unsigned long) 0, &msg_data
, &cred
, schedule
,
1237 (struct sockaddr_in
*) 0,
1238 (struct sockaddr_in
*) 0,
1240 free ((char *) ticket
);
1242 if (rem
!= KSUCCESS
)
1244 strcpy (pop_error
, KRB_ERROR
);
1245 strncat (pop_error
, krb_err_txt
[rem
],
1246 ERROR_MAX
- sizeof (KRB_ERROR
));
1250 #endif /* KERBEROS5 */
1252 #endif /* KERBEROS */
1255 } /* socket_connection */
1258 * Function: pop_getline
1260 * Purpose: Get a line of text from the connection and return a
1261 * pointer to it. The carriage return and linefeed at the end of
1262 * the line are stripped, but periods at the beginnings of lines
1263 * are NOT dealt with in any special way.
1266 * server The server from which to get the line of text.
1268 * Returns: The number of characters in the line, which is returned in
1269 * LINE, not including the final null. A return value of 0
1270 * indicates a blank line. A negative return value indicates an
1271 * error (in which case the contents of LINE are undefined. In
1272 * case of error, an error message is copied into pop_error.
1274 * Notes: The line returned is overwritten with each call to pop_getline.
1276 * Side effects: Closes the connection on error.
1278 * THE RETURNED LINE MAY CONTAIN EMBEDDED NULLS!
1281 pop_getline (server
, line
)
1285 #define GETLINE_ERROR "Error reading from server: "
1288 int search_offset
= 0;
1292 char *cp
= find_crlf (server
->buffer
+ server
->buffer_index
,
1299 found
= server
->buffer_index
;
1300 data_used
= (cp
+ 2) - server
->buffer
- found
;
1302 *cp
= '\0'; /* terminate the string to be returned */
1303 server
->data
-= data_used
;
1304 server
->buffer_index
+= data_used
;
1307 /* Embedded nulls will truncate this output prematurely,
1308 but that's OK because it's just for debugging anyway. */
1309 fprintf (stderr
, "<<< %s\n", server
->buffer
+ found
);
1310 *line
= server
->buffer
+ found
;
1311 return (data_used
- 2);
1315 bcopy (server
->buffer
+ server
->buffer_index
,
1316 server
->buffer
, server
->data
);
1317 /* Record the fact that we've searched the data already in
1318 the buffer for a CRLF, so that when we search below, we
1319 don't have to search the same data twice. There's a "-
1320 1" here to account for the fact that the last character
1321 of the data we have may be the CR of a CRLF pair, of
1322 which we haven't read the second half yet, so we may have
1323 to search it again when we read more data. */
1324 search_offset
= server
->data
- 1;
1325 server
->buffer_index
= 0;
1330 server
->buffer_index
= 0;
1335 /* There's a "- 1" here to leave room for the null that we put
1336 at the end of the read data below. We put the null there so
1337 that find_crlf knows where to stop when we call it. */
1338 if (server
->data
== server
->buffer_size
- 1)
1340 server
->buffer_size
+= GETLINE_INCR
;
1341 server
->buffer
= (char *)realloc (server
->buffer
, server
->buffer_size
);
1342 if (! server
->buffer
)
1344 strcpy (pop_error
, "Out of memory in pop_getline");
1349 ret
= RECV (server
->file
, server
->buffer
+ server
->data
,
1350 server
->buffer_size
- server
->data
- 1, 0);
1353 strcpy (pop_error
, GETLINE_ERROR
);
1354 strncat (pop_error
, strerror (errno
),
1355 ERROR_MAX
- sizeof (GETLINE_ERROR
));
1361 strcpy (pop_error
, "Unexpected EOF from server in pop_getline");
1368 server
->data
+= ret
;
1369 server
->buffer
[server
->data
] = '\0';
1371 cp
= find_crlf (server
->buffer
+ search_offset
,
1372 server
->data
- search_offset
);
1375 int data_used
= (cp
+ 2) - server
->buffer
;
1377 server
->data
-= data_used
;
1378 server
->buffer_index
= data_used
;
1381 fprintf (stderr
, "<<< %s\n", server
->buffer
);
1382 *line
= server
->buffer
;
1383 return (data_used
- 2);
1385 /* As above, the "- 1" here is to account for the fact that
1386 we may have read a CR without its accompanying LF. */
1387 search_offset
+= ret
- 1;
1395 * Function: sendline
1397 * Purpose: Sends a line of text to the POP server. The line of text
1398 * passed into this function should NOT have the carriage return
1399 * and linefeed on the end of it. Periods at beginnings of lines
1400 * will NOT be treated specially by this function.
1403 * server The server to which to send the text.
1404 * line The line of text to send.
1406 * Return value: Upon successful completion, a value of 0 will be
1407 * returned. Otherwise, a non-zero value will be returned, and
1408 * an error will be copied into pop_error.
1410 * Side effects: Closes the connection on error.
1413 sendline (server
, line
)
1417 #define SENDLINE_ERROR "Error writing to POP server: "
1420 ret
= fullwrite (server
->file
, line
, strlen (line
));
1422 { /* 0 indicates that a blank line was written */
1423 ret
= fullwrite (server
->file
, "\r\n", 2);
1429 strcpy (pop_error
, SENDLINE_ERROR
);
1430 strncat (pop_error
, strerror (errno
),
1431 ERROR_MAX
- sizeof (SENDLINE_ERROR
));
1436 fprintf (stderr
, ">>> %s\n", line
);
1442 * Procedure: fullwrite
1444 * Purpose: Just like write, but keeps trying until the entire string
1447 * Return value: Same as write. Pop_error is not set.
1450 fullwrite (fd
, buf
, nbytes
)
1459 while (nbytes
&& ((ret
= SEND (fd
, cp
, nbytes
, 0)) > 0))
1471 * Purpose: Reads a line from the server. If the return indicator is
1472 * positive, return with a zero exit status. If not, return with
1473 * a negative exit status.
1476 * server The server to read from.
1478 * Returns: 0 for success, else for failure and puts error in pop_error.
1480 * Side effects: On failure, may make the connection unusable.
1488 if (pop_getline (server
, &fromline
) < 0)
1493 if (! strncmp (fromline
, "+OK", 3))
1495 else if (! strncmp (fromline
, "-ERR", 4))
1497 strncpy (pop_error
, fromline
, ERROR_MAX
);
1498 pop_error
[ERROR_MAX
-1] = '\0';
1504 "Unexpected response from server; expecting +OK or -ERR");
1512 * Function: gettermination
1514 * Purpose: Gets the next line and verifies that it is a termination
1515 * line (nothing but a dot).
1517 * Return value: 0 on success, non-zero with pop_error set on error.
1519 * Side effects: Closes the connection on error.
1522 gettermination (server
)
1527 if (pop_getline (server
, &fromserver
) < 0)
1530 if (strcmp (fromserver
, "."))
1533 "Unexpected response from server in gettermination");
1543 * Function pop_close
1545 * Purpose: Close a pop connection, sending a "RSET" command to try to
1546 * preserve any changes that were made and a "QUIT" command to
1547 * try to get the server to quit, but ignoring any responses that
1550 * Side effects: The server is unusable after this function returns.
1551 * Changes made to the maildrop since the session was started (or
1552 * since the last pop_reset) may be lost.
1559 free ((char *) server
);
1565 * Function: pop_trash
1567 * Purpose: Like pop_close or pop_quit, but doesn't deallocate the
1568 * memory associated with the server. It is legal to call
1569 * pop_close or pop_quit after this function has been called.
1575 if (server
->file
>= 0)
1577 /* avoid recursion; sendline can call pop_trash */
1578 if (server
->trash_started
)
1580 server
->trash_started
= 1;
1582 sendline (server
, "RSET");
1583 sendline (server
, "QUIT");
1585 CLOSESOCKET (server
->file
);
1589 free (server
->buffer
);
1600 /* Return a pointer to the first CRLF in IN_STRING, which can contain
1601 embedded nulls and has LEN characters in it not including the final
1602 null, or 0 if it does not contain one. */
1605 find_crlf (in_string
, len
)
1611 if (*in_string
== '\r')
1613 if (*++in_string
== '\n')
1614 return (in_string
- 1);
1622 #endif /* MAIL_USE_POP */