shithub: mycel

Download patch

ref: 4653bf4759b83714a4931d28cecd01f6a7d95533
parent: 73c38e317976971341f58ebd74c568203cdfea1f
author: Philip Silva <philip.silva@protonmail.com>
date: Sun Jun 20 14:14:40 EDT 2021

cmd/jsfs

diff: cannot open a/cmd/devjs//null: file does not exist: 'a/cmd/devjs//null' diff: cannot open b/cmd/jsfs//null: file does not exist: 'b/cmd/jsfs//null' diff: cannot open a/domino/jsfcall//null: file does not exist: 'a/domino/jsfcall//null'
--- 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
+}