Module Name:    src
Committed By:   christos
Date:           Wed Nov 25 20:25:20 UTC 2015

Modified Files:
        src/external/bsd/nvi: Makefile.inc
        src/external/bsd/nvi/dist/cl: cl.h cl_main.c cl_screen.c cl_term.c

Log Message:
PR/50092: Rin Okuyama: Fix memory leaks in vi when resizing.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/external/bsd/nvi/Makefile.inc
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/nvi/dist/cl/cl.h
cvs rdiff -u -r1.4 -r1.5 src/external/bsd/nvi/dist/cl/cl_main.c \
    src/external/bsd/nvi/dist/cl/cl_screen.c \
    src/external/bsd/nvi/dist/cl/cl_term.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/bsd/nvi/Makefile.inc
diff -u src/external/bsd/nvi/Makefile.inc:1.1 src/external/bsd/nvi/Makefile.inc:1.2
--- src/external/bsd/nvi/Makefile.inc:1.1	Fri Nov 22 11:00:45 2013
+++ src/external/bsd/nvi/Makefile.inc	Wed Nov 25 15:25:20 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.inc,v 1.1 2013/11/22 16:00:45 christos Exp $
+#	$NetBSD: Makefile.inc,v 1.2 2015/11/25 20:25:20 christos Exp $
 
 .include <bsd.own.mk>
 
@@ -7,4 +7,4 @@ DIST= ${NETBSDSRCDIR}/external/bsd/nvi/d
 BINDIR=/usr/bin
 
 CWARNFLAGS.clang+=	-Wno-error=unused-const-variable
-VERSION=1.81.6-2013-11-20
+VERSION=1.81.6-2013-11-20nb1

Index: src/external/bsd/nvi/dist/cl/cl.h
diff -u src/external/bsd/nvi/dist/cl/cl.h:1.2 src/external/bsd/nvi/dist/cl/cl.h:1.3
--- src/external/bsd/nvi/dist/cl/cl.h:1.2	Fri Nov 22 10:52:05 2013
+++ src/external/bsd/nvi/dist/cl/cl.h	Wed Nov 25 15:25:20 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cl.h,v 1.2 2013/11/22 15:52:05 christos Exp $ */
+/*	$NetBSD: cl.h,v 1.3 2015/11/25 20:25:20 christos Exp $ */
 /*-
  * Copyright (c) 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -42,6 +42,8 @@ typedef struct _cl_private {
 	struct termios ex_enter;/* Terminal values to enter ex. */
 	struct termios vi_enter;/* Terminal values to enter vi. */
 
+	SCREEN	*screen;	/* Curses screen. */
+
 	char	*el;		/* Clear to EOL terminal string. */
 	char	*cup;		/* Cursor movement terminal string. */
 	char	*cuu1;		/* Cursor up terminal string. */
@@ -77,6 +79,8 @@ typedef struct _cl_private {
 #define	CL_SIGTERM	0x0100	/* SIGTERM arrived. */
 #define	CL_SIGWINCH	0x0200	/* SIGWINCH arrived. */
 #define	CL_STDIN_TTY	0x0400	/* Talking to a terminal. */
+#define	CL_SETUPTERM	0x0800	/* Terminal initialized. */
+#define	CL_CHANGE_TERM	0x1000	/* Terminal changed. */
 	u_int32_t flags;
 } CL_PRIVATE;
 

Index: src/external/bsd/nvi/dist/cl/cl_main.c
diff -u src/external/bsd/nvi/dist/cl/cl_main.c:1.4 src/external/bsd/nvi/dist/cl/cl_main.c:1.5
--- src/external/bsd/nvi/dist/cl/cl_main.c:1.4	Sun Jan 26 16:43:45 2014
+++ src/external/bsd/nvi/dist/cl/cl_main.c	Wed Nov 25 15:25:20 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cl_main.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
+/*	$NetBSD: cl_main.c,v 1.5 2015/11/25 20:25:20 christos Exp $ */
 /*-
  * Copyright (c) 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -16,7 +16,7 @@
 static const char sccsid[] = "Id: cl_main.c,v 10.54 2001/07/29 19:07:27 skimo Exp  (Berkeley) Date: 2001/07/29 19:07:27 ";
 #endif /* not lint */
 #else
