1 /* Determine the Java version supported by javaexec.
2    Copyright (C) 2006 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2006.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2, or (at your option)
8    any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software Foundation,
17    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18 
19 #include <config.h>
20 
21 /* Specification.  */
22 #include "javaversion.h"
23 
24 #include <errno.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 
28 #if ENABLE_RELOCATABLE
29 # include "relocatable.h"
30 #else
31 # define relocate(pathname) (pathname)
32 #endif
33 
34 /* Get PKGDATADIR.  */
35 #ifndef PKGDATADIR
36 #include "configmake.h"
37 #endif
38 
39 #include "javaexec.h"
40 #include "pipe.h"
41 #include "wait-process.h"
42 #include "error.h"
43 #include "getline.h"
44 #include "gettext.h"
45 
46 #define _(str) gettext (str)
47 
48 
49 struct locals
50 {
51   /* OUT */
52   char *line;
53 };
54 
55 static bool
execute_and_read_line(const char * progname,const char * prog_path,char ** prog_argv,void * private_data)56 execute_and_read_line (const char *progname,
57 		       const char *prog_path, char **prog_argv,
58 		       void *private_data)
59 {
60   struct locals *l = (struct locals *) private_data;
61   pid_t child;
62   int fd[1];
63   FILE *fp;
64   char *line;
65   size_t linesize;
66   size_t linelen;
67   int exitstatus;
68 
69   /* Open a pipe to the JVM.  */
70   child = create_pipe_in (progname, prog_path, prog_argv, DEV_NULL, false,
71 			  true, false, fd);
72 
73   if (child == -1)
74     return false;
75 
76   /* Retrieve its result.  */
77   fp = fdopen (fd[0], "r");
78   if (fp == NULL)
79     {
80       error (0, errno, _("fdopen() failed"));
81       return false;
82     }
83 
84   line = NULL; linesize = 0;
85   linelen = getline (&line, &linesize, fp);
86   if (linelen == (size_t)(-1))
87     {
88       error (0, 0, _("%s subprocess I/O error"), progname);
89       return false;
90     }
91   if (linelen > 0 && line[linelen - 1] == '\n')
92     line[linelen - 1] = '\0';
93 
94   fclose (fp);
95 
96   /* Remove zombie process from process list, and retrieve exit status.  */
97   exitstatus = wait_subprocess (child, progname, true, false, true, false);
98   if (exitstatus != 0)
99     {
100       free (line);
101       return false;
102     }
103 
104   l->line = line;
105   return false;
106 }
107 
108 char *
javaexec_version(void)109 javaexec_version (void)
110 {
111   const char *class_name = "javaversion";
112   const char *pkgdatadir = relocate (PKGDATADIR);
113   const char *args[1];
114   struct locals locals;
115 
116   args[0] = NULL;
117   locals.line = NULL;
118   execute_java_class (class_name, &pkgdatadir, 1, true, NULL, args,
119 		      false, false, execute_and_read_line, &locals);
120 
121   return locals.line;
122 }
123