mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-06-11 03:29:28 +00:00
Compare commits
35 Commits
emailler-v
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
9fdedd46bb | ||
|
9fa090f34d | ||
|
95615458aa | ||
|
d8d532fd72 | ||
|
7c402facc7 | ||
|
7bb47d4b85 | ||
|
d015ca310c | ||
|
e102d732b0 | ||
|
6106701fa8 | ||
|
077bddc9f1 | ||
|
e123dc2dbc | ||
|
675073a6c9 | ||
|
4e482b14cb | ||
|
ef07cc8b88 | ||
|
c2b4773e1c | ||
|
305c7bcf34 | ||
|
6e9c751f53 | ||
|
6613ec218c | ||
|
44c46943b0 | ||
|
52f6b664e4 | ||
|
9c4baa170d | ||
|
e943e0cca1 | ||
|
80bf13eb69 | ||
|
004c2cb1dc | ||
|
85f6fab6a9 | ||
|
6919adb9be | ||
|
6b1cde52c1 | ||
|
d7ec996cc8 | ||
|
ba19bc4f57 | ||
|
19ffeb1c8a | ||
|
f63fe7829f | ||
|
677137e851 | ||
|
332a5bb7e1 | ||
|
07bc9b40d8 | ||
|
432de5ad21 |
|
@ -82,7 +82,7 @@ Install the packages with root privs on the Pi:
|
|||
```
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
sudo apt install postfix postfix-pcre
|
||||
sudo apt install postfix postfix-pcre libsasl2-modules
|
||||
sudo apt install dovecot-common dovecot-pop3d
|
||||
sudo apt install fetchmail
|
||||
```
|
||||
|
@ -134,7 +134,7 @@ We will modify a number of configuration files:
|
|||
- `/etc/postfix/sasl/sasl_passwd`
|
||||
- `/etc/postfix/sasl/sasl_passwd.db`
|
||||
|
||||
Once Dovecot has been configured, the service may be controlled as follows:
|
||||
Once Postfix has been configured, the service may be controlled as follows:
|
||||
- `systemctl start postfix` - start service.
|
||||
- `systemctl stop postfix` - stop service.
|
||||
- `systemctl status postfix` - status of service.
|
||||
|
@ -179,6 +179,10 @@ My home network is 192.168.10.0/24, so I added it here:
|
|||
`mynetworks = 192.168.10.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128`.
|
||||
You should adjust this line to match your own LAN subnet.
|
||||
|
||||
I had an issue where the Pi was unable to connect to Google's SMTP server.
|
||||
It turned out it was trying to use IPv6, so I forced IPv4 as follows:
|
||||
`inet_protocols = ipv4`
|
||||
|
||||
Finally I added the following block of settings to enabled SASL authentication
|
||||
when talking to Gmail:
|
||||
|
||||
|
@ -245,7 +249,7 @@ mynetworks = 192.168.10.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
|
|||
mailbox_size_limit = 0
|
||||
recipient_delimiter = +
|
||||
inet_interfaces = all
|
||||
inet_protocols = all
|
||||
inet_protocols = ipv4
|
||||
|
||||
# Enable SASL authentication
|
||||
smtp_sasl_auth_enable = yes
|
||||
|
|
|
@ -27,14 +27,14 @@ Here is an example config file (with passwords replaced with `****` for obvious
|
|||
Bobbi
|
||||
****
|
||||
/H1/IP65
|
||||
/DATA/EMAIL
|
||||
/H1/DOCUMENTS/EMAIL
|
||||
bobbi.8bit@gmail.com
|
||||
```
|
||||
|
||||
The lines are as follows, in order:
|
||||
|
||||
1) IP address of the NNTP server, optionally followed by a colon and then the TCP port number. If the colon and port number are omitted, port 119 is the default.
|
||||
2) Username to use when connecting to NNTP.
|
||||
2) Username to use when connecting to NNTP. If your NNTP server does not need authentication then use '-' for the username and password.
|
||||
3) Password to use when connecting to NNTP.
|
||||
4) ProDOS path of the directory where the email executables are installed.
|
||||
5) ProDOS path to the root of the email folder tree. Mailboxes will be created and managed under this root path.
|
||||
|
|
|
@ -69,6 +69,10 @@ Recommended optional hardware:
|
|||
|
||||
Emai//er has been extensively tested using ProDOS 2.4.2. However, it should not be a problem to run it under other versions of ProDOS.
|
||||
|
||||
## Uthernet-II Slot
|
||||
|
||||
The default slot is 5. If you have your card in another slot then create a file called `ethernet.slot` using `EDIT.SYSTEM` with your slot number on the first line.
|
||||
|
||||
## Transport Level Security (TLS)
|
||||
|
||||
One problem faced by any retrocomputing project of this type is that Transport Layer Security (TLS) is endemic on today's Internet. While this is great for security, the encryption algorithms are not feasible to implement on a 6502-based system. In order to bridge the plain text world of the Apple II to today's encrypted Internet, I have set up a Raspberry Pi using several common open source packages as a gateway.
|
||||
|
|
|
@ -335,6 +335,8 @@ struct tabent {
|
|||
*/
|
||||
void file_ui_draw(uint16_t i, uint16_t first, uint16_t selected, uint16_t entries) {
|
||||
struct tabent *entry;
|
||||
if (i < first)
|
||||
return;
|
||||
gotoxy(5, i - first + 6);
|
||||
if (i < entries) {
|
||||
entry = (struct tabent*)iobuf + i;
|
||||
|
@ -395,14 +397,10 @@ void file_ui_draw_all(uint16_t first, uint16_t selected, uint16_t entries) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Perform ProDOS MLI ON_LINE call to
|
||||
* write all online volume names into iobuf[]
|
||||
* Return the number of entries
|
||||
* Asm code for online()
|
||||
*/
|
||||
uint16_t online(void) {
|
||||
uint16_t entries = 0;
|
||||
struct tabent *entry;
|
||||
uint8_t i, j, len;
|
||||
#pragma optimize (push, off)
|
||||
void onlineasm(void) {
|
||||
__asm__("lda #$00"); // All devices
|
||||
__asm__("sta mliparam + 1");
|
||||
__asm__("lda #<%v", iobuf); // iobuf LSB
|
||||
|
@ -413,6 +411,19 @@ uint16_t online(void) {
|
|||
__asm__("lda #$c5"); // ON_LINE
|
||||
__asm__("ldx #$02"); // Two parms
|
||||
__asm__("jsr callmli");
|
||||
}
|
||||
#pragma optimize (pop)
|
||||
|
||||
/*
|
||||
* Perform ProDOS MLI ON_LINE call to
|
||||
* write all online volume names into iobuf[]
|
||||
* Return the number of entries
|
||||
*/
|
||||
uint16_t online(void) {
|
||||
uint16_t entries = 0;
|
||||
struct tabent *entry;
|
||||
uint8_t i, j, len;
|
||||
onlineasm();
|
||||
entry = (struct tabent*)iobuf;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
len = iobuf[256 + i * 16] & 0x0f;
|
||||
|
|
14
apps/edit.c
14
apps/edit.c
|
@ -1730,8 +1730,8 @@ void disconnect_ramdisk(void) {
|
|||
uint16_t *s3d2 = (uint16_t*)0xbf26; // s3d2 driver vector
|
||||
if (*s0d1 != *s3d2)
|
||||
check_ramdisk(3 + (2 - 1) * 8); // s3d2
|
||||
if (*s0d1 != *s3d1)
|
||||
check_ramdisk(3 + (1 - 1) * 8); // s3d1
|
||||
// if (*s0d1 != *s3d1)
|
||||
// check_ramdisk(3 + (1 - 1) * 8); // s3d1
|
||||
if (*s0d1 == *s3d2) {
|
||||
s3d2dev = 0;
|
||||
goto s3d1; // No /RAM
|
||||
|
@ -1747,6 +1747,8 @@ void disconnect_ramdisk(void) {
|
|||
*s3d2 = *s0d1;
|
||||
--(*devcnt);
|
||||
s3d1:
|
||||
return;
|
||||
#if 0
|
||||
if (*s0d1 == *s3d1) {
|
||||
s3d1dev = 0;
|
||||
return; // No /RAM3
|
||||
|
@ -1761,6 +1763,7 @@ s3d1:
|
|||
s3d1vec = *s3d1;
|
||||
*s3d1 = *s0d1;
|
||||
--(*devcnt);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1808,6 +1811,7 @@ void reconnect_ramdisk(void) {
|
|||
printf("Unable to reconnect S3D2");
|
||||
}
|
||||
s3d1:
|
||||
# if 0
|
||||
if (s3d1dev) {
|
||||
*s3d1 = s3d1vec;
|
||||
++(*devcnt);
|
||||
|
@ -1828,6 +1832,7 @@ s3d1:
|
|||
beep();
|
||||
printf("Unable to reconnect S3D1");
|
||||
}
|
||||
#endif
|
||||
done:
|
||||
return;
|
||||
}
|
||||
|
@ -1891,7 +1896,7 @@ void init_aux_banks(void) {
|
|||
uint16_t count;
|
||||
clrscr();
|
||||
revers(1);
|
||||
cprintf("EDIT.SYSTEM v1.28 Bobbi 2021");
|
||||
cprintf("EDIT.SYSTEM v1.30 Bobbi 2021");
|
||||
revers(0);
|
||||
cprintf("\n\n\n %u x 64KB aux banks -> %uKB\n", banktbl[0], banktbl[0]*64);
|
||||
for (i = 1; i <= banktbl[0]; ++i) {
|
||||
|
@ -2044,6 +2049,8 @@ struct tabent {
|
|||
*/
|
||||
void file_ui_draw(uint16_t i, uint16_t first, uint16_t selected, uint16_t entries) {
|
||||
struct tabent *entry;
|
||||
if (i < first)
|
||||
return;
|
||||
gotoxy(5, i - first + 6);
|
||||
if (i < entries) {
|
||||
entry = (struct tabent*)iobuf + i;
|
||||
|
@ -2631,6 +2638,7 @@ int edit(char *fname) {
|
|||
}
|
||||
break;
|
||||
case 0x80 + '?': // OA-? "Help"
|
||||
case 0x80 + '/': // OA-/ "Help"
|
||||
help1:
|
||||
help(1);
|
||||
c = cgetc();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--------------------------------------------------------------------------------
|
||||
v1.28 }}} EDIT.SYSTEM HELP }}} Page One
|
||||
v1.30 }}} EDIT.SYSTEM HELP }}} Page One
|
||||
--------------------------------------+-----------------------------------------
|
||||
Navigation: | Editing:
|
||||
Cursor keys Move the cursor | [Return] Split line
|
||||
|
|
233
apps/email.c
233
apps/email.c
|
@ -1,7 +1,7 @@
|
|||
/////////////////////////////////////////////////////////////////
|
||||
// emai//er - Simple Email User Agent vaguely inspired by Elm
|
||||
// Handles INBOX in the format created by POP65
|
||||
// Bobbi June 2020 - May 2021
|
||||
// Bobbi June 2020 - June 2021
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -22,8 +22,9 @@
|
|||
// Program constants
|
||||
#define MSGS_PER_PAGE 19 // Number of messages shown on summary screen
|
||||
#define PROMPT_ROW 24 // Row that data entry prompt appears on
|
||||
#define LINEBUFSZ 1000 // According to RFC2822 Section 2.1.1 (998+CRLF)
|
||||
#define READSZ 512 // Size of buffer for copying files
|
||||
#define LINEBUFSZ 1024 // Max line 1000 according to RFC2822 Sect 2.1.1
|
||||
// We use 1024 because this is also used for scrollback
|
||||
|
||||
// Characters
|
||||
#define BELL 0x07
|
||||
|
@ -88,8 +89,7 @@ struct datetime {
|
|||
|
||||
static char filename[80];
|
||||
static char userentry[80];
|
||||
static char linebuf[LINEBUFSZ];
|
||||
static char halfscreen[0x0400];
|
||||
static uint8_t linebuf[LINEBUFSZ];
|
||||
static FILE *fp;
|
||||
static struct emailhdrs *headers;
|
||||
static uint16_t selection = 1;
|
||||
|
@ -553,7 +553,7 @@ uint8_t hexdigit(char c) {
|
|||
* p - Pointer to buffer to decode. Results written in place.
|
||||
* Returns number of bytes decoded
|
||||
*/
|
||||
uint16_t decode_quoted_printable(uint8_t *p) {
|
||||
uint16_t decode_quoted_printable(uint8_t *p, uint8_t isheader) {
|
||||
uint16_t i = 0, j = 0;
|
||||
uint8_t c;
|
||||
while (c = p[i]) {
|
||||
|
@ -564,7 +564,7 @@ uint16_t decode_quoted_printable(uint8_t *p) {
|
|||
c = 16 * hexdigit(p[i + 1]) + hexdigit(p[i + 2]);
|
||||
p[j++] = c;
|
||||
i += 3;
|
||||
} else if (c == '?')
|
||||
} else if ((c == '?') && isheader)
|
||||
break;
|
||||
else {
|
||||
p[j++] = c;
|
||||
|
@ -589,18 +589,19 @@ void printfield(char *s, uint8_t start, uint8_t end) {
|
|||
#pragma code-name (pop)
|
||||
|
||||
/*
|
||||
* Decode Subject header which may be encoded Quoted-Printable or Base64
|
||||
* Decode Subject or From header which may be encoded
|
||||
* Quoted-Printable or Base64
|
||||
* p - pointer to subject header content
|
||||
* Decoded (and sanitized) text is returned in linebuf[]
|
||||
*/
|
||||
void decode_subject(char *p) {
|
||||
void decode_qp_header(char *p) {
|
||||
uint8_t i = 0, j = 0;
|
||||
if (strncasecmp(p, "=?utf-8?", 8) == 0) {
|
||||
strcpy(linebuf, p + 10); // Skip '=?UTF-8?x?'
|
||||
if (p[8] == 'B')
|
||||
decode_base64(linebuf);
|
||||
else
|
||||
decode_quoted_printable(linebuf);
|
||||
decode_quoted_printable(linebuf, 1);
|
||||
while (linebuf[i]) {
|
||||
if ((linebuf[i] <= 127) && (linebuf[i] >= 32))
|
||||
linebuf[j++] = linebuf[i];
|
||||
|
@ -633,9 +634,10 @@ void print_one_email_summary(struct emailhdrs *h, uint8_t inverse) {
|
|||
putchar('|');
|
||||
printfield(h->date, 0, 16);
|
||||
putchar('|');
|
||||
printfield(h->from, 0, 20);
|
||||
decode_qp_header(h->from);
|
||||
printfield(linebuf, 0, 20);
|
||||
putchar('|');
|
||||
decode_subject(h->subject);
|
||||
decode_qp_header(h->subject);
|
||||
printfield(linebuf, 0, 39);
|
||||
putchar(NORMAL);
|
||||
}
|
||||
|
@ -923,6 +925,21 @@ void sanitize_filename(char *s) {
|
|||
|
||||
enum aux_ops {FROMAUX, TOAUX};
|
||||
|
||||
/*
|
||||
* Asm code for copyaux()
|
||||
*/
|
||||
#pragma optimize (push, off)
|
||||
void copyauxasm(enum aux_ops dir) {
|
||||
if (dir == TOAUX)
|
||||
__asm__("sec"); // Copy main->aux
|
||||
else
|
||||
__asm__("clc"); // Copy aux->main
|
||||
__asm__("sta $c000"); // Turn off 80STORE
|
||||
__asm__("jsr $c311"); // AUXMOVE
|
||||
__asm__("sta $c001"); // Turn on 80STORE
|
||||
}
|
||||
#pragma optimize (pop)
|
||||
|
||||
/*
|
||||
* Aux memory copy routine
|
||||
*/
|
||||
|
@ -933,72 +950,58 @@ void copyaux(char *src, char *dst, uint16_t len, enum aux_ops dir) {
|
|||
*a1 = src;
|
||||
*a2 = src + len - 1; // AUXMOVE moves length+1 bytes!!
|
||||
*a4 = dst;
|
||||
if (dir == TOAUX)
|
||||
__asm__("sec"); // Copy main->aux
|
||||
else
|
||||
__asm__("clc"); // Copy aux->main
|
||||
__asm__("sta $c000"); // Turn off 80STORE
|
||||
__asm__("jsr $c311"); // AUXMOVE
|
||||
__asm__("sta $c001"); // Turn on 80STORE
|
||||
copyauxasm(dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the current screen to the scrollback file
|
||||
* We preserve linebuf[] by copying it to aux 0x0800, and recover
|
||||
* it at the end. This saves us having an additional 1KB buffer.
|
||||
*/
|
||||
void save_screen_to_scrollback(FILE *fp) {
|
||||
copyaux(linebuf, (void*)0x800, 1024, TOAUX); // Preserve linebuf[]
|
||||
if (fwrite((void*)0x0400, 0x0400, 1, fp) != 1) { // Even cols
|
||||
error(ERR_NONFATAL, sb_err);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
copyaux((void*)0x400, halfscreen, 0x400, FROMAUX);
|
||||
if (fwrite(halfscreen, 0x0400, 1, fp) != 1) { // Odd cols
|
||||
copyaux((void*)0x400, linebuf, 0x400, FROMAUX);
|
||||
if (fwrite(linebuf, 0x0400, 1, fp) != 1) { // Odd cols
|
||||
error(ERR_NONFATAL, sb_err);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
copyaux((void*)0x800, linebuf, 1024, FROMAUX); // Recover linebuf[]
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a screen from the scrollback file
|
||||
* Screens are numbered 1, 2, 3 ...
|
||||
* Does not trash the screen holes, which must be preserved!
|
||||
* We preserve linebuf[] by copying it to aux 0x0800, and recover
|
||||
* it at the end. This saves us having an additional 1KB buffer.
|
||||
*/
|
||||
void load_screen_from_scrollback(FILE *fp, uint8_t screen) {
|
||||
uint8_t i;
|
||||
copyaux(linebuf, (void*)0x800, 1024, TOAUX); // Preserve linebuf[]
|
||||
if (fseek(fp, (screen - 1) * 0x0800, SEEK_SET) ||
|
||||
(fread(halfscreen, 0x0400, 1, fp) != 1)) { // Even cols
|
||||
(fread(linebuf, 0x0400, 1, fp) != 1)) { // Even cols
|
||||
error(ERR_NONFATAL, sb_err);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; i < 8; ++i)
|
||||
memcpy((char*)0x400 + i * 0x80, halfscreen + i * 0x80, 0x078);
|
||||
if (fread(halfscreen, 0x0400, 1, fp) != 1) { // Odd cols
|
||||
memcpy((char*)0x400 + i * 0x80, linebuf + i * 0x80, 0x078);
|
||||
if (fread(linebuf, 0x0400, 1, fp) != 1) { // Odd cols
|
||||
error(ERR_NONFATAL, sb_err);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; i < 8; ++i)
|
||||
copyaux(halfscreen + i * 0x80, (char*)0x400 + i * 0x80, 0x078, TOAUX);
|
||||
copyaux(linebuf + i * 0x80, (char*)0x400 + i * 0x80, 0x078, TOAUX);
|
||||
if (fseek(fp, 0, SEEK_END)) {
|
||||
error(ERR_NONFATAL, sb_err);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if text at p is a MIME boundary.
|
||||
* p is assumed to point to start of line.
|
||||
* Valid MIME boundaries start with "--", then have a char sequence
|
||||
* with no spaces, then CR
|
||||
*/
|
||||
uint8_t is_mime_boundary(char *p) {
|
||||
if (strncmp(p, "--", 2)) // Must start with "--"
|
||||
return 0;
|
||||
p += 2;
|
||||
do {
|
||||
if (*p == ' ') // Can not contain ' '
|
||||
return 0;
|
||||
++p;
|
||||
} while (*p && (*p != '\r'));
|
||||
return 1;
|
||||
done:
|
||||
copyaux((void*)0x800, linebuf, 1024, FROMAUX); // Recover linebuf[]
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1023,6 +1026,65 @@ enum mime_enc mime_encoding(char *s) {
|
|||
return ENC_SKIP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Support three levels of nesting
|
||||
*/
|
||||
static char mime_boundaries[3][71];
|
||||
static uint8_t mime_idx;
|
||||
|
||||
/*
|
||||
* linebuf[] is expected to contain the Content-Type: header
|
||||
* Parse it and obtain the MIME boundary, write it to buf[]
|
||||
* Returns 1 if boundary was found or if there is no room for more
|
||||
* boundaries to be stored, 0 if boundary was not found.
|
||||
*
|
||||
* Three levels of nesting are supported, to avoid mime_boundaries[]
|
||||
* chewing up too much memory.
|
||||
*/
|
||||
uint8_t mime_get_boundary(void) {
|
||||
char *p, *q;
|
||||
if (mime_idx > 2)
|
||||
return 1; // No point in trying if nested too deep
|
||||
p = strstr(linebuf, "boundary=");
|
||||
if (p) {
|
||||
q = strstr(p + 9, "\r"); // Terminated by EOL ..
|
||||
if (!q)
|
||||
q = strstr(p + 9, ";"); // .. or by semicolon
|
||||
if (q) {
|
||||
if (*(p + 9) == '\"') {
|
||||
// Trim quotes, if present
|
||||
strncpy(mime_boundaries[mime_idx], p + 10, q - p - 10);
|
||||
mime_boundaries[mime_idx][q - p - 11] = '\0';
|
||||
} else {
|
||||
strncpy(mime_boundaries[mime_idx], p + 9, q - p - 9);
|
||||
mime_boundaries[mime_idx][q - p - 9] = '\0';
|
||||
}
|
||||
//printf("Boundary: %s\n", mime_boundaries[mime_idx]);
|
||||
++mime_idx;
|
||||
}
|
||||
return 1; // Got boundary
|
||||
}
|
||||
return 0; // Did not get boundary
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if text at p is a MIME boundary.
|
||||
* Uses the MIME boundaries stored in mime_boundaries[]
|
||||
* p is assumed to point to start of line.
|
||||
*/
|
||||
uint8_t is_mime_boundary(char *p) {
|
||||
uint8_t i;
|
||||
if (strncmp(p, "--", 2)) // Must start with "--"
|
||||
return 0;
|
||||
p += 2;
|
||||
for (i = 0; i < mime_idx; ++i) {
|
||||
// Match boundary followed by '\r' or "--" (or anything else, actually)
|
||||
if (strncmp(mime_boundaries[i], p, strlen(mime_boundaries[i])) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display email with simple pager functionality
|
||||
* Includes support for decoding MIME headers
|
||||
|
@ -1057,6 +1119,7 @@ void email_pager(struct emailhdrs *h) {
|
|||
pos = hh.skipbytes;
|
||||
fseek(fp, pos, SEEK_SET); // Skip over headers
|
||||
mime_enc = ENC_7BIT;
|
||||
mime_idx = 0;
|
||||
restart:
|
||||
eof = 0;
|
||||
linecount = 0;
|
||||
|
@ -1081,7 +1144,8 @@ restart:
|
|||
fputs("Date: ", stdout);
|
||||
printfield(hh.date, 0, 39);
|
||||
fputs("\nFrom: ", stdout);
|
||||
printfield(hh.from, 0, 70);
|
||||
decode_qp_header(hh.from);
|
||||
printfield(linebuf, 0, 70);
|
||||
if (strncmp(hh.to, "News:", 5) == 0) {
|
||||
fputs("\nNewsgrp: ", stdout);
|
||||
printfield(&(hh.to[5]), 0, 70);
|
||||
|
@ -1098,7 +1162,7 @@ restart:
|
|||
}
|
||||
}
|
||||
fputs("\nSubject: ", stdout);
|
||||
decode_subject(hh.subject);
|
||||
decode_qp_header(hh.subject);
|
||||
printfield(linebuf, 0, 70);
|
||||
fputs("\n\n", stdout);
|
||||
get_line(fp, 1, linebuf, LINEBUFSZ, &pos); // Reset buffer
|
||||
|
@ -1133,8 +1197,8 @@ restart:
|
|||
printf("\n<Not showing HTML>\n");
|
||||
mime = 1;
|
||||
} else {
|
||||
mime = 2 + mime_get_boundary(); // 3 if boundary, 2 otherwise
|
||||
mime_binary = 1;
|
||||
mime = 3;
|
||||
}
|
||||
} else if (!strncasecmp(writep, cte, 27)) {
|
||||
mime = 3;
|
||||
|
@ -1172,12 +1236,14 @@ prompt_dl:
|
|||
mime_enc = ENC_SKIP; // Skip over binary MIME parts with no filename
|
||||
printf("\n");
|
||||
}
|
||||
} else if (mime == 2) {
|
||||
mime = 2 + mime_get_boundary(); // 3 if boundary, 2 otherwise
|
||||
}
|
||||
readp = writep = NULL;
|
||||
} else if (mime == 4) {
|
||||
switch (mime_enc) {
|
||||
case ENC_QP:
|
||||
chars = decode_quoted_printable(writep);
|
||||
chars = decode_quoted_printable(writep, 0);
|
||||
break;
|
||||
case ENC_B64:
|
||||
chars = decode_base64(writep);
|
||||
|
@ -1269,8 +1335,10 @@ retry:
|
|||
get_line(fp, 1, linebuf, LINEBUFSZ, &pos); // Reset buffer
|
||||
do {
|
||||
get_line(fp, 0, linebuf, LINEBUFSZ, &pos);
|
||||
if (!strncasecmp(linebuf, ct, 14))
|
||||
mime = 4;
|
||||
if (!strncasecmp(linebuf, ct, 14)) {
|
||||
mime = 3 + mime_get_boundary(); // 4 if boundary, 3 otherwise
|
||||
continue;
|
||||
}
|
||||
if (!strncasecmp(linebuf, cte, 27)) {
|
||||
mime = 4;
|
||||
mime_enc = mime_encoding(linebuf);
|
||||
|
@ -1278,6 +1346,11 @@ retry:
|
|||
mime = 0;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (mime == 3) { // We have Content-Type but no boundary yet
|
||||
mime_get_boundary();
|
||||
mime = 4;
|
||||
}
|
||||
} while (linebuf[0] != '\r');
|
||||
pos = hh.skipbytes;
|
||||
|
@ -1575,7 +1648,7 @@ esc_pressed:
|
|||
* Adds 'Re: ' to subject line unless it is already there
|
||||
*/
|
||||
void prefix_subject(FILE *f, char *subject, char *prefix) {
|
||||
decode_subject(subject);
|
||||
decode_qp_header(subject);
|
||||
fprintf(f, "Subject: %s%s\r",
|
||||
(strncmp(subject, prefix, strlen(prefix)) ? prefix : ""), linebuf);
|
||||
}
|
||||
|
@ -1613,16 +1686,18 @@ uint8_t write_email_headers(FILE *fp1, FILE *fp2, struct emailhdrs *h,
|
|||
if (mode == 'R') {
|
||||
truncate_header(h->date, buf, 40);
|
||||
fprintf(fp2, "On %s, ", buf);
|
||||
truncate_header(h->from, buf, 80);
|
||||
decode_qp_header(h->from);
|
||||
truncate_header(linebuf, buf, 80);
|
||||
fprintf(fp2, "%s wrote:\r\r", buf);
|
||||
} else {
|
||||
fprintf(fp2, "-------- Forwarded Message --------\r");
|
||||
decode_subject(h->subject);
|
||||
decode_qp_header(h->subject);
|
||||
truncate_header(linebuf, buf, 80);
|
||||
fprintf(fp2, "Subject: %s\r", buf);
|
||||
truncate_header(h->date, buf, 40);
|
||||
fprintf(fp2, "Date: %s\r", buf);
|
||||
truncate_header(h->from, buf, 80);
|
||||
decode_qp_header(h->from);
|
||||
truncate_header(linebuf, buf, 80);
|
||||
fprintf(fp2, "From: %s\r", buf);
|
||||
truncate_header(h->to, buf, 80);
|
||||
fprintf(fp2, "To: %s\r\r", buf);
|
||||
|
@ -1721,19 +1796,22 @@ char prompt_okay(char *msg) {
|
|||
*/
|
||||
void get_email_body(struct emailhdrs *h, FILE *f, char mode) {
|
||||
uint16_t chars;
|
||||
char c, *readp, *writep;
|
||||
uint8_t c, *readp, *writep;
|
||||
uint32_t pos = 0;
|
||||
const int8_t *b = b64dec - 43;
|
||||
uint8_t mime = 0, mime_enc = ENC_7BIT, mime_binary = 0;
|
||||
uint8_t mime = 0, mime_enc = ENC_7BIT, mime_binary, mime_hasfile;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
get_line(fp, 1, linebuf, LINEBUFSZ, &pos); // Reset buffer
|
||||
mime_idx = 0;
|
||||
do {
|
||||
spinner();
|
||||
get_line(fp, 0, linebuf, LINEBUFSZ, &pos);
|
||||
if (!strncasecmp(linebuf, mime_ver, 17))
|
||||
mime = 1;
|
||||
if (!strncasecmp(linebuf, ct, 14))
|
||||
mime = 4;
|
||||
if (!strncasecmp(linebuf, ct, 14)) {
|
||||
mime = 3 + mime_get_boundary(); // 4 if boundary, 3 otherwise
|
||||
continue;
|
||||
}
|
||||
if (!strncasecmp(linebuf, cte, 27)) {
|
||||
mime = 4;
|
||||
mime_enc = mime_encoding(linebuf);
|
||||
|
@ -1741,6 +1819,11 @@ void get_email_body(struct emailhdrs *h, FILE *f, char mode) {
|
|||
error(ERR_NONFATAL, unsupp_enc, linebuf + 27);
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (mime == 3) { // We have Content-Type but no boundary yet
|
||||
mime_get_boundary();
|
||||
mime = 4;
|
||||
}
|
||||
} while (linebuf[0] != '\r');
|
||||
pos = h->skipbytes;
|
||||
|
@ -1748,8 +1831,10 @@ void get_email_body(struct emailhdrs *h, FILE *f, char mode) {
|
|||
readp = linebuf;
|
||||
writep = linebuf;
|
||||
mime_binary = 0;
|
||||
mime_hasfile = 0;
|
||||
get_line(fp, 1, linebuf, LINEBUFSZ, &pos); // Reset buffer
|
||||
while (1) {
|
||||
spinner();
|
||||
if (!readp)
|
||||
readp = linebuf;
|
||||
if (!writep)
|
||||
|
@ -1757,22 +1842,20 @@ void get_email_body(struct emailhdrs *h, FILE *f, char mode) {
|
|||
if (get_line(fp, 0, writep, (LINEBUFSZ - (writep - linebuf)), &pos) == 0)
|
||||
break;
|
||||
if ((mime >= 1) && is_mime_boundary(writep)) {
|
||||
if ((mime == 4) && !mime_binary) // End of Text/Plain MIME section
|
||||
break;
|
||||
mime = 2;
|
||||
mime_enc = ENC_7BIT;
|
||||
mime_binary = 0;
|
||||
mime_hasfile = 0;
|
||||
readp = writep = NULL;
|
||||
} else if ((mime < 4) && (mime >= 2)) {
|
||||
if (!strncasecmp(writep, ct, 14)) {
|
||||
if (!strncmp(writep + 14, "text/plain", 10)) {
|
||||
mime = 3;
|
||||
} else if (!strncmp(writep + 14, "text/html", 9)) {
|
||||
printf("\n<Not showing HTML>\n");
|
||||
mime = 1;
|
||||
} else {
|
||||
mime = 2 + mime_get_boundary(); // 3 if boundary, 2 otherwise
|
||||
mime_binary = 1;
|
||||
mime = 3;
|
||||
}
|
||||
} else if (!strncasecmp(writep, cte, 27)) {
|
||||
mime = 3;
|
||||
|
@ -1781,16 +1864,20 @@ void get_email_body(struct emailhdrs *h, FILE *f, char mode) {
|
|||
printf(unsupp_enc, writep + 27);
|
||||
mime = 1;
|
||||
}
|
||||
} else if (strstr(writep, "filename=")) {
|
||||
mime_hasfile = 1;
|
||||
} else if ((mime == 3) && (!strncmp(writep, "\r", 1))) {
|
||||
mime = 4;
|
||||
if (mime_binary)
|
||||
mime_enc = ENC_SKIP; // Skip over binary MIME parts
|
||||
} else if (mime == 2) {
|
||||
mime = 2 + mime_get_boundary(); // 3 if boundary, 2 otherwise
|
||||
}
|
||||
readp = writep = NULL;
|
||||
} else if (mime == 4) {
|
||||
switch (mime_enc) {
|
||||
case ENC_QP:
|
||||
chars = decode_quoted_printable(writep);
|
||||
chars = decode_quoted_printable(writep, 0);
|
||||
break;
|
||||
case ENC_B64:
|
||||
chars = decode_base64(writep);
|
||||
|
@ -1801,7 +1888,7 @@ void get_email_body(struct emailhdrs *h, FILE *f, char mode) {
|
|||
}
|
||||
}
|
||||
if (readp) {
|
||||
if ((mime == 0) || ((mime == 4) && !mime_binary)) {
|
||||
if ((mime == 0) || ((mime == 4) && !mime_hasfile)) {
|
||||
do {
|
||||
c = word_wrap_line(f, &readp, 78, mode);
|
||||
} while (c == 1);
|
||||
|
@ -1976,7 +2063,7 @@ uint16_t get_db_index(void) {
|
|||
* on the current message. If they are, prompt the user and, if affirmative,
|
||||
* iterate through the tagged messages calling copy_to_mailbox() on each.
|
||||
*/
|
||||
uint8_t copy_to_mailbox_tagged(char *mbox, uint8_t delete) {
|
||||
uint8_t copy_to_mailbox_tagged(char *mbox, char mode, uint8_t delete) {
|
||||
uint16_t count = 0, tagcount = 0;
|
||||
struct emailhdrs *h;
|
||||
uint16_t l;
|
||||
|
@ -1985,7 +2072,8 @@ uint8_t copy_to_mailbox_tagged(char *mbox, uint8_t delete) {
|
|||
copy_to_mailbox(h, get_db_index(), mbox, delete, ' ');
|
||||
return 0;
|
||||
}
|
||||
snprintf(filename, 80, "%u tagged - ", total_tag);
|
||||
snprintf(filename, 80, "%s %u tagged - ",
|
||||
(mode == 'C' ? "Copy" : (mode == 'M' ? "Move" : "Archive")), total_tag);
|
||||
if (!prompt_okay(filename))
|
||||
return 0;
|
||||
h = (struct emailhdrs*)malloc(sizeof(struct emailhdrs));
|
||||
|
@ -2265,7 +2353,7 @@ void keyboard_hdlr(void) {
|
|||
if (h) {
|
||||
c = prompt_for_name("Copy to mbox", 1);
|
||||
if ((c != 0) && (c != 255))
|
||||
copy_to_mailbox_tagged(userentry, 0);
|
||||
copy_to_mailbox_tagged(userentry, 'C', 0);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
|
@ -2273,14 +2361,14 @@ void keyboard_hdlr(void) {
|
|||
if (h) {
|
||||
c = prompt_for_name("Move to mbox", 1);
|
||||
if ((c != 0) && (c != 255))
|
||||
copy_to_mailbox_tagged(userentry, 1);
|
||||
copy_to_mailbox_tagged(userentry, 'M', 1);
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
if (h) {
|
||||
goto_prompt_row();
|
||||
copy_to_mailbox_tagged("RECEIVED", 1);
|
||||
copy_to_mailbox_tagged("RECEIVED", 'A', 1);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
|
@ -2353,6 +2441,7 @@ void keyboard_hdlr(void) {
|
|||
load_app(APP_SMTP);
|
||||
break;
|
||||
case 0x80 + '?': // OA-? "Help"
|
||||
case 0x80 + '/': // OA-/ "Help"
|
||||
help(1);
|
||||
c = cgetc();
|
||||
email_summary();
|
||||
|
|
|
@ -4,7 +4,7 @@ passwordgoeshere
|
|||
NODELETE
|
||||
192.168.10.2:25
|
||||
apple2.local
|
||||
/IP65
|
||||
/DATA/EMAIL
|
||||
/H1/IP65
|
||||
/H1/DOCUMENTS/EMAIL
|
||||
bobbi.8bit@gmail.com
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/////////////////////////////////////////////////////////////////
|
||||
// EMAIL_COMMON.H
|
||||
// Definitions shared between pop65.c and email.c
|
||||
// Bobbi June 2020
|
||||
// Bobbi August 2021
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PROGNAME "emai//er v2.1.6"
|
||||
#define PROGNAME "emai//er v2.1.14"
|
||||
|
||||
// Configuration params from EMAIL.CFG
|
||||
char cfg_server[40]; // IP of POP3 server
|
||||
|
|
|
@ -42,7 +42,7 @@ void send(unsigned char flags, const char* str, ...)
|
|||
}
|
||||
|
||||
va_start(args, str);
|
||||
send_size += vsnprintf(send_buffer + send_size, sizeof(send_buffer) - send_size, str, args);
|
||||
send_size += vsnprintf((char*)send_buffer + send_size, sizeof(send_buffer) - send_size, str, args);
|
||||
va_end(args);
|
||||
|
||||
if (flags & SEND_LAST || sizeof(send_buffer) - send_size < 1024 / 4)
|
||||
|
@ -309,9 +309,9 @@ int main(void)
|
|||
{
|
||||
read(file, ð_init, 1);
|
||||
close(file);
|
||||
eth_init &= ~'0';
|
||||
eth_init &= 7;
|
||||
}
|
||||
printf("- %d", eth_init);
|
||||
printf("- %u", eth_init);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ int ifttt_trigger(const char* key, const char* event,
|
|||
return -1;
|
||||
}
|
||||
|
||||
len = url_download(url, download, sizeof(download));
|
||||
len = url_download(url, (uint8_t*)download, sizeof(download));
|
||||
|
||||
if (len < 12)
|
||||
{
|
||||
|
|
|
@ -78,15 +78,15 @@ struct linenoiseState {
|
|||
int history_index; /* The history index we are currently editing. */
|
||||
};
|
||||
|
||||
enum KEY_ACTION{
|
||||
CTRL_A = 1, /* Ctrl+a */
|
||||
CTRL_B = 2, /* Ctrl-b */
|
||||
CTRL_C = 3, /* Ctrl-c */
|
||||
CTRL_D = 4, /* Ctrl-d */
|
||||
CTRL_E = 5, /* Ctrl-e */
|
||||
CTRL_F = 6, /* Ctrl-f */
|
||||
CTRL_N = 14, /* Ctrl-n */
|
||||
CTRL_P = 16 /* Ctrl-p */
|
||||
enum KEY_ACTION {
|
||||
CTRL_A = 1, /* Ctrl+a */
|
||||
CTRL_B = 2, /* Ctrl-b */
|
||||
CTRL_C = 3, /* Ctrl-c */
|
||||
CTRL_D = 4, /* Ctrl-d */
|
||||
CTRL_E = 5, /* Ctrl-e */
|
||||
CTRL_F = 6, /* Ctrl-f */
|
||||
CTRL_N = 14, /* Ctrl-n */
|
||||
CTRL_P = 16 /* Ctrl-p */
|
||||
};
|
||||
|
||||
static void refreshLine(struct linenoiseState *l);
|
||||
|
@ -102,14 +102,16 @@ static int getColumns() {
|
|||
return cols;
|
||||
}
|
||||
|
||||
#ifdef __APPLE2__
|
||||
#pragma code-name (push, "LC")
|
||||
#endif
|
||||
|
||||
/* Beep, used for completion when there is nothing to complete or when all
|
||||
* the choices were already shown. */
|
||||
static void linenoiseBeep(void) {
|
||||
#ifdef __APPLE2__
|
||||
unsigned char x = wherex();
|
||||
#endif
|
||||
putchar('\a');
|
||||
#ifdef __APPLE2__
|
||||
gotox(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ============================== Completion ================================ */
|
||||
|
@ -123,6 +125,10 @@ static void freeCompletions(linenoiseCompletions *lc) {
|
|||
free(lc->cvec);
|
||||
}
|
||||
|
||||
#ifdef __APPLE2__
|
||||
#pragma code-name (push, "LC")
|
||||
#endif
|
||||
|
||||
/* This is an helper function for linenoiseEdit() and is called when the
|
||||
* user types the <tab> key in order to complete the string currently in the
|
||||
* input.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
144.76.35.198:119
|
||||
usergoeshere
|
||||
passwordgoeshere
|
||||
/IP65
|
||||
/DATA/EMAIL
|
||||
/H1/IP65
|
||||
/H1/DOCUMENTS/EMAIL
|
||||
bobbi.8bit@gmail.com
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#define BELL 7
|
||||
#define BACKSPACE 8
|
||||
|
||||
#define LOGFILE "NNTP65.LOG"
|
||||
|
||||
// Both pragmas are obligatory to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment registers.
|
||||
#pragma optimize (on)
|
||||
|
@ -327,7 +329,7 @@ void readconfigfile(void) {
|
|||
|
||||
colon = strchr(cfg_server, ':');
|
||||
if (!colon)
|
||||
nntp_port = 110;
|
||||
nntp_port = 119;
|
||||
else {
|
||||
nntp_port = atoi(colon + 1);
|
||||
*colon = '\0';
|
||||
|
@ -559,7 +561,8 @@ void update_mailbox(char *mbox) {
|
|||
update_email_db(mbox, &hdrs);
|
||||
puts("");
|
||||
|
||||
sprintf(filename, "%s/NEWS.SPOOL/NEWS.%u", cfg_emaildir, msg);
|
||||
//sprintf(filename, "%s/NEWS.SPOOL/NEWS.%u", cfg_emaildir, msg);
|
||||
sprintf(filename, "%s/NEWS.SPOOL/%s", cfg_emaildir, d->d_name);
|
||||
if (unlink(filename))
|
||||
printf("Can't delete %s\n", filename);
|
||||
}
|
||||
|
@ -568,7 +571,9 @@ void update_mailbox(char *mbox) {
|
|||
|
||||
void main(int argc, char *argv[]) {
|
||||
uint32_t nummsgs, lownum, highnum, msgnum, msg;
|
||||
uint16_t msgcount, i;
|
||||
char sendbuf[80];
|
||||
FILE *logfp;
|
||||
uint8_t eth_init = ETH_INIT_DEFAULT;
|
||||
|
||||
if ((argc == 2) && (strcmp(argv[1], "EMAIL") == 0))
|
||||
|
@ -632,11 +637,12 @@ void main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
// Copy IP config from IP65 to W5100
|
||||
w5100_config(eth_init);
|
||||
w5100_init(eth_init);
|
||||
w5100_config();
|
||||
|
||||
printf("Ok\nConnecting to %s (%u) - ", cfg_server, nntp_port);
|
||||
|
||||
if (!w5100_connect(parse_dotted_quad(cfg_server), nntp_port)) {
|
||||
if (!w5100_connect_addr(parse_dotted_quad(cfg_server), nntp_port)) {
|
||||
printf("Fail\n");
|
||||
error_exit();
|
||||
}
|
||||
|
@ -649,19 +655,28 @@ void main(int argc, char *argv[]) {
|
|||
if (expect(buf, "20")) // "200" if posting is allowed / "201" if no posting
|
||||
error_exit();
|
||||
|
||||
sprintf(sendbuf, "AUTHINFO USER %s\r\n", cfg_user);
|
||||
if (!w5100_tcp_send_recv(sendbuf, buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
}
|
||||
if (expect(buf, "381")) // Username accepted
|
||||
error_exit();
|
||||
// Skip authentication?
|
||||
if (strcmp(cfg_user, "-") != 0) {
|
||||
sprintf(sendbuf, "AUTHINFO USER %s\r\n", cfg_user);
|
||||
if (!w5100_tcp_send_recv(sendbuf, buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
}
|
||||
if (expect(buf, "381")) // Username accepted
|
||||
error_exit();
|
||||
|
||||
sprintf(sendbuf, "AUTHINFO PASS %s\r\n", cfg_pass);
|
||||
if (!w5100_tcp_send_recv(sendbuf, buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
sprintf(sendbuf, "AUTHINFO PASS %s\r\n", cfg_pass);
|
||||
if (!w5100_tcp_send_recv(sendbuf, buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
}
|
||||
if (expect(buf, "281")) // Authentication successful
|
||||
error_exit();
|
||||
}
|
||||
if (expect(buf, "281")) // Authentication successful
|
||||
error_exit();
|
||||
|
||||
// Make empty log file
|
||||
_filetype = PRODOS_T_TXT;
|
||||
_auxtype = 0;
|
||||
logfp = fopen(LOGFILE, "w");
|
||||
fclose(logfp);
|
||||
|
||||
while (1) {
|
||||
msg = fscanf(newsgroupsfp, "%s %s %ld", newsgroup, mailbox, &msgnum);
|
||||
|
@ -703,6 +718,7 @@ void main(int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
|
||||
msgcount = 0;
|
||||
while (1) {
|
||||
if (!w5100_tcp_send_recv("NEXT\r\n", buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
|
@ -724,11 +740,23 @@ void main(int argc, char *argv[]) {
|
|||
}
|
||||
spinner(filesize, 1); // Cleanup spinner
|
||||
fclose(fp);
|
||||
++msgcount;
|
||||
}
|
||||
printf("Updating NEWSGROUPS.NEW (%s:%ld) ...\n", newsgroup, msg);
|
||||
fprintf(newnewsgroupsfp, "%s %s %ld\n", newsgroup, mailbox, msg);
|
||||
printf("Updating mailbox %s ...\n", mailbox);
|
||||
update_mailbox(mailbox);
|
||||
|
||||
_filetype = PRODOS_T_TXT;
|
||||
_auxtype = 0;
|
||||
logfp = fopen(LOGFILE, "a");
|
||||
if (logfp) {
|
||||
fprintf(logfp, " %s", newsgroup);
|
||||
for (i = 0; i < (30 - strlen(newsgroup)); ++i)
|
||||
fputc(' ', logfp);
|
||||
fprintf(logfp, "%5u messages retrieved to mailbox %s\n", msgcount, mailbox);
|
||||
fclose(logfp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(newsgroupsfp);
|
||||
|
@ -752,5 +780,17 @@ void main(int argc, char *argv[]) {
|
|||
printf("Disconnecting\n");
|
||||
w5100_disconnect();
|
||||
|
||||
logfp = fopen(LOGFILE, "r");
|
||||
if (logfp) {
|
||||
puts("\nNNTP65 Session Summary:\n");
|
||||
i = fgetc(logfp);
|
||||
while (!feof(logfp)) {
|
||||
putchar(i);
|
||||
i = fgetc(logfp);
|
||||
}
|
||||
fclose(logfp);
|
||||
puts("");
|
||||
}
|
||||
|
||||
confirm_exit();
|
||||
}
|
||||
|
|
|
@ -369,7 +369,7 @@ void readconfigfile(void) {
|
|||
|
||||
colon = strchr(cfg_server, ':');
|
||||
if (!colon)
|
||||
nntp_port = 110;
|
||||
nntp_port = 119;
|
||||
else
|
||||
nntp_port = atoi(colon + 1);
|
||||
}
|
||||
|
@ -548,7 +548,8 @@ void main(int argc, char *argv[]) {
|
|||
printf("Ok\n");
|
||||
|
||||
// Copy IP config from IP65 to W5100
|
||||
w5100_config(eth_init);
|
||||
w5100_init(eth_init);
|
||||
w5100_config();
|
||||
|
||||
sprintf(filename, "%s/NEWS.OUTBOX", cfg_emaildir);
|
||||
dp = opendir(filename);
|
||||
|
@ -577,7 +578,7 @@ void main(int argc, char *argv[]) {
|
|||
linecount = 0;
|
||||
|
||||
while (1) {
|
||||
if ((get_line(fp, 0, linebuf, LINEBUFSZ) == 0) || (linecount == 20))
|
||||
if ((get_line(fp, 0, linebuf, LINEBUFSZ) == 0) || (linecount == 20) || (linebuf[0] == '\r'))
|
||||
break;
|
||||
++linecount;
|
||||
if (!strncmp(linebuf, "Newsgroups: ", 12))
|
||||
|
@ -632,7 +633,7 @@ sendmessage:
|
|||
if (!connected) {
|
||||
printf("\nConnecting to %s (%u) - ", cfg_server, nntp_port);
|
||||
|
||||
if (!w5100_connect(parse_dotted_quad(cfg_server), nntp_port)) {
|
||||
if (!w5100_connect_addr(parse_dotted_quad(cfg_server), nntp_port)) {
|
||||
printf("Fail\n");
|
||||
error_exit();
|
||||
}
|
||||
|
@ -645,19 +646,22 @@ sendmessage:
|
|||
if (expect(buf, "200 ")) // "200" if posting is allowed
|
||||
error_exit();
|
||||
|
||||
sprintf(sendbuf, "AUTHINFO USER %s\r\n", cfg_user);
|
||||
if (!w5100_tcp_send_recv(sendbuf, buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
}
|
||||
if (expect(buf, "381")) // Username accepted
|
||||
error_exit();
|
||||
// Skip authentication?
|
||||
if (strcmp(cfg_user, "-") != 0) {
|
||||
sprintf(sendbuf, "AUTHINFO USER %s\r\n", cfg_user);
|
||||
if (!w5100_tcp_send_recv(sendbuf, buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
}
|
||||
if (expect(buf, "381")) // Username accepted
|
||||
error_exit();
|
||||
|
||||
sprintf(sendbuf, "AUTHINFO PASS %s\r\n", cfg_pass);
|
||||
if (!w5100_tcp_send_recv(sendbuf, buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
sprintf(sendbuf, "AUTHINFO PASS %s\r\n", cfg_pass);
|
||||
if (!w5100_tcp_send_recv(sendbuf, buf, NETBUFSZ, DO_SEND, CMD_MODE)) {
|
||||
error_exit();
|
||||
}
|
||||
if (expect(buf, "281")) // Authentication successful
|
||||
error_exit();
|
||||
}
|
||||
if (expect(buf, "281")) // Authentication successful
|
||||
error_exit();
|
||||
|
||||
connected = 1;
|
||||
}
|
||||
|
|
|
@ -534,17 +534,19 @@ void main(int argc, char *argv[]) {
|
|||
// Abort on Ctrl-C to be consistent with Linenoise
|
||||
abort_key = 0x83;
|
||||
|
||||
w5100_init(eth_init);
|
||||
|
||||
printf("Ok\nObtaining IP address - ");
|
||||
if (dhcp_init()) {
|
||||
ip65_error_exit();
|
||||
}
|
||||
|
||||
// Copy IP config from IP65 to W5100
|
||||
w5100_config(eth_init);
|
||||
w5100_config();
|
||||
|
||||
printf("Ok\nConnecting to %s - ", cfg_server);
|
||||
|
||||
if (!w5100_connect(parse_dotted_quad(cfg_server), pop_port)) {
|
||||
if (!w5100_connect_addr(parse_dotted_quad(cfg_server), pop_port)) {
|
||||
printf("Fail\n");
|
||||
error_exit();
|
||||
}
|
||||
|
|
|
@ -280,7 +280,8 @@ void main(int argc, char *argv[]) {
|
|||
printf("Ok\n");
|
||||
|
||||
// Copy IP config from IP65 to W5100
|
||||
w5100_config(eth_init);
|
||||
w5100_init(eth_init);
|
||||
w5100_config();
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
|
@ -291,7 +292,7 @@ void main(int argc, char *argv[]) {
|
|||
if (!connected) {
|
||||
printf("\nConnecting to %s:%d - ", cfg_server, jetdirect_port);
|
||||
|
||||
if (!w5100_connect(parse_dotted_quad(cfg_server), jetdirect_port)) {
|
||||
if (!w5100_connect_addr(parse_dotted_quad(cfg_server), jetdirect_port)) {
|
||||
printf("Fail\n");
|
||||
error_exit();
|
||||
}
|
||||
|
@ -299,6 +300,7 @@ void main(int argc, char *argv[]) {
|
|||
printf("Ok\n\n");
|
||||
|
||||
}
|
||||
printf("Sending to printer ");
|
||||
if (!w5100_tcp_send()) {
|
||||
error_exit();
|
||||
}
|
||||
|
|
|
@ -163,6 +163,9 @@ void repair_mailbox(void) {
|
|||
}
|
||||
fclose(fp);
|
||||
|
||||
maxemailnum = 0;
|
||||
minemailnum = 65535;
|
||||
|
||||
printf("** Scanning directory %s\n", dirname);
|
||||
|
||||
while (d = readdir(dp)) {
|
||||
|
@ -180,6 +183,11 @@ void repair_mailbox(void) {
|
|||
}
|
||||
closedir(dp);
|
||||
|
||||
if (maxemailnum < minemailnum) {
|
||||
printf("** No messages in this directory\n");
|
||||
error_exit();
|
||||
}
|
||||
|
||||
printf("** Will process EMAIL.%u to EMAIL.%u\n", minemailnum, maxemailnum);
|
||||
for (emailnum = minemailnum; emailnum <= maxemailnum; ++emailnum) {
|
||||
sprintf(filename, "%s/EMAIL.%u", dirname, emailnum);
|
||||
|
|
|
@ -547,7 +547,8 @@ void main(int argc, char *argv[]) {
|
|||
printf("Ok\n");
|
||||
|
||||
// Copy IP config from IP65 to W5100
|
||||
w5100_config(eth_init);
|
||||
w5100_init(eth_init);
|
||||
w5100_config();
|
||||
|
||||
sprintf(filename, "%s/OUTBOX", cfg_emaildir);
|
||||
dp = opendir(filename);
|
||||
|
@ -577,7 +578,7 @@ void main(int argc, char *argv[]) {
|
|||
strcpy(recipients, "");
|
||||
|
||||
while (1) {
|
||||
if ((get_line(fp, 0, linebuf, LINEBUFSZ) == 0) || (linecount == 20)) {
|
||||
if ((get_line(fp, 0, linebuf, LINEBUFSZ) == 0) || (linecount == 20) || (linebuf[0] == '\r')) {
|
||||
if (strlen(recipients) == 0) {
|
||||
printf("No recipients (To or Cc) in %s. Skipping msg.\n", d->d_name);
|
||||
goto skiptonext;
|
||||
|
@ -644,7 +645,7 @@ sendmessage:
|
|||
if (!connected) {
|
||||
printf("\nConnecting to %s - ", cfg_smtp_server);
|
||||
|
||||
if (!w5100_connect(parse_dotted_quad(cfg_smtp_server), smtp_port)) {
|
||||
if (!w5100_connect_addr(parse_dotted_quad(cfg_smtp_server), smtp_port)) {
|
||||
printf("Fail\n");
|
||||
error_exit();
|
||||
}
|
||||
|
|
|
@ -152,9 +152,9 @@ int main(void)
|
|||
{
|
||||
read(file, ð_init, 1);
|
||||
close(file);
|
||||
eth_init &= ~'0';
|
||||
eth_init &= 7;
|
||||
}
|
||||
printf("- %d\n", eth_init);
|
||||
printf("- %u\n", eth_init);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
96
apps/w5100.c
96
apps/w5100.c
|
@ -65,12 +65,8 @@ static uint16_t addr_mask [2];
|
|||
|
||||
static void set_addr(uint16_t addr)
|
||||
{
|
||||
// The variables are necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment registers.
|
||||
uint8_t addr_hi = addr >> 8;
|
||||
uint8_t addr_lo = addr;
|
||||
*w5100_addr_hi = addr_hi;
|
||||
*w5100_addr_lo = addr_lo;
|
||||
*w5100_addr_hi = addr >> 8;
|
||||
*w5100_addr_lo = addr;
|
||||
}
|
||||
|
||||
static uint8_t get_byte(uint16_t addr)
|
||||
|
@ -91,54 +87,44 @@ static uint16_t get_word(uint16_t addr)
|
|||
{
|
||||
set_addr(addr);
|
||||
|
||||
{
|
||||
// The variables are necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment registers.
|
||||
uint8_t data_hi = *w5100_data;
|
||||
uint8_t data_lo = *w5100_data;
|
||||
return data_hi << 8 | data_lo;
|
||||
}
|
||||
return *w5100_data << 8 | *w5100_data;
|
||||
}
|
||||
|
||||
static void set_word(uint16_t addr, uint16_t data)
|
||||
{
|
||||
set_addr(addr);
|
||||
|
||||
{
|
||||
// The variables are necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment registers.
|
||||
uint8_t data_hi = data >> 8;
|
||||
uint8_t data_lo = data;
|
||||
*w5100_data = data_hi;
|
||||
*w5100_data = data_lo;
|
||||
}
|
||||
*w5100_data = data >> 8;
|
||||
*w5100_data = data;
|
||||
}
|
||||
|
||||
static void set_quad(uint16_t addr, uint32_t data)
|
||||
{
|
||||
set_addr(addr);
|
||||
|
||||
{
|
||||
// The variables are necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment registers.
|
||||
uint8_t data_1 = data;
|
||||
uint8_t data_2 = data >> 8;
|
||||
uint8_t data_3 = data >> 16;
|
||||
uint8_t data_4 = data >> 24;
|
||||
*w5100_data = data_1;
|
||||
*w5100_data = data_2;
|
||||
*w5100_data = data_3;
|
||||
*w5100_data = data_4;
|
||||
}
|
||||
*w5100_data = data;
|
||||
*w5100_data = data >> 8;
|
||||
*w5100_data = data >> 16;
|
||||
*w5100_data = data >> 24;
|
||||
}
|
||||
|
||||
void w5100_config(uint8_t eth_init)
|
||||
bool w5100_init(uint8_t eth_init)
|
||||
{
|
||||
w5100_mode = (uint8_t*)(eth_init << 4 | 0xC084);
|
||||
w5100_addr_hi = w5100_mode + 1;
|
||||
w5100_addr_lo = w5100_mode + 2;
|
||||
w5100_data = w5100_mode + 3;
|
||||
|
||||
// PPP Link Control Protocol Request Timer Register defaults to 0x28
|
||||
// on a real W5100. However, AppleWin features a virtual W5100 that
|
||||
// supports DNS offloading. On that virtual W5100, the (otherwise
|
||||
// anyhow unused) register defaults to 0x00 as detection mechanism.
|
||||
// https://github.com/a2retrosystems/uthernet2/wiki/Virtual-W5100-with-DNS
|
||||
return get_byte(0x0028) == 0x00;
|
||||
}
|
||||
|
||||
void w5100_config(void)
|
||||
{
|
||||
#ifdef SINGLE_SOCKET
|
||||
|
||||
// IP65 is inhibited so disable the W5100 Ping Block Mode.
|
||||
|
@ -193,14 +179,14 @@ void w5100_config(uint8_t eth_init)
|
|||
}
|
||||
}
|
||||
|
||||
bool w5100_connect(uint32_t addr, uint16_t port)
|
||||
static bool w5100_connect(uint16_t port)
|
||||
{
|
||||
// Socket x Mode Register: TCP
|
||||
set_byte(SOCK_REG(0x00), 0x01);
|
||||
|
||||
// Socket x Source Port Register
|
||||
set_word(SOCK_REG(0x04), ip65_random_word());
|
||||
|
||||
// Socket x Destination Port Register
|
||||
set_word(SOCK_REG(0x10), port);
|
||||
|
||||
// Socket x Command Register: OPEN
|
||||
set_byte(SOCK_REG(0x01), 0x01);
|
||||
|
||||
|
@ -213,12 +199,6 @@ bool w5100_connect(uint32_t addr, uint16_t port)
|
|||
}
|
||||
}
|
||||
|
||||
// Socket x Destination IP Address Register
|
||||
set_quad(SOCK_REG(0x0C), addr);
|
||||
|
||||
// Socket x Destination Port Register
|
||||
set_word(SOCK_REG(0x10), port);
|
||||
|
||||
// Socket x Command Register: CONNECT
|
||||
set_byte(SOCK_REG(0x01), 0x04);
|
||||
|
||||
|
@ -238,6 +218,34 @@ bool w5100_connect(uint32_t addr, uint16_t port)
|
|||
}
|
||||
}
|
||||
|
||||
bool w5100_connect_addr(uint32_t addr, uint16_t port)
|
||||
{
|
||||
// Socket x Mode Register: TCP, Use No Delayed ACK
|
||||
set_byte(SOCK_REG(0x00), 0x21);
|
||||
|
||||
// Socket x Destination IP Address Register
|
||||
set_quad(SOCK_REG(0x0C), addr);
|
||||
|
||||
return w5100_connect(port);
|
||||
}
|
||||
|
||||
bool w5100_connect_name(const char* name, uint8_t length, uint16_t port)
|
||||
{
|
||||
// Socket x Mode Register: TCP, Use No Delayed ACK, Use DNS Offloading
|
||||
set_byte(SOCK_REG(0x00), 0x29);
|
||||
|
||||
// Socket x DNS name length
|
||||
set_byte(SOCK_REG(0x2A), length);
|
||||
|
||||
// Socket x DNS name chars
|
||||
while (length--)
|
||||
{
|
||||
*w5100_data = *name++;
|
||||
}
|
||||
|
||||
return w5100_connect(port);
|
||||
}
|
||||
|
||||
bool w5100_connected(void)
|
||||
{
|
||||
// Socket x Status Register: SOCK_ESTABLISHED ?
|
||||
|
|
16
apps/w5100.h
16
apps/w5100.h
|
@ -46,13 +46,23 @@ void w5100_data_commit(bool do_send, uint16_t size);
|
|||
// to be sent to the server.
|
||||
extern volatile uint8_t* w5100_data;
|
||||
|
||||
// Initialize this module after the IP65 TCP/IP stack has been initialized.
|
||||
// Return true if the (virtual) W5100 supports DNS Offloading.
|
||||
// https://github.com/a2retrosystems/uthernet2/wiki/Virtual-W5100-with-DNS
|
||||
bool w5100_init(uint8_t eth_init);
|
||||
|
||||
// Configure W5100 Ethernet controller with additional information from IP65
|
||||
// after the IP65 TCP/IP stack has been configured.
|
||||
void w5100_config(uint8_t eth_init);
|
||||
void w5100_config(void);
|
||||
|
||||
// Connect to server with IP address <server_addr> on TCP port <server_port>.
|
||||
// Connect to server with IP address <addr> on TCP port <port>.
|
||||
// Return true if the connection is established, return false otherwise.
|
||||
bool w5100_connect(uint32_t addr, uint16_t port);
|
||||
bool w5100_connect_addr(uint32_t addr, uint16_t port);
|
||||
|
||||
// Connect to server with name <name>, <length> on TCP port <port> using
|
||||
// DNS Offloading.
|
||||
// Return true if the connection is established, return false otherwise.
|
||||
bool w5100_connect_name(const char* name, uint8_t length, uint16_t port);
|
||||
|
||||
// Check if still connected to server.
|
||||
// Return true if the connection is established, return false otherwise.
|
||||
|
|
|
@ -39,16 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#pragma optimize (on)
|
||||
#pragma static-locals (on)
|
||||
|
||||
bool w5100_http_open(uint32_t addr, uint16_t port, const char* selector,
|
||||
char* buffer, size_t length)
|
||||
static bool w5100_http_open(const char* selector, char* buffer, size_t length)
|
||||
{
|
||||
printf("Connecting to %s:%d ", dotted_quad(addr), port);
|
||||
|
||||
if (!w5100_connect(addr, port))
|
||||
{
|
||||
printf("- Connect failed\n");
|
||||
return false;
|
||||
}
|
||||
register volatile uint8_t *data = w5100_data;
|
||||
|
||||
printf("- Ok\n\nSending request ");
|
||||
{
|
||||
|
@ -82,15 +75,11 @@ bool w5100_http_open(uint32_t addr, uint16_t port, const char* selector,
|
|||
}
|
||||
|
||||
{
|
||||
// One less to allow for faster pre-increment below
|
||||
const char *dataptr = selector + pos - 1;
|
||||
const char *dataptr = selector + pos;
|
||||
uint16_t i;
|
||||
for (i = 0; i < snd; ++i)
|
||||
{
|
||||
// The variable is necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment register.
|
||||
char data = *++dataptr;
|
||||
*w5100_data = data;
|
||||
*data = *dataptr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,17 +121,13 @@ bool w5100_http_open(uint32_t addr, uint16_t port, const char* selector,
|
|||
}
|
||||
|
||||
{
|
||||
// One less to allow for faster pre-increment below
|
||||
char *dataptr = buffer + len - 1;
|
||||
char *dataptr = buffer + len;
|
||||
uint16_t i;
|
||||
for (i = 0; i < rcv; ++i)
|
||||
{
|
||||
// The variable is necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment register.
|
||||
char data = *w5100_data;
|
||||
*++dataptr = data;
|
||||
*dataptr++ = *data;
|
||||
|
||||
if (!memcmp(dataptr - 3, "\r\n\r\n", 4))
|
||||
if (!memcmp(dataptr - 4, "\r\n\r\n", 4))
|
||||
{
|
||||
rcv = i + 1;
|
||||
body = true;
|
||||
|
@ -183,3 +168,31 @@ bool w5100_http_open(uint32_t addr, uint16_t port, const char* selector,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool w5100_http_open_addr(uint32_t addr, uint16_t port, const char* selector,
|
||||
char* buffer, size_t length)
|
||||
{
|
||||
printf("Connecting to %s:%d ", dotted_quad(addr), port);
|
||||
|
||||
if (!w5100_connect_addr(addr, port))
|
||||
{
|
||||
printf("- Connect failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return w5100_http_open(selector, buffer, length);
|
||||
}
|
||||
|
||||
bool w5100_http_open_name(const char* name, uint8_t name_length, uint16_t port,
|
||||
const char* selector, char* buffer, size_t buffer_length)
|
||||
{
|
||||
printf("Connecting to port %d ", port);
|
||||
|
||||
if (!w5100_connect_name(name, name_length, port))
|
||||
{
|
||||
printf("- Connect failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return w5100_http_open(selector, buffer, buffer_length);
|
||||
}
|
||||
|
|
|
@ -37,12 +37,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Connect to server with IP address <server_addr> on TCP port <server_port>,
|
||||
// then HTTP GET <selector> and consume HTTP response header. Provide feedback
|
||||
// on progress to the user via STDOUT. After returning from w5100_http_open()
|
||||
// the connection is ready to consume the HTTP body.
|
||||
// Connect to server with IP address <addr> on TCP port <port>, then HTTP GET
|
||||
// <selector> and consume HTTP response header. Provide feedback on progress
|
||||
// to the user via STDOUT. After returning from w5100_http_open_addr(), the
|
||||
// connection is ready to consume the HTTP body.
|
||||
// Return true if the connection is established, return false otherwise.
|
||||
bool w5100_http_open(uint32_t addr, uint16_t port, const char* selector,
|
||||
char* buffer, size_t length);
|
||||
bool w5100_http_open_addr(uint32_t addr, uint16_t port, const char* selector,
|
||||
char* buffer, size_t length);
|
||||
|
||||
// Connect to server with name <name>, <name_length> on TCP port <port> using
|
||||
// DNS Offloading, then HTTP GET <selector> and consume HTTP response header.
|
||||
// Provide feedback on progress to the user via STDOUT. After returning from
|
||||
// w5100_http_open_name(), the connection is ready to consume the HTTP body.
|
||||
// Return true if the connection is established, return false otherwise.
|
||||
bool w5100_http_open_name(const char* name, uint8_t name_length, uint16_t port,
|
||||
const char* selector, char* buffer, size_t buffer_length);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -241,6 +241,7 @@ void exit_on_key(void)
|
|||
|
||||
void write_file(const char *name)
|
||||
{
|
||||
register volatile uint8_t *data = w5100_data;
|
||||
uint16_t i;
|
||||
int file;
|
||||
uint16_t rcv;
|
||||
|
@ -277,14 +278,10 @@ void write_file(const char *name)
|
|||
}
|
||||
|
||||
{
|
||||
// One less to allow for faster pre-increment below
|
||||
char *dataptr = buffer + len - 1;
|
||||
char *dataptr = buffer + len;
|
||||
for (i = 0; i < rcv; ++i)
|
||||
{
|
||||
// The variable is necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment register.
|
||||
char data = *w5100_data;
|
||||
*++dataptr = data;
|
||||
*dataptr++ = *data;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,6 +315,7 @@ void write_file(const char *name)
|
|||
|
||||
void write_device(char device)
|
||||
{
|
||||
register volatile uint8_t *data = w5100_data;
|
||||
uint16_t i;
|
||||
dhandle_t dio;
|
||||
uint16_t rcv;
|
||||
|
@ -383,8 +381,7 @@ void write_device(char device)
|
|||
rcv = sizeof(buffer) - len;
|
||||
}
|
||||
|
||||
// One less to allow for faster pre-increment below
|
||||
dataptr = buffer + len - 1;
|
||||
dataptr = buffer + len;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -394,16 +391,12 @@ void write_device(char device)
|
|||
rcv = 0x100 - len % 0x100;
|
||||
}
|
||||
|
||||
// One less to allow for faster pre-increment below
|
||||
dataptr = buffer + (skew[len / 0x100] << 8 | len % 0x100) - 1;
|
||||
dataptr = buffer + (skew[len / 0x100] << 8 | len % 0x100);
|
||||
}
|
||||
|
||||
for (i = 0; i < rcv; ++i)
|
||||
{
|
||||
// The variable is necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment register.
|
||||
char data = *w5100_data;
|
||||
*++dataptr = data;
|
||||
*dataptr++ = *data;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,6 +435,7 @@ int main(int, char *argv[])
|
|||
uint16_t i;
|
||||
char *arg;
|
||||
char device;
|
||||
bool Offload_DNS;
|
||||
uint8_t eth_init = ETH_INIT_DEFAULT;
|
||||
|
||||
if (doesclrscrafterexit())
|
||||
|
@ -475,11 +469,11 @@ int main(int, char *argv[])
|
|||
{
|
||||
read(file, ð_init, 1);
|
||||
close(file);
|
||||
eth_init &= ~'0';
|
||||
eth_init &= 7;
|
||||
}
|
||||
}
|
||||
|
||||
printf("- %d\n\nInitializing %s ", eth_init, eth_name);
|
||||
printf("- %u\n\nInitializing %s ", eth_init, eth_name);
|
||||
if (ip65_init(eth_init))
|
||||
{
|
||||
ip65_error_exit();
|
||||
|
@ -488,15 +482,20 @@ int main(int, char *argv[])
|
|||
// Abort on Ctrl-C to be consistent with Linenoise
|
||||
abort_key = 0x83;
|
||||
|
||||
printf("- Ok\n\nObtaining IP address ");
|
||||
if (dhcp_init())
|
||||
Offload_DNS = w5100_init(eth_init);
|
||||
|
||||
if (!Offload_DNS)
|
||||
{
|
||||
ip65_error_exit();
|
||||
printf("- Ok\n\nObtaining IP address ");
|
||||
if (dhcp_init())
|
||||
{
|
||||
ip65_error_exit();
|
||||
}
|
||||
}
|
||||
printf("- Ok\n\n");
|
||||
|
||||
// Copy IP config from IP65 to W5100
|
||||
w5100_config(eth_init);
|
||||
w5100_config();
|
||||
|
||||
load_argument("wget.urls");
|
||||
while (true)
|
||||
|
@ -504,7 +503,7 @@ int main(int, char *argv[])
|
|||
arg = get_argument(1, "URL", url_completion);
|
||||
|
||||
printf("\n\nProcessing URL ");
|
||||
if (!url_parse(arg))
|
||||
if (!url_parse(arg, !Offload_DNS))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -657,9 +656,21 @@ int main(int, char *argv[])
|
|||
save_argument("wget.files");
|
||||
|
||||
printf("\n\n");
|
||||
if (!w5100_http_open(url_ip, url_port, url_selector, buffer, sizeof(buffer)))
|
||||
if (Offload_DNS)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
if (!w5100_http_open_name(url_host, strlen(url_host) - 4, url_port,
|
||||
url_selector, buffer, sizeof(buffer)))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!w5100_http_open_addr(url_ip, url_port,
|
||||
url_selector, buffer, sizeof(buffer)))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (device)
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
# For assembler programs
|
||||
# ----------------------
|
||||
# c64rrnet.lib : C64 with RR-Net (or clone)
|
||||
# c64eth64.lib : C64 with ETH64
|
||||
# c64combo.lib : C64 with RR-Net or ETH64
|
||||
# a2uther.lib : Apple ][ with Uthernet (default slot: #3)
|
||||
# a2lancegs.lib : Apple ][ with LANceGS (default slot: #3)
|
||||
# a2uther2.lib : Apple ][ with Uthernet II (default slot: #3)
|
||||
# a2combo.lib : Apple ][ with Uthernet or LANceGS or Uthernet II (default slot: #3)
|
||||
# atrdragon.lib : ATARI 8-bit with Dragon Cart
|
||||
# atrdracarys.lib : ATARI 8-bit with Dracarys (default PBI device ID: #8)
|
||||
# atrcombo.lib : ATARI 8-bit with Dragon Cart or Dracarys (default PBI device ID: #8)
|
||||
# vic20rrnet.lib : VIC20 with RR-Net (or clone)
|
||||
# c64rrnet.lib : C64 with RR-Net (or clone)
|
||||
# c64eth64.lib : C64 with ETH64
|
||||
# c64combo.lib : C64 with RR-Net or ETH64
|
||||
# a2uther.lib : Apple ][ with Uthernet (default slot: #3)
|
||||
# a2uther2.lib : Apple ][ with Uthernet II (default slot: #3)
|
||||
# a2lancegs.lib : Apple ][ with LANceGS (default slot: #3)
|
||||
# a2combo.lib : Apple ][ with Uthernet or Uthernet II or LANceGS (default slot: #3)
|
||||
# atrdragon.lib : ATARI 8-bit with Dragon Cart
|
||||
# vic20rrnet.lib : VIC20 with RR-Net (or clone)
|
||||
|
||||
# For C programs
|
||||
# --------------
|
||||
# ip65_c64.lib : C64 with RR-Net or ETH64
|
||||
# ip65_apple2.lib : Apple ][ with Uthernet or LANceGS or Uthernet II (default slot: #3)
|
||||
# ip65_atari.lib : ATARI 8-bit with Dragon Cart or Dracarys (default PBI device ID: #8)
|
||||
# ip65_atarixl.lib : ATARI XL with Dragon Cart or Dracarys (default PBI device ID: #8)
|
||||
# ip65_apple2.lib : Apple ][ with Uthernet or Uthernet II or LANceGS (default slot: #3)
|
||||
# ip65_atari.lib : ATARI 8-bit with Dragon Cart
|
||||
# ip65_atarixl.lib : ATARI XL with Dragon Cart
|
||||
|
||||
DRIVERS=\
|
||||
c64rrnet.lib \
|
||||
|
@ -25,14 +23,12 @@ DRIVERS=\
|
|||
c64combo.lib \
|
||||
ip65_c64.lib \
|
||||
a2uther.lib \
|
||||
a2lancegs.lib \
|
||||
a2uther2.lib \
|
||||
a2lancegs.lib \
|
||||
a2combo.lib \
|
||||
ip65_apple2.lib \
|
||||
ip65_apple2_uther2.lib \
|
||||
atrdragon.lib \
|
||||
atrdracarys.lib \
|
||||
atrcombo.lib \
|
||||
ip65_atari.lib \
|
||||
ip65_atarixl.lib \
|
||||
vic20rrnet.lib
|
||||
|
@ -118,9 +114,9 @@ rr-net.o uthernet.o dragoncart.o vic20-rr-net.o: cs8900a.s
|
|||
|
||||
eth64.o lancegs.o: lan91c96.s
|
||||
|
||||
uthernet2.o dracarys.o: w5100.s
|
||||
uthernet2.o: w5100.s
|
||||
|
||||
c64combo.o a2combo.o atrcombo.o: ethernetcombo.s
|
||||
c64combo.o a2combo.o: ethernetcombo.s
|
||||
|
||||
c64rrnet.lib: rr-net.o $(CS8900AOBJS) c64init.o $(C64OBJS)
|
||||
|
||||
|
@ -132,10 +128,10 @@ ip65_c64.lib: rr-net.o eth64.o c64combo.o c64init.o $(C64_OBJS)
|
|||
|
||||
a2uther.lib: uthernet.o $(CS8900AOBJS) a2init.o $(A2OBJS)
|
||||
|
||||
a2lancegs.lib: lancegs.o $(LAN91C96OBJS) a2init.o $(A2OBJS)
|
||||
|
||||
a2uther2.lib: uthernet2.o $(W5100OBJS) a2init.o $(A2OBJS)
|
||||
|
||||
a2lancegs.lib: lancegs.o $(LAN91C96OBJS) a2init.o $(A2OBJS)
|
||||
|
||||
a2combo.lib: uthernet.o lancegs.o uthernet2.o a2combo.o a2init.o $(A2OBJS)
|
||||
|
||||
ip65_apple2.lib: uthernet.o lancegs.o uthernet2.o a2combo.o a2init.o $(A2_OBJS)
|
||||
|
@ -144,13 +140,9 @@ ip65_apple2_uther2.lib: uthernet2.o $(W5100OBJS) a2init.o $(A2_OBJS)
|
|||
|
||||
atrdragon.lib: dragoncart.o $(CS8900AOBJS) atrinit.o $(ATROBJS)
|
||||
|
||||
atrdracarys.lib: dracarys.o $(W5100OBJS) atrinit.o $(ATROBJS)
|
||||
ip65_atari.lib: dragoncart.o $(CS8900AOBJS) atrinit.o $(ATR_OBJS)
|
||||
|
||||
atrcombo.lib: dragoncart.o dracarys.o atrcombo.o atrinit.o $(ATROBJS)
|
||||
|
||||
ip65_atari.lib: dragoncart.o dracarys.o atrcombo.o atrinit.o $(ATR_OBJS)
|
||||
|
||||
ip65_atarixl.lib: dragoncart.o dracarys.o atrcombo.o atrinit.o $(ATRXL_OBJS)
|
||||
ip65_atarixl.lib: dragoncart.o $(CS8900AOBJS) atrinit.o $(ATRXL_OBJS)
|
||||
|
||||
vic20rrnet.lib: vic20-rr-net.o $(CS8900AOBJS) vic20init.o $(VIC20OBJS)
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
.exportzp eth_init_default = 5 ; Apple 2 default slot
|
||||
.exportzp eth_init_default = 3 ; Apple 2 default slot
|
||||
|
|
|
@ -1 +1 @@
|
|||
.exportzp eth_init_default = 8 ; PBI default device ID
|
||||
.exportzp eth_init_default = 0
|
||||
|
|
|
@ -132,7 +132,7 @@ set_name:
|
|||
eth_init:
|
||||
sta eth_init_value
|
||||
|
||||
.if .defined (__APPLE2__) .or .defined (__ATARI__)
|
||||
.if .defined (__APPLE2__)
|
||||
ldax #_w5100
|
||||
jsr patch_wrapper
|
||||
ldax #_w5100_name
|
||||
|
|
|
@ -41,12 +41,7 @@
|
|||
|
||||
; Ethernet address
|
||||
mac: .byte $00, $08, $DC ; OUI of WIZnet
|
||||
.ifdef __APPLE2__
|
||||
.byte $A2, $A2, $A2
|
||||
.endif
|
||||
.ifdef __ATARI__
|
||||
.byte $A8, $A8, $A8
|
||||
.endif
|
||||
|
||||
; Buffer attributes
|
||||
bufaddr:.res 2 ; Address
|
||||
|
@ -91,8 +86,6 @@ tmp := tmp4 ; Temporary value
|
|||
|
||||
;=====================================================================
|
||||
|
||||
.ifdef __APPLE2__
|
||||
|
||||
.rodata
|
||||
|
||||
fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03
|
||||
|
@ -155,54 +148,6 @@ init:
|
|||
bcs :- ; Always
|
||||
:
|
||||
|
||||
.endif
|
||||
|
||||
;=====================================================================
|
||||
|
||||
.ifdef __ATARI__
|
||||
|
||||
.rodata
|
||||
|
||||
pdtab: .byte %00000001
|
||||
.byte %00000010
|
||||
.byte %00000100
|
||||
.byte %00001000
|
||||
.byte %00010000
|
||||
.byte %00100000
|
||||
.byte %01000000
|
||||
.byte %10000000
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
|
||||
.bss
|
||||
|
||||
pdbit: .res 1
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
|
||||
mode := $D1F0
|
||||
addr := $D1F1
|
||||
data := $D1F3
|
||||
|
||||
pdvs := $D1FF ; parallel device select
|
||||
shpdvs := $0248 ; shadow parallel device select
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
|
||||
.code
|
||||
|
||||
init:
|
||||
; Convert parallel device ID (1-8) to parallel device bit
|
||||
tay
|
||||
lda pdtab-1,y
|
||||
sta pdbit
|
||||
|
||||
; Select parallel device
|
||||
sta shpdvs
|
||||
sta pdvs
|
||||
|
||||
.endif
|
||||
|
||||
;=====================================================================
|
||||
|
||||
; Indirect Bus I/F mode, Address Auto-Increment
|
||||
|
@ -287,13 +232,6 @@ fixup14:sta data
|
|||
;---------------------------------------------------------------------
|
||||
|
||||
poll:
|
||||
.ifdef __ATARI__
|
||||
; Select parallel device
|
||||
lda pdbit
|
||||
sta shpdvs
|
||||
sta pdvs
|
||||
.endif
|
||||
|
||||
; Check for completion of previous command
|
||||
; Socket 0 Command Register: = 0 ?
|
||||
jsr set_addrcmdreg0
|
||||
|
@ -401,13 +339,6 @@ send:
|
|||
sta adv
|
||||
stx adv+1
|
||||
|
||||
.ifdef __ATARI__
|
||||
; Select parallel device
|
||||
lda pdbit
|
||||
sta shpdvs
|
||||
sta pdvs
|
||||
.endif
|
||||
|
||||
; Set parameters for transmitting data
|
||||
lda #>$4000 ; Socket 0 TX Base Address
|
||||
ldx #$01 ; Write
|
||||
|
|
14
inc/ip65.h
14
inc/ip65.h
|
@ -7,9 +7,7 @@
|
|||
// Ethernet driver initialization parameter values
|
||||
//
|
||||
#if defined(__APPLE2__)
|
||||
#define ETH_INIT_DEFAULT 5 // Apple II slot number
|
||||
#elif defined(__ATARI__)
|
||||
#define ETH_INIT_DEFAULT 8 // ATARI PBI device ID
|
||||
#define ETH_INIT_DEFAULT 3 // Apple II slot number
|
||||
#else
|
||||
#define ETH_INIT_DEFAULT 0 // Unused
|
||||
#endif
|
||||
|
@ -294,16 +292,18 @@ bool __fastcall__ tftp_upload_from_memory(uint32_t server, const char* name,
|
|||
//
|
||||
// On success the variables url_ip, url_port and url_selector (see below) are valid.
|
||||
//
|
||||
// Inputs: url: Zero (or ctrl char) terminated string containing the URL
|
||||
// Inputs: url: Zero (or ctrl char) terminated string containing the URL
|
||||
// resolve: Resolve host in URL
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ url_parse(const char* url);
|
||||
bool __fastcall__ url_parse(const char* url, bool resolve);
|
||||
|
||||
// Access to parsed HTTP URL
|
||||
//
|
||||
// Access to the three items below is only valid after url_parse returned false.
|
||||
// Access to the four items below is only valid after url_parse returned false.
|
||||
//
|
||||
extern uint32_t url_ip; // IP address of host in URL
|
||||
extern char* url_host; // Zero terminated string containing host in URL + "\r\n\r\n"
|
||||
extern uint32_t url_ip; // IP address of host in URL (only if 'resolve' is true)
|
||||
extern uint16_t url_port; // Port number of URL
|
||||
extern char* url_selector; // Zero terminated string containing selector part of URL
|
||||
|
||||
|
|
16
ip65/dhcp.s
16
ip65/dhcp.s
|
@ -85,6 +85,7 @@ dhcp_message_sent_count: .res 1
|
|||
dhcp_timer: .res 1
|
||||
dhcp_loop_count: .res 1
|
||||
dhcp_break_polling_loop: .res 1
|
||||
dhcp_ip: .res 4
|
||||
|
||||
; DHCP constants
|
||||
BOOTREQUEST = 1
|
||||
|
@ -315,9 +316,9 @@ dhcp_in:
|
|||
cmp dhcp_inp+dhcp_yiaddr ; is the first byte in the assigned address 0?
|
||||
bne :+
|
||||
rts ; if so, it's a bogus response - ignore
|
||||
: ldx #4 ; copy the our new IP address
|
||||
: ldx #3 ; copy the new IP address
|
||||
: lda dhcp_inp+dhcp_yiaddr,x
|
||||
sta cfg_ip,x
|
||||
sta dhcp_ip,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
|
@ -423,7 +424,7 @@ send_dhcprequest:
|
|||
ldx #4 ; option length is 4
|
||||
stx output_buffer+dhcp_options+4
|
||||
dex
|
||||
: lda cfg_ip,x
|
||||
: lda dhcp_ip,x
|
||||
sta output_buffer+dhcp_options+5,x
|
||||
dex
|
||||
bpl :-
|
||||
|
@ -449,9 +450,16 @@ send_dhcprequest:
|
|||
|
||||
ldax #output_buffer
|
||||
jsr udp_send
|
||||
bcs :+ ; if we didn't send the message we probably need to wait for an ARP reply to come back.
|
||||
bcs :++ ; if we didn't send the message we probably need to wait for an ARP reply to come back.
|
||||
|
||||
lda #dhcp_bound ; technically, we should wait till we get a DHCPACK message. but we'll assume success
|
||||
sta dhcp_state
|
||||
ldx #3 ; set the new IP address
|
||||
: lda dhcp_ip,x
|
||||
sta cfg_ip,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
: rts
|
||||
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ url_download:
|
|||
sty url_selector
|
||||
ldy url_download_buffer+1
|
||||
sty url_selector+1
|
||||
ldy #1
|
||||
jsr url_parse_buffer
|
||||
bcc resource_download
|
||||
rts
|
||||
|
|
|
@ -65,7 +65,7 @@ _udp_recv_src_port:
|
|||
ldx udp_inp+udp_src_port
|
||||
rts
|
||||
|
||||
_udp_send:
|
||||
_udp_send:
|
||||
stax udp_send_src_port
|
||||
jsr popax
|
||||
stax udp_send_dest_port
|
||||
|
|
21
ip65/url.s
21
ip65/url.s
|
@ -13,6 +13,7 @@
|
|||
.import parse_integer
|
||||
.import dns_ip
|
||||
|
||||
.export url_host
|
||||
.export url_ip
|
||||
.export url_port
|
||||
.export url_selector
|
||||
|
@ -26,7 +27,8 @@ search_string = ptr1
|
|||
.bss
|
||||
|
||||
url_string: .res 2
|
||||
url_ip: .res 4 ; will be set with ip address of host in url
|
||||
url_host: .res 2 ; will be set with hostname + CRLFCRLF
|
||||
url_ip: .res 4 ; will be set with ip address of host in url (if resolve)
|
||||
url_port: .res 2 ; will be set with port number of url
|
||||
url_selector: .res 2 ; will be set with address of selector part of URL
|
||||
url_type: .res 1
|
||||
|
@ -35,6 +37,7 @@ search_string = ptr1
|
|||
url_type_gopher = 1
|
||||
url_type_http = 2
|
||||
|
||||
resolve: .res 1
|
||||
src_ptr: .res 1
|
||||
dest_ptr: .res 1
|
||||
|
||||
|
@ -46,28 +49,33 @@ search_string = ptr1
|
|||
; inputs:
|
||||
; AX = address of URL string
|
||||
; any control character (i.e. <$20) is treated as 'end of string', e.g. a CR or LF, as well as $00
|
||||
; Y = do resolve hostname
|
||||
; outputs:
|
||||
; sec if a malformed url, otherwise:
|
||||
; url_ip = ip address of host in url
|
||||
; url_port = port number of url
|
||||
; url_selector = address of selector part of URL
|
||||
url_parse:
|
||||
sty resolve
|
||||
ldy #<output_buffer
|
||||
sty url_selector
|
||||
ldy #>output_buffer
|
||||
sty url_selector+1
|
||||
ldy resolve
|
||||
|
||||
; parses a URL into a form that makes it easy to retrieve the specified resource
|
||||
; caution - the resulting selector part of URL must fit into the provided buffer !!!
|
||||
; inputs:
|
||||
; AX = address of URL string
|
||||
; any control character (i.e. <$20) is treated as 'end of string', e.g. a CR or LF, as well as $00
|
||||
; Y = do resolve hostname
|
||||
; url_selector = points to a buffer that selector part of URL will be placed into
|
||||
; outputs:
|
||||
; sec if a malformed url, otherwise:
|
||||
; url_ip = ip address of host in url
|
||||
; url_port = port number of url
|
||||
url_parse_buffer:
|
||||
sty resolve
|
||||
stax url_string
|
||||
ldy #url_type_http
|
||||
sty url_type
|
||||
|
@ -109,6 +117,8 @@ lda #url_type_gopher
|
|||
; now pointing at hostname
|
||||
bcs @exit_with_error
|
||||
@no_protocol_specifier:
|
||||
ldy resolve
|
||||
beq @no_resolve
|
||||
jsr dns_set_hostname
|
||||
bcs @exit_with_sec
|
||||
jsr dns_resolve
|
||||
|
@ -125,6 +135,7 @@ lda #url_type_gopher
|
|||
|
||||
jsr skip_to_hostname
|
||||
|
||||
@no_resolve:
|
||||
; skip over next colon
|
||||
ldax #colon
|
||||
jsr parser_skip_next
|
||||
|
@ -212,11 +223,17 @@ lda #url_type_gopher
|
|||
jsr skip_to_hostname
|
||||
; AX now pointing at hostname
|
||||
stax ptr1
|
||||
|
||||
clc
|
||||
lda url_selector
|
||||
sta ptr2
|
||||
adc dest_ptr
|
||||
sta url_host
|
||||
pla
|
||||
sta ptr2+1
|
||||
|
||||
adc #0
|
||||
sta url_host+1
|
||||
|
||||
lda #0
|
||||
sta src_ptr
|
||||
|
||||
|
|
10
ip65/url_c.s
10
ip65/url_c.s
|
@ -1,22 +1,32 @@
|
|||
.include "../inc/common.inc"
|
||||
|
||||
.export _url_parse
|
||||
.export _url_host
|
||||
.export _url_ip
|
||||
.export _url_port
|
||||
.export _url_selector
|
||||
|
||||
.import url_parse
|
||||
.import url_host
|
||||
.import url_ip
|
||||
.import url_port
|
||||
.import url_selector
|
||||
|
||||
.import popax
|
||||
.importzp tmp1
|
||||
|
||||
_url_parse:
|
||||
sta tmp1
|
||||
jsr popax
|
||||
ldy tmp1
|
||||
jsr url_parse
|
||||
ldx #$00
|
||||
txa
|
||||
rol
|
||||
rts
|
||||
|
||||
_url_host := url_host
|
||||
|
||||
_url_ip := url_ip
|
||||
|
||||
_url_port := url_port
|
||||
|
|
BIN
releases/emailler-2.1.10.po
Normal file
BIN
releases/emailler-2.1.10.po
Normal file
Binary file not shown.
BIN
releases/emailler-2.1.11.po
Normal file
BIN
releases/emailler-2.1.11.po
Normal file
Binary file not shown.
BIN
releases/emailler-2.1.12.po
Normal file
BIN
releases/emailler-2.1.12.po
Normal file
Binary file not shown.
BIN
releases/emailler-2.1.13.po
Normal file
BIN
releases/emailler-2.1.13.po
Normal file
Binary file not shown.
BIN
releases/emailler-2.1.14.po
Normal file
BIN
releases/emailler-2.1.14.po
Normal file
Binary file not shown.
BIN
releases/emailler-2.1.6.po
Normal file
BIN
releases/emailler-2.1.6.po
Normal file
Binary file not shown.
BIN
releases/emailler-2.1.7.po
Normal file
BIN
releases/emailler-2.1.7.po
Normal file
Binary file not shown.
BIN
releases/emailler-2.1.8.po
Normal file
BIN
releases/emailler-2.1.8.po
Normal file
Binary file not shown.
BIN
releases/emailler-2.1.9.po
Normal file
BIN
releases/emailler-2.1.9.po
Normal file
Binary file not shown.
|
@ -17,15 +17,14 @@ else ifeq ($(eth),sm)
|
|||
A2DRIVERLIB = ../drivers/a2lancegs.lib
|
||||
else ifeq ($(eth),wn)
|
||||
A2DRIVERLIB = ../drivers/a2uther2.lib
|
||||
ATRDRIVERLIB = ../drivers/atrdracarys.lib
|
||||
else
|
||||
C64DRIVERLIB = ../drivers/c64combo.lib
|
||||
A2DRIVERLIB = ../drivers/a2combo.lib
|
||||
ATRDRIVERLIB = ../drivers/atrcombo.lib
|
||||
ATRDRIVERLIB = ../drivers/atrdragon.lib
|
||||
VICDRIVERLIB = ../drivers/vic20rrnet.lib
|
||||
endif
|
||||
|
||||
# See http://vice-emu.sourceforge.net/
|
||||
# See https://vice-emu.sourceforge.net/
|
||||
C1541 ?= c1541
|
||||
|
||||
# See https://applecommander.github.io/
|
||||
|
@ -112,32 +111,28 @@ vt100.com: ATARI_CFG = ../apps/atrtelnet.cfg
|
|||
%.o: %.c
|
||||
|
||||
%.prg: %.o ip65 drivers
|
||||
ld65 -o $*.prg -C c64.cfg -m $*.c64.map -vm $< $(IP65LIB) $(C64DRIVERLIB) c64.lib
|
||||
ld65 -o $*.prg -C c64.cfg -m $*.prg.map -vm $< $(IP65LIB) $(C64DRIVERLIB) c64.lib
|
||||
|
||||
%.bin: %.o ip65 drivers
|
||||
ld65 -o $*.bin -C apple2.cfg -m $*.a2.map -vm $< $(IP65LIB) $(A2DRIVERLIB) apple2.lib
|
||||
ld65 -o $*.bin -C apple2.cfg -m $*.bin.map -vm $< $(IP65LIB) $(A2DRIVERLIB) apple2.lib
|
||||
|
||||
%.com: %.o ip65 drivers
|
||||
ld65 -o $*.com -C $(ATARI_CFG) -m $*.atr.map -vm $< $(IP65LIB) $(ATRDRIVERLIB) atari.lib
|
||||
ld65 -o $*.com -C $(ATARI_CFG) -m $*.com.map -vm $< $(IP65LIB) $(ATRDRIVERLIB) atari.lib
|
||||
|
||||
%.vicprg: %.o ip65 drivers
|
||||
ld65 -o $*.vicprg -C vic20-32k.cfg -m $*.vic.map -vm $< $(IP65LIB) $(VICDRIVERLIB) vic20.lib
|
||||
ld65 -o $*.vicprg -C vic20-32k.cfg -m $*.vicprg.map -vm $< $(IP65LIB) $(VICDRIVERLIB) vic20.lib
|
||||
|
||||
%.prg: %.c ip65 drivers
|
||||
cl65 -o $*.prg -O -t c64 -m $*.c64.map -vm $< $(wildcard $**.s) $(IP65LIB) ../drivers/ip65_c64.lib
|
||||
rm $*.o
|
||||
cl65 -o $*.prg -O -t c64 -m $*.prg.map -vm $< $(wildcard $**.s) $(IP65LIB) ../drivers/ip65_c64.lib
|
||||
|
||||
%.bin: %.c ip65 drivers
|
||||
cl65 -o $*.bin -O -t apple2 -m $*.a2.map -vm $< $(wildcard $**.s) $(IP65LIB) ../drivers/ip65_apple2.lib
|
||||
rm $*.o
|
||||
cl65 -o $*.bin -O -t apple2 -m $*.bin.map -vm $< $(wildcard $**.s) $(IP65LIB) ../drivers/ip65_apple2.lib
|
||||
|
||||
%.com: %.c ip65 drivers
|
||||
cl65 -o $*.com -O -t atari -m $*.atr.map -vm $< $(wildcard $**.s) $(IP65LIB) ../drivers/ip65_atari.lib
|
||||
rm $*.o
|
||||
cl65 -o $*.com -O -t atari -m $*.com.map -vm $< $(wildcard $**.s) $(IP65LIB) ../drivers/ip65_atari.lib
|
||||
|
||||
%.xl.com: %.c ip65 drivers
|
||||
cl65 -o $*.xl.com -O -t atarixl -m $*.atrxl.map -vm $< $(wildcard $**.s) $(IP65LIB) ../drivers/ip65_atarixl.lib
|
||||
rm $*.o
|
||||
cl65 -o $*.xl.com -O -t atarixl -m $*.xl.com.map -vm $< $(wildcard $**.s) $(IP65LIB) ../drivers/ip65_atarixl.lib
|
||||
|
||||
ip65test.d64: prg
|
||||
$(C1541) -format ip65,00 d64 $@
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
.import url_port
|
||||
.import url_selector
|
||||
.import url_resource_type
|
||||
.import url_parse
|
||||
.import url_download
|
||||
.import url_download_buffer
|
||||
.import url_download_buffer_length
|
||||
|
|
|
@ -100,6 +100,7 @@ test_url_parse:
|
|||
jsr print
|
||||
jsr print_cr
|
||||
ldax temp_url_ptr
|
||||
ldy #1
|
||||
jsr url_parse
|
||||
bcc :+
|
||||
jmp print_errorcode
|
||||
|
|
Loading…
Reference in New Issue
Block a user