summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavidn <davidn@FreeBSD.org>1997-05-11 10:25:38 +0000
committerdavidn <davidn@FreeBSD.org>1997-05-11 10:25:38 +0000
commitd8d579b282a8c7b61c3c83ff57414748052f6b88 (patch)
treed1a6de04927c57ed8cad8a8716bafcf6555d5906
parent665a2c9ba96ecde235da8598086244a85500020e (diff)
downloadFreeBSD-src-d8d579b282a8c7b61c3c83ff57414748052f6b88.zip
FreeBSD-src-d8d579b282a8c7b61c3c83ff57414748052f6b88.tar.gz
Fix memory leak caused by not freeing memory returned by cgetstr()
calls. The cost is a little more up-front memory allocation, but the effect seems minimal. Problem noticed-by: bde Added syslog at LOG_ERR when referencing an unknown gettytab entry and for other cgetent() failues (circular reference et al). To be merged into 2.2 after a few days testing.
-rw-r--r--libexec/getty/subr.c88
1 files changed, 80 insertions, 8 deletions
diff --git a/libexec/getty/subr.c b/libexec/getty/subr.c
index 270db52..84cbefb 100644
--- a/libexec/getty/subr.c
+++ b/libexec/getty/subr.c
@@ -33,7 +33,7 @@
#ifndef lint
/*static char sccsid[] = "from: @(#)subr.c 8.1 (Berkeley) 6/4/93";*/
-static char rcsid[] = "$Id$";
+static char rcsid[] = "$Id: subr.c,v 1.9 1997/02/22 14:21:40 peter Exp $";
#endif /* not lint */
/*
@@ -46,6 +46,7 @@ static char rcsid[] = "$Id$";
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/param.h>
+#include <syslog.h>
#ifdef DEBUG
#include <stdio.h>
#endif
@@ -71,31 +72,101 @@ gettable(name, buf)
register struct gettynums *np;
register struct gettyflags *fp;
long n;
+ int l;
+ char *p;
+ char *msg = NULL;
const char *dba[2];
+
+ static int firsttime = 1;
+
dba[0] = _PATH_GETTYTAB;
dba[1] = 0;
- if (cgetent(&buf, dba, name) != 0)
+ if (firsttime) {
+ /*
+ * we need to strdup() anything in the strings array
+ * initially in order to simplify things later
+ */
+ for (sp = gettystrs; sp->field; sp++)
+ if (sp->value != NULL) {
+ /* handle these ones more carefully */
+ if (sp >= &gettystrs[4] && sp <= &gettystrs[6])
+ l = 2;
+ else
+ l = strlen(sp->value) + 1;
+ if ((p = malloc(l)) != NULL) {
+ strncpy(p, sp->value, l);
+ p[l-1] = '\0';
+ }
+ /*
+ * replace, even if NULL, else we'll
+ * have problems with free()ing static mem
+ */
+ sp->value = p;
+ }
+ firsttime = 0;
+ }
+
+ switch (cgetent(&buf, (char **)dba, (char *)name)) {
+ case 1:
+ msg = "%s: couldn't resolve 'tc=' in gettytab '%s'";
+ case 0:
+ break;
+ case -1:
+ msg = "%s: unknown gettytab entry '%s'";
+ break;
+ case -2:
+ msg = "%s: retrieving gettytab entry '%s': %m";
+ break;
+ case -3:
+ msg = "%s: recursive 'tc=' reference gettytab entry '%s'";
+ break;
+ default:
+ msg = "%s: unexpected cgetent() error for entry '%s'";
+ break;
+ }
+
+ if (msg != NULL) {
+ syslog(LOG_ERR, msg, "getty", name);
return;
+ }
+
+ for (sp = gettystrs; sp->field; sp++) {
+ if ((l = cgetstr(buf, (char*)sp->field, &p)) >= 0) {
+ if (sp->value) {
+ /* prefer existing value */
+ if (strcmp(p, sp->value) != 0)
+ free(sp->value);
+ else {
+ free(p);
+ p = sp->value;
+ }
+ }
+ sp->value = p;
+ } else if (l == -1) {
+ free(sp->value);
+ sp->value = NULL;
+ }
+ }
- for (sp = gettystrs; sp->field; sp++)
- cgetstr(buf, sp->field, &sp->value);
for (np = gettynums; np->field; np++) {
- if (cgetnum(buf, np->field, &n) == -1)
+ if (cgetnum(buf, (char*)np->field, &n) == -1)
np->set = 0;
else {
np->set = 1;
np->value = n;
}
}
+
for (fp = gettyflags; fp->field; fp++) {
- if (cgetcap(buf, fp->field, ':') == NULL)
+ if (cgetcap(buf, (char *)fp->field, ':') == NULL)
fp->set = 0;
else {
fp->set = 1;
fp->value = 1 ^ fp->invrt;
}
}
+
#ifdef DEBUG
printf("name=\"%s\", buf=\"%s\"\r\n", name, buf);
for (sp = gettystrs; sp->field; sp++)
@@ -117,7 +188,7 @@ gendefaults()
for (sp = gettystrs; sp->field; sp++)
if (sp->value)
- sp->defalt = sp->value;
+ sp->defalt = strdup(sp->value);
for (np = gettynums; np->field; np++)
if (np->set)
np->defalt = np->value;
@@ -137,7 +208,8 @@ setdefaults()
for (sp = gettystrs; sp->field; sp++)
if (!sp->value)
- sp->value = sp->defalt;
+ sp->value = !sp->defalt ? sp->defalt
+ : strdup(sp->defalt);
for (np = gettynums; np->field; np++)
if (!np->set)
np->value = np->defalt;
OpenPOWER on IntegriCloud