aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pw.116
-rw-r--r--pw.c62
2 files changed, 78 insertions, 0 deletions
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;