home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
back2roots/padua
/
padua.7z
/
padua
/
amix
/
AmigaDOS-Emu.zoo
/
dos.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-14
|
10KB
|
490 lines
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <termio.h>
#include <fcntl.h>
#include <osfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma pack(2)
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/tasks.h>
#include <exec/execbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#pragma pack()
#include "arun.h"
#define TIME_OFFSET 252460800 /* Where AmigaDOS starts its times */
#define NFUNCS 400
struct doslib {
struct func vectors[NFUNCS];
struct DosLibrary lib;
} doslib;
struct DosLibrary *const DOSBase = &doslib.lib;
struct Process CurrentProcess;
struct CommandLineInterface CLI;
extern void SDOSBase_Execute(void);
extern void SDOSBase_Examine(void);
extern void SDOSBase_Lock(void);
extern void SDOSBase_UnLock(void);
extern void SDOSBase_Open(void);
extern void SDOSBase_Close(void);
extern void SDOSBase_Read(void);
extern void SDOSBase_Write(void);
extern void SDOSBase_Seek(void);
extern void SDOSBase_Input(void);
extern void SDOSBase_Output(void);
extern void SDOSBase_CurrentDir(void);
extern void SDOSBase_DeleteFile(void);
extern void SDOSBase_IoErr(void);
extern void SDOSBase_IsInteractive(void);
extern void SDOSBase_DateStamp(void);
static struct libinit { void (*func)(); int offset; } libinit[] =
{
{ SDOSBase_Execute, -0xde, },
{ SDOSBase_Examine, -0x66, },
{ SDOSBase_Lock, -0x54, },
{ SDOSBase_UnLock, -0x5a, },
{ SDOSBase_Open, -0x1e, },
{ SDOSBase_Close, -0x24, },
{ SDOSBase_Read, -0x2a, },
{ SDOSBase_Write, -0x30, },
{ SDOSBase_Seek, -0x42, },
{ SDOSBase_Input, -0x36, },
{ SDOSBase_Output, -0x3c, },
{ SDOSBase_CurrentDir, -0x7e, },
{ SDOSBase_DeleteFile, -0x48, },
{ SDOSBase_IoErr, -0x84, },
{ SDOSBase_IsInteractive, -0xd8, },
{ SDOSBase_DateStamp, -0xc0, },
{ 0, 0, },
};
struct RootNode RootNode;
struct DosInfo DosInfo;
struct FileHandle standardinputH, standardoutputH, erroroutputH;
struct FileLock erroroutputL, initialdirL;
ULONG CurrentDir;
void dos_init(void)
{
struct libinit *p2;
struct func *p;
int i;
DOSBase->dl_lib.lib_Node.ln_Name = DOSNAME;
DOSBase->dl_Root = (APTR)&RootNode;
RootNode.rn_Info = CTOB(&DosInfo);
standardinputH.fh_Arg1 = 0;
standardinputH.fh_Arg2 = 1;
standardoutputH.fh_Arg1 = 1;
standardoutputH.fh_Arg2 = 1;
erroroutputH.fh_Arg1 = 2;
erroroutputH.fh_Arg2 = 1;
erroroutputL.fl_Key = 2;
initialdirL.fl_Key = open(".", O_RDONLY);
CurrentDir = CTOB(&initialdirL);
/* First, fill all vectors with "unsupp" calls */
p = (struct func *)DOSBase;
for ( i=0 ; i<NFUNCS ; ++i )
{
--p;
p->opcode = 0x4eb9; /* jsr N.l */
p->addr = unsupp;
}
/* Now, fill in the supported vectors with the real jumps */
for ( p2=libinit ; p2->func ; ++p2 )
{
p = (struct func *)((char *)DOSBase + p2->offset);
p->opcode = 0x4ef9; /* jmp N.l */
p->addr = p2->func;
}
CurrentProcess.pr_Result2 = 1; /* IoErr -- yuck */
verbose("DOSBase = 0x%x", DOSBase);
CurrentProcess.pr_Task.tc_Node.ln_Name = "FakeProcess";
CurrentProcess.pr_CLI = CTOB(&CLI);
ExecBase->ThisTask = &CurrentProcess.pr_Task;
verbose("&CurrentProcess = 0x%x (&MsgPort=0x%x)",
&CurrentProcess, &CurrentProcess.pr_MsgPort);
verbose("&CurrentProcess.pr_CLI = 0x%x (offset 0x%x)",
&CurrentProcess.pr_CLI,
(char *)&CurrentProcess.pr_CLI - (char *)&CurrentProcess);
}
#ifdef INTERNAL_EXECUTE
static char *pathcat(const char *dir, const char *file)
{
char *p;
static char *buf;
static unsigned int buflen;
while (strlen(dir)+strlen(file)+2 > buflen)
buf = buf ? realloc(buf, buflen+=50) : malloc(buflen+=50);
if (buf)
{
p=buf;
while (*p++ = *dir++)
;
--p;
if (p>buf && p[-1] != '/')
*p++ = '/';
strcpy(p, file);
}
return buf;
}
static FILE *pathopen(const char *file)
{
FILE *fp;
char *p, *path;
if (fp = fopen(file, "r"))
return fp;
if (!(path = getenv("PATH")))
return 0;
if (!(path = strdup(path)))
return 0;
for ( p=strtok(path, ":") ; p ; p=strtok((char *)0, ":") )
{
char *name = pathcat(p, file);
if (name && (fp=fopen(name, "r")))
{
free(path);
return fp;
}
}
free(path);
return 0;
}
#endif
ULONG DOSBase_Execute(char *command, ULONG input, ULONG output)
{
#ifdef INTERNAL_EXECUTE
unsigned char *p;
int n;
ULONG savecmd;
ULONG *seg;
FILE *fp;
n = strcspn(command, " \t");
p = malloc(n + 2);
if (!p)
return -1;
p[0] = n;
strncpy((char *)p+1, command, n);
p[n+1] = 0;
if ((fp = pathopen((char *)p+1)) &&
(seg = adosload(fp, (char *)p+1, 0)))
{
(void)fclose(fp);
savecmd = CLI.cli_CommandName;
CLI.cli_CommandName = CTOB(p);
verbose("Execute(%s) (internal)", command);
runseg(seg, (unsigned char *)command+n, strlen(command+n));
CLI.cli_CommandName = savecmd;
}
else
{
verbose("Execute(%s) (external)", command);
system(command);
}
free(p);
#else
verbose("Execute(%s)", command);
system(command);
#endif
}
static void stat_to_fib(struct FileInfoBlock *fibp, struct stat *statp)
{
long temp;
struct tm *tp;
memset(fibp, 0, sizeof *fibp);
fibp->fib_DiskKey = statp->st_ino;
fibp->fib_DirEntryType = ((statp->st_mode&S_IFMT)==S_IFDIR) ? 1 : -1;
fibp->fib_FileName[0] = '.';
if (!(statp->st_mode&S_IREAD))
fibp->fib_Protection |= FIBF_READ;
if (!(statp->st_mode&S_IWRITE))
fibp->fib_Protection |= FIBF_WRITE;
if (!(statp->st_mode&S_IEXEC))
fibp->fib_Protection |= FIBF_EXECUTE;
fibp->fib_Protection |= (statp->st_uid&0xff)<<24;
fibp->fib_Protection |= (statp->st_gid&0xff)<<16;
fibp->fib_Size = statp->st_size;
fibp->fib_NumBlocks = statp->st_blocks;
temp = statp->st_mtime;
tp = localtime(&temp);
if (tp->tm_isdst)
temp += 60*60;
temp -= TIME_OFFSET;
temp -= timezone;
fibp->fib_Date.ds_Days = temp / (60*60*24);
temp %= (60*60*24);
fibp->fib_Date.ds_Minute = temp / 60;
fibp->fib_Date.ds_Tick = (temp%60) * TICKS_PER_SECOND;
}
ULONG DOSBase_Examine(ULONG lock, struct FileInfoBlock *fibp)
{
struct stat Stat;
struct FileLock *lp;
verbose("Examine(0x%x, 0x%x)", lock);
lp = (struct FileLock *)BTOC(lock);
if (fstat(lp->fl_Key, &Stat))
return 0;
stat_to_fib(fibp, &Stat);
return 1;
}
ULONG DOSBase_Lock(char *fn, ULONG mode)
{
int fd;
struct FileLock *lp;
verbose("Lock(%s, 0x%x)", fn, mode);
if (!strcmp(fn, "*"))
return CTOB(&erroroutputL);
if (!fn[0])
fn = ".";
if ((fd=open(fn, O_RDONLY)) < 0)
return 0;
lp = malloc(sizeof *lp);
if (!lp)
{
close(fd);
return 0;
}
lp->fl_Link = lp->fl_Access = lp->fl_Volume = 0;
lp->fl_Task = (struct MsgPort *)0;
lp->fl_Key = fd;
return CTOB(lp);
}
void DOSBase_UnLock(ULONG fl)
{
struct FileLock *lp;
verbose("UnLock(%8x)", fl);
if (fl)
{
lp = (struct FileLock *)BTOC(fl);
close(lp->fl_Key);
free(lp);
}
}
ULONG DOSBase_Open(char *fn, ULONG mode)
{
int fd, umode;
struct FileHandle *fp;
verbose("Open(%s, 0x%x)", fn, mode);
if (!strcmp(fn, "*"))
return CTOB(&erroroutputH);
if (!fn[0])
fn = ".";
switch (mode)
{
case MODE_OLDFILE:
umode = O_RDWR;
break;
case MODE_NEWFILE:
umode = O_RDWR|O_CREAT|O_TRUNC;
break;
default:
return 0;
}
if ((fd=open(fn, umode, 0666)) < 0)
return 0;
fp = malloc(sizeof *fp);
if (!fp)
{
close(fd);
return 0;
}
fp->fh_Buf = fp->fh_Pos = fp->fh_End = 0;
fp->fh_Func1 = fp->fh_Func2 = fp->fh_Func3 = 0;
fp->fh_Arg1 = fd;
fp->fh_Arg2 = 0;
return CTOB(fp);
}
void DOSBase_Close(ULONG fh)
{
struct FileHandle *fp;
verbose("Close(0x%x)", fh);
fp = (struct FileHandle *)BTOC(fh);
if (!fp->fh_Arg2)
{
close(fp->fh_Arg1);
free(fp);
}
}
ULONG DOSBase_Read(ULONG fh, void *buf, ULONG nbytes)
{
struct FileHandle *fp;
fp = (struct FileHandle *)BTOC(fh);
verbose("Read(0x%x, 0x%x, 0x%x)", fh, buf, nbytes);
return read(fp->fh_Arg1, buf, nbytes);
}
ULONG DOSBase_Write(ULONG fh, void *buf, ULONG nbytes)
{
struct FileHandle *fp;
fp = (struct FileHandle *)BTOC(fh);
verbose("Write(0x%x, 0x%x, 0x%x)", fh, buf, nbytes);
return write(fp->fh_Arg1, buf, nbytes);
}
ULONG DOSBase_Seek(ULONG fh, LONG pos, ULONG mode)
{
struct FileHandle *fp;
ULONG oldpos;
fp = (struct FileHandle *)BTOC(fh);
verbose("Seek(0x%x, 0x%x, 0x%x)", fh, pos, mode);
switch (mode)
{
case OFFSET_BEGINNING:
oldpos = lseek(fp->fh_Arg1, 0L, 1);
if (oldpos != -1L)
if (lseek(fp->fh_Arg1, pos, 0) == -1L)
return -1L;
return oldpos;
case OFFSET_CURRENT:
oldpos = lseek(fp->fh_Arg1, pos, 1);
if (oldpos != -1L)
oldpos -= pos;
return oldpos;
case OFFSET_END:
oldpos = lseek(fp->fh_Arg1, 0L, 1);
if (oldpos != -1L)
if (lseek(fp->fh_Arg1, pos, 2) == -1L)
return -1L;
return oldpos;
default:
return -1;
}
}
ULONG DOSBase_Input(void)
{
verbose("Input()");
return CTOB(&standardinputH);
}
ULONG DOSBase_Output(void)
{
verbose("Output()");
return CTOB(&standardoutputH);
}
ULONG DOSBase_CurrentDir(ULONG lock)
{
struct FileLock *lp;
ULONG prev;
verbose("CurrentDir(0x%x)", lock);
lp = (struct FileLock *)BTOC(lock);
if (fchdir(lock?lp->fl_Key:initialdirL.fl_Key))
panic("fchdir failed");
prev = CurrentDir;
CurrentDir = lock;
return prev;
}
ULONG DOSBase_DeleteFile(char *fn)
{
verbose("DeleteFile(%s)", fn);
return unlink(fn) == 0;
}
ULONG DOSBase_IoErr(void)
{
verbose("IoErr()");
return CurrentProcess.pr_Result2;
}
ULONG DOSBase_IsInteractive(ULONG fh)
{
struct FileHandle *fp;
struct termio termio;
fp = (struct FileHandle *)BTOC(fh);
verbose("IsInteractive(%8x)", fh);
return ioctl(fp->fh_Arg1, TCGETA, &termio) == 0;
}
ULONG *DOSBase_DateStamp(ULONG *v)
{
extern long time(long *);
long temp;
struct tm *tp;
verbose("DateStamp(0x%x)", v);
(void)time(&temp);
tp = localtime(&temp);
if (tp->tm_isdst)
temp += 60*60;
temp -= TIME_OFFSET;
temp -= timezone;
v[0] = temp / (60*60*24);
temp %= (60*60*24);
v[1] = temp / 60;
v[2] = (temp%60) * TICKS_PER_SECOND;
return v;
}