}
InputStream stdin = Boolean.valueOf(getSystemProperty("nestedvm.textstdin")).booleanValue() ? new TextInputStream(System.in) : System.in;
- addFD(new StdinFD(stdin));
- addFD(new StdoutFD(System.out));
- addFD(new StdoutFD(System.err));
+ addFD(new TerminalFD(stdin));
+ addFD(new TerminalFD(System.out));
+ addFD(new TerminalFD(System.err));
}
/** Copy everything from <i>src</i> to <i>addr</i> initializing uninitialized pages if required.
protected void _close() { try { data.close(); } catch(IOException e) { /*ignore*/ } }
}
- public static class OutputStreamFD extends FD {
- private OutputStream os;
- public int flags() { return O_WRONLY; }
- public OutputStreamFD(OutputStream os) { this.os = os; }
- public int write(byte[] a, int off, int length) throws ErrnoException {
- try {
- os.write(a,off,length);
- return length;
- } catch(IOException e) {
- throw new ErrnoException(EIO);
- }
+ public static class InputOutputStreamFD extends FD {
+ private final InputStream is;
+ private final OutputStream os;
+
+ public InputOutputStreamFD(InputStream is) { this(is,null); }
+ public InputOutputStreamFD(OutputStream os) { this(null,os); }
+ public InputOutputStreamFD(InputStream is, OutputStream os) {
+ this.is = is;
+ this.os = os;
+ if(is == null && os == null) throw new IllegalArgumentException("at least one stream must be supplied");
}
- public void _close() { try { os.close(); } catch(IOException e) { /*ignore*/ } }
- public FStat _fstat() { return new FStat(); }
- }
-
- public static class InputStreamFD extends FD {
- private InputStream is;
- public int flags() { return O_RDONLY; }
- public InputStreamFD(InputStream is) { this.is = is; }
+
+ public int flags() {
+ if(is != null && os != null) return O_RDWR;
+ if(is != null) return O_RDONLY;
+ if(os != null) return O_WRONLY;
+ throw new Error("should never happen");
+ }
+
+ public void _close() {
+ try {is.close(); } catch(IOException e) { /*ignore*/ }
+ try {os.close(); } catch(IOException e) { /*ignore*/ }
+ }
+
public int read(byte[] a, int off, int length) throws ErrnoException {
+ if(is == null) return super.read(a,off,length);
try {
int n = is.read(a,off,length);
return n < 0 ? 0 : n;
} catch(IOException e) {
throw new ErrnoException(EIO);
}
+ }
+
+ public int write(byte[] a, int off, int length) throws ErrnoException {
+ if(os == null) return super.write(a,off,length);
+ try {
+ os.write(a,off,length);
+ return length;
+ } catch(IOException e) {
+ throw new ErrnoException(EIO);
+ }
}
- public void _close() { try { is.close(); } catch(IOException e) { /*ignore*/ } }
+
public FStat _fstat() { return new FStat(); }
}
- static class StdinFD extends InputStreamFD {
- public StdinFD(InputStream is) { super(is); }
- public void _close() { /* noop */ }
- public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; }
- }
-
- static class StdoutFD extends OutputStreamFD {
- public StdoutFD(OutputStream os) { super(os); }
+ static class TerminalFD extends InputOutputStreamFD {
+ public TerminalFD(InputStream is) { this(is,null); }
+ public TerminalFD(OutputStream os) { this(null,os); }
+ public TerminalFD(InputStream is, OutputStream os) { super(is,os); }
public void _close() { /* noop */ }
public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; }
}
import org.ibex.nestedvm.util.*;
import java.io.*;
import java.util.*;
+import java.net.Socket;
+import java.net.ServerSocket;
// FEATURE: vfork
case SYS_getdents: return sys_getdents(a,b,c,d);
case SYS_unlink: return sys_unlink(a);
case SYS_getppid: return sys_getppid();
+ case SYS_opensocket: return sys_opensocket(a,b);
+ case SYS_listensocket: return sys_listensocket(a);
+ case SYS_accept: return sys_accept(a);
default: return super._syscall(syscall,a,b,c,d);
}
return n;
}
+ private static class SocketFD extends InputOutputStreamFD {
+ private final Socket s;
+
+ public SocketFD(Socket s) throws IOException {
+ super(s.getInputStream(),s.getOutputStream());
+ this.s = s;
+ }
+
+ public void _close() { try { s.close(); } catch(IOException e) { } }
+ }
+
+ public int sys_opensocket(int cstring, int port) throws FaultException, ErrnoException {
+ String hostname = cstring(cstring);
+ try {
+ FD fd = new SocketFD(new Socket(hostname,port));
+ int n = addFD(fd);
+ if(n == -1) fd.close();
+ return n;
+ } catch(IOException e) {
+ return -EIO;
+ }
+ }
+
+ private static class ListenSocketFD extends FD {
+ ServerSocket s;
+ public ListenSocketFD(ServerSocket s) { this.s = s; }
+ public int flags() { return 0; }
+ // FEATURE: What should these be?
+ public FStat _fstat() { return new FStat(); }
+ public void _close() { try { s.close(); } catch(IOException e) { } }
+ }
+
+ public int sys_listensocket(int port) {
+ try {
+ ListenSocketFD fd = new ListenSocketFD(new ServerSocket(port));
+ int n = addFD(fd);
+ if(n == -1) fd.close();
+ return n;
+ } catch(IOException e) {
+ return -EIO;
+ }
+ }
+
+ public int sys_accept(int fdn) {
+ if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD;
+ if(fds[fdn] == null) return -EBADFD;
+ if(!(fds[fdn] instanceof ListenSocketFD)) return -EBADFD;
+ try {
+ ServerSocket s = ((ListenSocketFD)fds[fdn]).s;
+ SocketFD fd = new SocketFD(s.accept());
+ int n = addFD(fd);
+ if(n == -1) fd.close();
+ return n;
+ } catch(IOException e) {
+ return -EIO;
+ }
+ }
+
// FEATURE: Run through the fork/wait stuff one more time
public static class GlobalState {
protected static final int OPEN = 1;
public static final int SYS_usleep = 45;
public static final int SYS_getppid = 46;
public static final int SYS_mkfifo = 47;
+ public static final int SYS_opensocket = 48;
+ public static final int SYS_listensocket = 49;
+ public static final int SYS_accept = 50;
public static final int EPERM = 1; /* Not super-user */
public static final int ENOENT = 2; /* No such file or directory */
public static final int ESRCH = 3; /* No such process */
SYSCALL_R(usleep)
SYSCALL(getppid)
SYSCALL_R(mkfifo)
+SYSCALL_R2(__open_socket_r,SYS_opensocket)
+SYSCALL_R2(__listen_socket_r,SYS_listensocket)
+SYSCALL_R2(__accept_r,SYS_accept)
REENT_WRAPPER2(ftruncate,int,off_t)
REENT_WRAPPER1(usleep,unsigned int)
REENT_WRAPPER2(mkfifo,const char *, mode_t)
+REENT_WRAPPER2(_open_socket,const char *,int)
+REENT_WRAPPER1(_listen_socket,int)
+REENT_WRAPPER1(_accept,int)
extern int __execve_r(struct _reent *ptr, const char *path, char *const argv[], char *const envp[]);
int _execve(const char *path, char *const argv[], char *const envp[]) {
#define SYS_usleep 45
#define SYS_getppid 46
#define SYS_mkfifo 47
+#define SYS_opensocket 48
+#define SYS_listensocket 49
+#define SYS_accept 50
} else if(argc > 2 && strcmp(argv[1],"crashme") == 0) {
volatile int *mem = (int*) atoi(argv[2]);
*mem = 1;
+ } else if(argc > 2 && strcmp(argv[1],"get") == 0) {
+ extern int _open_socket(const char *host, int port);
+ fd = _open_socket(argv[2],80);
+ if(fd == -1) { perror("open_socket"); exit(EXIT_FAILURE); }
+#define REQ "GET / HTTP/1.0\r\n\r\n"
+ n = write(fd,REQ,strlen(REQ));
+ if(n != strlen(REQ)) { perror("write"); exit(EXIT_FAILURE); }
+ for(;;) {
+ n = read(fd,buf,sizeof(buf));
+ if(n < 0) { perror("read"); exit(EXIT_FAILURE); }
+ if(n == 0) break;
+ write(1,buf,n);
+ }
+ } else if(argc > 1 && strcmp(argv[1],"server") == 0) {
+ extern int _listen_socket(int port);
+ extern int _accept(int fd);
+
+ int server = _listen_socket(2000);
+ if(server< 0) { perror("server_socket"); exit(EXIT_FAILURE); }
+ while((fd = _accept(server)) >= 0) {
+ char buf2[1024];
+ int n = read(fd,buf,sizeof(buf));
+ if(n < 0) { perror("read"); continue; }
+ if(n == 0) continue;
+ while(n > 0 && (buf[n-1] == '\r' || buf[n-1] == '\n')) n--;
+ buf[n] = '\0';
+ snprintf(buf2,sizeof(buf2),"Hello, %s from nestedvm's socket support\r\n",buf);
+ write(fd,buf2,strlen(buf2));
+ close(fd);
+ }
} else {
printf("%d\n", 0xffffff);
printf("%u\n", 0xffffffU);