/****************************************************************************
os_utils.c
For interface with RISCOS
****************************************************************************/

#include <stdio.h>
#include <string.h>
#include "kernel.h"
#include "swis.h"
#include "os_utils.h"
#include "cipher.h"

/* Operating system errors */

_kernel_oserror
error_bufferfull = { 1, "Command line buffer full" },
error_noteandd = { 1, "-Encrypt and -Decrypt are mutually exclusive" }, /* ~v0.08 */
error_notbothpasswords = { 1, "-Password and -File are mutually exclusive" },
error_badargs = { 1, "Bad arguments" },
error_filenotfound = { 1, "File not found" },
error_badheader = { 1, "Bad Header for Cipher file" },
error_unknownheader = { 1, "Unknown version of Cipher file" },
error_rename = { 1, "Rename Error: Output stored as '" CIPHER_TEMP "'"},
error_cantdeletesource = { 1, "Can't Delete Input: Output stored as '" CIPHER_TEMP "'"},
error_unknownswi = { 1, "Unknown " MODULE_NAME " swi" },
error_nomemory = { 1, "Run out of memory" },
*_last_os_error,
*_temp_os_error;

/****************************************************************************
read_line()
gets a line of input using OS_ReadLine
****************************************************************************/

_kernel_oserror *read_line(char *prompt, char *string, int size)
{
   _kernel_swi_regs r;

   printf("%s",prompt);

   r.r[0] = (int) string;
   r.r[1] = (int) size-1; /* leave room for the null */
   r.r[2] = (int) 0x20;
   r.r[3] = (int) 0xFF;
   return_os_error( _kernel_swi(OS_ReadLine, &r, &r) );
   string[r.r[1]] = 0;    /* 0 terminate the string */
   return 0;
}

/****************************************************************************
readargs()
calculates the arguments to a command using OS_ReadArgs
****************************************************************************/

_kernel_oserror *readargs(char *command_string, char *arg_string, int *buffer, int buffersize)
{
   _kernel_swi_regs r;
   r.r[0] = (int) command_string;
   r.r[1] = (int) arg_string;
   r.r[2] = (int) buffer;
   r.r[3] = (int) buffersize;
   return_os_error( _kernel_swi(OS_ReadArgs, &r, &r) );
/* if (buffer[3] < 0)  this is not testing the returned r3!       -v0.08  */
/* Caused occasional spurious errors 'Command line buffer full'    v0.08  */
   if (r.r[3] < 0)       /* This should test for buffer overflow  ~v0.08  */
      return &error_bufferfull;
   return 0;
}

/****************************************************************************
readfileinfo()
reads file information using OS_File
****************************************************************************/

_kernel_oserror *readfileinfo(char *file, int *load, int *exec, int *size, int *type)
{
   _kernel_swi_regs r;
   r.r[0] = (int) 17;
   r.r[1] = (int) file;
   return_os_error( _kernel_swi(OS_File, &r, &r) );
   if (r.r[0] != 1 && r.r[0] != 3)
     return &error_filenotfound;
   *load = r.r[2];
   *exec = r.r[3];
   *size = r.r[4];
   *type = (r.r[2] >> 8) & 0xFFF;
   return 0;
}

/****************************************************************************
setfiletype()
sets the filetype using OS_File
****************************************************************************/

_kernel_oserror *setfiletype(char *file, int type)
{
   _kernel_swi_regs r;
   r.r[0] = (int) 18;
   r.r[1] = (int) file;
   r.r[2] = (int) type;
   return_os_error( _kernel_swi(OS_File, &r, &r) );
   return 0;
}

/****************************************************************************
setfileloadexec()
sets the load and exec addresses using OS_File
****************************************************************************/

_kernel_oserror *setfileloadexec(char *file, int load, int exec)
{
   _kernel_swi_regs r;
   r.r[0] = (int) 2;
   r.r[1] = (int) file;
   r.r[2] = (int) load;
   return_os_error( _kernel_swi(OS_File, &r, &r) );
   r.r[0] = (int) 3;
   r.r[1] = (int) file;
   r.r[3] = (int) exec;
   return_os_error( _kernel_swi(OS_File, &r, &r) );
   return 0;
}

