|
@@ -12,7 +12,13 @@ import (
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
-const CRNL = "\r\n"
|
|
|
+const CRNL = "\r\n" // BBS Line Ending
|
|
|
+var Reset string = Color(0) // ANSI Color Reset
|
|
|
+var Unicode bool // Unicode support detected
|
|
|
+var CP437 bool // CP437 support detected
|
|
|
+var Full_CP437 bool // Full CP437 support detected (handles control codes properly)
|
|
|
+var Height int // Screen height detected
|
|
|
+var Width int // Screen width detected
|
|
|
|
|
|
/*
|
|
|
door32.sys:
|
|
@@ -30,8 +36,6 @@ g00r00 Line 7 : User's handle/alias
|
|
|
1 Line 11: Current node number
|
|
|
*/
|
|
|
|
|
|
-var Reset string = Color(0)
|
|
|
-
|
|
|
type DropfileConfig struct {
|
|
|
comm_type int
|
|
|
comm_handle int
|
|
@@ -99,37 +103,12 @@ func (d *Door) ReadDropfile(filename string) {
|
|
|
d.TimeOut = time.Now().Add(time.Duration(d.config.time_left) * time.Minute)
|
|
|
}
|
|
|
|
|
|
-func (d *Door) HasKey() bool {
|
|
|
- var fdsetRead = syscall.FdSet{}
|
|
|
- clearAll(&fdsetRead)
|
|
|
- set(&fdsetRead, d.READFD)
|
|
|
- timeout := syscall.Timeval{Sec: 0, Usec: 1}
|
|
|
- v, _ := syscall.Select(d.READFD+1, &fdsetRead, nil, nil, &timeout)
|
|
|
- if v == -1 {
|
|
|
- return false
|
|
|
- }
|
|
|
- if v == 0 {
|
|
|
- return false
|
|
|
- }
|
|
|
- return true
|
|
|
-}
|
|
|
-
|
|
|
-var Unicode bool // Unicode support detected
|
|
|
-var CP437 bool // CP437 support detected
|
|
|
-var Full_CP437 bool // Full CP437 support detected (handles control codes properly)
|
|
|
-var Height int // Screen height detected
|
|
|
-var Width int // Screen width detected
|
|
|
-
|
|
|
// Detect client terminal capabilities, Unicode, CP437, Full_CP437,
|
|
|
// screen Height and Width.
|
|
|
func (d *Door) detect() {
|
|
|
- // if d.config.comm_handle == 0 {
|
|
|
- // d.Write("\377\375\042\377\373\001") // fix telnet client
|
|
|
- // }
|
|
|
- d.Write("\x1b[0;30;40m\x1b[2J\x1b[H") // black on black, clrscr, go home
|
|
|
- d.Write("\x03\x04\x1b[6n") // hearts and diamonds does CP437 work?
|
|
|
-
|
|
|
- d.Write(CRNL + "\u2615\x1b[6n")
|
|
|
+ d.Write("\x1b[0;30;40m\x1b[2J\x1b[H") // black on black, clrscr, go home
|
|
|
+ d.Write("\x03\x04\x1b[6n") // hearts and diamonds does CP437 work?
|
|
|
+ d.Write(CRNL + "\u2615\x1b[6n") // hot beverage
|
|
|
d.Write("\x1b[999C\x1b[999B\x1b[6n" + Reset + "\x1b[2J\x1b[H") // goto end of screen + cursor pos
|
|
|
// time.Sleep(50 * time.Millisecond)
|
|
|
time.Sleep(250 * time.Millisecond)
|
|
@@ -137,7 +116,7 @@ func (d *Door) detect() {
|
|
|
// telnet term isn't in RAW mode, so keys are buffer until <CR>
|
|
|
var results string
|
|
|
|
|
|
- if true { // d.HasKey() {
|
|
|
+ if d.HasKey() {
|
|
|
buffer := make([]byte, 100)
|
|
|
r, err := syscall.Read(d.READFD, buffer)
|
|
|
results = string(buffer[:r])
|
|
@@ -174,7 +153,6 @@ func (d *Door) detect() {
|
|
|
pos = strings.Index(results, ";")
|
|
|
if pos != -1 {
|
|
|
height := results[:pos]
|
|
|
- // Height, err = strconv.Atoi(results)
|
|
|
Height, err = strconv.Atoi(height)
|
|
|
pos++
|
|
|
results = results[pos:]
|
|
@@ -227,415 +205,3 @@ func (d *Door) Write(output string) {
|
|
|
fmt.Printf("Write fail: %d != %d\n", len(buffer), n)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-/*
|
|
|
-func write(output string, config *DropfileConfig) {
|
|
|
- buffer := []byte(output)
|
|
|
- n, err := syscall.Write(config.comm_handle, buffer)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Write error/HANGUP?", n)
|
|
|
- }
|
|
|
-}
|
|
|
-*/
|
|
|
-
|
|
|
-// from: https://github.com/yubo/dea_ng
|
|
|
-// https://github.com/yubo/dea_ng/blob/master/go/src/directoryserver/streaming.go
|
|
|
-
|
|
|
-func set(fdSetPtr *syscall.FdSet, fd int) {
|
|
|
- (*fdSetPtr).Bits[fd/64] |= 1 << uint64(fd%64)
|
|
|
-}
|
|
|
-
|
|
|
-func isSet(fdSetPtr *syscall.FdSet, fd int) bool {
|
|
|
- return ((*fdSetPtr).Bits[fd/64] & (1 << uint64(fd%64))) != 0
|
|
|
-}
|
|
|
-
|
|
|
-func clearAll(fdSetPtr *syscall.FdSet) {
|
|
|
- for index, _ := range (*fdSetPtr).Bits {
|
|
|
- (*fdSetPtr).Bits[index] = 0
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (d *Door) SleepKey(sleep int64) int {
|
|
|
- // var fdsetRead, fdsetWrite, fdsete syscall.FdSet
|
|
|
- var fdsetRead syscall.FdSet
|
|
|
- // fdsetWrite := syscall.FdSet
|
|
|
- clearAll(&fdsetRead)
|
|
|
- // clearAll(&fdsetWrite)
|
|
|
- // clearAll(&fdsete)
|
|
|
- set(&fdsetRead, d.READFD)
|
|
|
- // timeout := syscall.Timeval{Sec: 0, Usec: 100}
|
|
|
- timeout := syscall.Timeval{Sec: sleep, Usec: 0}
|
|
|
- v, err := syscall.Select(d.READFD+1, &fdsetRead, nil, nil, &timeout)
|
|
|
- if v == -1 {
|
|
|
- fmt.Println("-1 : ", err)
|
|
|
- // hangup ?!
|
|
|
- return -2
|
|
|
- }
|
|
|
- if v == 0 {
|
|
|
- // timeout
|
|
|
- return -1
|
|
|
- }
|
|
|
- // var buffer []byte -- 0 byte buffer. doh!
|
|
|
- buffer := make([]byte, 1)
|
|
|
- r, err := syscall.Read(d.READFD, buffer)
|
|
|
- if r != 1 {
|
|
|
- fmt.Printf("Read said ready, but didn't read a character %d %v.", r, err)
|
|
|
- // hangup
|
|
|
- return -2
|
|
|
- }
|
|
|
- return int(buffer[0])
|
|
|
-}
|
|
|
-
|
|
|
-// Low level read key function.
|
|
|
-// This gets the raw keys from the client, it doesn't handle extended keys,
|
|
|
-// functions, arrows.
|
|
|
-// Return key, or -1 (Timeout/No key available), -2 hangup
|
|
|
-func (d *Door) getch() int {
|
|
|
- var fdsetRead syscall.FdSet
|
|
|
- clearAll(&fdsetRead)
|
|
|
- set(&fdsetRead, d.READFD)
|
|
|
-
|
|
|
- // 100 Usec seems like a good value, works with QModem in dosbox.
|
|
|
- timeout := syscall.Timeval{Sec: 0, Usec: 100}
|
|
|
- v, err := syscall.Select(d.READFD+1, &fdsetRead, nil, nil, &timeout)
|
|
|
- if v == -1 {
|
|
|
- // hangup
|
|
|
- return -2
|
|
|
- }
|
|
|
- if v == 0 {
|
|
|
- // timeout
|
|
|
- return -1
|
|
|
- }
|
|
|
-
|
|
|
- buffer := make([]byte, 1)
|
|
|
- r, err := syscall.Read(d.READFD, buffer)
|
|
|
- if r != 1 {
|
|
|
- fmt.Printf("Read said ready, but didn't read a character %d %v.", r, err)
|
|
|
- // hangup
|
|
|
- return -2
|
|
|
- }
|
|
|
- return int(buffer[0])
|
|
|
-}
|
|
|
-
|
|
|
-func (d *Door) getkey_or_pushback() int {
|
|
|
- if d.pushback.Len() != 0 {
|
|
|
- e := d.pushback.Front()
|
|
|
- d.pushback.Remove(e)
|
|
|
- return e.Value.(int)
|
|
|
- }
|
|
|
- return d.getch()
|
|
|
-}
|
|
|
-
|
|
|
-const (
|
|
|
- XKEY_UP_ARROW = 0x1001
|
|
|
- XKEY_DOWN_ARROW = 0x1002
|
|
|
- XKEY_RIGHT_ARROW = 0x1003
|
|
|
- XKEY_LEFT_ARROW = 0x1004
|
|
|
- XKEY_HOME = 0x1010
|
|
|
- XKEY_END = 0x1011
|
|
|
- XKEY_PGUP = 0x1012
|
|
|
- XKEY_PGDN = 0x1023
|
|
|
- XKEY_INSERT = 0x1024
|
|
|
- XKEY_DELETE = 0x7f
|
|
|
- XKEY_F1 = 0x1021
|
|
|
- XKEY_F2 = 0x1022
|
|
|
- XKEY_F3 = 0x1023
|
|
|
- XKEY_F4 = 0x1024
|
|
|
- XKEY_F5 = 0x1025
|
|
|
- XKEY_F6 = 0x1026
|
|
|
- XKEY_F7 = 0x1027
|
|
|
- XKEY_F8 = 0x1028
|
|
|
- XKEY_F9 = 0x1029
|
|
|
- XKEY_F10 = 0x102a
|
|
|
- XKEY_F11 = 0x102b
|
|
|
- XKEY_F12 = 0x102c
|
|
|
- XKEY_UNKNOWN = 0x1111
|
|
|
-)
|
|
|
-
|
|
|
-// Return key received, or XKEY_* values.
|
|
|
-// -1 timeout/no key
|
|
|
-// -2 hangup
|
|
|
-// -3 out of time
|
|
|
-func (d *Door) Getkey() int {
|
|
|
- var c, c2 int
|
|
|
-
|
|
|
- if d.TimeLeft() < 0 {
|
|
|
- return -3
|
|
|
- }
|
|
|
-
|
|
|
- c = d.getkey_or_pushback()
|
|
|
-
|
|
|
- if c < 0 {
|
|
|
- return c
|
|
|
- }
|
|
|
-
|
|
|
- // We get 0x0d 0x00, or 0x0d 0x0a from syncterm.
|
|
|
- if c == 0x0d {
|
|
|
- c2 = d.getkey_or_pushback()
|
|
|
- if c2 > 0 {
|
|
|
- // wasn't an error
|
|
|
- if c2 != 0x00 && c2 != 0x0a {
|
|
|
- // wasn't 0x00 or 0x0a
|
|
|
- d.pushback.PushFront(c2)
|
|
|
- }
|
|
|
- }
|
|
|
- return c
|
|
|
- }
|
|
|
-
|
|
|
- if c == 0 {
|
|
|
- // possibly doorway mode
|
|
|
- tries := 0
|
|
|
- c2 = d.getkey_or_pushback()
|
|
|
- for c2 < 0 {
|
|
|
- if tries > 7 {
|
|
|
- return c
|
|
|
- }
|
|
|
- c2 = d.getkey_or_pushback()
|
|
|
- tries++
|
|
|
- }
|
|
|
-
|
|
|
- switch c2 {
|
|
|
- case 0x50:
|
|
|
- return XKEY_DOWN_ARROW
|
|
|
- case 0x48:
|
|
|
- return XKEY_UP_ARROW
|
|
|
- case 0x4b:
|
|
|
- return XKEY_LEFT_ARROW
|
|
|
- case 0x4d:
|
|
|
- return XKEY_RIGHT_ARROW
|
|
|
- case 0x47:
|
|
|
- return XKEY_HOME
|
|
|
- case 0x4f:
|
|
|
- return XKEY_END
|
|
|
- case 0x49:
|
|
|
- return XKEY_PGUP
|
|
|
- case 0x51:
|
|
|
- return XKEY_PGDN
|
|
|
- case 0x3b:
|
|
|
- return XKEY_F1
|
|
|
- case 0x3c:
|
|
|
- return XKEY_F2
|
|
|
- case 0x3d:
|
|
|
- return XKEY_F3
|
|
|
- case 0x3e:
|
|
|
- return XKEY_F4
|
|
|
- case 0x3f:
|
|
|
- return XKEY_F5
|
|
|
- case 0x40:
|
|
|
- return XKEY_F6
|
|
|
- case 0x41:
|
|
|
- return XKEY_F7
|
|
|
- case 0x42:
|
|
|
- return XKEY_F8
|
|
|
- case 0x43:
|
|
|
- return XKEY_F9
|
|
|
- case 0x44:
|
|
|
- return XKEY_F10
|
|
|
- /*
|
|
|
- case 0x45:
|
|
|
- return XKEY_F11
|
|
|
- case 0x46:
|
|
|
- return XKEY_F12
|
|
|
- */
|
|
|
- case 0x52:
|
|
|
- return XKEY_INSERT
|
|
|
- case 0x53:
|
|
|
- return XKEY_DELETE
|
|
|
- default:
|
|
|
- fmt.Printf("ERROR Doorway mode: 0x00 %x\n", c2)
|
|
|
- return XKEY_UNKNOWN
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if c == 0x1b {
|
|
|
- // Escape key?
|
|
|
- c2 = d.getkey_or_pushback()
|
|
|
- if c2 < 0 {
|
|
|
- // Just escape key
|
|
|
- return c
|
|
|
- }
|
|
|
- var extended string = string(c2)
|
|
|
-
|
|
|
- c2 = d.getkey_or_pushback()
|
|
|
- for c2 > 0 {
|
|
|
- if c2 == 0x1b {
|
|
|
- d.pushback.PushBack(c2)
|
|
|
- break
|
|
|
- }
|
|
|
- extended += string(c2)
|
|
|
- c2 = d.getkey_or_pushback()
|
|
|
- }
|
|
|
-
|
|
|
- switch extended {
|
|
|
- case "[A":
|
|
|
- return XKEY_UP_ARROW
|
|
|
- case "[B":
|
|
|
- return XKEY_DOWN_ARROW
|
|
|
- case "[C":
|
|
|
- return XKEY_RIGHT_ARROW
|
|
|
- case "[D":
|
|
|
- return XKEY_LEFT_ARROW
|
|
|
- case "[H":
|
|
|
- return XKEY_HOME
|
|
|
- case "[F":
|
|
|
- return XKEY_END // terminal
|
|
|
- case "[K":
|
|
|
- return XKEY_END
|
|
|
- case "[V":
|
|
|
- return XKEY_PGUP
|
|
|
- case "[U":
|
|
|
- return XKEY_PGDN
|
|
|
- case "[@":
|
|
|
- return XKEY_INSERT
|
|
|
- case "[1":
|
|
|
- // Syncterm is lost, could be F1..F5?
|
|
|
- fmt.Printf("ERROR (Syncterm) Extended %#v\n", extended)
|
|
|
- return XKEY_UNKNOWN
|
|
|
- case "[2~":
|
|
|
- return XKEY_INSERT // terminal
|
|
|
- case "[3~":
|
|
|
- return XKEY_DELETE // terminal
|
|
|
- case "[5~":
|
|
|
- return XKEY_PGUP // terminal
|
|
|
- case "[6~":
|
|
|
- return XKEY_PGDN // terminal
|
|
|
- case "[15~":
|
|
|
- return XKEY_F5 // terminal
|
|
|
- case "[17~":
|
|
|
- return XKEY_F6 // terminal
|
|
|
- case "[18~":
|
|
|
- return XKEY_F7 // terminal
|
|
|
- case "[19~":
|
|
|
- return XKEY_F8 // terminal
|
|
|
- case "[20~":
|
|
|
- return XKEY_F9 // terminal
|
|
|
- case "[21~":
|
|
|
- return XKEY_F10 // terminal
|
|
|
- case "[23~":
|
|
|
- return XKEY_F11
|
|
|
- case "[24~":
|
|
|
- return XKEY_F12 // terminal
|
|
|
- case "OP":
|
|
|
- return XKEY_F1
|
|
|
- case "OQ":
|
|
|
- return XKEY_F2
|
|
|
- case "OR":
|
|
|
- return XKEY_F3
|
|
|
- case "OS":
|
|
|
- return XKEY_F4
|
|
|
- case "Ot":
|
|
|
- return XKEY_F5 // syncterm
|
|
|
- default:
|
|
|
- fmt.Printf("ERROR Extended %#v\n", extended)
|
|
|
- return XKEY_UNKNOWN
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return c
|
|
|
-}
|
|
|
-
|
|
|
-func (d *Door) WaitKey(secs int64) int {
|
|
|
- // var fdsetRead, fdsetWrite, fdsete syscall.FdSet
|
|
|
- var fdsetRead syscall.FdSet
|
|
|
- // fdsetWrite := syscall.FdSet
|
|
|
- clearAll(&fdsetRead)
|
|
|
- // clearAll(&fdsetWrite)
|
|
|
- // clearAll(&fdsete)
|
|
|
- set(&fdsetRead, d.READFD)
|
|
|
- // timeout := syscall.Timeval{Sec: 0, Usec: 100}
|
|
|
- timeout := syscall.Timeval{Sec: secs, Usec: 0}
|
|
|
- v, err := syscall.Select(d.READFD+1, &fdsetRead, nil, nil, &timeout)
|
|
|
- if v == -1 {
|
|
|
- fmt.Println("-1 : ", err)
|
|
|
- // hangup ?!
|
|
|
- return -2
|
|
|
- }
|
|
|
- if v == 0 {
|
|
|
- // timeout
|
|
|
- return -1
|
|
|
- }
|
|
|
-
|
|
|
- return d.Getkey()
|
|
|
-
|
|
|
- // var buffer []byte -- 0 byte buffer. doh!
|
|
|
- buffer := make([]byte, 1)
|
|
|
- r, err := syscall.Read(d.READFD, buffer)
|
|
|
- if r != 1 {
|
|
|
- fmt.Printf("Read said ready, but didn't read a character %d %v.", r, err)
|
|
|
- // hangup
|
|
|
- return -2
|
|
|
- }
|
|
|
- return int(buffer[0])
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
-func sleep_key(config *DropfileConfig, secs int) int {
|
|
|
- // var fdsetRead, fdsetWrite, fdsete syscall.FdSet
|
|
|
- var fdsetRead = syscall.FdSet{}
|
|
|
- // fdsetWrite := syscall.FdSet
|
|
|
- clearAll(&fdsetRead)
|
|
|
- // clearAll(&fdsetWrite)
|
|
|
- // clearAll(&fdsete)
|
|
|
- set(&fdsetRead, config.comm_handle)
|
|
|
- timeout := syscall.Timeval{Sec: int64(secs), Usec: 0}
|
|
|
- // v, err := syscall.Select(config.comm_handle+1, &fdsetRead, &fdsetWrite, &fdsete, &timeout)
|
|
|
- v, err := syscall.Select(config.comm_handle+1, &fdsetRead, nil, nil, &timeout)
|
|
|
- fmt.Println("v:", v, "err:", err)
|
|
|
- if v == -1 {
|
|
|
- fmt.Println("-1 : ", err)
|
|
|
- // hangup ?!
|
|
|
- return -2
|
|
|
- }
|
|
|
- if v == 0 {
|
|
|
- // timeout
|
|
|
- return -1
|
|
|
- }
|
|
|
- // var buffer []byte
|
|
|
- buffer := make([]byte, 1)
|
|
|
- // var buffer [1]byte
|
|
|
-
|
|
|
- r, err := syscall.Read(config.comm_handle, buffer)
|
|
|
- if r != 1 {
|
|
|
- fmt.Printf("Read said ready, but didn't read a character %d %v ?\n", r, err)
|
|
|
- // hangup
|
|
|
- return -2
|
|
|
- }
|
|
|
- return int(buffer[0])
|
|
|
-}
|
|
|
-*/
|
|
|
-
|
|
|
-/*
|
|
|
-func main() {
|
|
|
- fmt.Println("doorgo")
|
|
|
- var dropfile string
|
|
|
-
|
|
|
- flag.StringVar(&dropfile, "dropfile", "", "Dropfile to use")
|
|
|
- flag.Parse()
|
|
|
-
|
|
|
- if len(dropfile) == 0 {
|
|
|
- flag.PrintDefaults()
|
|
|
- os.Exit(2)
|
|
|
- }
|
|
|
- fmt.Printf("Loading: %s\n", dropfile)
|
|
|
-
|
|
|
- var config DropfileConfig
|
|
|
- read_dropfile(dropfile, &config)
|
|
|
-
|
|
|
- fmt.Printf("BBS %s, User %s / Handle %s\n", config.BBSID, config.real_name, config.handle)
|
|
|
- message := "Welcome BBS User!\n\r"
|
|
|
- // buffer := []byte(message)
|
|
|
- // n, err := syscall.Write(config.comm_handle, buffer)
|
|
|
- write(message, &config)
|
|
|
-
|
|
|
- write("Press a key...", &config)
|
|
|
- key := sleep_key(&config, 20)
|
|
|
- write("\n\r", &config)
|
|
|
- message = fmt.Sprintf("Key %d / %x\n\r", key, key)
|
|
|
- write(message, &config)
|
|
|
-
|
|
|
- write("\n\rReturning to BBS.\n\r", &config)
|
|
|
- fmt.Println("Done.")
|
|
|
- // fmt.Println(n, err)
|
|
|
-}
|
|
|
-*/
|