From 7aaf4f2423e2bcabce508e91255de673db50b728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Mon, 7 Jun 2021 16:36:05 +0200 Subject: Add [-w write-file] option ksh will write lines to write-file containing information about the status of the shell: after prompt: empty line after command entry: "cmd" followed by command after cwd change: "cwd" followed by new cwd fg is handled specially, printing a new "cmd" line with the original command associated with the job. --- jobs.c | 7 +++++++ ksh.Man | 7 ++++++- main.c | 12 ++++++++++++ misc.c | 12 ++++++++++-- path.c | 2 ++ sh.h | 1 + 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/jobs.c b/jobs.c index c8cc781..65c364f 100644 --- a/jobs.c +++ b/jobs.c @@ -840,6 +840,8 @@ j_resume(cp, bg) shprintf("[%d] ", j->job); running = 0; + if (writefd) + dprintf(writefd, "cmd"); for (p = j->proc_list; p != (Proc *) 0; p = p->next) { if (p->state == PSTOPPED) { p->state = PRUNNING; @@ -847,9 +849,14 @@ j_resume(cp, bg) running = 1; } shprintf("%s%s", p->command, p->next ? "| " : null); + if (writefd) + dprintf(writefd, "%s%s", + p->command, p->next ? "| " : null); } shprintf("%s", newline); shf_flush(shl_stdout); + if (writefd) + dprintf(writefd, "\n"); if (running) j->state = PRUNNING; diff --git a/ksh.Man b/ksh.Man index 69ea1f0..80ad538 100644 --- a/ksh.Man +++ b/ksh.Man @@ -43,7 +43,7 @@ sh \- Public domain Bourne shell .sh( \fBsh\fP .sh) -[\fB\(+-abCefhiklmnprsuvxX\fP] [\fB\(+-o\fP \fIoption\fP] [ [ \fB\-c\fP \fIcommand-string\fP [\fIcommand-name\fP] | \fB\-s\fP | \fIfile\fP ] [\fIargument\fP ...] ] +[\fB\(+-abCefhiklmnprsuvxX\fP] [\fB\(+-o\fP \fIoption\fP] [\fB-w\fP \fIwrite-file\fP]] [ [ \fB\-c\fP \fIcommand-string\fP [\fIcommand-name\fP] | \fB\-s\fP | \fIfile\fP ] [\fIargument\fP ...] ] .ad b .\"}}} .\"{{{ Description @@ -72,6 +72,11 @@ the shell reads commands from standard input; all non-option arguments are positional parameters .IP \fB\-r\fP restricted mode \(em see below +.IP "\fB\-w\fP \fIwrite-file\fP" +the shell writes to \fIwrite-file\fR an empty line after each +prompt, a line beginning with \fIcwd\fR after each directory change +and a line beginning with \fIcmd\fR after each interactive command +entry. .PP In addition to the above, the options described in the \fBset\fP built-in command can also be used on the command line. diff --git a/main.c b/main.c index 41d4d80..dad50d3 100644 --- a/main.c +++ b/main.c @@ -278,6 +278,9 @@ main(int argc, char *argv[]) /* Set this before parsing arguments */ Flag(FPRIVILEGED) = getuid() != ksheuid || getgid() != getegid(); + /* set before parse_args */ + writefd = 0; + /* this to note if monitor is set on command line (see below) */ Flag(FMONITOR) = 127; argi = parse_args(argv, OF_CMDLINE, (int *) 0); @@ -286,6 +289,10 @@ main(int argc, char *argv[]) /* NOTREACHED */ } + /* print initial cwd */ + if (writefd) + dprintf(writefd, "cwd%s\n", current_wd); + if (Flag(FCOMMAND)) { s = pushs(SSTRING, ATEMP); if (!(s->start = s->str = argv[argi++])) @@ -578,7 +585,12 @@ shell(s, toplevel) set_prompt(PS1, s); } + if (interactive && writefd) + dprintf(writefd, "\n"); t = compile(s); + if (interactive && writefd && s->start[0] != '\n') + dprintf(writefd, "cmd%s", s->start); + if (t != NULL && t->type == TEOF) { if (wastty && Flag(FIGNOREEOF) && --attempts > 0) { shellf("Use `exit' to leave ksh\n"); diff --git a/misc.c b/misc.c index 393da1c..80ce13b 100644 --- a/misc.c +++ b/misc.c @@ -347,7 +347,7 @@ parse_args(argv, what, setargsp) int what; /* OF_CMDLINE or OF_SET */ int *setargsp; { - static char cmd_opts[NELEM(goptions) + 3]; /* o:\0 */ + static char cmd_opts[NELEM(goptions) + 5]; /* o:w:\0 */ static char set_opts[NELEM(goptions) + 5]; /* Ao;s\0 */ char *opts; char *array = (char *) 0; @@ -359,7 +359,7 @@ parse_args(argv, what, setargsp) char *p, *q; /* see cmd_opts[] declaration */ - strlcpy(cmd_opts, "o:", sizeof cmd_opts); + strlcpy(cmd_opts, "o:w:", sizeof cmd_opts); p = cmd_opts + strlen(cmd_opts); /* see set_opts[] declaration */ strlcpy(set_opts, "A:o;s", sizeof set_opts); @@ -423,6 +423,14 @@ parse_args(argv, what, setargsp) } break; + case 'w': + writefd = open(go.optarg, O_WRONLY); + if (writefd == -1) { + bi_errorf("could not open %s", go.optarg); + return -1; + } + break; + case '?': return -1; diff --git a/path.c b/path.c index bb18075..70d8a71 100644 --- a/path.c +++ b/path.c @@ -198,6 +198,8 @@ set_current_wd(pathx) if (len > current_wd_size) current_wd = aresize(current_wd, current_wd_size = len, APERM); memcpy(current_wd, p, len); + if (writefd) + dprintf(writefd, "cwd%s\n", p); if (p != pathx && p != null) afree(p, ATEMP); } diff --git a/sh.h b/sh.h index 222b77c..6cd656d 100644 --- a/sh.h +++ b/sh.h @@ -186,6 +186,7 @@ EXTERN uid_t ksheuid; /* effective uid of shell */ EXTERN int exstat; /* exit status */ EXTERN int subst_exstat; /* exit status of last $(..)/`..` */ EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ +EXTERN int writefd; /* open file descriptor to -w file */ /* * Area-based allocation built on malloc/free -- cgit v1.2.3