Runtime.java (exec): Convert prog name and arguments to string array.

* java/lang/Runtime.java (exec): Convert prog name and arguments
	to string array.
	* java/lang/natPosixProcess.cc (startProcess): Fix typo in
	environment array conversion. Preserve current environment if envp
	not passed. Preserve PATH unless explicitly specified.
	* java/io/DataInputStream.java (readLine): Fix case where '\r' is
	followed by EOF. Set a flag when a line is terminated by '\r' and
	ignore following '\n' if set.

From-SVN: r27458
This commit is contained in:
Bryce McKinlay 1999-06-09 17:42:26 +00:00 committed by Bryce McKinlay
parent 8d30c4ee01
commit 1e45a14105
4 changed files with 87 additions and 33 deletions

View file

@ -1,3 +1,14 @@
1999-06-09 Bryce McKinlay <bryce@albatross.co.nz>
* java/lang/Runtime.java (exec): Convert prog name and arguments
to string array.
* java/lang/natPosixProcess.cc (startProcess): Fix typo in
environment array conversion. Preserve current environment if envp
not passed. Preserve PATH unless explicitly specified.
* java/io/DataInputStream.java (readLine): Fix case where '\r' is
followed by EOF. Set a flag when a line is terminated by '\r' and
ignore following '\n' if set.
1999-06-02 Warren Levy <warrenl@cygnus.com> 1999-06-02 Warren Levy <warrenl@cygnus.com>
* java/net/URL.java (URL(URL,String)): Initialize port to -1. * java/net/URL.java (URL(URL,String)): Initialize port to -1.

View file

