Subject: Re: Default 'login.conf' in new installs?
To: None <current-users@netbsd.org>
From: Christian Biere <christianbiere@gmx.de>
List: current-users
Date: 10/13/2006 21:39:20
--fdj2RfSjLxBAspz7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Patrick Welche wrote:
> On Thu, Oct 12, 2006 at 09:20:40PM +0200, Christian Biere wrote:
> > Patrick Welche wrote:
> > > Which reminds me of something I was unable to do: set the environment
> > > variable PGDATESTYLE to "ISO,DMY" in login.conf...

> > setenv doesn't work?
 
> Its the fact that the value I am trying to set it to contains a comma. As
> setenv takes a comma delimited list and there seems to be no way to
> escape it, I am stuck.

Could you try the attached patch? It adds support for backslash escaping.

-- 
Christian

--fdj2RfSjLxBAspz7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="login_cap.c.udif"

--- lib/libutil/login_cap.c	20 Dec 2005 21:32:20 -0000	1.23
+++ lib/libutil/login_cap.c	13 Oct 2006 19:35:00 -0000
@@ -489,53 +489,61 @@ envset(void *envp, const char *name, con
 int
 setuserenv(login_cap_t *lc, envfunc_t senv, void *envp)
 {
-	const char *stop = ", \t";
-	int i, count;
-	char *ptr;
-	char **res;
-	char *str = login_getcapstr(lc, "setenv", NULL, NULL);
+	const char *str = login_getcapstr(lc, "setenv", NULL, NULL);
+	const char *value;
+	char *buf, *q;
 		  
 	if (str == NULL || *str == '\0')
 		return 0;
-	
-	/* count the sub-strings */
-	for (i = 1, ptr = str; *ptr; i++) {
-		ptr += strcspn(ptr, stop);
-		if (*ptr)
-			ptr++;
-	}
-
-	/* allocate ptr array and string */
-	count = i;
-	res = malloc(count * sizeof(char *) + strlen(str) + 1);
 
-	if (!res)
+	buf = malloc(strlen(str) + 1);
+	if (!buf)
 		return -1;
-	
-	ptr = (char *)(void *)res + count * sizeof(char *);
-	strcpy(ptr, str);
-
-	/* split string */
-	for (i = 0; *ptr && i < count; i++) {
-		res[i] = ptr;
-		ptr += strcspn(ptr, stop);
-		if (*ptr)
-			*ptr++ = '\0';
-	}
-	
-	res[i] = NULL;
-
-	for (i = 0; i < count && res[i]; i++) {
-		if (*res[i] != '\0') {
-			if ((ptr = strchr(res[i], '=')) != NULL)
-				*ptr++ = '\0';
-			else 
-				ptr = NULL;
-			(void)(*senv)(envp, res[i], ptr ? ptr : "", 1);
+
+	value = NULL;
+	q = buf;
+	*q = '\0';
+
+	do {
+		size_t n;
+
+		n = strcspn(str, "=\\, \t");
+		memcpy(q, str, n);
+		q += n;
+		str += n;
+
+		switch (*str) {
+		case '=':
+			if (!value) {
+				*q++ = '\0';
+				value = q;
+			} else {
+				*q++ = *str;
+			}
+			break;
+		case '\\':
+			str++;
+			if ('\0' != *str) {
+				*q++ = *str;	
+				break;
+			}
+			/* FALLTHRU */
+		case ',':
+		case ' ':
+		case '\t':
+		case '\0':
+			if ('\0' != buf[0]) {
+				*q = '\0';
+				(void)(*senv)(envp, buf, value ? value : "", 1);
+			}
+			value = NULL;
+			q = buf;
+			*q = '\0';
+			break;
 		}
-	}
-	
-	free(res);
+	} while ('\0' != *str++);
+
+	free(buf);
 	return 0;
 }
 
@@ -623,7 +631,11 @@ setusercontext(login_cap_t *lc, struct p
 		}
 
 	if (flags & LOGIN_SETENV)
-		setuserenv(lc, envset, NULL);
+		if (setuserenv(lc, envset, NULL) < 0) {
+			syslog(LOG_ERR, "setuserenv(): %m");
+			login_close(flc);
+			return (-1);
+		}
 
 	if (flags & LOGIN_SETPATH)
 		setuserpath(lc, pwd ? pwd->pw_dir : "", envset, NULL);

--fdj2RfSjLxBAspz7--