OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [native/] [jni/] [java-lang/] [java_lang_VMProcess.c] - Blame information for rev 774

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 774 jeremybenn
/* java_lang_VMProcess.c -- native code for java.lang.VMProcess
2
   Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
#include <config.h>
39
 
40
#include "java_lang_VMProcess.h"
41
#include "gnu_java_nio_FileChannelImpl.h"
42
 
43
#include <sys/types.h>
44
#include <sys/wait.h>
45
#include <signal.h>
46
#include <stdlib.h>
47
#include <unistd.h>
48
#include <string.h>
49
#include <errno.h>
50
#include <fcntl.h>
51
#include <stdio.h>
52
 
53
#include "cpnative.h"
54
#include "cpproc.h"
55
 
56
/* Internal functions */
57
static char *copy_string (JNIEnv * env, jobject string);
58
static char *copy_elem (JNIEnv * env, jobject stringArray, jint i);
59
 
60
/*
61
 * Internal helper function to copy a String in UTF-8 format.
62
 */
63
static char *
64
copy_string (JNIEnv * env, jobject string)
65
{
66
  const char *utf;
67
  jclass clazz;
68
  char *copy;
69
 
70
  /* Check for null */
71
  if (string == NULL)
72
    {
73
      clazz = (*env)->FindClass (env, "java/lang/NullPointerException");
74
      if ((*env)->ExceptionOccurred (env))
75
        return NULL;
76
      (*env)->ThrowNew (env, clazz, NULL);
77
      (*env)->DeleteLocalRef (env, clazz);
78
      return NULL;
79
    }
80
 
81
  /* Extract UTF-8 */
82
  utf = (*env)->GetStringUTFChars (env, string, NULL);
83
  if ((*env)->ExceptionOccurred (env))
84
    return NULL;
85
 
86
  /* Copy it */
87
  if ((copy = strdup (utf)) == NULL)
88
    {
89
      clazz = (*env)->FindClass (env, "java/lang/InternalError");
90
      if ((*env)->ExceptionOccurred (env))
91
        return NULL;
92
      (*env)->ThrowNew (env, clazz, "strdup returned NULL");
93
      (*env)->DeleteLocalRef (env, clazz);
94
    }
95
 
96
  /* Done */
97
  (*env)->ReleaseStringUTFChars (env, string, utf);
98
  return copy;
99
}
100
 
101
/*
102
 * Internal helper function to copy a String[] element in UTF-8 format.
103
 */
104
static char *
105
copy_elem (JNIEnv * env, jobject stringArray, jint i)
106
{
107
  jobject elem;
108
  char *rtn;
109
 
110
  elem = (*env)->GetObjectArrayElement (env, stringArray, i);
111
  if ((*env)->ExceptionOccurred (env))
112
    return NULL;
113
  if ((rtn = copy_string (env, elem)) == NULL)
114
    return NULL;
115
  (*env)->DeleteLocalRef (env, elem);
116
  return rtn;
117
}
118
 
119
/*
120
 * private final native void nativeSpawn(String[], String[], File)
121
 *      throws java/io/IOException
122
 */
123
JNIEXPORT void JNICALL
124
Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this,
125
                                      jobjectArray cmdArray,
126
                                      jobjectArray envArray, jobject dirFile,
127
                                      jboolean redirect)
