Read commands from stdin when -f - is passed to sed(1)

This patch teaches sed to interpret a "-" in a special way when given
as an argument to the -f flag.

This behavior is also present in GNU sed.

PR:		244872
Tested by:	antoine (exp-run)
Reviewed by:	pfg, tobik (older version)
Approved by:	pfg (src)
Relnotes:	yes
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D24079
This commit is contained in:
Mateusz Piotrowski 2020-06-10 19:23:58 +00:00
parent ee424b7351
commit f9ab72bb47
3 changed files with 79 additions and 6 deletions

View File

@ -126,12 +126,13 @@ static void usage(void);
int
main(int argc, char *argv[])
{
int c, fflag;
int c, fflag, fflagstdin;
char *temp_arg;
(void) setlocale(LC_ALL, "");
fflag = 0;
fflagstdin = 0;
inplace = NULL;
while ((c = getopt(argc, argv, "EI:ae:f:i:lnru")) != -1)
@ -157,6 +158,8 @@ main(int argc, char *argv[])
break;
case 'f':
fflag = 1;
if (strcmp(optarg, "-") == 0)
fflagstdin = 1;
add_compunit(CU_FILE, optarg);
break;
case 'i':
@ -193,6 +196,8 @@ main(int argc, char *argv[])
if (*argv)
for (; *argv; argv++)
add_file(*argv);
else if (fflagstdin)
exit(rval);
else
add_file(NULL);
process();
@ -236,9 +241,14 @@ cu_fgets(char *buf, int n, int *more)
linenum = 0;
switch (script->type) {
case CU_FILE:
if ((f = fopen(script->s, "r")) == NULL)
err(1, "%s", script->s);
fname = script->s;
if (strcmp(script->s, "-") == 0) {
f = stdin;
fname = "stdin";
} else {
if ((f = fopen(script->s, "r")) == NULL)
err(1, "%s", script->s);
fname = script->s;
}
state = ST_FILE;
goto again;
case CU_STRING:

View File

@ -31,7 +31,7 @@
.\" @(#)sed.1 8.2 (Berkeley) 12/30/93
.\" $FreeBSD$
.\"
.Dd May 19, 2020
.Dd June 10, 2020
.Dt SED 1
.Os
.Sh NAME
@ -98,6 +98,10 @@ Append the editing commands found in the file
.Ar command_file
to the list of commands.
The editing commands should each be listed on a separate line.
The commands are read from the standard input if
.Ar command_file
is
.Dq Li - .
.It Fl I Ar extension
Edit files in-place, saving backups with the specified
.Ar extension .
@ -636,7 +640,9 @@ The
.Fl E , I , a
and
.Fl i
options, the prefixing
options, the special meaning of
.Fl f Cm - ,
the prefixing
.Dq \&+
in the second member of an address range,
as well as the

View File

@ -116,11 +116,68 @@ hex_subst_body()
atf_check -o "inline:" sed 's/\xx//' d
}
atf_test_case commands_on_stdin
commands_on_stdin_head()
{
atf_set "descr" "Verify -f -"
}
commands_on_stdin_body()
{
printf "a\n" > a
printf "s/a/b/\n" > a_to_b
printf "s/b/c/\n" > b_to_c
printf "s/c/d/\n" > ./-
atf_check -o 'inline:d\n' sed -f a_to_b -f - -f ./- a < b_to_c
# Verify that nothing is printed if there are no input files provided.
printf 'i\\\nx' > insert_x
atf_check -o 'empty' sed -f - < insert_x
}
atf_test_case commands_on_stdin
commands_on_stdin_head()
{
atf_set "descr" "Verify -f -"
}
commands_on_stdin_body()
{
printf "a\n" > a
printf "s/a/b/\n" > a_to_b
printf "s/b/c/\n" > b_to_c
printf "s/c/d/\n" > ./-
atf_check -o 'inline:d\n' sed -f a_to_b -f - -f ./- a < b_to_c
# Verify that nothing is printed if there are no input files provided.
printf 'i\\\nx' > insert_x
atf_check -o 'empty' sed -f - < insert_x
}
atf_test_case commands_on_stdin
commands_on_stdin_head()
{
atf_set "descr" "Verify -f -"
}
commands_on_stdin_body()
{
printf "a\n" > a
printf "s/a/b/\n" > a_to_b
printf "s/b/c/\n" > b_to_c
printf "s/c/d/\n" > ./-
atf_check -o 'inline:d\n' sed -f a_to_b -f - -f ./- a < b_to_c
# Verify that nothing is printed if there are no input files provided.
printf 'i\\\nx' > insert_x
atf_check -o 'empty' sed -f - < insert_x
}
atf_init_test_cases()
{
atf_add_test_case inplace_command_q
atf_add_test_case inplace_hardlink_src
atf_add_test_case inplace_symlink_src
atf_add_test_case escape_subst
atf_add_test_case commands_on_stdin
atf_add_test_case commands_on_stdin
atf_add_test_case commands_on_stdin
atf_add_test_case hex_subst
}