int pop_multi_first (popserver server, const char *command, char **response) { if (server->in_multi) { strcpy (pop_error, "Already in multi-line query in pop_multi_first"); return (-1); } if (sendline (server, command) || (pop_getline (server, response) < 0)) { return (-1); } if (0 == strncmp (*response, "-ERR", 4)) { snprintf (pop_error, ERROR_MAX, "%s", *response); return (-1); } else if (0 == strncmp (*response, "+OK", 3)) { for (*response += 3; **response == ' '; (*response)++) /* empty */; server->in_multi = true; return (0); } else { strcpy (pop_error, "Unexpected response from server in pop_multi_first"); return (-1); } }
/* * Procedure getok * * Purpose: Reads a line from the server. If the return indicator is * positive, return with a zero exit status. If not, return with * a negative exit status. * * 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. */ static int getok (popserver server) { char *fromline; if (pop_getline (server, &fromline) < 0) { return (-1); } if (! strncmp (fromline, "+OK", 3)) return (0); else if (! strncmp (fromline, "-ERR", 4)) { snprintf (pop_error, ERROR_MAX, "%s", fromline); return (-1); } else { strcpy (pop_error, "Unexpected response from server; expecting +OK or -ERR"); pop_trash (server); return (-1); } }
/* * Function: pop_stat * * Purpose: Issue the STAT command to the server and return (in the * value parameters) the number of messages in the maildrop and * the total size of the maildrop. * * Return value: 0 on success, or non-zero with an error in pop_error * in failure. * * Side effects: On failure, may make further operations on the * connection impossible. */ int pop_stat (popserver server, int *count, int *size) { char *fromserver; char *end_ptr; if (server->in_multi) { strcpy (pop_error, "In multi-line query in pop_stat"); return (-1); } if (sendline (server, "STAT") || (pop_getline (server, &fromserver) < 0)) return (-1); if (strncmp (fromserver, "+OK ", 4)) { if (0 == strncmp (fromserver, "-ERR", 4)) { strncpy (pop_error, fromserver, ERROR_MAX); } else { strcpy (pop_error, "Unexpected response from POP server in pop_stat"); pop_trash (server); } return (-1); } errno = 0; *count = strtol (&fromserver[4], &end_ptr, 10); /* Check validity of string-to-integer conversion. */ if (fromserver + 4 == end_ptr || *end_ptr != ' ' || errno) { strcpy (pop_error, "Unexpected response from POP server in pop_stat"); pop_trash (server); return (-1); } fromserver = end_ptr; errno = 0; *size = strtol (fromserver + 1, &end_ptr, 10); if (fromserver + 1 == end_ptr || errno) { strcpy (pop_error, "Unexpected response from POP server in pop_stat"); pop_trash (server); return (-1); } return (0); }
/* * Function: pop_last * * Purpose: Find out the highest seen message from the server. * * Arguments: * server The server. * * Return value: If successful, the highest seen message, which is * greater than or equal to 0. Otherwise, a negative number with * the error explained in pop_error. * * Side effects: Closes the connection on error. */ int pop_last (popserver server) { char *fromserver; if (server->in_multi) { strcpy (pop_error, "In multi-line query in pop_last"); return (-1); } if (sendline (server, "LAST")) return (-1); if (pop_getline (server, &fromserver) < 0) return (-1); if (! strncmp (fromserver, "-ERR", 4)) { snprintf (pop_error, ERROR_MAX, "%s", fromserver); return (-1); } else if (strncmp (fromserver, "+OK ", 4)) { strcpy (pop_error, "Unexpected response from server in pop_last"); pop_trash (server); return (-1); } else { char *end_ptr; int count; errno = 0; count = strtol (&fromserver[4], &end_ptr, 10); if (fromserver + 4 == end_ptr || errno) { strcpy (pop_error, "Unexpected response from server in pop_last"); pop_trash (server); return (-1); } return count; } }
int pop_multi_next (popserver server, char **line) { char *fromserver; int ret; if (! server->in_multi) { strcpy (pop_error, "Not in multi-line query in pop_multi_next"); return (-1); } ret = pop_getline (server, &fromserver); if (ret < 0) { return (-1); } if (fromserver[0] == '.') { if (! fromserver[1]) { *line = 0; server->in_multi = false; return (0); } else { *line = fromserver + 1; return (ret - 1); } } else { *line = fromserver; return (ret); } }
/* * Function: pop_list * * Purpose: Performs the POP "list" command and returns (in value * parameters) two malloc'd zero-terminated arrays -- one of * message IDs, and a parallel one of sizes. * * Arguments: * server The pop connection to talk to. * message The number of the one message about which to get * information, or 0 to get information about all * messages. * * Return value: 0 on success, non-zero with error in pop_error on * failure. * * Side effects: On failure, may make further operations on the * connection impossible. */ int pop_list (popserver server, int message, int **IDs, int **sizes) { int how_many, i; char *fromserver; if (server->in_multi) { strcpy (pop_error, "In multi-line query in pop_list"); return (-1); } if (message) how_many = 1; else { int count, size; if (pop_stat (server, &count, &size)) return (-1); how_many = count; } *IDs = (int *) malloc ((how_many + 1) * sizeof (int)); *sizes = (int *) malloc ((how_many + 1) * sizeof (int)); if (! (*IDs && *sizes)) { strcpy (pop_error, "Out of memory in pop_list"); return (-1); } if (message) { sprintf (pop_error, "LIST %d", message); if (sendline (server, pop_error)) { free ((char *) *IDs); free ((char *) *sizes); return (-1); } if (pop_getline (server, &fromserver) < 0) { free ((char *) *IDs); free ((char *) *sizes); return (-1); } if (strncmp (fromserver, "+OK ", 4)) { if (! strncmp (fromserver, "-ERR", 4)) snprintf (pop_error, ERROR_MAX, "%s", fromserver); else { strcpy (pop_error, "Unexpected response from server in pop_list"); pop_trash (server); } free ((char *) *IDs); free ((char *) *sizes); return (-1); } (*IDs)[0] = atoi (&fromserver[4]); fromserver = strchr (&fromserver[4], ' '); if (! fromserver) { strcpy (pop_error, "Badly formatted response from server in pop_list"); pop_trash (server); free ((char *) *IDs); free ((char *) *sizes); return (-1); } (*sizes)[0] = atoi (fromserver); (*IDs)[1] = (*sizes)[1] = 0; return (0); } else { if (pop_multi_first (server, "LIST", &fromserver)) { free ((char *) *IDs); free ((char *) *sizes); return (-1); } for (i = 0; i < how_many; i++) { if (pop_multi_next (server, &fromserver) <= 0) { free ((char *) *IDs); free ((char *) *sizes); return (-1); } (*IDs)[i] = atoi (fromserver); fromserver = strchr (fromserver, ' '); if (! fromserver) { strcpy (pop_error, "Badly formatted response from server in pop_list"); free ((char *) *IDs); free ((char *) *sizes); pop_trash (server); return (-1); } (*sizes)[i] = atoi (fromserver); } if (pop_multi_next (server, &fromserver) < 0) { free ((char *) *IDs); free ((char *) *sizes); return (-1); } else if (fromserver) { strcpy (pop_error, "Too many response lines from server in pop_list"); free ((char *) *IDs); free ((char *) *sizes); return (-1); } (*IDs)[i] = (*sizes)[i] = 0; return (0); } }