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