diff options
author | Andy Broad <andy@broad.ology.org.uk> | 2015-08-19 10:01:39 -0400 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2015-09-05 11:12:43 -0400 |
commit | a83a2cd160a98d16a60ee6d26a258a3e2bd61429 (patch) | |
tree | 2a93df0d5c93902f2d9e01d8ae7b53736f8ae185 /amigaos4/amigaos.c | |
parent | 218f8ee698859922a48120560577b709375ad149 (diff) | |
download | perl-a83a2cd160a98d16a60ee6d26a258a3e2bd61429.tar.gz |
amigaos4: add amigaos the glue code
amigaos.c: pure amigaos code
amigaio.c: bridge code between perl and amigaos
Diffstat (limited to 'amigaos4/amigaos.c')
-rw-r--r-- | amigaos4/amigaos.c | 1056 |
1 files changed, 1056 insertions, 0 deletions
diff --git a/amigaos4/amigaos.c b/amigaos4/amigaos.c new file mode 100644 index 0000000000..12fb577b70 --- /dev/null +++ b/amigaos4/amigaos.c @@ -0,0 +1,1056 @@ +/* amigaos.c uses only amigaos APIs, + * as opposed to amigaio.c which mixes amigaos and perl APIs */ + +#include <string.h> + +#include <sys/stat.h> +#include <unistd.h> +#include <assert.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#if defined(__CLIB2__) +# include <dos.h> +#endif +#if defined(__NEWLIB__) +# include <amiga_platform.h> +#endif +#include <fcntl.h> +#include <ctype.h> +#include <stdarg.h> + +#include <dos/dos.h> +#include <proto/dos.h> +#include <proto/exec.h> +#include <proto/utility.h> + +#include "amigaos.h" + +struct UtilityIFace *IUtility = NULL; + +/***************************************************************************/ + +struct Interface *OpenInterface(CONST_STRPTR libname, uint32 libver) +{ + struct Library *base = IExec->OpenLibrary(libname, libver); + struct Interface *iface = IExec->GetInterface(base, "main", 1, NULL); + if (iface == NULL) + { + // We should probably post some kind of error message here. + + IExec->CloseLibrary(base); + } + + return iface; +} + +/***************************************************************************/ + +void CloseInterface(struct Interface *iface) +{ + if (iface != NULL) + { + struct Library *base = iface->Data.LibBase; + IExec->DropInterface(iface); + IExec->CloseLibrary(base); + } +} + +BOOL __unlink_retries = FALSE; + +void ___makeenviron() __attribute__((constructor)); +void ___freeenviron() __attribute__((destructor)); + +void ___openinterfaces() __attribute__((constructor)); +void ___closeinterfaces() __attribute__((destructor)); + +void ___openinterfaces() +{ + if (!IDOS) + IDOS = (struct DOSIFace *)OpenInterface("dos.library", 53); + if (!IUtility) + IUtility = + (struct UtilityIFace *)OpenInterface("utility.library", 53); +} + +void ___closeinterfaces() +{ + CloseInterface((struct Interface *)IDOS); + CloseInterface((struct Interface *)IUtility); +} +int VARARGS68K araddebug(UBYTE *fmt, ...); +int VARARGS68K adebug(UBYTE *fmt, ...); + +#define __USE_RUNCOMMAND__ + +char **myenviron = NULL; +char **origenviron = NULL; + +int myexecve(const char *path, char *argv[], char *envp[]); +static void createvars(char **envp); + +struct args +{ + BPTR seglist; + int stack; + char *command; + int length; + int result; + char **envp; +}; + +int __myrc(char *arg) +{ + struct Task *thisTask = IExec->FindTask(0); + struct args *myargs = (struct args *)thisTask->tc_UserData; + if (myargs->envp) + createvars(myargs->envp); + // adebug("%s %ld %s \n",__FUNCTION__,__LINE__,myargs->command); + myargs->result = IDOS->RunCommand(myargs->seglist, myargs->stack, + myargs->command, myargs->length); + return 0; +} + +int32 myruncommand( + BPTR seglist, int stack, char *command, int length, char **envp) +{ + struct args myargs; + struct Task *thisTask = IExec->FindTask(0); + struct Process *proc; + + // adebug("%s %ld %s\n",__FUNCTION__,__LINE__,command?command:"NULL"); + + myargs.seglist = seglist; + myargs.stack = stack; + myargs.command = command; + myargs.length = length; + myargs.result = -1; + myargs.envp = envp; + + if ((proc = IDOS->CreateNewProcTags( + NP_Entry, __myrc, NP_Child, TRUE, NP_Input, IDOS->Input(), + NP_Output, IDOS->Output(), NP_Error, IDOS->ErrorOutput(), + NP_CloseInput, FALSE, NP_CloseOutput, FALSE, NP_CloseError, + FALSE, NP_CopyVars, FALSE, + + // NP_StackSize, ((struct Process + // *)myargs.parent)->pr_StackSize, + NP_Cli, TRUE, NP_UserData, (int)&myargs, + NP_NotifyOnDeathSigTask, thisTask, TAG_DONE))) + + { + IExec->Wait(SIGF_CHILD); + } + return myargs.result; +} + +static char *mystrdup(const char *s) +{ + char *result = NULL; + size_t size; + + size = strlen(s) + 1; + + if ((result = (char *)IExec->AllocVec(size, MEMF_ANY))) + { + memmove(result, s, size); + } + return result; +} + +static int pipenum = 0; + +int pipe(int filedes[2]) +{ + char pipe_name[1024]; + +// adebug("%s %ld \n",__FUNCTION__,__LINE__); +#ifdef USE_TEMPFILES + sprintf(pipe_name, "/T/%x.%08lx", pipenum++, IUtility->GetUniqueID()); +#else + sprintf(pipe_name, "/PIPE/%x%08lx/4096/0", pipenum++, + IUtility->GetUniqueID()); +#endif + + /* printf("pipe: %s \n", pipe_name);*/ + + filedes[1] = open(pipe_name, O_WRONLY | O_CREAT); + filedes[0] = open(pipe_name, O_RDONLY); + if (filedes[0] == -1 || filedes[1] == -1) + { + if (filedes[0] != -1) + close(filedes[0]); + if (filedes[1] != -1) + close(filedes[1]); + return -1; + } + /* printf("filedes %d %d\n", filedes[0], + * filedes[1]);fflush(stdout);*/ + + return 0; +} + +int fork(void) +{ + fprintf(stderr, "Can not bloody fork\n"); + errno = ENOMEM; + return -1; +} + +int wait(int *status) +{ + fprintf(stderr, "No wait try waitpid instead\n"); + errno = ECHILD; + return -1; +} + +char *convert_path_a2u(const char *filename) +{ + struct NameTranslationInfo nti; + + if (!filename) + { + return 0; + } + + __translate_amiga_to_unix_path_name(&filename, &nti); + + return mystrdup(filename); +} +char *convert_path_u2a(const char *filename) +{ + struct NameTranslationInfo nti; + + if (!filename) + { + return 0; + } + + if (strcmp(filename, "/dev/tty") == 0) + { + return mystrdup("CONSOLE:"); + ; + } + + __translate_unix_to_amiga_path_name(&filename, &nti); + + return mystrdup(filename); +} + +static struct SignalSemaphore environ_sema; + +void amigaos4_init_environ_sema() { IExec->InitSemaphore(&environ_sema); } + +void amigaos4_obtain_environ() { IExec->ObtainSemaphore(&environ_sema); } + +void amigaos4_release_environ() { IExec->ReleaseSemaphore(&environ_sema); } + +static void createvars(char **envp) +{ + if (envp) + { + /* Set a local var to indicate to any subsequent sh that it is + * not + * the top level shell and so should only inherit local amigaos + * vars */ + IDOS->SetVar("ABCSH_IMPORT_LOCAL", "TRUE", 5, GVF_LOCAL_ONLY); + + amigaos4_obtain_environ(); + + envp = myenviron; + + while ((envp != NULL) && (*envp != NULL)) + { + int len; + char *var; + char *val; + if ((len = strlen(*envp))) + { + if ((var = (char *)IExec->AllocVec( + len + 1, MEMF_ANY | MEMF_CLEAR))) + { + strcpy(var, *envp); + + val = strchr(var, '='); + if (val) + { + *val++ = '\0'; + if (*val) + { + IDOS->SetVar( + var, val, + strlen(val) + 1, + GVF_LOCAL_ONLY); + } + } + IExec->FreeVec(var); + } + } + envp++; + } + amigaos4_release_environ(); + } +} + +static BOOL contains_whitespace(char *string) +{ + + if (string) + { + + if (strchr(string, ' ')) + return TRUE; + if (strchr(string, '\t')) + return TRUE; + if (strchr(string, '\n')) + return TRUE; + if (strchr(string, 0xA0)) + return TRUE; + if (strchr(string, '"')) + return TRUE; + } + return FALSE; +} + +static int no_of_escapes(char *string) +{ + int cnt = 0; + char *p; + for (p = string; p < string + strlen(string); p++) + { + if (*p == '"') + cnt++; + if (*p == '*') + cnt++; + if (*p == '\n') + cnt++; + if (*p == '\t') + cnt++; + } + return cnt; +} + +struct command_data +{ + STRPTR args; + BPTR seglist; + struct Task *parent; +}; + +int myexecvp(const char *filename, char *argv[]) +{ + // adebug("%s %ld + //%s\n",__FUNCTION__,__LINE__,filename?filename:"NULL"); + /* if there's a slash or a colon consider filename a path and skip + * search */ + int res; + if ((strchr(filename, '/') == NULL) && (strchr(filename, ':') == NULL)) + { + char *path; + char *name; + char *pathpart; + char *p; + size_t len; + struct stat st; + + if (!(path = getenv("PATH"))) + { + path = ".:/bin:/usr/bin:/c"; + } + + len = strlen(filename) + 1; + name = (char *)alloca(strlen(path) + len); + pathpart = (char *)alloca(strlen(path) + 1); + p = path; + do + { + path = p; + + if (!(p = strchr(path, ':'))) + { + p = strchr(path, '\0'); + } + + memcpy(pathpart, path, p - path); + pathpart[p - path] = '\0'; + if (!(strlen(pathpart) == 0)) + { + sprintf(name, "%s/%s", pathpart, filename); + } + else + sprintf(name, "%s", filename); + + if ((stat(name, &st) == 0) && (S_ISREG(st.st_mode))) + { + /* we stated it and it's a regular file */ + /* let's boogie! */ + filename = name; + break; + } + + } while (*p++ != '\0'); + } + res = myexecve(filename, argv, myenviron); + return res; +} + +int myexecv(const char *path, char *argv[]) +{ + return myexecve(path, argv, myenviron); +} + +int myexecl(const char *path, ...) +{ + va_list va; + char *argv[1024]; /* 1024 enough? let's hope so! */ + int i = 0; + // adebug("%s %ld\n",__FUNCTION__,__LINE__); + + va_start(va, path); + i = 0; + + do + { + argv[i] = va_arg(va, char *); + } while (argv[i++] != NULL); + + va_end(va); + return myexecve(path, argv, myenviron); +} + +int myexecve(const char *filename, char *argv[], char *envp[]) +{ + FILE *fh; + char buffer[1000]; + int size = 0; + char **cur; + char *interpreter = 0; + char *interpreter_args = 0; + char *full = 0; + char *filename_conv = 0; + char *interpreter_conv = 0; + // char *tmp = 0; + char *fname; + // int tmpint; + // struct Task *thisTask = IExec->FindTask(0); + int result = -1; + + // adebug("%s %ld %s\n",__FUNCTION__,__LINE__,filename?filename:"NULL"); + + /* Calculate the size of filename and all args, including spaces and + * quotes */ + size = 0; // strlen(filename) + 1; + for (cur = (char **)argv /* +1 */; *cur; cur++) + { + size += + strlen(*cur) + 1 + + (contains_whitespace(*cur) ? (2 + no_of_escapes(*cur)) : 0); + } + /* Check if it's a script file */ + + fh = fopen(filename, "r"); + if (fh) + { + if (fgetc(fh) == '#' && fgetc(fh) == '!') + { + char *p; + char *q; + fgets(buffer, 999, fh); + p = buffer; + while (*p == ' ' || *p == '\t') + p++; + if (buffer[strlen(buffer) - 1] == '\n') + buffer[strlen(buffer) - 1] = '\0'; + if ((q = strchr(p, ' '))) + { + *q++ = '\0'; + if (*q != '\0') + { + interpreter_args = mystrdup(q); + } + } + else + interpreter_args = mystrdup(""); + + interpreter = mystrdup(p); + size += strlen(interpreter) + 1; + size += strlen(interpreter_args) + 1; + } + + fclose(fh); + } + else + { + /* We couldn't open this why not? */ + if (errno == ENOENT) + { + /* file didn't exist! */ + return -1; + } + } + + /* Allocate the command line */ + filename_conv = convert_path_u2a(filename); + + if (filename_conv) + size += strlen(filename_conv); + size += 1; + full = (char *)IExec->AllocVec(size + 10, MEMF_ANY | MEMF_CLEAR); + if (full) + { + if (interpreter) + { + interpreter_conv = convert_path_u2a(interpreter); +#if !defined(__USE_RUNCOMMAND__) +#warning(using system!) + sprintf(full, "%s %s %s ", interpreter_conv, + interpreter_args, filename_conv); +#else + sprintf(full, "%s %s ", interpreter_args, + filename_conv); +#endif + IExec->FreeVec(interpreter); + IExec->FreeVec(interpreter_args); + + if (filename_conv) + IExec->FreeVec(filename_conv); + fname = mystrdup(interpreter_conv); + + if (interpreter_conv) + IExec->FreeVec(interpreter_conv); + } + else + { +#ifndef __USE_RUNCOMMAND__ + sprintf(full, "%s ", filename_conv); +#else + sprintf(full, ""); +#endif + fname = mystrdup(filename_conv); + if (filename_conv) + IExec->FreeVec(filename_conv); + } + + for (cur = (char **)(argv + 1); *cur != 0; cur++) + { + if (contains_whitespace(*cur)) + { + int esc = no_of_escapes(*cur); + + if (esc > 0) + { + char *buff = IExec->AllocVec( + strlen(*cur) + 4 + esc, + MEMF_ANY | MEMF_CLEAR); + char *p = *cur; + char *q = buff; + + *q++ = '"'; + while (*p != '\0') + { + + if (*p == '\n') + { + *q++ = '*'; + *q++ = 'N'; + p++; + continue; + } + else if (*p == '"') + { + *q++ = '*'; + *q++ = '"'; + p++; + continue; + } + else if (*p == '*') + { + *q++ = '*'; + } + *q++ = *p++; + } + *q++ = '"'; + *q++ = ' '; + *q = '\0'; + strcat(full, buff); + IExec->FreeVec(buff); + } + else + { + strcat(full, "\""); + strcat(full, *cur); + strcat(full, "\" "); + } + } + else + { + strcat(full, *cur); + strcat(full, " "); + } + } + strcat(full, "\n"); + +// if(envp) +// createvars(envp); + +#ifndef __USE_RUNCOMMAND__ + result = IDOS->SystemTags( + full, SYS_UserShell, TRUE, NP_StackSize, + ((struct Process *)thisTask)->pr_StackSize, SYS_Input, + ((struct Process *)thisTask)->pr_CIS, SYS_Output, + ((struct Process *)thisTask)->pr_COS, SYS_Error, + ((struct Process *)thisTask)->pr_CES, TAG_DONE); +#else + + if (fname) + { + BPTR seglist = IDOS->LoadSeg(fname); + if (seglist) + { + /* check if we have an executable! */ + struct PseudoSegList *ps = NULL; + if (!IDOS->GetSegListInfoTags( + seglist, GSLI_Native, &ps, TAG_DONE)) + { + IDOS->GetSegListInfoTags( + seglist, GSLI_68KPS, &ps, TAG_DONE); + } + if (ps != NULL) + { + // adebug("%s %ld %s + // %s\n",__FUNCTION__,__LINE__,fname,full); + IDOS->SetCliProgramName(fname); + // result=RunCommand(seglist,8*1024,full,strlen(full)); + // result=myruncommand(seglist,8*1024,full,strlen(full),envp); + result = myruncommand(seglist, 8 * 1024, + full, -1, envp); + errno = 0; + } + else + { + errno = ENOEXEC; + } + IDOS->UnLoadSeg(seglist); + } + else + { + errno = ENOEXEC; + } + IExec->FreeVec(fname); + } + +#endif /* USE_RUNCOMMAND */ + + IExec->FreeVec(full); + if (errno == ENOEXEC) + return -1; + return result; + } + + if (interpreter) + IExec->FreeVec(interpreter); + if (filename_conv) + IExec->FreeVec(filename_conv); + + errno = ENOMEM; + + return -1; +} + +int pause(void) +{ + fprintf(stderr, "Pause not implemented\n"); + + errno = EINTR; + return -1; +} + +uint32 size_env(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message) +{ + if (strlen(message->sv_GDir) <= 4) + { + hook->h_Data = (APTR)(((uint32)hook->h_Data) + 1); + } + return 0; +} + +uint32 copy_env(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message) +{ + if (strlen(message->sv_GDir) <= 4) + { + char **env = (char **)hook->h_Data; + uint32 size = + strlen(message->sv_Name) + 1 + message->sv_VarLen + 1 + 1; + char *buffer = (char *)IExec->AllocVec((uint32)size, + MEMF_ANY | MEMF_CLEAR); + + snprintf(buffer, size - 1, "%s=%s", message->sv_Name, + message->sv_Var); + + *env = buffer; + env++; + hook->h_Data = env; + } + return 0; +} + +void ___makeenviron() +{ + struct Hook hook; + + char varbuf[8]; + uint32 flags = 0; + + struct DOSIFace *myIDOS = + (struct DOSIFace *)OpenInterface("dos.library", 53); + if (myIDOS) + { + if (myIDOS->GetVar("ABCSH_IMPORT_LOCAL", varbuf, 8, + GVF_LOCAL_ONLY) > 0) + { + flags = GVF_LOCAL_ONLY; + } + else + { + flags = GVF_GLOBAL_ONLY; + } + + hook.h_Entry = size_env; + hook.h_Data = 0; + + myIDOS->ScanVars(&hook, flags, 0); + hook.h_Data = (APTR)(((uint32)hook.h_Data) + 1); + + myenviron = (char **)IExec->AllocVec((uint32)hook.h_Data * + sizeof(char **), + MEMF_ANY | MEMF_CLEAR); + origenviron = myenviron; + if (!myenviron) + { + return; + } + hook.h_Entry = copy_env; + hook.h_Data = myenviron; + + myIDOS->ScanVars(&hook, flags, 0); + CloseInterface((struct Interface *)myIDOS); + } +} + +void ___freeenviron() +{ + char **i; + /* perl might change environ, it puts it back except for ctrl-c */ + /* so restore our own copy here */ + struct DOSIFace *myIDOS = + (struct DOSIFace *)OpenInterface("dos.library", 53); + if (myIDOS) + { + myenviron = origenviron; + + if (myenviron) + { + for (i = myenviron; *i != NULL; i++) + { + IExec->FreeVec(*i); + } + IExec->FreeVec(myenviron); + myenviron = NULL; + } + CloseInterface((struct Interface *)myIDOS); + } +} + +/* reimplementation of popen, clib2's doesn't do all we want */ + +static BOOL is_final_quote_character(const char *str) +{ + BOOL result; + + result = (BOOL)(str[0] == '\"' && (str[1] == '\0' || isspace(str[1]))); + + return (result); +} + +static BOOL is_final_squote_character(const char *str) +{ + BOOL result; + + result = (BOOL)(str[0] == '\'' && (str[1] == '\0' || isspace(str[1]))); + + return (result); +} + +int popen_child() +{ + struct Task *thisTask = IExec->FindTask(0); + + char *command = (char *)thisTask->tc_UserData; + size_t len; + char *str; + int argc; + int number_of_arguments; + char *argv[4]; + + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = command ? command : NULL; + argv[3] = NULL; + + // adebug("%s %ld %s\n",__FUNCTION__,__LINE__,command?command:"NULL"); + + /* We need to give this to sh via execvp, execvp expects filename, + * argv[] + */ + + myexecvp(argv[0], argv); + if (command) + IExec->FreeVec(command); + + IExec->Forbid(); + return 0; +} + +FILE *amigaos_popen(const char *cmd, const char *mode) +{ + FILE *result = NULL; + char pipe_name[50]; + char unix_pipe[50]; + char ami_pipe[50]; + char *cmd_copy; + BPTR input = 0; + BPTR output = 0; + struct Process *proc = NULL; + struct Task *thisTask = IExec->FindTask(0); + + /* First we need to check the mode + * We can only have unidirectional pipes + */ + // adebug("%s %ld cmd %s mode %s \n",__FUNCTION__,__LINE__,cmd, + // mode); + + switch (mode[0]) + { + case 'r': + case 'w': + break; + + default: + + errno = EINVAL; + return result; + } + + /* Make a unique pipe name + * we need a unix one and an amigaos version (of the same pipe!) + * as were linking with libunix. + */ + + sprintf(pipe_name, "%x%08lx/4096/0", pipenum++, + IUtility->GetUniqueID()); + sprintf(unix_pipe, "/PIPE/%s", pipe_name); + sprintf(ami_pipe, "PIPE:%s", pipe_name); + + /* Now we open the AmigaOs Filehandles That we wil pass to our + * Sub process + */ + + if (mode[0] == 'r') + { + /* A read mode pipe: Output from pipe input from NIL:*/ + input = IDOS->Open("NIL:", MODE_NEWFILE); + if (input != 0) + { + output = IDOS->Open(ami_pipe, MODE_NEWFILE); + } + } + else + { + + input = IDOS->Open(ami_pipe, MODE_NEWFILE); + if (input != 0) + { + output = IDOS->Open("NIL:", MODE_NEWFILE); + } + } + if ((input == 0) || (output == 0)) + { + /* Ouch stream opening failed */ + /* Close and bail */ + if (input) + IDOS->Close(input); + if (output) + IDOS->Close(output); + return result; + } + + /* We have our streams now start our new process + * We're using a new process so that execve can modify the environment + * with messing things up for the shell that launched perl + * Copy cmd before we launch the subprocess as perl seems to waste + * no time in overwriting it! The subprocess will free the copy. + */ + + if ((cmd_copy = mystrdup(cmd))) + { + // adebug("%s %ld + // %s\n",__FUNCTION__,__LINE__,cmd_copy?cmd_copy:"NULL"); + proc = IDOS->CreateNewProcTags( + NP_Entry, popen_child, NP_Child, TRUE, NP_StackSize, + ((struct Process *)thisTask)->pr_StackSize, NP_Input, input, + NP_Output, output, NP_Error, IDOS->ErrorOutput(), + NP_CloseError, FALSE, NP_Cli, TRUE, NP_Name, + "Perl: popen process", NP_UserData, (int)cmd_copy, + TAG_DONE); + } + if (!proc) + { + /* New Process Failed to start + * Close and bail out + */ + if (input) + IDOS->Close(input); + if (output) + IDOS->Close(output); + if (cmd_copy) + IExec->FreeVec(cmd_copy); + } + + /* Our new process is running and will close it streams etc + * once its done. All we need to is open the pipe via stdio + */ + + return fopen(unix_pipe, mode); +} + +/* Work arround for clib2 fstat */ +#ifndef S_IFCHR +#define S_IFCHR 0x0020000 +#endif + +#define SET_FLAG(u, v) ((void)((u) |= (v))) + +int afstat(int fd, struct stat *statb) +{ + int result; + BPTR fh; + int mode; + BOOL input; + /* In the first instance pass it to fstat */ + // adebug("fd %ld ad %ld\n",fd,amigaos_get_file(fd)); + + if ((result = fstat(fd, statb) >= 0)) + return result; + +/* Now we've got a file descriptor but we failed to stat it */ +/* Could be a nil: or could be a std#? */ + +/* if get_default_file fails we had a dud fd so return failure */ +#if !defined(__CLIB2__) + + fh = amigaos_get_file(fd); + + /* if nil: return failure*/ + if (fh == 0) + return -1; + + /* Now compare with our process Input() Output() etc */ + /* if these were regular files sockets or pipes we had already + * succeeded */ + /* so we can guess they a character special console.... I hope */ + + struct ExamineData *data; + char name[120]; + name[0] = '\0'; + + data = IDOS->ExamineObjectTags(EX_FileHandleInput, fh, TAG_END); + if (data != NULL) + { + + IUtility->Strlcpy(name, data->Name, sizeof(name)); + + IDOS->FreeDosObject(DOS_EXAMINEDATA, data); + } + + // adebug("ad %ld '%s'\n",amigaos_get_file(fd),name); + mode = S_IFCHR; + + if (fh == IDOS->Input()) + { + input = TRUE; + SET_FLAG(mode, S_IRUSR); + SET_FLAG(mode, S_IRGRP); + SET_FLAG(mode, S_IROTH); + } + else if (fh == IDOS->Output() || fh == IDOS->ErrorOutput()) + { + input = FALSE; + SET_FLAG(mode, S_IWUSR); + SET_FLAG(mode, S_IWGRP); + SET_FLAG(mode, S_IWOTH); + } + else + { + /* we got a filehandle not handle by fstat or the above */ + /* most likely it's NIL: but lets check */ + struct ExamineData *exd = NULL; + if ((exd = IDOS->ExamineObjectTags(EX_FileHandleInput, fh, + TAG_DONE))) + { + BOOL isnil = FALSE; + if (exd->Type == + (20060920)) // Ugh yes I know nasty..... + { + isnil = TRUE; + } + IDOS->FreeDosObject(DOS_EXAMINEDATA, exd); + if (isnil) + { + /* yep we got NIL: */ + SET_FLAG(mode, S_IRUSR); + SET_FLAG(mode, S_IRGRP); + SET_FLAG(mode, S_IROTH); + SET_FLAG(mode, S_IWUSR); + SET_FLAG(mode, S_IWGRP); + SET_FLAG(mode, S_IWOTH); + } + else + { + IExec->DebugPrintF( + "unhandled filehandle in afstat()\n"); + return -1; + } + } + } + + memset(statb, 0, sizeof(statb)); + + statb->st_mode = mode; + +#endif + return 0; +} + +BPTR amigaos_get_file(int fd) +{ + BPTR fh = (BPTR)NULL; + if (!(fh = _get_osfhandle(fd))) + { + switch (fd) + { + case 0: + fh = IDOS->Input(); + break; + case 1: + fh = IDOS->Output(); + break; + case 2: + fh = IDOS->ErrorOutput(); + break; + default: + break; + } + } + return fh; +} |