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  }