summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fix.go44
-rw-r--r--gui.go27
-rw-r--r--hostname.go11
-rw-r--r--hostnameStatus.go2
-rw-r--r--linuxstatus/args.go61
-rw-r--r--linuxstatus/common.go34
-rw-r--r--linuxstatus/draw.go34
-rw-r--r--linuxstatus/hostname.go86
-rw-r--r--linuxstatus/linuxloop.go44
-rw-r--r--linuxstatus/net.go292
-rw-r--r--linuxstatus/new.go17
-rw-r--r--linuxstatus/structs.go57
-rw-r--r--linuxstatus/timer.go31
-rw-r--r--linuxstatus/unix.go97
-rw-r--r--linuxstatus/update.go31
-rw-r--r--main.go4
-rw-r--r--structs.go4
17 files changed, 843 insertions, 33 deletions
diff --git a/fix.go b/fix.go
new file mode 100644
index 0000000..6bc0896
--- /dev/null
+++ b/fix.go
@@ -0,0 +1,44 @@
+// This creates a simple hello world window
+package main
+
+import (
+ "go.wit.com/log"
+)
+
+func fix() bool {
+ log.Warn("")
+ if ! me.status.Ready() {
+ log.Warn("The IPv6 Control Panel is not Ready() yet")
+ return false
+ }
+ if me.status.ValidHostname() {
+ log.Warn("Your hostname is VALID:", me.status.GetHostname())
+ } else {
+ log.Warn("You must first fix your hostname:", me.status.GetHostname())
+ return false
+ }
+ if me.digStatus.IPv4() {
+ log.Warn("IPv4 addresses are resolving")
+ } else {
+ log.Warn("You must first figure out why you can't look up IPv4 addresses")
+ log.Warn("Are you on the internet at all?")
+ return false
+ }
+ if me.digStatus.IPv6() {
+ log.Warn("IPv6 addresses are resolving")
+ } else {
+ log.Warn("You must first figure out why you can't look up IPv6 addresses")
+ return false
+ }
+ if ! me.status.IPv4() {
+ log.Warn("You do not have real IPv4 addresses. Nothing to fix here")
+ }
+ if ! me.status.IPv6() {
+ log.Warn("IPv6 DNS is broken. Check what is broken here")
+ log.Warn("What are my IPv6 addresses?")
+ log.Warn("What are the AAAA resource records in DNS?")
+ return false
+ }
+ log.Warn("YOU SHOULD BE IN IPv6 BLISS")
+ return true
+}
diff --git a/gui.go b/gui.go
index 40f75b6..4b4b3c8 100644
--- a/gui.go
+++ b/gui.go
@@ -41,7 +41,8 @@ func detailsTab(title string) {
grid.SetNext(1,1)
grid.NewLabel("domainname =")
- me.domainname = grid.NewLabel("domainname")
+ grid.NewLabel("DEPRECATED")
+// me.domainname = grid.NewLabel("domainname")
grid.NewLabel("hostname -s =")
me.hostshort = grid.NewLabel("hostname -s")
@@ -209,24 +210,7 @@ func mainWindow(title string) {
// This is where you figure out what to do next to fix the problems
gr.NewButton("fix", func () {
- if ! me.status.Ready() {
- log.Warn("The IPv6 Control Panel is not Ready() yet")
- return
- }
- if me.status.ValidHostname() {
- log.Warn("Your hostname is VALID:", me.status.GetHostname())
- } else {
- log.Warn("You must first fix your hostname:", me.status.GetHostname())
- return
- }
- if ! me.status.IPv4() {
- log.Warn("You do not have real IPv4 addresses. Nothing to fix here")
- }
- if ! me.status.IPv6() {
- log.Warn("IPv6 DNS is broken. Check what is broken here")
- return
- }
- log.Warn("FIGURE OUT WHAT TO DO HERE")
+ fix()
})
grid.Margin()
@@ -243,6 +227,9 @@ func mainWindow(title string) {
gr.NewButton("OS details", func () {
me.details.Toggle()
})
+ gr.NewButton("Linux details", func () {
+ me.statusOS.Update()
+ })
gr.NewButton("resolver status", func () {
if ! me.digStatus.Ready() {return}
me.digStatus.window.Toggle()
@@ -368,7 +355,7 @@ func updateDNS() {
// lookup the NS records for your domain
// if your host is test.wit.com, find the NS resource records for wit.com
- lookupNS(me.domainname.S)
+ lookupNS(me.statusOS.GetDomainName())
log.Println("updateDNS() END")
}
diff --git a/hostname.go b/hostname.go
index 062f033..9ca821f 100644
--- a/hostname.go
+++ b/hostname.go
@@ -25,18 +25,7 @@ func getHostname() {
me.status.SetHostname(s)
dn := run("domainname")
- if (me.domainname.S != dn) {
- log.Log(CHANGE, "domainname has changed from", me.domainname.S, "to", dn)
- me.domainname.SetText(dn)
- me.changed = true
- }
-
hshort := run("hostname -s")
- if (me.hostshort.S != hshort) {
- log.Log(CHANGE, "hostname -s has changed from", me.hostshort.S, "to", hshort)
- me.hostshort.SetText(hshort)
- me.changed = true
- }
var test string
test = hshort + "." + dn
diff --git a/hostnameStatus.go b/hostnameStatus.go
index b58fb04..bc13f6a 100644
--- a/hostnameStatus.go
+++ b/hostnameStatus.go
@@ -297,7 +297,7 @@ func (hs *hostnameStatus) updateStatus() {
log.Log(STATUS, "updateStatus() START")
hs.hostShort.Set(me.hostshort.S)
- hs.domainname.Set(me.domainname.S)
+ hs.domainname.Set(me.statusOS.GetDomainName())
if hs.ValidHostname() {
vals = lookupDoH(hs.GetHostname(), "AAAA")
diff --git a/linuxstatus/args.go b/linuxstatus/args.go
new file mode 100644
index 0000000..9457410
--- /dev/null
+++ b/linuxstatus/args.go
@@ -0,0 +1,61 @@
+package linuxstatus
+
+/*
+ this enables command line options from other packages like 'gui' and 'log'
+*/
+
+import (
+ "go.wit.com/log"
+)
+
+var NOW log.LogFlag
+var NET log.LogFlag
+var DNS log.LogFlag
+var PROC log.LogFlag
+var SPEW log.LogFlag
+var CHANGE log.LogFlag
+var STATUS log.LogFlag
+
+func init() {
+ NOW.B = false
+ NOW.Name = "NOW"
+ NOW.Subsystem = "cpdns"
+ NOW.Desc = "temp debugging stuff"
+ NOW.Register()
+
+ NET.B = false
+ NET.Name = "NET"
+ NET.Subsystem = "cpdns"
+ NET.Desc = "Network logging"
+ NET.Register()
+
+ DNS.B = false
+ DNS.Name = "DNS"
+ DNS.Subsystem = "cpdns"
+ DNS.Desc = "dnsStatus.update()"
+ DNS.Register()
+
+ PROC.B = false
+ PROC.Name = "PROC"
+ PROC.Subsystem = "cpdns"
+ PROC.Desc = "/proc logging"
+ PROC.Register()
+
+ SPEW.B = false
+ SPEW.Name = "SPEW"
+ SPEW.Subsystem = "cpdns"
+ SPEW.Desc = "spew logging"
+ SPEW.Register()
+
+ CHANGE.B = false
+ CHANGE.Name = "CHANGE"
+ CHANGE.Subsystem = "cpdns"
+ CHANGE.Desc = "show droplet state changes"
+ CHANGE.Register()
+
+ STATUS.B = false
+ STATUS.Name = "STATUS"
+ STATUS.Subsystem = "cpdns"
+ STATUS.Desc = "updateStatus()"
+ STATUS.Register()
+}
diff --git a/linuxstatus/common.go b/linuxstatus/common.go
new file mode 100644
index 0000000..c4aea10
--- /dev/null
+++ b/linuxstatus/common.go
@@ -0,0 +1,34 @@
+// This creates a simple hello world window
+package linuxstatus
+
+import (
+ "go.wit.com/log"
+)
+
+func (hs *LinuxStatus) Show() {
+ log.Log(CHANGE, "linuxStatus.Show() window")
+ hs.window.Show()
+ hs.hidden = false
+}
+
+func (hs *LinuxStatus) Hide() {
+ log.Log(CHANGE, "linuxStatus.Hide() window")
+ hs.window.Hide()
+ hs.hidden = true
+}
+
+func (hs *LinuxStatus) Toggle() {
+ log.Log(CHANGE, "linuxStatus.Toggle() window")
+ if hs.hidden {
+ hs.window.Show()
+ } else {
+ hs.window.Hide()
+ }
+}
+
+func (hs *LinuxStatus) Ready() bool {
+ if me == nil {return false}
+ if hs == nil {return false}
+ if hs.window == nil {return false}
+ return me.ready
+}
diff --git a/linuxstatus/draw.go b/linuxstatus/draw.go
new file mode 100644
index 0000000..b7fbbea
--- /dev/null
+++ b/linuxstatus/draw.go
@@ -0,0 +1,34 @@
+// This creates a simple hello world window
+package linuxstatus
+
+import (
+ "go.wit.com/gui/gadgets"
+)
+
+// creates the actual widgets.
+// it's assumed you are always passing in a box
+func draw(ls *LinuxStatus) {
+ if ! ls.Ready() {return}
+ ls.group = ls.window.Box().NewGroup("Real Stuff")
+
+ ls.grid = ls.group.NewGrid("gridnuts", 2, 2)
+
+ ls.grid.SetNext(1,1)
+
+ ls.hostshort = gadgets.NewOneLiner(ls.grid, "hostname -s")
+ ls.domainname = gadgets.NewOneLiner(ls.grid, "domain name")
+ ls.NSrr = gadgets.NewOneLiner(ls.grid, "NS records =")
+ ls.uid = gadgets.NewOneLiner(ls.grid, "UID =")
+ ls.IPv4 = gadgets.NewOneLiner(ls.grid, "Current IPv4 =")
+ ls.IPv6 = gadgets.NewOneLiner(ls.grid, "Current IPv6 =")
+ ls.workingIPv6 = gadgets.NewOneLiner(ls.grid, "Real IPv6 =")
+ // ls.nics = gadgets.NewOneLiner(ls.grid, "network intefaces =")
+
+ ls.grid.NewLabel("interfaces =")
+ ls.Interfaces = ls.grid.NewCombobox("Interfaces")
+
+ ls.speedActual = gadgets.NewOneLiner(ls.grid, "refresh speed =")
+
+ ls.grid.Margin()
+ ls.grid.Pad()
+}
diff --git a/linuxstatus/hostname.go b/linuxstatus/hostname.go
new file mode 100644
index 0000000..76854f5
--- /dev/null
+++ b/linuxstatus/hostname.go
@@ -0,0 +1,86 @@
+// figures out if your hostname is valid
+// then checks if your DNS is setup correctly
+package linuxstatus
+
+import (
+ "go.wit.com/log"
+ "go.wit.com/shell"
+
+ // will try to get this hosts FQDN
+ "github.com/Showmax/go-fqdn"
+)
+
+func (ls *LinuxStatus) GetDomainName() string {
+ if ! me.Ready() {return ""}
+ return me.domainname.Get()
+}
+
+func (ls *LinuxStatus) setDomainName(dn string) {
+ if ! me.Ready() {return}
+ me.domainname.Set(dn)
+}
+
+func getHostname() {
+ var err error
+ var s string = "gui.Label == nil"
+ s, err = fqdn.FqdnHostname()
+ if (err != nil) {
+ log.Error(err, "FQDN hostname error")
+ return
+ }
+ log.Warn("full hostname should be:", s)
+
+ dn := run("domainname")
+ if (me.domainname.Get() != dn) {
+ log.Log(CHANGE, "domainname has changed from", me.GetDomainName(), "to", dn)
+ me.setDomainName(dn)
+ me.changed = true
+ }
+
+ hshort := run("hostname -s")
+ if (me.hostshort.Get() != hshort) {
+ log.Log(CHANGE, "hostname -s has changed from", me.hostshort.Get(), "to", hshort)
+ me.hostshort.Set(hshort)
+ me.changed = true
+ }
+
+ /*
+ var test string
+ test = hshort + "." + dn
+ if (me.status.GetHostname() != test) {
+ log.Log(CHANGE, "me.hostname", me.status.GetHostname(), "does not equal", test)
+ if (me.hostnameStatus.S != "BROKEN") {
+ log.Log(CHANGE, "me.hostname", me.status.GetHostname(), "does not equal", test)
+ me.changed = true
+ me.hostnameStatus.SetText("BROKEN")
+ }
+ } else {
+ if (me.hostnameStatus.S != "VALID") {
+ log.Log(CHANGE, "me.hostname", me.status.GetHostname(), "is valid")
+ me.hostnameStatus.SetText("VALID")
+ me.changed = true
+ }
+ }
+ */
+}
+
+// returns true if the hostname is good
+// check that all the OS settings are correct here
+// On Linux, /etc/hosts, /etc/hostname
+// and domainname and hostname
+func goodHostname() bool {
+ hostname := shell.Chomp(shell.Cat("/etc/hostname"))
+ log.Log(NOW, "hostname =", hostname)
+
+ hs := run("hostname -s")
+ dn := run("domainname")
+ log.Log(NOW, "hostname short =", hs, "domainname =", dn)
+
+ tmp := hs + "." + dn
+ if (hostname == tmp) {
+ log.Log(NOW, "hostname seems to be good", hostname)
+ return true
+ }
+
+ return false
+}
diff --git a/linuxstatus/linuxloop.go b/linuxstatus/linuxloop.go
new file mode 100644
index 0000000..44946c6
--- /dev/null
+++ b/linuxstatus/linuxloop.go
@@ -0,0 +1,44 @@
+// GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
+// Copyright (c) 2023 WIT.COM, Inc.
+// This is a control panel for DNS
+
+package linuxstatus
+
+import (
+ "strconv"
+
+ "go.wit.com/log"
+)
+
+func linuxLoop() {
+ me.changed = false
+ duration := timeFunction(getHostname)
+ log.Info("getHostname() execution Time: ", duration, "me.changed =", me.changed)
+
+ duration = timeFunction(scanInterfaces)
+ log.Log(NET, "scanInterfaces() execution Time: ", duration)
+ for i, t := range me.ifmap {
+ log.Log(NET, strconv.Itoa(i) + " iface = " + t.iface.Name)
+ }
+
+ var aaaa []string
+ aaaa = dhcpAAAA()
+ var all string
+ for _, s := range aaaa {
+ log.Log(NET, "my actual AAAA = ",s)
+ all += s + "\n"
+ }
+ // me.IPv6.SetText(all)
+
+ /*
+ processName := getProcessNameByPort(53)
+ fmt.Println("Process with port 53:", processName)
+
+ commPath := filepath.Join("/proc", proc.Name(), "comm")
+ comm, err := ioutil.ReadFile(commPath)
+ if err != nil {
+ return "", err // Error reading the process name
+ }
+ return strings.TrimSpace(string(comm)), nil
+ */
+}
diff --git a/linuxstatus/net.go b/linuxstatus/net.go
new file mode 100644
index 0000000..27e1a7b
--- /dev/null
+++ b/linuxstatus/net.go
@@ -0,0 +1,292 @@
+// This creates a simple hello world window
+package linuxstatus
+
+import (
+ // "log"
+ "net"
+ "strings"
+
+ "go.wit.com/log"
+)
+
+// this doesn't work
+/*
+func watchNetworkInterfaces() {
+ // Get list of network interfaces
+ interfaces, _ := net.Interfaces()
+
+ // Set up a notification channel
+ notification := make(chan net.Interface)
+
+ log.Log(NET, "watchNet()")
+ // Start goroutine to watch for changes
+ go func() {
+ log.Log(NET, "watchNet() func")
+ for {
+ log.Log(NET, "forever loop start")
+ // Check for changes in each interface
+ for _, i := range interfaces {
+ log.Log(NET, "something on i =", i)
+ if status := i.Flags & net.FlagUp; status != 0 {
+ notification <- i
+ log.Log(NET, "something on i =", i)
+ }
+ }
+ log.Log(NET, "forever loop end")
+ }
+ }()
+}
+*/
+
+func IsIPv6(address string) bool {
+ return strings.Count(address, ":") >= 2
+}
+
+func (t *IPtype) IsReal() bool {
+ if (t.ip.IsPrivate() || t.ip.IsLoopback() || t.ip.IsLinkLocalUnicast()) {
+ log.Log(NET, "\t\tIP is Real = false")
+ return false
+ } else {
+ log.Log(NET, "\t\tIP is Real = true")
+ return true
+ }
+}
+
+func IsReal(ip *net.IP) bool {
+ if (ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkLocalUnicast()) {
+ log.Log(NET, "\t\tIP is Real = false")
+ return false
+ } else {
+ log.Log(NET, "\t\tIP is Real = true")
+ return true
+ }
+}
+
+func renameInterface(i *net.Interface) {
+ /*
+ /sbin/ip link set eth1 down
+ /sbin/ip link set eth1 name eth123
+ /sbin/ip link set eth123 up
+ */
+}
+
+// Will figure out if an interface was just added
+func checkInterface(i net.Interface) {
+ val, ok := me.ifmap[i.Index]
+ if ! ok {
+ log.Info(i.Name, "is a new network interface. The linux kernel index =", i.Index)
+ me.ifmap[i.Index] = new(IFtype)
+ me.ifmap[i.Index].gone = false
+ me.ifmap[i.Index].iface = &i
+ me.changed = true
+ if (me.Interfaces != nil) {
+ me.Interfaces.AddText(i.Name)
+ me.Interfaces.SetText(i.Name)
+ }
+ return
+ }
+ me.ifmap[i.Index].gone = false
+ log.Log(NET, "me.ifmap[i] does exist. Need to compare everything.", i.Index, i.Name, val.iface.Index, val.iface.Name)
+ if (val.iface.Name != i.Name) {
+ log.Info(val.iface.Name, "has changed to it's name to", i.Name)
+ me.ifmap[i.Index].iface = &i
+ me.changed = true
+ if (me.Interfaces != nil) {
+ me.Interfaces.AddText(i.Name)
+ me.Interfaces.SetText(i.Name)
+ }
+ return
+ }
+}
+
+/*
+ These are the real IP address you have been
+ given from DHCP
+*/
+func dhcpAAAA() []string {
+ var aaaa []string
+
+ for s, t := range me.ipmap {
+ if (t.IsReal()) {
+ if (t.ipv6) {
+ aaaa = append(aaaa, s)
+ }
+ }
+ }
+ return aaaa
+}
+
+func realA() []string {
+ var a []string
+
+ for s, t := range me.ipmap {
+ if (t.IsReal()) {
+ if (t.ipv4) {
+ a = append(a, s)
+ }
+ }
+ }
+ return a
+}
+
+func checkDNS() (map[string]*IPtype, map[string]*IPtype) {
+ var ipv4s map[string]*IPtype
+ var ipv6s map[string]*IPtype
+
+ ipv4s = make(map[string]*IPtype)
+ ipv6s = make(map[string]*IPtype)
+
+ for s, t := range me.ipmap {
+ i := t.iface
+ ipt := "IPv4"
+ if (t.ipv6) {
+ ipt = "IPv6"
+ }
+ if (t.IsReal()) {
+ log.Info("\tIP is Real ", ipt, i.Index, i.Name, s)
+ if (t.ipv6) {
+ ipv6s[s] = t
+ } else {
+ ipv4s[s] = t
+ }
+ } else {
+ log.Info("\tIP is not Real", ipt, i.Index, i.Name, s)
+ }
+ }
+ return ipv6s, ipv4s
+}
+
+// Will figure out if an IP address is new
+func checkIP(ip *net.IPNet, i net.Interface) bool {
+ log.Log(NET, "\t\taddr.(type) = *net.IPNet")
+ log.Log(NET, "\t\taddr.(type) =", ip)
+ var realip string
+ realip = ip.IP.String()
+
+ val, ok := me.ipmap[realip]
+ if ok {
+ log.Log(NET, val.ipnet.IP.String(), "is already a defined IP address")
+ me.ipmap[realip].gone = false
+ return false
+ }
+
+ me.ipmap[realip] = new(IPtype)
+ me.ipmap[realip].gone = false
+ me.ipmap[realip].ipv4 = true
+ me.ipmap[realip].ipnet = ip
+ me.ipmap[realip].ip = ip.IP
+ me.ipmap[realip].iface = &i
+ t := "IPv4"
+ if (IsIPv6(ip.String())) {
+ me.ipmap[realip].ipv6 = true
+ me.ipmap[realip].ipv4 = false
+ t = "IPv6"
+ if (me.IPv6 != nil) {
+ me.IPv6.Set(realip)
+ }
+ } else {
+ me.ipmap[realip].ipv6 = false
+ me.ipmap[realip].ipv4 = true
+ if (me.IPv4 != nil) {
+ me.IPv4.Set(realip)
+ }
+ }
+ if (IsReal(&ip.IP)) {
+ log.Info("\tIP is Real ", t, i.Index, i.Name, realip)
+ } else {
+ log.Info("\tIP is not Real", t, i.Index, i.Name, realip)
+ }
+ log.Log(NET, "\t\tIP is IsPrivate() =", ip.IP.IsPrivate())
+ log.Log(NET, "\t\tIP is IsLoopback() =", ip.IP.IsLoopback())
+ log.Log(NET, "\t\tIP is IsLinkLocalUnicast() =", ip.IP.IsLinkLocalUnicast())
+ // log.Info("HERE HERE", "realip =", realip, "me.ip[realip]=", me.ipmap[realip])
+ return true
+}
+
+func scanInterfaces() {
+ log.Log(NET, "scanInterfaces() START")
+ ifaces, _ := net.Interfaces()
+ // me.ifnew = ifaces
+ log.Log(NET, SPEW, ifaces)
+ for _, i := range ifaces {
+ addrs, _ := i.Addrs()
+ // log.Info("range ifaces = ", i)
+ checkInterface(i)
+ log.Log(NET, "*net.Interface.Name = ", i.Name, i.Index)
+ log.Log(NET, SPEW, i)
+ log.Log(NET, SPEW, addrs)
+ for _, addr := range addrs {
+ log.Log(NET, "\taddr =", addr)
+ log.Log(NET, SPEW, addrs)
+ ips, _ := net.LookupIP(addr.String())
+ log.Log(NET, "\tLookupIP(addr) =", ips)
+ switch v := addr.(type) {
+ case *net.IPNet:
+ if checkIP(v, i) {
+ log.Log(true, "scanInterfaces() IP is new () i =", v.IP.String())
+ }
+ default:
+ log.Log(NET, "\t\taddr.(type) = NO IDEA WHAT TO DO HERE v =", v)
+ }
+ }
+ }
+ if deleteChanges() {
+ me.changed = true
+ log.Log(NET, "deleteChanges() detected network changes")
+ }
+ updateRealAAAA()
+ log.Log(NET, "scanInterfaces() END")
+}
+
+// displays the IP address found on your network interfaces
+func updateRealAAAA() {
+ var all4 string
+ var all6 string
+ for s, t := range me.ipmap {
+ if (t.ipv4) {
+ all4 += s + "\n"
+ log.Log(NET, "IPv4 =", s)
+ } else if (t.ipv6) {
+ all6 += s + "\n"
+ log.Log(NET, "IPv6 =", s)
+ } else {
+ log.Log(NET, "???? =", s)
+ }
+ }
+ all4 = sortLines(all4)
+ all6 = sortLines(all6)
+ if (me.IPv4.Get() != all4) {
+ log.Log(NET, "IPv4 addresses have changed", all4)
+ me.IPv4.Set(all4)
+ }
+ if (me.IPv6.Get() != all6) {
+ log.Log(NET, "IPv6 addresses have changed", all6)
+ me.IPv6.Set(all6)
+ }
+}
+
+// delete network interfaces and ip addresses from the gui
+func deleteChanges() bool {
+ var changed bool = false
+ for i, t := range me.ifmap {
+ if (t.gone) {
+ log.Log(CHANGE, "DELETE int =", i, "name =", t.name, t.iface)
+ delete(me.ifmap, i)
+ changed = true
+ }
+ t.gone = true
+ }
+ for s, t := range me.ipmap {
+ if (t.gone) {
+ log.Log(CHANGE, "DELETE name =", s, "IPv4 =", t.ipv4)
+ log.Log(CHANGE, "DELETE name =", s, "IPv6 =", t.ipv6)
+ log.Log(CHANGE, "DELETE name =", s, "iface =", t.iface)
+ log.Log(CHANGE, "DELETE name =", s, "ip =", t.ip)
+ delete(me.ipmap, s)
+ changed = true
+ }
+ t.gone = true
+ }
+
+ return changed
+}
diff --git a/linuxstatus/new.go b/linuxstatus/new.go
new file mode 100644
index 0000000..0ce504c
--- /dev/null
+++ b/linuxstatus/new.go
@@ -0,0 +1,17 @@
+// This creates a simple hello world window
+package linuxstatus
+
+import (
+)
+
+func New() *LinuxStatus {
+ me = &LinuxStatus {
+ hidden: true,
+ ready: false,
+ }
+
+ me.init = true
+ return me
+
+ // me.window = gadgets.NewBasicWindow(me.myGui, "Linux OS Details")
+}
diff --git a/linuxstatus/structs.go b/linuxstatus/structs.go
new file mode 100644
index 0000000..185f0d7
--- /dev/null
+++ b/linuxstatus/structs.go
@@ -0,0 +1,57 @@
+/*
+ figures out if your hostname is valid
+ then checks if your DNS is setup correctly
+*/
+
+package linuxstatus
+
+import (
+ "net"
+ "go.wit.com/gui/gui"
+ "go.wit.com/gui/gadgets"
+)
+
+var me *LinuxStatus
+
+type LinuxStatus struct {
+ init bool
+ ready bool
+ hidden bool
+ changed bool
+
+ ifmap map[int]*IFtype // the current interfaces
+ ipmap map[string]*IPtype // the current ip addresses
+
+ window *gadgets.BasicWindow
+ group *gui.Node
+ grid *gui.Node
+
+ hostshort *gadgets.OneLiner
+ domainname *gadgets.OneLiner
+ fqdn *gadgets.OneLiner
+ NSrr *gadgets.OneLiner
+ uid *gadgets.OneLiner
+ IPv4 *gadgets.OneLiner
+ IPv6 *gadgets.OneLiner
+ workingIPv6 *gadgets.OneLiner
+ Interfaces *gui.Node
+ speedActual *gadgets.OneLiner
+
+}
+
+type IPtype struct {
+ gone bool // used to track if the ip exists
+ ipv6 bool // the future
+ ipv4 bool // the past
+ LinkLocal bool
+ iface *net.Interface
+ ip net.IP
+ ipnet *net.IPNet
+}
+
+type IFtype struct {
+ gone bool // used to track if the interface exists
+ name string // just a shortcut to the name. maybe this is dumb
+ // up bool // could be used to track ifup/ifdown
+ iface *net.Interface
+}
diff --git a/linuxstatus/timer.go b/linuxstatus/timer.go
new file mode 100644
index 0000000..cd82f49
--- /dev/null
+++ b/linuxstatus/timer.go
@@ -0,0 +1,31 @@
+package linuxstatus
+
+import (
+ "time"
+ "sort"
+ "strings"
+)
+
+// timeFunction takes a function as an argument and returns the execution time.
+func timeFunction(f func()) time.Duration {
+ startTime := time.Now() // Record the start time
+ f() // Execute the function
+ return time.Since(startTime) // Calculate the elapsed time
+}
+
+// sortLines takes a string, splits it on newlines, sorts the lines,
+// and rejoins them with newlines.
+func sortLines(input string) string {
+ lines := strings.Split(input, "\n")
+
+ // Trim leading and trailing whitespace from each line
+ for i, line := range lines {
+ lines[i] = strings.TrimSpace(line)
+ }
+
+ sort.Strings(lines)
+ tmp := strings.Join(lines, "\n")
+ tmp = strings.TrimLeft(tmp, "\n")
+ tmp = strings.TrimRight(tmp, "\n")
+ return tmp
+}
diff --git a/linuxstatus/unix.go b/linuxstatus/unix.go
new file mode 100644
index 0000000..99509c0
--- /dev/null
+++ b/linuxstatus/unix.go
@@ -0,0 +1,97 @@
+// Various Linux/Unix'y things
+
+// https://wiki.archlinux.org/title/Dynamic_DNS
+
+package linuxstatus
+
+import (
+ "os"
+ "os/exec"
+ "net"
+ "bytes"
+ "fmt"
+ "strings"
+
+ "go.wit.com/log"
+ "go.wit.com/shell"
+)
+
+func CheckSuperuser() bool {
+ return os.Getuid() == 0
+}
+
+func Escalate() {
+ if os.Getuid() != 0 {
+ cmd := exec.Command("sudo", "./control-panel-dns") // TODO: get the actual path
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ err := cmd.Run()
+ if err != nil {
+ log.Error(err, "exit in Escalate()")
+ log.Exit(err)
+ }
+ }
+}
+
+// You need permission to do a zone transfer. Otherwise:
+// dig +noall +answer +multiline lab.wit.com any
+// dig +all +multiline fire.lab.wit.com # gives the zonefile header (ttl vals)
+func DumpPublicDNSZone(zone string) {
+ entries, err := net.LookupHost(zone)
+ if err != nil {
+ panic(err)
+ }
+ for _, entry := range entries {
+ log.Println(entry)
+ }
+}
+
+func dumpIPs(host string) {
+ ips, err := net.LookupIP(host)
+ if err != nil {
+ log.Error(err, "dumpIPs() failed")
+ }
+ for _, ip := range ips {
+ log.Println(host, ip)
+ }
+}
+
+/*
+ check if ddclient is installed, working, and/or configured
+ https://github.com/ddclient/ddclient
+*/
+func ddclient() {
+}
+
+/*
+ check if ddupdate is installed, working, and/or configured
+*/
+func ddupdate() {
+}
+
+func run(s string) string {
+ cmdArgs := strings.Fields(s)
+ // Define the command you want to run
+ // cmd := exec.Command(cmdArgs)
+ cmd := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
+
+ // Create a buffer to capture the output
+ var out bytes.Buffer
+
+ // Set the output of the command to the buffer
+ cmd.Stdout = &out
+
+ // Run the command
+ err := cmd.Run()
+ if err != nil {
+ fmt.Println("Error running command:", err)
+ return ""
+ }
+
+ tmp := shell.Chomp(out.String())
+ // Output the results
+ log.Info("Command Output:", tmp)
+
+ return tmp
+}
diff --git a/linuxstatus/update.go b/linuxstatus/update.go
new file mode 100644
index 0000000..1ab8cee
--- /dev/null
+++ b/linuxstatus/update.go
@@ -0,0 +1,31 @@
+package linuxstatus
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ "go.wit.com/log"
+)
+
+func (ls *LinuxStatus) Update() {
+ log.Info("linuxStatus() Update() START")
+ if ls == nil {
+ log.Error(errors.New("linuxStatus() Update() ls == nil"))
+ return
+ }
+ duration := timeFunction(func () {
+ linuxLoop()
+ })
+ s := fmt.Sprint(duration)
+ ls.speedActual.Set(s)
+
+ if (duration > 500 * time.Millisecond ) {
+ // ls.speed, "SLOW")
+ } else if (duration > 100 * time.Millisecond ) {
+ // ls.speed, "OK")
+ } else {
+ // ls.speed, "FAST")
+ }
+ log.Info("linuxStatus() Update() END")
+}
diff --git a/main.go b/main.go
index f417b86..5eb83f6 100644
--- a/main.go
+++ b/main.go
@@ -17,6 +17,8 @@ import (
"go.wit.com/gui/gui"
"go.wit.com/gui/debugger"
+ "go.wit.com/control-panels/dns/linuxstatus"
+
"github.com/miekg/dns"
)
@@ -47,6 +49,8 @@ func main() {
me.digStatus = NewDigStatusWindow(me.myGui)
me.status = NewHostnameStatusWindow(me.myGui)
+ linuxstatus.New()
+
if debugger.ArgDebug() {
log.Sleep(2)
debugger.DebugWindow(me.myGui)
diff --git a/structs.go b/structs.go
index c3f6622..e8db7ee 100644
--- a/structs.go
+++ b/structs.go
@@ -6,6 +6,7 @@ import (
"time"
"go.wit.com/gui/gui"
"go.wit.com/gui/gadgets"
+ "go.wit.com/control-panels/dns/linuxstatus"
"github.com/miekg/dns"
)
@@ -15,10 +16,11 @@ var me Host
type Host struct {
status *hostnameStatus // keeps track of the hostname and it's status
+ statusOS *linuxstatus.LinuxStatus // what the Linux OS sees
hostnameStatus *gui.Node // a summary for the user of where things are
- domainname *gui.Node // kernel.org
+ // domainname *gui.Node // kernel.org
hostshort *gui.Node // hostname -s
artificialSleep float64 `default:"0.7"` // artificial sleep on startup