1/* 2 * Copyright (c) 1989 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7#include <popper.h> 8RCSID("$Id$"); 9 10/* 11 * sendline: Send a line of a multi-line response to a client. 12 */ 13static int 14pop_sendline(POP *p, char *buffer) 15{ 16 char * bp; 17 18 /* Byte stuff lines that begin with the termination octet */ 19 if (*buffer == POP_TERMINATE) 20 fputc(POP_TERMINATE,p->output); 21 22 /* Look for a <NL> in the buffer */ 23 if ((bp = strchr(buffer, '\n'))) 24 *bp = 0; 25 26 /* Send the line to the client */ 27 fputs(buffer,p->output); 28 29#ifdef DEBUG 30 if(p->debug) 31 pop_log(p,POP_DEBUG,"Sending line \"%s\"",buffer); 32#endif /* DEBUG */ 33 34 /* Put a <CR><NL> if a newline was removed from the buffer */ 35 if (bp) 36 fputs ("\r\n",p->output); 37 return bp != NULL; 38} 39 40/* 41 * send: Send the header and a specified number of lines 42 * from a mail message to a POP client. 43 */ 44 45int 46pop_send(POP *p) 47{ 48 MsgInfoList * mp; /* Pointer to message info list */ 49 int msg_num; 50 int msg_lines; 51 char buffer[MAXMSGLINELEN]; 52#ifdef RETURN_PATH_HANDLING 53 char * return_path_adr; 54 char * return_path_end; 55 int return_path_sent; 56 int return_path_linlen; 57#endif 58 int sent_nl = 0; 59 60 /* Convert the first parameter into an integer */ 61 msg_num = atoi(p->pop_parm[1]); 62 63 /* Is requested message out of range? */ 64 if ((msg_num < 1) || (msg_num > p->msg_count)) 65 return (pop_msg (p,POP_FAILURE,"Message %d does not exist.",msg_num)); 66 67 /* Get a pointer to the message in the message list */ 68 mp = &p->mlp[msg_num-1]; 69 70 /* Is the message flagged for deletion? */ 71 if (mp->flags & DEL_FLAG) 72 return (pop_msg (p,POP_FAILURE, 73 "Message %d has been deleted.",msg_num)); 74 75 /* If this is a TOP command, get the number of lines to send */ 76 if (strcmp(p->pop_command, "top") == 0) { 77 /* Convert the second parameter into an integer */ 78 msg_lines = atoi(p->pop_parm[2]); 79 } 80 else { 81 /* Assume that a RETR (retrieve) command was issued */ 82 msg_lines = -1; 83 /* Flag the message as retreived */ 84 mp->flags |= RETR_FLAG; 85 } 86 87 /* Display the number of bytes in the message */ 88 pop_msg(p, POP_SUCCESS, "%ld octets", mp->length); 89 90 if(IS_MAILDIR(p)) { 91 int e = pop_maildir_open(p, mp); 92 if(e != POP_SUCCESS) 93 return e; 94 } 95 96 /* Position to the start of the message */ 97 fseek(p->drop, mp->offset, 0); 98 99 return_path_sent = 0; 100 101 if(!IS_MAILDIR(p)) { 102 /* Skip the first line (the sendmail "From" line) */ 103 fgets (buffer,MAXMSGLINELEN,p->drop); 104 105#ifdef RETURN_PATH_HANDLING 106 if (strncmp(buffer,"From ",5) == 0) { 107 return_path_linlen = strlen(buffer); 108 for (return_path_adr = buffer+5; 109 (*return_path_adr == ' ' || *return_path_adr == '\t') && 110 return_path_adr < buffer + return_path_linlen; 111 return_path_adr++) 112 ; 113 if (return_path_adr < buffer + return_path_linlen) { 114 if ((return_path_end = strchr(return_path_adr, ' ')) != NULL) 115 *return_path_end = '\0'; 116 if (strlen(return_path_adr) != 0 && *return_path_adr != '\n') { 117 static char tmpbuf[MAXMSGLINELEN + 20]; 118 if (snprintf (tmpbuf, 119 sizeof(tmpbuf), 120 "Return-Path: %s\n", 121 return_path_adr) < MAXMSGLINELEN) { 122 pop_sendline (p,tmpbuf); 123 if (hangup) 124 return pop_msg (p, POP_FAILURE, 125 "SIGHUP or SIGPIPE flagged"); 126 return_path_sent++; 127 } 128 } 129 } 130 } 131#endif 132 } 133 134 /* Send the header of the message followed by a blank line */ 135 while (fgets(buffer,MAXMSGLINELEN,p->drop)) { 136#ifdef RETURN_PATH_HANDLING 137 /* Don't send existing Return-Path-header if already sent own */ 138 if (!return_path_sent || strncasecmp(buffer, "Return-Path:", 12) != 0) 139#endif 140 sent_nl = pop_sendline (p,buffer); 141 /* A single newline (blank line) signals the 142 end of the header. sendline() converts this to a NULL, 143 so that's what we look for. */ 144 if (*buffer == 0) break; 145 if (hangup) 146 return (pop_msg (p,POP_FAILURE,"SIGHUP or SIGPIPE flagged")); 147 } 148 /* Send the message body */ 149 { 150 int blank_line = 1; 151 while (fgets(buffer, MAXMSGLINELEN-1, p->drop)) { 152 /* Look for the start of the next message */ 153 if (!IS_MAILDIR(p) && blank_line && strncmp(buffer,"From ",5) == 0) 154 break; 155 blank_line = (strncmp(buffer, "\n", 1) == 0); 156 /* Decrement the lines sent (for a TOP command) */ 157 if (msg_lines >= 0 && msg_lines-- == 0) break; 158 sent_nl = pop_sendline(p,buffer); 159 if (hangup) 160 return (pop_msg (p,POP_FAILURE,"SIGHUP or SIGPIPE flagged")); 161 } 162 /* add missing newline at end */ 163 if(!sent_nl) 164 fputs("\r\n", p->output); 165 /* some pop-clients want a blank line at the end of the 166 message, we always add one here, but what the heck -- in 167 outer (white) space, no one can hear you scream */ 168 if(IS_MAILDIR(p)) 169 fputs("\r\n", p->output); 170 } 171 /* "." signals the end of a multi-line transmission */ 172 fputs(".\r\n",p->output); 173 fflush(p->output); 174 175 return(POP_SUCCESS); 176} 177