]> Cypherpunks repositories - gostls13.git/commitdiff
add os.Hostname
authorRuss Cox <rsc@golang.org>
Mon, 29 Jun 2009 20:44:46 +0000 (13:44 -0700)
committerRuss Cox <rsc@golang.org>
Mon, 29 Jun 2009 20:44:46 +0000 (13:44 -0700)
R=r
DELTA=188  (182 added, 3 deleted, 3 changed)
OCL=30856
CL=30860

src/pkg/os/Makefile
src/pkg/os/os_test.go
src/pkg/os/sys_darwin.go [new file with mode: 0644]
src/pkg/os/sys_linux.go [new file with mode: 0644]
src/pkg/syscall/syscall_darwin.go
src/pkg/syscall/syscall_linux.go
src/pkg/syscall/zsyscall_darwin_386.go
src/pkg/syscall/zsyscall_darwin_amd64.go

index c5f790f15d0a75a51b24a772efe97d7328df13df..bb2559e8689cc2b04e5bc89b9d2c7e1f99e8318c 100644 (file)
@@ -2,8 +2,9 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
+
 # DO NOT EDIT.  Automatically generated by gobuild.
-# gobuild -m dir_${GOOS}_${GOARCH}.go env.go error.go file.go path.go stat_${GOOS}_${GOARCH}.go time.go types.go exec.go proc.go getwd.go >Makefile
+# gobuild -m dir_${GOOS}_${GOARCH}.go env.go error.go file.go path.go stat_${GOOS}_${GOARCH}.go time.go types.go exec.go proc.go getwd.go sys_${GOOS}.go >Makefile
 
 D=
 
@@ -20,7 +21,7 @@ test: packages
 
 coverage: packages
        gotest
-       6cov -g `pwd` | grep -v '_test\.go:'
+       6cov -g $$(pwd) | grep -v '_test\.go:'
 
 %.$O: %.go
        $(GC) -I_obj $*.go
@@ -49,6 +50,7 @@ O4=\
        exec.$O\
        getwd.$O\
        path.$O\
+       sys_$(GOOS).$O\
 
 
 phases: a1 a2 a3 a4
@@ -67,7 +69,7 @@ a3: $(O3)
        rm -f $(O3)
 
 a4: $(O4)
-       $(AR) grc _obj$D/os.a dir_$(GOOS)_$(GOARCH).$O exec.$O getwd.$O path.$O
+       $(AR) grc _obj$D/os.a dir_$(GOOS)_$(GOARCH).$O exec.$O getwd.$O path.$O sys_$(GOOS).$O
        rm -f $(O4)
 
 
index fb555eb8613b3ded62279c7ec8942270ec4d80b4..3dd975660e670bf3d4cae3f8c0a5d7cef6879d69 100644 (file)
@@ -587,3 +587,43 @@ func TestOpenError(t *testing.T) {
                }
        }
 }
+
+func run(t *testing.T, cmd []string) string {
+       // Run /bin/hostname and collect output.
+       r, w, err := Pipe();
+       if err != nil {
+               t.Fatal(err);
+       }
+       pid, err := ForkExec("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr});
+       if err != nil {
+               t.Fatal(err);
+       }
+       w.Close();
+
+       var b io.ByteBuffer;
+       io.Copy(r, &b);
+       Wait(pid, 0);
+       output := string(b.Data());
+       if n := len(output); n > 0 && output[n-1] == '\n' {
+               output = output[0:n-1];
+       }
+       if output == "" {
+               t.Fatalf("%v produced no output", cmd);
+       }
+
+       return output;
+}
+
+
+func TestHostname(t *testing.T) {
+       // Check internal Hostname() against the output of /bin/hostname.
+       hostname, err := Hostname();
+       if err != nil {
+               t.Fatalf("%v", err);
+       }
+       want := run(t, []string{"/bin/hostname"});
+       if hostname != want {
+               t.Errorf("Hostname() = %q, want %q", hostname, want);
+       }
+}
+
diff --git a/src/pkg/os/sys_darwin.go b/src/pkg/os/sys_darwin.go
new file mode 100644 (file)
index 0000000..ed5e501
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// Darwin-specific
+
+package os
+
+import (
+       "os";
+       "syscall";
+)
+
+func Hostname() (name string, err os.Error) {
+       var errno int;
+       name, errno = syscall.Sysctl("kern.hostname");
+       if errno != 0 {
+               return "", NewSyscallError("sysctl kern.hostname", errno);
+       }
+       return name, nil;
+}
diff --git a/src/pkg/os/sys_linux.go b/src/pkg/os/sys_linux.go
new file mode 100644 (file)
index 0000000..85f094e
--- /dev/null
@@ -0,0 +1,29 @@
+// 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.
+
+// Linux-specific
+
+package os
+
+import "os"
+
+// Hostname returns the host name reported by the kernel.
+func Hostname() (name string, err os.Error) {
+       f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0);
+       if err != nil {
+               return "", err;
+       }
+       defer f.Close();
+
+       var buf [512]byte;      // Enough for a DNS name.
+       n, err := f.Read(&buf);
+       if err != nil {
+               return "", err;
+       }
+
+       if n > 0 && buf[n-1] == '\n' {
+               n--;
+       }
+       return string(buf[0:n]), nil;
+}
index dcb92e0aca18a340f223e047f55e990154e76cb6..b8657aca56e85d072e22035a022842a591e54a4b 100644 (file)
@@ -361,6 +361,82 @@ func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno
        return kevent(kq, change, len(changes), event, len(events), timeout);
 }
 