-__RCSID("$NetBSD: cl_main.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
+__RCSID("$NetBSD: cl_main.c,v 1.5 2015/11/25 20:25:20 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -109,6 +109,7 @@ main(int argc, char **argv)
 		ttype = "unknown";
 	}
 	term_init(gp->progname, ttype);
+	F_SET(clp, CL_SETUPTERM);
 
 	/* Add the terminal type to the global structure. */
 	if ((OG_D_STR(gp, GO_TERM) =
@@ -292,6 +293,22 @@ static void
 h_winch(int signo)
 {
 	GLOBAL_CLP;
+	sigset_t sigset;
+	struct timespec timeout;
+
+	/*
+	 * Some window managers continuously change the screen size of terminal
+	 * emulators, by which a lot of SIGWINCH signals are to be received. In
+	 * such a case, we only need to respond the final signal; the remaining
+	 * signals are meaningless.  Thus, we wait here up to 1/10 of a second
+	 * for a succeeding signal received.
+	 */
+	(void)sigemptyset(&sigset);
+	(void)sigaddset(&sigset, SIGWINCH);
+	timeout.tv_sec = 0;
+	timeout.tv_nsec = 100 * 1000 * 1000;
+	while (sigtimedwait(&sigset, NULL, &timeout) != -1)
+		continue;
 
 	F_SET(clp, CL_SIGWINCH);
 }
Index: src/external/bsd/nvi/dist/cl/cl_screen.c
diff -u src/external/bsd/nvi/dist/cl/cl_screen.c:1.4 src/external/bsd/nvi/dist/cl/cl_screen.c:1.5
--- src/external/bsd/nvi/dist/cl/cl_screen.c:1.4	Sun Jan 26 16:43:45 2014
+++ src/external/bsd/nvi/dist/cl/cl_screen.c	Wed Nov 25 15:25:20 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cl_screen.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
+/*	$NetBSD: cl_screen.c,v 1.5 2015/11/25 20:25:20 christos Exp $ */
 /*-
  * Copyright (c) 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -16,7 +16,7 @@
 static const char sccsid[] = "Id: cl_screen.c,v 10.56 2002/05/03 19:59:44 skimo Exp  (Berkeley) Date: 2002/05/03 19:59:44 ";
 #endif /* not lint */
 #else
-__RCSID("$NetBSD: cl_screen.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
+__RCSID("$NetBSD: cl_screen.c,v 1.5 2015/11/25 20:25:20 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -34,6 +34,10 @@ __RCSID("$NetBSD: cl_screen.c,v 1.4 2014
 #include "../common/common.h"
 #include "cl.h"
 
+#ifndef BLOCK_SIGNALS
+extern sigset_t __sigblockset;
+#endif
+
 static int	cl_ex_end __P((GS *));
 static int	cl_ex_init __P((SCR *));
 static void	cl_freecap __P((CL_PRIVATE *));
@@ -53,26 +57,38 @@ cl_screen(SCR *sp, u_int32_t flags)
 	CL_PRIVATE *clp;
 	WINDOW *win;
 	GS *gp;
+	int ret, error;
+	sigset_t oset;
 
 	gp = sp->gp;
 	clp = CLP(sp);
 	win = CLSP(sp) ? CLSP(sp) : stdscr;
 
+	ret = 0;
+
+	/*
+	 * During initialization of the screen, block signals to make sure that
+	 * curses/terminfo routines are not interrupted.
+	 */
+	error = sigprocmask(SIG_BLOCK, &__sigblockset, &oset);
+
 	/* See if the current information is incorrect. */
 	if (F_ISSET(gp, G_SRESTART)) {
 		if (CLSP(sp)) {
 		    delwin(CLSP(sp));
 		    sp->cl_private = NULL;
 		}
-		if (cl_quit(gp))
-			return (1);
+		if (cl_quit(gp)) {
+			ret = 1;
+			goto end;
+		}
 		F_CLR(gp, G_SRESTART);
 	}
 	
 	/* See if we're already in the right mode. */
 	if ((LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX)) ||
 	    (LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI)))
-		return (0);
+		goto end;
 
 	/*
 	 * Fake leaving ex mode.
@@ -109,8 +125,10 @@ cl_screen(SCR *sp, u_int32_t flags)
 
 	/* Enter the requested mode. */
 	if (LF_ISSET(SC_EX)) {
-		if (cl_ex_init(sp))
-			return (1);
+		if (cl_ex_init(sp)) {
+			ret = 1;
+			goto end;
+		}
 		F_SET(clp, CL_IN_EX | CL_SCR_EX_INIT);
 
 		/*
@@ -121,12 +139,18 @@ cl_screen(SCR *sp, u_int32_t flags)
 			tputs(tgoto(clp->cup,
 			    0, O_VAL(sp, O_LINES) - 1), 1, cl_putchar);
 	} else {
-		if (cl_vi_init(sp))
-			return (1);
+		if (cl_vi_init(sp)) {
+			ret = 1;
+			goto end;
+		}
 		F_CLR(clp, CL_IN_EX);
 		F_SET(clp, CL_SCR_VI_INIT);
 	}
-	return (0);
+end:
+	/* Unblock signals. */
+	if (error == 0)
+		(void)sigprocmask(SIG_SETMASK, &oset, NULL);
+	return ret;
 }
 
 /*
@@ -234,10 +258,14 @@ cl_vi_init(SCR *sp)
 	o_cols = getenv("COLUMNS");
 	cl_putenv(sp, "COLUMNS", NULL, (u_long)O_VAL(sp, O_COLUMNS));
 
+	/* Delete cur_term if exists. */
+	if (F_ISSET(clp, CL_SETUPTERM)) {
+		if (del_curterm(cur_term))
+			return (1);
+		F_CLR(clp, CL_SETUPTERM);
+	}
+
 	/*
-	 * We don't care about the SCREEN reference returned by newterm, we
-	 * never have more than one SCREEN at a time.
-	 *
 	 * XXX
 	 * The SunOS initscr() can't be called twice.  Don't even think about
 	 * using it.  It fails in subtle ways (e.g. select(2) on fileno(stdin)
@@ -249,7 +277,7 @@ cl_vi_init(SCR *sp)
 	 * have to specify the terminal type.
 	 */
 	errno = 0;
-	if (newterm(__UNCONST(ttype), stdout, stdin) == NULL) {
+	if ((clp->screen = newterm(__UNCONST(ttype), stdout, stdin)) == NULL) {
 		if (errno)
 			msgq(sp, M_SYSERR, "%s", ttype);
 		else
@@ -374,8 +402,6 @@ cl_vi_init(SCR *sp)
 
 fast:	/* Set the terminal modes. */
 	if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &clp->vi_enter)) {
-		if (errno == EINTR)
-			goto fast;
 		msgq(sp, M_SYSERR, "tcsetattr");
 err:		(void)cl_vi_end(sp->gp);
 		return (1);
@@ -416,6 +442,9 @@ cl_vi_end(GS *gp)
 	/* End curses window. */
 	(void)endwin();
 
+	/* Delete curses screen. */
+	delscreen(clp->screen);
+
 	/*
 	 * XXX
 	 * The screen TE sequence just got sent.  See the comment in
@@ -434,6 +463,8 @@ static int
 cl_ex_init(SCR *sp)
 {
 	CL_PRIVATE *clp;
+	int error;
+	const char *ttype;
 
 	clp = CLP(sp);
 
@@ -445,6 +476,22 @@ cl_ex_init(SCR *sp)
 	if (!F_ISSET(clp, CL_STDIN_TTY))
 		return (0);
 
+	if (F_ISSET(clp, CL_CHANGE_TERM)) {
+		if (F_ISSET(clp, CL_SETUPTERM) && del_curterm(cur_term))
+			return (1);
+		F_CLR(clp, CL_SETUPTERM | CL_CHANGE_TERM);
+	}
+
+	if (!F_ISSET(clp, CL_SETUPTERM)) {
+		/* We'll need a terminal type. */
+		if (opts_empty(sp, O_TERM, 0))
+			return (1);
+		ttype = O_STR(sp, O_TERM);
+		(void)setupterm(ttype, STDOUT_FILENO, &error);
+		if (error == 0 || error == -1)
+			return (1);
+	}
+
 	/* Get the ex termcap/terminfo strings. */
 	(void)cl_getcap(sp, "cup", &clp->cup);
 	(void)cl_getcap(sp, "smso", &clp->smso);
Index: src/external/bsd/nvi/dist/cl/cl_term.c
diff -u src/external/bsd/nvi/dist/cl/cl_term.c:1.4 src/external/bsd/nvi/dist/cl/cl_term.c:1.5
--- src/external/bsd/nvi/dist/cl/cl_term.c:1.4	Sun Jan 26 16:43:45 2014
+++ src/external/bsd/nvi/dist/cl/cl_term.c	Wed Nov 25 15:25:20 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cl_term.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
+/*	$NetBSD: cl_term.c,v 1.5 2015/11/25 20:25:20 christos Exp $ */
 /*-
  * Copyright (c) 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -16,7 +16,7 @@
 static const char sccsid[] = "Id: cl_term.c,v 10.31 2001/07/08 13:06:56 skimo Exp  (Berkeley) Date: 2001/07/08 13:06:56 ";
 #endif /* not lint */
 #else
-__RCSID("$NetBSD: cl_term.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
+__RCSID("$NetBSD: cl_term.c,v 1.5 2015/11/25 20:25:20 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -268,9 +268,12 @@ cl_optchange(SCR *sp, int opt, const cha
 	clp = CLP(sp);
 
 	switch (opt) {
+	case O_TERM:
+		if (F_ISSET(sp, SC_SCR_EX))
+			F_SET(clp, CL_CHANGE_TERM);
+		/* FALLTHROUGH */
 	case O_COLUMNS:
 	case O_LINES:
-	case O_TERM:
 		/*
 		 * Changing the columns, lines or terminal require that
 		 * we restart the screen.
@@ -417,7 +420,6 @@ cl_ssize(SCR *sp, int sigwinch, size_t *
 			*rowp = row;
 		if (colp != NULL)
 			*colp = col;
-		resizeterm(row, col);
 		return (0);
 	}
 

Reply via email to