+struct dev_fd_t emu_interesting_fds[] = {
+ [IFD_SOUND] = { "/dev/dsp", -1, emu_sound_open },
+ { NULL, 0, NULL },
+};
+
+static const struct {
+ const char *from;
+ const char *to;
+} path_map[] = {
+ { "/mnt/tmp", "./tmp" },
+};
+
+static const char *wrap_path(const char *path)
+{
+ char *buff, *p;
+ size_t size;
+ int i, len;
+
+ // do only path mapping for now
+ for (i = 0; i < ARRAY_SIZE(path_map); i++) {
+ p = strstr(path, path_map[i].from);
+ if (p != NULL) {
+ size = strlen(path) + strlen(path_map[i].to) + 1;
+ buff = malloc(size);
+ if (buff == NULL)
+ break;
+ len = p - path;
+ strncpy(buff, path, len);
+ snprintf(buff + len, size - len, "%s%s", path_map[i].to,
+ path + len + strlen(path_map[i].from));
+ dbg("mapped path \"%s\" -> \"%s\"\n", path, buff);
+ return buff;
+ }
+ }
+
+ return path;
+}
+
+static void wrap_path_free(const char *w_path, const char *old_path)
+{
+ if (w_path != old_path)
+ free((void *)w_path);
+}
+
+void *emu_do_fopen(const char *path, const char *mode)
+{
+ const char *w_path;
+ FILE *ret;
+
+ w_path = wrap_path(path);
+ ret = fopen(w_path, mode);
+ wrap_path_free(w_path, path);
+
+ return ret;
+}
+
+// FIXME: threads..
+int emu_do_system(const char *command)
+{
+ static char tmp_path[512];
+ int need_ginge = 0;
+ const char *p2;
+ char *p;
+ int ret;
+
+ if (command == NULL)
+ return -1;
+
+ for (p2 = command; *p2 && isspace(*p2); p2++)
+ ;
+
+ if (*p2 == '.') // relative path?
+ need_ginge = 1;
+ else if (*p2 == '/' && strncmp(p2, "/bin", 4) && strncmp(p2, "/lib", 4)
+ && strncmp(p2, "/sbin", 4) && strncmp(p2, "/usr", 4))
+ // absolute path, but not a system command
+ need_ginge = 1;
+
+ p2 = wrap_path(command);
+ if (need_ginge) {
+ make_local_path(tmp_path, sizeof(tmp_path), "ginge_prep");
+ p = tmp_path + strlen(tmp_path);
+
+ snprintf(p, sizeof(tmp_path) - (p - tmp_path), " --nomenu %s", p2);
+ }
+ else
+ snprintf(tmp_path, sizeof(tmp_path), "%s", p2);
+ wrap_path_free(p2, command);
+
+ dbg("system: \"%s\"\n", tmp_path);
+
+ // the app might want the screen too..
+ fb_thread_pause();
+ ret = system(tmp_path);
+ fb_thread_resume();
+ return ret;
+}
+
+int emu_do_execve(const char *filename, char *const argv[], char *const envp[])
+{
+ const char **new_argv;
+ char *prep_path;
+ int i, ret, argc;
+
+ if (filename == NULL)
+ return -1;
+
+ if (strstr(filename, "/gp2xmenu") != NULL)
+ exit(0);
+
+ for (i = 0; argv[i] != NULL; i++)
+ ;
+ argc = i + 1;
+
+ new_argv = calloc(argc + 2, sizeof(new_argv[0]));
+ if (new_argv == NULL)
+ return -1;
+
+ prep_path = malloc(512);
+ if (prep_path == NULL)
+ return -1;
+
+ make_local_path(prep_path, 512, "ginge_prep");
+ new_argv[0] = prep_path;
+ new_argv[1] = "--nomenu";
+ new_argv[2] = wrap_path(filename);
+
+ if (argv[0] != NULL)
+ for (i = 1; argv[i] != NULL; i++)
+ new_argv[i + 2] = argv[i];
+
+ dbg("execve \"%s\" %s \"%s\"\n", new_argv[0], new_argv[1], new_argv[2]);
+ ret = execve(new_argv[0], (char **)new_argv, envp);
+ perror("execve");
+ return ret;
+}
+
+// vim:shiftwidth=2:expandtab