Skip to content

Commit

Permalink
Initial implementation of a profiles feature for termshark
Browse files Browse the repository at this point in the history
This work is driven by this issue:
#108

Here's a description of how everything currently works. Prior to this
change, termshark had one config file (per user), stored in a standard
location. I'll use Linux as an example -
~/.config/termshark/termshark.toml. With this change, there's a new set
of subdirectories, one per profile, containing toml files e.g. after
some profiles have been created, you might have:

~/.config/termshark/profiles/classic/termshark.toml
~/.config/termshark/profiles/extracolumns/termshark.toml
~/.config/termshark/profiles/darker/termshark.toml

These toml files are the same structure as the default termshark.toml.

Termshark starts with the default profile, represented by the default
config file (not in the new profiles/ dir).

There are two new console commands:

(1) :profile -> switch profile to one that exists already

When a non-default profile is chosen, the settings in that profile's
config file take precedence. If a setting is needed and not set
explicitly, termshark falls back to the setting in the default
profile. When a setting is explicitly changed, it is changed in the
newly activated profile.

(2) :new-profile -> create a new profile

The user must choose a name that is not in use (and that can be used as
a directory name). When created, termshark automatically switches to the
new profile. If the profile in use at the time of creation is not the
default, termshark copies the previous profile to the new profile and
proceeds from there. If the profile in use is the default, the new
profile will be empty.

When termshark is using a non-default profile, it is shown on the top
line of the UI.

Termshark can be started with a non-default profile using the new
-C/--profile command-line flag. Note that although I chose this to line
up with Wireshark's invocation, termshark does not use Wireshark
profiles in any way.
  • Loading branch information
gcla committed Jun 12, 2022
1 parent 9c15935 commit c5bfbef
Show file tree
Hide file tree
Showing 9 changed files with 1,170 additions and 134 deletions.
4 changes: 3 additions & 1 deletion cli/all.go
Expand Up @@ -12,6 +12,7 @@ import "github.com/jessevdk/go-flags"
// Used to determine if we should run tshark instead e.g. stdout is not a tty
type Tshark struct {
PassThru string `long:"pass-thru" default:"auto" optional:"true" optional-value:"true" choice:"yes" choice:"no" choice:"auto" choice:"true" choice:"false" description:"Run tshark instead (auto => if stdout is not a tty)."`
Profile string `long:"profile" short:"C" description:"Start with this configuration profile." value-name:"<profile>"`
PrintIfaces bool `short:"D" optional:"true" optional-value:"true" description:"Print a list of the interfaces on which termshark can capture."`
TailSwitch
}
Expand All @@ -27,6 +28,7 @@ type Termshark struct {
CaptureFilter string `short:"f" description:"Apply capture filter." value-name:"<capture filter>"`
TimestampFormat string `short:"t" description:"Set the format of the packet timestamp printed in summary lines." choice:"a" choice:"ad" choice:"adoy" choice:"d" choice:"dd" choice:"e" choice:"r" choice:"u" choice:"ud" choice:"udoy" value-name:"<timestamp format>"`
PlatformSwitches
Profile string `long:"profile" short:"C" description:"Start with this configuration profile." value-name:"<profile>"`
PassThru string `long:"pass-thru" default:"auto" optional:"true" optional-value:"true" choice:"auto" choice:"true" choice:"false" description:"Run tshark instead (auto => if stdout is not a tty)."`
LogTty bool `long:"log-tty" optional:"true" optional-value:"true" choice:"true" choice:"false" description:"Log to the terminal."`
Debug TriState `long:"debug" default:"unset" hidden:"true" optional:"true" optional-value:"true" description:"Enable termshark debugging. See https://termshark.io/userguide."`
Expand All @@ -40,7 +42,7 @@ type Termshark struct {

// If args are passed through to tshark (e.g. stdout not a tty), then
// strip these out so tshark doesn't fail.
var TermsharkOnly = []string{"--pass-thru", "--log-tty", "--debug", "--tail"}
var TermsharkOnly = []string{"--pass-thru", "--profile", "--log-tty", "--debug", "--tail"}

func FlagIsTrue(val string) bool {
return val == "true" || val == "yes"
Expand Down
54 changes: 25 additions & 29 deletions cmd/termshark/termshark.go
Expand Up @@ -27,7 +27,6 @@ import (
"github.com/gcla/termshark/v2/shark"
"github.com/gcla/termshark/v2/streams"
"github.com/gcla/termshark/v2/system"
"github.com/gcla/termshark/v2/theme"
"github.com/gcla/termshark/v2/tty"
"github.com/gcla/termshark/v2/ui"
"github.com/gcla/termshark/v2/widgets/filter"
Expand Down Expand Up @@ -149,15 +148,6 @@ func cmain() int {
fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", err.Error()))
}

if os.Getenv("TERMSHARK_CAPTURE_MODE") == "1" {
err = system.DumpcapExt(termshark.DumpcapBin(), termshark.TSharkBin(), os.Args[1:]...)
if err != nil {
return 1
} else {
return 0
}
}

// Used to determine if we should run tshark instead e.g. stdout is not a tty
var tsopts cli.Tshark

Expand Down Expand Up @@ -193,6 +183,29 @@ func cmain() int {
}
}

// From here, the current profile is referenced. So load it up prior to first use. If the user
// provides a non-existent profile name, it should be an error, just as for Wireshark.
if tsopts.Profile != "" {
if err = profiles.Use(tsopts.Profile); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
return 1
}
}

// If this variable is set, it's set by termshark internally, and termshark is guaranteed to
// construct a valid command-line invocation. So it doesn't matter if I do this after the CLI
// parsing logic because there's no risk of an error causing a short-circuit and this command
// not being run. The reason to do it after the CLI parsing logic is so that I have the correct
// config profile loaded, needed for the tshark command.
if os.Getenv("TERMSHARK_CAPTURE_MODE") == "1" {
err = system.DumpcapExt(termshark.DumpcapBin(), termshark.TSharkBin(), os.Args[1:]...)
if err != nil {
return 1
} else {
return 0
}
}

// Run after accessing the config so I can use the configured tshark binary, if there is one. I need that
// binary in the case that termshark is run where stdout is not a tty, in which case I exec tshark - but
// it makes sense to use the one in termshark.toml
Expand Down Expand Up @@ -1150,24 +1163,7 @@ Loop:
// Need to do that here because the app won't know how many colors the screen
// has (and therefore which variant of the theme to load) until the screen is
// activated.
mode := app.GetColorMode()
modeStr := theme.Mode(mode) // more concise
themeName := profiles.ConfString(fmt.Sprintf("main.theme-%s", modeStr), "default")
loaded := false
if themeName != "" {
err = theme.Load(themeName, app)
if err != nil {
log.Warnf("Theme %s could not be loaded: %v", themeName, err)
} else {
loaded = true
}
}
if !loaded && themeName != "default" {
err = theme.Load("default", app)
if err != nil {
log.Warnf("Theme %s could not be loaded: %v", themeName, err)
}
}
ui.ApplyCurrentTheme(app)

// This needs to run after the toml config file is loaded.
ui.SetupColors()
Expand All @@ -1186,7 +1182,7 @@ Loop:
ui.StartUIChan = nil // make sure it's not triggered again

if runtime.GOOS != "windows" {
if mode == gowid.Mode8Colors {
if app.GetColorMode() == gowid.Mode8Colors {
// If exists is true, it means we already tried and then reverted back, so
// just load up termshark normally with no further interruption.
if _, exists := os.LookupEnv("TERMSHARK_ORIGINAL_TERM"); !exists {
Expand Down

0 comments on commit c5bfbef

Please sign in to comment.