diff --git a/internal/firewall/firewalld.go b/internal/firewall/firewalld.go new file mode 100644 index 0000000..e69de29 diff --git a/internal/firewall/iptables.go b/internal/firewall/iptables.go new file mode 100644 index 0000000..e69de29 diff --git a/internal/firewall/nftables.go b/internal/firewall/nftables.go new file mode 100644 index 0000000..e69de29 diff --git a/internal/firewall/type.go b/internal/firewall/type.go new file mode 100644 index 0000000..e69de29 diff --git a/internal/firewall/ufw.go b/internal/firewall/ufw.go new file mode 100644 index 0000000..e69de29 diff --git a/internal/parser/journald.go b/internal/parser/journald.go new file mode 100644 index 0000000..2142c93 --- /dev/null +++ b/internal/parser/journald.go @@ -0,0 +1,41 @@ +package parser + +import ( + "bufio" + "errors" + "fmt" + "os" + "os/exec" + "regexp" +) + +func ParseJournald(unit string) (Parser, error) { + if unit == "" { + return Parser{}, errors.New("unit name cannot be empty") + } + + validUnitName := regexp.MustCompile(`^[a-zA-Z0-9:_\.\-@]+$`) + if !validUnitName.MatchString(unit) { + return Parser{}, fmt.Errorf("invalid systemd unit name: %s", unit) + } + + cmd := exec.Command("journalctl", "-u", unit, "-f", "-n", "0", "-o", "short", "--no-pager") + + stdout, err := cmd.StdoutPipe() + if err != nil { + return Parser{}, fmt.Errorf("stdout pipe error: %w", err) + } + + if err := cmd.Start(); err != nil { + return Parser{}, fmt.Errorf("failed to start journalctl: %w", err) + } + + p := Parser{ + parser: bufio.NewScanner(stdout), + ch: make(chan string, 100), + cmd: cmd, + file: nil, + } + + return p, nil +} diff --git a/internal/parser/parser.go b/internal/parser/parser.go new file mode 100644 index 0000000..271ed23 --- /dev/null +++ b/internal/parser/parser.go @@ -0,0 +1,31 @@ +package parser + +import ( + "bufio" + "os/exec" +) + +type Parser struct { + parser *bufio.Scanner + ch chan string + cmd *exec.Cmd + file *string +} + +func (p *Parser) Start() { + go func() { + for p.parser.Scan() { + p.ch <- p.parser.Text() + } + }() +} + +func (p *Parser) Stop() { + if p.cmd != nil && p.cmd.Process != nil { + p.cmd.Process.Kill() + } +} + +func (p *Parser) Channel() <-chan string { + return p.ch +} diff --git a/internal/parser/tail.go b/internal/parser/tail.go new file mode 100644 index 0000000..eddb36d --- /dev/null +++ b/internal/parser/tail.go @@ -0,0 +1,39 @@ +package parser + +import ( + "bufio" + "errors" + "fmt" + "os" + "os/exec" +) + +func ParseFile(path string) (Parser, error) { + if path == "" { + return Parser{}, errors.New("path cannot be empty") + } + + if _, err := os.Stat(path); os.IsNotExist(err) { + return Parser{}, fmt.Errorf("file does not exist: %s", path) + } + + cmd := exec.Command("tail", "-F", "-n", "10", path) + + stdout, err := cmd.StdoutPipe() + if err != nil { + return Parser{}, fmt.Errorf("stdout pipe error: %w", err) + } + + if err := cmd.Start(); err != nil { + return Parser{}, fmt.Errorf("failed to start tail parser: %w", err) + } + + p := Parser{ + parser: bufio.NewScanner(stdout), + ch: make(chan string, 100), + cmd: cmd, + file: &path, + } + + return p, nil +}