1 /* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 #include "java.h" 26 // #include "jdk_strerror.h" 27 28 /* 29 * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put 30 * "/foo" into buf. 31 */ 32 jboolean 33 GetApplicationHome(char *buf, jint bufsize) 34 { 35 const char *execname = GetExecName(); 36 if (execname != NULL) { 37 JLI_Snprintf(buf, bufsize, "%s", execname); 38 buf[bufsize-1] = '\0'; 39 } else { 40 return JNI_FALSE; 41 } 42 43 if (JLI_StrRChr(buf, '/') == 0) { 44 buf[0] = '\0'; 45 return JNI_FALSE; 46 } 47 *(JLI_StrRChr(buf, '/')) = '\0'; /* executable file */ 48 if (JLI_StrLen(buf) < 4 || JLI_StrRChr(buf, '/') == 0) { 49 buf[0] = '\0'; 50 return JNI_FALSE; 51 } 52 if (JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0) 53 *(JLI_StrRChr(buf, '/')) = '\0'; /* sparcv9 or amd64 */ 54 if (JLI_StrLen(buf) < 4 || JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0) { 55 buf[0] = '\0'; 56 return JNI_FALSE; 57 } 58 *(JLI_StrRChr(buf, '/')) = '\0'; /* bin */ 59 60 return JNI_TRUE; 61 } 62 /* 63 * Return true if the named program exists 64 */ 65 static int 66 ProgramExists(char *name) 67 { 68 struct stat sb; 69 if (stat(name, &sb) != 0) return 0; 70 if (S_ISDIR(sb.st_mode)) return 0; 71 return (sb.st_mode & S_IEXEC) != 0; 72 } 73 74 /* 75 * Find a command in a directory, returning the path. 76 */ 77 static char * 78 Resolve(char *indir, char *cmd) 79 { 80 char name[PATH_MAX + 2], *real; 81 82 if ((JLI_StrLen(indir) + JLI_StrLen(cmd) + 1) > PATH_MAX) return 0; 83 JLI_Snprintf(name, sizeof(name), "%s%c%s", indir, FILE_SEPARATOR, cmd); 84 if (!ProgramExists(name)) return 0; 85 real = JLI_MemAlloc(PATH_MAX + 2); 86 if (!realpath(name, real)) 87 JLI_StrCpy(real, name); 88 return real; 89 } 90 91 /* 92 * Find a path for the executable 93 */ 94 char * 95 FindExecName(char *program) 96 { 97 char cwdbuf[PATH_MAX+2]; 98 char *path; 99 char *tmp_path; 100 char *f; 101 char *result = NULL; 102 103 /* absolute path? */ 104 if (*program == FILE_SEPARATOR || 105 (FILE_SEPARATOR=='\\' && JLI_StrRChr(program, ':'))) 106 return Resolve("", program+1); 107 108 /* relative path? */ 109 if (JLI_StrRChr(program, FILE_SEPARATOR) != 0) { 110 char buf[PATH_MAX+2]; 111 return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program); 112 } 113 114 /* from search path? */ 115 path = getenv("PATH"); 116 if (!path || !*path) path = "."; 117 tmp_path = JLI_MemAlloc(JLI_StrLen(path) + 2); 118 JLI_StrCpy(tmp_path, path); 119 120 for (f=tmp_path; *f && result==0; ) { 121 char *s = f; 122 while (*f && (*f != PATH_SEPARATOR)) ++f; 123 if (*f) *f++ = 0; 124 if (*s == FILE_SEPARATOR) 125 result = Resolve(s, program); 126 else { 127 /* relative path element */ 128 char dir[2*PATH_MAX]; 129 JLI_Snprintf(dir, sizeof(dir), "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)), 130 FILE_SEPARATOR, s); 131 result = Resolve(dir, program); 132 } 133 if (result != 0) break; 134 } 135 136 JLI_MemFree(tmp_path); 137 return result; 138 } 139 140 void JLI_ReportErrorMessage(const char* fmt, ...) { 141 va_list vl; 142 va_start(vl, fmt); 143 vfprintf(stderr, fmt, vl); 144 fprintf(stderr, "\n"); 145 va_end(vl); 146 } 147 148 void JLI_ReportErrorMessageSys(const char* fmt, ...) { 149 va_list vl; 150 char buf[1024]; 151 152 // jdk_strerror(errno, buf, (size_t) 1024) 153 fprintf(stderr, "%s\n", strerror(errno)); 154 155 va_start(vl, fmt); 156 vfprintf(stderr, fmt, vl); 157 fprintf(stderr, "\n"); 158 va_end(vl); 159 } 160 161 void JLI_ReportExceptionDescription(JNIEnv * env) { 162 (*env)->ExceptionDescribe(env); 163 } 164 165 /* 166 * Since using the file system as a registry is a bit risky, perform 167 * additional sanity checks on the identified directory to validate 168 * it as a valid jre/sdk. 169 * 170 * Return 0 if the tests fail; otherwise return non-zero (true). 171 * 172 * Note that checking for anything more than the existence of an 173 * executable object at bin/java relative to the path being checked 174 * will break the regression tests. 175 */ 176 static int 177 CheckSanity(char *path, char *dir) 178 { 179 char buffer[PATH_MAX]; 180 181 if (JLI_StrLen(path) + JLI_StrLen(dir) + 11 > PATH_MAX) 182 return (0); /* Silently reject "impossibly" long paths */ 183 184 JLI_Snprintf(buffer, sizeof(buffer), "%s/%s/bin/java", path, dir); 185 return ((access(buffer, X_OK) == 0) ? 1 : 0); 186 } 187 188 /* 189 * "Borrowed" from Solaris 10 where the unsetenv() function is being added 190 * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As 191 * such, in the fullness of time this will appear in libc on all relevant 192 * Solaris/Linux platforms and maybe even the Windows platform. At that 193 * time, this stub can be removed. 194 * 195 * This implementation removes the environment locking for multithreaded 196 * applications. (We don't have access to these mutexes within libc and 197 * the launcher isn't multithreaded.) Note that what remains is platform 198 * independent, because it only relies on attributes that a POSIX environment 199 * defines. 200 * 201 * Returns 0 on success, -1 on failure. 202 * 203 * Also removed was the setting of errno. The only value of errno set 204 * was EINVAL ("Invalid Argument"). 205 */ 206 207 /* 208 * s1(environ) is name=value 209 * s2(name) is name(not the form of name=value). 210 * if names match, return value of 1, else return 0 211 */ 212 static int 213 match_noeq(const char *s1, const char *s2) 214 { 215 while (*s1 == *s2++) { 216 if (*s1++ == '=') 217 return (1); 218 } 219 if (*s1 == '=' && s2[-1] == '\0') 220 return (1); 221 return (0); 222 } 223 224 /* 225 * added for SUSv3 standard 226 * 227 * Delete entry from environ. 228 * Do not free() memory! Other threads may be using it. 229 * Keep it around forever. 230 */ 231 static int 232 borrowed_unsetenv(const char *name) 233 { 234 long idx; /* index into environ */ 235 236 if (name == NULL || *name == '\0' || 237 JLI_StrChr(name, '=') != NULL) { 238 return (-1); 239 } 240 241 for (idx = 0; environ[idx] != NULL; idx++) { 242 if (match_noeq(environ[idx], name)) 243 break; 244 } 245 if (environ[idx] == NULL) { 246 /* name not found but still a success */ 247 return (0); 248 } 249 /* squeeze up one entry */ 250 do { 251 environ[idx] = environ[idx+1]; 252 } while (environ[++idx] != NULL); 253 254 return (0); 255 } 256 /* --- End of "borrowed" code --- */ 257 258 /* 259 * Wrapper for unsetenv() function. 260 */ 261 int 262 UnsetEnv(char *name) 263 { 264 return(borrowed_unsetenv(name)); 265 } 266 267 jboolean 268 IsJavaw() 269 { 270 /* noop on UNIX */ 271 return JNI_FALSE; 272 } 273 274 void 275 InitLauncher(jboolean javaw) 276 { 277 JLI_SetTraceLauncher(); 278 } 279 280 /* 281 * The implementation for finding classes from the bootstrap 282 * class loader, refer to java.h 283 */ 284 static FindClassFromBootLoader_t *findBootClass = NULL; 285 286 jclass 287 FindBootStrapClass(JNIEnv *env, const char* classname) 288 { 289 if (findBootClass == NULL) { 290 findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT, 291 "JVM_FindClassFromBootLoader"); 292 if (findBootClass == NULL) { 293 JLI_ReportErrorMessage(DLL_ERROR4, 294 "JVM_FindClassFromBootLoader"); 295 return NULL; 296 } 297 } 298 return findBootClass(env, classname); 299 } 300 301 StdArg 302 *JLI_GetStdArgs() 303 { 304 return NULL; 305 } 306 307 int 308 JLI_GetStdArgc() { 309 return 0; 310 } 311 312 jobjectArray 313 CreateApplicationArgs(JNIEnv *env, char **strv, int argc) 314 { 315 return NewPlatformStringArray(env, strv, argc); 316 }