Index: bin/sh/eval.c =================================================================== --- bin/sh/eval.c +++ bin/sh/eval.c @@ -760,7 +760,8 @@ const char *text, *p, *ps4; int i; - ps4 = expandstr(ps4val()); + whichprompt = 4; + ps4 = expandstr(getprompt(NULL)); out2str(ps4 != NULL ? ps4 : ps4val()); for (i = 0; i < varlist->count; i++) { text = varlist->args[i]; Index: bin/sh/parser.c =================================================================== --- bin/sh/parser.c +++ bin/sh/parser.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "shell.h" #include "parser.h" @@ -2047,6 +2048,9 @@ case 2: fmt = ps2val(); break; + case 4: + fmt = ps4val(); + break; default: return internal_error; } @@ -2062,6 +2066,60 @@ switch (*++fmt) { + /* + * Print time or date as per provided format. + */ + case 'D': { + char tfmt[128], *len; + time_t now; + + if (fmt[1] != '{') { + /* + * "\D" but not "\D{", so treat the + * '\' literally and rewind fmt to + * treat 'D' literally next iteration. + */ + ps[i] = '\\'; + fmt--; + break; + } + /* + * Consume the 'D' character and try to copy + * fmt from after '{' until '}'. + * Don't consume '{' from fmt yet. + */ + fmt++; + len = memccpy(tfmt, fmt + 1, '}', sizeof(tfmt)); + if (len == NULL) { + /* + * Format too long or '}' not found, + * so ignore "\D{" altogether. + * The loop will do i++, but nothing + * was written to ps, so do i-- here. + * "fmt++" will consume the '{'. + */ + i--; + break; + } + /* + * Either way, consume fmt until '}'. The loop + * will do fmt++ to finally consume the '}'. + */ + if (len - tfmt == 1) { + /* "\D{}" is documented to mean %X. */ + fmt++; + strcpy(tfmt, "%X"); + } else { + fmt += len - tfmt; + /* Truncate tfmt before '}'. */ + *--len = '\0'; + } + now = time(NULL); + i += strftime(&ps[i], PROMPTLEN - i - 1, + tfmt, localtime(&now)) - 1; + } + break; + /* * Hostname. * Index: bin/sh/sh.1 =================================================================== --- bin/sh/sh.1 +++ bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd May 10, 2021 +.Dd Jul 18, 2022 .Dt SH 1 .Os .Sh NAME @@ -1422,6 +1422,16 @@ may include any of the following formatting sequences, which are replaced by the given information: .Bl -tag -width indent +.It Li \eD{format} +The result of calling +.Xr strftime 3 +with the provided +.Ar format . +The brackets are required. +Void +.Ar format +is equivalent to +\&%X. .It Li \eH This system's fully-qualified hostname (FQDN). .It Li \eh