emailler/apps/pop65-slow.c

241 lines
4.9 KiB
C

///////////////////////////////////////////
//
// POP3 Client
// Bobbi June 2020
//
// https://www.ietf.org/rfc/rfc1939.txt
//
///////////////////////////////////////////
#include <cc65.h>
#include <fcntl.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include "../inc/ip65.h"
#define FILENAME "/H1/DOCUMENTS/EMAIL.TXT"
char expected[80] = "";
volatile uint8_t await_response = 0;
volatile uint8_t got_expected = 0;
volatile uint8_t data_mode = 0; // Set to 1 when receiving body of email
unsigned char buf[1500];
int len;
FILE *fp;
// Configuration params from POP65.CFG
char cfg_server[80];
char cfg_user[80];
char cfg_pass[80];
void error_exit(void)
{
printf("- %s\n", ip65_strerror(ip65_error));
exit(EXIT_FAILURE);
}
void confirm_exit(void)
{
printf("\nPress any key ");
cgetc();
}
/*
* Handle an incoming TCP message
*/
void __fastcall__ tcpcb(const uint8_t *tcp_buf, int16_t tcp_len) {
int idx;
await_response = 0;
len = tcp_len;
if (len != -1) {
if (data_mode) {
// printf("%d ", len);
memcpy(buf, tcp_buf, len);
buf[len] = 0;
for (idx = 0; idx < len; ++idx) {
if ((idx % 11) == 0)
ip65_process();
if (buf[idx] != '\r')
putchar(buf[idx]);
}
fwrite(buf, 1, len, fp);
idx = strstr(buf, "\r\n.\r\n"); // CRLF.CRLF
if (idx) {
puts("Found end");
data_mode = 0; // If found, turn off data_mode
fclose(fp);
}
return;
}
memcpy(buf, tcp_buf, len);
buf[len-1] = 0; // HACK TO REMOVE DUPLICATE CR/LF
printf("<%s", buf);
if (strlen(expected) > 0) {
#ifdef DEBUG
printf("Expected:%s", expected);
#endif
if (strncmp(buf, expected, strlen(expected)) == 0) {
got_expected = 1;
#ifdef DEBUG
printf(" match\n");
#endif
} else {
got_expected = 0;
#ifdef DEBUG
printf(" NO match\n");
#endif
}
} else
got_expected = 1;
}
}
/*
* Check gotexpected flag and quit if false
*/
void checkgotexpected(void) {
int i;
while (await_response == 1) {
#ifdef DEBUG
putchar('.');
#endif
ip65_process();
for (i = 0; i < 20000; ++i);
}
if (!got_expected) {
printf("Didn't get expected response\n");
error_exit();
} else
putchar('.');
}
/*
* Send a TCP message
* msg - string to send
* expect - sting to expect (or empty string)
*/
void sendmessage(char *msg, char *expect) {
strcpy(expected, expect);
if (strncmp(msg, "PASS", 4) == 0)
printf(">PASS ****\n");
else
printf(">%s", msg);
if (tcp_send(msg, strlen(msg))) {
error_exit();
}
await_response = 1;
ip65_process();
}
void readconfigfile(void) {
fp = fopen("POP65.CFG", "r");
if (!fp) {
puts("Can't open config file POP65.CFG");
error_exit();
}
fscanf(fp, "%s", cfg_server);
fscanf(fp, "%s", cfg_user);
fscanf(fp, "%s", cfg_pass);
fclose(fp);
}
int main(void)
{
uint8_t eth_init = ETH_INIT_DEFAULT;
char sendbuf[80];
uint16_t msg, nummsgs;
uint32_t bytes;
if (doesclrscrafterexit())
{
atexit(confirm_exit);
}
videomode(VIDEOMODE_80COL);
printf("\nReading POP65.CFG -");
readconfigfile();
printf(" Ok");
#ifdef __APPLE2__
{
int file;
printf("\nSetting slot -");
file = open("ethernet.slot", O_RDONLY);
if (file != -1)
{
read(file, &eth_init, 1);
close(file);
eth_init &= ~'0';
}
printf(" %d\n", eth_init);
}
#endif
printf("Initializing -");
if (ip65_init(eth_init))
{
error_exit();
}
printf(" Ok\nObtaining IP address -");
if (dhcp_init())
{
error_exit();
}
printf(" Ok\nConnecting to %s -", cfg_server);
if (tcp_connect(parse_dotted_quad(cfg_server), 110, tcpcb)) {
error_exit();
}
printf(" Ok\n\n");
strcpy(expected, "+OK");
ip65_process();
await_response = 1;
checkgotexpected();
sprintf(sendbuf, "USER %s\n", cfg_user);
sendmessage(sendbuf, "+OK");
ip65_process();
checkgotexpected();
sprintf(sendbuf, "PASS %s\n", cfg_pass);
sendmessage(sendbuf, "+OK Logged in.");
ip65_process();
checkgotexpected();
sendmessage("STAT\n", "+OK");
ip65_process();
checkgotexpected();
sscanf(buf, "+OK %u %lu", &nummsgs, &bytes);
printf(" %u message(s), %lu total bytes\n", nummsgs, bytes);
for (msg = 1; msg <= nummsgs; ++msg) {
data_mode = 1;
remove(FILENAME);
fp = fopen(FILENAME, "wb");
if (!fp) {
printf("Can't open %s\n", FILENAME);
error_exit();
}
sprintf(sendbuf, "RETR %d\n", msg);
sendmessage(sendbuf, "");
do {
ip65_process();
} while (data_mode == 1);
}
sendmessage("QUIT\n", "+OK Logging out.");
ip65_process();
checkgotexpected();
printf(" Ok\nClosing connection -");
if (tcp_close()) {
error_exit();
}
printf(" Ok\n\n");
return EXIT_SUCCESS;
}