9fans.net/go@v0.0.7/cmd/samterm/sys.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "flag" 6 "fmt" 7 "io" 8 "log" 9 "os" 10 "strconv" 11 12 "9fans.net/go/draw" 13 "9fans.net/go/plan9" 14 "9fans.net/go/plan9/client" 15 "9fans.net/go/plumb" 16 ) 17 18 var exname string 19 20 func usage() { 21 fmt.Fprintf(os.Stderr, "usage: samterm -a -W winsize\n") 22 os.Exit(2) 23 } 24 25 func getscreen() { 26 flag.BoolVar(&autoindent, "a", autoindent, "enable autoindent") 27 winsize := flag.String("W", "", "set initial window `size`") 28 log.SetPrefix("samterm: ") 29 log.SetFlags(0) 30 flag.Usage = usage 31 flag.Parse() 32 33 d, err := draw.Init(nil, "", "sam", *winsize) 34 if err != nil { 35 log.Fatal("drawinit: ", err) 36 } 37 display = d 38 screen = display.ScreenImage 39 font = display.Font 40 41 t := os.Getenv("tabstop") 42 if t != "" { 43 maxtab, _ = strconv.Atoi(t) 44 } 45 screen.Draw(screen.Clipr, display.White, nil, draw.ZP) 46 } 47 48 func screensize(w *int, h *int) bool { 49 if w != nil { 50 *w = 0 51 } 52 if h != nil { 53 *h = 0 54 } 55 return false 56 } 57 58 func snarfswap(fromsam []byte) (fromterm []byte) { 59 defer display.WriteSnarf(fromsam) 60 _, size, err := display.ReadSnarf(nil) 61 if err != nil { 62 return nil 63 } 64 fromterm = make([]byte, size) 65 n, size, err := display.ReadSnarf(fromterm) 66 if n < size { 67 return nil 68 } 69 return fromterm[:n] 70 } 71 72 func dumperrmsg(count int, typ Hmesg, count0 int, c int) { 73 fmt.Fprintf(os.Stderr, "samterm: host mesg: count %d %#x %#x %#x %s...ignored\n", count, typ, count0, c, rcvstring()) 74 } 75 76 func removeextern() { 77 os.Remove(exname) 78 } 79 80 func extproc(c chan string, fd *os.File) { 81 buf := make([]byte, READBUFSIZE) 82 for { 83 n, err := fd.Read(buf) 84 if err != nil { 85 fmt.Fprintf(os.Stderr, "samterm: extern read error: %v\n", err) 86 return /* not a fatal error */ 87 } 88 c <- string(buf[:n]) 89 } 90 } 91 92 func plumb2cmd(m *plumb.Message) string { 93 act := m.LookupAttr("action") 94 if act != "" && act != "showfile" { 95 /* can't handle other cases yet */ 96 return "" 97 } 98 cmd := "B " + string(m.Data) 99 if cmd[len(cmd)-1] != '\n' { 100 cmd += "\n" 101 } 102 addr := m.LookupAttr("addr") 103 if addr != "" { 104 cmd += addr + "\n" 105 } 106 return cmd 107 } 108 109 func plumbproc(edit *client.Fid) { 110 r := bufio.NewReader(edit) 111 for { 112 m := new(plumb.Message) 113 if err := m.Recv(r); err != nil { 114 fmt.Fprintf(os.Stderr, "samterm: plumb read error: %v\n", err) 115 return /* not a fatal error */ 116 } 117 if cmd := plumb2cmd(m); cmd != "" { 118 plumbc <- cmd 119 } 120 } 121 } 122 123 func plumbstart() error { 124 f, err := plumb.Open("send", plan9.OWRITE) 125 if err == nil { /* not open is ok */ 126 plumbfd = f 127 } 128 129 f, err = plumb.Open("edit", plan9.OREAD) 130 if err != nil { 131 return err 132 } 133 134 plumbc = make(chan string) 135 go plumbproc(f) 136 return nil 137 } 138 139 func hostproc(c chan []byte) { 140 var buf [2][READBUFSIZE]byte 141 i := 0 142 for { 143 i = 1 - i /* toggle */ 144 n, err := hostfd[0].Read(buf[i][:]) 145 if false { 146 fmt.Fprintf(os.Stderr, "hostproc %d\n", n) 147 } 148 if err != nil { 149 if err == io.EOF { 150 if exiting != 0 { // TODO(rsc) races 151 return 152 } 153 err = io.ErrUnexpectedEOF 154 } 155 log.Fatalf("host read error: %v", err) 156 } 157 if false { 158 fmt.Fprintf(os.Stderr, "hostproc send %d\n", i) 159 } 160 c <- buf[i][:n] 161 } 162 } 163 164 func hoststart() { 165 hostc = make(chan []byte) 166 go hostproc(hostc) 167 }