Index: cmdbuf.c
===================================================================
--- cmdbuf.c.orig
+++ cmdbuf.c
@@ -14,11 +14,16 @@
  * Used only by command() and related functions.
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
 #include "less.h"
 #include "cmd.h"
 #include "charset.h"
 #if HAVE_STAT
+#include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #endif
 
 extern int sc_width;
@@ -1365,6 +1370,7 @@ init_cmdhist()
 #if CMD_HISTORY
 	struct mlist *ml = NULL;
 	char line[CMDBUF_SIZE];
+	char buf[BUFSIZ];
 	char *filename;
 	FILE *f;
 	char *p;
@@ -1376,6 +1382,7 @@ init_cmdhist()
 	free(filename);
 	if (f == NULL)
 		return;
+	setbuf(f, buf);
 	if (fgets(line, sizeof(line), f) == NULL ||
 	    strncmp(line, HISTFILE_FIRST_LINE, strlen(HISTFILE_FIRST_LINE)) != 0)
 	{
@@ -1450,8 +1457,16 @@ save_cmdhist()
 {
 #if CMD_HISTORY
 	char *filename;
+	char *tempname;
+	char buf[BUFSIZ];
 	FILE *f;
-	int modified = 0;
+	int modified = 0, fd;
+	mode_t umask_save;
+#if HAVE_STAT
+	struct stat st;
+	uid_t uid;
+	gid_t gid;
+#endif
 
 	filename = histfile_name();
 	if (filename == NULL)
@@ -1462,27 +1477,71 @@ save_cmdhist()
 	if (mlist_shell.modified)
 		modified = 1;
 #endif
-	if (!modified)
+	if (!modified) {
+		free(filename);
 		return;
-	f = fopen(filename, "w");
-	free(filename);
-	if (f == NULL)
+	}
+#if HAVE_STAT
+	/* Do not overwrite other users history files due `su' */
+	st.st_dev = st.st_ino = 0;
+	st.st_mode = 0600;
+	uid = getuid();
+	gid = getgid();
+	if ((stat(filename, &st) == 0) && (uid != 0) &&
+	   !((st.st_uid == uid) ? (st.st_mode & 0200)
+			        : ((st.st_gid == gid)
+					? (st.st_mode & 0020)
+					: (st.st_mode & 0002))))
+	{
+		free(filename);
+		return;
+	}
+#endif
+	tempname = malloc((strlen(filename)+strlen("XXXXXX"))*sizeof(char)+2);
+	if (tempname == NULL) {
+		free(filename);
+		return;
+	}
+	sprintf(tempname, "%s.XXXXXX", filename);
+	(void)mktemp(tempname);
+	if (*tempname == '\0') {
+		free(filename);
+		free(tempname);
 		return;
-#if HAVE_FCHMOD
-	/* Make history file readable only by owner. */
-	fchmod(fileno(f), 0600);
+	}
+
+	umask_save = umask(077);
+#if HAVE_STAT
+	fd = open(tempname, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, ((st.st_mode & 0777) | 0600));
+#else
+	fd = open(tempname, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600));
 #endif
+	(void)umask(umask_save);
 
-	fprintf(f, "%s\n", HISTFILE_FIRST_LINE);
+	if (fd < 0) {
+		free(filename);
+		free(tempname);
+		return;
+	}
 
+	f = fdopen(fd, "w");
+	if (f == NULL) {
+		free(filename);
+		free(tempname);
+		return;
+	}
+	setbuf(f, buf);
+	fprintf(f, "%s\n", HISTFILE_FIRST_LINE);
 	fprintf(f, "%s\n", HISTFILE_SEARCH_SECTION);
 	save_mlist(&mlist_search, f);
-
 #if SHELL_ESCAPE || PIPEC
 	fprintf(f, "%s\n", HISTFILE_SHELL_SECTION);
 	save_mlist(&mlist_shell, f);
 #endif
-
 	fclose(f);
+	if (rename(tempname, filename) < 0)
+		unlink(tempname);
+	free(filename);
+	free(tempname);
 #endif /* CMD_HISTORY */
 }
Index: configure.ac
===================================================================
--- configure.ac.orig
+++ configure.ac
@@ -251,7 +251,7 @@ AC_TRY_COMPILE([#include <sys/types.h>
 
 # Checks for library functions.
 AC_TYPE_SIGNAL
-AC_CHECK_FUNCS([fsync popen _setjmp sigprocmask sigsetmask snprintf stat system fchmod])
+AC_CHECK_FUNCS([tcdrain popen _setjmp sigprocmask sigsetmask snprintf stat system fchmod])
 
 # AC_CHECK_FUNCS may not work for inline functions, so test these separately.
 AC_MSG_CHECKING(for memcpy)
Index: defines.h.in
===================================================================
--- defines.h.in.orig
+++ defines.h.in
@@ -219,8 +219,8 @@
 /* Define HAVE_FILENO if you have the fileno() macro. */
 #undef HAVE_FILENO
 
-/* Define to 1 if you have the `fsync' function. */
-#undef HAVE_FSYNC
+/* Define to 1 if you have the `tcdrain' function. */
+#undef HAVE_TCDRAIN
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
Index: screen.c
===================================================================
--- screen.c.orig
+++ screen.c
@@ -431,8 +431,8 @@ raw_mode(on)
 		 */
 		s = save_term;
 	}
-#if HAVE_FSYNC
-	fsync(tty);
+#ifdef HAVE_TCDRAIN
+	tcdrain(tty);
 #endif
 	tcsetattr(tty, TCSADRAIN, &s);
 #if MUST_SET_LINE_DISCIPLINE
