/* Copyright 1998 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Generic (c.module) * * THIS FILE REQUIRES CUSTOMISATION * * � Acorn Computers Ltd. 1997 * */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "kernel.h" #include "swis.h" #include "sys/errno.h" #include "module.h" #include "GenericHdr.h" #include "utils.h" #include "protocol.h" #include "connect.h" #include "MemCheck:MemCheck.h" #if CMHG_VERSION < 516 #define CMHG_CONST #else #define CMHG_CONST const #endif /* TinySupport SWIs. This does not work if any library static data * is used within the module. This means errno (__errno) and __ctype * (as used by any macro call to is.... functions) If you re-enable * this SWI call, this module will fail to work at all. */ #define NO_TINYSTUBS #ifdef ROM #ifndef NO_TINYSTUBS static _kernel_oserror *__ROM; #define TinySupport_Share (0x82c43) #define TinySupport_Die (0x82c41) #endif #endif #define NO_SUCH_SWI (0x1E6) #define URL_PROTOCOL_REGISTER 0x83e20 #define URL_PROTOCOL_DEREGISTER 0x83e21 #ifndef ROM extern int messages_file(void); #endif #ifndef ROM #ifdef DEFINE_ERRNO int __errno; #endif #endif static int callback_pending_flag; /* Sets clibrary_realloc_routine_is_buggy to 1 if RISC OS 3.1 or earlier (ROM realloc is broken) */ static int clibrary_realloc_routine_is_buggy; static void module_check_os_version(void) { int os; (void) _swix(OS_Byte, _INR(0,2)|_OUT(1), 129, 0, 255, &os); clibrary_realloc_routine_is_buggy = (os <= 0xA4); } static int registered; static _kernel_oserror *try_to_register(void) { _kernel_oserror *e; if (registered) return NULL; e = _swix(URL_PROTOCOL_REGISTER, _INR(0,4), 0, GenericFetcher_00, CONNECT_DEFAULT_PROTOCOL_NAME ":", Module_VersionNumber, Module_Help " � Acorn"); if (e == NULL) { registered = 1; } return e; } static _kernel_oserror *try_to_deregister(void) { if (!registered) { return NULL; } else { registered = 0; return _swix(URL_PROTOCOL_DEREGISTER, _INR(0,1), 0, GenericFetcher_00); } } static _kernel_oserror *register_with_url(void) { _kernel_oserror *e; e = try_to_register(); if (e == NULL) return e; if (e->errnum != NO_SUCH_SWI) return e; #ifndef ROM e = _swix(OS_Module, _INR(0,1), 1 /* Load */, "System:Modules.Network.URL.URL"); return try_to_register(); #else return NULL; #endif } /*************************************************************/ /* _kernel_oserror *module_init(char *cmd_fail, int podu... */ /*************************************************************/ /* Start up and register ourselves with the URL module */ /*************************************************************/ _kernel_oserror *module_init(CMHG_CONST char *cmd_tail, int podule_base, void *pw) { _kernel_oserror *e; (void) podule_base; (void) cmd_tail; #ifdef ROM #ifndef NO_TINYSTUBS __ROM = _swix(TinySupport_Share, _IN(0), pw); #endif #endif debug_initialise("Generic", 0, 0); debug_output_device(DEBUGIT_OUTPUT); registered = 0; callback_pending_flag = 0; session_init(); module_check_os_version(); MemCheck_InitNoDebug(); MemCheck_SetQuitting(0,0); MemCheck_RedirectToFilename("adfs::4.Trace.Genericmem"); MemCheck_InterceptSCLStringFunctions(); MemCheck_RegisterMiscBlock((void *)0x01c0001c,8164); MemCheck_SetStoreMallocFunctions(1); MemCheck_SetReportFrees(1); MemCheck_SetChecking(0,0); e = register_with_url(); if (e) { #ifndef ROM if (e->errnum == NO_SUCH_SWI) { _kernel_oserror *newe = find_error(); newe->errnum = 0x115; /* NeedMod */ strcpy(newe->errmess, "NeedMod"); e = _swix(MessageTrans_ErrorLookup, _INR(0,7), newe, 0, 0, 0, Module_Title, "URL", 0, 0); } #endif return e; } #ifndef ROM e = _swix(ResourceFS_RegisterFiles, _IN(0), messages_file()); if (e) { (void) try_to_deregister(); return e; } #endif if (getenv(Module_Title "$Path")) { e = messages_file_open(Module_Title ":Messages"); } else { e = messages_file_open("Resources:$.Resources.URL." "Generic" ".Messages"); } if (e) { #ifndef ROM (void) _swix(ResourceFS_DeregisterFiles, _IN(0), messages_file()); #endif (void) try_to_deregister(); return e; } callback_pending_flag = 0; /* Set up a callevery */ e = _swix(OS_CallEvery, _INR(0,2), 15*100-1, callevery_entry, pw); if (e) { messages_file_close(); #ifndef ROM (void) _swix(ResourceFS_DeregisterFiles, _IN(0), messages_file()); #endif (void) try_to_deregister(); return e; } return NULL; } void service_handler(int service_number, _kernel_swi_regs *r, void *pw) { dprintf(("module_1", "Service &%X: R0 = %d for URL version %03d\n", service_number, r->r[0], r->r[2])); (void) pw; (void) service_number; switch (r->r[0]) { case 0: (void) try_to_register(); break; case 1: (void) try_to_deregister(); break; default: break; } } _kernel_oserror *module_kill(int fatal, int podule, void *pw) { (void) fatal; (void) podule; (void) _swix(OS_RemoveTickerEvent, _INR(0,1), callevery_entry, pw); if (callback_pending_flag) { (void) _swix(OS_RemoveCallBack, _INR(0,1), callback_entry, pw); } messages_file_close(); #ifndef ROM (void) _swix(ResourceFS_DeregisterFiles, _IN(0), messages_file()); #endif ses_kill_all(); (void) try_to_deregister(); #ifdef ROM #ifndef NO_TINYSTUBS if(!__ROM) _swix(TinySupport_Die, 0); #endif #endif return NULL; } _kernel_oserror *swi_handler(int swi_offset, _kernel_swi_regs *r, void *pw) { (void) pw; switch (swi_offset) { case GenericFetcher_GetData - GenericFetcher_00: return(generic_start(r)); case GenericFetcher_Status - GenericFetcher_00: return(generic_status(r)); case GenericFetcher_ReadData - GenericFetcher_00: return(generic_readdata(r)); case GenericFetcher_Stop - GenericFetcher_00: return (generic_stop(r)); default: return(error_BAD_SWI); } } int callback_handler(_kernel_swi_regs *r, void *pw) { (void) pw; (void) r; if (!callback_pending_flag) { return 1; } callback_pending_flag = 0; return 1; } int callevery_handler(_kernel_swi_regs *r, void *pw) { (void) r; if (callback_pending_flag) { return 1; } callback_pending_flag = 1; (void) _swix(OS_AddCallBack, _INR(0,1), callback_entry, pw); return 1; } /* RISC OS 3.1 SVC mode realloc is broken, so we must provide our own */ char *module_realloc(void *ptr, size_t size) { dprintf(("module_1", "module_realloc(%p, %d)\n", ptr, size)); if (!clibrary_realloc_routine_is_buggy) return realloc(ptr, size); if (ptr == NULL) { return malloc(size); } if (size == 0) { free(ptr); return NULL; } else { const int *rma_block = ptr; const size_t newsize = size - (rma_block[-1] - 4); char *newptr; if (_swix(OS_Module, _IN(0)|_INR(2,3)|_OUT(2), 0xD, ptr, newsize, &newptr) != NULL) { return NULL; } return newptr; } }