@ -21,6 +21,11 @@ package java.io;
public class DataInputStream extends FilterInputStream implements DataInput public class DataInputStream extends FilterInputStream implements DataInput
{ {
// readLine() hack to ensure that an '\r' not followed by an '\n' is
// handled correctly. If set, readLine() will ignore the first char it sees
// if that char is a '\n'
boolean ignoreInitialNewline = false;
public DataInputStream(InputStream in) public DataInputStream(InputStream in)
{ {
super(in); super(in);
@ -103,14 +108,29 @@ public class DataInputStream extends FilterInputStream implements DataInput
{ {
StringBuffer strb = new StringBuffer(); StringBuffer strb = new StringBuffer();
while (true) readloop: while (true)
{ {
int c = read(); int c = 0;
if (c < 0) // got an EOF char ch = ' ';
return strb.length() > 0 ? strb.toString() : null; boolean getnext = true;
char ch = (char) c; while (getnext)
if ((ch &= 0xFF) == '\n') {
break; getnext = false;
c = read();
if (c < 0) // got an EOF
return strb.length() > 0 ? strb.toString() : null;
ch = (char) c;
if ((ch &= 0xFF) == '\n')
// hack to correctly handle '\r\n' sequences
if (ignoreInitialNewline)
{
ignoreInitialNewline = false;
getnext = true;
}
else
break readloop;
}
if (ch == '\r') if (ch == '\r')
{ {
// FIXME: The following code tries to adjust the stream back one // FIXME: The following code tries to adjust the stream back one
@ -134,18 +154,35 @@ public class DataInputStream extends FilterInputStream implements DataInput
// and since it is undesirable to make non-deprecated methods // and since it is undesirable to make non-deprecated methods
// less efficient, the following seems like the most reasonable // less efficient, the following seems like the most reasonable
// approach. // approach.
if (in instanceof BufferedInputStream && (read() & 0xFF) != '\n') int next_c = 0;
char next_ch = ' ';
if (in instanceof BufferedInputStream)
{ {
BufferedInputStream bin = (BufferedInputStream) in; next_c = read();
if (bin.pos > 0) next_ch = (char) (next_c & 0xFF);
bin.pos--; if ((next_ch != '\n') && (next_c >= 0))
{
BufferedInputStream bin = (BufferedInputStream) in;
if (bin.pos > 0)
bin.pos--;
}
} }
else if (markSupported()) else if (markSupported())
{ {
mark(1); next_c = read();
if ((read() & 0xFF) != '\n') next_ch = (char) (next_c & 0xFF);
reset(); if ((next_ch != '\n') && (next_c >= 0))
} {
mark(1);
if ((read() & 0xFF) != '\n')
reset();
}
}
// In order to catch cases where 'in' isn't a BufferedInputStream
// and doesn't support mark() (such as reading from a Socket), set
// a flag that instructs readLine() to ignore the first character
// it sees _if_ that character is a '\n'.
else ignoreInitialNewline = true;
break; break;
} }
strb.append(ch); strb.append(ch);

View file

@ -13,6 +13,7 @@ package java.lang;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.StringTokenizer;
/** /**
* @author Tom Tromey <tromey@cygnus.com> * @author Tom Tromey <tromey@cygnus.com>
@ -30,15 +31,15 @@ public class Runtime
{ {
public Process exec (String prog) throws IOException public Process exec (String prog) throws IOException
{ {
String[] a = new String[1]; return exec (prog, null);
a[0] = prog;
return exec (a, null);
} }
public Process exec (String prog, String[] envp) throws IOException public Process exec (String prog, String[] envp) throws IOException
{ {
String[] a = new String[1]; StringTokenizer st = new StringTokenizer(prog);
a[0] = prog; String[] a = new String[st.countTokens ()];
for (int i = 0; i < a.length; i++)
a[i] = st.nextToken ();
return exec (a, envp); return exec (a, envp);
} }

View file

@ -20,6 +20,7 @@ details. */
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <cni.h> #include <cni.h>
#include <jvm.h> #include <jvm.h>
@ -115,15 +116,7 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray,
// thrown we will leak memory. // thrown we will leak memory.
char **args = (char **) _Jv_Malloc ((progarray->length + 1) char **args = (char **) _Jv_Malloc ((progarray->length + 1)
* sizeof (char *)); * sizeof (char *));
char **env = NULL; char **env = NULL;
if (envp)
env = (char **) _Jv_Malloc ((envp->length + 1) * sizeof (char *));
// for (int i = 0; i < progarray->length; ++i)
// args[i] = NULL;
// for (int i = 0; i < envp->length; ++i)
// env[i] = NULL;
// FIXME: GC will fail here if _Jv_Malloc throws an exception. // FIXME: GC will fail here if _Jv_Malloc throws an exception.
// That's because we have to manually free the contents, but we // That's because we have to manually free the contents, but we
@ -134,10 +127,11 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray,
if (envp) if (envp)
{ {
env = (char **) _Jv_Malloc ((envp->length + 1) * sizeof (char *));
elts = elements (envp); elts = elements (envp);
for (int i = 0; i < envp->length; ++i) for (int i = 0; i < envp->length; ++i)
args[i] = new_string (elts[i]); env[i] = new_string (elts[i]);
args[envp->length] = NULL; env[envp->length] = NULL;
} }
// Create pipes for I/O. // Create pipes for I/O.
@ -172,8 +166,18 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray,
// Child process, so remap descriptors and exec. // Child process, so remap descriptors and exec.
if (envp) if (envp)
environ = env; {
// preserve PATH unless specified explicitly
char *path_val = getenv("PATH");
environ = env;
if (getenv("PATH") == NULL)
{
char *path_env = (char *) _Jv_Malloc (strlen(path_val) + 5 + 1);
sprintf (path_env, "PATH=%s", path_val);
putenv (path_env);
}
}
// We ignore errors from dup2 because they should never occur. // We ignore errors from dup2 because they should never occur.
dup2 (outp[0], 0); dup2 (outp[0], 0);
dup2 (inp[1], 1); dup2 (inp[1], 1);
@ -186,8 +190,9 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray,
close (outp[0]); close (outp[0]);
close (outp[1]); close (outp[1]);
environ = env;
execvp (args[0], args); execvp (args[0], args);
// FIXME: should throw an IOException if execvp() fails. Not trivial,
// because _Jv_Throw won't work from child process
_exit (127); _exit (127);
} }