emailler/apps/hfs65.c

336 lines
6.1 KiB
C
Raw Normal View History

#include <dio.h>
#include <cc65.h>
#include <fcntl.h>
#include <conio.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <device.h>
#include <dirent.h>
#include "../inc/ip65.h"
#ifdef __CBM__
//#define IMAGE ".D64"
#endif
#ifdef __APPLE2__
#define IMAGE ".PO"
#endif
#ifdef __ATARI__
//#define IMAGE ".ATR"
char* __fastcall__ getdevicedir(unsigned char, char*, size_t) { return NULL; } // Hack just to make it build !
#endif
#define SEND_FIRST 1
#define SEND_LAST 2
unsigned char send_buffer[1024];
unsigned int send_size;
unsigned char send_type;
void send(unsigned char flags, const char* str, ...)
{
va_list args;
if (flags & SEND_FIRST)
{
send_size = 0;
send_type = HTTPD_RESPONSE_200_HTML;
}
va_start(args, str);
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)
{
#ifdef __CBM__
{
unsigned char* ptr = send_buffer;
unsigned char* end = send_buffer + send_size;
for (; ptr != end; ++ptr)
{
*ptr = toascii(*ptr);
}
}
#endif
httpd_send_response(send_type, send_buffer, send_size);
send_size = 0;
send_type = HTTPD_RESPONSE_NOHEADER;
}
}
void error(void)
{
httpd_send_response(HTTPD_RESPONSE_500, 0, 0);
printf("500\n");
}
void root(void)
{
char diskdir[FILENAME_MAX];
char* rootdir = diskdir;
unsigned char disk = getfirstdevice();
#ifdef __APPLE2__
// skip '/'
++rootdir;
#endif
send(SEND_FIRST, "<h2>/</h2><table style='border-spacing: 1em 0em'>");
while (disk != INVALID_DEVICE)
{
if (getdevicedir(disk, diskdir, sizeof(diskdir)))
{
send(0, "<tr><td>Disk</td><td><a href='%s'>%s</a></td></tr>",
rootdir, rootdir);
#ifdef IMAGE
{
dhandle_t dio = dio_open(disk);
if (dio)
{
send(0, "<tr><td>Image</td><td><a href='%s"IMAGE"'>%s"IMAGE"</a></td><td align=right>%u</td></tr>",
rootdir, rootdir, dio_query_sectcount(dio));
dio_close(dio);
}
}
#endif
}
disk = getnextdevice(disk);
}
send(SEND_LAST, "</table>");
printf("200\n");
}
void directory(const char* path)
{
char* delimiter;
struct dirent *ent;
DIR *dir = opendir(".");
if (!dir)
{
error();
return;
}
send(SEND_FIRST, "<h2>%s</h2><table style='border-spacing: 1em 0em'>", path);
delimiter = strrchr(path, '/');
if (delimiter && delimiter != path)
{
*delimiter = '\0';
send(0, "<tr><td>Directory</td><td><a href='%s'>..</a></td></tr>", path);
*delimiter = '/';
}
else
{
send(0, "<tr><td>Disk</td><td><a href='/'>..</a></td></tr>");
}
while (ent = readdir(dir))
{
if (_DE_ISREG(ent->d_type))
{
#ifdef __ATARI__
send(0, "<tr><td>File</td><td><a href='%s/%s'>%s</a></td></tr>",
path, ent->d_name, ent->d_name);
#else
send(0, "<tr><td>File</td><td><a href='%s/%s'>%s</a></td><td align=right>%u</td></tr>",
path, ent->d_name, ent->d_name, ent->d_blocks);
#endif
continue;
}
if (_DE_ISDIR(ent->d_type))
{
send(0, "<tr><td>Directory</td><td><a href='%s/%s'>%s</a></td></tr>",
path, ent->d_name, ent->d_name);
}
}
send(SEND_LAST, "</table>");
closedir(dir);
printf("200\n");
}
unsigned char file(const char* name)
{
int size;
int file = open(name, O_RDONLY);
if (file < 0)
{
return 0;
}
send_type = HTTPD_RESPONSE_200_DATA;
while ((size = read(file, send_buffer, sizeof(send_buffer))) > 0)
{
httpd_send_response(send_type, send_buffer, size);
send_type = HTTPD_RESPONSE_NOHEADER;
}
close(file);
printf("200\n");
return 1;
}
#ifdef IMAGE
void image()
{
unsigned int sector = 0;
dhandle_t dio = dio_open(getcurrentdevice());
if (!dio)
{
error();
return;
}
send_size = dio_query_sectsize(dio);
send_type = HTTPD_RESPONSE_200_DATA;
#ifdef __ATARI__
#error "TODO: Send ATR header."
dio_query_sectcount(dio);
#endif
while (!dio_read(dio, sector++, send_buffer))
{
httpd_send_response(send_type, send_buffer, send_size);
send_type = HTTPD_RESPONSE_NOHEADER;
}
dio_close(dio);
printf("200\n");
}
#endif
void http_server(uint32_t client, const char* method, const char* path)
{
char* delimiter;
printf("%s \"%s %s\" ", dotted_quad(client), method, path);
if (stricmp(method, "get") || path[0] != '/')
{
error();
return;
}
if (path[1] == '\0')
{
root();
return;
}
#ifndef __APPLE2__
// skip '/'
++path;
#endif
if (!chdir(path))
{
directory(path);
return;
}
delimiter = strrchr(path, '/');
if (delimiter && delimiter != path)
{
*delimiter++ = '\0';
if (!chdir(path) && file(delimiter))
{
return;
}
}
#ifdef IMAGE
else
{
delimiter = strrchr(path, '.');
if (delimiter)
{
*delimiter = '\0';
if (!chdir(path))
{
image();
return;
}
}
}
#endif
httpd_send_response(HTTPD_RESPONSE_404, 0, 0);
printf("404\n");
}
void error_exit(void)
{
2020-04-15 12:52:59 +00:00
printf("- %s\n", ip65_strerror(ip65_error));
if (doesclrscrafterexit())
{
printf("\nPress any key ");
cgetc();
}
2018-07-27 15:07:31 +00:00
exit(EXIT_FAILURE);
}
2020-04-15 19:25:23 +00:00
int main(void)
{
char cwd[FILENAME_MAX];
Removed Ethernet driver I/O base. So far the base address of the Ethernet chip was a general property of all Ethernet drivers. It served two purposes: 1. Allowing to use a single Ethernet driver for a certain Ethernet chip, no matter what machine was connected to the chip. 2. Allowing use an Ethernet card in all Apple II slots. However, we now use customized Ethernet drivers for the individual machines so 1.) isn't relevant anymore. In fact one wants to omit the overhead of a runtime-adjustable base address where it isn't needed. So only the Apple II slots are left. But this should rather be a driver-internal approach then. We should just hand the driver the slot number the user wants to use and have the driver do its thing. Independently from the aspect if the driver parameter is a base address or a slot number the parameter handling was changed too. For asm programs there was so far a specific init function to be called prior to the main init function if it was desired to chnage the parameter default. This was done to keep the main init function backward compatible. But now that the parameter (now the slot number) is only used on the Apple II anyhow it seems reasonable to drop the specific init function again and just provide the parameter to the main init function. All C64-only user code can stay as-is. Only Apple II user code needs to by adjusted. Please note that this change only affects asm programs, C programs always used a single init function with the Apple II slot number as parameter.
2019-05-02 12:44:24 +00:00
unsigned char eth_init = ETH_INIT_DEFAULT;
getcwd(cwd, sizeof(cwd));
#ifdef __APPLE2__
videomode(VIDEOMODE_80COL);
#endif
2019-05-10 15:47:06 +00:00
printf("\nHttpFileServer65 v1.1"
"\n=====================");
#ifdef __APPLE2__
{
int file;
printf("\n\nSetting slot ");
file = open("ethernet.slot", O_RDONLY);
if (file != -1)
{
Removed Ethernet driver I/O base. So far the base address of the Ethernet chip was a general property of all Ethernet drivers. It served two purposes: 1. Allowing to use a single Ethernet driver for a certain Ethernet chip, no matter what machine was connected to the chip. 2. Allowing use an Ethernet card in all Apple II slots. However, we now use customized Ethernet drivers for the individual machines so 1.) isn't relevant anymore. In fact one wants to omit the overhead of a runtime-adjustable base address where it isn't needed. So only the Apple II slots are left. But this should rather be a driver-internal approach then. We should just hand the driver the slot number the user wants to use and have the driver do its thing. Independently from the aspect if the driver parameter is a base address or a slot number the parameter handling was changed too. For asm programs there was so far a specific init function to be called prior to the main init function if it was desired to chnage the parameter default. This was done to keep the main init function backward compatible. But now that the parameter (now the slot number) is only used on the Apple II anyhow it seems reasonable to drop the specific init function again and just provide the parameter to the main init function. All C64-only user code can stay as-is. Only Apple II user code needs to by adjusted. Please note that this change only affects asm programs, C programs always used a single init function with the Apple II slot number as parameter.
2019-05-02 12:44:24 +00:00
read(file, &eth_init, 1);
close(file);
eth_init &= 7;
}
printf("- %u", eth_init);
}
#endif
printf("\n\nInitializing ");
Removed Ethernet driver I/O base. So far the base address of the Ethernet chip was a general property of all Ethernet drivers. It served two purposes: 1. Allowing to use a single Ethernet driver for a certain Ethernet chip, no matter what machine was connected to the chip. 2. Allowing use an Ethernet card in all Apple II slots. However, we now use customized Ethernet drivers for the individual machines so 1.) isn't relevant anymore. In fact one wants to omit the overhead of a runtime-adjustable base address where it isn't needed. So only the Apple II slots are left. But this should rather be a driver-internal approach then. We should just hand the driver the slot number the user wants to use and have the driver do its thing. Independently from the aspect if the driver parameter is a base address or a slot number the parameter handling was changed too. For asm programs there was so far a specific init function to be called prior to the main init function if it was desired to chnage the parameter default. This was done to keep the main init function backward compatible. But now that the parameter (now the slot number) is only used on the Apple II anyhow it seems reasonable to drop the specific init function again and just provide the parameter to the main init function. All C64-only user code can stay as-is. Only Apple II user code needs to by adjusted. Please note that this change only affects asm programs, C programs always used a single init function with the Apple II slot number as parameter.
2019-05-02 12:44:24 +00:00
if (ip65_init(eth_init))
{
error_exit();
}
printf("- Ok\n\nObtaining IP address ");
if (dhcp_init())
{
error_exit();
}
printf("- Ok\n\nStarting server on %s\n\n", dotted_quad(cfg_ip));
httpd_start(80, http_server);
chdir(cwd);
2020-04-15 19:25:23 +00:00
return EXIT_SUCCESS;
}