128
{
129
  int fds[CPIO_EXEC_NUM_PIPES];
130
  jobject streams[CPIO_EXEC_NUM_PIPES] = { NULL, NULL, NULL };
131
  jobject dirString = NULL;
132
  char **newEnviron = NULL;
133
  jsize cmdArrayLen = 0;
134
  jsize envArrayLen = 0;
135
  char **strings = NULL;
136
  int num_strings = 0;
137
  char *dir = NULL;
138
  pid_t pid = -1;
139
  char errbuf[64];
140
  jmethodID method, vmmethod;
141
  jclass clazz, vmclazz;
142
  int i;
143
  int pipe_count = redirect ? 2 : 3;
144
  int err;
145
 
146
  /* Check for null */
147
  if (cmdArray == NULL)
148
    goto null_pointer_exception;
149
 
150
  /* Invoke dirFile.getPath() */
151
  if (dirFile != NULL)
152
    {
153
      clazz = (*env)->FindClass (env, "java/io/File");
154
      if ((*env)->ExceptionOccurred (env))
155
        return;
156
      method = (*env)->GetMethodID (env,
157
                                    clazz, "getPath", "()Ljava/lang/String;");
158
      if ((*env)->ExceptionOccurred (env))
159
        return;
160
      dirString = (*env)->CallObjectMethod (env, dirFile, method);
161
      if ((*env)->ExceptionOccurred (env))
162
        return;
163
      (*env)->DeleteLocalRef (env, clazz);
164
    }
165
 
166
  /*
167
   * Allocate array of C strings. We put all the C strings we need to
168
   * handle the command parameters, the new environment, and the new
169
   * directory into a single array for simplicity of (de)allocation.
170
   */
171
  cmdArrayLen = (*env)->GetArrayLength (env, cmdArray);
172
  if (cmdArrayLen == 0)
173
    goto null_pointer_exception;
174
  if (envArray != NULL)
175
    envArrayLen = (*env)->GetArrayLength (env, envArray);
176
  if ((strings = malloc (((cmdArrayLen + 1)
177
                          + (envArray != NULL ? envArrayLen + 1 : 0)
178
                          + (dirString !=
179
                             NULL ? 1 : 0)) * sizeof (*strings))) == NULL)
180
    {
181
      strncpy (errbuf, "malloc failed", sizeof(errbuf));
182
      goto out_of_memory;
183
    }
184
 
185
  /* Extract C strings from the various String parameters */
186
  for (i = 0; i < cmdArrayLen; i++)
187
    {
188
      if ((strings[num_strings++] = copy_elem (env, cmdArray, i)) == NULL)
189
        goto done;
190
    }
191
  strings[num_strings++] = NULL;        /* terminate array with NULL */
192
  if (envArray != NULL)
193
    {
194
      newEnviron = strings + num_strings;
195
      for (i = 0; i < envArrayLen; i++)
196
        {
197
          if ((strings[num_strings++] = copy_elem (env, envArray, i)) == NULL)
198
            goto done;
199
        }
200
      strings[num_strings++] = NULL;    /* terminate array with NULL */
201
    }
202
  if (dirString != NULL)
203
    {
204
      if ((dir = copy_string (env, dirString)) == NULL)
205
        goto done;
206
    }
207
 
208
  /* Create inter-process pipes */
209
  err = cpproc_forkAndExec(strings, newEnviron, fds, pipe_count, &pid, dir);
210
  if (err != 0)
211
    {
212
      strncpy(errbuf, cpnative_getErrorString (err), sizeof(errbuf));
213
      goto system_error;
214
    }
215
 
216
  /* Create Input/OutputStream objects around parent file descriptors */
217
  vmclazz = (*env)->FindClass (env, "gnu/java/nio/VMChannel");
218
  clazz = (*env)->FindClass (env, "gnu/java/nio/FileChannelImpl");
219
  if ((*env)->ExceptionOccurred (env))
220
    goto done;
221
  vmmethod = (*env)->GetMethodID (env, vmclazz, "<init>", "(I)V");
222
  method = (*env)->GetMethodID (env, clazz, "<init>", "(Lgnu/java/nio/VMChannel;I)V");
223
  if ((*env)->ExceptionOccurred (env))
224
    goto done;
225
  for (i = 0; i < pipe_count; i++)
226
    {
227
      /* Mode is WRITE (2) for in and READ (1) for out and err. */
228
      const int fd = fds[i];
229
      const int mode = ((i == CPIO_EXEC_STDIN) ? 2 : 1);
230
      jclass sclazz;
231
      jmethodID smethod;
232
 
233
      jobject vmchannel;
234
      jobject channel;
235
      vmchannel = (*env)->NewObject (env, vmclazz, vmmethod, fd);
236
      if ((*env)->ExceptionOccurred (env))
237
        goto done;
238
      channel = (*env)->NewObject (env, clazz, method, vmchannel, mode);
239
      if ((*env)->ExceptionOccurred (env))
240
        goto done;
241
 
242
      if (mode == gnu_java_nio_FileChannelImpl_WRITE)
243
        sclazz = (*env)->FindClass (env, "java/io/FileOutputStream");
244
      else
245
        sclazz = (*env)->FindClass (env, "java/io/FileInputStream");
246
      if ((*env)->ExceptionOccurred (env))
247
        goto done;
248
 
249
      smethod = (*env)->GetMethodID (env, sclazz, "<init>",
250
                                     "(Lgnu/java/nio/FileChannelImpl;)V");
251
      if ((*env)->ExceptionOccurred (env))
252
        goto done;
253
 
254
      streams[i] = (*env)->NewObject (env, sclazz, smethod, channel);
255
      if ((*env)->ExceptionOccurred (env))
256
        goto done;
257
 
258
      (*env)->DeleteLocalRef (env, sclazz);
259
    }
260
  (*env)->DeleteLocalRef (env, clazz);
261
 
262
  /* Invoke VMProcess.setProcessInfo() to update VMProcess object */
263
  method = (*env)->GetMethodID (env,
264
                                (*env)->GetObjectClass (env, this),
265
                                "setProcessInfo",
266
                                "(Ljava/io/OutputStream;Ljava/io/InputStream;Ljava/io/InputStream;J)V");
267
  if ((*env)->ExceptionOccurred (env))
268
    goto done;
269
  (*env)->CallVoidMethod (env, this, method,
270
                          streams[CPIO_EXEC_STDIN],
271
                          streams[CPIO_EXEC_STDOUT],
272
                          streams[CPIO_EXEC_STDERR],
273
                          (jlong) pid);
274
  if ((*env)->ExceptionOccurred (env))
275
    goto done;
276
 
277
done:
278
  /*
279
   * We get here in both the success and failure cases in the
280
   * parent process. Our goal is to clean up the mess we created.
281
   */
282
 
283
  /*
284
   * Close parent's ends of pipes if Input/OutputStreams never got created.
285
   * This can only happen in a failure case. If a Stream object
286
   * was created for a file descriptor, we don't close it because it
287
   * will get closed when the Stream object is finalized.
288
   */
289
  for (i = 0; i < pipe_count; i++)
290
    {
291
      const int fd = fds[i];
292
 
293
      if (fd != -1 && streams[i] == NULL)
294
        close (fd);
295
    }
296
 
297
  /* Free C strings */
298
  while (num_strings > 0)
299
    free (strings[--num_strings]);
300
  free (strings);
301
  if (dir != NULL)
302
    free(dir);
303
  /* Done */
304
  return;
305
 
306
null_pointer_exception:
307
  clazz = (*env)->FindClass (env, "java/lang/NullPointerException");
308
  if ((*env)->ExceptionOccurred (env))
309
    goto done;
310
  (*env)->ThrowNew (env, clazz, NULL);
311
  (*env)->DeleteLocalRef (env, clazz);
312
  goto done;
313
 
314
out_of_memory:
315
  clazz = (*env)->FindClass (env, "java/lang/InternalError");
316
  if ((*env)->ExceptionOccurred (env))
317
    goto done;
318
  (*env)->ThrowNew (env, clazz, errbuf);
319
  (*env)->DeleteLocalRef (env, clazz);
320
  goto done;
321
 
322
system_error:
323
  clazz = (*env)->FindClass (env, "java/io/IOException");
324
  if ((*env)->ExceptionOccurred (env))
325
    goto done;
326
  (*env)->ThrowNew (env, clazz, errbuf);
327
  (*env)->DeleteLocalRef (env, clazz);
328
  goto done;
329
}
330
 
