return rval;
}
+namespace {
+ class SettingException
+ {
+ std::string info;
+
+ public:
+ SettingException(const std::string &exc_info) : info(exc_info)
+ {
+ }
+
+ const std::string &getInfo()
+ {
+ return info;
+ }
+ };
+}
+
+
// Read a setting value
//
// In general a setting value is a single-line string. It may contain multiple parts
// encoding (the "classic" locale).
//
// Params:
+// service_name - the name of the service to which the setting applies
// i - reference to string iterator through the line
// end - iterator at end of line
// part_positions - list of <int,int> to which the position of each setting value
c = *i;
if (c == '\"') break;
if (c == '\n') {
- // TODO error here.
+ throw SettingException("Line end inside quoted string");
}
else if (c == '\\') {
// A backslash escapes the following character.
if (i != end) {
c = *i;
if (c == '\n') {
- // TODO error here.
+ throw SettingException("Line end follows backslash escape character (`\\')");
}
rval += c;
}
}
if (i == end) {
// String wasn't terminated
- // TODO error here
- break;
+ throw SettingException("Unterminated quoted string");
}
}
else if (c == '\\') {
rval += *i;
}
else {
- // TODO error here
+ throw SettingException("Backslash escape (`\\') not followed by character");
}
}
else if (isspace(c, locale::classic())) {
continue;
}
else if (c == '#') {
- // hmm... comment? Probably, though they should have put a space
- // before it really. TODO throw an exception, and document
- // that '#' for comments must be preceded by space, and in values
- // must be quoted.
- break;
+ // Possibly intended a comment; we require leading whitespace to reduce occurrence of accidental
+ // comments in setting values.
+ throw SettingException("hashmark (`#') comment must be separated from setting value by whitespace");
}
else {
if (new_part) {
}
service_file.close();
- // TODO check we actually have all the settings - type, command
+
+ if (service_type == ServiceType::PROCESS || service_type == ServiceType::BGPROCESS || service_type == ServiceType::SCRIPTED) {
+ if (command.length() == 0) {
+ throw ServiceDescriptionExc(name, "Service command not specified");
+ }
+ }
// Now replace the dummy service record with a real record:
for (auto iter = records.begin(); iter != records.end(); iter++) {
return rval;
}
+ catch (SettingException &setting_exc)
+ {
+ // Must remove the dummy service record.
+ std::remove(records.begin(), records.end(), rval);
+ delete rval;
+ throw ServiceDescriptionExc(name, setting_exc.getInfo());
+ }
catch (...) {
// Must remove the dummy service record.
std::remove(records.begin(), records.end(), rval);