/*++ Function: OutputDebugStringA See MSDN doc. --*/ VOID PALAPI OutputDebugStringA( IN LPCSTR lpOutputString) { char *env_string; ENTRY("OutputDebugStringA (lpOutputString=%p (%s))\n", lpOutputString?lpOutputString:"NULL", lpOutputString?lpOutputString:"NULL"); /* as we don't support debug events, we are going to output the debug string to stderr instead of generating OUT_DEBUG_STRING_EVENT */ if ( (lpOutputString != NULL) && (NULL != (env_string = MiscGetenv(PAL_OUTPUTDEBUGSTRING)))) { fprintf(stderr, "%s", lpOutputString); } LOGEXIT("OutputDebugStringA returns\n"); }
/*++ Function: INIT_FindEXEPath Abstract: Determine the full, canonical path of the current executable by searching $PATH. Parameters: LPCSTR exe_name : file to search for Return: pointer to buffer containing the full path. This buffer must be released by the caller using free() Notes : this function assumes that "exe_name" is in Unix style (no \) Notes 2: This doesn't handle the case of directories with the desired name (and directories are usually executable...) --*/ static LPWSTR INIT_FindEXEPath(LPCSTR exe_name) { CHAR real_path[MAXPATHLEN]; LPSTR env_path; LPSTR path_ptr; LPSTR cur_dir; INT exe_name_length; BOOL need_slash; LPWSTR return_value; INT return_size; struct stat theStats; /* if a path is specified, only search there */ if(strchr(exe_name, '/')) { if ( -1 == stat( exe_name, &theStats ) ) { ERROR( "The file does not exist\n" ); return NULL; } if ( UTIL_IsExecuteBitsSet( &theStats ) ) { if(!realpath(exe_name, real_path)) { ERROR("realpath() failed!\n"); return NULL; } return_size=MultiByteToWideChar(CP_ACP,0,real_path,-1,NULL,0); return_value=malloc(return_size*sizeof(WCHAR)); if(!return_size || !return_value) { ERROR("Not enough memory to create full path\n"); } else { if(!MultiByteToWideChar(CP_ACP, 0, real_path, -1, return_value, return_size)) { ASSERT("MultiByteToWideChar failure\n"); free(return_value); return_value = NULL; } else { TRACE("full path to executable is %s\n", real_path); } } return return_value; } } /* no path was specified : search $PATH */ env_path=MiscGetenv("PATH"); if(!env_path || *env_path=='\0') { WARN("$PATH isn't set.\n"); goto last_resort; } /* get our own copy of env_path so we can modify it */ env_path=strdup(env_path); if(!env_path) { ERROR("Not enough memory to copy $PATH!\n"); return NULL; } exe_name_length=strlen(exe_name); cur_dir=env_path; while(cur_dir) { LPSTR full_path; struct stat theStats; /* skip all leading ':' */ while(*cur_dir==':') { cur_dir++; } if(*cur_dir=='\0') { break; } /* cut string at next ':' */ path_ptr=strchr(cur_dir, ':'); if(path_ptr) { /* check if we need to add a '/' between the path and filename */ need_slash=(*(path_ptr-1))!='/'; /* NULL_terminate path element */ *path_ptr++='\0'; } else { /* check if we need to add a '/' between the path and filename */ need_slash=(cur_dir[strlen(cur_dir)-1])!='/'; } TRACE("looking for %s in %s\n", exe_name, cur_dir); /* build tentative full file name */ full_path=malloc(strlen(cur_dir)+exe_name_length+2); if(!full_path) { ERROR("Not enough memory!\n"); break; } strcpy(full_path,cur_dir); if(need_slash) { strcat(full_path, "/"); } strcat(full_path, exe_name); /* see if file exists AND is executable */ if ( -1 != stat( full_path, &theStats ) ) { if( UTIL_IsExecuteBitsSet( &theStats ) ) { /* generate canonical path */ if(!realpath(full_path, real_path)) { ERROR("realpath() failed!\n"); free(full_path); free(env_path); return NULL; } free(full_path); return_size=MultiByteToWideChar(CP_ACP,0,real_path,-1,NULL,0); return_value=malloc(return_size*sizeof(WCHAR)); if(!return_size || !return_value) { ERROR("Not enough memory to create full path\n"); free(env_path); return NULL; } if(!MultiByteToWideChar(CP_ACP, 0, real_path, -1, return_value, return_size)) { ASSERT("MultiByteToWideChar failure\n"); free(return_value); return_value = NULL; } else { TRACE("found %s in %s; real path is %s\n", exe_name, cur_dir,real_path); } free(env_path); return return_value; } } /* file doesn't exist : keep searching */ free(full_path); /* path_ptr is NULL if there's no ':' after this directory */ cur_dir=path_ptr; } free(env_path); TRACE("No %s found in $PATH (%s)\n", exe_name, MiscGetenv("PATH")); last_resort: /* last resort : see if the executable is in the current directory. This is possible if it comes from a exec*() call. */ if(0 == stat(exe_name,&theStats)) { if ( UTIL_IsExecuteBitsSet( &theStats ) ) { if(!realpath(exe_name, real_path)) { ERROR("realpath() failed!\n"); return NULL; } return_size=MultiByteToWideChar(CP_ACP,0,real_path,-1,NULL,0); return_value=malloc(return_size*sizeof(WCHAR)); if(!return_size || !return_value) { ERROR("Not enough memory to create full path\n"); } else { if(!MultiByteToWideChar(CP_ACP, 0, real_path, -1, return_value, return_size)) { ASSERT("MultiByteToWideChar failure\n"); free(return_value); return_value = NULL; } else { TRACE("full path to executable is %s\n", real_path); } } return return_value; } else { ERROR("found %s in current directory, but it isn't executable!\n", exe_name); } } else { TRACE("last resort failed : executable %s is not in the current " "directory\n",exe_name); } ERROR("executable %s not found anywhere!\n", exe_name); return NULL; }
static const char * safegetenv(const char * s) { const char * ss = MiscGetenv(s); return ss? ss : ""; }