1 /*
   2  * Copyright (c) 2013, 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 
  26 #include <errno.h>
  27 #include <fcntl.h>
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <unistd.h>
  31 #include <sys/types.h>
  32 #include <sys/stat.h>
  33 
  34 #include "childproc.h"
  35 
  36 extern int errno;
  37 
  38 #define ALLOC(X,Y) { \
  39     void *mptr; \
  40     mptr = malloc (Y); \
  41     if (mptr == 0) { \
  42         error (fdout, ERR_MALLOC); \
  43     } \
  44     X = mptr; \
  45 }
  46 
  47 #define ERR_MALLOC 1
  48 #define ERR_PIPE 2
  49 #define ERR_ARGS 3
  50 
  51 void error (int fd, int err) {
  52     write (fd, &err, sizeof(err));
  53     exit (1);
  54 }
  55 
  56 void shutItDown() {
  57     fprintf(stdout, "This command is not for general use and should ");
  58     fprintf(stdout, "only be run as the result of a call to\n");
  59     fprintf(stdout, "ProcessBuilder.start() or Runtime.exec() in a java ");
  60     fprintf(stdout, "application\n");
  61     _exit(1);
  62 }
  63 
  64 /*
  65  * read the following off the pipefd
  66  * - the ChildStuff struct
  67  * - the SpawnInfo struct
  68  * - the data strings for fields in ChildStuff
  69  */
  70 void initChildStuff (int fdin, int fdout, ChildStuff *c) {
  71     int n;
  72     int argvBytes, nargv, envvBytes, nenvv;
  73     int dirlen;
  74     char *buf;
  75     SpawnInfo sp;
  76     int bufsize, offset=0;
  77     int magic;
  78     int res;
  79 
  80     res = readFully (fdin, &magic, sizeof(magic));
  81     if (res != 4 || magic != magicNumber()) {
  82         error (fdout, ERR_PIPE);
  83     }
  84 
  85     if (readFully (fdin, c, sizeof(*c)) == -1) {
  86         error (fdout, ERR_PIPE);
  87     }
  88 
  89     if (readFully (fdin, &sp, sizeof(sp)) == -1) {
  90         error (fdout, ERR_PIPE);
  91     }
  92 
  93     bufsize = sp.argvBytes + sp.envvBytes +
  94               sp.dirlen + sp.parentPathvBytes;
  95 
  96     ALLOC(buf, bufsize);
  97 
  98     if (readFully (fdin, buf, bufsize) == -1) {
  99         error (fdout, ERR_PIPE);
 100     }
 101 
 102     /* Initialize argv[] */
 103     ALLOC(c->argv, sizeof(char *) * sp.nargv);
 104     initVectorFromBlock (c->argv, buf+offset, sp.nargv-1);
 105     offset += sp.argvBytes;
 106 
 107     /* Initialize envv[] */
 108     if (sp.nenvv == 0) {
 109         c->envv = 0;
 110     } else {
 111         ALLOC(c->envv, sizeof(char *) * sp.nenvv);
 112         initVectorFromBlock (c->envv, buf+offset, sp.nenvv-1);
 113         offset += sp.envvBytes;
 114     }
 115 
 116     /* Initialize pdir */
 117     if (sp.dirlen == 0) {
 118         c->pdir = 0;
 119     } else {
 120         c->pdir = buf+offset;
 121         offset += sp.dirlen;
 122     }
 123 
 124     /* Initialize parentPathv[] */
 125     ALLOC(parentPathv, sizeof (char *) * sp.nparentPathv)
 126     initVectorFromBlock ((const char**)parentPathv, buf+offset, sp.nparentPathv-1);
 127     offset += sp.parentPathvBytes;
 128 }
 129 
 130 int main(int argc, char *argv[]) {
 131     ChildStuff c;
 132     int t;
 133     struct stat buf;
 134     /* argv[0] contains the fd number to read all the child info */
 135     int r, fdin, fdout;
 136 
 137     r = sscanf (argv[argc-1], "%d:%d", &fdin, &fdout);
 138     if (r == 2 && fcntl(fdin, F_GETFD) != -1) {
 139         fstat(fdin, &buf);
 140         if (!S_ISFIFO(buf.st_mode))
 141             shutItDown();
 142     } else {
 143         shutItDown();
 144     }
 145     initChildStuff (fdin, fdout, &c);
 146 
 147     childProcess (&c);
 148     return 0; /* NOT REACHED */
 149 }