char * _gst_relocate_path (const char *path) { const char *p; char *s; /* Detect absolute paths. */ #if defined(MSDOS) || defined(WIN32) || defined(__OS2__) if ((path[0] && path[1] == ':') || path[0] == '/' || path[0] == '\\') return xstrdup (path); #else if (path[0] == '/') return xstrdup (path); #endif /* Remove filename from executable path. */ p = _gst_executable_path + strlen (_gst_executable_path); do --p; while (p >= _gst_executable_path && *p != '/' #if defined(MSDOS) || defined(WIN32) || defined(__OS2__) && *p != '\\' #endif ); p++; /* Now p points just past the last separator (if any). */ s = alloca (p - _gst_executable_path + strlen (path) + 1); sprintf (s, "%.*s%s", (int)(p - _gst_executable_path), _gst_executable_path, path); return _gst_get_full_file_name (s); }
/* Store the full pathname of the current executable. */ void _gst_set_executable_path (const char *argv0) { char location[MAX_PATH]; static char location_as_posix_path[2 * MAX_PATH]; int length = GetModuleFileName (NULL, location, sizeof (location)); if (length <= 0) return NULL; /* On Cygwin, we need to convert paths coming from Win32 system calls to the Unix-like slashified notation. There's no error return defined for cygwin_conv_to_posix_path. See cygwin-api/func-cygwin-conv-to-posix-path.html. Does it overflow the buffer of expected size MAX_PATH or does it truncate the path? I don't know. Let's catch both. */ cygwin_conv_to_posix_path (location, location_as_posix_path); location_as_posix_path[MAX_PATH - 1] = '\0'; if (strlen (location_as_posix_path) >= MAX_PATH - 1) /* A sign of buffer overflow or path truncation. */ _gst_executable_path = NULL; else _gst_executable_path = _gst_get_full_file_name (location_as_posix_path); }
int _gst_initialize (const char *kernel_dir, const char *image_file, int flags) { char *currentDirectory = _gst_get_cur_dir_name (); const char *home = getenv ("HOME"); char *str; mst_Boolean loadBinary, abortOnFailure; int rebuild_image_flags = flags & (GST_REBUILD_IMAGE | GST_MAYBE_REBUILD_IMAGE); /* Even though we're nowhere near through initialization, we set this to make sure we don't invoke a callin function which would recursively invoke us. */ _gst_smalltalk_initialized = true; _gst_init_snprintfv (); if (!_gst_executable_path) _gst_executable_path = DEFAULT_EXECUTABLE; /* By default, apply this kludge fpr OSes such as Windows and MS-DOS which have no concept of home directories. */ if (home == NULL) home = xstrdup (currentDirectory); asprintf ((char **) &_gst_user_file_base_path, "%s/%s", home, LOCAL_BASE_DIR_NAME); /* Check that supplied paths are readable. If they're not, fail unless they told us in advance. */ if (kernel_dir && !_gst_file_is_readable (kernel_dir)) { if (flags & GST_IGNORE_BAD_KERNEL_PATH) kernel_dir = NULL; else { _gst_errorf ("kernel path %s not readable", kernel_dir); exit (1); } } /* For the image file, it is okay to find none if we can/should rebuild the image file. */ if (image_file && (flags & (GST_REBUILD_IMAGE | GST_MAYBE_REBUILD_IMAGE)) == 0 && !_gst_file_is_readable (image_file)) { if (flags & GST_IGNORE_BAD_IMAGE_PATH) image_file = NULL; else { _gst_errorf ("Couldn't open image file %s", image_file); exit (1); } } /* The image path can be used as the default kernel path, so we split it anyway into directory+filename. */ if (image_file) { const char *p; /* Compute the actual path of the image file */ p = image_file + strlen (image_file); for (;;) if (*--p == '/' #if defined(MSDOS) || defined(WIN32) || defined(__OS2__) || *p == '\\' #endif ) { char *dirname; int n = p > image_file ? p - image_file : 1; asprintf (&dirname, "%.*s", n, image_file); _gst_image_file_path = dirname; /* Remove path from image_file. */ image_file = p + 1; break; } else if (p == image_file) { _gst_image_file_path = "."; break; } } else { /* No image file given, we use the system default or revert to the current directory. */ str = _gst_relocate_path (IMAGE_PATH); if (_gst_file_is_readable (str)) _gst_image_file_path = str; else { free (str); _gst_image_file_path = xstrdup (currentDirectory); } flags |= GST_IGNORE_BAD_IMAGE_PATH; image_file = "gst.im"; } if (!kernel_dir) { str = _gst_relocate_path (KERNEL_PATH); if (!_gst_file_is_readable (str)) { free (str); asprintf (&str, "%s/kernel", _gst_image_file_path); } kernel_dir = str; } xfree (currentDirectory); /* Uff, we're done with the complicated part. Set variables to mirror what we've decided in the above marathon. */ _gst_image_file_path = _gst_get_full_file_name (_gst_image_file_path); _gst_kernel_file_path = _gst_get_full_file_name (kernel_dir); asprintf (&str, "%s/%s", _gst_image_file_path, image_file); _gst_binary_image_name = str; _gst_smalltalk_passed_argc = smalltalk_argc; _gst_smalltalk_passed_argv = smalltalk_argv; no_user_files = (flags & GST_IGNORE_USER_FILES) != 0; _gst_no_tty = (flags & GST_NO_TTY) != 0 || !isatty (0); site_pre_image_file = _gst_find_file (SITE_PRE_IMAGE_FILE_NAME, GST_DIR_KERNEL_SYSTEM); user_pre_image_file = find_user_file (USER_PRE_IMAGE_FILE_NAME); if (!_gst_regression_testing) user_init_file = find_user_file (USER_INIT_FILE_NAME); else user_init_file = NULL; _gst_init_sysdep (); _gst_init_signals (); _gst_init_event_loop(); _gst_init_cfuncs (); _gst_init_sockets (); _gst_init_primitives (); if (_gst_regression_testing) { _gst_declare_tracing = 0; _gst_execution_tracing = 0; _gst_verbosity = 2; setvbuf (stdout, NULL, _IOLBF, 1024); } if (rebuild_image_flags == 0) loadBinary = abortOnFailure = true; else { loadBinary = (rebuild_image_flags == GST_MAYBE_REBUILD_IMAGE && ok_to_load_binary ()); abortOnFailure = false; /* If we must create a new non-local image, but the directory is not writeable, we must resort to the current directory. In practice this is what happens when a "normal user" puts stuff in his ".st" directory or does "gst -i". */ if (!loadBinary && !_gst_file_is_writeable (_gst_image_file_path) && (flags & GST_IGNORE_BAD_IMAGE_PATH)) { _gst_image_file_path = _gst_get_cur_dir_name (); asprintf (&str, "%s/gst.im", _gst_image_file_path); _gst_binary_image_name = str; loadBinary = (rebuild_image_flags == GST_MAYBE_REBUILD_IMAGE && ok_to_load_binary ()); } } if (loadBinary && _gst_load_from_file (_gst_binary_image_name)) { _gst_init_interpreter (); _gst_init_vmproxy (); } else if (abortOnFailure) { _gst_errorf ("Couldn't load image file %s", _gst_binary_image_name); return 1; } else { mst_Boolean willRegressTest = _gst_regression_testing; int result; _gst_regression_testing = false; _gst_init_oop_table (NULL, INITIAL_OOP_TABLE_SIZE); _gst_init_mem_default (); _gst_init_dictionary (); _gst_init_interpreter (); _gst_init_vmproxy (); _gst_install_initial_methods (); result = load_standard_files (); _gst_regression_testing = willRegressTest; if (result) return result; if (!_gst_save_to_file (_gst_binary_image_name)) _gst_errorf ("Couldn't open file %s", _gst_binary_image_name); } _gst_kernel_initialized = true; _gst_invoke_hook (GST_RETURN_FROM_SNAPSHOT); if (user_init_file) _gst_process_file (user_init_file, GST_DIR_ABS); #ifdef HAVE_READLINE _gst_initialize_readline (); #endif /* HAVE_READLINE */ return 0; }