sed: Fix -i option behavior with 'q' command.

Don't just exit when encountering the 'q' command if we edit file
inplace, and give mf_fgets() a chance to actually handle the
inplace case.

Also add a regression test.

Submitted by:	Yuri Pankov <yuripv@yuripv.net>
Approved by:	re (kib)
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D16798
This commit is contained in:
Mark Johnston 2018-08-29 17:09:03 +00:00
parent 94ec7ec758
commit b480502648
4 changed files with 31 additions and 6 deletions

View File

@ -46,6 +46,8 @@ extern int aflag, eflag, nflag;
extern const char *fname, *outfname; extern const char *fname, *outfname;
extern FILE *infile, *outfile; extern FILE *infile, *outfile;
extern int rflags; /* regex flags to use */ extern int rflags; /* regex flags to use */
extern const char *inplace;
extern int quit;
void cfclose(struct s_command *, struct s_command *); void cfclose(struct s_command *, struct s_command *);
void compile(void); void compile(void);

View File

@ -102,6 +102,7 @@ FILE *outfile; /* Current output file */
int aflag, eflag, nflag; int aflag, eflag, nflag;
int rflags = 0; int rflags = 0;
int quit = 0;
static int rval; /* Exit status */ static int rval; /* Exit status */
static int ispan; /* Whether inplace editing spans across files */ static int ispan; /* Whether inplace editing spans across files */
@ -115,7 +116,7 @@ const char *fname; /* File name. */
const char *outfname; /* Output file name */ const char *outfname; /* Output file name */
static char oldfname[PATH_MAX]; /* Old file name (for in-place editing) */ static char oldfname[PATH_MAX]; /* Old file name (for in-place editing) */
static char tmpfname[PATH_MAX]; /* Temporary file name (for in-place editing) */ static char tmpfname[PATH_MAX]; /* Temporary file name (for in-place editing) */
static const char *inplace; /* Inplace edit file extension. */ const char *inplace; /* Inplace edit file extension. */
u_long linenum; u_long linenum;
static void add_compunit(enum e_cut, char *); static void add_compunit(enum e_cut, char *);
@ -338,7 +339,7 @@ mf_fgets(SPACE *sp, enum e_spflag spflag)
} }
for (;;) { for (;;) {
if (infile != NULL && (c = getc(infile)) != EOF) { if (infile != NULL && (c = getc(infile)) != EOF && !quit) {
(void)ungetc(c, infile); (void)ungetc(c, infile);
break; break;
} }

View File

@ -210,10 +210,14 @@ process(void)
} }
break; break;
case 'q': case 'q':
if (!nflag && !pd) if (inplace == NULL) {
OUT(); if (!nflag && !pd)
flush_appends(); OUT();
exit(0); flush_appends();
exit(0);
}
quit = 1;
break;
case 'r': case 'r':
if (appendx >= appendnum) if (appendx >= appendnum)
if ((appends = realloc(appends, if ((appends = realloc(appends,

View File

@ -38,6 +38,7 @@ inplace_hardlink_src_body()
atf_check ln a b atf_check ln a b
atf_check sed -i '' -e 's,foo,bar,g' b atf_check sed -i '' -e 's,foo,bar,g' b
atf_check -o 'inline:bar\n' -s exit:0 cat b atf_check -o 'inline:bar\n' -s exit:0 cat b
atf_check -s not-exit:0 stat -q '.!'*
} }
atf_test_case inplace_symlink_src atf_test_case inplace_symlink_src
@ -50,10 +51,27 @@ inplace_symlink_src_body()
echo foo > a echo foo > a
atf_check ln -s a b atf_check ln -s a b
atf_check -e not-empty -s not-exit:0 sed -i '' -e 's,foo,bar,g' b atf_check -e not-empty -s not-exit:0 sed -i '' -e 's,foo,bar,g' b
atf_check -s not-exit:0 stat -q '.!'*
}
atf_test_case inplace_command_q
inplace_command_q_head()
{
atf_set "descr" "Verify -i works correctly with the 'q' command"
}
inplace_command_q_body()
{
printf '1\n2\n3\n' > a
atf_check -o 'inline:1\n2\n' sed '2q' a
atf_check sed -i.bak '2q' a
atf_check -o 'inline:1\n2\n' cat a
atf_check -o 'inline:1\n2\n3\n' cat a.bak
atf_check -s not-exit:0 stat -q '.!'*
} }
atf_init_test_cases() atf_init_test_cases()
{ {
atf_add_test_case inplace_command_q
atf_add_test_case inplace_hardlink_src atf_add_test_case inplace_hardlink_src
atf_add_test_case inplace_symlink_src atf_add_test_case inplace_symlink_src
} }