zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

auth.go (2321B)


      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 }