diff --git a/Build.sh b/Build.sh index e34f93f..eaf27af 100644 --- a/Build.sh +++ b/Build.sh @@ -1,5 +1,5 @@ #!/bin/sh -srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.725 2017/05/15 13:35:38 tg Exp $' +srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.726 2017/08/07 20:40:56 tg Exp $' #- # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013, 2014, 2015, 2016, 2017 @@ -2090,6 +2090,11 @@ ac_test mmap lock_fcntl 0 'for mmap and munmap' <<-'EOF' munmap(NULL, 0)); } EOF +ac_test ftruncate mmap 0 'for ftruncate' <<-'EOF' + #include + int main(void) { return (ftruncate(0, 0)); } +EOF + ac_test nice <<-'EOF' #include int main(void) { return (nice(4)); } @@ -2244,8 +2249,8 @@ EOF # other checks # fd='if to use persistent history' -ac_cache PERSISTENT_HISTORY || case $HAVE_MMAP$HAVE_FLOCK$HAVE_LOCK_FCNTL in -11*|101) fv=1 ;; +ac_cache PERSISTENT_HISTORY || case $HAVE_FTRUNCATE$HAVE_MMAP$HAVE_FLOCK$HAVE_LOCK_FCNTL in +111*|1101) fv=1 ;; esac test 1 = $fv || check_categories="$check_categories no-histfile" ac_testdone @@ -2404,7 +2409,7 @@ addsrcs '!' HAVE_STRLCPY strlcpy.c addsrcs USE_PRINTF_BUILTIN printf.c test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose" -add_cppflags -DMKSH_BUILD_R=551 +add_cppflags -DMKSH_BUILD_R=561 $e $bi$me: Finished configuration testing, now producing output.$ao diff --git a/histrap.c b/histrap.c index 79d0340..4410b84 100644 --- a/histrap.c +++ b/histrap.c @@ -27,7 +27,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.162 2017/04/29 22:04:28 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.163 2017/08/07 20:40:57 tg Exp $"); Trap sigtraps[ksh_NSIG + 1]; static struct sigaction Sigact_ign; @@ -714,26 +714,65 @@ histsave(int *lnp, const char *cmd, int svmode, bool ignoredups) #if HAVE_PERSISTENT_HISTORY static const unsigned char sprinkle[2] = { HMAGIC1, HMAGIC2 }; -#endif -void -hist_init(Source *s) +static int +hist_persist_back(int srcfd) +{ + off_t tot, mis; + ssize_t n, w; + char *buf, *cp; + int rv = 0; +#define MKSH_HS_BUFSIZ 4096 + + if ((buf = malloc_osfunc(MKSH_HS_BUFSIZ)) == NULL) + return (1); + + tot = lseek(srcfd, (off_t)0, SEEK_END); + lseek(srcfd, (off_t)0, SEEK_SET); + lseek(histfd, (off_t)0, SEEK_SET); + + mis = tot; + while (mis > 0) { + if ((n = blocking_read(srcfd, (cp = buf), + MKSH_HS_BUFSIZ)) == -1) { + if (errno == EINTR) { + intrcheck(); + continue; + } + goto copy_error; + } + mis -= n; + while (n) { + if (intrsig) + goto has_intrsig; + if ((w = write(histfd, cp, n)) != -1) { + n -= w; + cp += w; + continue; + } + if (errno == EINTR) { + has_intrsig: + intrcheck(); + continue; + } + goto copy_error; + } + } + if (ftruncate(histfd, tot)) { + copy_error: + rv = 1; + } + free_osfunc(buf); + return (rv); +} + +static void +hist_persist_init(void) { -#if HAVE_PERSISTENT_HISTORY unsigned char *base; int lines, fd; - enum { hist_init_first, hist_init_retry, hist_init_restore } hs; -#endif + enum { hist_init_first, hist_init_retry, hist_use_it } hs; - histsave(NULL, NULL, HIST_DISCARD, true); - - if (Flag(FTALKING) == 0) - return; - - hstarted = true; - hist_source = s; - -#if HAVE_PERSISTENT_HISTORY if (((hname = str_val(global("HISTFILE"))) == NULL) || !*hname) { hname = NULL; return; @@ -753,9 +792,8 @@ hist_init(Source *s) mksh_lockfd(histfd); histfsize = lseek(histfd, (off_t)0, SEEK_END); - if (histfsize > MKSH_MAXHISTFSIZE || hs == hist_init_restore) { + if (histfsize > MKSH_MAXHISTFSIZE) { /* we ignore too large files but still append to them */ - /* we also don't need to re-read after truncation */ goto hist_init_tail; } else if (histfsize > 2) { /* we have some data, check its validity */ @@ -781,6 +819,7 @@ hist_init(Source *s) if ((fd = binopen3(nhname, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) { /* just don't truncate then, meh. */ + hs = hist_use_it; goto hist_trunc_dont; } if (fstat(histfd, &sb) >= 0 && @@ -795,28 +834,26 @@ hist_init(Source *s) hp = history; while (hp < histptr) { if (!writehistline(fd, - s->line - (histptr - hp), *hp)) + hist_source->line - (histptr - hp), *hp)) goto hist_trunc_abort; ++hp; } - /* now unlock, close both, rename, rinse, repeat */ + /* now transfer back */ + if (!hist_persist_back(fd)) { + /* success! */ + hs = hist_use_it; + } + hist_trunc_abort: + /* remove temporary file */ close(fd); fd = -1; - hist_finish(); - if (rename(nhname, hname) < 0) { - hist_trunc_abort: - if (fd != -1) - close(fd); - unlink(nhname); - if (fd != -1) - goto hist_trunc_dont; - /* darn! restore histfd and pray */ - } - hs = hist_init_restore; + unlink(nhname); + /* use whatever is in the file now */ hist_trunc_dont: afree(nhname, ATEMP); - if (hs == hist_init_restore) - goto retry; + if (hs == hist_use_it) + goto hist_trunc_done; + goto hist_init_fail; } } else if (histfsize != 0) { /* negative or too small... */ @@ -840,9 +877,26 @@ hist_init(Source *s) return; } } + hist_trunc_done: histfsize = lseek(histfd, (off_t)0, SEEK_END); hist_init_tail: mksh_unlkfd(histfd); +} +#endif + +void +hist_init(Source *s) +{ + histsave(NULL, NULL, HIST_DISCARD, true); + + if (Flag(FTALKING) == 0) + return; + + hstarted = true; + hist_source = s; + +#if HAVE_PERSISTENT_HISTORY + hist_persist_init(); #endif }