Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Mar 2017 02:36:51 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r315773 - head/sbin/devd
Message-ID:  <201703230236.v2N2apvX051799@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: imp
Date: Thu Mar 23 02:36:51 2017
New Revision: 315773
URL: https://svnweb.freebsd.org/changeset/base/315773

Log:
  Implement quote escaping. String values may now contain " if you
  it is preceded by \.
  
  foo="I \"like\" C++"
  
  gives the value 'I "like" C++' to the variable 'foo'. If a character
  other than " follows the \, both the \ and that character are passed
  through.
  
  Differential Revision: https://reviews.freebsd.org/D6286
  Sponsored by: Netflix

Modified:
  head/sbin/devd/devd.cc
  head/sbin/devd/devd.hh

Modified: head/sbin/devd/devd.cc
==============================================================================
--- head/sbin/devd/devd.cc	Thu Mar 23 02:33:27 2017	(r315772)
+++ head/sbin/devd/devd.cc	Thu Mar 23 02:36:51 2017	(r315773)
@@ -411,6 +411,32 @@ var_list::is_set(const string &var) cons
 	return (_vars.find(var) != _vars.end());
 }
 
+/** fix_value
+ *
+ * Removes quoted characters that have made it this far. \" are
+ * converted to ". For all other characters, both \ and following
+ * character. So the string 'fre\:\"' is translated to 'fred\:"'.
+ */
+const std::string &
+var_list::fix_value(const std::string &val) const
+{
+	char *tmp, *dst;
+	const char *src;
+	std::string *rv;
+
+	dst = tmp = new char[val.length()];
+	src = val.c_str();
+	while (*src) {
+		if (*src == '\\' && src[1] == '"')
+			src++;
+		else
+			*dst++ = *src++;
+	}
+	rv = new string(tmp);
+	delete tmp;
+	return *rv;
+}
+
 void
 var_list::set_variable(const string &var, const string &val)
 {
@@ -420,9 +446,9 @@ var_list::set_variable(const string &var
 	 * can consume excessive amounts of systime inside of connect().  Only
 	 * log when we're in -d mode.
 	 */
+	_vars[var] = fix_value(val);
 	if (no_daemon)
 		devdlog(LOG_DEBUG, "setting %s=%s\n", var.c_str(), val.c_str());
-	_vars[var] = val;
 }
 
 void
@@ -711,8 +737,13 @@ config::chop_var(char *&buffer, char *&l
 	if (*walker == '"') {
 		walker++;	// skip "
 		rhs = walker;
-		while (*walker && *walker != '"')
+		while (*walker && *walker != '"') {
+			// Skip \" ... We leave it in the string and strip the \ later.
+			// due to the super simplistic parser that we have here.
+			if (*walker == '\\' && walker[1] == '"')
+				walker++;
 			walker++;
+		}
 		if (*walker != '"')
 			return (false);
 		rhs[-2] = '\0';

Modified: head/sbin/devd/devd.hh
==============================================================================
--- head/sbin/devd/devd.hh	Thu Mar 23 02:33:27 2017	(r315772)
+++ head/sbin/devd/devd.hh	Thu Mar 23 02:36:51 2017	(r315773)
@@ -48,14 +48,17 @@ public:
 	 * no variable of %var is set, then %bogus will be returned.
 	 */
 	const std::string &get_variable(const std::string &var) const;
-	/** Is there a variable of %var set in thi stable?
+	/** Is there a variable of %var set in this table?
 	 */
 	bool is_set(const std::string &var) const;
 	/** A completely bogus string.
 	 */
 	static const std::string bogus;
 	static const std::string nothing;
+
 private:
+	const std::string &fix_value(const std::string &val) const;
+
 	std::map<std::string, std::string> _vars;
 };
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703230236.v2N2apvX051799>