Patchwork [gccgo] Add RTEMS specific patches to libgo

login
register
mail settings
Submitter Ian Taylor
Date June 27, 2010, 12:07 a.m.
Message ID <mcrlja11gpj.fsf@google.com>
Download mbox | patch
Permalink /patch/57077/
State New
Headers show

Comments

Ian Taylor - June 27, 2010, 12:07 a.m.
This patch from Vinu Rajashekhar adds some RTEMS specific support to the
libgo library.  Committed to gccgo branch.

Ian

Patch

Index: libgo/syscalls/sysfile.go
===================================================================
--- libgo/syscalls/sysfile.go	(revision 160705)
+++ libgo/syscalls/sysfile.go	(working copy)
@@ -1,418 +0,0 @@ 
-// sysfile.go -- File handling.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Support for basic Unix file operations.  This file simply
-// translates from Go data types to Unix data types, and handles
-// errno.  FIXME: This could probably be done mechanically.
-
-package syscall
-
-import "unsafe"
-
-// FIXME.
-const OS = "linux"
-
-func libc_open(name *byte, mode int, perm int) int __asm__ ("open");
-func libc_close(fd int) int __asm__ ("close");
-func libc_read(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("read");
-func libc_write(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("write");
-func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread64");
-func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite64");
-func libc_lseek64(int, Offset_t, int) Offset_t __asm__ ("lseek64");
-func libc_pipe(filedes *int) int __asm__("pipe");
-func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat");
-func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat");
-func libc_lstat(name *byte, buf *Stat_t) int __asm__ ("lstat");
-func libc_unlink(name *byte) int __asm__ ("unlink");
-func libc_rmdir(name *byte) int __asm__ ("rmdir");
-func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl");
-func libc_mkdir(name *byte, perm Mode_t) int __asm__ ("mkdir");
-func libc_gettimeofday(tv *Timeval, tz *Timezone) int __asm__ ("gettimeofday");
-func libc_select(int, *byte, *byte, *byte, *Timeval) int __asm__ ("select");
-func libc_chdir(name *byte) int __asm__ ("chdir");
-func libc_fchdir(int) int __asm__ ("fchdir");
-func libc_getcwd(*byte, Size_t) *byte __asm__ ("getcwd");
-func libc_link(oldpath *byte, newpath *byte) int __asm__ ("link");
-func libc_symlink(oldpath *byte, newpath *byte) int __asm__ ("symlink");
-func libc_readlink(*byte, *byte, Size_t) Ssize_t  __asm__ ("readlink");
-func libc_rename(oldpath *byte, newpath *byte) int __asm__ ("rename");
-func libc_chmod(path *byte, mode Mode_t) int __asm__ ("chmod");
-func libc_fchmod(fd int, mode Mode_t) int __asm__ ("fchmod");
-func libc_chown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("chown");
-func libc_fchown(fd int, owner Uid_t, group Gid_t) int __asm__ ("fchown");
-func libc_lchown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("lchown");
-func libc_truncate64(path *byte, length Offset_t) int __asm__ ("truncate64");
-func libc_ftruncate64(fd int, length Offset_t) int __asm__ ("ftruncate64");
-func libc_utimes(filename *byte, times *[2]Timeval) int __asm__ ("utimes");
-func libc_getuid() Uid_t __asm__ ("getuid");
-func libc_geteuid() Uid_t __asm__ ("geteuid");
-func libc_getgid() Gid_t __asm__ ("getgid");
-func libc_getegid() Gid_t __asm__ ("getegid");
-func libc_getgroups(size int, list *Gid_t) int __asm__ ("getgroups");
-func libc_setgroups(size Size_t, list *Gid_t) int __asm__ ("setgroups");
-func libc_getpagesize() int __asm__ ("getpagesize");
-func libc_exit(status int) __asm__ ("exit")
-func libc_getpid() Pid_t __asm__ ("getpid")
-func libc_getppid() Pid_t __asm__ ("getppid")
-func libc_kill(Pid_t, int) int __asm__ ("kill")
-
-func Open(name string, mode int, perm int) (fd int, errno int) {
-  fd = libc_open(StringBytePtr(name), mode, perm);
-  if fd < 0 { errno = GetErrno() }
-  return;
-}
-
-func Creat(name string, perm int) (fd int, errno int) {
-  fd = libc_open(StringBytePtr(name), O_CREAT | O_WRONLY | O_TRUNC, perm);
-  if fd < 0 { errno = GetErrno() }
-  return;
-}
-
-func Close(fd int) (errno int) {
-  r := libc_close(fd);
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Read(fd int, p []byte) (n int, errno int) {
-  var _p0 *byte;
-  if len(p) > 0 { _p0 = &p[0]; }
-  r := libc_read(fd, _p0, Size_t(len(p)));
-  if r == -1 { errno = GetErrno() }
-  n = int(r);
-  return;
-}
-
-func Write(fd int, p []byte) (n int, errno int) {
-  var _p0 *byte;
-  if len(p) > 0 { _p0 = &p[0]; }
-  r := libc_write(fd, _p0, Size_t(len(p)));
-  if r == -1 { errno = GetErrno() }
-  n = int(r);
-  return;
-}
-
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
-  var _p0 *byte;
-  if len(p) > 0 { _p0 = &p[0]; }
-  r := libc_pread(fd, _p0, Size_t(len(p)), Offset_t(offset));
-  if r == -1 { errno = GetErrno() }
-  n = int(r);
-  return;
-}
-
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
-  var _p0 *byte;
-  if len(p) > 0 { _p0 = &p[0]; }
-  r := libc_pwrite(fd, _p0, Size_t(len(p)), Offset_t(offset));
-  if r == -1 { errno = GetErrno() }
-  n = int(r);
-  return;
-}
-
-func Seek(fd int, offset int64, whence int) (off int64, errno int) {
-  r := libc_lseek64(fd, Offset_t(offset), whence);
-  if r == -1 { errno = GetErrno() }
-  off = int64(r);
-  return;
-}
-
-func Pipe(p []int) (errno int) {
-  if len(p) != 2 {
-    return EINVAL;
-  }
-  var pp [2]int;
-  r := libc_pipe(&pp[0]);
-  if r < 0 {
-    errno = GetErrno();
-  }
-  p[0] = pp[0];
-  p[1] = pp[1];
-  return;
-}
-
-func Stat(name string, buf *Stat_t) (errno int) {
-  r := libc_stat(StringBytePtr(name), buf);
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Lstat(name string, buf *Stat_t) (errno int) {
-  r := libc_lstat(StringBytePtr(name), buf);
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Fstat(fd int, buf *Stat_t) (errno int) {
-  r := libc_fstat(fd, buf);
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Unlink(name string) (errno int) {
-  r := libc_unlink(StringBytePtr(name));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Rmdir(name string) (errno int) {
-  r := libc_rmdir(StringBytePtr(name));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Mkdir(path string, mode int) (errno int) {
-  r := libc_mkdir(StringBytePtr(path), Mode_t(mode));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Gettimeofday(tv *Timeval) (errno int) {
-  r := libc_gettimeofday(tv, nil);
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-type FdSet struct {
-	__fds_bits [32]int32;
-}
-
-func Select(nfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int) {
-  n = libc_select(nfds, (*byte)(unsafe.Pointer(r)),
-		  (*byte)(unsafe.Pointer(e)),
-		  (*byte)(unsafe.Pointer(e)), timeout);
-  if n < 0 { errno = GetErrno() }
-  return;
-}
-
-func Chdir(path string) (errno int) {
-  r := libc_chdir(StringBytePtr(path));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Fchdir(fd int) (errno int) {
-  r := libc_fchdir(int(fd));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-const ImplementsGetwd = true
-
-func Getwd() (ret string, errno int) {
-	for len := Size_t(4096); ; len *= 2 {
-		b := make([]byte, len);
-		p := libc_getcwd(&b[0], len);
-		if p != nil {
-			i := 0;
-			for b[i] != 0 {
-				i++;
-			}
-			return string(b[0:i]), 0;
-		}
-		e := GetErrno();
-		if e != ERANGE {
-			return "", e;
-		}
-	}
-}
-
-func Link(oldpath, newpath string) (errno int) {
-  r := libc_link(StringBytePtr(oldpath), StringBytePtr(newpath));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Symlink(oldpath, newpath string) (errno int) {
-  r := libc_symlink(StringBytePtr(oldpath), StringBytePtr(newpath));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Readlink(path string, buf []byte) (n int, errno int) {
-  var _p0 *byte;
-  if len(buf) > 0 { _p0 = &buf[0]; }
-  r := libc_readlink(StringBytePtr(path), _p0, Size_t(len(buf)));
-  if r < 0 { errno = GetErrno() }
-  n = int(r);
-  return;
-}
-
-func Rename(oldpath, newpath string) (errno int) {
-	r := libc_rename(StringBytePtr(oldpath), StringBytePtr(newpath));
-	if r < 0 { errno = GetErrno() }
-	return 
-}
-
-func Chmod(path string, mode int) (errno int) {
-  r := libc_chmod(StringBytePtr(path), Mode_t(mode));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Fchmod(fd, mode int) (errno int) {
-  r := libc_fchmod(fd, Mode_t(mode));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Chown(path string, uid int, gid int) (errno int) {
-  r := libc_chown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Lchown(path string, uid int, gid int) (errno int) {
-  r := libc_lchown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Fchown(fd int, uid int, gid int) (errno int) {
-  r := libc_fchown(fd, Uid_t(uid), Gid_t(gid));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Truncate(path string, length int64) (errno int) {
-  r := libc_truncate64(StringBytePtr(path), Offset_t(length));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Ftruncate(fd int, length int64) (errno int) {
-  r := libc_ftruncate64(fd, Offset_t(length));
-  if r < 0 { errno = GetErrno() }
-  return;
-}
-
-func Utimes(path string, tv []Timeval) (errno int) {
-  if len(tv) != 2 {
-    return EINVAL;
-  }
-  r := libc_utimes(StringBytePtr(path),
-		   (*[2]Timeval)(unsafe.Pointer(&tv[0])));
-  if r < 0 {
-    errno = GetErrno();
-  }
-  return;
-}
-
-// Getuid returns the numeric user id of the caller.
-func Getuid() int {
-  return int(libc_getuid());
-}
-
-// Geteuid returns the numeric effective user id of the caller.
-func Geteuid() int {
-  return int(libc_geteuid());
-}
-
-// Getgid returns the numeric group id of the caller.
-func Getgid() int {
-  return int(libc_getgid());
-}
-
-// Getegid returns the numeric effective group id of the caller.
-func Getegid() int {
-  return int(libc_getegid());
-}
-
-// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
-func Getgroups() (gids []int, errno int) {
-	n := libc_getgroups(0, nil);
-	if n < 0 {
-		return nil, GetErrno();
-	}
-	if n == 0 {
-		return nil, 0;
-	}
-
-	// Sanity check group count.  Max is 1<<16 on Linux.
-	if n < 0 || n > 1<<20 {
-		return nil, EINVAL;
-	}
-
-	a := make([]Gid_t, n);
-	n = libc_getgroups(n, &a[0]);
-	if n < 0 {
-		return nil, GetErrno();
-	}
-	gids = make([]int, n);
-	for i, v := range a[0:n] {
-		gids[i] = int(v);
-	}
-	return;
-}
-
-func Setgroups(gids []int) (errno int) {
-	if len(gids) == 0 {
-		return libc_setgroups(0, nil);
-	}
-
-	a := make([]Gid_t, len(gids));
-	for i, v := range gids {
-		a[i] = Gid_t(v);
-	}
-	return libc_setgroups(Size_t(len(a)), &a[0]);
-}
-
-func Getpagesize() int {
-	return libc_getpagesize();
-}
-
-func TimespecToNsec(ts Timespec) int64 {
-	return int64(ts.Sec)*1e9 + int64(ts.Nsec);
-}
-
-func NsecToTimespec(nsec int64) (ts Timespec) {
-	ts.Sec = Timespec_sec_t(nsec / 1e9);
-	ts.Nsec = Timespec_nsec_t(nsec % 1e9);
-	return;
-}
-
-func TimevalToNsec(tv Timeval) int64 {
-	return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3;
-}
-
-func NsecToTimeval(nsec int64) (tv Timeval) {
-	nsec += 999;	// round up to microsecond
-	tv.Sec = Timeval_sec_t(nsec/1e9);
-	tv.Usec = Timeval_usec_t(nsec%1e9 / 1e3);
-	return;
-}
-
-func Exit(code int) {
-	libc_exit(code);
-}
-
-func Sleep(nsec int64) (errno int) {
-	tv := NsecToTimeval(nsec);
-	n, err := Select(0, nil, nil, nil, &tv);
-	return err;
-}
-
-func fcntl(fd, cmd, arg int) (val int, errno int) {
-  val = libc_fcntl(int(fd), int(cmd), int(arg));
-  if val == -1 { errno = GetErrno() }
-  return;
-}
-
-func Getpid() (pid int) {
-  return int(libc_getpid());
-}
-
-func Getppid() (ppid int) {
-  return int(libc_getppid());
-}
-
-func Kill(pid int, sig int) (errno int) {
-	r := libc_kill(Pid_t(pid), sig)
-	if r < 0 {
-		errno = GetErrno()
-	}
-	return
-}
Index: libgo/syscalls/socket_bsd.go
===================================================================
--- libgo/syscalls/socket_bsd.go	(revision 0)
+++ libgo/syscalls/socket_bsd.go	(revision 0)
@@ -0,0 +1,134 @@ 
+// socket_bsd.go -- Socket handling specific to *BSD based systems.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Low-level socket interface.
+// Only for implementing net package.
+// DO NOT USE DIRECTLY.
+
+package syscall
+
+import "unsafe"
+
+type RawSockaddrInet4 struct {
+	Len uint8;
+	Family uint8;
+	Port uint16;
+	Addr [4]byte /* in_addr */;
+	Zero [8]uint8;
+}
+
+type RawSockaddrInet6 struct {
+	Len uint8;
+	Family uint8;
+	Port uint16;
+	Flowinfo uint32;
+	Addr [16]byte /* in6_addr */;
+	Scope_id uint32;
+}
+
+type RawSockaddrUnix struct {
+	Len uint8;
+	Family uint8;
+	Path [108]int8;
+}
+
+type RawSockaddr struct {
+	Len uint8;
+	Family uint8;
+	Data [14]int8;
+}
+
+func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Len = SizeofSockaddrInet4;
+	sa.raw.Family = AF_INET;
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+	p[0] = byte(sa.Port>>8);
+	p[1] = byte(sa.Port);
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i];
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
+}
+
+func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Len = SizeofSockaddrInet6;
+	sa.raw.Family = AF_INET6;
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+	p[0] = byte(sa.Port>>8);
+	p[1] = byte(sa.Port);
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i];
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
+}
+
+func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	name := sa.Name;
+	n := len(name);
+	if n >= len(sa.raw.Path) || n == 0 {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Len = byte(3 + n); // 2 for Family, Len; 1 for NUL.
+	sa.raw.Family = AF_UNIX;
+	for i := 0; i < n; i++ {
+		sa.raw.Path[i] = int8(name[i]);
+	}
+	if sa.raw.Path[0] == '@' {
+		sa.raw.Path[0] = 0;
+	}
+
+	// length is family, name, NUL.
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), Socklen_t(sa.raw.Len), 0;
+}
+
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
+	switch rsa.Addr.Family {
+	case AF_UNIX:
+		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
+		if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
+			return nil, EINVAL
+		}
+		sa := new(SockaddrUnix)
+		n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL.
+		for i := 0; i < n; i++ {
+			if pp.Path[i] == 0 {
+				// found early NUL; assume Len is overestimating.
+				n = i
+				break
+			}
+		}
+		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
+		sa.Name = string(bytes[0:n])
+		return sa, 0
+
+	case AF_INET:
+		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
+		sa := new(SockaddrInet4);
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+		sa.Port = int(p[0])<<8 + int(p[1]);
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i];
+		}
+		return sa, 0;
+
+	case AF_INET6:
+		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
+		sa := new(SockaddrInet6);
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+		sa.Port = int(p[0])<<8 + int(p[1]);
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i];
+		}
+		return sa, 0;
+	}
+	return nil, EAFNOSUPPORT;
+}
Index: libgo/syscalls/exec.go
===================================================================
--- libgo/syscalls/exec.go	(revision 160705)
+++ libgo/syscalls/exec.go	(working copy)
@@ -8,57 +8,7 @@ 
 
 package syscall
 
-import (
-	"sync";
-	"unsafe";
-)
-
-// Lock synchronizing creation of new file descriptors with fork.
-//
-// We want the child in a fork/exec sequence to inherit only the
-// file descriptors we intend.  To do that, we mark all file
-// descriptors close-on-exec and then, in the child, explicitly
-// unmark the ones we want the exec'ed program to keep.
-// Unix doesn't make this easy: there is, in general, no way to
-// allocate a new file descriptor close-on-exec.  Instead you
-// have to allocate the descriptor and then mark it close-on-exec.
-// If a fork happens between those two events, the child's exec
-// will inherit an unwanted file descriptor.
-//
-// This lock solves that race: the create new fd/mark close-on-exec
-// operation is done holding ForkLock for reading, and the fork itself
-// is done holding ForkLock for writing.  At least, that's the idea.
-// There are some complications.
-//
-// Some system calls that create new file descriptors can block
-// for arbitrarily long times: open on a hung NFS server or named
-// pipe, accept on a socket, and so on.  We can't reasonably grab
-// the lock across those operations.
-//
-// It is worse to inherit some file descriptors than others.
-// If a non-malicious child accidentally inherits an open ordinary file,
-// that's not a big deal.  On the other hand, if a long-lived child
-// accidentally inherits the write end of a pipe, then the reader
-// of that pipe will not see EOF until that child exits, potentially
-// causing the parent program to hang.  This is a common problem
-// in threaded C programs that use popen.
-//
-// Luckily, the file descriptors that are most important not to
-// inherit are not the ones that can take an arbitrarily long time
-// to create: pipe returns instantly, and the net package uses
-// non-blocking I/O to accept on a listening socket.
-// The rules for which file descriptor-creating operations use the
-// ForkLock are as follows:
-//
-// 1) Pipe.    Does not block.  Use the ForkLock.
-// 2) Socket.  Does not block.  Use the ForkLock.
-// 3) Accept.  If using non-blocking mode, use the ForkLock.
-//             Otherwise, live with the race.
-// 4) Open.    Can block.  Use O_CLOEXEC if available (Linux).
-//             Otherwise, live with the race.
-// 5) Dup.     Does not block.  Use the ForkLock.
-//             On Linux, could use fcntl F_DUPFD_CLOEXEC
-//             instead of the ForkLock, but only for dup(fd, -1).
+import "unsafe"
 
 func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl")
 func libc_fork() Pid_t __asm__ ("fork")
@@ -68,40 +18,6 @@  func libc_execve(*byte, **byte, **byte) 
 func libc_sysexit(int) __asm__ ("_exit")
 func libc_wait4(Pid_t, *int, int, *Rusage) Pid_t __asm__ ("wait4")
 
-type WaitStatus int
-
-var ForkLock sync.RWMutex
-
-// Convert array of string to array
-// of NUL-terminated byte pointer.
-func StringArrayPtr(ss []string) []*byte {
-	bb := make([]*byte, len(ss)+1);
-	for i := 0; i < len(ss); i++ {
-		bb[i] = StringBytePtr(ss[i]);
-	}
-	bb[len(ss)] = nil;
-	return bb;
-}
-
-func CloseOnExec(fd int) {
-	fcntl(fd, F_SETFD, FD_CLOEXEC);
-}
-
-func SetNonblock(fd int, nonblocking bool) (errno int) {
-	flag, err := fcntl(fd, F_GETFL, 0);
-	if err != 0 {
-		return err;
-	}
-	if nonblocking {
-		flag |= O_NONBLOCK;
-	} else {
-		flag &= ^O_NONBLOCK;
-	}
-	flag, err = fcntl(fd, F_SETFL, flag);
-	return err;
-}
-
-
 // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
 // If a dup or exec fails, write the errno int to pipe.
 // (Pipe is close-on-exec so if exec succeeds, it will be closed.)
@@ -318,71 +234,6 @@  func Exec(argv0 string, argv []string, e
 	return GetErrno();
 }
 
-// Wait status is 7 bits at bottom, either 0 (exited),
-// 0x7F (stopped), or a signal number that caused an exit.
-// The 0x80 bit is whether there was a core dump.
-// An extra number (exit code, signal causing a stop)
-// is in the high bits.  At least that's the idea.
-// There are various irregularities.  For example, the
-// "continued" status is 0xFFFF, distinguishing itself
-// from stopped via the core dump bit.
-
-const (
-	mask = 0x7F;
-	core = 0x80;
-	exited = 0x00;
-	stopped = 0x7F;
-	shift = 8;
-)
-
-func (w WaitStatus) Exited() bool {
-	return w&mask == exited;
-}
-
-func (w WaitStatus) Signaled() bool {
-	return w&mask != stopped && w&mask != exited;
-}
-
-func (w WaitStatus) Stopped() bool {
-	return w&0xFF == stopped;
-}
-
-func (w WaitStatus) Continued() bool {
-	return w == 0xFFFF;
-}
-
-func (w WaitStatus) CoreDump() bool {
-	return w.Signaled() && w&core != 0;
-}
-
-func (w WaitStatus) ExitStatus() int {
-	if !w.Exited() {
-		return -1;
-	}
-	return int(w >> shift) & 0xFF;
-}
-
-func (w WaitStatus) Signal() int {
-	if !w.Signaled() {
-		return -1;
-	}
-	return int(w & mask);
-}
-
-func (w WaitStatus) StopSignal() int {
-	if !w.Stopped() {
-		return -1;
-	}
-	return int(w >> shift) & 0xFF;
-}
-
-func (w WaitStatus) TrapCause() int {
-	if w.StopSignal() != SIGTRAP {
-		return -1;
-	}
-	return int(w >> shift) >> 8;
-}
-
 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
 	var status int;
 	r := libc_wait4(Pid_t(pid), &status, options, rusage);
Index: libgo/syscalls/socket.go
===================================================================
--- libgo/syscalls/socket.go	(revision 160705)
+++ libgo/syscalls/socket.go	(working copy)
@@ -12,38 +12,15 @@  package syscall
 
 import "unsafe"
 
-type RawSockaddrInet4 struct {
-	Family uint16;
-	Port uint16;
-	Addr [4]byte /* in_addr */;
-	Zero [8]uint8;
-}
 const SizeofSockaddrInet4 = 16
-
-type RawSockaddrInet6 struct {
-	Family uint16;
-	Port uint16;
-	Flowinfo uint32;
-	Addr [16]byte /* in6_addr */;
-	Scope_id uint32;
-}
 const SizeofSockaddrInet6 = 28
-
-type RawSockaddrUnix struct {
-	Family uint16;
-	Path [108]int8;
-}
 const SizeofSockaddrUnix = 110
 
-type RawSockaddr struct {
-	Family uint16;
-	Data [14]int8;
-}
-
 type RawSockaddrAny struct {
 	Addr RawSockaddr;
 	Pad [12]int8;
 }
+
 const SizeofSockaddrAny = 0x1c;
 
 // For testing: clients can set this flag to force
@@ -60,113 +37,17 @@  type SockaddrInet4 struct {
 	raw RawSockaddrInet4;
 }
 
-func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	if sa.Port < 0 || sa.Port > 0xFFFF {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Family = AF_INET;
-	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
-	p[0] = byte(sa.Port>>8);
-	p[1] = byte(sa.Port);
-	for i := 0; i < len(sa.Addr); i++ {
-		sa.raw.Addr[i] = sa.Addr[i];
-	}
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0;
-}
-
 type SockaddrInet6 struct {
 	Port int;
 	Addr [16]byte;
 	raw RawSockaddrInet6;
 }
 
-func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	if sa.Port < 0 || sa.Port > 0xFFFF {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Family = AF_INET6;
-	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
-	p[0] = byte(sa.Port>>8);
-	p[1] = byte(sa.Port);
-	for i := 0; i < len(sa.Addr); i++ {
-		sa.raw.Addr[i] = sa.Addr[i];
-	}
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0;
-}
-
 type SockaddrUnix struct {
 	Name string;
 	raw RawSockaddrUnix;
 }
 
-func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
-	name := sa.Name;
-	n := len(name);
-	if n >= len(sa.raw.Path) || n == 0 {
-		return nil, 0, EINVAL;
-	}
-	sa.raw.Family = AF_UNIX;
-	for i := 0; i < n; i++ {
-		sa.raw.Path[i] = int8(name[i]);
-	}
-	if sa.raw.Path[0] == '@' {
-		sa.raw.Path[0] = 0;
-	}
-
-	// length is family, name, NUL.
-	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 1 + Socklen_t(n) + 1, 0;
-}
-
-func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
-	switch rsa.Addr.Family {
-	case AF_UNIX:
-		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
-		sa := new(SockaddrUnix);
-		if pp.Path[0] == 0 {
-			// "Abstract" Unix domain socket.
-			// Rewrite leading NUL as @ for textual display.
-			// (This is the standard convention.)
-			// Not friendly to overwrite in place,
-			// but the callers below don't care.
-			pp.Path[0] = '@';
-		}
-
-		// Assume path ends at NUL.
-		// This is not technically the Linux semantics for
-		// abstract Unix domain sockets--they are supposed
-		// to be uninterpreted fixed-size binary blobs--but
-		// everyone uses this convention.
-		n := 0;
-		for n < len(pp.Path) && pp.Path[n] != 0 {
-			n++;
-		}
-		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
-		sa.Name = string(bytes[0:n]);
-		return sa, 0;
-
-	case AF_INET:
-		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
-		sa := new(SockaddrInet4);
-		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
-		sa.Port = int(p[0])<<8 + int(p[1]);
-		for i := 0; i < len(sa.Addr); i++ {
-			sa.Addr[i] = pp.Addr[i];
-		}
-		return sa, 0;
-
-	case AF_INET6:
-		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
-		sa := new(SockaddrInet6);
-		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
-		sa.Port = int(p[0])<<8 + int(p[1]);
-		for i := 0; i < len(sa.Addr); i++ {
-			sa.Addr[i] = pp.Addr[i];
-		}
-		return sa, 0;
-	}
-	return nil, EAFNOSUPPORT;
-}
-
 type Linger struct {
 	Onoff int32;
 	Linger int32;
Index: libgo/syscalls/sysfile_rtems.go
===================================================================
--- libgo/syscalls/sysfile_rtems.go	(revision 0)
+++ libgo/syscalls/sysfile_rtems.go	(revision 0)
@@ -0,0 +1,34 @@ 
+// sysfile_rtems.go -- RTEMS specific file handling.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for basic Unix file operations.  This file simply
+// translates from Go data types to Unix data types, and handles
+// errno.  FIXME: This could probably be done mechanically.
+
+package syscall
+
+const (
+	OS = "rtems"
+	// No support for async I/O in RTEMS.
+	O_ASYNC = 0
+)
+
+func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread")
+func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite")
+func libc_lseek64(int, Offset_t, int) Offset_t __asm__ ("lseek")
+func libc_truncate64(path *byte, length Offset_t) int __asm__ ("truncate")
+func libc_ftruncate64(fd int, length Offset_t) int __asm__ ("ftruncate")
+func libc_nanosleep(req *Timespec, rem *Timespec) int __asm__ ("nanosleep")
+
+func Sleep(nsec int64) (errno int) {
+	errno = 0
+	ts := NsecToTimespec(nsec)
+	r := libc_nanosleep(&ts, nil)
+	if r < 0 {
+		errno = GetErrno()
+	}
+	return
+}
Index: libgo/syscalls/stringbyte.go
===================================================================
--- libgo/syscalls/stringbyte.go	(revision 0)
+++ libgo/syscalls/stringbyte.go	(revision 0)
@@ -0,0 +1,24 @@ 
+// stringbyte.go -- string to bytes functions.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+// StringByteSlice returns a NUL-terminated slice of bytes
+// containing the text of s.
+func StringByteSlice(s string) []byte {
+	a := make([]byte, len(s)+1);
+	for i := 0; i < len(s); i++ {
+		a[i] = s[i];
+	}
+	return a;
+}
+
+// StringBytePtr returns a pointer to a NUL-terminated array of bytes
+// containing the text of s.
+func StringBytePtr(s string) *byte {
+	p := StringByteSlice(s);
+	return &p[0];
+}
Index: libgo/syscalls/syscall_stubs.go
===================================================================
--- libgo/syscalls/syscall_stubs.go	(revision 0)
+++ libgo/syscalls/syscall_stubs.go	(revision 0)
@@ -0,0 +1,33 @@ 
+// syscall_stubs.go -- Stubs of the basic syscall interface.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package contains an interface to the low-level operating system
+// primitives.  The details vary depending on the underlying system.
+// Its primary use is inside other packages that provide a more portable
+// interface to the system, such as "os", "time" and "net".  Use those
+// packages rather than this one if you can.
+// For details of the functions and data types in this package consult
+// the manuals for the appropriate operating system.
+
+// These are stubs.
+
+package syscall
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+  var r uintptr;
+  var i int;
+  i = -1;
+  r = uintptr(i);
+  return r, 0, uintptr(ENOSYS);
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+  var r uintptr;
+  var i int;
+  i = -1;
+  r = uintptr(i);
+  return r, 0, uintptr(ENOSYS);
+}
Index: libgo/syscalls/errstr_rtems.go
===================================================================
--- libgo/syscalls/errstr_rtems.go	(revision 0)
+++ libgo/syscalls/errstr_rtems.go	(revision 0)
@@ -0,0 +1,33 @@ 
+// errstr_rtems.go -- RTEMS specific error strings.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+const ENONE = 0
+
+// RTEMS uses strerror_r in newlib, which is a GNU extension returning a char *.
+func libc_strerror_r(int, *byte, Size_t) int __asm__ ("strerror_r")
+func GetErrno() int
+func SetErrno(int)
+
+func Errstr(errno int) string {
+	for len := Size_t(128); ; len *= 2 {
+		b := make([]byte, len+1)
+
+		// The newlib strerror_r always returns the string in buffer.
+		libc_strerror_r(errno, &b[0], len)
+		b[len] = 0
+
+		i := 0
+		for b[i] != 0 {
+			i++
+		}
+
+		if Size_t(i) < len {
+			return string(b[0:i])
+		}
+	}
+}
Index: libgo/syscalls/sysfile_linux.go
===================================================================
--- libgo/syscalls/sysfile_linux.go	(revision 0)
+++ libgo/syscalls/sysfile_linux.go	(revision 0)
@@ -0,0 +1,38 @@ 
+// sysfile_linux.go -- Linux specific file handling.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for basic Unix file operations.  This file simply
+// translates from Go data types to Unix data types, and handles
+// errno.  FIXME: This could probably be done mechanically.
+
+package syscall
+
+const OS = "linux"
+
+func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread64")
+func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite64")
+func libc_lseek64(int, Offset_t, int) Offset_t __asm__ ("lseek64")
+func libc_truncate64(path *byte, length Offset_t) int __asm__ ("truncate64")
+func libc_ftruncate64(fd int, length Offset_t) int __asm__ ("ftruncate64")
+func libc_setgroups(size Size_t, list *Gid_t) int __asm__ ("setgroups")
+
+func Sleep(nsec int64) (errno int) {
+	tv := NsecToTimeval(nsec);
+	n, err := Select(0, nil, nil, nil, &tv);
+	return err;
+}
+
+func Setgroups(gids []int) (errno int) {
+	if len(gids) == 0 {
+		return libc_setgroups(0, nil);
+	}
+
+	a := make([]Gid_t, len(gids));
+	for i, v := range gids {
+		a[i] = Gid_t(v);
+	}
+	return libc_setgroups(Size_t(len(a)), &a[0]);
+}
Index: libgo/syscalls/sysfile_posix.go
===================================================================
--- libgo/syscalls/sysfile_posix.go	(revision 0)
+++ libgo/syscalls/sysfile_posix.go	(revision 0)
@@ -0,0 +1,413 @@ 
+// sysfile_posix.go -- POSIX File handling.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for basic Unix file operations.  This file simply
+// translates from Go data types to Unix data types, and handles
+// errno.  FIXME: This could probably be done mechanically.
+
+package syscall
+
+import "unsafe"
+
+func libc_open(name *byte, mode int, perm int) int __asm__ ("open");
+func libc_close(fd int) int __asm__ ("close");
+func libc_read(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("read");
+func libc_write(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("write");
+func libc_pipe(filedes *int) int __asm__("pipe");
+func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat");
+func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat");
+func libc_lstat(name *byte, buf *Stat_t) int __asm__ ("lstat");
+func libc_unlink(name *byte) int __asm__ ("unlink");
+func libc_rmdir(name *byte) int __asm__ ("rmdir");
+func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl");
+func libc_mkdir(name *byte, perm Mode_t) int __asm__ ("mkdir");
+func libc_gettimeofday(tv *Timeval, tz *Timezone) int __asm__ ("gettimeofday");
+func libc_select(int, *byte, *byte, *byte, *Timeval) int __asm__ ("select");
+func libc_chdir(name *byte) int __asm__ ("chdir");
+func libc_fchdir(int) int __asm__ ("fchdir");
+func libc_getcwd(*byte, Size_t) *byte __asm__ ("getcwd");
+func libc_link(oldpath *byte, newpath *byte) int __asm__ ("link");
+func libc_symlink(oldpath *byte, newpath *byte) int __asm__ ("symlink");
+func libc_readlink(*byte, *byte, Size_t) Ssize_t  __asm__ ("readlink");
+func libc_rename(oldpath *byte, newpath *byte) int __asm__ ("rename");
+func libc_chmod(path *byte, mode Mode_t) int __asm__ ("chmod");
+func libc_fchmod(fd int, mode Mode_t) int __asm__ ("fchmod");
+func libc_chown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("chown");
+func libc_fchown(fd int, owner Uid_t, group Gid_t) int __asm__ ("fchown");
+func libc_lchown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("lchown");
+func libc_utimes(filename *byte, times *[2]Timeval) int __asm__ ("utimes");
+func libc_getuid() Uid_t __asm__ ("getuid");
+func libc_geteuid() Uid_t __asm__ ("geteuid");
+func libc_getgid() Gid_t __asm__ ("getgid");
+func libc_getegid() Gid_t __asm__ ("getegid");
+func libc_getgroups(size int, list *Gid_t) int __asm__ ("getgroups");
+func libc_getpagesize() int __asm__ ("getpagesize");
+func libc_exit(status int) __asm__ ("exit")
+func libc_getpid() Pid_t __asm__ ("getpid")
+func libc_getppid() Pid_t __asm__ ("getppid")
+func libc_kill(Pid_t, int) int __asm__ ("kill")
+
+func Open(name string, mode int, perm int) (fd int, errno int) {
+  fd = libc_open(StringBytePtr(name), mode, perm);
+  if fd < 0 { errno = GetErrno() }
+  return;
+}
+
+func Creat(name string, perm int) (fd int, errno int) {
+  fd = libc_open(StringBytePtr(name), O_CREAT | O_WRONLY | O_TRUNC, perm);
+  if fd < 0 { errno = GetErrno() }
+  return;
+}
+
+func Close(fd int) (errno int) {
+  r := libc_close(fd);
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Read(fd int, p []byte) (n int, errno int) {
+  var _p0 *byte;
+  if len(p) > 0 { _p0 = &p[0]; }
+  r := libc_read(fd, _p0, Size_t(len(p)));
+  if r == -1 { errno = GetErrno() }
+  n = int(r);
+  return;
+}
+
+func Write(fd int, p []byte) (n int, errno int) {
+  var _p0 *byte;
+  if len(p) > 0 { _p0 = &p[0]; }
+  r := libc_write(fd, _p0, Size_t(len(p)));
+  if r == -1 { errno = GetErrno() }
+  n = int(r);
+  return;
+}
+
+func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+  var _p0 *byte;
+  if len(p) > 0 { _p0 = &p[0]; }
+  r := libc_pread(fd, _p0, Size_t(len(p)), Offset_t(offset));
+  if r == -1 { errno = GetErrno() }
+  n = int(r);
+  return;
+}
+
+func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+  var _p0 *byte;
+  if len(p) > 0 { _p0 = &p[0]; }
+  r := libc_pwrite(fd, _p0, Size_t(len(p)), Offset_t(offset));
+  if r == -1 { errno = GetErrno() }
+  n = int(r);
+  return;
+}
+
+func Seek(fd int, offset int64, whence int) (off int64, errno int) {
+  r := libc_lseek64(fd, Offset_t(offset), whence);
+  if r == -1 { errno = GetErrno() }
+  off = int64(r);
+  return;
+}
+
+func Pipe(p []int) (errno int) {
+  if len(p) != 2 {
+    return EINVAL;
+  }
+  var pp [2]int;
+  r := libc_pipe(&pp[0]);
+  if r < 0 {
+    errno = GetErrno();
+  }
+  p[0] = pp[0];
+  p[1] = pp[1];
+  return;
+}
+
+func Stat(name string, buf *Stat_t) (errno int) {
+  r := libc_stat(StringBytePtr(name), buf);
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Lstat(name string, buf *Stat_t) (errno int) {
+  r := libc_lstat(StringBytePtr(name), buf);
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Fstat(fd int, buf *Stat_t) (errno int) {
+  r := libc_fstat(fd, buf);
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Unlink(name string) (errno int) {
+  r := libc_unlink(StringBytePtr(name));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Rmdir(name string) (errno int) {
+  r := libc_rmdir(StringBytePtr(name));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Mkdir(path string, mode int) (errno int) {
+  r := libc_mkdir(StringBytePtr(path), Mode_t(mode));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Gettimeofday(tv *Timeval) (errno int) {
+  r := libc_gettimeofday(tv, nil);
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+type FdSet_t struct {
+	Fds_bits [(FD_SETSIZE + 63) / 64]int64;
+}
+
+func FDSet(fd int, set *FdSet_t) {
+	set.Fds_bits[fd / 64] |= (1 << (uint)(fd % 64))
+}
+
+func FDClr(fd int, set *FdSet_t) {
+	set.Fds_bits[fd / 64] &= ^(1 << (uint)(fd % 64))
+}
+
+func FDIsSet(fd int, set *FdSet_t) bool {
+	if set.Fds_bits[fd / 64] & (1 << (uint)(fd % 64)) != 0 {
+		return true
+	} else {
+		return false
+	}
+}
+
+func FDZero(set *FdSet_t) {
+	for i := 0; i < ((FD_SETSIZE + 63) / 64); i++ {
+		set.Fds_bits[i] = 0
+	}
+}
+
+func Select(nfds int, r *FdSet_t, w *FdSet_t, e *FdSet_t, timeout *Timeval) (n int, errno int) {
+  n = libc_select(nfds, (*byte)(unsafe.Pointer(r)),
+		  (*byte)(unsafe.Pointer(e)),
+		  (*byte)(unsafe.Pointer(e)), timeout);
+  if n < 0 { errno = GetErrno() }
+  return;
+}
+
+func Chdir(path string) (errno int) {
+  r := libc_chdir(StringBytePtr(path));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Fchdir(fd int) (errno int) {
+  r := libc_fchdir(int(fd));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+const ImplementsGetwd = true
+
+func Getwd() (ret string, errno int) {
+	for len := Size_t(4096); ; len *= 2 {
+		b := make([]byte, len);
+		p := libc_getcwd(&b[0], len);
+		if p != nil {
+			i := 0;
+			for b[i] != 0 {
+				i++;
+			}
+			return string(b[0:i]), 0;
+		}
+		e := GetErrno();
+		if e != ERANGE {
+			return "", e;
+		}
+	}
+}
+
+func Link(oldpath, newpath string) (errno int) {
+  r := libc_link(StringBytePtr(oldpath), StringBytePtr(newpath));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Symlink(oldpath, newpath string) (errno int) {
+  r := libc_symlink(StringBytePtr(oldpath), StringBytePtr(newpath));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Readlink(path string, buf []byte) (n int, errno int) {
+  var _p0 *byte;
+  if len(buf) > 0 { _p0 = &buf[0]; }
+  r := libc_readlink(StringBytePtr(path), _p0, Size_t(len(buf)));
+  if r < 0 { errno = GetErrno() }
+  n = int(r);
+  return;
+}
+
+func Rename(oldpath, newpath string) (errno int) {
+	r := libc_rename(StringBytePtr(oldpath), StringBytePtr(newpath));
+	if r < 0 { errno = GetErrno() }
+	return 
+}
+
+func Chmod(path string, mode int) (errno int) {
+  r := libc_chmod(StringBytePtr(path), Mode_t(mode));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Fchmod(fd, mode int) (errno int) {
+  r := libc_fchmod(fd, Mode_t(mode));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Chown(path string, uid int, gid int) (errno int) {
+  r := libc_chown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Lchown(path string, uid int, gid int) (errno int) {
+  r := libc_lchown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Fchown(fd int, uid int, gid int) (errno int) {
+  r := libc_fchown(fd, Uid_t(uid), Gid_t(gid));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Truncate(path string, length int64) (errno int) {
+  r := libc_truncate64(StringBytePtr(path), Offset_t(length));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Ftruncate(fd int, length int64) (errno int) {
+  r := libc_ftruncate64(fd, Offset_t(length));
+  if r < 0 { errno = GetErrno() }
+  return;
+}
+
+func Utimes(path string, tv []Timeval) (errno int) {
+  if len(tv) != 2 {
+    return EINVAL;
+  }
+  r := libc_utimes(StringBytePtr(path),
+		   (*[2]Timeval)(unsafe.Pointer(&tv[0])));
+  if r < 0 {
+    errno = GetErrno();
+  }
+  return;
+}
+
+// Getuid returns the numeric user id of the caller.
+func Getuid() int {
+  return int(libc_getuid());
+}
+
+// Geteuid returns the numeric effective user id of the caller.
+func Geteuid() int {
+  return int(libc_geteuid());
+}
+
+// Getgid returns the numeric group id of the caller.
+func Getgid() int {
+  return int(libc_getgid());
+}
+
+// Getegid returns the numeric effective group id of the caller.
+func Getegid() int {
+  return int(libc_getegid());
+}
+
+// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
+func Getgroups() (gids []int, errno int) {
+	n := libc_getgroups(0, nil);
+	if n < 0 {
+		return nil, GetErrno();
+	}
+	if n == 0 {
+		return nil, 0;
+	}
+
+	// Sanity check group count.  Max is 1<<16 on Linux.
+	if n < 0 || n > 1<<20 {
+		return nil, EINVAL;
+	}
+
+	a := make([]Gid_t, n);
+	n = libc_getgroups(n, &a[0]);
+	if n < 0 {
+		return nil, GetErrno();
+	}
+	gids = make([]int, n);
+	for i, v := range a[0:n] {
+		gids[i] = int(v);
+	}
+	return;
+}
+
+func Getpagesize() int {
+	return libc_getpagesize();
+}
+
+func TimespecToNsec(ts Timespec) int64 {
+	return int64(ts.Sec)*1e9 + int64(ts.Nsec);
+}
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+	ts.Sec = Timespec_sec_t(nsec / 1e9);
+	ts.Nsec = Timespec_nsec_t(nsec % 1e9);
+	return;
+}
+
+func TimevalToNsec(tv Timeval) int64 {
+	return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3;
+}
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+	nsec += 999;	// round up to microsecond
+	tv.Sec = Timeval_sec_t(nsec/1e9);
+	tv.Usec = Timeval_usec_t(nsec%1e9 / 1e3);
+	return;
+}
+
+func Exit(code int) {
+	libc_exit(code);
+}
+
+func fcntl(fd, cmd, arg int) (val int, errno int) {
+  val = libc_fcntl(int(fd), int(cmd), int(arg));
+  if val == -1 { errno = GetErrno() }
+  return;
+}
+
+func Getpid() (pid int) {
+  return int(libc_getpid());
+}
+
+func Getppid() (ppid int) {
+  return int(libc_getppid());
+}
+
+func Kill(pid int, sig int) (errno int) {
+	r := libc_kill(Pid_t(pid), sig)
+	if r < 0 {
+		errno = GetErrno()
+	}
+	return
+}
Index: libgo/syscalls/exec_stubs.go
===================================================================
--- libgo/syscalls/exec_stubs.go	(revision 0)
+++ libgo/syscalls/exec_stubs.go	(revision 0)
@@ -0,0 +1,25 @@ 
+// exec_stubs.go -- fork/exec stubs.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Stubs for fork, exec and wait.
+
+package syscall
+
+func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
+	return -1, ENOSYS;
+}
+
+func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
+	return -1, ENOSYS;
+}
+
+func Exec(argv0 string, argv []string, envv []string) (err int) {
+	return ENOSYS;
+}
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+	return -1, ENOSYS;
+}
Index: libgo/syscalls/exec_helpers.go
===================================================================
--- libgo/syscalls/exec_helpers.go	(revision 0)
+++ libgo/syscalls/exec_helpers.go	(revision 0)
@@ -0,0 +1,154 @@ 
+// exec_helpers.go -- helper functions used with fork, exec, wait.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+import "sync"
+
+// Lock synchronizing creation of new file descriptors with fork.
+//
+// We want the child in a fork/exec sequence to inherit only the
+// file descriptors we intend.  To do that, we mark all file
+// descriptors close-on-exec and then, in the child, explicitly
+// unmark the ones we want the exec'ed program to keep.
+// Unix doesn't make this easy: there is, in general, no way to
+// allocate a new file descriptor close-on-exec.  Instead you
+// have to allocate the descriptor and then mark it close-on-exec.
+// If a fork happens between those two events, the child's exec
+// will inherit an unwanted file descriptor.
+//
+// This lock solves that race: the create new fd/mark close-on-exec
+// operation is done holding ForkLock for reading, and the fork itself
+// is done holding ForkLock for writing.  At least, that's the idea.
+// There are some complications.
+//
+// Some system calls that create new file descriptors can block
+// for arbitrarily long times: open on a hung NFS server or named
+// pipe, accept on a socket, and so on.  We can't reasonably grab
+// the lock across those operations.
+//
+// It is worse to inherit some file descriptors than others.
+// If a non-malicious child accidentally inherits an open ordinary file,
+// that's not a big deal.  On the other hand, if a long-lived child
+// accidentally inherits the write end of a pipe, then the reader
+// of that pipe will not see EOF until that child exits, potentially
+// causing the parent program to hang.  This is a common problem
+// in threaded C programs that use popen.
+//
+// Luckily, the file descriptors that are most important not to
+// inherit are not the ones that can take an arbitrarily long time
+// to create: pipe returns instantly, and the net package uses
+// non-blocking I/O to accept on a listening socket.
+// The rules for which file descriptor-creating operations use the
+// ForkLock are as follows:
+//
+// 1) Pipe.    Does not block.  Use the ForkLock.
+// 2) Socket.  Does not block.  Use the ForkLock.
+// 3) Accept.  If using non-blocking mode, use the ForkLock.
+//             Otherwise, live with the race.
+// 4) Open.    Can block.  Use O_CLOEXEC if available (Linux).
+//             Otherwise, live with the race.
+// 5) Dup.     Does not block.  Use the ForkLock.
+//             On Linux, could use fcntl F_DUPFD_CLOEXEC
+//             instead of the ForkLock, but only for dup(fd, -1).
+
+type WaitStatus int
+
+var ForkLock sync.RWMutex
+
+// Convert array of string to array
+// of NUL-terminated byte pointer.
+func StringArrayPtr(ss []string) []*byte {
+	bb := make([]*byte, len(ss)+1);
+	for i := 0; i < len(ss); i++ {
+		bb[i] = StringBytePtr(ss[i]);
+	}
+	bb[len(ss)] = nil;
+	return bb;
+}
+
+func CloseOnExec(fd int) {
+	fcntl(fd, F_SETFD, FD_CLOEXEC);
+}
+
+func SetNonblock(fd int, nonblocking bool) (errno int) {
+	flag, err := fcntl(fd, F_GETFL, 0);
+	if err != 0 {
+		return err;
+	}
+	if nonblocking {
+		flag |= O_NONBLOCK;
+	} else {
+		flag &= ^O_NONBLOCK;
+	}
+	flag, err = fcntl(fd, F_SETFL, flag);
+	return err;
+}
+
+// Wait status is 7 bits at bottom, either 0 (exited),
+// 0x7F (stopped), or a signal number that caused an exit.
+// The 0x80 bit is whether there was a core dump.
+// An extra number (exit code, signal causing a stop)
+// is in the high bits.  At least that's the idea.
+// There are various irregularities.  For example, the
+// "continued" status is 0xFFFF, distinguishing itself
+// from stopped via the core dump bit.
+
+const (
+	mask = 0x7F;
+	core = 0x80;
+	exited = 0x00;
+	stopped = 0x7F;
+	shift = 8;
+)
+
+func (w WaitStatus) Exited() bool {
+	return w&mask == exited;
+}
+
+func (w WaitStatus) Signaled() bool {
+	return w&mask != stopped && w&mask != exited;
+}
+
+func (w WaitStatus) Stopped() bool {
+	return w&0xFF == stopped;
+}
+
+func (w WaitStatus) Continued() bool {
+	return w == 0xFFFF;
+}
+
+func (w WaitStatus) CoreDump() bool {
+	return w.Signaled() && w&core != 0;
+}
+
+func (w WaitStatus) ExitStatus() int {
+	if !w.Exited() {
+		return -1;
+	}
+	return int(w >> shift) & 0xFF;
+}
+
+func (w WaitStatus) Signal() int {
+	if !w.Signaled() {
+		return -1;
+	}
+	return int(w & mask);
+}
+
+func (w WaitStatus) StopSignal() int {
+	if !w.Stopped() {
+		return -1;
+	}
+	return int(w >> shift) & 0xFF;
+}
+
+func (w WaitStatus) TrapCause() int {
+	if w.StopSignal() != SIGTRAP {
+		return -1;
+	}
+	return int(w >> shift) >> 8;
+}
Index: libgo/syscalls/socket_linux.go
===================================================================
--- libgo/syscalls/socket_linux.go	(revision 0)
+++ libgo/syscalls/socket_linux.go	(revision 0)
@@ -0,0 +1,135 @@ 
+// socket_linux.go -- Socket handling specific to Linux.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Low-level socket interface.
+// Only for implementing net package.
+
+// DO NOT USE DIRECTLY.
+
+package syscall
+
+import "unsafe"
+
+type RawSockaddrInet4 struct {
+	Family uint16;
+	Port uint16;
+	Addr [4]byte /* in_addr */;
+	Zero [8]uint8;
+}
+
+type RawSockaddrInet6 struct {
+	Family uint16;
+	Port uint16;
+	Flowinfo uint32;
+	Addr [16]byte /* in6_addr */;
+	Scope_id uint32;
+}
+
+type RawSockaddrUnix struct {
+	Family uint16;
+	Path [108]int8;
+}
+
+type RawSockaddr struct {
+	Family uint16;
+	Data [14]int8;
+}
+
+func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Family = AF_INET;
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+	p[0] = byte(sa.Port>>8);
+	p[1] = byte(sa.Port);
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i];
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0;
+}
+
+func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Family = AF_INET6;
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
+	p[0] = byte(sa.Port>>8);
+	p[1] = byte(sa.Port);
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i];
+	}
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0;
+}
+
+func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+	name := sa.Name;
+	n := len(name);
+	if n >= len(sa.raw.Path) || n == 0 {
+		return nil, 0, EINVAL;
+	}
+	sa.raw.Family = AF_UNIX;
+	for i := 0; i < n; i++ {
+		sa.raw.Path[i] = int8(name[i]);
+	}
+	if sa.raw.Path[0] == '@' {
+		sa.raw.Path[0] = 0;
+	}
+
+	// length is family, name, NUL.
+	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 1 + Socklen_t(n) + 1, 0;
+}
+
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
+	switch rsa.Addr.Family {
+	case AF_UNIX:
+		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
+		sa := new(SockaddrUnix);
+		if pp.Path[0] == 0 {
+			// "Abstract" Unix domain socket.
+			// Rewrite leading NUL as @ for textual display.
+			// (This is the standard convention.)
+			// Not friendly to overwrite in place,
+			// but the callers below don't care.
+			pp.Path[0] = '@';
+		}
+
+		// Assume path ends at NUL.
+		// This is not technically the Linux semantics for
+		// abstract Unix domain sockets--they are supposed
+		// to be uninterpreted fixed-size binary blobs--but
+		// everyone uses this convention.
+		n := 0;
+		for n < len(pp.Path) - 3 && pp.Path[n] != 0 {
+			n++;
+		}
+		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
+		sa.Name = string(bytes[0:n]);
+		return sa, 0;
+
+	case AF_INET:
+		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
+		sa := new(SockaddrInet4);
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+		sa.Port = int(p[0])<<8 + int(p[1]);
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i];
+		}
+		return sa, 0;
+
+	case AF_INET6:
+		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
+		sa := new(SockaddrInet6);
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+		sa.Port = int(p[0])<<8 + int(p[1]);
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i];
+		}
+		return sa, 0;
+	}
+	return nil, EAFNOSUPPORT;
+}
Index: libgo/syscalls/syscall.go
===================================================================
--- libgo/syscalls/syscall.go	(revision 160705)
+++ libgo/syscalls/syscall.go	(working copy)
@@ -48,20 +48,3 @@  func Syscall6(trap, a1, a2, a3, a4, a5, 
   }
   return r, 0, uintptr(GetErrno());
 }
-
-// StringByteSlice returns a NUL-terminated slice of bytes
-// containing the text of s.
-func StringByteSlice(s string) []byte {
-	a := make([]byte, len(s)+1);
-	for i := 0; i < len(s); i++ {
-		a[i] = s[i];
-	}
-	return a;
-}
-
-// StringBytePtr returns a pointer to a NUL-terminated array of bytes
-// containing the text of s.
-func StringBytePtr(s string) *byte {
-	p := StringByteSlice(s);
-	return &p[0];
-}
Index: libgo/configure.ac
===================================================================
--- libgo/configure.ac	(revision 160789)
+++ libgo/configure.ac	(working copy)
@@ -115,14 +115,17 @@  AC_SUBST(LIBFFIINCS)
 is_darwin=no
 is_freebsd=no
 is_linux=no
+is_rtems=no
 case ${host} in
   *-*-darwin*) is_darwin=yes ;;
   *-*-freebsd*) is_freebsd=yes ;;
   *-*-linux*)  is_linux=yes  ;;
+  *-*-rtems*)  is_rtems=yes  ;;
 esac
 AM_CONDITIONAL(LIBGO_IS_DARWIN, test $is_darwin = yes)
 AM_CONDITIONAL(LIBGO_IS_FREEBSD, test $is_freebsd = yes)
 AM_CONDITIONAL(LIBGO_IS_LINUX, test $is_linux = yes)
+AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
 
 is_386=no
 is_x86_64=no
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 160950)
+++ libgo/Makefile.am	(working copy)
@@ -879,15 +879,35 @@  syscall_os_file =
 syscall_arch_file =
 endif
 
+if LIBGO_IS_RTEMS
+syscall_exec_os_file = syscalls/exec_stubs.go
+syscall_socket_os_file = syscalls/socket_bsd.go
+syscall_socket_epoll_file=
+syscall_sysfile_os_file = syscalls/sysfile_rtems.go
+syscall_syscall_file = syscalls/syscall_stubs.go
+syscall_errstr_file = syscalls/errstr_rtems.go
+else
+syscall_exec_os_file = syscalls/exec.go
+syscall_socket_os_file = syscalls/socket_linux.go
+syscall_socket_epoll_file = syscalls/socket_epoll.go
+syscall_sysfile_os_file = syscalls/sysfile_linux.go
+syscall_syscall_file = syscalls/syscall.go
+syscall_errstr_file = syscalls/errstr.go
+endif
+
 go_syscall_files = \
-	syscalls/errstr.go \
-	syscalls/exec.go \
+	$(syscall_errstr_file) \
+	syscalls/exec_helpers.go \
+	$(syscall_exec_os_file) \
 	syscalls/socket.go \
-	syscalls/socket_epoll.go \
-	syscalls/syscall.go \
+	$(syscall_socket_os_file) \
+	$(syscall_socket_epoll_file) \
+	$(syscall_syscall_file) \
+	syscalls/stringbyte.go \
 	$(syscall_os_file) \
 	$(syscall_arch_file) \
-	syscalls/sysfile.go \
+	syscalls/sysfile_posix.go \
+	$(syscall_sysfile_os_file) \
 	sysinfo.go
 go_syscall_c_files = \
 	syscalls/errno.c