+//sys  sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL
+
+// Translate "kern.hostname" to []_C_int{0,1,2,3}.
+func nametomib(name string) (mib []_C_int, errno int) {
+       const CTL_MAXNAME = 12;
+       const siz = uintptr(unsafe.Sizeof(mib[0]));
+
+       // NOTE(rsc): It seems strange to set the buffer to have
+       // size CTL_MAXNAME+2 but use only CTL_MAXNAME
+       // as the size.  I don't know why the +2 is here, but the
+       // kernel uses +2 for its own implementation of this function.
+       // I am scared that if we don't include the +2 here, the kernel
+       // will silently write 2 words farther than we specify
+       // and we'll get memory corruption.
+       var buf [CTL_MAXNAME+2] _C_int;
+       n := uintptr(CTL_MAXNAME)*siz;
+
+       p := (*byte)(unsafe.Pointer(&buf[0]));
+       bytes := StringByteSlice(name);
+
+       // Magic sysctl: "setting" 0.3 to a string name
+       // lets you read back the array of integers form.
+       if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 {
+               return nil, errno;
+       }
+       return buf[0:n/siz], 0;
+}
+
+func Sysctl(name string) (value string, errno int) {
+       // Translate name to mib number.
+       mib, errno := nametomib(name);
+       if errno != 0 {
+               return "", errno;
+       }
+
+       // Find size.
+       n := uintptr(0);
+       if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
+               return "", errno;
+       }
+       if n == 0 {
+               return "", 0;
+       }
+
+       // Read into buffer of that size.
+       buf := make([]byte, n);
+       if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
+               return "", errno;
+       }
+
+       // Throw away terminating NUL.
+       if n > 0 && buf[n-1] == '\x00' {
+               n--;
+       }
+       return string(buf[0:n]), 0;
+}
+
+func SysctlUint32(name string) (value uint32, errno int) {
+       // Translate name to mib number.
+       mib, errno := nametomib(name);
+       if errno != 0 {
+               return 0, errno;
+       }
+
+       // Read into buffer of that size.
+       n := uintptr(4);
+       buf := make([]byte, 4);
+       if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
+               return 0, errno;
+       }
+       if n != 4 {
+               return 0, EIO;
+       }
+       return *(*uint32)(unsafe.Pointer(&buf[0])), 0;
+}
+
 // TODO: wrap
 //     Acct(name nil-string) (errno int)
 //     Futimes(fd int, timeval *Timeval) (errno int)   // Pointer to 2 timevals!
@@ -500,7 +576,6 @@ func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno
 // Kdebug_trace
 // Sigreturn
 // Mmap
-// __Sysctl
 // Mlock
 // Munlock
 // Atsocket
index 4c9ac287564dc98200cfe389021324fbe7eeebf3..c3ef9162aecb51ec32d9ea0f063bd028173f17c7 100644 (file)
@@ -383,8 +383,6 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
 // Recvfrom
 // Sendmsg
 // Recvmsg
-// Getsockname
-// Getpeername
 // Socketpair
 // Getsockopt
 
index 6241efa51453b6f71cdb6c29ccd179b9abd16987..c83e63de3f93855e9dad761b39876b4723a92924 100644 (file)
@@ -87,6 +87,14 @@ func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, time
        return;
 }
 
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
+       var _p0 *_C_int;
+       if len(mib) > 0 { _p0 = &mib[0]; }
+       r0, r1, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen));
+       errno = int(e1);
+       return;
+}
+
 func fcntl(fd int, cmd int, arg int) (val int, errno int) {
        r0, r1, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg));
        val = int(r0);
index 49e17d43b13a0d4aa6b3c8f75c307bdb605f2b16..7afb209538f6c78ae6cdf11cf7af76f9d3ffc835 100644 (file)
@@ -87,6 +87,14 @@ func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, time
        return;
 }
 
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
+       var _p0 *_C_int;
+       if len(mib) > 0 { _p0 = &mib[0]; }
+       r0, r1, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen));
+       errno = int(e1);
+       return;
+}
+
 func fcntl(fd int, cmd int, arg int) (val int, errno int) {
        r0, r1, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg));
        val = int(r0);