1 package xgb
2
3
8
9 import (
10 "encoding/binary"
11 "errors"
12 "io"
13 "os"
14 )
15
16
17
18
19 func readAuthority(hostname, display string) (
20 name string, data []byte, err error) {
21
22
23
24 b := make([]byte, 256)
25
26
27 const familyLocal = 256
28 const familyWild = 65535
29
30 if len(hostname) == 0 || hostname == "localhost" {
31 hostname, err = os.Hostname()
32 if err != nil {
33 return "", nil, err
34 }
35 }
36
37 fname := os.Getenv("XAUTHORITY")
38 if len(fname) == 0 {
39 home := os.Getenv("HOME")
40 if len(home) == 0 {
41 err = errors.New("Xauthority not found: $XAUTHORITY, $HOME not set")
42 return "", nil, err
43 }
44 fname = home + "/.Xauthority"
45 }
46
47 r, err := os.Open(fname)
48 if err != nil {
49 return "", nil, err
50 }
51 defer r.Close()
52
53 for {
54 var family uint16
55 if err := binary.Read(r, binary.BigEndian, &family); err != nil {
56 return "", nil, err
57 }
58
59 addr, err := getString(r, b)
60 if err != nil {
61 return "", nil, err
62 }
63
64 disp, err := getString(r, b)
65 if err != nil {
66 return "", nil, err
67 }
68
69 name0, err := getString(r, b)
70 if err != nil {
71 return "", nil, err
72 }
73
74 data0, err := getBytes(r, b)
75 if err != nil {
76 return "", nil, err
77 }
78
79 addrmatch := (family == familyWild) ||
80 (family == familyLocal && addr == hostname)
81 dispmatch := (disp == "") || (disp == display)
82
83 if addrmatch && dispmatch {
84 return name0, data0, nil
85 }
86 }
87 panic("unreachable")
88 }
89
90 func getBytes(r io.Reader, b []byte) ([]byte, error) {
91 var n uint16
92 if err := binary.Read(r, binary.BigEndian, &n); err != nil {
93 return nil, err
94 } else if n > uint16(len(b)) {
95 return nil, errors.New("bytes too long for buffer")
96 }
97
98 if _, err := io.ReadFull(r, b[0:n]); err != nil {
99 return nil, err
100 }
101 return b[0:n], nil
102 }
103
104 func getString(r io.Reader, b []byte) (string, error) {
105 b, err := getBytes(r, b)
106 if err != nil {
107 return "", err
108 }
109 return string(b), nil
110 }
111
View as plain text