New module 'javaversion'.
[gnulib.git] / lib / javaversion.c
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 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 /* Specification.  */
24 #include "javaversion.h"
25
26 #include <errno.h>
27 #include <stdbool.h>
28 #include <stdio.h>
29
30 #if ENABLE_RELOCATABLE
31 # include "relocatable.h"
32 #else
33 # define relocate(pathname) (pathname)
34 #endif
35
36 #include "javaexec.h"
37 #include "pipe.h"
38 #include "wait-process.h"
39 #include "error.h"
40 #include "getline.h"
41 #include "gettext.h"
42
43 #define _(str) gettext (str)
44
45
46 struct locals
47 {
48   /* OUT */
49   char *line;
50 };
51
52 static bool
53 execute_and_read_line (const char *progname,
54                        const char *prog_path, char **prog_argv,
55                        void *private_data)
56 {
57   struct locals *l = (struct locals *) private_data;
58   pid_t child;
59   int fd[1];
60   FILE *fp;
61   char *line;
62   size_t linesize;
63   size_t linelen;
64   int exitstatus;
65
66   /* Open a pipe to the JVM.  */
67   child = create_pipe_in (progname, prog_path, prog_argv, DEV_NULL, false,
68                           true, false, fd);
69
70   if (child == -1)
71     return false;
72
73   /* Retrieve its result.  */
74   fp = fdopen (fd[0], "r");
75   if (fp == NULL)
76     {
77       error (0, errno, _("fdopen() failed"));
78       return false;
79     }
80
81   line = NULL; linesize = 0;
82   linelen = getline (&line, &linesize, fp);
83   if (linelen == (size_t)(-1))
84     {
85       error (0, 0, _("%s subprocess I/O error"), progname);
86       return false;
87     }
88   if (linelen > 0 && line[linelen - 1] == '\n')
89     line[linelen - 1] = '\0';
90
91   fclose (fp);
92
93   /* Remove zombie process from process list, and retrieve exit status.  */
94   exitstatus = wait_subprocess (child, progname, true, false, true, false);
95   if (exitstatus != 0)
96     {
97       free (line);
98       return false;
99     }
100
101   l->line = line;
102   return false;
103 }
104
105 char *
106 javaexec_version (void)
107 {
108   const char *class_name = "javaversion";
109   const char *pkgdatadir = relocate (PKGDATADIR);
110   const char *args[1];
111   struct locals locals;
112
113   args[0] = NULL;
114   locals.line = NULL;
115   execute_java_class (class_name, &pkgdatadir, 1, true, NULL, args,
116                       false, false, execute_and_read_line, &locals);
117
118   return locals.line;
119 }