]>
diplodocus.org Git - nmh/blob - test/fakepop.c
2 * fakepop - A fake POP server used by the nmh test suite
4 * This code is Copyright (c) 2012, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
14 #include <sys/types.h>
17 #define PIDFILE "/tmp/fakepop.pid"
21 #define CHECKUSER() if (!user) { \
22 putcrlf(s, "-ERR Aren't you forgetting " \
23 "something? Like the USER command?"); \
26 #define CHECKAUTH() if (!auth) { \
27 putcrlf(s, "-ERR Um, hello? Forget to " \
32 void putcrlf(int, char *);
33 int serve(const char *, const char *);
35 static void putpopbulk(int, char *);
36 static int getpop(int, char *, ssize_t
);
37 static char *readmessage(FILE *);
40 main(int argc
, char *argv
[])
44 int rc
, s
, user
= 0, auth
= 0, i
, j
;
50 fprintf(stderr
, "Usage: %s port username "
51 "password mail-file [mail-file ...]\n", argv
[0]);
55 if (strcmp(argv
[2], "XOAUTH") == 0) {
63 mfiles
= malloc(sizeof(FILE *) * numfiles
);
66 fprintf(stderr
, "Unable to allocate %d bytes for file "
67 "array\n", (int) (sizeof(FILE *) * numfiles
));
71 octets
= malloc(sizeof(*octets
) * numfiles
);
74 fprintf(stderr
, "Unable to allocate %d bytes for size "
75 "array\n", (int) (sizeof(FILE *) * numfiles
));
79 for (i
= 4, j
= 0; i
< argc
; i
++, j
++) {
80 if (!(mfiles
[j
] = fopen(argv
[i
], "r"))) {
81 fprintf(stderr
, "Unable to open message file \"%s\""
82 ": %s\n", argv
[i
], strerror(errno
));
87 * POP wants the size of the maildrop in bytes, but
88 * with \r\n line endings. Calculate that.
93 while (fgets(line
, sizeof(line
), mfiles
[j
])) {
94 octets
[j
] += strlen(line
);
95 if (strrchr(line
, '\n'))
102 s
= serve(PIDFILE
, argv
[1]);
105 * Pretend to be a POP server
108 putcrlf(s
, "+OK Not really a POP server, but we play one on TV");
111 char linebuf
[LINESIZE
];
113 rc
= getpop(s
, linebuf
, sizeof(linebuf
));
116 break; /* Error or EOF */
118 if (strcasecmp(linebuf
, "CAPA") == 0) {
119 putpopbulk(s
, "+OK We have no capabilities, really\r\n"
120 "FAKE-CAPABILITY\r\n");
121 if (xoauth
!= NULL
) {
122 putcrlf(s
, "SASL XOAUTH2");
125 } else if (strncasecmp(linebuf
, "USER ", 5) == 0) {
126 if (strcmp(linebuf
+ 5, argv
[2]) == 0) {
127 putcrlf(s
, "+OK Niiiice!");
130 putcrlf(s
, "-ERR Don't play me, bro!");
132 } else if (strncasecmp(linebuf
, "PASS ", 5) == 0) {
134 if (strcmp(linebuf
+ 5, argv
[3]) == 0) {
135 putcrlf(s
, "+OK Aren't you a sight "
139 putcrlf(s
, "-ERR C'mon!");
141 } else if (xoauth
!= NULL
142 && strncasecmp(linebuf
, "AUTH XOAUTH2", 12) == 0) {
143 if (strstr(linebuf
, xoauth
) == NULL
) {
144 putcrlf(s
, "+ base64-json-err");
145 rc
= getpop(s
, linebuf
, sizeof(linebuf
));
147 break; /* Error or EOF */
148 putcrlf(s
, "-ERR [AUTH] Invalid credentials.");
151 putcrlf(s
, "+OK Welcome.");
153 } else if (strcasecmp(linebuf
, "STAT") == 0) {
156 for (i
= 0, j
= 0; i
< numfiles
; i
++) {
162 snprintf(linebuf
, sizeof(linebuf
),
163 "+OK %d %d", i
, (int) total
);
165 } else if (strncasecmp(linebuf
, "RETR ", 5) == 0) {
167 rc
= sscanf(linebuf
+ 5, "%d", &i
);
169 putcrlf(s
, "-ERR Whaaaa...?");
172 if (i
< 1 || i
> numfiles
) {
173 putcrlf(s
, "-ERR That message number is "
174 "out of range, jerkface!");
177 if (mfiles
[i
- 1] == NULL
) {
178 putcrlf(s
, "-ERR Sorry, don't have it anymore");
180 char *buf
= readmessage(mfiles
[i
- 1]);
181 putcrlf(s
, "+OK Here you go ...");
185 } else if (strncasecmp(linebuf
, "DELE ", 5) == 0) {
187 rc
= sscanf(linebuf
+ 5, "%d", &i
);
189 putcrlf(s
, "-ERR Whaaaa...?");
192 if (i
< 1 || i
> numfiles
) {
193 putcrlf(s
, "-ERR That message number is "
194 "out of range, jerkface!");
197 if (mfiles
[i
- 1] == NULL
) {
198 putcrlf(s
, "-ERR Um, didn't you tell me "
199 "to delete it already?");
201 fclose(mfiles
[i
- 1]);
202 mfiles
[i
- 1] = NULL
;
203 putcrlf(s
, "+OK Alright man, I got rid of it");
205 } else if (strcasecmp(linebuf
, "QUIT") == 0) {
206 putcrlf(s
, "+OK See ya, wouldn't want to be ya!");
210 putcrlf(s
, "-ERR Um, what?");
218 * Put one big buffer to the POP server. Should have already had the line
219 * endings set up and dot-stuffed if necessary.
223 putpopbulk(int socket
, char *data
)
225 ssize_t datalen
= strlen(data
);
227 if (write(socket
, data
, datalen
) < 0) {
233 * Get one line from the POP server. We don't do any buffering here.
237 getpop(int socket
, char *data
, ssize_t len
)
243 cc
= read(socket
, data
+ offset
, len
- offset
);
246 fprintf(stderr
, "Read failed: %s\n", strerror(errno
));
257 fprintf(stderr
, "Input buffer overflow "
258 "(%d bytes)\n", (int) len
);
262 if (data
[offset
- 1] == '\n' && data
[offset
- 2] == '\r') {
263 data
[offset
- 2] = '\0';
269 #define HAVEROOM(buf, size, used, new) do { \
270 if (used + new > size - 1) { \
271 buf = realloc(buf, size += BUFALLOC); \
276 * Read a file and return it as one malloc()'d buffer. Convert \n to \r\n
277 * and dot-stuff if necessary.
281 readmessage(FILE *file
)
283 char *buffer
= malloc(BUFALLOC
);
284 ssize_t bufsize
= BUFALLOC
, used
= 0;
285 char linebuf
[LINESIZE
];
290 while (fgets(linebuf
, sizeof(linebuf
), file
)) {
291 if (strcmp(linebuf
, ".\n") == 0) {
292 HAVEROOM(buffer
, bufsize
, used
, 4);
293 strcat(buffer
, "..\r\n");
296 if (i
&& linebuf
[i
- 1] == '\n') {
297 HAVEROOM(buffer
, bufsize
, used
, i
+ 1);
298 linebuf
[i
- 1] = '\0';
299 strcat(buffer
, linebuf
);
300 strcat(buffer
, "\r\n");
302 HAVEROOM(buffer
, bufsize
, used
, i
);
303 strcat(buffer
, linebuf
);
309 * Put a terminating dot at the end
312 HAVEROOM(buffer
, bufsize
, used
, 3);
314 strcat(buffer
, ".\r\n");