Page MenuHomeFreeBSD

sh: implement PS1 \D to print current time
ClosedPublic

Authored by pstef on Jul 18 2022, 8:38 AM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, Nov 21, 11:00 PM
Unknown Object (File)
Thu, Nov 21, 12:18 AM
Unknown Object (File)
Wed, Nov 20, 9:30 PM
Unknown Object (File)
Wed, Nov 20, 9:29 PM
Unknown Object (File)
Fri, Nov 15, 1:34 PM
Unknown Object (File)
Thu, Nov 14, 11:10 PM
Unknown Object (File)
Tue, Nov 12, 9:26 PM
Unknown Object (File)
Sat, Nov 9, 12:12 PM

Details

Summary

\D{format} yields the result of calling strftime(3) with the provided
format and the current time.

When PS4 can use this, it will enable us to easily generate timestamps
when tracing script execution.

Diff Detail

Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

pstef requested review of this revision.Jul 18 2022, 8:38 AM

Place the result of strftime() in the right place instead of always at the beginning of the buffer.
Simplify conditional early exit.

pstef set the repository for this revision to rG FreeBSD src repository.

Remove debugging changes not meant for review.

Handle rare cases the way bash does it.

Simplify and add comments.

jilles requested changes to this revision.Jul 18 2022, 9:04 PM

A little unfortunate to have these strange backslash sequences spread out further, but it's nothing that bash doesn't do.

bin/sh/eval.c
764

This order of operations and lack of escaping means that a parameter expansion in a directory name (\w) will be expanded. If expandstr is extended to PS1 and PS2 and with command substitution, this may lead to command execution from changing into a weirdly-named directory.

I haven't thought of a good solution here yet, but this one is not the right one.

bin/sh/sh.1
1426–1429

and with the current time

1430

Brackets are [].

1431

Perhaps "Empty" is clearer.

This revision now requires changes to proceed.Jul 18 2022, 9:04 PM

A little unfortunate to have these strange backslash sequences spread out further, but it's nothing that bash doesn't do.

In a way, this has nothing to do with bash. I want sh PS4 to be able to generate some kind of timestamps when executing a script with tracing on. The way bash does it is just a convention which I think is not worth diverging from.

bin/sh/eval.c
764

This order of operations and lack of escaping means that a parameter expansion in a directory name (\w) will be expanded.

Isn't this true already? Currently we call expandstr() on ps4val() and getprompt() will not be much different.

bin/sh/eval.c
764

I now understand what you mean. Formatting sequences like \w are first translated to, for example, the CWD, and then subject to parameter expansion. So if CWD is /usr/$X, \w is translated to that and then the $X is expanded.

bin/sh/eval.c
764

Perhaps the solution is to escape all $ at the end of getprompt() and then apply expandstr() to both PS1 and PS2?

In a way, this has nothing to do with bash. I want sh PS4 to be able to generate some kind of timestamps when executing a script with tracing on. The way bash does it is just a convention which I think is not worth diverging from.

The more POSIX-like way would be to add some level of command substitution to expandstr() (ensuring set -x doesn't apply to the nested command) and put in something like $(date +%s) in PS4. However, this is slower and harder to implement. It is also more flexible.

bin/sh/eval.c
764

That would be all $ and ` generated by backslash sequences.

Actually applying expandstr() to PS1 and PS2 will require some way to deal with re-entering the parser, so it shouldn't be done as part of this review.

pstef retitled this revision from sh: implement PS \D and allow PS4 to use formatting sequences to sh: implement PS1 \D to print current time.
pstef edited the summary of this revision. (Show Details)

Drop PS4 support and update the manual page changes according to feedback.

Code is OK like this.

bin/sh/sh.1
1426–1430

Perhaps this could be formulated a bit differently so no prior knowledge of strftime is assumed: "The current time formatted using the .Xr strftime 3 format .Ar format."

pstef marked 5 inline comments as done.

In this iteration I tried to address all new feedback.
I also was annoyed by the current formatting of the file, so this is a diff against D37926 where I reduce indentation.

When I was looking at this code today, I thought that the unconditional memccpy() is a bit wasteful in the \D{} case, because the one copied byte is a special case and when it's noticed, the copied byte is overwriten by strcpy() with "%X".
There is little to be gained in either performance or legibility of the code, but when I rewrote this locally to be less wasteful, it didn't look much worse, nor did it look much better.
Opinions?

Simplify the code part a bit.
Also improve comments and some variable names.

Minutes after posting the previous version, I thought about handling the rare corner case when strftime() returns 0.

Back out the previous update.
The -1 was there for the i++ that the loop always performs, so it's needed regardless of whether strftime() returned 0 or more.
Split the calculation that was there before into two parts, one of which just decrements i and makes a comment on why it's done.

This revision was not accepted when it landed; it landed in state Needs Review.Sep 23 2023, 6:28 PM
This revision was automatically updated to reflect the committed changes.