So, fair bit of warning here, text extraction in C is pretty bad (even though scanf and it’s cousins needs to die in a fire). As for this specific usage of it, hmmm…
If I understand you correctly, the problem is that you have a space in your user/group and this is not recognized? This seems to be the failing logic:
/* Will fail on this config: create 0777 "my user" "my group"*/
static int readModeUidGid(const char *configFile, int lineNum, char *key,
const char *directive, mode_t *mode, uid_t *pUid,
gid_t *pGid)
{
char u[200], g[200];
unsigned int m;
char tmp;
int rc;
if (!strcmp("su", directive))
/* do not read <mode> for the 'su' directive */
rc = 0;
else
rc = sscanf(key, "%o %199s %199s%c", &m, u, g, &tmp);
/* We support 'key <owner> <group> notation now */
if (rc == 0) {
rc = sscanf(key, "%199s %199s%c", u, g, &tmp);
/* Simulate that we have read mode and keep the default value. */
if (rc > 0) {
m = *mode;
rc += 1;
}
}
if (rc == 4) {
message(MESS_ERROR, "%s:%d extra arguments for "
"%s\n", configFile, lineNum, directive);
return -1;
}
if (rc > 0) {
*mode = m;
}
if (rc > 1) {
if (resolveUid(u, pUid) != 0) {
message(MESS_ERROR, "%s:%d unknown user '%s'\n",
configFile, lineNum, u);
return -1;
}
}
if (rc > 2) {
if (resolveGid(g, pGid) != 0) {
message(MESS_ERROR, "%s:%d unknown group '%s'\n",
configFile, lineNum, g);
return -1;
}
}
return 0;
}
The problem here is that instead of getting owner=my owner
and group=my group
you get owner="my
and group=owner"
, yes? This in turn results in one of three error messages:
myConfig:42 extra arguments for 'create'
myConfig:42 unknown user '"my'
myConfig:42 unknown group 'user"'
Simple workaround; never, ever use whitespace in usernames or groupnames. I assume this is not an option here though.
I would recode this entire function to use a custom char-by-char parser that breaks out each component into three separate strings in this case. Something like:
char conf_mode[10] = { 0 };
char conf_user[200] = { 0 };
char conf_group[200] = { 0 };
char param = 0;
char quoted = 0;
char offset = 0;
for (i = 0; key[i] != 0; i++) {
if (key[i] == '"') {
quoted = (quoted) ? 0 : 1; // Toggle
continue; // Do not copy
}
if (key[i] == ' ' && !quoted) {
param += 1;
offset = i;
continue;
}
switch(param) {
case 0: conf_mode[i-offset] = key[i]; break;
case 1: conf_user[i-offset] = key[i]; break;
case 2: conf_group[i-offset] = key[i]; break;
default: key[i+1] = 0; break; // Exit loop, ugly version
}
}
[...]
// Put parameter sanity checks here
return 0;