summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/appl/popper/pop_send.c
blob: 166b990a141935e0ebd6e10f44a248159acd7e01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 * Copyright (c) 1989 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#include <popper.h>
RCSID("$Id: pop_send.c,v 1.25 1999/03/05 14:14:28 joda Exp $");

/*
 *  sendline:   Send a line of a multi-line response to a client.
 */
static int
pop_sendline(POP *p, char *buffer)
{
    char        *   bp;

    /*  Byte stuff lines that begin with the termination octet */
    if (*buffer == POP_TERMINATE) 
      fputc(POP_TERMINATE,p->output);

    /*  Look for a <NL> in the buffer */
    if ((bp = strchr(buffer, '\n')))
      *bp = 0;

    /*  Send the line to the client */
    fputs(buffer,p->output);

#ifdef DEBUG
    if(p->debug)
      pop_log(p,POP_DEBUG,"Sending line \"%s\"",buffer);
#endif /* DEBUG */

    /*  Put a <CR><NL> if a newline was removed from the buffer */
    if (bp)
      fputs ("\r\n",p->output);
    return bp != NULL;
}

/* 
 *  send:   Send the header and a specified number of lines 
 *          from a mail message to a POP client.
 */

int
pop_send(POP *p)
{
    MsgInfoList         *   mp;         /*  Pointer to message info list */
    int		            msg_num;
    int			    msg_lines;
    char                    buffer[MAXMSGLINELEN];
#ifdef RETURN_PATH_HANDLING
    char		*   return_path_adr;
    char		*   return_path_end;
    int			    return_path_sent;
    int			    return_path_linlen;
#endif
    int			sent_nl = 0;

    /*  Convert the first parameter into an integer */
    msg_num = atoi(p->pop_parm[1]);

    /*  Is requested message out of range? */
    if ((msg_num < 1) || (msg_num > p->msg_count))
        return (pop_msg (p,POP_FAILURE,"Message %d does not exist.",msg_num));

    /*  Get a pointer to the message in the message list */
    mp = &p->mlp[msg_num-1];

    /*  Is the message flagged for deletion? */
    if (mp->flags & DEL_FLAG)
        return (pop_msg (p,POP_FAILURE,
			 "Message %d has been deleted.",msg_num));

    /*  If this is a TOP command, get the number of lines to send */
    if (strcmp(p->pop_command, "top") == 0) {
        /*  Convert the second parameter into an integer */
        msg_lines = atoi(p->pop_parm[2]);
    }
    else {
        /*  Assume that a RETR (retrieve) command was issued */
        msg_lines = -1;
        /*  Flag the message as retreived */
        mp->flags |= RETR_FLAG;
    }
    
    /*  Display the number of bytes in the message */
    pop_msg(p, POP_SUCCESS, "%ld octets", mp->length);

    if(IS_MAILDIR(p)) {
	int e = pop_maildir_open(p, mp);
	if(e != POP_SUCCESS)
	    return e;
    }

    /*  Position to the start of the message */
    fseek(p->drop, mp->offset, 0);

    return_path_sent = 0;

    if(!IS_MAILDIR(p)) {
	/*  Skip the first line (the sendmail "From" line) */
	fgets (buffer,MAXMSGLINELEN,p->drop);

#ifdef RETURN_PATH_HANDLING
	if (strncmp(buffer,"From ",5) == 0) {
	    return_path_linlen = strlen(buffer);
	    for (return_path_adr = buffer+5;
		 (*return_path_adr == ' ' || *return_path_adr == '\t') &&
		     return_path_adr < buffer + return_path_linlen;
		 return_path_adr++)
		;
	    if (return_path_adr < buffer + return_path_linlen) {
		if ((return_path_end = strchr(return_path_adr, ' ')) != NULL)
		    *return_path_end = '\0';
		if (strlen(return_path_adr) != 0 && *return_path_adr != '\n') {
		    static char tmpbuf[MAXMSGLINELEN + 20];
		    if (snprintf (tmpbuf,
				  sizeof(tmpbuf),
				  "Return-Path: %s\n",
				  return_path_adr) < MAXMSGLINELEN) {
			pop_sendline (p,tmpbuf);
			if (hangup)
			    return pop_msg (p, POP_FAILURE,
					    "SIGHUP or SIGPIPE flagged");
			return_path_sent++;
		    }
		}
	    }
	}
#endif
    }

    /*  Send the header of the message followed by a blank line */
    while (fgets(buffer,MAXMSGLINELEN,p->drop)) {
#ifdef RETURN_PATH_HANDLING
	/* Don't send existing Return-Path-header if already sent own */
	if (!return_path_sent || strncasecmp(buffer, "Return-Path:", 12) != 0)
#endif
	    sent_nl = pop_sendline (p,buffer);
        /*  A single newline (blank line) signals the 
            end of the header.  sendline() converts this to a NULL, 
            so that's what we look for. */
        if (*buffer == 0) break;
        if (hangup)
	    return (pop_msg (p,POP_FAILURE,"SIGHUP or SIGPIPE flagged"));
    }
    /*  Send the message body */
    {
	int blank_line = 1;
	while (fgets(buffer, MAXMSGLINELEN-1, p->drop)) {
	    /*  Look for the start of the next message */
	    if (!IS_MAILDIR(p) && blank_line && strncmp(buffer,"From ",5) == 0)
		break;
	    blank_line = (strncmp(buffer, "\n", 1) == 0);
	    /*  Decrement the lines sent (for a TOP command) */
	    if (msg_lines >= 0 && msg_lines-- == 0) break;
	    sent_nl = pop_sendline(p,buffer);
	    if (hangup)
		return (pop_msg (p,POP_FAILURE,"SIGHUP or SIGPIPE flagged"));
	}
	/* add missing newline at end */
	if(!sent_nl)
	    fputs("\r\n", p->output);
	/* some pop-clients want a blank line at the end of the
           message, we always add one here, but what the heck -- in
           outer (white) space, no one can hear you scream */
	if(IS_MAILDIR(p))
	    fputs("\r\n", p->output);
    }
    /*  "." signals the end of a multi-line transmission */
    fputs(".\r\n",p->output);
    fflush(p->output);

    return(POP_SUCCESS);
}
OpenPOWER on IntegriCloud