github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/apps/tao/tao.go (about) 1 // Copyright (c) 2015, Kevin Walsh. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "flag" 19 "fmt" 20 "os" 21 "strings" 22 "syscall" 23 24 _ "github.com/golang/glog" 25 "github.com/jlmucb/cloudproxy/go/util" 26 "github.com/jlmucb/cloudproxy/go/util/options" 27 ) 28 29 // This file does not use package glog or package flag. It is intended to be a 30 // thin wrapper around the other commands, and it deliberately does not parse 31 // most arguments. 32 33 func help() { 34 help := "Usage: %[1]s [-help] <command> <args>\n" 35 help += "\n" 36 help += "Options:\n" 37 help += " -help Show this help message\n" 38 help += " -help <command> Show help on <command>\n" 39 help += "\n" 40 help += "Commands:\n" 41 help += " domain Configure and manage Tao domains\n" 42 help += " host Start and stop a Tao host\n" 43 help += " run Start a new hosted program\n" 44 help += " list List hosted programs\n" 45 help += " stop Stop hosted programs\n" 46 help += " kill Kill hosted programs\n" 47 help += "\n" 48 49 fmt.Fprintf(os.Stderr, help, os.Args[0]) 50 logging := options.Category{"logging", "Options to control log output"} 51 options.ShowRelevant(os.Stderr, logging) 52 } 53 54 func match(s string, a ...string) bool { 55 for _, v := range a { 56 if s == v { 57 return true 58 } 59 } 60 return false 61 } 62 63 func flagName(arg string) string { 64 if arg == "" || arg[0] != '-' { 65 return "" 66 } 67 arg = arg[1:] 68 if len(arg) > 0 && arg[0] == '-' { 69 arg = arg[1:] 70 } 71 return arg 72 } 73 74 func main() { 75 // tao -help ==> show main help 76 // tao ==> show main help 77 // tao [commonopts] cmd [otheropts] ==> some_cmd [commonopts] [otheropts] 78 79 boolopts := []string{"quiet", "help"} 80 valopts := []string{"tao_domain"} 81 82 flag.VisitAll(func(f *flag.Flag) { 83 type BoolFlag interface { 84 IsBoolFlag() bool 85 } 86 if b, ok := f.Value.(BoolFlag); ok && b.IsBoolFlag() { 87 boolopts = append(boolopts, f.Name) 88 } else { 89 valopts = append(valopts, f.Name) 90 } 91 }) 92 93 // TODO(sid): This does not pass application arguments like -domain_config 94 // or path to the called program (like tao_lauch). I don't see why all the 95 // arguments to tao_launch, for example, should be checked by tao. We should 96 // sure that tao_launch also passes the arguments to the launched program as 97 // should linux_host. --- jlm 98 var args []string 99 cmd := "help" 100 for i := 1; i < len(os.Args); i++ { 101 arg := os.Args[i] 102 if arg == "help" || arg == "-?" { 103 args = append(args, "-help") 104 continue 105 } 106 if arg == "--" { 107 args = append(args, os.Args[i:]...) 108 break 109 } 110 if arg == "" || arg[0] != '-' { 111 cmd = arg 112 args = append(args, os.Args[i+1:]...) 113 break 114 } 115 if e := strings.Index(arg, "="); e != -1 { // -name=val 116 name := flagName(arg[0:e]) 117 if !match(name, boolopts...) && !match(name, valopts...) { 118 options.Usage("Unrecognized option: %s", arg) 119 } 120 args = append(args, arg) 121 } else if match(flagName(arg), boolopts...) { // -bool 122 args = append(args, arg) 123 } else if match(flagName(arg), valopts...) { // -name val 124 if i+1 >= len(os.Args) { 125 options.Usage("flag needs an argument: %s", arg) 126 } 127 args = append(args, arg, os.Args[i+1]) 128 i++ 129 } else { 130 options.Usage("Unrecognized option: %s", arg) 131 } 132 } 133 134 // Add a default --tao_domain 135 // config := os.Getenv("TAO_DOMAIN") 136 // if config != "" { 137 // arg := fmt.Sprintf("--tao_domain='%s'", config) 138 // args = append([]string{arg}, args...) 139 // } 140 141 // Add a default --log_dir 142 logdir := os.TempDir() + "/tao_log" 143 if !util.IsDir(logdir) { 144 err := os.Mkdir(logdir, 0777) 145 options.FailIf(err, "Can't create log directory: %s", logdir) 146 err = os.Chmod(logdir, 0777) 147 options.FailIf(err, "Can't set permissions on log directory: %s", logdir) 148 } 149 arg := fmt.Sprintf("--log_dir=%s", logdir) 150 args = append([]string{arg}, args...) 151 152 // Maybe add --alsologtostderr=true too? 153 154 switch cmd { 155 case "help": 156 help() 157 case "domain": 158 subcmd(cmd, "tao_admin", args) 159 case "host": 160 subcmd(cmd, "linux_host", args) 161 case "run", "list", "stop", "kill": 162 subcmd(cmd, "tao_launch", args) 163 default: 164 options.Usage("Unrecognized tao command: %s", cmd) 165 } 166 } 167 168 func subcmd(cmd, prog string, args []string) { 169 dirs := util.LiberalSearchPath() 170 binary := util.FindExecutable(prog, dirs) 171 if binary == "" { 172 options.Fail(nil, "Can't find `%s` on path '%s'", prog, strings.Join(dirs, ":")) 173 } 174 args = append([]string{"tao_" + cmd}, args...) 175 err := syscall.Exec(binary, args, os.Environ()) 176 options.Fail(err, "Can't exec `%s`", cmd) 177 }