github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/auth.go (about) 1 package xgb 2 3 /* 4 auth.go contains functions to facilitate the parsing of .Xauthority files. 5 6 It is largely unmodified from the original XGB package that I forked. 7 */ 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "io" 13 "os" 14 ) 15 16 // readAuthority reads the X authority file for the DISPLAY. 17 // If hostname == "" or hostname == "localhost", 18 // then use the system's hostname (as returned by os.Hostname) instead. 19 func readAuthority(hostname, display string) ( 20 name string, data []byte, err error) { 21 22 // b is a scratch buffer to use and should be at least 256 bytes long 23 // (i.e. it should be able to hold a hostname). 24 b := make([]byte, 256) 25 26 // As per /usr/include/X11/Xauth.h. 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 }