#line 23 "fc.def"
#line 47 "fc.def"
#include <config.h>
#if defined (HISTORY)
#ifndef _MINIX
# include <sys/param.h>
#endif
#include "../bashtypes.h"
#include "posixstat.h"
#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <chartypes.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include <errno.h>
#include "../shell.h"
#include "../builtins.h"
#include "../flags.h"
#include "../bashhist.h"
#include "maxpath.h"
#include <readline/history.h>
#include "bashgetopt.h"
#include "common.h"
#if !defined (errno)
extern int errno;
#endif
extern int current_command_line_count;
extern int literal_history;
extern int posixly_correct;
extern int unlink __P((const char *));
extern FILE *sh_mktmpfp __P((char *, int, char **));
extern int delete_last_history __P((void));
typedef struct repl {
struct repl *next;
char *pat;
char *rep;
} REPL;
#define histline(i) (hlist[(i)]->line)
#define histdata(i) (hlist[(i)]->data)
#define FREE_RLIST() \
do { \
for (rl = rlist; rl; ) { \
REPL *r; \
r = rl->next; \
if (rl->pat) \
free (rl->pat); \
if (rl->rep) \
free (rl->rep); \
free (rl); \
rl = r; \
} \
} while (0)
static char *fc_dosubs __P((char *, REPL *));
static char *fc_gethist __P((char *, HIST_ENTRY **));
static int fc_gethnum __P((char *, HIST_ENTRY **));
static int fc_number __P((WORD_LIST *));
static void fc_replhist __P((char *));
#ifdef INCLUDE_UNUSED
static char *fc_readline __P((FILE *));
static void fc_addhist __P((char *));
#endif
#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
#if defined (STRICT_POSIX)
# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}"
#else
# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
#endif
int
fc_builtin (list)
WORD_LIST *list;
{
register int i;
register char *sep;
int numbering, reverse, listing, execute;
int histbeg, histend, last_hist, retval, opt;
FILE *stream;
REPL *rlist, *rl;
char *ename, *command, *newcom, *fcedit;
HIST_ENTRY **hlist;
char *fn;
numbering = 1;
reverse = listing = execute = 0;
ename = (char *)NULL;
reset_internal_getopt ();
lcurrent = list;
while (fc_number (loptend = lcurrent) == 0 &&
(opt = internal_getopt (list, ":e:lnrs")) != -1)
{
switch (opt)
{
case 'n':
numbering = 0;
break;
case 'l':
listing = 1;
break;
case 'r':
reverse = 1;
break;
case 's':
execute = 1;
break;
case 'e':
ename = list_optarg;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (ename && (*ename == '-') && (ename[1] == '\0'))
execute = 1;
if (execute)
{
rlist = (REPL *)NULL;
while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
{
*sep++ = '\0';
rl = (REPL *)xmalloc (sizeof (REPL));
rl->next = (REPL *)NULL;
rl->pat = savestring (list->word->word);
rl->rep = savestring (sep);
if (rlist == NULL)
rlist = rl;
else
{
rl->next = rlist;
rlist = rl;
}
list = list->next;
}
rlist = REVERSE_LIST (rlist, REPL *);
hlist = history_list ();
command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
if (command == NULL)
{
builtin_error (_("no command found"));
if (rlist)
FREE_RLIST ();
return (EXECUTION_FAILURE);
}
if (rlist)
{
newcom = fc_dosubs (command, rlist);
free (command);
FREE_RLIST ();
command = newcom;
}
fprintf (stderr, "%s\n", command);
fc_replhist (command);
return (parse_and_execute (command, "fc", SEVAL_NOHIST));
}
hlist = history_list ();
if (hlist == 0)
return (EXECUTION_SUCCESS);
for (i = 0; hlist[i]; i++);
if (listing == 0 && hist_last_line_added)
delete_last_history ();
last_hist = i - 1 - hist_last_line_added;
if (list)
{
histbeg = fc_gethnum (list->word->word, hlist);
list = list->next;
if (list)
histend = fc_gethnum (list->word->word, hlist);
else
histend = listing ? last_hist : histbeg;
}
else
{
if (listing)
{
histend = last_hist;
histbeg = histend - 16 + 1;
if (histbeg < 0)
histbeg = 0;
}
else
histbeg = histend = last_hist;
}
if ((histbeg < 0) || (histend < 0))
{
sh_erange ((char *)NULL, _("history specification"));
return (EXECUTION_FAILURE);
}
if (histend < histbeg)
{
i = histend;
histend = histbeg;
histbeg = i;
reverse = 1;
}
if (listing)
stream = stdout;
else
{
numbering = 0;
stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
if (stream == 0)
{
builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
FREE (fn);
return (EXECUTION_FAILURE);
}
}
for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
{
QUIT;
if (numbering)
fprintf (stream, "%d", i + history_base);
if (listing)
{
if (posixly_correct)
fputs ("\t", stream);
else
fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
}
fprintf (stream, "%s\n", histline (i));
}
if (listing)
return (EXECUTION_SUCCESS);
fclose (stream);
if (ename)
{
command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
sprintf (command, "%s %s", ename, fn);
}
else
{
fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
sprintf (command, "%s %s", fcedit, fn);
}
retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
if (retval != EXECUTION_SUCCESS)
{
unlink (fn);
free (fn);
return (EXECUTION_FAILURE);
}
remember_on_history = 1;
begin_unwind_frame ("fc builtin");
add_unwind_protect ((Function *)xfree, fn);
add_unwind_protect (unlink, fn);
unwind_protect_int (echo_input_at_read);
echo_input_at_read = 1;
retval = fc_execute_file (fn);
run_unwind_frame ("fc builtin");
return (retval);
}
static int
fc_number (list)
WORD_LIST *list;
{
char *s;
if (list == 0)
return 0;
s = list->word->word;
if (*s == '-')
s++;
return (legal_number (s, (intmax_t *)NULL));
}
static int
fc_gethnum (command, hlist)
char *command;
HIST_ENTRY **hlist;
{
int sign = 1, n, clen;
register int i, j;
register char *s;
for (i = 0; hlist[i]; i++);
i -= 1 + hist_last_line_added;
if (command == NULL)
return (i);
s = command;
if (s && (*s == '-'))
{
sign = -1;
s++;
}
if (s && DIGIT(*s))
{
n = atoi (s);
n *= sign;
if (n < 0)
{
n += i + 1;
return (n < 0 ? 0 : n);
}
else if (n == 0)
return (i);
else
{
n -= history_base;
return (i < n ? i : n);
}
}
clen = strlen (command);
for (j = i; j >= 0; j--)
{
if (STREQN (command, histline (j), clen))
return (j);
}
return (-1);
}
static char *
fc_gethist (command, hlist)
char *command;
HIST_ENTRY **hlist;
{
int i;
if (hlist == 0)
return ((char *)NULL);
i = fc_gethnum (command, hlist);
if (i >= 0)
return (savestring (histline (i)));
else
return ((char *)NULL);
}
#ifdef INCLUDE_UNUSED
static char *
fc_readline (stream)
FILE *stream;
{
register int c;
int line_len = 0, lindex = 0;
char *line = (char *)NULL;
while ((c = getc (stream)) != EOF)
{
if ((lindex + 2) >= line_len)
line = (char *)xrealloc (line, (line_len += 128));
if (c == '\n')
{
line[lindex++] = '\n';
line[lindex++] = '\0';
return (line);
}
else
line[lindex++] = c;
}
if (!lindex)
{
if (line)
free (line);
return ((char *)NULL);
}
if (lindex + 2 >= line_len)
line = (char *)xrealloc (line, lindex + 3);
line[lindex++] = '\n';
line[lindex++] = '\0';
return (line);
}
#endif
static char *
fc_dosubs (command, subs)
char *command;
REPL *subs;
{
register char *new, *t;
register REPL *r;
for (new = savestring (command), r = subs; r; r = r->next)
{
t = strsub (new, r->pat, r->rep, 1);
free (new);
new = t;
}
return (new);
}
static void
fc_replhist (command)
char *command;
{
int n;
if (command == 0 || *command == '\0')
return;
n = strlen (command);
if (command[n - 1] == '\n')
command[n - 1] = '\0';
if (command && *command)
{
delete_last_history ();
maybe_add_history (command);
}
}
#ifdef INCLUDE_UNUSED
static void
fc_addhist (line)
char *line;
{
register int n;
if (line == 0 || *line == 0)
return;
n = strlen (line);
if (line[n - 1] == '\n')
line[n - 1] = '\0';
if (line && *line)
maybe_add_history (line);
}
#endif
#endif