Merge pull request #41 from mneumann/fix_dragonfly

Support DragonFly BSD
diff --git a/mktypes.bash b/mktypes.bash
index 9952c88..0c07680 100755
--- a/mktypes.bash
+++ b/mktypes.bash
@@ -13,7 +13,7 @@
 $GODEFS types.go |gofmt > ztypes_$GOARCH.go
 
 case $GOOS in
-freebsd)
+freebsd|dragonfly)
 	$GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go
 	;;
 esac
diff --git a/pty_dragonfly.go b/pty_dragonfly.go
new file mode 100644
index 0000000..5dc82de
--- /dev/null
+++ b/pty_dragonfly.go
@@ -0,0 +1,77 @@
+package pty
+
+import (
+	"errors"
+	"os"
+	"syscall"
+	"unsafe"
+	"strings"
+)
+
+// same code as pty_darwin.go
+func open() (pty, tty *os.File, err error) {
+	p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	sname, err := ptsname(p)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	err = grantpt(p)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	err = unlockpt(p)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	t, err := os.OpenFile(sname, os.O_RDWR, 0)
+	if err != nil {
+		return nil, nil, err
+	}
+	return p, t, nil
+}
+
+
+func grantpt(f *os.File) error {
+        _, err := isptmaster(f.Fd())
+        return err
+}
+
+func unlockpt(f *os.File) error {
+        _, err := isptmaster(f.Fd())
+        return err
+}
+
+func isptmaster(fd uintptr) (bool, error) {
+	err := ioctl(fd, syscall.TIOCISPTMASTER, 0)
+	return err == nil, err
+}
+
+var (
+	emptyFiodgnameArg fiodgnameArg
+	ioctl_FIODNAME   = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg))
+)
+
+func ptsname(f *os.File) (string, error) {
+	name := make([]byte, _C_SPECNAMELEN)
+	fa := fiodgnameArg {Name: (*byte)(unsafe.Pointer(&name[0])), Len: _C_SPECNAMELEN, Pad_cgo_0: [4]byte{0,0,0,0}}
+
+	err := ioctl(f.Fd(), ioctl_FIODNAME, uintptr(unsafe.Pointer(&fa)))
+	if err != nil {
+		return "", err
+	}
+
+	for i, c := range name {
+		if c == 0 {
+                        s := "/dev/" + string(name[:i])
+			return strings.Replace(s, "ptm", "pts", -1), nil
+		}
+	}
+	return "", errors.New("TIOCPTYGNAME string not NUL-terminated")
+}
diff --git a/pty_unsupported.go b/pty_unsupported.go
index 898c730..bd3d1e7 100644
--- a/pty_unsupported.go
+++ b/pty_unsupported.go
@@ -1,4 +1,4 @@
-// +build !linux,!darwin,!freebsd
+// +build !linux,!darwin,!freebsd,!dragonfly
 
 package pty
 
diff --git a/types_dragonfly.go b/types_dragonfly.go
new file mode 100644
index 0000000..5c0493b
--- /dev/null
+++ b/types_dragonfly.go
@@ -0,0 +1,17 @@
+// +build ignore
+
+package pty
+
+/*
+#define _KERNEL
+#include <sys/conf.h>
+#include <sys/param.h>
+#include <sys/filio.h>
+*/
+import "C"
+
+const (
+	_C_SPECNAMELEN = C.SPECNAMELEN /* max length of devicename */
+)
+
+type fiodgnameArg C.struct_fiodname_args
diff --git a/ztypes_dragonfly_amd64.go b/ztypes_dragonfly_amd64.go
new file mode 100644
index 0000000..6b0ba03
--- /dev/null
+++ b/ztypes_dragonfly_amd64.go
@@ -0,0 +1,14 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_dragonfly.go
+
+package pty
+
+const (
+	_C_SPECNAMELEN = 0x3f
+)
+
+type fiodgnameArg struct {
+	Name      *byte
+	Len       uint32
+	Pad_cgo_0 [4]byte
+}