* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
* Editline and history functions (and glue).
#define MAXHISTLOOPS 4 /* max recursions through fc */
#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */
History
*hist
; /* history cookie */
EditLine
*el
; /* editline cookie */
static FILE *el_in
, *el_out
;
STATIC
char *fc_replace
__P((const char *, char *, char *));
* Set history and editing status. Called whenever the status may
* have changed (figures out what to do).
#define editing (Eflag || Vflag)
out2str("sh: can't initialize history\n");
if (editing
&& !el
&& isatty(0)) { /* && isatty(2) ??? */
if (el_in
== NULL
|| el_out
== NULL
)
el
= el_init(arg0
, el_in
, el_out
);
el_set(el
, EL_HIST
, history
, hist
);
el_set(el
, EL_PROMPT
, getprompt
);
out2str("sh: can't initialize editing\n");
} else if (!editing
&& el
) {
el_set(el
, EL_EDITOR
, "vi");
el_set(el
, EL_EDITOR
, "emacs");
if (el
) { /* no editing if not interactive */
cp
= lookupvar("HISTSIZE");
if (cp
== NULL
|| *cp
== '\0' ||
(histsize
= atoi(cp
)) < 0)
history(hist
, H_EVENT
, histsize
);
* This command is provided since POSIX decided to standardize
* the Korn shell fc command. Oh well...
extern int optind
, optopt
, optreset
;
int lflg
= 0, nflg
= 0, rflg
= 0, sflg
= 0;
char *firststr
, *laststr
;
int first
, last
, direction
;
char *pat
= NULL
, *repl
; /* ksh "fc old=new" crap */
struct jmploc
*volatile savehandler
;
char editfile
[MAXPATHLEN
+ 1];
/* Avoid longjmp clobbering */
error("history not active");
error("missing history argument");
optreset
= 1; optind
= 1; /* initialize getopt */
while (not_fcnumber(argv
[optind
]) &&
(ch
= getopt(argc
, argv
, ":e:lnrs")) != EOF
)
error("option -%c expects argument", optopt
);
error("unknown option: -%c", optopt
);
argc
-= optind
, argv
+= optind
;
if (lflg
== 0 || editor
|| sflg
) {
* Catch interrupts to reset active counter and
if (setjmp(jmploc
.loc
)) {
longjmp(handler
->loc
, 1);
if (++active
> MAXHISTLOOPS
) {
error("called recursively too many times");
(editor
= bltinlookup("FCEDIT", 1)) == NULL
&&
(editor
= bltinlookup("EDITOR", 1)) == NULL
)
if (editor
[0] == '-' && editor
[1] == '\0') {
* If executing, parse [old=new] now
if (lflg
== 0 && argc
> 0 &&
((repl
= strchr(argv
[0], '=')) != NULL
)) {
* determine [first] and [last]
firststr
= lflg
? "-16" : "-1";
laststr
= lflg
? "-1" : argv
[0];
* Turn into event numbers.
first
= str_to_event(firststr
, 0);
last
= str_to_event(laststr
, 1);
* XXX - this should not depend on the event numbers
* always increasing. Add sequence numbers or offset
* to the history element in next (diskbased) release.
direction
= first
< last
? H_PREV
: H_NEXT
;
* If editing, grab a temp file.
sprintf(editfile
, "%s/_shXXXXXX", _PATH_TMP
);
if ((fd
= mkstemp(editfile
)) < 0)
error("can't create temporary file %s", editfile
);
if ((efp
= fdopen(fd
, "w")) == NULL
) {
error("can't allocate stdio buffer for temp\n");
* Loop through selected history events. If listing or executing,
* do it now. Otherwise, put into temp file and call the editor
* The history interface needs rethinking, as the following
* convolutions will demonstrate.
he
= history(hist
, H_NEXT_EVENT
, first
);
for (;he
!= NULL
; he
= history(hist
, direction
)) {
out1fmt("%5d ", he
->num
);
fc_replace(he
->str
, pat
, repl
) : (char *)he
->str
;
if (displayhist
&& hist
) {
* XXX what about recursive and
history(hist
, H_ENTER
, s
);
* At end? (if we were to loose last, we'd sure be
editcmd
= stalloc(strlen(editor
) + strlen(editfile
) + 2);
sprintf(editcmd
, "%s %s", editor
, editfile
);
evalstring(editcmd
); /* XXX - should use no JC command */
readcmdfile(editfile
); /* XXX - should read back - quick tst */
if (lflg
== 0 && active
> 0)
if (*s
== *p
&& strncmp(s
, p
, plen
) == 0) {
*p
= '\0'; /* so no more matches */
dest
= grabstackstr(dest
);
he
= history(hist
, H_FIRST
);
while (he
!= NULL
&& i
--) {
he
= history(hist
, H_NEXT
);
he
= history(hist
, H_LAST
);
he
= history(hist
, H_NEXT_EVENT
, i
);
* the notion of first and last is
* backwards to that of the history package
he
= history(hist
, last
? H_FIRST
: H_LAST
);
error("history number %s not found (internal error)",
he
= history(hist
, H_PREV_STR
, str
);
error("history pattern not found: %s", str
);