ref: 4653bf4759b83714a4931d28cecd01f6a7d95533
parent: 73c38e317976971341f58ebd74c568203cdfea1f
author: Philip Silva <philip.silva@protonmail.com>
date: Sun Jun 20 14:14:40 EDT 2021
cmd/jsfs
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,5 @@
~*
.DS_Store
/cmd/browse/browse
+/cmd/jsfs/jsfs
main.js
--- a/browser/fs/fs.go
+++ b/browser/fs/fs.go
@@ -6,6 +6,7 @@
"fmt"
"github.com/knusbaum/go9p/fs"
"github.com/knusbaum/go9p/proto"
+ "github.com/psilva261/opossum"
"github.com/psilva261/opossum/logger"
"github.com/psilva261/opossum/nodes"
"net"
@@ -43,7 +44,7 @@
return
}
un = u.Username
- gn, err = group(u)
+ gn, err = opossum.Group(u)
if err != nil { log.Errorf("get group: %v", err)return
--- a/browser/fs/fs_plan9.go
+++ b/browser/fs/fs_plan9.go
@@ -4,20 +4,15 @@
"fmt"
"github.com/knusbaum/go9p"
"os"
- "os/user"
"syscall"
)
-func group(u *user.User) (string, error) {- return u.Gid, nil
-}
-
func post(srv go9p.Srv) (err error) {f1, f2, err := os.Pipe()
if err != nil { return fmt.Errorf("pipe: %w", err)}
-
+
go func() {err = go9p.ServeReadWriter(f1, f1, srv)
if err != nil {--- a/browser/fs/fs_unix.go
+++ b/browser/fs/fs_unix.go
@@ -3,18 +3,8 @@
package fs
import (
- "fmt"
"github.com/knusbaum/go9p"
- "os/user"
)
-
-func group(u *user.User) (string, error) {- g, err := user.LookupGroupId(u.Gid)
- if err != nil {- return "", fmt.Errorf("get group: %w", err)- }
- return g.Name, nil
-}
func post(srv go9p.Srv) (err error) { return go9p.PostSrv("opossum", srv)--- a/cmd/devjs/main.go
+++ /dev/null
@@ -1,133 +1,0 @@
-// js package as separate program (very wip)
-package main
-
-import (
- "encoding/json"
- "fmt"
- "github.com/psilva261/opossum/domino"
- "github.com/psilva261/opossum/domino/jsfcall"
- "github.com/psilva261/opossum/logger"
- "io"
- "os"
- "strings"
-)
-
-var (
- d *domino.Domino
- log *logger.Logger
-)
-
-func init() {- f := false
- t := true
- domino.DebugDumpJS = &t
- logger.Quiet = &f
- logger.Init()
- log = &logger.Logger{Debug: true}- domino.SetLogger(log)
-}
-
-func usage() {- log.Printf("usage: devjs -h htmlfile jsfile1 [jsfile2 [..]]")- os.Exit(1)
-}
-
-func Main(r io.Reader, w io.Writer, htm string, js []string) error {- msg := jsfcall.Msg{}- dec := json.NewDecoder(r)
- enc := json.NewEncoder(w)
-
- for {- err := dec.Decode(&msg)
- if err == io.EOF {- if d != nil {- // TODO: probably that's not even necessary
- d.Stop()
- }
- break
- }
- if err != nil {- return fmt.Errorf("decode: %v", err)- }
-
- switch msg.Type {- case jsfcall.Tinit:
- log.Printf("received Tinit")- log.Printf("htm=%v", htm)- d = domino.NewDomino(htm, nil, nil)
- d.Start()
- initialized := false
- for _, s := range js {- if _, err := d.Exec/*6*/(s, !initialized); err != nil {- if strings.Contains(err.Error(), "halt at") {- return fmt.Errorf("execution halted: %w", err)- }
- log.Printf("exec <script>: %v", err)- }
- initialized = true
- }
- if err := d.CloseDoc(); err != nil {- return fmt.Errorf("close doc: %w", err)- }
- resHtm, changed, err := d.TrackChanges()
- if err == nil {- log.Printf("processJS: changed = %v", changed)- } else {- return fmt.Errorf("track changes: %w", err)- }
- msg := &jsfcall.Msg{- Type: jsfcall.Rinit,
- Html: resHtm,
- }
- if err := enc.Encode(&msg); err != nil {- return fmt.Errorf("encode: %v", err)- }
- default:
- return fmt.Errorf("unhandled msg: %+v", msg)- }
- }
-
- return nil
-}
-
-func main() {- args := os.Args[1:]
- if len(args) == 0 {- usage()
- }
-
- htmlfile := ""
- jsfiles := make([]string, 0, len(args))
-
- for len(args) > 0 {- switch args[0] {- case "-h":
- htmlfile, args = args[1], args[2:]
- default:
- var jsfile string
- jsfile, args = args[0], args[1:]
- jsfiles = append(jsfiles, jsfile)
- }
- }
-
- htm := ""
- js := make([]string, 0, len(jsfiles))
- if htmlfile != "" {- b, err := os.ReadFile(htmlfile)
- if err != nil {- log.Fatalf(err.Error())
- }
- htm = string(b)
- }
- for _, jsfile := range jsfiles {- b, err := os.ReadFile(jsfile)
- if err != nil {- log.Fatalf(err.Error())
- }
- js = append(js, string(b))
- }
-
- if err := Main(os.Stdin, os.Stdout, htm, js); err != nil {- log.Fatalf("Main: %+v", err)- }
-}
--- /dev/null
+++ b/cmd/jsfs/main.go
@@ -1,0 +1,168 @@
+// js package as separate program (very wip)
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "github.com/knusbaum/go9p"
+ "github.com/knusbaum/go9p/fs"
+ "github.com/psilva261/opossum"
+ "github.com/psilva261/opossum/domino"
+ "github.com/psilva261/opossum/logger"
+ "io"
+ "net"
+ "os"
+ "os/user"
+ "strings"
+)
+
+var (
+ d *domino.Domino
+ log *logger.Logger
+ htm string
+ js []string
+)
+
+func init() {+ f := false
+ t := true
+ domino.DebugDumpJS = &t
+ logger.Quiet = &f
+ logger.Init()
+ log = &logger.Logger{Debug: true}+ domino.SetLogger(log)
+}
+
+func usage() {+ log.Printf("usage: jsfs -h htmlfile jsfile1 [jsfile2 [..]]")+ os.Exit(1)
+}
+
+func Main(r io.Reader, w io.Writer) (err error) {+ u, err := user.Current()
+ if err != nil {+ return fmt.Errorf("get user: %v", err)+ }
+ un := u.Username
+ gn, err := opossum.Group(u)
+ if err != nil {+ return fmt.Errorf("get group: %v", err)+ }
+
+ jsFS, root := fs.NewFS(un, gn, 0500)
+ c := fs.NewListenFile(jsFS.NewStat("ctl", un, gn, 0600))+ root.AddChild(c)
+ lctl := (*fs.ListenFileListener)(c)
+ go Ctl(lctl)
+ go func() {+ err := go9p.ServeReadWriter(r, w, jsFS.Server())
+ if err != nil {+ log.Errorf("jsfs: serve rw: %v", err)+ }
+ }()
+
+ return
+}
+
+func Ctl(lctl *fs.ListenFileListener) {+ for {+ conn, err := lctl.Accept()
+ if err != nil {+ log.Errorf("accept: %v", err)+ continue
+ }
+ go ctl(conn)
+ }
+}
+
+func ctl(conn net.Conn) {+ r := bufio.NewReader(conn)
+ w := bufio.NewWriter(conn)
+ defer conn.Close()
+
+ l, err := r.ReadString('\n')+ if err != nil {+ log.Errorf("jsfs: read string: %v", err)+ return
+ }
+ l = strings.TrimSpace(l)
+
+ switch l {+ case "start":
+ d = domino.NewDomino(htm, nil, nil)
+ d.Start()
+ initialized := false
+ for _, s := range js {+ if _, err := d.Exec(s, !initialized); err != nil {+ if strings.Contains(err.Error(), "halt at") {+ log.Errorf("execution halted: %v", err)+ return
+ }
+ log.Printf("exec <script>: %v", err)+ }
+ initialized = true
+ }
+ if err := d.CloseDoc(); err != nil {+ log.Errorf("close doc: %v", err)+ return
+ }
+ resHtm, changed, err := d.TrackChanges()
+ if err != nil {+ log.Errorf("track changes: %v", err)+ return
+ }
+ log.Printf("jsfs: processJS: changed = %v", changed)+ if changed {+ w.WriteString(resHtm)
+ w.Flush()
+ }
+ case "stop":
+ if d != nil {+ d.Stop()
+ d = nil
+ }
+ default:
+ log.Errorf("unknown cmd")+ }
+}
+
+func main() {+ args := os.Args[1:]
+ if len(args) == 0 {+ usage()
+ }
+
+ htmlfile := ""
+ jsfiles := make([]string, 0, len(args))
+
+ for len(args) > 0 {+ switch args[0] {+ case "-h":
+ htmlfile, args = args[1], args[2:]
+ default:
+ var jsfile string
+ jsfile, args = args[0], args[1:]
+ jsfiles = append(jsfiles, jsfile)
+ }
+ }
+
+ js = make([]string, 0, len(jsfiles))
+ if htmlfile != "" {+ b, err := os.ReadFile(htmlfile)
+ if err != nil {+ log.Fatalf(err.Error())
+ }
+ htm = string(b)
+ }
+ for _, jsfile := range jsfiles {+ b, err := os.ReadFile(jsfile)
+ if err != nil {+ log.Fatalf(err.Error())
+ }
+ js = append(js, string(b))
+ }
+
+ if err := Main(os.Stdin, os.Stdout); err != nil {+ log.Fatalf("Main: %+v", err)+ }
+}
--- /dev/null
+++ b/cmd/jsfs/main_test.go
@@ -1,0 +1,61 @@
+package main
+
+import (
+ "9fans.net/go/plan9"
+ "9fans.net/go/plan9/client"
+ "bytes"
+ "io"
+ "bufio"
+ "net"
+ "os/user"
+ "strings"
+ "testing"
+)
+
+func TestMain(t *testing.T) {+ u, err := user.Current()
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ un := u.Username
+ c1, c2 := net.Pipe()
+ err = Main(c1, c1)
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ conn, err := client.NewConn(c2)
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ fsys, err := conn.Attach(nil, un, "")
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ d, err := fsys.Stat("ctl")+ if err != nil {+ t.Fatalf("%v", err)+ }
+ if d.Name != "ctl" {+ t.Fail()
+ }
+ htm = "<html><h1 id=title>hello</h1></html>"
+ js = []string{+ "document.getElementById('title').innerHTML='world'",+ }
+ fid, err := fsys.Open("ctl", plan9.ORDWR)+ if err != nil {+ t.Fatalf("%v", err)+ }
+ defer fid.Close()
+ fid.Write([]byte("start\n"))+ r := bufio.NewReader(fid)
+ b := bytes.NewBuffer([]byte{})+ _, err = io.Copy(b, r)
+ if !strings.Contains(err.Error(), io.ErrClosedPipe.Error()) {+ t.Fatalf("%+v", err)+ }
+ t.Logf("%v", b.String())+ if !strings.Contains(b.String(), `<h1 id="title">world</h1>`) {+ t.Fail()
+ }
+}
--- a/domino/jsfcall/jsfcall.go
+++ /dev/null
@@ -1,17 +1,0 @@
-package jsfcall
-
-const (
- _ = iota
- Rerror
- Tinit
- Rinit
- Tclick
- Rclick
-)
-
-type Msg struct {- Type uint8
- Error string
- Changed bool
- Html string
-}
--- /dev/null
+++ b/opossum_plan9.go
@@ -1,0 +1,9 @@
+package opossum
+
+import (
+ "os/user"
+)
+
+func Group(u *user.User) (string, error) {+ return u.Gid, nil
+}
--- /dev/null
+++ b/opossum_unix.go
@@ -1,0 +1,16 @@
+// +build !plan9
+
+package opossum
+
+import (
+ "fmt"
+ "os/user"
+)
+
+func Group(u *user.User) (string, error) {+ g, err := user.LookupGroupId(u.Gid)
+ if err != nil {+ return "", fmt.Errorf("get group: %w", err)+ }
+ return g.Name, nil
+}
--
⑨