/* * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ #include #include #include #include #include #include #include #include #include #include #include #include "processutil_md.h" /* * Utility used by j.l.ProcessBuilder (via UNIXProcess) to launch * target commands. This (small) binary is launched via posix_spawn. * It sets up the required environment for the target and then * execs the target. * * argv[0] target command * argv[1] working directory for command * argv[2] = string containing fd numbers of pipes created in the parent * in following order: * stdinfd stdoutfd stderrfd statuspipe * argv[3] = "1" redirect stderr to stdout, "0" don't * argv[4]+ args to target * * The std{in,out,err} fds must be moved to their correct numbers first * and the temporary pipe fd is also moved to position 3 * Then all fds above this are closed. * * Target environment (comprising null terminated strings) * preceded by total byte length and number of strings * are sent down the pipe. if these two initial vals are -1, then * there is no environment. * * Response message sent up pipe to VM, if an error occurs: * * - Msg type (4 bytes) * 1 = chdir error (detail in Field 1) * 2 = exec error (detail in Field 1) * 3 = target terminated (exit code in Field 1) * - Field 1 (4 bytes) * * Assuming no error occured, the pipe will be set to close on exec * and the parent will see EOF on its side of the pipe. This indicates * a successful launch of the target. */ static int stdinfd, stdoutfd, stderrfd, pipefd; static void reply (int first, int second) { int response[2]; response[0] = first; response[1] = second; write (pipefd, &response[0], sizeof(response)); } void *jlup_xmalloc (void *env, int size) { return malloc (size); } int main (int argc, char *argv[]) { int err; int child; int envL; /* size of child environment */ int nenv; /* number of entries in child environment */ int flags, stderrIsPipe, redirectStderr; const char **env, *ptr; char name [256]; const char *nullptr = 0; struct sigaction sa; FILE *f; jlup_initialize (NULL); sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NOCLDSTOP | SA_RESTART; sigaction(SIGCHLD, &sa, NULL); if (sscanf (argv[2], "%d %d %d %d", &stdinfd, &stdoutfd, &stderrfd, &pipefd) != 4) { reply (2, 0); exit (0); } if (*argv[1] != 0) { err = chdir (argv[1]); if (err != 0) { reply (1, errno); exit (0); } } flags = atoi (argv[3]); redirectStderr = flags & 0x1; stderrIsPipe = flags & 0x2; argv [3] = argv [0]; /* overwrite the args just handled */ jlup_moveDescriptor (stdinfd, 0); jlup_moveDescriptor (stdoutfd, 1); if (redirectStderr) { if (stderrIsPipe) { jlup_closeSafely (stderrfd); } dup2 (1, 2); } else { jlup_moveDescriptor (stderrfd, 2); } jlup_moveDescriptor (pipefd, 3); pipefd = 3; if (jlup_closeDescriptors(4) ==0) { reply (2, errno); exit (0); } /* read child's environment */ if (jlup_readFully(pipefd, &envL, sizeof(envL)) != sizeof(envL) || jlup_readFully(pipefd, &nenv, sizeof(nenv)) != sizeof(nenv)) { reply (2, errno); exit (0); } if (envL == -1) { /* no environment */ env = 0; } else if (envL != 0) { /* at least one entry in environment */ ptr = malloc (envL); if (jlup_readFully(pipefd, (void *)ptr, envL) != envL) { reply (2, errno); exit (0); } env = malloc (sizeof(char *) * nenv); jlup_initVectorFromBlock (env, ptr, nenv); } else { /* empty environment */ env = &nullptr; } err = fcntl (pipefd, F_SETFD, FD_CLOEXEC); jlup_execvpe ((const char * )argv[3], (const char * const*)&argv[3], env); reply (2, errno); exit (0); return 0; /* keep compiler happy */ }