rsc.io/go@v0.0.0-20150416155037-e040fd465409/misc/ios/detect.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build ignore
     6  
     7  // detect attempts to autodetect the correct
     8  // values of the environment variables
     9  // used by go_darwin_arm_exec.
    10  package main
    11  
    12  import (
    13  	"bytes"
    14  	"fmt"
    15  	"io/ioutil"
    16  	"os"
    17  	"os/exec"
    18  	"strings"
    19  )
    20  
    21  func main() {
    22  	devID := detectDevID()
    23  	fmt.Printf("export GOIOS_DEV_ID=%s\n", devID)
    24  
    25  	udid := detectUDID()
    26  	mp := detectMobileProvisionFile(udid)
    27  
    28  	f, err := ioutil.TempFile("", "go_ios_detect_")
    29  	check(err)
    30  	fname := f.Name()
    31  	defer os.Remove(fname)
    32  
    33  	out := combinedOutput(parseMobileProvision(mp))
    34  	_, err = f.Write(out)
    35  	check(err)
    36  	check(f.Close())
    37  
    38  	appID, err := plistExtract(fname, "ApplicationIdentifierPrefix:0")
    39  	check(err)
    40  	fmt.Printf("export GOIOS_APP_ID=%s\n", appID)
    41  
    42  	teamID, err := plistExtract(fname, "Entitlements:com.apple.developer.team-identifier")
    43  	check(err)
    44  	fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID)
    45  }
    46  
    47  func detectDevID() string {
    48  	cmd := exec.Command("security", "find-identity", "-p", "codesigning", "-v")
    49  	lines := getLines(cmd)
    50  
    51  	for _, line := range lines {
    52  		if !bytes.Contains(line, []byte("iPhone Developer")) {
    53  			continue
    54  		}
    55  		fields := bytes.Fields(line)
    56  		return string(fields[1])
    57  	}
    58  	fail("no code signing identity found")
    59  	panic("unreachable")
    60  }
    61  
    62  var udidPrefix = []byte("UniqueDeviceID: ")
    63  
    64  func detectUDID() []byte {
    65  	cmd := exec.Command("ideviceinfo")
    66  	lines := getLines(cmd)
    67  	for _, line := range lines {
    68  		if bytes.HasPrefix(line, udidPrefix) {
    69  			return bytes.TrimPrefix(line, udidPrefix)
    70  		}
    71  	}
    72  	fail("udid not found; is the device connected?")
    73  	panic("unreachable")
    74  }
    75  
    76  func detectMobileProvisionFile(udid []byte) string {
    77  	cmd := exec.Command("mdfind", "-name", ".mobileprovision")
    78  	lines := getLines(cmd)
    79  
    80  	for _, line := range lines {
    81  		if len(line) == 0 {
    82  			continue
    83  		}
    84  		xmlLines := getLines(parseMobileProvision(string(line)))
    85  		for _, xmlLine := range xmlLines {
    86  			if bytes.Contains(xmlLine, udid) {
    87  				return string(line)
    88  			}
    89  		}
    90  	}
    91  	fail("did not find mobile provision matching device udid %s", udid)
    92  	panic("ureachable")
    93  }
    94  
    95  func parseMobileProvision(fname string) *exec.Cmd {
    96  	return exec.Command("security", "cms", "-D", "-i", string(fname))
    97  }
    98  
    99  func plistExtract(fname string, path string) ([]byte, error) {
   100  	out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print "+path, fname).CombinedOutput()
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	return bytes.TrimSpace(out), nil
   105  }
   106  
   107  func getLines(cmd *exec.Cmd) [][]byte {
   108  	out := combinedOutput(cmd)
   109  	return bytes.Split(out, []byte("\n"))
   110  }
   111  
   112  func combinedOutput(cmd *exec.Cmd) []byte {
   113  	out, err := cmd.CombinedOutput()
   114  	if err != nil {
   115  		fmt.Println(strings.Join(cmd.Args, "\n"))
   116  		fmt.Fprintln(os.Stderr, err)
   117  		os.Exit(1)
   118  	}
   119  	return out
   120  }
   121  
   122  func check(err error) {
   123  	if err != nil {
   124  		fail(err.Error())
   125  	}
   126  }
   127  
   128  func fail(msg string, v ...interface{}) {
   129  	fmt.Fprintf(os.Stderr, msg, v...)
   130  	fmt.Fprintln(os.Stderr)
   131  	os.Exit(1)
   132  }