• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/
1/* Execute a C# program.
2   Copyright (C) 2003-2007 Free Software Foundation, Inc.
3   Written by Bruno Haible <bruno@clisp.org>, 2003.
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 3 of the License, or
8   (at your option) 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, see <http://www.gnu.org/licenses/>.  */
17
18#include <config.h>
19#include <alloca.h>
20
21/* Specification.  */
22#include "csharpexec.h"
23
24#include <stdio.h>
25#include <stdlib.h>
26
27#include "execute.h"
28#include "sh-quote.h"
29#include "xmalloca.h"
30#include "error.h"
31#include "gettext.h"
32
33/* Handling of MONO_PATH is just like Java CLASSPATH.  */
34#define CLASSPATHVAR "MONO_PATH"
35#define new_classpath new_monopath
36#define set_classpath set_monopath
37#define reset_classpath reset_monopath
38#include "classpath.h"
39#include "classpath.c"
40#undef reset_classpath
41#undef set_classpath
42#undef new_classpath
43#undef CLASSPATHVAR
44
45/* Handling of clix' PATH variable is just like Java CLASSPATH.  */
46#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
47  /* Win32, Cygwin */
48  #define CLASSPATHVAR "PATH"
49#elif defined __APPLE__ && defined __MACH__
50  /* MacOS X */
51  #define CLASSPATHVAR "DYLD_LIBRARY_PATH"
52#else
53  /* Normal Unix */
54  #define CLASSPATHVAR "LD_LIBRARY_PATH"
55#endif
56#define new_classpath new_clixpath
57#define set_classpath set_clixpath
58#define reset_classpath reset_clixpath
59#include "classpath.h"
60#include "classpath.c"
61#undef reset_classpath
62#undef set_classpath
63#undef new_classpath
64#undef CLASSPATHVAR
65
66#define _(str) gettext (str)
67
68
69/* Survey of CIL interpreters.
70
71   Program    from
72
73   ilrun      pnet
74   mono       mono
75   clix       sscli
76
77   With Mono, the MONO_PATH is a colon separated list of pathnames. (On
78   Windows: semicolon separated list of pathnames.)
79
80   We try the CIL interpreters in the following order:
81     1. "ilrun", because it is a completely free system.
82     2. "mono", because it is a partially free system but doesn't integrate
83        well with Unix.
84     3. "clix", although it is not free, because it is a kind of "reference
85        implementation" of C#.
86   But the order can be changed through the --enable-csharp configuration
87   option.
88 */
89
90static int
91execute_csharp_using_pnet (const char *assembly_path,
92			   const char * const *libdirs,
93			   unsigned int libdirs_count,
94			   const char * const *args, unsigned int nargs,
95			   bool verbose, bool quiet,
96			   execute_fn *executer, void *private_data)
97{
98  static bool ilrun_tested;
99  static bool ilrun_present;
100
101  if (!ilrun_tested)
102    {
103      /* Test for presence of ilrun:
104	 "ilrun --version >/dev/null 2>/dev/null"  */
105      char *argv[3];
106      int exitstatus;
107
108      argv[0] = "ilrun";
109      argv[1] = "--version";
110      argv[2] = NULL;
111      exitstatus = execute ("ilrun", "ilrun", argv, false, false, true, true,
112			    true, false);
113      ilrun_present = (exitstatus == 0);
114      ilrun_tested = true;
115    }
116
117  if (ilrun_present)
118    {
119      unsigned int argc;
120      char **argv;
121      char **argp;
122      unsigned int i;
123      bool err;
124
125      argc = 1 + 2 * libdirs_count + 1 + nargs;
126      argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
127
128      argp = argv;
129      *argp++ = "ilrun";
130      for (i = 0; i < libdirs_count; i++)
131	{
132	  *argp++ = "-L";
133	  *argp++ = (char *) libdirs[i];
134	}
135      *argp++ = (char *) assembly_path;
136      for (i = 0; i < nargs; i++)
137	*argp++ = (char *) args[i];
138      *argp = NULL;
139      /* Ensure argv length was correctly calculated.  */
140      if (argp - argv != argc)
141	abort ();
142
143      if (verbose)
144	{
145	  char *command = shell_quote_argv (argv);
146	  printf ("%s\n", command);
147	  free (command);
148	}
149
150      err = executer ("ilrun", "ilrun", argv, private_data);
151
152      freea (argv);
153
154      return err;
155    }
156  else
157    return -1;
158}
159
160static int
161execute_csharp_using_mono (const char *assembly_path,
162			   const char * const *libdirs,
163			   unsigned int libdirs_count,
164			   const char * const *args, unsigned int nargs,
165			   bool verbose, bool quiet,
166			   execute_fn *executer, void *private_data)
167{
168  static bool mono_tested;
169  static bool mono_present;
170
171  if (!mono_tested)
172    {
173      /* Test for presence of mono:
174	 "mono --version >/dev/null 2>/dev/null"  */
175      char *argv[3];
176      int exitstatus;
177
178      argv[0] = "mono";
179      argv[1] = "--version";
180      argv[2] = NULL;
181      exitstatus = execute ("mono", "mono", argv, false, false, true, true,
182			    true, false);
183      mono_present = (exitstatus == 0);
184      mono_tested = true;
185    }
186
187  if (mono_present)
188    {
189      char *old_monopath;
190      char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *));
191      unsigned int i;
192      bool err;
193
194      /* Set MONO_PATH.  */
195      old_monopath = set_monopath (libdirs, libdirs_count, false, verbose);
196
197      argv[0] = "mono";
198      argv[1] = (char *) assembly_path;
199      for (i = 0; i <= nargs; i++)
200	argv[2 + i] = (char *) args[i];
201
202      if (verbose)
203	{
204	  char *command = shell_quote_argv (argv);
205	  printf ("%s\n", command);
206	  free (command);
207	}
208
209      err = executer ("mono", "mono", argv, private_data);
210
211      /* Reset MONO_PATH.  */
212      reset_monopath (old_monopath);
213
214      freea (argv);
215
216      return err;
217    }
218  else
219    return -1;
220}
221
222static int
223execute_csharp_using_sscli (const char *assembly_path,
224			    const char * const *libdirs,
225			    unsigned int libdirs_count,
226			    const char * const *args, unsigned int nargs,
227			    bool verbose, bool quiet,
228			    execute_fn *executer, void *private_data)
229{
230  static bool clix_tested;
231  static bool clix_present;
232
233  if (!clix_tested)
234    {
235      /* Test for presence of clix:
236	 "clix >/dev/null 2>/dev/null ; test $? = 1"  */
237      char *argv[2];
238      int exitstatus;
239
240      argv[0] = "clix";
241      argv[1] = NULL;
242      exitstatus = execute ("clix", "clix", argv, false, false, true, true,
243			    true, false);
244      clix_present = (exitstatus == 0 || exitstatus == 1);
245      clix_tested = true;
246    }
247
248  if (clix_present)
249    {
250      char *old_clixpath;
251      char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *));
252      unsigned int i;
253      bool err;
254
255      /* Set clix' PATH variable.  */
256      old_clixpath = set_clixpath (libdirs, libdirs_count, false, verbose);
257
258      argv[0] = "clix";
259      argv[1] = (char *) assembly_path;
260      for (i = 0; i <= nargs; i++)
261	argv[2 + i] = (char *) args[i];
262
263      if (verbose)
264	{
265	  char *command = shell_quote_argv (argv);
266	  printf ("%s\n", command);
267	  free (command);
268	}
269
270      err = executer ("clix", "clix", argv, private_data);
271
272      /* Reset clix' PATH variable.  */
273      reset_clixpath (old_clixpath);
274
275      freea (argv);
276
277      return err;
278    }
279  else
280    return -1;
281}
282
283bool
284execute_csharp_program (const char *assembly_path,
285			const char * const *libdirs,
286			unsigned int libdirs_count,
287			const char * const *args,
288			bool verbose, bool quiet,
289			execute_fn *executer, void *private_data)
290{
291  unsigned int nargs;
292  int result;
293
294  /* Count args.  */
295  {
296    const char * const *arg;
297
298    for (nargs = 0, arg = args; *arg != NULL; nargs++, arg++)
299     ;
300  }
301
302  /* First try the C# implementation specified through --enable-csharp.  */
303#if CSHARP_CHOICE_PNET
304  result = execute_csharp_using_pnet (assembly_path, libdirs, libdirs_count,
305				      args, nargs, verbose, quiet,
306				      executer, private_data);
307  if (result >= 0)
308    return (bool) result;
309#endif
310
311#if CSHARP_CHOICE_MONO
312  result = execute_csharp_using_mono (assembly_path, libdirs, libdirs_count,
313				      args, nargs, verbose, quiet,
314				      executer, private_data);
315  if (result >= 0)
316    return (bool) result;
317#endif
318
319  /* Then try the remaining C# implementations in our standard order.  */
320#if !CSHARP_CHOICE_PNET
321  result = execute_csharp_using_pnet (assembly_path, libdirs, libdirs_count,
322				      args, nargs, verbose, quiet,
323				      executer, private_data);
324  if (result >= 0)
325    return (bool) result;
326#endif
327
328#if !CSHARP_CHOICE_MONO
329  result = execute_csharp_using_mono (assembly_path, libdirs, libdirs_count,
330				      args, nargs, verbose, quiet,
331				      executer, private_data);
332  if (result >= 0)
333    return (bool) result;
334#endif
335
336  result = execute_csharp_using_sscli (assembly_path, libdirs, libdirs_count,
337				       args, nargs, verbose, quiet,
338				       executer, private_data);
339  if (result >= 0)
340    return (bool) result;
341
342  if (!quiet)
343    error (0, 0, _("C# virtual machine not found, try installing pnet"));
344  return true;
345}
346