// We extract the list of open modules for a process by parsing out the // /proc/<pid>/maps // File. This lists all the files mapped into the processes memory space. bool MCSystemListProcessModules(uint32_t p_process_id, MCSystemListProcessModulesCallback p_callback, void *p_context) { char t_maps_file[6 + I4L + 5 + 1]; sprintf(t_maps_file, "/proc/%u/maps", p_process_id); FILE *t_stream; t_stream = fopen(t_maps_file, "r"); if (t_stream == nil) return false; bool t_success; t_success = true; // Each line is of a fixed format, with any module path appearing at '/'. // Modules are repeated in the map for each segment that is mapped in. Thus // we only report the first appearance, and assume that they are always // consecutive. char t_last_module[4096]; t_last_module[0] = '\0'; while(t_success) { char t_line[4096]; if (fgets(t_line, 4096, t_stream) == nil) break; // See if there is a module path char *t_path; t_path = strchr(t_line, '/'); if (t_path == nil) continue; // See if it is a shared library (terminated by .so, or containing .so.) if (!MCCStringEndsWith(t_path, ".so") || !MCCStringContains(t_path, ".so.") || MCCStringEqual(t_path, t_last_module)) continue; MCAutoStringRef t_path_str; /* UNCHECKED */ MCStringCreateWithSysString(t_path, &t_path_str); t_success = p_callback(p_context, *t_path_str); } fclose(t_stream); return t_success; }
int platform_main(int argc, char *argv[], char *envp[]) { // On Linux, the argv and envp could be in pretty much any format. The // safest thing to do is let the C library's iconv convert to a known // format. To do this, the system locale needs to be retrieved. setlocale(LC_ALL, ""); MCsysencoding = strclone(nl_langinfo(CODESET)); if (!MCInitialize()) { fprintf(stderr, "Fatal: initialization failed\n"); exit(-1); } if (!MCSInitialize()) { fprintf(stderr, "Fatal: platform initialization failed\n"); exit(-1); } if (!MCScriptInitialize()) { fprintf(stderr, "Fatal: script initialization failed\n"); exit(-1); } // Linux needs the platform layer to be initialised early so that it can // use it to load the weakly-linked dynamic libraries that the engine // depends on. MCS_preinit(); // Core initialisation complete; // This depends on libFoundation and MCsystem being initialised first initialise_required_weak_link_glib(); // Convert the argv array to StringRefs MCAutoStringRefArray t_argv; /* UNCHECKED */ t_argv.New(argc); for (int i = 0; i < argc; i++) { /* UNCHECKED */ MCStringCreateWithSysString(argv[i], t_argv[i]); } // Convert the envp array to StringRefs int envc = 0; while (envp[envc] != nullptr) ++envc; MCAutoStringRefArray t_envp; /* UNCHECKED */ t_envp.New(envc + 1); for (int i = 0; envp[i] != nullptr; ++i) { /* UNCHECKED */ MCStringCreateWithSysString(envp[i], t_envp[i]); } // Terminate the envp array t_envp[envc] = nil; extern int MCSystemElevatedMain(int, char* argv[]); if (argc == 3&& strcmp(argv[1], "-elevated-slave") == 0) return MCSystemElevatedMain(argc, argv); struct X_init_options t_options; t_options.argc = argc; t_options.argv = *t_argv; t_options.envp = *t_envp; t_options.app_code_path = nullptr; if (!X_init(t_options)) { // Try to print an informative error message or, failing that, just // report that an error occurred. if (MCresult != nil) { MCExecContext ctxt(nil, nil, nil); MCAutoValueRef t_result; MCAutoStringRef t_string; MCresult -> eval(ctxt, &t_result); ctxt . ConvertToString(*t_result, &t_string); MCAutoStringRefAsSysString t_autostring; /* UNCHECKED */ t_autostring . Lock(*t_string); fprintf(stderr, "Startup error - %s\n", *t_autostring); } else { fprintf(stderr, "Fatal: unknown startup error\n"); } exit(-1); } X_main_loop(); int t_exit_code = X_close(); MCScriptFinalize(); MCFinalize(); exit(t_exit_code); }
// This call is primarily designed to be used by the plugin installer. As this // is generally installed 'per-user', we simply scan '/proc' for processes owned // by the calling user. bool MCSystemListProcesses(MCSystemListProcessesCallback p_callback, void* p_context) { bool t_success; t_success = true; DIR *t_dir; t_dir = nil; if (t_success) { t_dir = opendir("/proc"); if (t_dir == nil) t_success = false; } if (t_success) { dirent *t_entry; while(t_success) { // Fetch the next entry t_entry = readdir(t_dir); if (t_entry == nil) break; // Work out if the entry is a process id int32_t t_pid; MCAutoStringRef t_dname; /* UNCHECKED */ MCStringCreateWithCString(t_entry -> d_name, &t_dname); if (!MCU_strtol(*t_dname, t_pid)) continue; // Work out the full path ("/proc/<int>") and stat so we can // check ownership. char t_path[6 + I4L + 1]; struct stat64 t_stat; sprintf(t_path, "/proc/%u", t_pid); stat64(t_path, &t_stat); if (t_stat . st_uid != getuid()) continue; // We have a viable process to report. First fetch its path MCAutoStringRef t_exe_link, t_exe_path; /* UNCHECKED */ MCStringFormat(&t_exe_link, "/proc/%u/exe", t_pid); if (!MCS_resolvepath(*t_exe_link, &t_exe_path)) { t_success = false; break; } // Next fetch its 'description' from the first line of the status // file. char t_status_file[6 + I4L + 7 + 1]; char t_status[256]; FILE *t_stream; sprintf(t_status_file, "/proc/%u/status", t_pid); t_stream = fopen(t_status_file, "r"); if (t_stream != nil) { if (fgets(t_status, 256, t_stream) != nil) { char *t_tab; t_tab = strchr(t_status, '\t'); if (t_tab != nil) MCMemoryMove(t_status, t_tab + 1, MCCStringLength(t_tab + 1)); } else t_status[0] = '\0'; fclose(t_stream); } else t_status[0] = '\0'; MCAutoStringRef t_status_str; /* UNCHECKED */ MCStringCreateWithSysString(t_status, &t_status_str); t_success = p_callback(p_context, t_pid, *t_exe_path, *t_status_str); } } if (t_dir != nil) closedir(t_dir); return t_success; }