--- hist.c.orig 2004-10-17 21:51:17.000000000 -0700 +++ hist.c 2004-10-17 21:49:52.000000000 -0700 @@ -2005,7 +2005,7 @@ void savehistfile(char *fn, int err, int writeflags) { - char *t, *start = NULL; + char *t, *tmpfile, *start = NULL; FILE *out; Histent he; zlong xcurhist = curhist - !!(histactive & HA_ACTIVE); @@ -2042,12 +2042,14 @@ extended_history = 1; } if (writeflags & HFILE_APPEND) { + tmpfile = NULL; out = fdopen(open(unmeta(fn), O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600), "a"); } else { - out = fdopen(open(unmeta(fn), - O_CREAT | O_WRONLY | O_TRUNC | O_NOCTTY, 0600), "w"); + tmpfile = bicat(unmeta(fn), ".new"); + unlink(tmpfile); + out = fdopen(open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600), "w"); } if (out) { for (; he && he->histnum <= xcurhist; he = down_histent(he)) { @@ -2092,6 +2094,11 @@ lasthist.text = ztrdup(start); } fclose(out); + if (tmpfile) { + if (rename(tmpfile, unmeta(fn)) < 0) + zerr("can't rename %s.new to $HISTFILE", fn, 0); + free(tmpfile); + } if (writeflags & HFILE_SKIPOLD && !(writeflags & (HFILE_FAST | HFILE_NO_REWRITE))) { @@ -2111,8 +2118,13 @@ pophiststack(); histactive = remember_histactive; } - } else if (err) - zerr("can't write history file %s", fn, 0); + } else if (err) { + if (tmpfile) { + zerr("can't write history file %s.new", fn, 0); + free(tmpfile); + } else + zerr("can't write history file %s", fn, 0); + } unlockhistfile(fn); }