#include <string.h>
#include <stddef.h>
#include <unistd.h>
+#ifndef __WIN32__
+# include <spawn.h> // posix_spawn
+#endif
#include "request.h"
-#define DEBUG(str, x...) Debug(str, x)
+#define assert(cnd) do{ \
+ if( !(cnd) ) { \
+ fprintf(stderr, "%s:%i - assert failed - " #cnd"\n", __FILE__, __LINE__);\
+ exit(-1); \
+ } \
+}while(0)
#define MAX_FPS 16
// === Types ===
// === IMPORTS ===
+extern int gbSyscallDebugEnabled;
// === GLOBALS ===
FILE *gaSyscall_LocalFPs[MAX_FPS];
break;
// Data (special handling)
case 'd':
- len = va_arg(*Args, int);
+ len = va_arg(*Args, size_t);
str = va_arg(*Args, char*);
// Save the pointer for later
// Create parameter block
Dest->Type = ARG_TYPE_DATA;
- Dest->Length = len;
+ Dest->Length = str ? len : 0;
Dest->Flags = 0;
if( direction & 2 )
Dest->Flags |= ARG_FLAG_RETURN;
// Has data?
if( direction & 1 )
{
- if( DataDest )
+ if( DataDest && str )
memcpy(DataDest, str, len);
}
else
{
va_list args;
int paramCount, dataLength;
- int retCount = 1, retLength = sizeof(uint64_t);
+ int retCount = 2, retLength = sizeof(uint64_t) + sizeof(uint32_t);
void **retPtrs; // Pointers to return buffers
const char *str;
tRequestHeader *req;
req->ClientID = 0; //< Filled later
req->CallID = SyscallID;
req->NParams = paramCount;
+ req->MessageLength = dataLength;
dataPtr = &req->Params[paramCount];
// Fill `output` and `input`
}
va_end(args);
- // Send syscall request
+ // --- Send syscall request
if( SendRequest(req, dataLength, retLength) < 0 ) {
fprintf(stderr, "syscalls.c: SendRequest failed (SyscallID = %i)\n", SyscallID);
exit(127);
}
- // Parse return value
- dataPtr = &req->Params[req->NParams];
- retValue = 0;
- if( req->NParams >= 1 )
- {
- switch(req->Params[0].Type)
- {
- case ARG_TYPE_INT64:
- retValue = *(uint64_t*)dataPtr;
- dataPtr += req->Params[0].Length;
- break;
- case ARG_TYPE_INT32:
- retValue = *(uint32_t*)dataPtr;
- dataPtr += req->Params[0].Length;
- break;
- }
- }
+ dataPtr = (void*)&req->Params[req->NParams];
+ assert(req->NParams >= 2);
+ // return
+ assert(req->Params[0].Type == ARG_TYPE_INT64);
+ assert(req->Params[0].Length == sizeof(uint64_t));
+ retValue = *(uint64_t*)dataPtr;
+ dataPtr += sizeof(uint64_t);
+ // errno
+ assert(req->Params[1].Type == ARG_TYPE_INT32);
+ assert(req->Params[1].Length == sizeof(uint32_t));
+ acess__errno = *(uint32_t*)dataPtr;
+ dataPtr += sizeof(uint32_t);
// Write changes to buffers
+ if( req->NParams - 2 != retCount ) {
+ fprintf(stderr, "syscalls.c: Return count inbalance (%i - 1 != exp %i) [Call %i]\n",
+ req->NParams, retCount, SyscallID);
+ exit(127);
+ }
retCount = 0;
- for( i = 1; i < req->NParams; i ++ )
+ for( i = 2; i < req->NParams; i ++ )
{
#if 0
int j;
printf(" %02x", ((uint8_t*)dataPtr)[j]);
printf("\n");
#endif
+ assert( req->Params[i].Type == ARG_TYPE_DATA );
memcpy( retPtrs[retCount++], dataPtr, req->Params[i].Length );
dataPtr += req->Params[i].Length;
}
free( req );
free( retPtrs );
- DEBUG(": %llx", retValue);
+ if( gbSyscallDebugEnabled ) {
+ SYSTRACE(": %i 0x%llx", SyscallID, retValue);
+ }
return retValue;
}
return ftell( gaSyscall_LocalFPs[FD] );
}
-int native_execve(const char *filename, char *const argv[], char *const envp[])
+int native_execve(const char *filename, const char *const argv[], const char *const envp[])
{
int ret;
- ret = execve(filename, argv, envp);
+ ret = execve(filename, (void*)argv, (void*)envp);
perror("native_execve");
return ret;
}
+
+int native_spawn(const char *filename, const char *const argv[], const char *const envp[])
+{
+ int rv;
+
+ fprintf(stderr, "native_spawn('%s')\n", filename);
+
+ #if __WIN32__
+ rv = _spawnve(_P_NOWAIT, filename, argv, envp);
+ #else
+ rv = posix_spawn(NULL, filename, NULL, NULL, (void*)argv, (void*)envp);
+ #endif
+
+ if( rv == 0 ) {
+ perror("native_spawn");
+ }
+
+ return rv;
+}