PR/10266: Jason R. Thorpe: curses programs totally broken.
Re-write t_agetstr() so that it does not use realloc so userland programs don't break. We now use an internal buffer to keep track of the memory we allocate. This changes the api of t_agetstr() to take 2 fewer arguments, but there are not many programs that use it. Please note that this does not change binary compatibility with the previous t_agetstr() since the usage was: char *area, *p; *area = NULL; t_agetstr(ti, "ic", &area, &p); ... free(area); Since we don't touch the arguments and free(NULL) is a no-op, nothing breaks. Since we don't break binary compatibility there is no reason to bump the library's major number, but since we change t_agetstr() I'll bump the minor number for good measure.
This commit is contained in:
parent
0812154e48
commit
a6265aca19
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: termcap.3,v 1.21 2001/01/05 23:05:08 christos Exp $
|
||||
.\" $NetBSD: termcap.3,v 1.22 2001/11/02 18:24:20 christos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -74,7 +74,7 @@
|
|||
.Ft char *
|
||||
.Fn t_getstr "struct tinfo *info" "char *id" "char **area" "size_t *limit"
|
||||
.Ft char *
|
||||
.Fn t_agetstr "struct tinfo *info" "char *id" "char **buffer" "char **area"
|
||||
.Fn t_agetstr "struct tinfo *info" "char *id"
|
||||
.Ft int
|
||||
.Fn t_getterm "struct tinfo *info" "char **area" "size_t *limit"
|
||||
.Ft int
|
||||
|
@ -342,55 +342,11 @@ The function
|
|||
.Fn t_agetstr
|
||||
performs the same function as
|
||||
.Fn t_getstr
|
||||
except sufficient memory is first allocated to hold the desired string
|
||||
argument before adding it to the buffer. To initialise the buffer for
|
||||
except it handles memory allocation automatically. The memory that
|
||||
.Fn t_agetstr
|
||||
the first call must be done with the contents of
|
||||
.Fa buffer
|
||||
set to NULL. Subsequent calls to
|
||||
.Fn t_agetstr
|
||||
can pass
|
||||
.Fa buffer
|
||||
and
|
||||
.Fa area
|
||||
in unmodified and the requested string argument will be appended to
|
||||
the buffer after sufficient memory has been allocated. Modifying either
|
||||
.Fa buffer
|
||||
or
|
||||
.Fa area
|
||||
between calls to
|
||||
.Fn t_agetstr
|
||||
will certainly lead to the function misbehaving. When the storage
|
||||
allocated by
|
||||
.Fn t_agetstr
|
||||
is no longer required it can be freed by passing the pointer contained
|
||||
in
|
||||
.Fa buffer
|
||||
to
|
||||
.Fn free .
|
||||
If an error occurs within
|
||||
.Fn t_agetstr
|
||||
a NULL will be returned and
|
||||
.Fa buffer
|
||||
and
|
||||
.Fa area
|
||||
will remain unmodified.
|
||||
.Em NOTE
|
||||
.Fn t_agetstr
|
||||
uses
|
||||
.Fn realloc
|
||||
to reallocate the buffer memory so saving a copy of either
|
||||
.Fa buffer
|
||||
or
|
||||
.Fa area
|
||||
for use after subsequent calls to
|
||||
.Fn t_agetstr
|
||||
is likely to fail. It is best to keep offsets from
|
||||
.Fa buffer
|
||||
to the desired string and calculate pointer addresses only after all
|
||||
the calls to
|
||||
.Fn t_agetstr
|
||||
have been done.
|
||||
allocates will be freed when
|
||||
.Fn t_freent
|
||||
is called.
|
||||
.Pp
|
||||
The function
|
||||
.Fn t_getterm
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: termcap.c,v 1.39 2001/10/31 21:52:17 christos Exp $ */
|
||||
/* $NetBSD: termcap.c,v 1.40 2001/11/02 18:24:20 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1993
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: termcap.c,v 1.39 2001/10/31 21:52:17 christos Exp $");
|
||||
__RCSID("$NetBSD: termcap.c,v 1.40 2001/11/02 18:24:20 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -108,6 +108,7 @@ t_setinfo(struct tinfo **bp, const char *entry)
|
|||
(*bp)->bc = t_getstr(*bp, "bc", &cap_ptr, &limit);
|
||||
if ((*bp)->bc)
|
||||
(*bp)->bc = strdup((*bp)->bc);
|
||||
(*bp)->tbuf = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -251,6 +252,7 @@ t_getent(bp, name)
|
|||
(*bp)->bc = t_getstr(*bp, "bc", &cap_ptr, &limit);
|
||||
if ((*bp)->bc)
|
||||
(*bp)->bc = strdup((*bp)->bc);
|
||||
(*bp)->tbuf = NULL;
|
||||
}
|
||||
|
||||
return (i + 1);
|
||||
|
@ -460,39 +462,44 @@ tgetstr(id, area)
|
|||
* fix it for now is to allocate a lot -- 8K, and leak if we need to
|
||||
* realloc. This API needs to be destroyed!.
|
||||
*/
|
||||
#define BSIZE 8192
|
||||
#define BSIZE 256
|
||||
char *
|
||||
t_agetstr(struct tinfo *info, const char *id, char **bufptr, char **area)
|
||||
t_agetstr(struct tinfo *info, const char *id)
|
||||
{
|
||||
size_t new_size;
|
||||
char *new_buf;
|
||||
struct tbuf *tb;
|
||||
|
||||
_DIAGASSERT(info != NULL);
|
||||
_DIAGASSERT(id != NULL);
|
||||
_DIAGASSERT(bufptr != NULL);
|
||||
_DIAGASSERT(area != NULL);
|
||||
|
||||
t_getstr(info, id, NULL, &new_size);
|
||||
|
||||
/* either the string is empty or the capability does not exist. */
|
||||
if (new_size == 0 || new_size > BSIZE)
|
||||
if (new_size == 0)
|
||||
return NULL;
|
||||
|
||||
/* check if we have a buffer, if not malloc one and fill it in. */
|
||||
if (*bufptr == NULL) {
|
||||
if ((new_buf = (char *) malloc(BSIZE)) == NULL)
|
||||
if ((tb = info->tbuf) == NULL || (tb->eptr - tb->ptr) < new_size) {
|
||||
if (new_size < BSIZE)
|
||||
new_size = BSIZE;
|
||||
else
|
||||
new_size++;
|
||||
|
||||
if ((tb = malloc(sizeof(*info->tbuf))) == NULL)
|
||||
return NULL;
|
||||
*bufptr = new_buf;
|
||||
*area = new_buf;
|
||||
} else if (*area - *bufptr >= BSIZE - new_size) {
|
||||
char buf[BSIZE];
|
||||
char *b = buf;
|
||||
size_t len = BSIZE;
|
||||
/* Leak! */
|
||||
return strdup(t_getstr(info, id, &b, &len));
|
||||
|
||||
if ((tb->data = tb->ptr = tb->eptr = malloc(new_size)) == NULL)
|
||||
return NULL;
|
||||
|
||||
tb->eptr += new_size;
|
||||
|
||||
if (info->tbuf != NULL)
|
||||
tb->next = info->tbuf;
|
||||
else
|
||||
tb->next = NULL;
|
||||
|
||||
info->tbuf = tb;
|
||||
}
|
||||
return t_getstr(info, id, area, NULL);
|
||||
|
||||
return t_getstr(info, id, &tb->ptr, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -503,12 +510,18 @@ void
|
|||
t_freent(info)
|
||||
struct tinfo *info;
|
||||
{
|
||||
struct tbuf *tb;
|
||||
_DIAGASSERT(info != NULL);
|
||||
free(info->info);
|
||||
if (info->up != NULL)
|
||||
free(info->up);
|
||||
if (info->bc != NULL)
|
||||
free(info->bc);
|
||||
for (tb = info->tbuf; tb;) {
|
||||
tb = info->tbuf->next;
|
||||
free(info->tbuf->data);
|
||||
free(info->tbuf);
|
||||
}
|
||||
free(info);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: termcap.h,v 1.12 2000/05/28 09:58:15 blymn Exp $ */
|
||||
/* $NetBSD: termcap.h,v 1.13 2001/11/02 18:24:20 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -60,7 +60,7 @@ int t_getent __P((struct tinfo **, const char *));
|
|||
int t_getnum __P((struct tinfo *, const char *));
|
||||
int t_getflag __P((struct tinfo *, const char *));
|
||||
char *t_getstr __P((struct tinfo *, const char *, char **, size_t *));
|
||||
char *t_agetstr(struct tinfo *, const char *, char **, char **);
|
||||
char *t_agetstr(struct tinfo *, const char *);
|
||||
int t_getterm(struct tinfo *, char **, size_t *);
|
||||
int t_goto __P((struct tinfo *, const char *, int, int, char *, size_t));
|
||||
int t_puts __P((struct tinfo *, const char *, int,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: termcap_private.h,v 1.3 2001/06/13 10:46:00 wiz Exp $ */
|
||||
/* $NetBSD: termcap_private.h,v 1.4 2001/11/02 18:24:20 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998-1999 Brett Lymn
|
||||
|
@ -37,7 +37,10 @@ struct tinfo
|
|||
char *info;
|
||||
char *up; /* for use by tgoto */
|
||||
char *bc; /* for use by tgoto */
|
||||
struct tbuf { /* for use by t_agetstr() */
|
||||
struct tbuf *next; /* pointer to next area */
|
||||
char *data; /* pointer to beginning of buffer */
|
||||
char *ptr; /* current data pointer */
|
||||
char *eptr; /* pointer to the end of buffer */
|
||||
} *tbuf;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue