229 { 230 const char *s = getenv("PATH"); 231 return (s != NULL) ? s : defaultPath(); 232 } 233 234 static int 235 countOccurrences(const char *s, char c) 236 { 237 int count; 238 for (count = 0; *s != '\0'; s++) 239 count += (*s == c); 240 return count; 241 } 242 243 static const char * const * 244 splitPath(JNIEnv *env, const char *path) 245 { 246 const char *p, *q; 247 char **pathv; 248 int i; 249 int count = countOccurrences(path, ':') + 1; 250 251 pathv = NEW(char*, count+1); 252 pathv[count] = NULL; 253 for (p = path, i = 0; i < count; i++, p = q + 1) { 254 for (q = p; (*q != ':') && (*q != '\0'); q++) 255 ; 256 if (q == p) /* empty PATH component => "." */ 257 pathv[i] = "./"; 258 else { 259 int addSlash = ((*(q - 1)) != '/'); 260 pathv[i] = NEW(char, q - p + addSlash + 1); 261 memcpy(pathv[i], p, q - p); 262 if (addSlash) 263 pathv[i][q - p] = '/'; 264 pathv[i][q - p + addSlash] = '\0'; 265 } 266 } 267 return (const char * const *) pathv; 268 } 269 270 /** 271 * Cached value of JVM's effective PATH. 272 * (We don't support putenv("PATH=...") in native code) 273 */ 274 static const char *parentPath; 275 276 /** 277 * Split, canonicalized version of parentPath 278 */ 279 static const char * const *parentPathv; 280 281 static jfieldID field_exitcode; 282 283 JNIEXPORT void JNICALL 284 Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz) 285 { 286 field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I"); 287 469 while (*(p++)); 470 } 471 vector[count] = NULL; 472 } 473 474 static void 475 throwIOException(JNIEnv *env, int errnum, const char *defaultDetail) 476 { 477 static const char * const format = "error=%d, %s"; 478 const char *detail = defaultDetail; 479 char *errmsg; 480 jstring s; 481 482 if (errnum != 0) { 483 const char *s = strerror(errnum); 484 if (strcmp(s, "Unknown error") != 0) 485 detail = s; 486 } 487 /* ASCII Decimal representation uses 2.4 times as many bits as binary. */ 488 errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum)); 489 sprintf(errmsg, format, errnum, detail); 490 s = JNU_NewStringPlatform(env, errmsg); 491 if (s != NULL) { 492 jobject x = JNU_NewObjectByName(env, "java/io/IOException", 493 "(Ljava/lang/String;)V", s); 494 if (x != NULL) 495 (*env)->Throw(env, x); 496 } 497 free(errmsg); 498 } 499 500 #ifdef DEBUG_PROCESS 501 /* Debugging process code is difficult; where to write debug output? */ 502 static void 503 debugPrint(char *format, ...) 504 { 505 FILE *tty = fopen("/dev/tty", "w"); 506 va_list ap; 507 va_start(ap, format); 508 vfprintf(tty, format, ap); | 229 { 230 const char *s = getenv("PATH"); 231 return (s != NULL) ? s : defaultPath(); 232 } 233 234 static int 235 countOccurrences(const char *s, char c) 236 { 237 int count; 238 for (count = 0; *s != '\0'; s++) 239 count += (*s == c); 240 return count; 241 } 242 243 static const char * const * 244 splitPath(JNIEnv *env, const char *path) 245 { 246 const char *p, *q; 247 char **pathv; 248 int i; 249 int k; 250 int count = countOccurrences(path, ':') + 1; 251 252 pathv = NEW(char*, count+1); 253 if (pathv == NULL) 254 return NULL; 255 256 pathv[count] = NULL; 257 for (p = path, i = 0; i < count; i++, p = q + 1) { 258 for (q = p; (*q != ':') && (*q != '\0'); q++); 259 260 if (q == p) /* empty PATH component => "." */ 261 pathv[i] = "./"; 262 else { 263 int addSlash = ((*(q - 1)) != '/'); 264 pathv[i] = NEW(char, q - p + addSlash + 1); 265 if (pathv[i] == NULL) 266 goto cleanUpMemory; 267 268 memcpy(pathv[i], p, q - p); 269 if (addSlash) 270 pathv[i][q - p] = '/'; 271 pathv[i][q - p + addSlash] = '\0'; 272 } 273 } 274 return (const char * const *) pathv; 275 276 cleanUpMemory: 277 for (k = 0; k <= i; k++) 278 free(pathv[k]); 279 return NULL; 280 } 281 282 /** 283 * Cached value of JVM's effective PATH. 284 * (We don't support putenv("PATH=...") in native code) 285 */ 286 static const char *parentPath; 287 288 /** 289 * Split, canonicalized version of parentPath 290 */ 291 static const char * const *parentPathv; 292 293 static jfieldID field_exitcode; 294 295 JNIEXPORT void JNICALL 296 Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz) 297 { 298 field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I"); 299 481 while (*(p++)); 482 } 483 vector[count] = NULL; 484 } 485 486 static void 487 throwIOException(JNIEnv *env, int errnum, const char *defaultDetail) 488 { 489 static const char * const format = "error=%d, %s"; 490 const char *detail = defaultDetail; 491 char *errmsg; 492 jstring s; 493 494 if (errnum != 0) { 495 const char *s = strerror(errnum); 496 if (strcmp(s, "Unknown error") != 0) 497 detail = s; 498 } 499 /* ASCII Decimal representation uses 2.4 times as many bits as binary. */ 500 errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum)); 501 if (errmsg == NULL) 502 return; 503 504 sprintf(errmsg, format, errnum, detail); 505 s = JNU_NewStringPlatform(env, errmsg); 506 if (s != NULL) { 507 jobject x = JNU_NewObjectByName(env, "java/io/IOException", 508 "(Ljava/lang/String;)V", s); 509 if (x != NULL) 510 (*env)->Throw(env, x); 511 } 512 free(errmsg); 513 } 514 515 #ifdef DEBUG_PROCESS 516 /* Debugging process code is difficult; where to write debug output? */ 517 static void 518 debugPrint(char *format, ...) 519 { 520 FILE *tty = fopen("/dev/tty", "w"); 521 va_list ap; 522 va_start(ap, format); 523 vfprintf(tty, format, ap); |