From c91333deea98660aea85dbb525933a6f198415cb Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sun, 8 May 2022 13:37:05 -0700 Subject: New :s option to save the state. --- pw.1 | 16 ++++++++++++++++ pw.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/pw.1 b/pw.1 index 6785564..a66df34 100644 --- a/pw.1 +++ b/pw.1 @@ -668,6 +668,22 @@ the trigger count is reset to zero. Thus when the command is used to resume capture, the same number of capture events will have to occur again before the next automatic suspension. +.IP "\fB:s\fP [\fIfilename\fP]" +Save a snapshot of the configuration state to the specified file. +The state is saved as a sequence of colon and trigger commands, +such that the resulting file is suitable as an argument to the +.B -f +option. If saving the state to +.I filename +is successful, then when +.I pw +is started up with +.I filename +as the argument to the +.B -f +option, the grep stack and trigger state will be stored to exactly +the same configuration that existed at the time the state was saved. + .SH OPTIONS .IP "\fB-i\fP \fIreal\fP" diff --git a/pw.c b/pw.c index cfc4d71..96ad94e 100644 --- a/pw.c +++ b/pw.c @@ -103,6 +103,7 @@ typedef struct grep { char *pat; regex_t rx; int inv; + int flags; int err; void (*dtor)(char *); } grep; @@ -312,6 +313,7 @@ static int grinit(grep *gr, char *pat, int inv, void (*dtor)(char *)) gr->pat = pat; gr->inv = inv; gr->dtor = dtor; + gr->flags = regex_flags; return (gr->err = regcomp(&gr->rx, pat, regex_flags | REG_NOSUB)) != 0; } @@ -829,6 +831,66 @@ static execode execute(pwstate *pw, const char *cmd, char *resbuf, res = exec_ok; } break; + case 's': + { + int rflg = 0; + FILE *f; + + if (arg[0] == 0) { + snprintf(resbuf, size, "file name required!"); + break; + } + + if ((f = fopen(arg, "w")) == 0) { + snprintf(resbuf, size, "unable to open %s", arg); + break; + } + + if (pw->tcount) + fprintf(f, ":f%d\n", pw->tcount); + if (pw->sncount) + fprintf(f, ":c%d\n", pw->sncount); + + for (int i = 0; i < ngrep; i++) { + grep *gr = &grepstack[i]; + if (gr->flags != rflg) { + rflg = gr->flags; + fputs(((gr->flags & REG_EXTENDED)) ? ":E\n" : ":B\n", f); + } + fputs(gr->inv ? ":v" : ":g", f); + fputs(gr->pat, f); + putc('\n', f); + } + + if ((pw->stat & (stat_htmode | stat_ttmode))) { + int tch = ((pw->stat & stat_htmode)) ? '/' : '?'; + for (int i = 0; i < maxtrig; i++) { + grep *gr = triglist[i]; + if (gr != 0) { + if (gr->flags != rflg) { + rflg = gr->flags; + fputs(((gr->flags & REG_EXTENDED)) ? ":E\n" : ":B\n", f); + } + if (gr->inv) + fprintf(f, "%d%c!%s\n", i + 1, tch, gr->pat); + else if (gr->pat[0] == '!') + fprintf(f, "%d%c\\!%s\n", i + 1, tch, gr->pat); + else + fprintf(f, "%d%c%s\n", i + 1, tch, gr->pat); + } + } + } + + if (ferror(f)) { + snprintf(resbuf, size, "write error!"); + } else { + snprintf(resbuf, size, "config saved!"); + res = exec_msg; + } + + fclose(f); + } + break; case 0: res = exec_ok; break; -- cgit v1.2.3