From: Russ Cox Date: Mon, 29 Jun 2009 20:44:46 +0000 (-0700) Subject: add os.Hostname X-Git-Tag: weekly.2009-11-06~1307 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b32769b1a33c4008c6f314b178f2b30b4192281a;p=gostls13.git add os.Hostname R=r DELTA=188 (182 added, 3 deleted, 3 changed) OCL=30856 CL=30860 --- diff --git a/src/pkg/os/Makefile b/src/pkg/os/Makefile index c5f790f15d..bb2559e868 100644 --- a/src/pkg/os/Makefile +++ b/src/pkg/os/Makefile @@ -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) diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go index fb555eb861..3dd975660e 100644 --- a/src/pkg/os/os_test.go +++ b/src/pkg/os/os_test.go @@ -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 index 0000000000..ed5e501e8c --- /dev/null +++ b/src/pkg/os/sys_darwin.go @@ -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 index 0000000000..85f094effb --- /dev/null +++ b/src/pkg/os/sys_linux.go @@ -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; +} diff --git a/src/pkg/syscall/syscall_darwin.go b/src/pkg/syscall/syscall_darwin.go index dcb92e0aca..b8657aca56 100644 --- a/src/pkg/syscall/syscall_darwin.go +++ b/src/pkg/syscall/syscall_darwin.go @@ -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 diff --git a/src/pkg/syscall/syscall_linux.go b/src/pkg/syscall/syscall_linux.go index 4c9ac28756..c3ef9162ae 100644 --- a/src/pkg/syscall/syscall_linux.go +++ b/src/pkg/syscall/syscall_linux.go @@ -383,8 +383,6 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) { // Recvfrom // Sendmsg // Recvmsg -// Getsockname -// Getpeername // Socketpair // Getsockopt diff --git a/src/pkg/syscall/zsyscall_darwin_386.go b/src/pkg/syscall/zsyscall_darwin_386.go index 6241efa514..c83e63de3f 100644 --- a/src/pkg/syscall/zsyscall_darwin_386.go +++ b/src/pkg/syscall/zsyscall_darwin_386.go @@ -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); diff --git a/src/pkg/syscall/zsyscall_darwin_amd64.go b/src/pkg/syscall/zsyscall_darwin_amd64.go index 49e17d43b1..7afb209538 100644 --- a/src/pkg/syscall/zsyscall_darwin_amd64.go +++ b/src/pkg/syscall/zsyscall_darwin_amd64.go @@ -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);