summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/tools/sss_groupadd.c34
-rw-r--r--server/tools/sss_groupdel.c34
-rw-r--r--server/tools/sss_groupmod.c47
-rw-r--r--server/tools/sss_useradd.c33
-rw-r--r--server/tools/sss_userdel.c33
-rw-r--r--server/tools/sss_usermod.c54
-rw-r--r--server/tools/tools_util.c125
-rw-r--r--server/tools/tools_util.h17
8 files changed, 289 insertions, 88 deletions
diff --git a/server/tools/sss_groupadd.c b/server/tools/sss_groupadd.c
index b7994080..05f814a7 100644
--- a/server/tools/sss_groupadd.c
+++ b/server/tools/sss_groupadd.c
@@ -158,6 +158,7 @@ int main(int argc, const char **argv)
struct tevent_req *req;
struct ops_ctx *data = NULL;
int ret = EXIT_SUCCESS;
+ const char *pc_groupname = NULL;
debug_prg_name = argv[0];
@@ -199,24 +200,43 @@ int main(int argc, const char **argv)
debug_level = pc_debug;
/* groupname is an argument, not option */
- data->name = poptGetArg(pc);
- if (data->name == NULL) {
+ pc_groupname = poptGetArg(pc);
+ if (pc_groupname == NULL) {
usage(pc, _("Specify group to add\n"));
ret = EXIT_FAILURE;
goto fini;
}
+ ret = parse_name_domain(data, pc_groupname);
+ if (ret != EOK) {
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+
data->gid = pc_gid;
- /* arguments processed, go on to actual work */
- ret = find_domain_for_id(ctx, data->gid, &dom);
+ ret = get_domain_by_id(data->ctx, data->gid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain && data->gid && data->domain != dom) {
+ ERROR("Selected domain %s conflicts with selected GID %llu\n",
+ data->domain->name, (unsigned long long int) data->gid);
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain == NULL && dom) {
+ data->domain = dom;
+ }
+
+ ret = get_domain_type(data->ctx, data->domain);
switch (ret) {
case ID_IN_LOCAL:
- data->domain = dom;
break;
case ID_IN_LEGACY_LOCAL:
- data->domain = dom;
case ID_OUTSIDE:
ret = groupadd_legacy(data);
if(ret != EOK) {
@@ -231,7 +251,7 @@ int main(int argc, const char **argv)
goto fini;
default:
- DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret));
+ DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret));
ERROR("Error looking up domain\n");
ret = EXIT_FAILURE;
goto fini;
diff --git a/server/tools/sss_groupdel.c b/server/tools/sss_groupdel.c
index a8b93578..96782084 100644
--- a/server/tools/sss_groupdel.c
+++ b/server/tools/sss_groupdel.c
@@ -147,6 +147,7 @@ int main(int argc, const char **argv)
struct tevent_req *req;
struct sss_domain_info *dom;
struct group *grp_info;
+ const char *pc_groupname = NULL;
poptContext pc = NULL;
struct poptOption long_options[] = {
@@ -195,27 +196,48 @@ int main(int argc, const char **argv)
debug_level = pc_debug;
- data->name = poptGetArg(pc);
- if(data->name == NULL) {
+ pc_groupname = poptGetArg(pc);
+ if(pc_groupname == NULL) {
usage(pc, _("Specify group to delete\n"));
ret = EXIT_FAILURE;
goto fini;
}
+ ret = parse_name_domain(data, pc_groupname);
+ if (ret != EOK) {
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+
/* arguments processed, go on to actual work */
grp_info = getgrnam(data->name);
if (grp_info) {
data->gid = grp_info->gr_gid;
}
- ret = find_domain_for_id(ctx, data->gid, &dom);
+ /* arguments processed, go on to actual work */
+ ret = get_domain_by_id(data->ctx, data->gid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain && data->gid && data->domain != dom) {
+ ERROR("Selected domain %s conflicts with selected GID %llu\n",
+ data->domain->name, (unsigned long long int) data->gid);
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain == NULL && dom) {
+ data->domain = dom;
+ }
+
+ ret = get_domain_type(data->ctx, data->domain);
switch (ret) {
case ID_IN_LOCAL:
- data->domain = dom;
break;
case ID_IN_LEGACY_LOCAL:
- data->domain = dom;
case ID_OUTSIDE:
ret = groupdel_legacy(data);
if(ret != EOK) {
@@ -232,7 +254,7 @@ int main(int argc, const char **argv)
goto fini;
default:
- DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret));
+ DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret));
ERROR("Error looking up domain\n");
ret = EXIT_FAILURE;
goto fini;
diff --git a/server/tools/sss_groupmod.c b/server/tools/sss_groupmod.c
index d6088846..5420fc03 100644
--- a/server/tools/sss_groupmod.c
+++ b/server/tools/sss_groupmod.c
@@ -261,7 +261,8 @@ static void add_to_groups_done(struct tevent_req *req)
}
static int groupmod_legacy(struct tools_ctx *tools_ctx,
- struct ops_ctx *ctx, int old_domain)
+ struct ops_ctx *ctx,
+ struct sss_domain_info *old_domain)
{
int ret = EOK;
char *command = NULL;
@@ -276,8 +277,13 @@ static int groupmod_legacy(struct tools_ctx *tools_ctx,
}
if (ctx->gid) {
- ret = find_domain_for_id(tools_ctx, ctx->gid, &dom);
- if (ret == old_domain) {
+ ret = get_domain_by_id(tools_ctx, ctx->gid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ talloc_free(command);
+ return EINVAL;
+ }
+ if (dom == old_domain) {
APPEND_PARAM(command, GROUPMOD_GID, ctx->gid);
} else {
ERROR("Changing gid only allowed inside the same domain\n");
@@ -329,6 +335,7 @@ int main(int argc, const char **argv)
int ret;
struct group *grp_info;
gid_t old_gid = 0;
+ const char *pc_groupname = NULL;
debug_prg_name = argv[0];
@@ -389,13 +396,19 @@ int main(int argc, const char **argv)
}
/* groupname is an argument without --option */
- data->name = poptGetArg(pc);
- if (data->name == NULL) {
+ pc_groupname = poptGetArg(pc);
+ if (pc_groupname == NULL) {
usage(pc, _("Specify group to modify\n"));
ret = EXIT_FAILURE;
goto fini;
}
+ ret = parse_name_domain(data, pc_groupname);
+ if (ret != EOK) {
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+
data->gid = pc_gid;
/* arguments processed, go on to actual work */
@@ -404,16 +417,30 @@ int main(int argc, const char **argv)
old_gid = grp_info->gr_gid;
}
- ret = find_domain_for_id(ctx, old_gid, &dom);
+ ret = get_domain_by_id(data->ctx, data->gid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain && data->gid && data->domain != dom) {
+ ERROR("Selected domain %s conflicts with selected GID %llu\n",
+ data->domain->name, (unsigned long long int) data->gid);
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain == NULL && dom) {
+ data->domain = dom;
+ }
+
+ ret = get_domain_type(data->ctx, data->domain);
switch (ret) {
case ID_IN_LOCAL:
- data->domain = dom;
break;
case ID_IN_LEGACY_LOCAL:
- data->domain = dom;
case ID_OUTSIDE:
- ret = groupmod_legacy(ctx, data, ret);
+ ret = groupmod_legacy(ctx, data, data->domain);
if(ret != EOK) {
ERROR("Cannot delete group from domain using the legacy tools\n");
}
@@ -426,7 +453,7 @@ int main(int argc, const char **argv)
goto fini;
default:
- DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret));
+ DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret));
ERROR("Error looking up domain\n");
ret = EXIT_FAILURE;
goto fini;
diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c
index 22698e6f..35dcee76 100644
--- a/server/tools/sss_useradd.c
+++ b/server/tools/sss_useradd.c
@@ -327,6 +327,7 @@ int main(int argc, const char **argv)
char *pc_shell = NULL;
char *basedir = NULL;
int pc_debug = 0;
+ const char *pc_username = NULL;
struct poptOption long_options[] = {
POPT_AUTOHELP
{ "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, 0, _("The debug level to run with"), NULL },
@@ -401,13 +402,19 @@ int main(int argc, const char **argv)
}
/* username is an argument without --option */
- data->name = poptGetArg(pc);
- if (data->name == NULL) {
+ pc_username = poptGetArg(pc);
+ if (pc_username == NULL) {
usage(pc, (_("Specify user to add\n")));
ret = EXIT_FAILURE;
goto fini;
}
+ ret = parse_name_domain(data, pc_username);
+ if (ret != EOK) {
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+
/* Same as shadow-utils useradd, -g can specify gid or group name */
if (pc_group != NULL) {
ret = get_gid(data, pc_group);
@@ -470,14 +477,28 @@ int main(int argc, const char **argv)
}
/* arguments processed, go on to actual work */
- ret = find_domain_for_id(ctx, data->uid, &dom);
+ ret = get_domain_by_id(data->ctx, data->uid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain && data->uid && data->domain != dom) {
+ ERROR("Selected domain %s conflicts with selected UID %llu\n",
+ data->domain->name, (unsigned long long int) data->uid);
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain == NULL && dom) {
+ data->domain = dom;
+ }
+
+ ret = get_domain_type(data->ctx, data->domain);
switch (ret) {
case ID_IN_LOCAL:
- data->domain = dom;
break;
case ID_IN_LEGACY_LOCAL:
- data->domain = dom;
case ID_OUTSIDE:
ret = useradd_legacy(data, groups);
if(ret != EOK) {
@@ -492,7 +513,7 @@ int main(int argc, const char **argv)
goto fini;
default:
- DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret));
+ DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret));
ERROR("Error looking up domain\n");
ret = EXIT_FAILURE;
goto fini;
diff --git a/server/tools/sss_userdel.c b/server/tools/sss_userdel.c
index f7cb7571..be35b4fa 100644
--- a/server/tools/sss_userdel.c
+++ b/server/tools/sss_userdel.c
@@ -147,6 +147,7 @@ int main(int argc, const char **argv)
struct tevent_req *req;
struct sss_domain_info *dom;
struct passwd *pwd_info;
+ const char *pc_username = NULL;
int pc_debug = 0;
poptContext pc = NULL;
@@ -196,27 +197,47 @@ int main(int argc, const char **argv)
debug_level = pc_debug;
- data->name = poptGetArg(pc);
- if (data->name == NULL) {
+ pc_username = poptGetArg(pc);
+ if (pc_username == NULL) {
usage(pc, _("Specify user to delete\n"));
ret = EXIT_FAILURE;
goto fini;
}
+ ret = parse_name_domain(data, pc_username);
+ if (ret != EOK) {
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+
/* arguments processed, go on to actual work */
pwd_info = getpwnam(data->name);
if (pwd_info) {
data->uid = pwd_info->pw_uid;
}
- ret = find_domain_for_id(ctx, data->uid, &dom);
+ ret = get_domain_by_id(data->ctx, data->uid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain && data->uid && data->domain != dom) {
+ ERROR("Selected domain %s conflicts with selected UID %llu\n",
+ data->domain->name, (unsigned long long int) data->uid);
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain == NULL && dom) {
+ data->domain = dom;
+ }
+
+ ret = get_domain_type(data->ctx, data->domain);
switch (ret) {
case ID_IN_LOCAL:
- data->domain = dom;
break;
case ID_IN_LEGACY_LOCAL:
- data->domain = dom;
case ID_OUTSIDE:
ret = userdel_legacy(data);
if(ret != EOK) {
@@ -233,7 +254,7 @@ int main(int argc, const char **argv)
goto fini;
default:
- DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret));
+ DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret));
ERROR("Error looking up domain\n");
ret = EXIT_FAILURE;
goto fini;
diff --git a/server/tools/sss_usermod.c b/server/tools/sss_usermod.c
index ca6463fa..0e1055dd 100644
--- a/server/tools/sss_usermod.c
+++ b/server/tools/sss_usermod.c
@@ -289,7 +289,8 @@ static void add_to_groups_done(struct tevent_req *req)
static int usermod_legacy(struct tools_ctx *tools_ctx, struct ops_ctx *ctx,
uid_t uid, gid_t gid,
const char *gecos, const char *home,
- const char *shell, int lock, int old_domain)
+ const char *shell, int lock,
+ struct sss_domain_info *old_domain)
{
int ret = EOK;
char *command = NULL;
@@ -298,8 +299,13 @@ static int usermod_legacy(struct tools_ctx *tools_ctx, struct ops_ctx *ctx,
APPEND_STRING(command, USERMOD);
if (uid) {
- ret = find_domain_for_id(tools_ctx, uid, &dom);
- if (ret == old_domain) {
+ ret = get_domain_by_id(tools_ctx, ctx->gid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ talloc_free(command);
+ return EINVAL;
+ }
+ if (dom == old_domain) {
APPEND_PARAM(command, USERMOD_UID, uid);
} else {
ERROR("Changing uid only allowed inside the same domain\n");
@@ -309,8 +315,13 @@ static int usermod_legacy(struct tools_ctx *tools_ctx, struct ops_ctx *ctx,
}
if (gid) {
- ret = find_domain_for_id(tools_ctx, gid, &dom);
- if (ret == old_domain) {
+ ret = get_domain_by_id(tools_ctx, ctx->gid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ talloc_free(command);
+ return EINVAL;
+ }
+ if (dom == old_domain) {
APPEND_PARAM(command, USERMOD_GID, gid);
} else {
ERROR("Changing gid only allowed inside the same domain\n");
@@ -381,6 +392,7 @@ int main(int argc, const char **argv)
int ret;
struct passwd *pwd_info;
uid_t old_uid = 0;
+ const char *pc_username = NULL;
debug_prg_name = argv[0];
@@ -452,29 +464,49 @@ int main(int argc, const char **argv)
}
/* username is an argument without --option */
- data->name = poptGetArg(pc);
- if (data->name == NULL) {
+ pc_username = poptGetArg(pc);
+ if (pc_username == NULL) {
usage(pc, _("Specify user to modify\n"));
ret = EXIT_FAILURE;
goto fini;
}
+ ret = parse_name_domain(data, pc_username);
+ if (ret != EOK) {
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+
pwd_info = getpwnam(data->name);
if (pwd_info) {
old_uid = pwd_info->pw_uid;
}
- ret = find_domain_for_id(ctx, old_uid, &dom);
+ ret = get_domain_by_id(data->ctx, data->uid, &dom);
+ if (ret != EOK) {
+ ERROR("Cannot get domain info\n");
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain && data->uid && data->domain != dom) {
+ ERROR("Selected domain %s conflicts with selected UID %llu\n",
+ data->domain->name, (unsigned long long int) data->uid);
+ ret = EXIT_FAILURE;
+ goto fini;
+ }
+ if (data->domain == NULL && dom) {
+ data->domain = dom;
+ }
+
+ ret = get_domain_type(data->ctx, data->domain);
switch (ret) {
case ID_IN_LOCAL:
- data->domain = dom;
break;
case ID_IN_LEGACY_LOCAL:
- data->domain = dom;
case ID_OUTSIDE:
ret = usermod_legacy(ctx, data, pc_uid, pc_gid, pc_gecos,
- pc_home, pc_shell, pc_lock, ret);
+ pc_home, pc_shell, pc_lock, data->domain);
if(ret != EOK) {
ERROR("Cannot delete user from domain using the legacy tools\n");
}
diff --git a/server/tools/tools_util.c b/server/tools/tools_util.c
index b580300b..1e0e91de 100644
--- a/server/tools/tools_util.c
+++ b/server/tools/tools_util.c
@@ -69,52 +69,61 @@ static int is_domain_local_legacy(struct tools_ctx *ctx, struct sss_domain_info
return -1;
}
-enum id_domain find_domain_for_id(struct tools_ctx *ctx,
- uint32_t id,
- struct sss_domain_info **dom_ret)
+enum id_domain get_domain_type(struct tools_ctx *ctx,
+ struct sss_domain_info *dom)
+{
+ if (dom == NULL) {
+ return ID_OUTSIDE;
+ }
+
+ if (strcasecmp(dom->provider, "local") == 0) {
+ return ID_IN_LOCAL;
+ } else if (is_domain_local_legacy(ctx, dom) == 0) {
+ return ID_IN_LEGACY_LOCAL;
+ }
+
+ return ID_IN_OTHER;
+}
+
+static struct sss_domain_info *get_local_domain(struct tools_ctx *ctx)
{
struct sss_domain_info *dom = NULL;
- if (id) {
- /* ID specified, find which domain it's in */
- for (dom = ctx->domains; dom; dom = dom->next) {
- if (id < dom->id_min || id > dom->id_max) {
- continue;
- } else {
- if (strcasecmp(dom->provider, "local") == 0) {
- *dom_ret = dom;
- return ID_IN_LOCAL;
- } else if (is_domain_local_legacy(ctx, dom) == 0) {
- *dom_ret = dom;
- return ID_IN_LEGACY_LOCAL;
- } else {
- *dom_ret = dom;
- return ID_IN_OTHER;
- }
- }
- }
- if (dom == NULL) {
- *dom_ret = NULL;
- return ID_OUTSIDE;
+ /* No ID specified, find LOCAL */
+ for (dom = ctx->domains; dom; dom = dom->next) {
+ if (strcasecmp(dom->provider, "local") == 0) {
+ break;
}
- } else {
- /* No ID specified, find LOCAL */
+ }
+
+ return dom;
+}
+
+int get_domain_by_id(struct tools_ctx *ctx,
+ uint32_t id,
+ struct sss_domain_info **_dom)
+{
+ struct sss_domain_info *dom = NULL;
+ int ret = EOK;
+
+ if (id) {
for (dom = ctx->domains; dom; dom = dom->next) {
- if (strcasecmp(dom->provider, "local") == 0) {
- *dom_ret = dom;
- return ID_IN_LOCAL;
+ if (id >= dom->id_min && id <= dom->id_max) {
+ break;
}
}
+ }
+
+ if (dom == NULL && id == 0) {
+ dom = get_local_domain(ctx);
if (dom == NULL) {
- DEBUG(1, ("Could not get LOCAL domain info\n"));
- *dom_ret = dom;
- return ID_ERROR;
+ DEBUG(1, ("Cannot find local domain info\n"));
+ ret = ENOENT;
}
}
- /* We should never end up here */
- *dom_ret = NULL;
- return ID_ERROR;
+ *_dom = dom;
+ return ret;
}
int setup_db(struct tools_ctx **tools_ctx)
@@ -229,6 +238,40 @@ int parse_groups(TALLOC_CTX *mem_ctx, const char *optstr, char ***_out)
return EOK;
}
+int parse_name_domain(struct ops_ctx *octx,
+ const char *fullname)
+{
+ int ret;
+ char *domain = NULL;
+ struct sss_domain_info *dom;
+
+ ret = sss_parse_name(octx, octx->ctx->snctx, fullname, &domain, &octx->name);
+ if (ret != EOK) {
+ DEBUG(0, ("Cannot parse full name\n"));
+ return ret;
+ }
+ DEBUG(5, ("Parsed username: %s\n", octx->name));
+
+ if (domain) {
+ DEBUG(5, ("Parsed domain: %s\n", domain));
+
+ /* Got string domain name, find corresponding sss_domain_info */
+ for (dom = octx->ctx->domains; dom; dom = dom->next) {
+ if (strcasecmp(dom->name, domain) == 0) {
+ DEBUG(6, ("Found sss_domain_info for given domain name\n"));
+ octx->domain = dom;
+ break;
+ }
+ }
+ if (octx->domain == NULL) {
+ DEBUG(0, ("Invalid domain %s specified in FQDN\n", domain));
+ return EINVAL;
+ }
+ }
+
+ return EOK;
+}
+
int set_locale(void)
{
char *c;
@@ -253,18 +296,26 @@ int set_locale(void)
return EOK;
}
-int init_sss_tools(struct tools_ctx **ctx)
+int init_sss_tools(struct tools_ctx **_ctx)
{
int ret;
+ struct tools_ctx *ctx;
/* Connect to the database */
- ret = setup_db(ctx);
+ ret = setup_db(&ctx);
if (ret != EOK) {
DEBUG(1, ("Could not set up database\n"));
ret = EXIT_FAILURE;
goto fini;
}
+ ret = sss_names_init(ctx, ctx->confdb, &ctx->snctx);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not set up parsing\n"));
+ goto fini;
+ }
+
+ *_ctx = ctx;
ret = EOK;
fini:
return ret;
diff --git a/server/tools/tools_util.h b/server/tools/tools_util.h
index 5bf3b384..772ba36b 100644
--- a/server/tools/tools_util.h
+++ b/server/tools/tools_util.h
@@ -44,6 +44,7 @@ struct tools_ctx {
struct tevent_context *ev;
struct confdb_ctx *confdb;
struct sysdb_ctx *sysdb;
+ struct sss_names_ctx *snctx;
struct sss_domain_info *domains;
};
@@ -53,7 +54,7 @@ struct ops_ctx {
struct tevent_context *ev;
struct sss_domain_info *domain;
- const char *name;
+ char *name;
uid_t uid;
gid_t gid;
char *gecos;
@@ -71,7 +72,7 @@ struct ops_ctx {
bool done;
};
-int init_sss_tools(struct tools_ctx **ctx);
+int init_sss_tools(struct tools_ctx **_ctx);
int setup_db(struct tools_ctx **ctx);
@@ -79,10 +80,16 @@ void usage(poptContext pc, const char *error);
int parse_groups(TALLOC_CTX *mem_ctx, const char *optstr, char ***_out);
-enum id_domain find_domain_for_id(struct tools_ctx *ctx,
- uint32_t id,
- struct sss_domain_info **dom_ret);
+enum id_domain get_domain_type(struct tools_ctx *ctx,
+ struct sss_domain_info *dom);
+
+int get_domain_by_id(struct tools_ctx *ctx,
+ uint32_t id,
+ struct sss_domain_info **_dom);
int set_locale(void);
+int parse_name_domain(struct ops_ctx *octx,
+ const char *fullname);
+
#endif /* __TOOLS_UTIL_H__ */