libnx/nx/source/runtime/argv.c
2018-01-20 19:37:11 +01:00

117 lines
2.8 KiB
C

#include <switch.h>
#include <string.h>
#include <ctype.h>
// System globals we define here
int __system_argc;
char** __system_argv;
extern char* fake_heap_start;
extern char* fake_heap_end;
extern u32 __argdata__;
void argvSetup(void)
{
Result rc=0;
MemoryInfo meminfo;
u32 pageinfo=0;
u8 *argdata = (u8*)&__argdata__;
u32 *arg32 = (u32*)argdata;
u32 argdata_allocsize;
u32 argdata_strsize;
u32 argvptr_pos;
u32 max_argv;
u32 argi;
u32 arglen=0;
bool quote_flag=0;
bool end_flag=0;
char *args;
char *argstart;
char *argstorage;
__system_argc = 0;
__system_argv = NULL;
rc = svcQueryMemory(&meminfo, &pageinfo, (u64)argdata);
// TODO: Use envHasArgv() here.
// This memory is only mapped when arguments were passed.
if (R_FAILED(rc) || meminfo.perm != 0x3)
return;
argdata_allocsize = arg32[0];
argdata_strsize = arg32[1];
args = (char*)&argdata[0x20];
if (argdata_allocsize==0 || argdata_strsize==0) return;
argvptr_pos = 0x20 + argdata_strsize+1;
if (argvptr_pos >= argdata_allocsize) return;
argstorage = (char*)&argdata[argvptr_pos];
argvptr_pos += (argdata_strsize+1 + 0x9) & ~0x7;
if (argvptr_pos >= argdata_allocsize) return;
max_argv = (argdata_allocsize - argvptr_pos) >> 3;
if (max_argv < 2) return;
__system_argv = (char**)&argdata[argvptr_pos];
argstart = NULL;
for(argi=0; argi<argdata_strsize; argi++) {
if (argstart == NULL && isspace(args[argi])) continue;
if (argstart == NULL) {
if (args[argi] == '"') {
argstart = &args[argi+1];
quote_flag = 1;
}
else if(args[argi]!=0) {
argstart = &args[argi];
arglen++;
}
}
else {
end_flag = 0;
if (quote_flag && args[argi] == '"') {
end_flag = 1;
}
else if (isspace(args[argi])) {
end_flag = 1;
}
else if(args[argi]!=0) {
arglen++;
}
if ((args[argi]==0 || end_flag) && arglen) {
strncpy(argstorage, argstart, arglen);
argstorage[arglen] = 0;
__system_argv[__system_argc] = argstorage;
__system_argc++;
argstart = NULL;
quote_flag = 0;
argstorage+= arglen+1;
arglen = 0;
if (__system_argc >= max_argv) break;
}
}
}
if (arglen && __system_argc < max_argv) {
strncpy(argstorage, argstart, arglen);
argstorage[arglen] = 0;
__system_argv[__system_argc] = argstorage;
__system_argc++;
}
__system_argv[__system_argc] = NULL;
}