1package wayland
2
3import (
4 "fmt"
5 "os"
6 "path/filepath"
7
8 "golang.org/x/sys/unix"
9)
10
11func listen(runtimeDir string) (name string, fd int, cleanup func(), err error) {
12 for n := 1; n <= 32; n++ {
13 name = fmt.Sprintf("wayland-%d", n)
14 path := filepath.Join(runtimeDir, name)
15 lock := path + ".lock"
16 l, e := unix.Open(lock, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0660)
17 if e != nil {
18 return "", -1, nil, e
19 }
20 if e = unix.Flock(l, unix.LOCK_EX|unix.LOCK_NB); e != nil {
21 unix.Close(l)
22 if e == unix.EWOULDBLOCK {
23 continue
24 }
25 return "", -1, nil, e
26 }
27 cleanup = func() { os.Remove(path); os.Remove(lock); unix.Close(l) }
28 if e = os.Remove(path); e != nil && !os.IsNotExist(e) {
29 cleanup()
30 return "", -1, nil, e
31 }
32 fd, e = unix.Socket(unix.AF_UNIX, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
33 if e == nil {
34 e = unix.Bind(fd, &unix.SockaddrUnix{Name: path})
35 }
36 if e == nil {
37 e = unix.Listen(fd, 128)
38 }
39 if e != nil {
40 if fd >= 0 {
41 unix.Close(fd)
42 }
43 cleanup()
44 return "", -1, nil, e
45 }
46 return name, fd, cleanup, nil
47 }
48 return "", -1, nil, fmt.Errorf("no free wayland socket in %s", runtimeDir)
49}