331
/*
332
 * private static final native boolean nativeReap()
333
 */
334
JNIEXPORT jboolean JNICALL
335
Java_java_lang_VMProcess_nativeReap (JNIEnv * env, jclass clazz)
336
{
337
  char ebuf[64];
338
  jfieldID field;
339
  jint status;
340
  pid_t pid;
341
  int err;
342
 
343
  /* Try to reap a child process, but don't block */
344
  err = cpproc_waitpid((pid_t)-1, &status, &pid, WNOHANG);
345
  if (err == 0 && pid == 0)
346
    return JNI_FALSE;
347
 
348
  /* Check result from waitpid() */
349
  if (err != 0)
350
    {
351
      if (err == ECHILD || err == EINTR)
352
        return JNI_FALSE;
353
      snprintf(ebuf, sizeof (ebuf), "waitpid(%ld): %s",
354
               (long) pid, cpnative_getErrorString(errno));
355
      clazz = (*env)->FindClass (env, "java/lang/InternalError");
356
      if ((*env)->ExceptionOccurred (env))
357
        return JNI_FALSE;
358
      (*env)->ThrowNew (env, clazz, ebuf);
359
      (*env)->DeleteLocalRef (env, clazz);
360
      return JNI_FALSE;
361
    }
362
 
363
  /* Get exit code; for signal termination return negative signal value XXX */
364
  if (WIFEXITED (status))
365
    status = (jint) (jbyte) WEXITSTATUS (status);
366
  else if (WIFSIGNALED (status))
367
    status = -(jint) WTERMSIG (status);
368
  else
369
    return JNI_FALSE;           /* process merely stopped; ignore */
370
 
371
  /* Return process pid and exit status */
372
  field = (*env)->GetStaticFieldID (env, clazz, "reapedPid", "J");
373
  if ((*env)->ExceptionOccurred (env))
374
    return JNI_FALSE;
375
  (*env)->SetStaticLongField (env, clazz, field, (jlong) pid);
376
  if ((*env)->ExceptionOccurred (env))
377
    return JNI_FALSE;
378
  field = (*env)->GetStaticFieldID (env, clazz, "reapedExitValue", "I");
379
  if ((*env)->ExceptionOccurred (env))
380
    return JNI_FALSE;
381
  (*env)->SetStaticIntField (env, clazz, field, status);
382
  if ((*env)->ExceptionOccurred (env))
383
    return JNI_FALSE;
384
 
385
  /* Done */
386
  return JNI_TRUE;
387
}
388
 
389
/*
390
 * private static final native void nativeKill(long)
391
 */
392
JNIEXPORT void JNICALL
393
Java_java_lang_VMProcess_nativeKill (JNIEnv * env, jclass clazz, jlong pid)
394
{
395
  char ebuf[64];
396
  int err;
397
 
398
  err = cpproc_kill((pid_t) pid, SIGKILL);
399
  if (err != 0)
400
    {
401
      snprintf (ebuf, sizeof (ebuf), "kill(%ld): %s",
402
                (long) pid, cpnative_getErrorString (err));
403
      clazz = (*env)->FindClass (env, "java/lang/InternalError");
404
      if ((*env)->ExceptionOccurred (env))
405
        return;
406
      (*env)->ThrowNew (env, clazz, ebuf);
407
      (*env)->DeleteLocalRef (env, clazz);
408
    }
409
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.