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); }