blob: a14496e7456d1ea05c623d86e81f88a0d2cb4b56 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#undef _LARGEFILE64_SOURCE
27#define _LARGEFILE64_SOURCE 1
28
29#include "jni.h"
30#include "jvm.h"
31#include "jvm_md.h"
32#include "jni_util.h"
33#include "io_util.h"
34
35/*
36 * Platform-specific support for java.lang.Process
37 */
38#include <assert.h>
39#include <stddef.h>
40#include <stdlib.h>
41#include <sys/types.h>
42#include <ctype.h>
43#include <wait.h>
44#include <signal.h>
45#include <string.h>
46#include <errno.h>
47#include <dirent.h>
48#include <unistd.h>
49#include <fcntl.h>
50#include <limits.h>
51
52#ifndef STDIN_FILENO
53#define STDIN_FILENO 0
54#endif
55
56#ifndef STDOUT_FILENO
57#define STDOUT_FILENO 1
58#endif
59
60#ifndef STDERR_FILENO
61#define STDERR_FILENO 2
62#endif
63
64#ifndef SA_NOCLDSTOP
65#define SA_NOCLDSTOP 0
66#endif
67
68#ifndef SA_RESTART
69#define SA_RESTART 0
70#endif
71
72#define FAIL_FILENO (STDERR_FILENO + 1)
73
74static void
75setSIGCHLDHandler(JNIEnv *env)
76{
77 /* There is a subtle difference between having the signal handler
78 * for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process
79 * termination information for child processes if the signal
80 * handler is SIG_IGN. It must be SIG_DFL.
81 *
82 * We used to set the SIGCHLD handler only on Linux, but it's
83 * safest to set it unconditionally.
84 *
85 * Consider what happens if java's parent process sets the SIGCHLD
86 * handler to SIG_IGN. Normally signal handlers are inherited by
87 * children, but SIGCHLD is a controversial case. Solaris appears
88 * to always reset it to SIG_DFL, but this behavior may be
89 * non-standard-compliant, and we shouldn't rely on it.
90 *
91 * References:
92 * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
93 * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
94 */
95 struct sigaction sa;
96 sa.sa_handler = SIG_DFL;
97 sigemptyset(&sa.sa_mask);
98 sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
99 if (sigaction(SIGCHLD, &sa, NULL) < 0)
100 JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
101}
102
103static void*
104xmalloc(JNIEnv *env, size_t size)
105{
106 void *p = malloc(size);
107 if (p == NULL)
108 JNU_ThrowOutOfMemoryError(env, NULL);
109 return p;
110}
111
112#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
113
114/**
115 * If PATH is not defined, the OS provides some default value.
116 * Unfortunately, there's no portable way to get this value.
117 * Fortunately, it's only needed if the child has PATH while we do not.
118 */
119static const char*
120defaultPath(void)
121{
122#ifdef __solaris__
123 /* These really are the Solaris defaults! */
124 return (geteuid() == 0 || getuid() == 0) ?
125 "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
126 "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
127#else
128 return ":/bin:/usr/bin"; /* glibc */
129#endif
130}
131
132static const char*
133effectivePath(void)
134{
135 const char *s = getenv("PATH");
136 return (s != NULL) ? s : defaultPath();
137}
138
139static int
140countOccurrences(const char *s, char c)
141{
142 int count;
143 for (count = 0; *s != '\0'; s++)
144 count += (*s == c);
145 return count;
146}
147
148static const char * const *
149splitPath(JNIEnv *env, const char *path)
150{
151 const char *p, *q;
152 char **pathv;
153 int i;
154 int count = countOccurrences(path, ':') + 1;
155
156 pathv = NEW(char*, count+1);
157 pathv[count] = NULL;
158 for (p = path, i = 0; i < count; i++, p = q + 1) {
159 for (q = p; (*q != ':') && (*q != '\0'); q++)
160 ;
161 if (q == p) /* empty PATH component => "." */
162 pathv[i] = "./";
163 else {
164 int addSlash = ((*(q - 1)) != '/');
165 pathv[i] = NEW(char, q - p + addSlash + 1);
166 memcpy(pathv[i], p, q - p);
167 if (addSlash)
168 pathv[i][q - p] = '/';
169 pathv[i][q - p + addSlash] = '\0';
170 }
171 }
172 return (const char * const *) pathv;
173}
174
175/**
176 * Cached value of JVM's effective PATH.
177 * (We don't support putenv("PATH=...") in native code)
178 */
179static const char *parentPath;
180
181/**
182 * Split, canonicalized version of parentPath
183 */
184static const char * const *parentPathv;
185
186static jfieldID field_exitcode;
187
188JNIEXPORT void JNICALL
189Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz)
190{
191 field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I");
192
193 parentPath = effectivePath();
194 parentPathv = splitPath(env, parentPath);
195
196 setSIGCHLDHandler(env);
197}
198
199
200#ifndef WIFEXITED
201#define WIFEXITED(status) (((status)&0xFF) == 0)
202#endif
203
204#ifndef WEXITSTATUS
205#define WEXITSTATUS(status) (((status)>>8)&0xFF)
206#endif
207
208#ifndef WIFSIGNALED
209#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
210#endif
211
212#ifndef WTERMSIG
213#define WTERMSIG(status) ((status)&0x7F)
214#endif
215
216/* Block until a child process exits and return its exit code.
217 Note, can only be called once for any given pid. */
218JNIEXPORT jint JNICALL
219Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env,
220 jobject junk,
221 jint pid)
222{
223 /* We used to use waitid() on Solaris, waitpid() on Linux, but
224 * waitpid() is more standard, so use it on all POSIX platforms. */
225 int status;
226 /* Wait for the child process to exit. This returns immediately if
227 the child has already exited. */
228 while (waitpid(pid, &status, 0) < 0) {
229 switch (errno) {
230 case ECHILD: return 0;
231 case EINTR: break;
232 default: return -1;
233 }
234 }
235
236 if (WIFEXITED(status)) {
237 /*
238 * The child exited normally; get its exit code.
239 */
240 return WEXITSTATUS(status);
241 } else if (WIFSIGNALED(status)) {
242 /* The child exited because of a signal.
243 * The best value to return is 0x80 + signal number,
244 * because that is what all Unix shells do, and because
245 * it allows callers to distinguish between process exit and
246 * process death by signal.
247 * Unfortunately, the historical behavior on Solaris is to return
248 * the signal number, and we preserve this for compatibility. */
249#ifdef __solaris__
250 return WTERMSIG(status);
251#else
252 return 0x80 + WTERMSIG(status);
253#endif
254 } else {
255 /*
256 * Unknown exit code; pass it through.
257 */
258 return status;
259 }
260}
261
262static int
263closeDescriptors(void)
264{
265 DIR *dp;
266 struct dirent64 *dirp;
267 int from_fd = FAIL_FILENO + 1;
268
269 /* We're trying to close all file descriptors, but opendir() might
270 * itself be implemented using a file descriptor, and we certainly
271 * don't want to close that while it's in use. We assume that if
272 * opendir() is implemented using a file descriptor, then it uses
273 * the lowest numbered file descriptor, just like open(). So we
274 * close a couple explicitly. */
275
276 close(from_fd); /* for possible use by opendir() */
277 close(from_fd + 1); /* another one for good luck */
278
279 if ((dp = opendir("/proc/self/fd")) == NULL)
280 return 0;
281
282 /* We use readdir64 instead of readdir to work around Solaris bug
283 * 6395699: /proc/self/fd fails to report file descriptors >= 1024 on Solaris 9
284 */
285 while ((dirp = readdir64(dp)) != NULL) {
286 int fd;
287 if (isdigit(dirp->d_name[0]) &&
288 (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2)
289 close(fd);
290 }
291
292 closedir(dp);
293
294 return 1;
295}
296
297static void
298moveDescriptor(int fd_from, int fd_to)
299{
300 if (fd_from != fd_to) {
301 dup2(fd_from, fd_to);
302 close(fd_from);
303 }
304}
305
306static const char *
307getBytes(JNIEnv *env, jbyteArray arr)
308{
309 return arr == NULL ? NULL :
310 (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
311}
312
313static void
314releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
315{
316 if (parr != NULL)
317 (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
318}
319
320static void
321initVectorFromBlock(const char**vector, const char* block, int count)
322{
323 int i;
324 const char *p;
325 for (i = 0, p = block; i < count; i++) {
326 /* Invariant: p always points to the start of a C string. */
327 vector[i] = p;
328 while (*(p++));
329 }
330 vector[count] = NULL;
331}
332
333static void
334throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
335{
336 static const char * const format = "error=%d, %s";
337 const char *detail = defaultDetail;
338 char *errmsg;
339 jstring s;
340
341 if (errnum != 0) {
342 const char *s = strerror(errnum);
343 if (strcmp(s, "Unknown error") != 0)
344 detail = s;
345 }
346 /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
347 errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
348 sprintf(errmsg, format, errnum, detail);
349 s = JNU_NewStringPlatform(env, errmsg);
350 if (s != NULL) {
351 jobject x = JNU_NewObjectByName(env, "java/io/IOException",
352 "(Ljava/lang/String;)V", s);
353 if (x != NULL)
354 (*env)->Throw(env, x);
355 }
356 free(errmsg);
357}
358
359#ifdef DEBUG_PROCESS
360/* Debugging process code is difficult; where to write debug output? */
361static void
362debugPrint(char *format, ...)
363{
364 FILE *tty = fopen("/dev/tty", "w");
365 va_list ap;
366 va_start(ap, format);
367 vfprintf(tty, format, ap);
368 va_end(ap);
369 fclose(tty);
370}
371#endif /* DEBUG_PROCESS */
372
373/* Version of execvpe when child's PATH differs from parent's */
374static int
375execvp_usingParentPath(const char *file, const char *const argv[])
376{
377 char expanded_file[PATH_MAX];
378 int filelen = strlen(file);
379 int sticky_errno = 0;
380 const char * const * dirs;
381 /* Search parent's PATH */
382 for (dirs = parentPathv; *dirs; dirs++) {
383 const char * dir = *dirs;
384 int dirlen = strlen(dir);
385 if (filelen + dirlen + 1 >= PATH_MAX) {
386 /* Resist the urge to remove this limit;
387 * calling malloc after fork is unsafe. */
388 errno = ENAMETOOLONG;
389 continue;
390 }
391 strcpy(expanded_file, dir);
392 strcpy(expanded_file + dirlen, file);
393 execvp(expanded_file, (char **) argv);
394 /* There are 3 responses to various classes of errno:
395 * return immediately, continue (especially for ENOENT),
396 * or continue with "sticky" errno.
397 *
398 * From exec(3):
399 *
400 * If permission is denied for a file (the attempted
401 * execve returned EACCES), these functions will continue
402 * searching the rest of the search path. If no other
403 * file is found, however, they will return with the
404 * global variable errno set to EACCES.
405 */
406 switch (errno) {
407 case EACCES:
408 sticky_errno = errno;
409 /* FALLTHRU */
410 case ENOENT:
411 case ENOTDIR:
412#ifdef ELOOP
413 case ELOOP:
414#endif
415#ifdef ESTALE
416 case ESTALE:
417#endif
418#ifdef ENODEV
419 case ENODEV:
420#endif
421#ifdef ETIMEDOUT
422 case ETIMEDOUT:
423#endif
424 break; /* Try other directories in PATH */
425 default:
426 return -1;
427 }
428 }
429 if (sticky_errno != 0)
430 errno = sticky_errno;
431 return -1;
432}
433
434/* execvpe should have been included in the Unix standards. */
435static int
436execvpe(const char *file, const char *const argv[], const char *const envp[])
437{
438 /* This is one of the rare times it's more portable to declare an
439 * external symbol explicitly, rather than via a system header.
440 * The declaration is standardized as part of UNIX98, but there is
441 * no standard (not even de-facto) header file where the
442 * declaration is to be found. See:
443 * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
444 * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
445 *
446 * "All identifiers in this volume of IEEE Std 1003.1-2001, except
447 * environ, are defined in at least one of the headers" (!)
448 */
449 extern char **environ;
450
451 if (envp != NULL)
452 environ = (char **) envp;
453
454 if (/* Parent and child environment the same? Use child PATH. */
455 (envp == NULL)
456
457 /* http://www.opengroup.org/onlinepubs/009695399/functions/exec.html
458 * "If the file argument contains a slash character, it is used as
459 * the pathname for this file. Otherwise, the path prefix for this
460 * file is obtained by a search of the directories passed in the
461 * PATH environment variable" */
462 || (strchr(file, '/') != NULL)
463
464 /* Parent and child PATH the same? Use child PATH. */
465 || (strcmp(parentPath, effectivePath()) == 0)
466
467 /* We want ENOENT, not EACCES, for zero-length program names. */
468 || (*file == '\0'))
469
470 return execvp(file, (char **) argv);
471 else
472 return execvp_usingParentPath(file, argv);
473}
474
475static void
476closeSafely(int fd)
477{
478 if (fd != -1)
479 close(fd);
480}
481
482#ifndef __solaris__
483#undef fork1
484#define fork1() fork()
485#endif
486
487JNIEXPORT jint JNICALL
488Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
489 jobject process,
490 jbyteArray prog,
491 jbyteArray argBlock, jint argc,
492 jbyteArray envBlock, jint envc,
493 jbyteArray dir,
494 jboolean redirectErrorStream,
495 jobject stdin_fd,
496 jobject stdout_fd,
497 jobject stderr_fd)
498{
499 int errnum;
500 int resultPid = -1;
501 int in[2], out[2], err[2], fail[2];
502 const char **argv = NULL;
503 const char **envv = NULL;
504 const char *pprog = getBytes(env, prog);
505 const char *pargBlock = getBytes(env, argBlock);
506 const char *penvBlock = getBytes(env, envBlock);
507 const char *pdir = getBytes(env, dir);
508
509 in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
510
511 assert(prog != NULL && argBlock != NULL);
512 if (pprog == NULL) goto Catch;
513 if (pargBlock == NULL) goto Catch;
514 if (envBlock != NULL && penvBlock == NULL) goto Catch;
515 if (dir != NULL && pdir == NULL) goto Catch;
516
517 /* Convert pprog + pargBlock into a char ** argv */
518 if ((argv = NEW(const char *, argc + 2)) == NULL)
519 goto Catch;
520 argv[0] = pprog;
521 initVectorFromBlock(argv+1, pargBlock, argc);
522
523 if (envBlock != NULL) {
524 /* Convert penvBlock into a char ** envv */
525 if ((envv = NEW(const char *, envc + 1)) == NULL)
526 goto Catch;
527 initVectorFromBlock(envv, penvBlock, envc);
528 }
529
530 if ((pipe(in) < 0) ||
531 (pipe(out) < 0) ||
532 (pipe(err) < 0) ||
533 (pipe(fail) < 0)) {
534 throwIOException(env, errno, "Bad file descriptor");
535 goto Catch;
536 }
537
538 resultPid = fork1();
539 if (resultPid < 0) {
540 throwIOException(env, errno, "Fork failed");
541 goto Catch;
542 }
543
544 if (resultPid == 0) {
545 /* Child process */
546
547 /* Close the parent sides of the pipe.
548 Give the child sides of the pipes the right fileno's.
549 Closing pipe fds here is redundant, since closeDescriptors()
550 would do it anyways, but a little paranoia is a good thing. */
551 /* Note: it is possible for in[0] == 0 */
552 close(in[1]);
553 moveDescriptor(in[0], STDIN_FILENO);
554 close(out[0]);
555 moveDescriptor(out[1], STDOUT_FILENO);
556 close(err[0]);
557 if (redirectErrorStream) {
558 close(err[1]);
559 dup2(STDOUT_FILENO, STDERR_FILENO);
560 } else {
561 moveDescriptor(err[1], STDERR_FILENO);
562 }
563 close(fail[0]);
564 moveDescriptor(fail[1], FAIL_FILENO);
565
566 /* close everything */
567 if (closeDescriptors() == 0) { /* failed, close the old way */
568 int max_fd = (int)sysconf(_SC_OPEN_MAX);
569 int i;
570 for (i = FAIL_FILENO + 1; i < max_fd; i++)
571 close(i);
572 }
573
574 /* change to the new working directory */
575 if (pdir != NULL && chdir(pdir) < 0)
576 goto WhyCantJohnnyExec;
577
578 if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1)
579 goto WhyCantJohnnyExec;
580
581 execvpe(argv[0], argv, envv);
582
583 WhyCantJohnnyExec:
584 /* We used to go to an awful lot of trouble to predict whether the
585 * child would fail, but there is no reliable way to predict the
586 * success of an operation without *trying* it, and there's no way
587 * to try a chdir or exec in the parent. Instead, all we need is a
588 * way to communicate any failure back to the parent. Easy; we just
589 * send the errno back to the parent over a pipe in case of failure.
590 * The tricky thing is, how do we communicate the *success* of exec?
591 * We use FD_CLOEXEC together with the fact that a read() on a pipe
592 * yields EOF when the write ends (we have two of them!) are closed.
593 */
594 errnum = errno;
595 write(FAIL_FILENO, &errnum, sizeof(errnum));
596 close(FAIL_FILENO);
597 _exit(-1);
598 }
599
600 /* parent process */
601
602 close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */
603 if (read(fail[0], &errnum, sizeof(errnum)) != 0) {
604 waitpid(resultPid, NULL, 0);
605 throwIOException(env, errnum, "Exec failed");
606 goto Catch;
607 }
608
609 (*env)->SetIntField(env, stdin_fd, IO_fd_fdID, in [1]);
610 (*env)->SetIntField(env, stdout_fd, IO_fd_fdID, out[0]);
611 (*env)->SetIntField(env, stderr_fd, IO_fd_fdID, err[0]);
612
613 Finally:
614 /* Always clean up the child's side of the pipes */
615 closeSafely(in [0]);
616 closeSafely(out[1]);
617 closeSafely(err[1]);
618
619 /* Always clean up fail descriptors */
620 closeSafely(fail[0]);
621 closeSafely(fail[1]);
622
623 free(argv);
624 free(envv);
625
626 releaseBytes(env, prog, pprog);
627 releaseBytes(env, argBlock, pargBlock);
628 releaseBytes(env, envBlock, penvBlock);
629 releaseBytes(env, dir, pdir);
630
631 return resultPid;
632
633 Catch:
634 /* Clean up the parent's side of the pipes in case of failure only */
635 closeSafely(in [1]);
636 closeSafely(out[0]);
637 closeSafely(err[0]);
638 goto Finally;
639}
640
641JNIEXPORT void JNICALL
642Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, jobject junk, jint pid)
643{
644 kill(pid, SIGTERM);
645}