diff --git a/NOTES.md b/NOTES.md index 16aa923e155942dfdd07ac96fdfcde6441b590f0..dcea2dbc93ca931b2db98cd2c08763bdf8b1dff0 100644 --- a/NOTES.md +++ b/NOTES.md @@ -60,7 +60,7 @@ repl.commands? * Commands for a local mail system? * Commands to connect to Mattermost or mastodon? * Commands to manage users. - * `SHOW VERSION` - versioninfo doesn't work; what else? + * `SHOW VERSION` - [versioninfo](https://github.com/earthboundkid/versioninfo) will work for go install. * Check db version; notify user if it changes; refuse to write to db if it has. ## Module links diff --git a/accounts/accounts.go b/accounts/accounts.go index b905cb16e99e4475cf70f5c6d718dbec4d578a44..becd7b99c8edc58abdcaea8bac39bf869f2d0b9e 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -36,7 +36,7 @@ func ValidName(login string) error { } // Open verifies that an account exists. -func Open(login string) error { +func Open(login, name string) error { err := ValidName(login) if err != nil { return err @@ -55,10 +55,13 @@ func Open(login string) error { user.Login = login user.Admin = 0 - fmt.Printf("Welcome new user %s\n", login) - user.Name, err = GetLine("please enter your name: ") - if err != nil { - return err + user.Name = name + if name == "" { + fmt.Printf("Welcome new user %s\n", login) + user.Name, err = GetLine("please enter your name: ") + if err != nil { + return err + } } err = User.Folders.AddUser(*user) diff --git a/dclish/dclish.go b/dclish/dclish.go index 237f1978d6f0328c5241cf7d91aa803ea685b382..3e6cb9e00c49d45f3323388bd3fd4d425c4291da 100644 --- a/dclish/dclish.go +++ b/dclish/dclish.go @@ -27,7 +27,7 @@ type Command struct { Args []string MaxArgs int MinArgs int - Commands []*Command + Commands Commands Action ActionFunc Description string } @@ -108,11 +108,13 @@ func split(line string) []string { // ParseAndRun parses a command line and runs the command. func (c Commands) ParseAndRun(line string) error { - // TODO: this doesn't handle a DCL command line completely. + // Split into words. words := split(line) - cmd, ok := c[strings.ToUpper(words[0])] + + // Find the command. + wordup := strings.ToUpper(words[0]) + cmd, ok := c[wordup] if !ok { - wordup := strings.ToUpper(words[0]) possibles := []string{} for word := range c { if strings.HasPrefix(word, wordup) { @@ -124,13 +126,26 @@ func (c Commands) ParseAndRun(line string) error { fmt.Printf("ERROR: Unknown command '%s'\n", words[0]) return nil case 1: - cmd = c[possibles[0]] + wordup = possibles[0] + cmd = c[wordup] default: fmt.Printf("ERROR: Ambiguous command '%s' (matches %s)\n", words[0], strings.Join(possibles, ", ")) return nil } } + + // Deal with subcommands. + if len(cmd.Commands) > 0 { + if len(words) == 1 { + fmt.Printf("ERROR: missing subcommand for %s.\n", wordup) + return nil + } + // TODO: quoting is probably an issue here - break ParseAndRun into ParseAndRun + Run. + newline := strings.Join(words[1:], " ") + return cmd.Commands.ParseAndRun(newline) + } + if cmd.Action == nil { fmt.Printf("ERROR: Command not implemented:\n%s\n", cmd.Description) return nil @@ -139,6 +154,7 @@ func (c Commands) ParseAndRun(line string) error { cmd.Flags[flg].Value = cmd.Flags[flg].Default } cmd.Args = []string{} + if len(words) == 1 { if len(cmd.Args) < cmd.MinArgs { fmt.Println("ERROR: Not enough args.") diff --git a/folders/sql/1_create_table.up.sql b/folders/sql/1_create_table.up.sql index c8f55c2f0fe97672adcf357c6e56bc2f817c8b41..74bb11c115363182ad8a337d34b7d7cc3ae0cce8 100644 --- a/folders/sql/1_create_table.up.sql +++ b/folders/sql/1_create_table.up.sql @@ -3,6 +3,7 @@ CREATE TABLE users ( name VARCHAR(53) NOT NULL, admin INT DEFAULT 0, disabled INT DEFAULT 0, + last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, update_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL ) WITHOUT ROWID; @@ -140,3 +141,18 @@ CREATE TABLE mark ( ON DELETE CASCADE ON UPDATE CASCADE ) WITHOUT ROWID; + +--- TODO: The following is incomplete: +--- User configs. +CREATE TABLE config ( + login VARCHAR(25) REFERENCES users(login) ON DELETE CASCADE ON UPDATE CASCADE, + folder VARCHAR(25) REFERENCES folders(name) ON DELETE CASCADE ON UPDATE CASCADE, + always INT NOT NULL, + alert INT NOT NULL DEFAULT 0, --- 0=no, 1=brief, 2=readnew +) WITHOUT ROWID; + +--- System configs. +CREATE TABLE system ( + default_expire INT NOT NULL DEFAULT -1, + expire_limit INT NOT NULL DEFAULT -1, +) WITHOUT ROWID; diff --git a/go.mod b/go.mod index 406d51c905576656a91fcd4844fb61d2a00a1d78..ef5e66584e5598fc3ff29d78b56d626b898ed9b8 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,7 @@ go 1.24.2 require ( github.com/adrg/xdg v0.5.3 github.com/chzyer/readline v1.5.1 - github.com/davecgh/go-spew v1.1.1 - github.com/gdamore/tcell/v2 v2.7.1 + github.com/gdamore/tcell/v2 v2.8.1 github.com/golang-migrate/migrate/v4 v4.18.3 github.com/jmoiron/sqlx v1.4.0 github.com/rivo/tview v0.0.0-20250501113434-0c592cd31026 @@ -15,26 +14,24 @@ require ( ) require ( + github.com/carlmjohnson/versioninfo v0.22.5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/earthboundkid/versioninfo/v2 v2.24.1 // indirect - github.com/gdamore/encoding v1.0.0 // indirect - github.com/golang-migrate/migrate v3.5.4+incompatible // indirect + github.com/gdamore/encoding v1.0.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.7 // indirect go.uber.org/atomic v1.11.0 // indirect golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect golang.org/x/sys v0.33.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect - modernc.org/libc v1.65.1 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect + modernc.org/libc v1.65.2 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.10.0 // indirect ) diff --git a/go.sum b/go.sum index ec0708642f0bb9ccde75b2211857926955fbfb65..5fafbe6e01c71a8cc434e12b0802789ecbb39313 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,30 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= +github.com/carlmjohnson/versioninfo v0.22.5 h1:O00sjOLUAFxYQjlN/bzYTuZiS0y6fWDQjMRvwtKgwwc= +github.com/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/earthboundkid/versioninfo/v2 v2.24.1 h1:SJTMHaoUx3GzjjnUO1QzP3ZXK6Ee/nbWyCm58eY3oUg= -github.com/earthboundkid/versioninfo/v2 v2.24.1/go.mod h1:VcWEooDEuyUJnMfbdTh0uFN4cfEIg+kHMuWB2CDCLjw= -github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= -github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell/v2 v2.7.1 h1:TiCcmpWHiAU7F0rA2I3S2Y4mmLmO9KHxJ7E1QhYzQbc= -github.com/gdamore/tcell/v2 v2.7.1/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= +github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw= +github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo= +github.com/gdamore/tcell/v2 v2.8.1 h1:KPNxyqclpWpWQlPLx6Xui1pMk8S+7+R37h3g07997NU= +github.com/gdamore/tcell/v2 v2.8.1/go.mod h1:bj8ori1BG3OYMjmb3IklZVWfZUJ1UBQt9JXrOCOhGWw= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= -github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA= -github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk= github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs= github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -29,18 +34,19 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= -github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -50,6 +56,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/urfave/cli/v3 v3.3.2 h1:BYFVnhhZ8RqT38DxEYVFPPmGFTEf7tJwySTXsVRrS/o= github.com/urfave/cli/v3 v3.3.2/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -57,54 +65,104 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -modernc.org/libc v1.65.0 h1:e183gLDnAp9VJh6gWKdTy0CThL9Pt7MfcR/0bgb7Y1Y= -modernc.org/libc v1.65.0/go.mod h1:7m9VzGq7APssBTydds2zBcxGREwvIGpuUBaKTXdm2Qs= -modernc.org/libc v1.65.1 h1:EwykJ3C7c5pCiZTU3dLkgRm3VdFGNFc8UXXzhhEZvbQ= -modernc.org/libc v1.65.1/go.mod h1:+LU/iIPTqxVVdAl3E++KC9npafs4zI4pkLiolMVDatc= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s= +modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.27.1 h1:emhLB4uoOmkZUnTDFcMI3AbkmU/Evjuerit9Taqe6Ss= +modernc.org/ccgo/v4 v4.27.1/go.mod h1:543Q0qQhJWekKVS5P6yL5fO6liNhla9Lbm2/B3rEKDE= +modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8= +modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/libc v1.65.2 h1:drWL1QO9fKXr3kXDN8y+4lKyBr8bA3mtUBQpftq3IJw= +modernc.org/libc v1.65.2/go.mod h1:VI3V2S5mNka4deJErQ0jsMXe7jgxojE2fOB/mWoHlbc= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4= modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= +modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI= modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/main.go b/main.go index e6acf8f7386ba4dd7d407a44e613aa45eda76519..65011cada29ab9c795fc1e7b03c2b5f9d93cf67a 100644 --- a/main.go +++ b/main.go @@ -26,6 +26,11 @@ func main() { Usage: "user to run bulletin as", Required: true, }, + &cli.StringFlag{ + Name: "name", + Aliases: []string{"n"}, + Usage: "TODO: name for development", + }, &cli.StringFlag{ Name: "batch", Aliases: []string{"b"}, @@ -41,7 +46,7 @@ func main() { fmt.Println("ERROR: can only run batch commands as SYSTEM.") os.Exit(1) } - err := accounts.Open(user) + err := accounts.Open(user, cmd.String("name")) if err != nil { fmt.Printf("ERROR: %s.", err) os.Exit(1) @@ -60,7 +65,8 @@ func main() { } os.Exit(exitcode) } - err := accounts.Open(user) + + err := accounts.Open(user, cmd.String("name")) if err != nil { return err } diff --git a/repl/command.go b/repl/command.go index 11913d98e5e115c859d880e661a41e87cffa280e..9472a1cb11994eb76df9ea20ed280da2890ab998 100644 --- a/repl/command.go +++ b/repl/command.go @@ -147,8 +147,8 @@ changed, a file can be specified which contains the text. If the editor is used for changing the text, the old message text will be extracted. This can be suppressed by the qualifier /NEW. - Format: - CHANGE [file-name]`, + Format: + CHANGE [file-name]`, MaxArgs: 1, Action: ActionChange, Flags: dclish.Flags{ @@ -712,36 +712,17 @@ specified as xxx%"""address""".`, Description: `Sets the current or message-id message as marked. Marked messages are displayed with an asterisk in the left hand column of the directory listing. A marked message can serve as a reminder of important -information. The UNMARK command sets the current or message-id message -as unmarked. - - Format: - - MARK [message-number or numbers] - UNMARK [message-number or numbers] +information. -NOTE: The list of marked messages are stored in a file -username.BULLMARK. The files are created in the directory pointed to by -the logical name BULL_MARK. If BULL_MARK is not defined, SYS$LOGIN will -be used.`, + Format: + MARK [message-number or numbers]`, MaxArgs: 1, }, "UNMARK": { - Description: `Sets the current or message-id message as marked. Marked messages are -displayed with an asterisk in the left hand column of the directory -listing. A marked message can serve as a reminder of important -information. The UNMARK command sets the current or message-id message -as unmarked. - - Format: + Description: `Sets the current or message-id message as unmarked. - MARK [message-number or numbers] - UNMARK [message-number or numbers] - -NOTE: The list of marked messages are stored in a file -username.BULLMARK. The files are created in the directory pointed to by -the logical name BULL_MARK. If BULL_MARK is not defined, SYS$LOGIN will -be used.`, + Format: + UNMARK [message-number or numbers]`, MaxArgs: 1, }, "MODIFY": { @@ -844,8 +825,8 @@ released to the print queue until you exit, unless you add the qualifier /NOW or change one of the print job's qualifiers. Multiple messages are concatenated into one print job. - Format: - PRINT [message_number][-message_number1],[...] + Format: + PRINT [message_number][-message_number1],[...] A range of messages to be printed can optionally be specified, i.e. PRINT 2-5. @@ -910,8 +891,8 @@ will be displayed. However, if there are new messages, the first new message will be displayed. Each time you enter the command, the next page, or if there are no more pages, the next message will be displayed. - Format: - READ [message-number] + Format: + READ [message-number] The message's relative number is found by the DIRECTORY command. If you specify a number greater than the number of messages in the folder, the @@ -995,8 +976,8 @@ the help on the SEEN command.`, Description: `Removes a folder. Only the owner of a folder or a privileged user can remove the folder. - Format: - REMOVE folder-name`, + Format: + REMOVE folder-name`, MinArgs: 1, MaxArgs: 1, Action: ActionRemove, @@ -1006,8 +987,8 @@ remove the folder. read message with "RE:" preceeding it. Format and qualifiers is exactly the same as the ADD command except for /NOINDENT and /EXTRACT. - Format: - REPLY [file-name]`, + Format: + REPLY [file-name]`, MaxArgs: 1, Action: ActionReply, Flags: dclish.Flags{ @@ -1033,8 +1014,8 @@ the same as the ADD command except for /NOINDENT and /EXTRACT. Description: `Invokes the VAX/VMS Personal Mail Utility (MAIL) to send a reply mail message to the owner of the currently read message. - Format: - RESPOND [file-name] + Format: + RESPOND [file-name] If you wish to use another method for sending the mail, define BULL_MAILER to point to a command procedure. This procedure will then be @@ -1097,9 +1078,8 @@ username and subject of the message.`, Description: `Searches the currently selected folder for the message containing the first occurrence of the specified text string. - Format: - - SEARCH [search-string] + Format: + SEARCH [search-string] The search starts from the first message in the current folder. The search includes both the text of the message, and the description @@ -1151,46 +1131,22 @@ search can be aborted by typing a CTRL-C.`, track of messages on a per message basis. Seen messages are displayed with a greater than sign in the left hand column of the directory listing. Once you have used the SEEN command once, messages will be -automatically be set as being SEEN when they are read. The UNSEEN -command sets the current or message-id message as unseen. - - Format: +automatically be set as being SEEN when they are read. - SEEN [message-number or numbers] - UNSEEN [message-number or numbers] + Format: + SEEN [message-number or numbers] If you have used the SEEN command and wish to disable the automatic marking of messages in regular folders as SEEN when they are read, type -the command SEEN/NOREAD. To reenable, simply use the SEEN command again. - -NOTE: The list of SEEN messages are stored in a file username.BULLMARK. -NEWSMARK. The files are created in the directory pointed to by the -logical name BULL_MARK. If BULL_MARK is not defined, SYS$LOGIN will be -used.`, +the command SEEN/NOREAD. To reenable, simply use the SEEN command again.`, MinArgs: 1, MaxArgs: 1, }, "UNSEEN": { - Description: `Sets the current or message-id message as seen. This allows you to keep -track of messages on a per message basis. Seen messages are displayed -with a greater than sign in the left hand column of the directory -listing. Once you have used the SEEN command once, messages will be -automatically be set as being SEEN when they are read. The UNSEEN -command sets the current or message-id message as unseen. - - Format: - - SEEN [message-number or numbers] - UNSEEN [message-number or numbers] - -If you have used the SEEN command and wish to disable the automatic -marking of messages in regular folders as SEEN when they are read, type -the command SEEN/NOREAD. To reenable, simply use the SEEN command again. + Description: `Sets the current or message-id message as unseen. -NOTE: The list of SEEN messages are stored in a file username.BULLMARK. -NEWSMARK. The files are created in the directory pointed to by the -logical name BULL_MARK. If BULL_MARK is not defined, SYS$LOGIN will be -used.`, + Format: + UNSEEN [message-number or numbers]`, MinArgs: 1, MaxArgs: 1, }, @@ -1201,9 +1157,8 @@ READ, etc. will apply only to those messages. Use the CREATE command to create a folder. Use the DIRECTORY/FOLDER command to see the list of folders that have been created. - Format: - - SELECT [folder-name] + Format: + SELECT [folder-name] The complete folder name need not be specified. BULLETIN will try to find the closest matching name. I.e. INFOV can be used for INFOVAX. @@ -1228,11 +1183,11 @@ message.`, Description: `The SET command is used with other commands to define or change characteristics of the BULLETIN Utility. - Format: - SET option`, - Flags: dclish.Flags{ + Format: + SET option`, + Commands: dclish.Commands{ "ACCESS": { - Description: ` Controls access to a private folder. A private folder can only be + Description: `Controls access to a private folder. A private folder can only be selected by users who have been granted access. Only the owner of that folder is allowed to grant access. @@ -1264,7 +1219,7 @@ messages, and thus will not be able to set any login flags. (NOTE: If such a user selects such a folder and then uses SET ACCESS to grant him or herself access, the user must reselect the folder in order for the new access to take affect in order to be able to set login flags.) -3 id + The id-name can be one or more ids contained in the system Rights Database. This includes usernames and UICs. A UIC that contains a comma must be enclosed in quotes. UICs can contain wildcards, i.e. @@ -1276,32 +1231,40 @@ is useful when the folder is shared among nodes in a cluster. Alternatively, the id-name can be a filename which contains a list of ids. The filename should be preceeded by a "@". If the suffix is not specified, it will be assumed that the suffix is ".DIS" . -3 /ALL -Specifies that access to the folder is granted to all users. If /READ -is not specified, the folder will no longer be private. If /READ is -specified, all users will have read access, but only privileged users -will have write access (of course non-privileged users can gain access -via a later SET ACCESS command.) - -Format: - - SET ACCESS /ALL [folder-name] -3 /READ -Specifies that access to the folder will be limited to being able to -read the messages. -3 Warning -If a user logs in after a private folder has been created but before -being given access, and then is given access, any defaults that the -folder has, i.e. /BRIEF, /READNEW, & /NOTIFY, will not be set for that -user. This is because if the id is not a username, it becomes an -extremely lengthy operation to check each user to see if have that id -assigned to them. The alternative is to set the defaults for all users -after every SET ACCESS, but that might cause problems with users who -have manually reset those defaults. The correct solution requires a -large programming modification, which will be done in a later version.`, + +Warning + + If a user logs in after a private folder has been created but before + being given access, and then is given access, any defaults that the + folder has, i.e. /BRIEF, /READNEW, & /NOTIFY, will not be set for that + user. This is because if the id is not a username, it becomes an + extremely lengthy operation to check each user to see if have that id + assigned to them. The alternative is to set the defaults for all users + after every SET ACCESS, but that might cause problems with users who + have manually reset those defaults. The correct solution requires a + large programming modification, which will be done in a later version.`, + MinArgs: 1, + MaxArgs: 1, + Flags: dclish.Flags{ + "/ALL": { + Description: ` Specifies that access to the folder is granted to all users. If /READ + is not specified, the folder will no longer be private. If /READ is + specified, all users will have read access, but only privileged users + will have write access (of course non-privileged users can gain access + via a later SET ACCESS command.) + + Format: + SET ACCESS /ALL[=folder-name]`, + OptArg: true, + }, + "/READ": { + Description: ` Specifies that access to the folder will be limited to being able to + read the messages.`, + }, + }, }, "ALWAYS": { - Description: ` Specifies that the selected folder has the ALWAYS attribute. This + Description: `Specifies that the selected folder has the ALWAYS attribute. This causes messages in the folder to be displayed differently when logging in. SYSTEM messages will be displayed every time a user logs in, rather than just once. Non-SYSTEM message will also be displayed every time @@ -1311,10 +1274,16 @@ meant for messages which are very important, and thus you want to make sure they are read. Format: - SET [NO]ALWAYS`, + SET ALWAYS`, + }, + "NOALWAYS": { + Description: `Removes ALWAYS attribute from the selected folder. + + Format: + SET NOALWAYS`, }, "BRIEF": { - Description: ` Controls whether you will be alerted upon logging that there are new + Description: `Controls whether you will be alerted upon logging that there are new messages in the currently selected folder. A new message is defined as one that has been created since the last time you logged in or accessed BULLETIN. Note the difference between BRIEF and READNEW. The latter @@ -1323,41 +1292,53 @@ and prompts the user to read the messages. Setting BRIEF will clear a READNEW setting (and visa versa). Format: - SET [NO]BRIEF -3 /ALL -Specifies that the SET [NO]BRIEF option is the default for all users for -the specified folder. This is a privileged qualifier. -3 /DEFAULT -Specifies that the [NO]BRIEF option is the default for the specified -folder. This is a privileged qualifier. It will only affect brand new -users (or those that have never logged in). Use /ALL to modify all users. -3 /FOLDER - /FOLDER=foldername - -Specifies the folder for which the option is to modified. If not -specified, the selected folder is modified. Valid only with NOBRIEF. -3 /PERMANENT - /[NO]PERMANENT + SET BRIEF`, + Flags: dclish.Flags{ + "/ALL": { + Description: ` Specifies that the SET BRIEF option is the default for all users for + the specified folder. This is a privileged qualifier.`, + }, + "/DEFAULT": { + Description: ` Specifies that the BRIEF option is the default for the specified + folder. This is a privileged qualifier. It will only affect brand new + users (or those that have never logged in). Use /ALL to modify all + users.`, + }, + "/PERMANENT": { + Description: `/[NO]PERMANENT Specifies that BRIEF is a permanent flag and cannot be changed by the individual, except if changing to SHOWNEW or READNEW. This is a privileged qualifier.`, + }, + }, }, - "CONTINUOUS_BRIEF": { - Description: ` Specifies that if BRIEF is set for a folder, and there are new messages, -the notification message "there are new messages" will be displayed every -time when logging in, until the new messages are read. Normally, the -BRIEF setting causes notification only at the first time that new messages -are detected. + "NOBRIEF": { + Description: `Turns off BRIEF for the selected or specified folder. Format: - SET [NO]CONTINUOUS_BRIEF - -NOTE: Both SET GENERIC and SET CONTINUOUS_BRIEF cannot be set for the -same user.`, + SET NOBRIEF`, + Flags: dclish.Flags{ + "/ALL": { + Description: ` Specifies that the SET NOBRIEF option is the default for all users for + the specified folder. This is a privileged qualifier.`, + }, + "/DEFAULT": { + Description: ` Specifies that the NOBRIEF option is the default for the specified + folder. This is a privileged qualifier. It will only affect brand new + users (or those that have never logged in). Use /ALL to modify all + users.`, + }, + "/FOLDER": { + Description: `/FOLDER=foldername + + Specifies the folder for which the option is to modified. If not + specified, the selected folder is modified.`, + }, + }, }, "DEFAULT_EXPIRE": { - Description: ` Specifies the number of days the message created by BBOARD (or direct + Description: `Specifies the number of days the message created by BBOARD (or direct PMDF path) is to be retained. The default is 14 days. The highest limit that can be specified is 30 days. This can be overridden by a user with privileges. @@ -1367,8 +1348,8 @@ If no expiration date is entered when prompted for a date, or if prompting has been disabled via SET NOPROMPT_EXPIRE, this value will be used. - Format: - SET DEFAULT_EXPIRE days + Format: + SET DEFAULT_EXPIRE days If -1 is specified, messages will become permanent. If 0 is specified, no default expiration date will be present. The latter should never be @@ -1377,153 +1358,79 @@ disappear. NOTE: This value is the same value that SET BBOARD/EXPIRATION specifies. If one is changed, the other will change also.`, - }, - "DUMP": { - Description: ` Specifies that messages deleted from the selected folder are written -into a dump (or log) file. The name of the log file is foldername.LOG, -and it is located in the folder directory. - - Format: - SET [NO]DUMP - -The command SHOW FOLDER/FULL will show if dump has been set. (NOTE: -SHOW FOLDER/FULL is a privileged command.)`, + MinArgs: 1, + MaxArgs: 1, }, "EXPIRE_LIMIT": { - Description: ` Specifies expiration limit that is allowed for messages. Non-privileged -users cannot specify an expiration that exceeds the number of days -specified. Privileged users can exceed the limit. + Description: `Specifies expiration limit that is allowed for messages. Non-privileged +users cannot specify an expiration that exceeds the number of days +specified. Privileged users can exceed the limit. Setting days to 0 +removes the expiration limit. - SET [NO]EXPIRE_LIMIT [days] + Format: + SET EXPIRE_LIMIT days The command SHOW FOLDER/FULL will show the expiration limit, if one exists. (NOTE: SHOW FOLDER/FULL is a privileged command.)`, + MinArgs: 1, + MaxArgs: 1, }, "FOLDER": { - Description: ` Select a folder of messages. Identical to the SELECT command. See help + Description: `Select a folder of messages. Identical to the SELECT command. See help on that command for more information. Format: - SET FOLDER [folder-name] -3 /MARKED -Selects messages that have been marked (indicated by an asterisk). -After using /MARKED, in order to see all messages, the folder will have -to be reselected. -`, - }, - "GENERIC": { - Description: ` Specifies that the given account is a "generic" account, i.e used by -many different people. If an account is specified as GENERIC, new -messages placed in the GENERAL folder will be displayed upon logging in -for a specific number of days, rather than only once. The default -period is 7 days. This command is a privileged command. - - Format: - SET [NO]GENERIC username - -NOTE: Both SET GENERIC and SET CONTINUOUS_BRIEF cannot be set for the -same user. -3 /DAYS - /DAYS=number_of_days - -Specifies the number days that new GENERAL messages will be displayed -for upon logging in. -`, - }, - "KEYPAD": { - Description: ` Controls whether the keypad has been enabled such that the keys on the -keypad correspond to command definitions. These definitions can be seen -via the SHOW KEYPAD command. The default is NOKEYPAD unless the /KEYPAD -qualifier has been added to the BULLETIN command line. - - Format: - SET [NO]KEYPAD -`, - }, - "LOGIN": { - Description: ` Controls whether the specified user will be alerted of any messages, -whether system or non-system, upon logging in. If an account has the -DISMAIL flag set, SET NOLOGIN is automatically applied to that account -during the first time that the account logs in. However, this will not -occur if DISMAIL is set for an old account. Additionally, removing the -DISMAIL flag will not automatically enable LOGIN. (The reason for the -above was to avoid extra overhead for constant checking for the DISMAIL -flag.) This command is a privileged command. - - Format: - SET [NO]LOGIN username -`, - }, - "NODE": { - Description: ` Modifies the selected folder from a local folder to a remote folder. A -remote folder is a folder in which the messages are actually stored on a -folder at a remote DECNET node. The SET NODE command specifies the name -of the remote node, and optionally the name of the remote folder. If -the remote folder name is not included, it is assumed to be the same as -the local folder. When the command is executed, the selected folder -will then point to the remote folder. If there were messages in the -local folder, they will be deleted. This feature is present only if the -BULLCP process is running on the remote node. - - Format: - SET NODE nodename [remotename] - SET NONODE - -NOTE: If one node adds a message to a remote node, other nodes connected -to the same folder will not immediately be aware of the new message. -This info is updated every 15 minutes, or if a user accesses that -folder. -3 /FOLDER - /FOLDER=foldername - -Specifies the folder for which the node information is to modified. -If not specified, the selected folder is modified. -`, + SET FOLDER [folder-name]`, + MaxArgs: 1, + Action: ActionSetFolder, + Flags: dclish.Flags{ + "/MARKED": { + Description: ` Selects messages that have been marked (indicated by an asterisk). After + using /MARKED, in order to see all messages, the folder will have to be + reselected.`, + }, + }, }, "NOTIFY": { - Description: ` Specifies whether you will be notified via a broadcast message when a + Description: `Specifies whether you will be notified via a broadcast message when a message is added to the selected folder. Format: - SET [NO]NOTIFY + SET NOTIFY In a cluster, if the logical name MAIL$SYSTEM_FLAGS is defined so that bit 1 is set, users will be notified no matter which node they are logged in to. If you wish to disable this, you should define BULL_SYSTEM_FLAGS -so that bit 1 is cleared. -3 /ALL -Specifies that the SET [NO]NOTIFY option is the default for all users for -the specified folder. This is a privileged qualifier. -3 /DEFAULT -Specifies that the [NO]NOTIFY option is the default for the specified -folder. This is a privileged qualifier. It will only affect brand new -users (or those that have never logged in). Use /ALL to modify all users. -3 /FOLDER - /FOLDER=foldername - -Specifies the folder for which the option is to modified. If not -specified, the selected folder is modified. Valid only with NONOTIFY. -3 /PERMANENT - /[NO]PERMANENT - -Specifies that NOTIFY is a permanent flag and cannot be changed by the -individual. /DEFAULT must be specified. This is a privileged qualifier. -`, - }, - "PAGE": { - Description: ` Specifies whether any directory listing or message reading output will -pause when it reaches the end of the page or not. Setting NOPAGE is -useful for terminals that can store more than one screenful at a time, -and that have a remote printer that can then print the contents of the -terminal's memory. The default is PAGE, unless the default was changed -by specifying /NOPAGE on the command line to invoke BULLETIN. +so that bit 1 is cleared.`, + Flags: dclish.Flags{ + "/ALL": { + Description: ` Specifies that the SET NOTIFY option is the default for all users for + the specified folder. This is a privileged qualifier.`, + }, + "/DEFAULT": { + Description: ` Specifies that the NOTIFY option is the default for the specified + folder. This is a privileged qualifier. It will only affect brand new + users (or those that have never logged in). Use /ALL to modify all + users.`, + }, + "/PERMANENT": { + Description: `/[NO]PERMANENT + + Specifies that NOTIFY is a permanent flag and cannot be changed by + the individual. /DEFAULT must be specified. This is a privileged + qualifier.`, + }, + }, + }, + "NONOTIFY": { + Description: `Removes notification from the current folder or optional folder-name. Format: - SET [NO]PAGE -`, + SET NONOTIFY [folder-name]`, + MaxArgs: 1, }, "PRIVILEGES": { - Description: ` Specifies either process privileges or rights identifiers that are + Description: `Specifies either process privileges or rights identifiers that are necessary to use privileged commands. Use the SHOW PRIVILEGES command to see what is presently set. This is a privileged command. @@ -1532,31 +1439,37 @@ to see what is presently set. This is a privileged command. The parameters are one or more privileges separated by commas. To remove a privilege, specify the privilege preceeded by "NO". If /ID is -specified, the parameters are rights identifiers. -3 /ID - /[NO]ID +specified, the parameters are rights identifiers.`, + Flags: dclish.Flags{ + "/ID": { + Description: `/[NO]ID -If specified, then the rights identifier which is specified as the -parameter will allow users holding that rights identifier to execute -privileged commands. If /NOID is specified, the identifier is removed. -`, + If specified, then the rights identifier which is specified as the + parameter will allow users holding that rights identifier to execute + privileged commands. If /NOID is specified, the identifier is removed.`, + }, + }, }, "PROMPT_EXPIRE": { - Description: `Specifies that a user will be prompted for an expiration date when -adding a message. If NOPROMPT_EXPIRE is specified, the user will -not be prompted, and the default expiration (which is set by SET -DEFAULT_EXPIRE) will be used. If the value specified is greater than the -expiration limit, and the user does not have privileges, then the -expiration limit will be used as the default expiration. (If there is no -expiration limit, and the user doesn't have privileges, then an error -will result.) PROMPT_EXPIRE is the default. + Description: `Specifies that a user will be prompted for an expiration date when +adding a message. If the value specified is greater than the expiration +limit, and the user does not have privileges, then the expiration limit +will be used as the default expiration. (If there is no expiration +limit, and the user doesn't have privileges, then an error will result.) +PROMPT_EXPIRE is the default. Format: - SET [NO]PROMPT_EXPIRE -`, + SET PROMPT_EXPIRE`, + }, + "NOPROMPT_EXPIRE": { + Description: `The user will not be prompted, and the default expiration (which is set +by SET DEFAULT_EXPIRE) will be used. + + Format: + SET NOPROMPT_EXPIRE`, }, "READNEW": { - Description: ` Controls whether you will be prompted upon logging in if you wish to + Description: `Controls whether you will be prompted upon logging in if you wish to read new non-system or folder messages (if any exist). A new message is defined as one that has been added since the last login, or since accessing BULLETIN. The default setting for READNEW is dependent on how @@ -1565,7 +1478,7 @@ the folder was created by the owner. In order to apply this to a specific folder, first select the folder (using the SELECT command), and then enter the SET READNEW command. - Format: + Format: SET [NO]READNEW NOTE: If you have several folders with READNEW enabled, each folder's @@ -1576,30 +1489,37 @@ However, if you enter BULLETIN, you will be told that new messages are present in those other folders. Also, it is not possible to EXIT the READNEW mode if there are SYSTEM folders which have new messages. Typing the EXIT command will cause you to skip to those folders. (See HELP SET -SYSTEM for a description of a SYSTEM folder). -3 /ALL -Specifies that the SET [NO]READNEW option is the default for all users for -the specified folder. This is a privileged qualifier. The difference -between this and /DEFAULT is that the latter will only apply to new users -(i.e. any users which have never executed BULLETIN). -3 /DEFAULT -Specifies that the [NO]READNEW option is the default for the specified -folder. This is a privileged qualifier. It will only affect brand new -users (or those that have never logged in). Use /ALL to modify all users. -3 /FOLDER - /FOLDER=foldername - -Specifies the folder for which the option is to modified. If not -specified, the selected folder is modified. Valid only with NOREADNEW. -3 /PERMANENT - /[NO]PERMANENT - -Specifies that READNEW is a permanent flag and cannot be changed by the -individual. This is a privileged qualifier. -`, +SYSTEM for a description of a SYSTEM folder).`, + Flags: dclish.Flags{ + "/ALL": { + Description: ` Specifies that the SET [NO]READNEW option is the default for all users + for the specified folder. This is a privileged qualifier. The + difference between this and /DEFAULT is that the latter will only + apply to new users (i.e. any users which have never executed + BULLETIN).`, + }, + "/DEFAULT": { + Description: ` Specifies that the [NO]READNEW option is the default for the specified + folder. This is a privileged qualifier. It will only affect brand new + users (or those that have never logged in). Use /ALL to modify all + users.`, + }, + "/FOLDER": { + Description: `/FOLDER=foldername + + Specifies the folder for which the option is to modified. If not + specified, the selected folder is modified. Valid only with NOREADNEW.`, + }, + "/PERMANENT": { + Description: `/[NO]PERMANENT + + Specifies that READNEW is a permanent flag and cannot be changed by + the individual. This is a privileged qualifier.`, + }, + }, }, "SHOWNEW": { - Description: ` Controls whether a directory listing of new messages for the current + Description: `Controls whether a directory listing of new messages for the current folder will be displayed when logging in. This is similar to READNEW, except you will not be prompted to read the messages. The default is dependent on how the folder was created by the owner. A new message is @@ -1609,35 +1529,43 @@ accessing BULLETIN. In order to apply this to a specific folder, first select the folder (using the SELECT command), and then enter the SET SHOWNEW command. - Format: - SET [NO]SHOWNEW -3 /ALL -Specifies that the SET [NO]SHOWNEW option is the default for all users for -the specified folder. This is a privileged qualifier. The difference -between this and /DEFAULT is that the latter will only apply to new users -(i.e. any users which have never executed BULLETIN). -3 /DEFAULT -Specifies that the [NO]SHOWNEW option is the default for the specified -folder. This is a privileged qualifier. It will only affect brand new -users (or those that have never logged in). Use /ALL to modify all users. -3 /FOLDER - /FOLDER=foldername - -Specifies the folder for which the option is to modified. If not -specified, the selected folder is modified. Valid only with NOSHOWNEW. -3 /PERMANENT - /[NO]PERMANENT - -Specifies that SHOWNEW is a permanent flag and cannot be changed by the -individual, except if changing to READNEW. This is a privileged qualifier. -`, + Format: + SET [NO]SHOWNEW`, + Flags: dclish.Flags{ + "/ALL": { + Description: ` Specifies that the SET [NO]SHOWNEW option is the default for all users + for the specified folder. This is a privileged qualifier. The + difference between this and /DEFAULT is that the latter will only + apply to new users (i.e. any users which have never executed + BULLETIN).`, + }, + "/DEFAULT": { + Description: ` Specifies that the [NO]SHOWNEW option is the default for the specified + folder. This is a privileged qualifier. It will only affect brand new + users (or those that have never logged in). Use /ALL to modify all + users.`, + }, + "/FOLDER": { + Description: `/FOLDER=foldername + + Specifies the folder for which the option is to modified. If not + specified, the selected folder is modified. Valid only with NOSHOWNEW.`, + }, + "/PERMANENT": { + Description: `/[NO]PERMANENT + + Specifies that SHOWNEW is a permanent flag and cannot be changed by + the individual, except if changing to READNEW. This is a privileged + qualifier.`, + }, + }, }, "SYSTEM": { - Description: ` Specifies that the selected folder is a SYSTEM folder. A SYSTEM folder + Description: `Specifies that the selected folder is a SYSTEM folder. A SYSTEM folder is allowed to have SYSTEM and SHUTDOWN messages added to it. This is a privileged command. - Format: + Format: SET [NO]SYSTEM By default, the GENERAL folder is a SYSTEM folder, and the setting for @@ -1652,52 +1580,41 @@ folder at the other node is also a SYSTEM folder. "SHOW": { Description: `The SHOW command displays information about certain characteristics. `, - Flags: dclish.Flags{ + Commands: dclish.Commands{ "FLAGS": { - Description: ` Shows whether BRIEF, NOTIFY, READNEW, or SHOWNEW has been set for the + Description: `Shows whether BRIEF, NOTIFY, READNEW, or SHOWNEW has been set for the currently selected folder. `, }, "FOLDER": { - Description: ` Shows information about a folder of messages. Owner and description are -shown. If the folder name is omitted, and a folder has been selected via + Description: `Shows information about a folder of messages. Owner and description are +shown. If the folder name is omitted, and a folder has been selected via the SELECT command, information about that folder is shown. Format: - SHOW FOLDER [folder-name] -3 /FULL -Control whether all information of the folder is displayed. This -includes DUMP & SYSTEM settings, the access list if the folder is -private, and BBOARD information. This information is only those who -have access to that folder. -`, - }, - "KEYPAD": { - Description: ` Displays the keypad command definitions. If the keypad has been enabled -by either the SET KEYPAD COMMAND, or /KEYPAD is specified on the command -line, the keypad keys will be defined as commands. SHOW KEYPAD is the -equivalent of HELP KEYPAD. - -NOTE: If the keypad is not enabled, PF2 is defined to be SET KEYPAD. -3 /PRINT -Prints the keypad definitions on the default printer (SYS$PRINT). -`, + SHOW FOLDER [folder-name]`, + Flags: dclish.Flags{ + "/FULL": { + Description: ` Control whether all information of the folder is displayed. This + includes the SYSTEM setting, the access list if the folder is private, + and BBOARD information. This information is only those who have access + to that folder.`, + }, + }, }, "NEW": { - Description: ` Shows folders which have new unread messages for which BRIEF or READNEW -have been set. (Note: If you enter BULLETIN but do not read new unread -messages, you will not be notified about them the next time you enter -BULLETIN. This is a design "feature" and cannot easily be changed.) -`, + Description: `Shows folders which have new unread messages for which BRIEF or READNEW +have been set. (Note: If you enter BULLETIN but do not read new unread +messages, you will not be notified about them the next time you enter +BULLETIN. This is a design "feature" and cannot easily be changed.)`, }, "PRIVILEGES": { - Description: ` Shows the privileges necessary to use privileged commands. Also shows -any rights identifiers that would also give a user privileges. (The -latter are ACLs which are set on the BULLUSER.DAT file.) -`, + Description: `Shows the privileges necessary to use privileged commands. Also shows +any rights identifiers that would also give a user privileges. (The +latter are ACLs which are set on the BULLUSER.DAT file.)`, }, "USER": { - Description: ` Shows the last time that a user logged in, or if /FOLDER is specified, + Description: `Shows the last time that a user logged in, or if /FOLDER is specified, the latest message which a user has read in the folder. If NOLOGIN is set for a user, this information will be displayed. This is a privileged command. Non-privileged users will only be able to display @@ -1713,56 +1630,52 @@ NOTE: The last logged in time displayed is that which is stored when the BULLETIN/LOGIN command is executed, not that which VMS stores. Some sites make BULLETIN/LOGIN an optional command for users to store in their own LOGIN.COM, so this command can be used to show which users -have done this. -3 /ALL -Specifies that information for all users is to be displayed. This is a -privileged command. -3 /LOGIN - /[NO]LOGIN - -Specifies that only those users which do not have NOLOGIN set are to be -displayed. If negated, only those users with NOLOGIN set are displayed. -This is a privileged command. The qualifier /ALL need not be specified. -3 /FOLDER - /FOLDER=[foldername] - -Specifies to display the latest message that was read by the user(s) for -the specified foldername. A newsgroup can be specified, but the info -can only be shown if the user has subscribed to the newsgroup. If the -foldername is not specified, the selected folder will be used. -3 /SINCE - /SINCE=[date] - -Specifies to display only those users whose latest read message date is -the same date or later than the specified date. If no date is -specified, the date of the current message is used. Only valid for -folders or with /LOGIN. Use /START for newsgroups. -3 /START - /START=[number] - -Specifies to display only those users whose latest read message number -is equal to or greather than the specified number. If no number is -specified, the message number of the current message is used. Only -valid for newsgroups. Use /SINCE for folders and with /LOGIN. -`, +have done this.`, + MaxArgs: 1, + Flags: dclish.Flags{ + "/ALL": { + Description: ` Specifies that information for all users is to be displayed. This is a + privileged command.`, + }, + "/LOGIN": { + Description: `/[NO]LOGIN + + Specifies that only those users which do not have NOLOGIN set are to + be displayed. If negated, only those users with NOLOGIN set are + displayed. This is a privileged command. The qualifier /ALL need not + be specified.`, + }, + "/FOLDER": { + Description: `/FOLDER=[foldername] + + Specifies to display the latest message that was read by the user(s) + for the specified foldername. A newsgroup can be specified, but the + info can only be shown if the user has subscribed to the newsgroup. If + the foldername is not specified, the selected folder will be used.`, + }, + "/SINCE": { + Description: `/SINCE=[date] + + Specifies to display only those users whose latest read message date + is the same date or later than the specified date. If no date is + specified, the date of the current message is used. Only valid for + folders or with /LOGIN. Use /START for newsgroups.`, + }, + "/START": { + Description: `/START=[number] + + Specifies to display only those users whose latest read message number + is equal to or greather than the specified number. If no number is + specified, the message number of the current message is used. Only + valid for newsgroups. Use /SINCE for folders and with /LOGIN.`, + }, + }, }, "VERSION": { - Description: ` Shows the version of BULLETIN and the date that the executable was -linked. -`, + Description: ` Shows the version of BULLETIN and the date that the executable was + linked.`, + Action: ActionShowVersion, }, }, }, - "UNDELETE": { - Description: `Undeletes he specified message if the message was deleted using the -DELETE command. Deleted messages are not actually deleted but have -their expiration date set to 15 minutes in the future and are deleted -then. Undeleting the message will reset the expiration date back to its -original value. Deleted messages will be indicated as such by the -string (DELETED) when either reading or doing a directory listing. - - Format: - UNDELETE [message-number] -`, - }, } diff --git a/repl/repl.go b/repl/repl.go index 07afdf823180cb9de6a1f48f59ccc8b17a996ddb..2a11baa3644c2f982f5d1273b0023baa4f75e45a 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -31,12 +31,21 @@ func Loop() error { // TODO: Remove once commands are implemented. unimplemented := 0 - total := 0 + total := len(commands) for c := range commands { if commands[c].Action == nil { unimplemented++ } - total++ + if len(commands[c].Commands) > 0 { + total-- + unimplemented-- + for subc := range commands[c].Commands { + if commands[c].Commands[subc].Action == nil { + unimplemented++ + } + } + total += len(commands[c].Commands) + } } fmt.Printf("TODO: %d out of %d commands still to be implemented.\n", unimplemented, total) diff --git a/repl/set.go b/repl/set.go new file mode 100644 index 0000000000000000000000000000000000000000..4b296bc016601005c9229d7aca4d8d7edb34e34f --- /dev/null +++ b/repl/set.go @@ -0,0 +1,35 @@ +// Package repl implements the main event loop. +package repl + +import ( + "errors" + "fmt" + "strings" + + "git.lyda.ie/kevin/bulletin/accounts" + "git.lyda.ie/kevin/bulletin/dclish" +) + +// ActionSetFolder handles the `SET FOLDER` command. This selects a folder. +func ActionSetFolder(cmd *dclish.Command) error { + if len(cmd.Args) != 1 { + return errors.New("TODO: need to add code for /MARK") + } + // TODO: Move shared code here and in ActionSelect and ActionDirectory into a function. + if strings.Contains(cmd.Args[0], "%") { + return errors.New("Folder name cannot contain a %") + } + folder := accounts.User.Folders.FindFolder(cmd.Args[0]) + if folder == "" { + return errors.New("Unable to select the folder") + } + if accounts.User.Folders.IsFolderAccess(folder, accounts.User.Login) { + accounts.User.CurrentFolder = folder + fmt.Printf("Folder has been set to '%s'.\n", folder) + return nil + } + // TODO: Should be: + // WRITE(6,'('' You are not allowed to access folder.'')') + // WRITE(6,'('' See '',A,'' if you wish to access folder.'')') + return errors.New("Unable to select the folder") +} diff --git a/repl/show.go b/repl/show.go new file mode 100644 index 0000000000000000000000000000000000000000..1ffa7259d4cde9745a7e102c2aa8b00a0b920eee --- /dev/null +++ b/repl/show.go @@ -0,0 +1,18 @@ +// Package repl implements the main event loop. +package repl + +import ( + "fmt" + + "github.com/carlmjohnson/versioninfo" + + "git.lyda.ie/kevin/bulletin/dclish" +) + +// ActionShowVersion handles the `SHOW VERSION` command. This selects a folder. +func ActionShowVersion(_ *dclish.Command) error { + fmt.Printf("BULLETIN Version %s\n", versioninfo.Version) + fmt.Printf("Linked on %s\n", + versioninfo.LastCommit.Format("2006-05-04 15:02:01")) + return nil +}