char * get_executable_dir (void) { char path[MAXPATHLEN]; int rval; int i; /* Look in this special place for a link to the executable. This only works on Linux, but it is benign if we try it elsewhere. */ rval = readlink ("/proc/self/exe", path, sizeof(path)); if (rval <= 0) { // If can't read /proc/self/exe, get program path from PATH // variable. char *p = get_executable_dir_from_path(saved_orig_program_name); strncpy(path, p, sizeof(path)); rval = strlen(path); } else { path[rval] = '\0'; // readlink doesn't append NULL } if (rval > 0) { for (i=rval-1; i >= 0; i--) { if (path[i] == '/') break; } if (i > 0) { /* Overwrite the trailing slash, giving the directory portion of the path. */ path[i] = '\0'; } else if (i == 0) { /* Directory is the root */ strcpy (path, "/"); } if (is_directory (path)) { /* Verify that it is a directory */ return string_copy (path); } } /* TBD: try to extract the name from argv0 */ /* Can't get anything reasonable. */ return NULL; }
// Get program path from PATH variable. static char * get_executable_dir_from_path(char *name) { if (is_dir_separator (name[0])) return name; #if defined(_WIN32) else if (name[1] == ':' && is_dir_separator(name[2])) return name; #endif else { /* relative path */ char *path = getenv("PATH"); if (path != NULL) { char *p = string_copy(path); char *tmp; char *dir; #if defined(_WIN32) #if defined(__MINGW32__) /* mingw uses semicolon as separator */ while ((dir = strtok(p, ";")) != NULL) { #else /* strtok_r doesn't exist */ while ((dir = strtok(p, ":")) != NULL) { #endif /* __MINGW32__ */ #else while ((dir = strtok_r(p, ":", &tmp)) != NULL) { #endif /* _WIN32 */ if (is_directory(dir)) { char filename[MAXPATHLEN]; snprintf(filename, MAXPATHLEN, "%s%s%s", dir, DIR_SEPARATOR_STR, name); if (is_executable(filename)) { return string_copy(filename); } #if defined(_WIN32) else { /* if not found, then try again with or without .exe suffix, * depending on whether the original filename had one; * e.g. if invoked opencc when opencc.exe is full name. */ char *suffix = get_suffix(filename); if (suffix != NULL && strcmp(suffix, "exe") == 0) { /* has suffix so try without suffix */ *(suffix-1) = NIL; } else { /* add exe suffix */ strcat(filename, ".exe"); } if (is_executable(filename)) { return string_copy(filename); } } #endif } p = NULL; } } } return name; } char * get_executable_dir (void) { char path[MAXPATHLEN]; int rval = 0; int i; #if defined(linux) /* Look in this special place for a link to the executable. This only works on Linux, but it is benign if we try it elsewhere. */ rval = readlink ("/proc/self/exe", path, sizeof(path)); #endif if (rval <= 0) { // If can't read /proc/self/exe, get program path from PATH // variable. char *p = get_executable_dir_from_path(saved_orig_program_name); strncpy(path, p, sizeof(path)); rval = strlen(path); } else { path[rval] = '\0'; // readlink doesn't append NULL } if (rval > 0) { for (i=rval-1; i >= 0; i--) { if (is_dir_separator(path[i])) break; } if (i > 0) { /* Overwrite the trailing slash, giving the directory portion of the path. */ path[i] = '\0'; } else if (i == 0) { /* Directory is the root */ strcpy (path, DIR_SEPARATOR_STR); } if (is_directory (path)) { /* Verify that it is a directory */ return string_copy (path); } } /* TBD: try to extract the name from argv0 */ /* Can't get anything reasonable. */ #ifdef TARG_NVISA internal_error("unable to find $PATH for nvopencc"); #endif return NULL; } void dump_file_to_stdout(char *filename) { char buf[buf_size]; FILE *f; int n; if (filename == NULL || !file_exists(filename)) internal_error("file does not exist"); f = fopen(filename, "r"); if (f == NULL) internal_error("cannot open file for read"); // Copy the content of file to stdout. while ((n = fread(buf, 1, buf_size, f)) > 0) { if (-1 == write(1, buf, n)) { internal_error("cannot write to file"); break; } } fclose(f); }