func main() { defer app.Exiting() x := app.New() stacks := false opts.NewFlag("F", "debug fuse requests", &zxfs.Debug) opts.NewFlag("D", "debug", &x.Debug) opts.NewFlag("s", "statistics", &sflag) opts.NewFlag("x", "addr: re-export locally the ql tree to this address", &xaddr) opts.NewFlag("S", "dump stacks on unmount for debugging", &stacks) args, err := opts.Parse(x.Args) if err != nil { app.Warn("%s", err) opts.Usage() app.Exits(err) } switch len(args) { case 0: case 1: mntdir = args[1] default: app.Warn("wrong number of arguments") opts.Usage() app.Exits("usage") } dprintf("debug on\n") qfs, err := qlfs.New("qlfs") if err != nil { app.Fatal(err) } qfs.Dbg = x.Debug qfs.Flags.Add("fdebug", &zxfs.Debug) st := &zx.IOstats{} qfs.IOstats = st if xaddr != "" { rfs.Server(qfs, xaddr) } err = zxfs.MountServer(qfs, mntdir) if sflag { st.Averages() app.Warn("%s iostats:\n%s\n", qfs.Name(), st) } if stacks { app.Warn("*** PANICING ON USER REQUEST (-S) ***") panic("stack dump") } if err != nil { app.Fatal("%s", err) } app.Warn("unmounted: exiting") }
func pspdf(t *Text, wid int, out io.Writer, cline, outfig string) { // pipe the roff writer into a command to output ps and pdf cmd := exec.Command("sh", "-c", cline) cmd.Stdout = out stdin, err := cmd.StdinPipe() if err != nil { app.Fatal("pipe to sh: %s", err) } if err := cmd.Start(); err != nil { app.Fatal("pipe to sh: %s", err) } wrroff(t, wid, stdin, outfig) stdin.Close() if err := cmd.Wait(); err != nil { app.Warn("pspdf: sh: %s", err) } }
func main() { defer app.Exiting() os.Args[0] = "auth" app.New() dfltdir := auth.KeyDir() dir = dfltdir opts.NewFlag("d", "adir: clive auth dir", &dir) opts.NewFlag("f", "force write of key file when file already exists", &force) args, err := opts.Parse(os.Args) if err != nil { app.Warn("%s", err) opts.Usage() app.Exits(err) } if len(args) < 3 { opts.Usage() app.Exits("usage") } name, user, secret := args[0], args[1], args[2] groups := args[3:] file := auth.KeyFile(dir, name) fi, _ := os.Stat(file) if fi != nil && !force { app.Fatal("key file already exists") } err = auth.SaveKey(dir, name, user, secret, groups...) if err != nil { app.Fatal("%s: %s", file, err) } ks, err := auth.LoadKey(dir, name) if err != nil { app.Fatal("can't load key: %s", err) } for _, k := range ks { if k.Uid == user { app.Warn("%s", file) return } } app.Fatal("bad user") }
func (t *Text) indentPars() { top := &Elem{} t.Elems = indentedPars(top, t.Elems) if len(t.Elems) > 0 { app.Fatal("paragraphs left at lvl %d", t.Elems[0].indent) } t.Elems = top.Child t.iprintf("\nindented pars:\n") for _, e := range t.Elems { t.iprintf("%s\n", e) } t.iprintf("\n") }
// Add lf or gf to the 1st child of a pipe if it's a std pipe and not |a b c or -|a b c // Add |pf to std pipes that have a single child // No rewrite happens in inner pipes within subcmds, because they inherit the // input from the outer command. // builtins that do run here do not use a rewrite. func (x *xCmd) pipeRewrite(nd *Nd) *Nd { if x.plvl > 0 || nd == nil { return nd } if nd.Kind != Npipe { app.Fatal("pipeRewrite bug") } if len(nd.Child) == 0 { return nd } c := nd.Child[0] if c.Kind != Nexec || c.hasInOutRedirs() { return nd } if c.isHereCmd() || c.isCmd(noRewrites...) { return nd } c.Child = append(c.Child, nil) copy(c.Child[1:], c.Child[0:]) lf := "lf" if nd.IsGet { lf = "gf" } c.Child[0] = &Nd{Kind: Nname, Args: []string{lf}} if len(nd.Child) > 1{ f := nd.Child[1] if nd.IsGet || f.Kind != Nfor || len(f.Child) == 0 || len(f.Child[0].Child) != 1 { return nd } // insert pf between lf and for nd.Child = append(nd.Child, nil) copy(nd.Child[2:], nd.Child[1:]) pfnames := &Nd{Kind: Nname, Args: []string{"pf"}} pf := &Nd{Kind: Nexec, Child: []*Nd{pfnames}} pf.Redirs = append(pf.Redirs, x.newRedir("0", "|", false)...) pf.Redirs = append(pf.Redirs, x.newRedir("1", "|", false)...) nd.Child[1] = pf return nd } c.Redirs = append(c.Redirs, x.newRedir("1", "|", false)...) x.noDups(c.Redirs) pfnames := &Nd{Kind: Nname, Args: []string{"pf"}} pf := &Nd{Kind: Nexec, Child: []*Nd{pfnames}} pf.Redirs = append(pf.Redirs, x.newRedir("0", "|", false)...) nd.Child = append(nd.Child, pf) return nd }
func runTODO(x *xEnv, argv ...string) error { defer app.Exiting() app.Fatal("bug: todo: %v", app.Args()) return nil }
func main() { defer app.Exiting() os.Args[0] = "Q" c := app.New() opts.NewFlag("c", "ignored for compatibility", &dummy) opts.NewFlag("D", "debug", &c.Debug) edir := dbg.Usr opts.NewFlag("e", "env: qlfs environment name (defaults to uid)", &edir) opts.NewFlag("q", "qldir: qlfs root dir (defaults to /n/ql)", &ql) args, err := opts.Parse(os.Args) if err != nil { app.Warn("%s", err) opts.Usage() app.Exits(err) } cmd := "" if len(args) == 0 { app.Warn("no command given") opts.Usage() app.Exits(err) } cmd = strings.Join(args, " ") app.Dprintf("run %s\n", cmd) _, err = os.Stat(path.Join(ql, "Ctl")) if err != nil { app.Fatal("qlfs: %s", err) } env := path.Join(ql, edir) _, err = os.Stat(env) if err != nil { err = os.Mkdir(env, 0775) } if err != nil { app.Fatal("%s", err) } cdir := fmt.Sprintf("%s/%d", env, os.Getpid()) if err := os.Mkdir(cdir, 0755); err != nil { app.Fatal("%s", err) } var b bytes.Buffer io.Copy(&b, os.Stdin) if err := ioutil.WriteFile(path.Join(cdir, "in"), b.Bytes(), 0644); err != nil { os.RemoveAll(cdir) app.Fatal("writing in: %s", err) } if err := ioutil.WriteFile(path.Join(cdir, "cmd"), []byte(cmd), 0644); err != nil { os.RemoveAll(cdir) app.Fatal("writing cmd: %s", err) } oc := make(chan bool, 2) pfd, err := os.Open(path.Join(cdir, "pout")) if err != nil { app.Warn("out: %s", err) oc <- true } else { go func() { io.Copy(os.Stdout, pfd) pfd.Close() oc <- true }() } efd, err := os.Open(path.Join(cdir, "perr")) if err != nil { app.Warn("err: %s", err) oc <- true } else { go func() { io.Copy(os.Stderr, efd) efd.Close() oc <- true }() } <-oc <-oc sts, err := ioutil.ReadFile(path.Join(cdir, "wait")) os.RemoveAll(cdir) if err != nil { app.Exits(err) } s := string(sts) if s == "success" { s = "" } app.Exits(s) }
// Define a new flag with the given name and usage. // valuep must be a pointer to the argument type and will be set to // the command line flag value if the flag is found. // Known types are bool, int, Counter, Octal, Hexa, int64, uint64, string, // float64, time.Duration, time.Time, and []string. // []string is a string option that may be repeated. // The time formats understood are // "01/02" // "01/02/06" // "01/02/2006" // "2006/0102" // "15:04:05" // "15:04" // "3pm" // "3:04pm" // "01/02 15:04" // "01/02/06 15:04" // "01/02/2006 15:04" // "2006/0102 15:04 " // // If the name is "+..." or "-..." and vp is *int, then it is understood as // a request to accept +number or -number as an argument. // // The help string should just describe the flag for flags with no // argument, and should be something like "dir: do this with dir" // if the flag accepts a "dir" argument. This convention is used to generate // a good usage diagnostic. func (f *Flags) NewFlag(name, help string, vp interface{}) { if vp == nil { app.Fatal("flag %s: nil value", name) } if len(name) == 0 { app.Fatal("empty flag name") } if f.defs[name] != nil { app.Fatal("flag %s redefined", name) } aname := "" if i := strings.Index(help, ":"); i > 0 { aname = help[:i] } switch vp.(type) { case *bool: case *int: if aname == "" { aname = "num" } if name[0] == '+' { if f.plus != nil { app.Fatal("flag +number redefined") } f.plus = &def{name: name, help: help, valp: vp, argname: aname} return } if name[0] == '-' { if f.minus != nil { app.Fatal("flag -number redefined") } f.minus = &def{name: name, help: help, valp: vp, argname: aname} return } case *Counter: case *Octal, *Hexa, *int64, *uint64, *float64: if aname == "" { aname = "num" } case *string, *[]string: if aname == "" { aname = "str" } case *time.Duration: if aname == "" { aname = "ival" } case *time.Time: if aname == "" { aname = "time" } case *Range: if aname == "" { aname = "range" } default: app.Fatal("flag %s: unknown flag type", name) } if name[0]=='+' || name[0]=='-' { app.Fatal("name '±...' is only for *int") } f.defs[name] = &def{name: name, help: help, valp: vp, argname: aname} }