Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hist and fc: only run edited commands if changes are saved. #748

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
92 changes: 83 additions & 9 deletions src/cmd/ksh93/bltins/hist.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#if !SHOPT_SCRIPTONLY

static void hist_subst(const char*, int fd, char*);
static int hist_compare(int fdo, int initial_fdo);

#if 0
/* for the benefit of the dictionary generator */
Expand All @@ -42,10 +43,11 @@ int b_hist(int argc,char *argv[], Shbltin_t *context)
{
History_t *hp;
char *arg;
int flag,fdo;
Sfio_t *outfile;
char *fname;
int flag,fdo,initial_fdo;
Sfio_t *outfile,*initial_file;
char *fname,*initial_fname;
int range[2], incr, index2, indx= -1;
char ran_editor = 0; /* editor-called flag */
char *edit = 0; /* name of editor */
char *replace = 0; /* replace old=new */
int lflag = 0, nflag = 0, rflag = 0;
Expand Down Expand Up @@ -213,26 +215,50 @@ int b_hist(int argc,char *argv[], Shbltin_t *context)
errormsg(SH_DICT,ERROR_system(1),e_create,fname);
UNREACHABLE();
}
if(!(initial_fname=pathtmp(NULL,0,0,NULL)))
{
errormsg(SH_DICT,ERROR_exit(1),e_create,"");
UNREACHABLE();
}
if((initial_fdo=open(initial_fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
{
errormsg(SH_DICT,ERROR_system(1),e_create,initial_fname);
UNREACHABLE();
}
outfile= sfnew(NULL,sh.outbuff,IOBSIZE,fdo,SFIO_WRITE);
initial_file= sfnew(NULL,sh.outbuff,IOBSIZE,initial_fdo,SFIO_WRITE);
arg = "\n";
nflag++;
}
while(1)
{
if(nflag==0)
{
sfprintf(outfile,"%d\t",range[flag]);
if(lflag==0)
sfprintf(initial_file,"%d\t",range[flag]);
}
else if(lflag)
sfputc(outfile,'\t');
hist_list(sh.hist_ptr,outfile,hist_tell(sh.hist_ptr,range[flag]),0,arg);
if(lflag)
sh_sigcheck();
else
hist_list(sh.hist_ptr,initial_file,hist_tell(sh.hist_ptr,range[flag]),0,arg);
if(range[flag] == range[1-flag])
break;
range[flag] += incr;
}
if(lflag)
if(lflag==0)
{
initial_fdo = sh_chkopen(initial_fname);
unlink(initial_fname);
free(initial_fname);
}
else
return 0;
sfclose(outfile);
sfclose(initial_file);
hist_eof(hp);
arg = edit;
if(!arg && !(arg=nv_getval(sh_scoped(HISTEDIT))) && !(arg=nv_getval(sh_scoped(FCEDNOD))))
Expand All @@ -251,10 +277,9 @@ int b_hist(int argc,char *argv[], Shbltin_t *context)
com[1] = fname;
com[2] = 0;
error_info.errors = sh_eval(sh_sfeval(com),0);
ran_editor = 1;
}
fdo = sh_chkopen(fname);
unlink(fname);
free(fname);
/* don't history fc itself unless forked */
error_info.flags |= ERROR_SILENT;
if(!sh_isstate(SH_FORKED))
Expand All @@ -265,6 +290,7 @@ int b_hist(int argc,char *argv[], Shbltin_t *context)
{
hist_subst(error_info.id,fdo,replace);
sh_close(fdo);
sh_close(initial_fdo);
}
else if(error_info.errors == 0)
{
Expand All @@ -279,17 +305,34 @@ int b_hist(int argc,char *argv[], Shbltin_t *context)
errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
UNREACHABLE();
}
iop = sfnew(NULL,buff,IOBSIZE,fdo,SFIO_READ);
sh_eval(iop,1); /* this will close fdo */
hist_depth--;
if(!ran_editor)
{
iop = sfnew(NULL,buff,IOBSIZE,fdo,SFIO_READ);
sh_eval(iop,1); /* this will close fdo */
hist_depth--;
}
/* run the command post-editor only if it has been changed */
else if(hist_compare(fdo,initial_fdo))
{
fdo = sh_chkopen(fname);
iop = sfnew(NULL,buff,IOBSIZE,fdo,SFIO_READ);
sh_eval(iop,1);
hist_depth--;
}
else
sh_close(fdo);
sh_close(initial_fdo);
}
else
{
sh_close(fdo);
sh_close(initial_fdo);
if(!sh_isoption(SH_VERBOSE))
sh_offstate(SH_VERBOSE);
sh_offstate(SH_HISTORY);
}
unlink(fname);
free(fname);
return sh.exitval;
}

Expand Down Expand Up @@ -325,6 +368,37 @@ static void hist_subst(const char *command,int fd,char *replace)
sh_eval(sfopen(NULL,sp,"s"),1);
}

/*
* check that a change has occurred after viewing the temporary file
* with the full editor
*/
static int hist_compare(int fdo, int initial_fdo)
{
off_t size,initial_size;
char *string,*initial_string;
int c,d;
if((size = lseek(fdo,0,SEEK_END)) < 0 || (initial_size = lseek(initial_fdo,0,SEEK_END)) < 0)
return 1;
lseek(fdo,0,SEEK_SET);
lseek(initial_fdo,0,SEEK_SET);
c = (int)size;
d = (int)initial_size;
if(c != d)
return 1;
string = stkalloc(sh.stk,c+1);
initial_string = stkalloc(sh.stk,d+1);
if(read(fdo,string,c)!=c || read(initial_fdo,initial_string,d)!=d)
return 1;
string[c] = 0;
initial_string[c] = 0;
for(int x=0; x<=c; x++)
{
if(string[x] != initial_string[x])
return 1;
}
return 0;
}

#else

int b_hist(int argc,char *argv[], Shbltin_t *context)
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/ksh93/data/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@ const char sh_opthist[] =
"editor returns a non-zero exit status, this will suppress the "
"entry into the history list and the command re-execution. Command "
"line variable assignments and redirections affect both the \f?\f "
"command and the commands that are re-executed.]"
"command and the commands that are re-executed. If no change is "
"made in-editor, the command will not run. ]"
"[+?\afirst\a and \alast\a define the range of commands. \afirst\a and "
"\alast\a can be one of the following:]{"
"[+\anumber\a?A positive number representing a command "
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/sh.1
Original file line number Diff line number Diff line change
Expand Up @@ -6962,7 +6962,7 @@ is not set, then
.BR /bin/ed\^ )
is used as the editor.
When editing is complete, the edited command(s)
is executed if the changes have been saved.
is executed if changes have been made and saved.
If
.I last\^
is not specified,
Expand Down