]> git.ipfire.org Git - thirdparty/mtr.git/commitdiff
feat(curses): add report snapshot on exit 643/head
authorDarafei Praliaskouski <me@komzpa.net>
Thu, 7 May 2026 20:22:25 +0000 (00:22 +0400)
committerDarafei Praliaskouski <me@komzpa.net>
Mon, 25 May 2026 11:04:36 +0000 (15:04 +0400)
bash-completion/mtr
man/mtr.8.in
test/cmdparse.py
ui/display.c
ui/mtr.c
ui/mtr.h

index 63b153b1aff490c7c295576635c195906414a212..bc60346e92783a560e63d03643861025eb1ef7ca 100644 (file)
@@ -54,7 +54,8 @@ _mtr_module()
         --filename --inet --inet6 --udp --tcp --address --first-ttl
         --max-ttl --max-unknown --port --localport --psize --bitpattern
         --interval --gracetime --tos --mpls --timeout --mark --report
-        --report-wide --report-cycles --json --xml --csv --raw --split
+        --report-wide --report-on-exit --report-cycles --json --xml --csv
+        --raw --split
         --curses --displaymode --gtk --no-dns --show-ips --order --ipinfo
         --aslookup --help --version
       '
index 8684ac523110d6298e21f9553d6c131a18211a11..a3d05c65958b41be17a9b0c2e2189bc98e301c13 100644 (file)
@@ -17,6 +17,9 @@ mtr \- a network diagnostic tool
 .B \-\-report-wide\c
 ]
 [\c
+.B \-\-report\-on\-exit\c
+]
+[\c
 .B \-\-xml\c
 ]
 [\c
@@ -202,6 +205,11 @@ mode.  When in this mode,
 .B mtr
 will not cut hostnames in the report.
 .TP
+.B \-\-report\-on\-exit
+Use this option with the curses interface to print a report snapshot after
+leaving curses mode. This keeps the last trace visible in terminals that switch
+to an alternate screen while curses is active.
+.TP
 .B \-x\fR, \fB\-\-xml
 Use this option to tell
 .B mtr
index 6a093d2eeccc99c0784167f6bdfeeabcb5433f29..1aaf166ee7c2adf1484bcaf0a67e56b9e8e30ef4 100755 (executable)
@@ -119,6 +119,14 @@ class TestMtrCommandParse(unittest.TestCase):
         self.assertIn('Drop', reply.stdout)
         self.assertIn('Jint', reply.stdout)
 
+    def test_help_lists_report_on_exit(self):
+        'Test that the curses exit snapshot option remains advertised.'
+
+        reply = self.run_mtr('--help')
+
+        self.assertEqual(reply.returncode, 0)
+        self.assertIn('--report-on-exit', reply.stdout)
+
     def test_port_with_tcp_succeeds_flag(self):
         'Test that specifying -P with -T (TCP) succeeds.'
 
index a076154fe8da1cbd70843c2213b108541ac3abd3..25c3dc4f8c52e57159776788184ea48863784cd8 100644 (file)
@@ -146,6 +146,8 @@ void display_close(
         asn_close(ctl);
 #endif
         mtr_curses_close();
+        if (ctl->ReportOnExit)
+            report_close(ctl);
         break;
 #endif
     case DisplaySplit:
index 98977f6c5cc9531a89cdc805e95d4822617f2b4b..671204dbd96e9b343ba510b65cf0c6626d1ee389 100644 (file)
--- a/ui/mtr.c
+++ b/ui/mtr.c
@@ -127,6 +127,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
 #endif
     fputs(" -r, --report                     output using report mode\n", out);
     fputs(" -w, --report-wide                output wide report\n", out);
+    fputs("     --report-on-exit             print report after curses exits\n", out);
     fputs(" -c, --report-cycles COUNT        set the number of pings sent\n", out);
 #ifdef HAVE_JANSSON
     fputs(" -j, --json                       output json\n", out);
@@ -420,12 +421,13 @@ static void parse_arg(
      */
     enum {
         OPT_DISPLAYMODE = CHAR_MAX + 1,
-        OPT_IPINFO4 = CHAR_MAX + 2,
+        OPT_REPORT_ON_EXIT = CHAR_MAX + 2,
+        OPT_IPINFO4 = CHAR_MAX + 3,
 #ifdef ENABLE_IPV6
-        OPT_IPINFO6 = CHAR_MAX + 3,
-        OPT_CACHE = CHAR_MAX + 4,
+        OPT_IPINFO6 = CHAR_MAX + 4,
+        OPT_CACHE = CHAR_MAX + 5,
 #else
-        OPT_CACHE = CHAR_MAX + 3,
+        OPT_CACHE = CHAR_MAX + 4,
 #endif /* ifdef ENABLE_IPV6 */
     };
     static const struct option long_options[] = {
@@ -441,6 +443,7 @@ static void parse_arg(
 
         {"report", 0, NULL, 'r'},
         {"report-wide", 0, NULL, 'w'},
+        {"report-on-exit", 0, NULL, OPT_REPORT_ON_EXIT},
         {"xml", 0, NULL, 'x'},
 #ifdef HAVE_CURSES
         {"curses", 0, NULL, 't'},
@@ -535,6 +538,9 @@ static void parse_arg(
             ctl->reportwide = 1;
             ctl->DisplayMode = DisplayReport;
             break;
+        case OPT_REPORT_ON_EXIT:
+            ctl->ReportOnExit = 1;
+            break;
 #ifdef HAVE_CURSES
         case 't':
             ctl->DisplayMode = DisplayCurses;
index c4fd2ebf94bd7bebd6bfa0b00643a59d390655fa..09df6dbb14ad28b7f33eb88f0e491c92c6b479e1 100644 (file)
--- a/ui/mtr.h
+++ b/ui/mtr.h
@@ -122,7 +122,8 @@ struct mtr_ctl {
      ForceMaxPing:1,
         use_dns:1, cache:1,
         show_ips:1,
-        enablempls:1, dns:1, reportwide:1, Interactive:1, DisplayMode:5, CompactLayout:1;
+        enablempls:1, dns:1, reportwide:1, Interactive:1, DisplayMode:5,
+        CompactLayout:1, ReportOnExit:1;
 #ifdef HAVE_IPINFO
 #ifdef ENABLE_IPV6
     char *ipinfo_provider6;