Limit history file size to 1 GiB for sanity (especially considering struct stat.sb_size is sometimes unsigned, sometimes signed, and sometimes larger than long, ugh…)
This commit is contained in:
parent
5161342b9b
commit
d158038191
104
histrap.c
104
histrap.c
|
@ -26,7 +26,7 @@
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.105 2011/02/09 13:08:25 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.106 2011/02/09 15:08:01 tg Exp $");
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* MirOS: This is the default mapping type, and need not be specified.
|
* MirOS: This is the default mapping type, and need not be specified.
|
||||||
|
@ -60,11 +60,15 @@ static int hstarted; /* set after hist_init() called */
|
||||||
static Source *hist_source;
|
static Source *hist_source;
|
||||||
|
|
||||||
#if HAVE_PERSISTENT_HISTORY
|
#if HAVE_PERSISTENT_HISTORY
|
||||||
static char *hname; /* current name of history file */
|
/* current history file: name, fd, size */
|
||||||
|
static char *hname;
|
||||||
static int histfd;
|
static int histfd;
|
||||||
static int hsize;
|
static int hsize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const char T_not_in_history[] = "not in history";
|
||||||
|
#define T_history (T_not_in_history + 7)
|
||||||
|
|
||||||
int
|
int
|
||||||
c_fc(const char **wp)
|
c_fc(const char **wp)
|
||||||
{
|
{
|
||||||
|
@ -86,6 +90,7 @@ c_fc(const char **wp)
|
||||||
while ((optc = ksh_getopt(wp, &builtin_opt,
|
while ((optc = ksh_getopt(wp, &builtin_opt,
|
||||||
"e:glnrs0,1,2,3,4,5,6,7,8,9,")) != -1)
|
"e:glnrs0,1,2,3,4,5,6,7,8,9,")) != -1)
|
||||||
switch (optc) {
|
switch (optc) {
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
p = builtin_opt.optarg;
|
p = builtin_opt.optarg;
|
||||||
if (ksh_isdash(p))
|
if (ksh_isdash(p))
|
||||||
|
@ -99,21 +104,29 @@ c_fc(const char **wp)
|
||||||
memcpy(editor + len, " $_", 4);
|
memcpy(editor + len, " $_", 4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'g': /* non-AT&T ksh */
|
|
||||||
|
/* non-AT&T ksh */
|
||||||
|
case 'g':
|
||||||
gflag = true;
|
gflag = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
lflag = true;
|
lflag = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
nflag = true;
|
nflag = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
rflag = true;
|
rflag = true;
|
||||||
break;
|
break;
|
||||||
case 's': /* POSIX version of -e - */
|
|
||||||
|
/* POSIX version of -e - */
|
||||||
|
case 's':
|
||||||
sflag = true;
|
sflag = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* kludge city - accept -num as -- -num (kind of) */
|
/* kludge city - accept -num as -- -num (kind of) */
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
@ -128,6 +141,7 @@ c_fc(const char **wp)
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
@ -185,9 +199,10 @@ c_fc(const char **wp)
|
||||||
/* can't fail if hfirst didn't fail */
|
/* can't fail if hfirst didn't fail */
|
||||||
hlast = hist_get_newest(false);
|
hlast = hist_get_newest(false);
|
||||||
} else {
|
} else {
|
||||||
/* POSIX says not an error if first/last out of bounds
|
/*
|
||||||
* when range is specified; AT&T ksh and pdksh allow out of
|
* POSIX says not an error if first/last out of bounds
|
||||||
* bounds for -l as well.
|
* when range is specified; AT&T ksh and pdksh allow out
|
||||||
|
* of bounds for -l as well.
|
||||||
*/
|
*/
|
||||||
hfirst = hist_get(first, (lflag || last) ? true : false, lflag);
|
hfirst = hist_get(first, (lflag || last) ? true : false, lflag);
|
||||||
if (!hfirst)
|
if (!hfirst)
|
||||||
|
@ -201,7 +216,8 @@ c_fc(const char **wp)
|
||||||
char **temp;
|
char **temp;
|
||||||
|
|
||||||
temp = hfirst; hfirst = hlast; hlast = temp;
|
temp = hfirst; hfirst = hlast; hlast = temp;
|
||||||
rflag = !rflag; /* POSIX */
|
/* POSIX */
|
||||||
|
rflag = !rflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* List history */
|
/* List history */
|
||||||
|
@ -273,22 +289,12 @@ c_fc(const char **wp)
|
||||||
|
|
||||||
if (stat(tf->name, &statb) < 0)
|
if (stat(tf->name, &statb) < 0)
|
||||||
n = 128;
|
n = 128;
|
||||||
else {
|
else if (statb.st_size > (1024 * 1048576)) {
|
||||||
unsigned long st_sizeUL;
|
bi_errorf("%s %s too large: %lu", T_history,
|
||||||
|
"file", (unsigned long)statb.st_size);
|
||||||
/* we pretty much assume ulong >= size_t */
|
goto errout;
|
||||||
st_sizeUL = (unsigned long)statb.st_size;
|
} else
|
||||||
if (
|
|
||||||
/* too big, truncated by the cast */
|
|
||||||
statb.st_size != (long)st_sizeUL ||
|
|
||||||
/* a few additional bytes do not fit */
|
|
||||||
notoktoadd(st_sizeUL, 1 + X_EXTRA)) {
|
|
||||||
bi_errorf(T_intovfl, st_sizeUL, '+',
|
|
||||||
1UL + X_EXTRA);
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
n = statb.st_size + 1;
|
n = statb.st_size + 1;
|
||||||
}
|
|
||||||
Xinit(xs, xp, n, hist_source->areap);
|
Xinit(xs, xp, n, hist_source->areap);
|
||||||
while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) {
|
while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) {
|
||||||
xp += n;
|
xp += n;
|
||||||
|
@ -321,8 +327,10 @@ hist_execute(char *cmd)
|
||||||
|
|
||||||
for (p = cmd; p; p = q) {
|
for (p = cmd; p; p = q) {
|
||||||
if ((q = strchr(p, '\n'))) {
|
if ((q = strchr(p, '\n'))) {
|
||||||
*q++ = '\0'; /* kill the newline */
|
/* kill the newline */
|
||||||
if (!*q) /* ignore trailing newline */
|
*q++ = '\0';
|
||||||
|
if (!*q)
|
||||||
|
/* ignore trailing newline */
|
||||||
q = NULL;
|
q = NULL;
|
||||||
}
|
}
|
||||||
histsave(&hist_source->line, p, true, true);
|
histsave(&hist_source->line, p, true, true);
|
||||||
|
@ -334,7 +342,7 @@ hist_execute(char *cmd)
|
||||||
q[-1] = '\n';
|
q[-1] = '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*-
|
||||||
* Commands are executed here instead of pushing them onto the
|
* Commands are executed here instead of pushing them onto the
|
||||||
* input 'cause POSIX says the redirection and variable assignments
|
* input 'cause POSIX says the redirection and variable assignments
|
||||||
* in
|
* in
|
||||||
|
@ -370,9 +378,11 @@ hist_replace(char **hp, const char *pat, const char *rep, bool globr)
|
||||||
any_subst = true;
|
any_subst = true;
|
||||||
len = s1 - s;
|
len = s1 - s;
|
||||||
XcheckN(xs, xp, len + rep_len);
|
XcheckN(xs, xp, len + rep_len);
|
||||||
memcpy(xp, s, len); /* first part */
|
/*; first part */
|
||||||
|
memcpy(xp, s, len);
|
||||||
xp += len;
|
xp += len;
|
||||||
memcpy(xp, rep, rep_len); /* replacement */
|
/* replacement */
|
||||||
|
memcpy(xp, rep, rep_len);
|
||||||
xp += rep_len;
|
xp += rep_len;
|
||||||
}
|
}
|
||||||
if (!any_subst) {
|
if (!any_subst) {
|
||||||
|
@ -404,14 +414,14 @@ hist_get(const char *str, bool approx, bool allow_cur)
|
||||||
if (approx)
|
if (approx)
|
||||||
hp = hist_get_oldest();
|
hp = hist_get_oldest();
|
||||||
else {
|
else {
|
||||||
bi_errorf("%s: %s", str, "not in history");
|
bi_errorf("%s: %s", str, T_not_in_history);
|
||||||
hp = NULL;
|
hp = NULL;
|
||||||
}
|
}
|
||||||
} else if ((ptrdiff_t)hp > (ptrdiff_t)histptr) {
|
} else if ((ptrdiff_t)hp > (ptrdiff_t)histptr) {
|
||||||
if (approx)
|
if (approx)
|
||||||
hp = hist_get_newest(allow_cur);
|
hp = hist_get_newest(allow_cur);
|
||||||
else {
|
else {
|
||||||
bi_errorf("%s: %s", str, "not in history");
|
bi_errorf("%s: %s", str, T_not_in_history);
|
||||||
hp = NULL;
|
hp = NULL;
|
||||||
}
|
}
|
||||||
} else if (!allow_cur && hp == histptr) {
|
} else if (!allow_cur && hp == histptr) {
|
||||||
|
@ -423,7 +433,7 @@ hist_get(const char *str, bool approx, bool allow_cur)
|
||||||
|
|
||||||
/* the -1 is to avoid the current fc command */
|
/* the -1 is to avoid the current fc command */
|
||||||
if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0)
|
if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0)
|
||||||
bi_errorf("%s: %s", str, "not in history");
|
bi_errorf("%s: %s", str, T_not_in_history);
|
||||||
else
|
else
|
||||||
hp = &history[n];
|
hp = &history[n];
|
||||||
}
|
}
|
||||||
|
@ -452,9 +462,9 @@ hist_get_oldest(void)
|
||||||
return (history);
|
return (history);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************/
|
/*
|
||||||
/* Back up over last histsave */
|
* Back up over last histsave
|
||||||
/******************************/
|
*/
|
||||||
static void
|
static void
|
||||||
histbackup(void)
|
histbackup(void)
|
||||||
{
|
{
|
||||||
|
@ -669,7 +679,8 @@ histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
|
||||||
|
|
||||||
hp = histptr;
|
hp = histptr;
|
||||||
|
|
||||||
if (++hp >= history + histsize) { /* remove oldest command */
|
if (++hp >= history + histsize) {
|
||||||
|
/* remove oldest command */
|
||||||
afree(*history, APERM);
|
afree(*history, APERM);
|
||||||
for (hp = history; hp < history + histsize - 1; hp++)
|
for (hp = history; hp < history + histsize - 1; hp++)
|
||||||
hp[0] = hp[1];
|
hp[0] = hp[1];
|
||||||
|
@ -689,7 +700,7 @@ histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
|
||||||
* if your system ain't got it - then you'll have to undef HISTORYFILE
|
* if your system ain't got it - then you'll have to undef HISTORYFILE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*-
|
||||||
* Open a history file
|
* Open a history file
|
||||||
* Format is:
|
* Format is:
|
||||||
* Bytes 1, 2:
|
* Bytes 1, 2:
|
||||||
|
@ -1116,7 +1127,8 @@ inittraps(void)
|
||||||
"Signal", i);
|
"Signal", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sigtraps[SIGEXIT_].name = "EXIT"; /* our name for signal 0 */
|
/* our name for signal 0 */
|
||||||
|
sigtraps[SIGEXIT_].name = "EXIT";
|
||||||
|
|
||||||
(void)sigemptyset(&Sigact_ign.sa_mask);
|
(void)sigemptyset(&Sigact_ign.sa_mask);
|
||||||
Sigact_ign.sa_flags = 0; /* interruptible */
|
Sigact_ign.sa_flags = 0; /* interruptible */
|
||||||
|
@ -1124,7 +1136,8 @@ inittraps(void)
|
||||||
|
|
||||||
sigtraps[SIGINT].flags |= TF_DFL_INTR | TF_TTY_INTR;
|
sigtraps[SIGINT].flags |= TF_DFL_INTR | TF_TTY_INTR;
|
||||||
sigtraps[SIGQUIT].flags |= TF_DFL_INTR | TF_TTY_INTR;
|
sigtraps[SIGQUIT].flags |= TF_DFL_INTR | TF_TTY_INTR;
|
||||||
sigtraps[SIGTERM].flags |= TF_DFL_INTR; /* not fatal for interactive */
|
/* SIGTERM is not fatal for interactive */
|
||||||
|
sigtraps[SIGTERM].flags |= TF_DFL_INTR;
|
||||||
sigtraps[SIGHUP].flags |= TF_FATAL;
|
sigtraps[SIGHUP].flags |= TF_FATAL;
|
||||||
sigtraps[SIGCHLD].flags |= TF_SHELL_USES;
|
sigtraps[SIGCHLD].flags |= TF_SHELL_USES;
|
||||||
|
|
||||||
|
@ -1318,7 +1331,8 @@ runtrap(Trap *p, bool is_last)
|
||||||
if (trapstr[0] == '\0')
|
if (trapstr[0] == '\0')
|
||||||
/* SIG_IGN */
|
/* SIG_IGN */
|
||||||
goto donetrap;
|
goto donetrap;
|
||||||
if (i == SIGEXIT_ || i == SIGERR_) { /* avoid recursion on these */
|
if (i == SIGEXIT_ || i == SIGERR_) {
|
||||||
|
/* avoid recursion on these */
|
||||||
old_changed = p->flags & TF_CHANGED;
|
old_changed = p->flags & TF_CHANGED;
|
||||||
p->flags &= ~TF_CHANGED;
|
p->flags &= ~TF_CHANGED;
|
||||||
p->trap = NULL;
|
p->trap = NULL;
|
||||||
|
@ -1384,7 +1398,8 @@ settrap(Trap *p, const char *s)
|
||||||
|
|
||||||
if (p->trap)
|
if (p->trap)
|
||||||
afree(p->trap, APERM);
|
afree(p->trap, APERM);
|
||||||
strdupx(p->trap, s, APERM); /* handles s == 0 */
|
/* handles s == NULL */
|
||||||
|
strdupx(p->trap, s, APERM);
|
||||||
p->flags |= TF_CHANGED;
|
p->flags |= TF_CHANGED;
|
||||||
f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN;
|
f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN;
|
||||||
|
|
||||||
|
@ -1428,7 +1443,8 @@ block_pipe(void)
|
||||||
restore_dfl = 1;
|
restore_dfl = 1;
|
||||||
} else if (p->cursig == SIG_DFL) {
|
} else if (p->cursig == SIG_DFL) {
|
||||||
setsig(p, SIG_IGN, SS_RESTORE_CURR);
|
setsig(p, SIG_IGN, SS_RESTORE_CURR);
|
||||||
restore_dfl = 1; /* restore to SIG_DFL */
|
/* restore to SIG_DFL */
|
||||||
|
restore_dfl = 1;
|
||||||
}
|
}
|
||||||
return (restore_dfl);
|
return (restore_dfl);
|
||||||
}
|
}
|
||||||
|
@ -1491,7 +1507,8 @@ setsig(Trap *p, sig_t f, int flags)
|
||||||
if (p->cursig != f) {
|
if (p->cursig != f) {
|
||||||
p->cursig = f;
|
p->cursig = f;
|
||||||
(void)sigemptyset(&sigact.sa_mask);
|
(void)sigemptyset(&sigact.sa_mask);
|
||||||
sigact.sa_flags = 0 /* interruptible */;
|
/* interruptible */
|
||||||
|
sigact.sa_flags = 0;
|
||||||
sigact.sa_handler = f;
|
sigact.sa_handler = f;
|
||||||
sigaction(p->signal, &sigact, NULL);
|
sigaction(p->signal, &sigact, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1511,7 +1528,8 @@ setexecsig(Trap *p, int restore)
|
||||||
/* restore original value for exec'd kids */
|
/* restore original value for exec'd kids */
|
||||||
p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL);
|
p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL);
|
||||||
switch (restore & SS_RESTORE_MASK) {
|
switch (restore & SS_RESTORE_MASK) {
|
||||||
case SS_RESTORE_CURR: /* leave things as they currently are */
|
case SS_RESTORE_CURR:
|
||||||
|
/* leave things as they currently are */
|
||||||
break;
|
break;
|
||||||
case SS_RESTORE_ORIG:
|
case SS_RESTORE_ORIG:
|
||||||
p->flags |= p->flags & TF_ORIG_IGN ? TF_EXEC_IGN : TF_EXEC_DFL;
|
p->flags |= p->flags & TF_ORIG_IGN ? TF_EXEC_IGN : TF_EXEC_DFL;
|
||||||
|
|
Loading…
Reference in New Issue