/****************************************************************************
os_rename(char *from, char *to)
Renames a file using OS_FSControl 25
****************************************************************************/

_kernel_oserror *os_rename(char *from, char *to)
{
   _kernel_swi_regs r;
   r.r[0] = (int) 25;
   r.r[1] = (int) from;
   r.r[2] = (int) to;
   return_os_error( _kernel_swi(OS_FSControl, &r, &r) );
   return 0;
}

/****************************************************************************
os_remove(char *file)
Removes a file using OS_File 6
****************************************************************************/

_kernel_oserror *os_remove(char *file)
{
   _kernel_swi_regs r;
   r.r[0] = (int) 6;
   r.r[1] = (int) file;
   return_os_error( _kernel_swi(OS_File, &r, &r) );
   return 0;
}

/****************************************************************************
os_fopen()
Opens a file using OS_Find 64-255
If the file does not exist then an error is called
****************************************************************************/

_kernel_oserror *os_fopen(char *file, enum os_fopenmode mode, int *handle)
{
   _kernel_swi_regs r;
   r.r[0] = (int) mode;
   r.r[1] = (int) file;
   return_os_error( _kernel_swi(OS_Find, &r, &r) );
   *handle = r.r[0];
   return 0;
}

/****************************************************************************
os_fread()
Reads from a file using OS_GBPB
****************************************************************************/

_kernel_oserror *os_fread(void *buffer, int buffersize, int handle, int *bytesread)
{
   _kernel_swi_regs r;
/* printf("fread(buffer=%p, size=%i, handle=%i)...", buffer, buffersize, handle); */
   r.r[0] = (int) 4;
   r.r[1] = (int) handle;
   r.r[2] = (int) buffer;
   r.r[3] = (int) buffersize;
/* if (buffersize == 0) printf("buffer is 0\n"); */
   return_os_error( _kernel_swi(OS_GBPB, &r, &r) );
   *bytesread = buffersize - r.r[3];
/* printf("read = %i OK\n", *bytesread); */
   return 0;
}

/****************************************************************************
os_fwrite()
Writes to a file using OS_GBPB
****************************************************************************/

_kernel_oserror *os_fwrite(void *buffer, int buffersize, int handle)
{
   _kernel_swi_regs r;
/* printf("fwrite(buffer=%p, size=%i, handle=%i)...", buffer, buffersize, handle); */
   r.r[0] = (int) 2;
   r.r[1] = (int) handle;
   r.r[2] = (int) buffer;
   r.r[3] = (int) buffersize;
   return_os_error( _kernel_swi(OS_GBPB, &r, &r) );
/* printf("OK\n"); */
   return 0;
}

/****************************************************************************
os_feof()
Reads the file's EOF status using OS_Args 5
****************************************************************************/

_kernel_oserror *os_feof(int handle, int *result)
{
   _kernel_swi_regs r;
   r.r[0] = (int) 5;
   r.r[1] = (int) handle;
   return_os_error( _kernel_swi(OS_Args, &r, &r) );
   *result = (r.r[2] != 0);
   return 0;
}

/****************************************************************************
os_setextend()
Reads sets an open files extent using OS_Args 3
****************************************************************************/

_kernel_oserror *os_setextent(int handle, int extent)
{
   _kernel_swi_regs r;
   r.r[0] = (int) 3;
   r.r[1] = (int) handle;
   r.r[2] = (int) extent;
   return_os_error( _kernel_swi(OS_Args, &r, &r) );
   return 0;
}

/****************************************************************************
os_fclose()
Closes an open file using OS_Find 0
****************************************************************************/

_kernel_oserror *os_fclose(int handle)
{
   _kernel_swi_regs r;
   if (handle == 0)
      return 0;      /* assume that a handle of zero is an error */
   r.r[0] = (int) 0;
   r.r[1] = (int) handle;
   return_os_error( _kernel_swi(OS_Find, &r, &r) );
   return 0;
}

