s3-talloc Change TALLOC_REALLOC_ARRAY() to talloc_realloc()
[ira/wip.git] / source3 / utils / net_conf.c
index 4fffcf8a8c25403bcad33c9064c2a0b62c699bc0..0ae120669993be06ebd58a5b573add3fa36d4069 100644 (file)
  */
 
 #include "includes.h"
+#include "system/filesys.h"
 #include "utils/net.h"
+#include "lib/smbconf/smbconf.h"
+#include "lib/smbconf/smbconf_init.h"
+#include "lib/smbconf/smbconf_reg.h"
 
 /**********************************************************************
  *
  *
  **********************************************************************/
 
-static int net_conf_list_usage(int argc, const char **argv)
+static int net_conf_list_usage(struct net_context *c, int argc,
+                              const char **argv)
 {
-       d_printf("USAGE: net conf list\n");
+       d_printf("%s net conf list\n", _("Usage:"));
        return -1;
 }
 
-static int net_conf_import_usage(int argc, const char**argv)
+static int net_conf_import_usage(struct net_context *c, int argc,
+                                const char**argv)
 {
-       d_printf("USAGE: net conf import [--test|-T] <filename> "
-                "[<servicename>]\n"
-                "\t[--test|-T]    testmode - do not act, just print "
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net conf import [--test|-T] <filename> "
+                  "[<servicename>]\n"
+                  "\t[--test|-T]    testmode - do not act, just print "
                        "what would be done\n"
-                "\t<servicename>  only import service <servicename>, "
-                       "ignore the rest\n");
+                  "\t<servicename>  only import service <servicename>, "
+                       "ignore the rest\n"));
        return -1;
 }
 
-static int net_conf_listshares_usage(int argc, const char **argv)
+static int net_conf_listshares_usage(struct net_context *c, int argc,
+                                    const char **argv)
 {
-       d_printf("USAGE: net conf listshares\n");
+       d_printf("%s\nnet conf listshares\n", _("Usage:"));
        return -1;
 }
 
-static int net_conf_drop_usage(int argc, const char **argv)
+static int net_conf_drop_usage(struct net_context *c, int argc,
+                              const char **argv)
 {
-       d_printf("USAGE: net conf drop\n");
+       d_printf("%s\nnet conf drop\n", _("Usage:"));
        return -1;
 }
 
-static int net_conf_showshare_usage(int argc, const char **argv)
+static int net_conf_showshare_usage(struct net_context *c, int argc,
+                                   const char **argv)
 {
-       d_printf("USAGE: net conf showshare <sharename>\n");
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _("net conf showshare <sharename>\n"));
        return -1;
 }
 
-static int net_conf_addshare_usage(int argc, const char **argv)
+static int net_conf_addshare_usage(struct net_context *c, int argc,
+                                  const char **argv)
 {
-       d_printf("USAGE: net conf addshare <sharename> <path> "
-                "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
-                "\t<sharename>      the new share name.\n"
-                "\t<path>           the path on the filesystem to export.\n"
-                "\twriteable={y|N}  set \"writeable to \"yes\" or "
-                "\"no\" (default) on this share.\n"
-                "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
-                "\"no\" (default)   on this share.\n"
-                "\t<comment>        optional comment for the new share.\n");
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net conf addshare <sharename> <path> "
+                  "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
+                  "\t<sharename>      the new share name.\n"
+                  "\t<path>           the path on the filesystem to export.\n"
+                  "\twriteable={y|N}  set \"writeable to \"yes\" or "
+                  "\"no\" (default) on this share.\n"
+                  "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
+                  "\"no\" (default)   on this share.\n"
+                  "\t<comment>        optional comment for the new share.\n"));
        return -1;
 }
 
-static int net_conf_delshare_usage(int argc, const char **argv)
+static int net_conf_delshare_usage(struct net_context *c, int argc,
+                                  const char **argv)
 {
-       d_printf("USAGE: net conf delshare <sharename>\n");
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _("net conf delshare <sharename>\n"));
        return -1;
 }
 
-static int net_conf_setparm_usage(int argc, const char **argv)
+static int net_conf_setparm_usage(struct net_context *c, int argc,
+                                 const char **argv)
 {
-       d_printf("USAGE: net conf setparm <section> <param> <value>\n");
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net conf setparm <section> <param> <value>\n"));
        return -1;
 }
 
-static int net_conf_getparm_usage(int argc, const char **argv)
+static int net_conf_getparm_usage(struct net_context *c, int argc,
+                                 const char **argv)
 {
-       d_printf("USAGE: net conf getparm <section> <param>\n");
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net conf getparm <section> <param>\n"));
        return -1;
 }
 
-static int net_conf_delparm_usage(int argc, const char **argv)
+static int net_conf_delparm_usage(struct net_context *c, int argc,
+                                 const char **argv)
 {
-       d_printf("USAGE: net conf delparm <section> <param>\n");
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net conf delparm <section> <param>\n"));
        return -1;
 }
 
-static int net_conf_getincludes_usage(int argc, const char **argv)
+static int net_conf_getincludes_usage(struct net_context *c, int argc,
+                                     const char **argv)
 {
-       d_printf("USAGE: net conf getincludes <section>\n");
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net conf getincludes <section>\n"));
        return -1;
 }
 
-static int net_conf_setincludes_usage(int argc, const char **argv)
+static int net_conf_setincludes_usage(struct net_context *c, int argc,
+                                     const char **argv)
 {
-       d_printf("USAGE: net conf setincludes <section> [<filename>]*\n");
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net conf setincludes <section> [<filename>]*\n"));
        return -1;
 }
 
-static int net_conf_delincludes_usage(int argc, const char **argv)
+static int net_conf_delincludes_usage(struct net_context *c, int argc,
+                                     const char **argv)
 {
-       d_printf("USAGE: net conf delincludes <section>\n");
+       d_printf("%s\n%s",
+               _("Usage:"),
+               _(" net conf delincludes <section>\n"));
        return -1;
 }
 
@@ -137,77 +174,84 @@ static int net_conf_delincludes_usage(int argc, const char **argv)
 /**
  * This functions process a service previously loaded with libsmbconf.
  */
-static WERROR import_process_service(struct smbconf_ctx *conf_ctx,
-                                    const char *servicename,
-                                    const uint32_t num_params,
-                                    const char **param_names,
-                                    const char **param_values)
+static sbcErr import_process_service(struct net_context *c,
+                                    struct smbconf_ctx *conf_ctx,
+                                    struct smbconf_service *service)
 {
        uint32_t idx;
-       WERROR werr = WERR_OK;
+       sbcErr err = SBC_ERR_OK;
        uint32_t num_includes = 0;
        char **includes = NULL;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (opt_testmode) {
+       if (c->opt_testmode) {
                const char *indent = "";
-               if (servicename != NULL) {
-                       d_printf("[%s]\n", servicename);
+               if (service->name != NULL) {
+                       d_printf("[%s]\n", service->name);
                        indent = "\t";
                }
-               for (idx = 0; idx < num_params; idx++) {
-                       d_printf("%s%s = %s\n", indent, param_names[idx],
-                                param_values[idx]);
+               for (idx = 0; idx < service->num_params; idx++) {
+                       d_printf("%s%s = %s\n", indent,
+                                service->param_names[idx],
+                                service->param_values[idx]);
                }
                d_printf("\n");
                goto done;
        }
 
-       if (smbconf_share_exists(conf_ctx, servicename)) {
-               werr = smbconf_delete_share(conf_ctx, servicename);
-               if (!W_ERROR_IS_OK(werr)) {
+       if (smbconf_share_exists(conf_ctx, service->name)) {
+               err = smbconf_delete_share(conf_ctx, service->name);
+               if (!SBC_ERROR_IS_OK(err)) {
                        goto done;
                }
        }
-       werr = smbconf_create_share(conf_ctx, servicename);
-       if (!W_ERROR_IS_OK(werr)) {
+       err = smbconf_create_share(conf_ctx, service->name);
+       if (!SBC_ERROR_IS_OK(err)) {
                goto done;
        }
 
-       for (idx = 0; idx < num_params; idx ++) {
-               if (strequal(param_names[idx], "include")) {
-                       includes = TALLOC_REALLOC_ARRAY(mem_ctx,
+       for (idx = 0; idx < service->num_params; idx ++) {
+               if (strequal(service->param_names[idx], "include")) {
+                       includes = talloc_realloc(mem_ctx,
                                                        includes,
                                                        char *,
                                                        num_includes+1);
                        if (includes == NULL) {
-                               werr = WERR_NOMEM;
+                               err = SBC_ERR_NOMEM;
                                goto done;
                        }
                        includes[num_includes] = talloc_strdup(includes,
-                                                       param_values[idx]);
+                                               service->param_values[idx]);
                        if (includes[num_includes] == NULL) {
-                               werr = WERR_NOMEM;
+                               err = SBC_ERR_NOMEM;
                                goto done;
                        }
                        num_includes++;
                } else {
-                       werr = smbconf_set_parameter(conf_ctx,
-                                                    servicename,
-                                                    param_names[idx],
-                                                    param_values[idx]);
-                       if (!W_ERROR_IS_OK(werr)) {
+                       err = smbconf_set_parameter(conf_ctx,
+                                                    service->name,
+                                                    service->param_names[idx],
+                                                    service->param_values[idx]);
+                       if (!SBC_ERROR_IS_OK(err)) {
+                               d_fprintf(stderr,
+                                         _("Error in section [%s], parameter \"%s\": %s\n"),
+                                         service->name, service->param_names[idx],
+                                         sbcErrorString(err));
                                goto done;
                        }
                }
        }
 
-       werr = smbconf_set_includes(conf_ctx, servicename, num_includes,
-                                   (const char **)includes);
+       err = smbconf_set_includes(conf_ctx, service->name, num_includes,
+                                  (const char **)includes);
+       if (!SBC_ERROR_IS_OK(err)) {
+               goto done;
+       }
 
+       err = SBC_ERR_OK;
 done:
        TALLOC_FREE(mem_ctx);
-       return werr;
+       return err;
 }
 
 
@@ -217,47 +261,44 @@ done:
  *
  **********************************************************************/
 
-static int net_conf_list(struct smbconf_ctx *conf_ctx,
+static int net_conf_list(struct net_context *c, struct smbconf_ctx *conf_ctx,
                         int argc, const char **argv)
 {
-       WERROR werr = WERR_OK;
+       sbcErr err;
        int ret = -1;
        TALLOC_CTX *mem_ctx;
        uint32_t num_shares;
-       char **share_names;
-       uint32_t *num_params;
-       char ***param_names;
-       char ***param_values;
        uint32_t share_count, param_count;
+       struct smbconf_service **shares = NULL;
 
        mem_ctx = talloc_stackframe();
 
-       if (argc != 0) {
-               net_conf_list_usage(argc, argv);
+       if (argc != 0 || c->display_usage) {
+               net_conf_list_usage(c, argc, argv);
                goto done;
        }
 
-       werr = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &share_names,
-                                 &num_params, &param_names, &param_values);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error getting config: %s\n",
-                         dos_errstr(werr));
+       err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &shares);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error getting config: %s\n"),
+                         sbcErrorString(err));
                goto done;
        }
 
        for (share_count = 0; share_count < num_shares; share_count++) {
                const char *indent = "";
-               if (share_names[share_count] != NULL) {
-                       d_printf("[%s]\n", share_names[share_count]);
+               if (shares[share_count]->name != NULL) {
+                       d_printf("[%s]\n", shares[share_count]->name);
                        indent = "\t";
                }
-               for (param_count = 0; param_count < num_params[share_count];
+               for (param_count = 0;
+                    param_count < shares[share_count]->num_params;
                     param_count++)
                {
                        d_printf("%s%s = %s\n",
                                 indent,
-                                param_names[share_count][param_count],
-                                param_values[share_count][param_count]);
+                                shares[share_count]->param_names[param_count],
+                                shares[share_count]->param_values[param_count]);
                }
                d_printf("\n");
        }
@@ -269,7 +310,7 @@ done:
        return ret;
 }
 
-static int net_conf_import(struct smbconf_ctx *conf_ctx,
+static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
                           int argc, const char **argv)
 {
        int ret = -1;
@@ -278,19 +319,22 @@ static int net_conf_import(struct smbconf_ctx *conf_ctx,
        char *conf_source = NULL;
        TALLOC_CTX *mem_ctx;
        struct smbconf_ctx *txt_ctx;
-       WERROR werr;
+       sbcErr err;
+
+       if (c->display_usage)
+               return net_conf_import_usage(c, argc, argv);
 
        mem_ctx = talloc_stackframe();
 
        switch (argc) {
                case 0:
                default:
-                       net_conf_import_usage(argc, argv);
+                       net_conf_import_usage(c, argc, argv);
                        goto done;
                case 2:
-                       servicename = talloc_strdup_lower(mem_ctx, argv[1]);
+                       servicename = talloc_strdup(mem_ctx, argv[1]);
                        if (servicename == NULL) {
-                               d_printf("error: out of memory!\n");
+                               d_printf(_("error: out of memory!\n"));
                                goto done;
                        }
                case 1:
@@ -303,84 +347,128 @@ static int net_conf_import(struct smbconf_ctx *conf_ctx,
 
        conf_source = talloc_asprintf(mem_ctx, "file:%s", filename);
        if (conf_source == NULL) {
-               d_printf("error: out of memory!\n");
+               d_printf(_("error: out of memory!\n"));
                goto done;
        }
 
-       werr = smbconf_init(mem_ctx, &txt_ctx, conf_source);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_printf("error loading file '%s': %s\n", filename,
-                        dos_errstr(werr));
+       err = smbconf_init(mem_ctx, &txt_ctx, conf_source);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error loading file '%s': %s\n"), filename,
+                        sbcErrorString(err));
                goto done;
        }
 
-       if (opt_testmode) {
-               d_printf("\nTEST MODE - "
-                        "would import the following configuration:\n\n");
+       if (c->opt_testmode) {
+               d_printf(_("\nTEST MODE - "
+                        "would import the following configuration:\n\n"));
        }
 
        if (servicename != NULL) {
-               char **param_names, **param_values;
-               uint32_t num_params;
-
-               werr = smbconf_get_share(txt_ctx, mem_ctx,
-                                        servicename,
-                                        &num_params,
-                                        &param_names,
-                                        &param_values);
-               if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
+               struct smbconf_service *service = NULL;
+
+               err = smbconf_get_share(txt_ctx, mem_ctx,
+                                       servicename,
+                                       &service);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       goto cancel;
                }
-               werr = import_process_service(conf_ctx,
-                                             servicename,
-                                             num_params,
-                                             (const char **)param_names,
-                                             (const char **)param_values);
-               if (!W_ERROR_IS_OK(werr)) {
+
+               err = smbconf_transaction_start(conf_ctx);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       d_printf(_("error starting transaction: %s\n"),
+                                sbcErrorString(err));
                        goto done;
                }
+
+               err = import_process_service(c, conf_ctx, service);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       goto cancel;
+               }
        } else {
-               char **share_names, ***param_names, ***param_values;
-               uint32_t num_shares, *num_params, sidx;
+               struct smbconf_service **services = NULL;
+               uint32_t num_shares, sidx;
 
-               werr = smbconf_get_config(txt_ctx, mem_ctx,
+               err = smbconf_get_config(txt_ctx, mem_ctx,
                                          &num_shares,
-                                         &share_names,
-                                         &num_params,
-                                         &param_names,
-                                         &param_values);
-               if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
+                                         &services);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       goto cancel;
                }
-               if (!opt_testmode) {
-                       werr = smbconf_drop(conf_ctx);
-                       if (!W_ERROR_IS_OK(werr)) {
-                               goto done;
+               if (!c->opt_testmode) {
+                       if (!SBC_ERROR_IS_OK(smbconf_drop(conf_ctx))) {
+                               goto cancel;
                        }
                }
+
+               /*
+                * Wrap the importing of shares into a transaction,
+                * but only 100 at a time, in order to save memory.
+                * The allocated memory accumulates across the actions
+                * within the transaction, and for me, some 1500
+                * imported shares, the MAX_TALLOC_SIZE of 256 MB
+                * was exceeded.
+                */
+               err = smbconf_transaction_start(conf_ctx);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       d_printf(_("error starting transaction: %s\n"),
+                                sbcErrorString(err));
+                       goto done;
+               }
+
                for (sidx = 0; sidx < num_shares; sidx++) {
-                       werr = import_process_service(conf_ctx,
-                                       share_names[sidx],
-                                       num_params[sidx],
-                                       (const char **)param_names[sidx],
-                                       (const char **)param_values[sidx]);
-                       if (!W_ERROR_IS_OK(werr)) {
+                       err = import_process_service(c, conf_ctx,
+                                                    services[sidx]);
+                       if (!SBC_ERROR_IS_OK(err)) {
+                               goto cancel;
+                       }
+
+                       if (sidx % 100) {
+                               continue;
+                       }
+
+                       err = smbconf_transaction_commit(conf_ctx);
+                       if (!SBC_ERROR_IS_OK(err)) {
+                               d_printf(_("error committing transaction: "
+                                          "%s\n"),
+                                        sbcErrorString(err));
+                               goto done;
+                       }
+                       err = smbconf_transaction_start(conf_ctx);
+                       if (!SBC_ERROR_IS_OK(err)) {
+                               d_printf(_("error starting transaction: %s\n"),
+                                        sbcErrorString(err));
                                goto done;
                        }
                }
        }
 
-       ret = 0;
+       err = smbconf_transaction_commit(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error committing transaction: %s\n"),
+                        sbcErrorString(err));
+       } else {
+               ret = 0;
+       }
+
+       goto done;
+
+cancel:
+       err = smbconf_transaction_cancel(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error cancelling transaction: %s\n"),
+                        sbcErrorString(err));
+       }
 
 done:
        TALLOC_FREE(mem_ctx);
        return ret;
 }
 
-static int net_conf_listshares(struct smbconf_ctx *conf_ctx,
-                              int argc, const char **argv)
+static int net_conf_listshares(struct net_context *c,
+                              struct smbconf_ctx *conf_ctx, int argc,
+                              const char **argv)
 {
-       WERROR werr = WERR_OK;
+       sbcErr err;
        int ret = -1;
        uint32_t count, num_shares = 0;
        char **share_names = NULL;
@@ -388,14 +476,14 @@ static int net_conf_listshares(struct smbconf_ctx *conf_ctx,
 
        mem_ctx = talloc_stackframe();
 
-       if (argc != 0) {
-               net_conf_listshares_usage(argc, argv);
+       if (argc != 0 || c->display_usage) {
+               net_conf_listshares_usage(c, argc, argv);
                goto done;
        }
 
-       werr = smbconf_get_share_names(conf_ctx, mem_ctx, &num_shares,
-                                      &share_names);
-       if (!W_ERROR_IS_OK(werr)) {
+       err = smbconf_get_share_names(conf_ctx, mem_ctx, &num_shares,
+                                     &share_names);
+       if (!SBC_ERROR_IS_OK(err)) {
                goto done;
        }
 
@@ -411,21 +499,21 @@ done:
        return ret;
 }
 
-static int net_conf_drop(struct smbconf_ctx *conf_ctx,
+static int net_conf_drop(struct net_context *c, struct smbconf_ctx *conf_ctx,
                         int argc, const char **argv)
 {
        int ret = -1;
-       WERROR werr;
+       sbcErr err;
 
-       if (argc != 0) {
-               net_conf_drop_usage(argc, argv);
+       if (argc != 0 || c->display_usage) {
+               net_conf_drop_usage(c, argc, argv);
                goto done;
        }
 
-       werr = smbconf_drop(conf_ctx);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error deleting configuration: %s\n",
-                         dos_errstr(werr));
+       err = smbconf_drop(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error deleting configuration: %s\n"),
+                         sbcErrorString(err));
                goto done;
        }
 
@@ -435,44 +523,42 @@ done:
        return ret;
 }
 
-static int net_conf_showshare(struct smbconf_ctx *conf_ctx,
-                             int argc, const char **argv)
+static int net_conf_showshare(struct net_context *c,
+                             struct smbconf_ctx *conf_ctx, int argc,
+                             const char **argv)
 {
        int ret = -1;
-       WERROR werr = WERR_OK;
+       sbcErr err;
        const char *sharename = NULL;
        TALLOC_CTX *mem_ctx;
-       uint32_t num_params;
        uint32_t count;
-       char **param_names;
-       char **param_values;
+       struct smbconf_service *service = NULL;
 
        mem_ctx = talloc_stackframe();
 
-       if (argc != 1) {
-               net_conf_showshare_usage(argc, argv);
+       if (argc != 1 || c->display_usage) {
+               net_conf_showshare_usage(c, argc, argv);
                goto done;
        }
 
-       sharename = talloc_strdup_lower(mem_ctx, argv[0]);
+       sharename = talloc_strdup(mem_ctx, argv[0]);
        if (sharename == NULL) {
                d_printf("error: out of memory!\n");
                goto done;
        }
 
-       werr = smbconf_get_share(conf_ctx, mem_ctx, sharename, &num_params,
-                                &param_names, &param_values);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_printf("error getting share parameters: %s\n",
-                        dos_errstr(werr));
+       err = smbconf_get_share(conf_ctx, mem_ctx, sharename, &service);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error getting share parameters: %s\n"),
+                        sbcErrorString(err));
                goto done;
        }
 
-       d_printf("[%s]\n", sharename);
+       d_printf("[%s]\n", service->name);
 
-       for (count = 0; count < num_params; count++) {
-               d_printf("\t%s = %s\n", param_names[count],
-                        param_values[count]);
+       for (count = 0; count < service->num_params; count++) {
+               d_printf("\t%s = %s\n", service->param_names[count],
+                        service->param_values[count]);
        }
 
        ret = 0;
@@ -488,11 +574,12 @@ done:
  * This is a high level utility function of the net conf utility,
  * not a direct frontend to the smbconf API.
  */
-static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
-                            int argc, const char **argv)
+static int net_conf_addshare(struct net_context *c,
+                            struct smbconf_ctx *conf_ctx, int argc,
+                            const char **argv)
 {
        int ret = -1;
-       WERROR werr = WERR_OK;
+       sbcErr err;
        char *sharename = NULL;
        const char *path = NULL;
        const char *comment = NULL;
@@ -501,17 +588,23 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
        SMB_STRUCT_STAT sbuf;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
+       if (c->display_usage) {
+               net_conf_addshare_usage(c, argc, argv);
+               ret = 0;
+               goto done;
+       }
+
        switch (argc) {
                case 0:
                case 1:
                default:
-                       net_conf_addshare_usage(argc, argv);
+                       net_conf_addshare_usage(c, argc, argv);
                        goto done;
                case 5:
                        comment = argv[4];
                case 4:
                        if (!strnequal(argv[3], "guest_ok=", 9)) {
-                               net_conf_addshare_usage(argc, argv);
+                               net_conf_addshare_usage(c, argc, argv);
                                goto done;
                        }
                        switch (argv[3][9]) {
@@ -524,12 +617,12 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
                                        guest_ok = "no";
                                        break;
                                default:
-                                       net_conf_addshare_usage(argc, argv);
+                                       net_conf_addshare_usage(c, argc, argv);
                                        goto done;
                        }
                case 3:
                        if (!strnequal(argv[2], "writeable=", 10)) {
-                               net_conf_addshare_usage(argc, argv);
+                               net_conf_addshare_usage(c, argc, argv);
                                goto done;
                        }
                        switch (argv[2][10]) {
@@ -542,14 +635,14 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
                                        writeable = "no";
                                        break;
                                default:
-                                       net_conf_addshare_usage(argc, argv);
+                                       net_conf_addshare_usage(c, argc, argv);
                                        goto done;
                        }
                case 2:
                        path = argv[1];
-                       sharename = talloc_strdup_lower(mem_ctx, argv[0]);
+                       sharename = talloc_strdup(mem_ctx, argv[0]);
                        if (sharename == NULL) {
-                               d_printf("error: out of memory!\n");
+                               d_printf(_("error: out of memory!\n"));
                                goto done;
                        }
 
@@ -565,26 +658,20 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
        if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
                               strlen(sharename)))
        {
-               d_fprintf(stderr, "ERROR: share name %s contains "
-                        "invalid characters (any of %s)\n",
+               d_fprintf(stderr, _("ERROR: share name %s contains "
+                        "invalid characters (any of %s)\n"),
                         sharename, INVALID_SHARENAME_CHARS);
                goto done;
        }
 
-       if (getpwnam(sharename)) {
-               d_fprintf(stderr, "ERROR: share name %s is already a valid "
-                         "system user name.\n", sharename);
-               goto done;
-       }
-
        if (strequal(sharename, GLOBAL_NAME)) {
                d_fprintf(stderr,
-                         "ERROR: 'global' is not a valid share name.\n");
+                         _("ERROR: 'global' is not a valid share name.\n"));
                goto done;
        }
 
        if (smbconf_share_exists(conf_ctx, sharename)) {
-               d_fprintf(stderr, "ERROR: share %s already exists.\n",
+               d_fprintf(stderr, _("ERROR: share %s already exists.\n"),
                          sharename);
                goto done;
        }
@@ -593,103 +680,134 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
 
        if (path[0] != '/') {
                d_fprintf(stderr,
-                         "Error: path '%s' is not an absolute path.\n",
+                         _("Error: path '%s' is not an absolute path.\n"),
                          path);
                goto done;
        }
 
-       if (sys_stat(path, &sbuf) != 0) {
+       if (sys_stat(path, &sbuf, false) != 0) {
                d_fprintf(stderr,
-                         "ERROR: cannot stat path '%s' to ensure "
-                         "this is a directory.\n"
-                         "Error was '%s'.\n",
+                         _("ERROR: cannot stat path '%s' to ensure "
+                           "this is a directory.\n"
+                           "Error was '%s'.\n"),
                          path, strerror(errno));
                goto done;
        }
 
-       if (!S_ISDIR(sbuf.st_mode)) {
+       if (!S_ISDIR(sbuf.st_ex_mode)) {
                d_fprintf(stderr,
-                         "ERROR: path '%s' is not a directory.\n",
+                         _("ERROR: path '%s' is not a directory.\n"),
                          path);
                goto done;
        }
 
        /*
-        * create the share
+        * start a transaction
         */
 
-       werr = smbconf_create_share(conf_ctx, sharename);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error creating share %s: %s\n",
-                         sharename, dos_errstr(werr));
+       err = smbconf_transaction_start(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf("error starting transaction: %s\n",
+                        sbcErrorString(err));
                goto done;
        }
 
+       /*
+        * create the share
+        */
+
+       err = smbconf_create_share(conf_ctx, sharename);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error creating share %s: %s\n"),
+                         sharename, sbcErrorString(err));
+               goto cancel;
+       }
+
        /*
         * fill the share with parameters
         */
 
-       werr = smbconf_set_parameter(conf_ctx, sharename, "path", path);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error setting parameter %s: %s\n",
-                         "path", dos_errstr(werr));
-               goto done;
+       err = smbconf_set_parameter(conf_ctx, sharename, "path", path);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
+                         "path", sbcErrorString(err));
+               goto cancel;
        }
 
        if (comment != NULL) {
-               werr = smbconf_set_parameter(conf_ctx, sharename, "comment",
-                                            comment);
-               if (!W_ERROR_IS_OK(werr)) {
-                       d_fprintf(stderr, "Error setting parameter %s: %s\n",
-                                 "comment", dos_errstr(werr));
-                       goto done;
+               err = smbconf_set_parameter(conf_ctx, sharename, "comment",
+                                           comment);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
+                                 "comment", sbcErrorString(err));
+                       goto cancel;
                }
        }
 
-       werr = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error setting parameter %s: %s\n",
-                         "'guest ok'", dos_errstr(werr));
-               goto done;
+       err = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
+                         "'guest ok'", sbcErrorString(err));
+               goto cancel;
        }
 
-       werr = smbconf_set_parameter(conf_ctx, sharename, "writeable",
-                                    writeable);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error setting parameter %s: %s\n",
-                         "writeable", dos_errstr(werr));
-               goto done;
+       err = smbconf_set_parameter(conf_ctx, sharename, "writeable",
+                                   writeable);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
+                         "writeable", sbcErrorString(err));
+               goto cancel;
        }
 
-       ret = 0;
+       /*
+        * commit the whole thing
+        */
+
+       err = smbconf_transaction_commit(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf("error committing transaction: %s\n",
+                        sbcErrorString(err));
+       } else {
+               ret = 0;
+       }
+
+       goto done;
+
+cancel:
+       err = smbconf_transaction_cancel(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf("error cancelling transaction: %s\n",
+                        sbcErrorString(err));
+       }
 
 done:
        TALLOC_FREE(mem_ctx);
        return ret;
 }
 
-static int net_conf_delshare(struct smbconf_ctx *conf_ctx,
-                            int argc, const char **argv)
+static int net_conf_delshare(struct net_context *c,
+                            struct smbconf_ctx *conf_ctx, int argc,
+                            const char **argv)
 {
        int ret = -1;
        const char *sharename = NULL;
-       WERROR werr = WERR_OK;
+       sbcErr err;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (argc != 1) {
-               net_conf_delshare_usage(argc, argv);
+       if (argc != 1 || c->display_usage) {
+               net_conf_delshare_usage(c, argc, argv);
                goto done;
        }
-       sharename = talloc_strdup_lower(mem_ctx, argv[0]);
+       sharename = talloc_strdup(mem_ctx, argv[0]);
        if (sharename == NULL) {
-               d_printf("error: out of memory!\n");
+               d_printf(_("error: out of memory!\n"));
                goto done;
        }
 
-       werr = smbconf_delete_share(conf_ctx, sharename);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error deleting share %s: %s\n",
-                         sharename, dos_errstr(werr));
+       err = smbconf_delete_share(conf_ctx, sharename);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error deleting share %s: %s\n"),
+                         sharename, sbcErrorString(err));
                goto done;
        }
 
@@ -699,61 +817,88 @@ done:
        return ret;
 }
 
-static int net_conf_setparm(struct smbconf_ctx *conf_ctx,
+static int net_conf_setparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
                            int argc, const char **argv)
 {
        int ret = -1;
-       WERROR werr = WERR_OK;
+       sbcErr err;
        char *service = NULL;
        char *param = NULL;
        const char *value_str = NULL;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (argc != 3) {
-               net_conf_setparm_usage(argc, argv);
+       if (argc != 3 || c->display_usage) {
+               net_conf_setparm_usage(c, argc, argv);
                goto done;
        }
-       service = talloc_strdup_lower(mem_ctx, argv[0]);
-       if (service == NULL) {
-               d_printf("error: out of memory!\n");
-               goto done;
+       /*
+        * NULL service name means "dangling parameters" to libsmbconf.
+        * We use the empty string from the command line for this purpose.
+        */
+       if (strlen(argv[0]) != 0) {
+               service = talloc_strdup(mem_ctx, argv[0]);
+               if (service == NULL) {
+                       d_printf(_("error: out of memory!\n"));
+                       goto done;
+               }
        }
-       param = talloc_strdup_lower(mem_ctx, argv[1]);
+       param = strlower_talloc(mem_ctx, argv[1]);
        if (param == NULL) {
-               d_printf("error: out of memory!\n");
+               d_printf(_("error: out of memory!\n"));
                goto done;
        }
        value_str = argv[2];
 
+       err = smbconf_transaction_start(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error starting transaction: %s\n"),
+                        sbcErrorString(err));
+               goto done;
+       }
+
        if (!smbconf_share_exists(conf_ctx, service)) {
-               werr = smbconf_create_share(conf_ctx, service);
-               if (!W_ERROR_IS_OK(werr)) {
-                       d_fprintf(stderr, "Error creating share '%s': %s\n",
-                                 service, dos_errstr(werr));
-                       goto done;
+               err = smbconf_create_share(conf_ctx, service);
+               if (!SBC_ERROR_IS_OK(err)) {
+                       d_fprintf(stderr, _("Error creating share '%s': %s\n"),
+                                 service, sbcErrorString(err));
+                       goto cancel;
                }
        }
 
-       werr = smbconf_set_parameter(conf_ctx, service, param, value_str);
+       err = smbconf_set_parameter(conf_ctx, service, param, value_str);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error setting value '%s': %s\n"),
+                         param, sbcErrorString(err));
+               goto cancel;
+       }
 
-       if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error setting value '%s': %s\n",
-                         param, dos_errstr(werr));
-               goto done;
+       err = smbconf_transaction_commit(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error committing transaction: %s\n"),
+                        sbcErrorString(err));
+       } else {
+               ret = 0;
        }
 
-       ret = 0;
+       goto done;
+
+cancel:
+       err = smbconf_transaction_cancel(conf_ctx);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error cancelling transaction: %s\n"),
+                        sbcErrorString(err));
+       }
 
 done:
        TALLOC_FREE(mem_ctx);
        return ret;
 }
 
-static int net_conf_getparm(struct smbconf_ctx *conf_ctx,
+static int net_conf_getparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
                            int argc, const char **argv)
 {
        int ret = -1;
-       WERROR werr = WERR_OK;
+       sbcErr err;
        char *service = NULL;
        char *param = NULL;
        char *valstr = NULL;
@@ -761,36 +906,41 @@ static int net_conf_getparm(struct smbconf_ctx *conf_ctx,
 
        mem_ctx = talloc_stackframe();
 
-       if (argc != 2) {
-               net_conf_getparm_usage(argc, argv);
+       if (argc != 2 || c->display_usage) {
+               net_conf_getparm_usage(c, argc, argv);
                goto done;
        }
-       service = talloc_strdup_lower(mem_ctx, argv[0]);
-       if (service == NULL) {
-               d_printf("error: out of memory!\n");
-               goto done;
+       /*
+        * NULL service name means "dangling parameters" to libsmbconf.
+        * We use the empty string from the command line for this purpose.
+        */
+       if (strlen(argv[0]) != 0) {
+               service = talloc_strdup(mem_ctx, argv[0]);
+               if (service == NULL) {
+                       d_printf(_("error: out of memory!\n"));
+                       goto done;
+               }
        }
-       param = talloc_strdup_lower(mem_ctx, argv[1]);
+       param = strlower_talloc(mem_ctx, argv[1]);
        if (param == NULL) {
-               d_printf("error: out of memory!\n");
+               d_printf(_("error: out of memory!\n"));
                goto done;
        }
 
-       werr = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
-
-       if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
+       err = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
+       if (SBC_ERROR_EQUAL(err, SBC_ERR_NO_SUCH_SERVICE)) {
                d_fprintf(stderr,
-                         "Error: given service '%s' does not exist.\n",
+                         _("Error: given service '%s' does not exist.\n"),
                          service);
                goto done;
-       } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
+       } else if (SBC_ERROR_EQUAL(err, SBC_ERR_INVALID_PARAM)) {
                d_fprintf(stderr,
-                         "Error: given parameter '%s' is not set.\n",
+                         _("Error: given parameter '%s' is not set.\n"),
                          param);
                goto done;
-       } else if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error getting value '%s': %s.\n",
-                         param, dos_errstr(werr));
+       } else if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error getting value '%s': %s.\n"),
+                         param, sbcErrorString(err));
                goto done;
        }
 
@@ -802,45 +952,50 @@ done:
        return ret;
 }
 
-static int net_conf_delparm(struct smbconf_ctx *conf_ctx,
+static int net_conf_delparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
                            int argc, const char **argv)
 {
        int ret = -1;
-       WERROR werr = WERR_OK;
+       sbcErr err;
        char *service = NULL;
        char *param = NULL;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (argc != 2) {
-               net_conf_delparm_usage(argc, argv);
+       if (argc != 2 || c->display_usage) {
+               net_conf_delparm_usage(c, argc, argv);
                goto done;
        }
-       service = talloc_strdup_lower(mem_ctx, argv[0]);
-       if (service == NULL) {
-               d_printf("error: out of memory!\n");
-               goto done;
+       /*
+        * NULL service name means "dangling parameters" to libsmbconf.
+        * We use the empty string from the command line for this purpose.
+        */
+       if (strlen(argv[0]) != 0) {
+               service = talloc_strdup(mem_ctx, argv[0]);
+               if (service == NULL) {
+                       d_printf(_("error: out of memory!\n"));
+                       goto done;
+               }
        }
-       param = talloc_strdup_lower(mem_ctx, argv[1]);
+       param = strlower_talloc(mem_ctx, argv[1]);
        if (param == NULL) {
                d_printf("error: out of memory!\n");
                goto done;
        }
 
-       werr = smbconf_delete_parameter(conf_ctx, service, param);
-
-       if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
+       err = smbconf_delete_parameter(conf_ctx, service, param);
+       if (SBC_ERROR_EQUAL(err, SBC_ERR_NO_SUCH_SERVICE)) {
                d_fprintf(stderr,
-                         "Error: given service '%s' does not exist.\n",
+                         _("Error: given service '%s' does not exist.\n"),
                          service);
                goto done;
-       } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
+       } else if (SBC_ERROR_EQUAL(err, SBC_ERR_INVALID_PARAM)) {
                d_fprintf(stderr,
-                         "Error: given parameter '%s' is not set.\n",
+                         _("Error: given parameter '%s' is not set.\n"),
                          param);
                goto done;
-       } else if (!W_ERROR_IS_OK(werr)) {
-               d_fprintf(stderr, "Error deleting value '%s': %s.\n",
-                         param, dos_errstr(werr));
+       } else if (!SBC_ERROR_IS_OK(err)) {
+               d_fprintf(stderr, _("Error deleting value '%s': %s.\n"),
+                         param, sbcErrorString(err));
                goto done;
        }
 
@@ -851,10 +1006,11 @@ done:
        return ret;
 }
 
-static int net_conf_getincludes(struct smbconf_ctx *conf_ctx,
+static int net_conf_getincludes(struct net_context *c,
+                               struct smbconf_ctx *conf_ctx,
                                int argc, const char **argv)
 {
-       WERROR werr;
+       sbcErr err;
        uint32_t num_includes;
        uint32_t count;
        char *service;
@@ -862,21 +1018,21 @@ static int net_conf_getincludes(struct smbconf_ctx *conf_ctx,
        int ret = -1;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (argc != 1) {
-               net_conf_getincludes_usage(argc, argv);
+       if (argc != 1 || c->display_usage) {
+               net_conf_getincludes_usage(c, argc, argv);
                goto done;
        }
 
-       service = talloc_strdup_lower(mem_ctx, argv[0]);
+       service = talloc_strdup(mem_ctx, argv[0]);
        if (service == NULL) {
-               d_printf("error: out of memory!\n");
+               d_printf(_("error: out of memory!\n"));
                goto done;
        }
 
-       werr = smbconf_get_includes(conf_ctx, mem_ctx, service,
+       err = smbconf_get_includes(conf_ctx, mem_ctx, service,
                                    &num_includes, &includes);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_printf("error getting includes: %s\n", dos_errstr(werr));
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error getting includes: %s\n"), sbcErrorString(err));
                goto done;
        }
 
@@ -891,24 +1047,25 @@ done:
        return ret;
 }
 
-static int net_conf_setincludes(struct smbconf_ctx *conf_ctx,
+static int net_conf_setincludes(struct net_context *c,
+                               struct smbconf_ctx *conf_ctx,
                                int argc, const char **argv)
 {
-       WERROR werr;
+       sbcErr err;
        char *service;
        uint32_t num_includes;
        const char **includes;
        int ret = -1;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (argc < 1) {
-               net_conf_setincludes_usage(argc, argv);
+       if (argc < 1 || c->display_usage) {
+               net_conf_setincludes_usage(c, argc, argv);
                goto done;
        }
 
-       service = talloc_strdup_lower(mem_ctx, argv[0]);
+       service = talloc_strdup(mem_ctx, argv[0]);
        if (service == NULL) {
-               d_printf("error: out of memory!\n");
+               d_printf(_("error: out of memory!\n"));
                goto done;
        }
 
@@ -919,9 +1076,9 @@ static int net_conf_setincludes(struct smbconf_ctx *conf_ctx,
                includes = argv + 1;
        }
 
-       werr = smbconf_set_includes(conf_ctx, service, num_includes, includes);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_printf("error setting includes: %s\n", dos_errstr(werr));
+       err = smbconf_set_includes(conf_ctx, service, num_includes, includes);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error setting includes: %s\n"), sbcErrorString(err));
                goto done;
        }
 
@@ -932,28 +1089,29 @@ done:
        return ret;
 }
 
-static int net_conf_delincludes(struct smbconf_ctx *conf_ctx,
+static int net_conf_delincludes(struct net_context *c,
+                               struct smbconf_ctx *conf_ctx,
                                int argc, const char **argv)
 {
-       WERROR werr;
+       sbcErr err;
        char *service;
        int ret = -1;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (argc != 1) {
-               net_conf_delincludes_usage(argc, argv);
+       if (argc != 1 || c->display_usage) {
+               net_conf_delincludes_usage(c, argc, argv);
                goto done;
        }
 
-       service = talloc_strdup_lower(mem_ctx, argv[0]);
+       service = talloc_strdup(mem_ctx, argv[0]);
        if (service == NULL) {
-               d_printf("error: out of memory!\n");
+               d_printf(_("error: out of memory!\n"));
                goto done;
        }
 
-       werr = smbconf_delete_includes(conf_ctx, service);
-       if (!W_ERROR_IS_OK(werr)) {
-               d_printf("error deleting includes: %s\n", dos_errstr(werr));
+       err = smbconf_delete_includes(conf_ctx, service);
+       if (!SBC_ERROR_IS_OK(err)) {
+               d_printf(_("error deleting includes: %s\n"), sbcErrorString(err));
                goto done;
        }
 
@@ -976,22 +1134,23 @@ done:
  * The wrapper calls handles opening and closing of the
  * configuration.
  */
-static int net_conf_wrap_function(int (*fn)(struct smbconf_ctx *,
+static int net_conf_wrap_function(struct net_context *c,
+                                 int (*fn)(struct net_context *,
+                                           struct smbconf_ctx *,
                                            int, const char **),
                                  int argc, const char **argv)
 {
-       WERROR werr;
+       sbcErr err;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
        struct smbconf_ctx *conf_ctx;
        int ret = -1;
 
-       werr = smbconf_init(mem_ctx, &conf_ctx, "registry:");
-
-       if (!W_ERROR_IS_OK(werr)) {
+       err = smbconf_init(mem_ctx, &conf_ctx, "registry:");
+       if (!SBC_ERROR_IS_OK(err)) {
                return -1;
        }
 
-       ret = fn(conf_ctx, argc, argv);
+       ret = fn(c, conf_ctx, argc, argv);
 
        smbconf_shutdown(conf_ctx);
 
@@ -1005,75 +1164,165 @@ static int net_conf_wrap_function(int (*fn)(struct smbconf_ctx *,
  */
 struct conf_functable {
        const char *funcname;
-       int (*fn)(struct smbconf_ctx *ctx, int argc, const char **argv);
-       const char *helptext;
+       int (*fn)(struct net_context *c, struct smbconf_ctx *ctx, int argc,
+                 const char **argv);
+       int valid_transports;
+       const char *description;
+       const char *usage;
 };
 
 /**
- * This imitates net_run_function2 but calls the main functions
+ * This imitates net_run_function but calls the main functions
  * through the wrapper net_conf_wrap_function().
  */
-static int net_conf_run_function(int argc, const char **argv,
-                                const char *whoami,
+static int net_conf_run_function(struct net_context *c, int argc,
+                                const char **argv, const char *whoami,
                                 struct conf_functable *table)
 {
        int i;
 
        if (argc != 0) {
                for (i=0; table[i].funcname; i++) {
-                       if (StrCaseCmp(argv[0], table[i].funcname) == 0)
-                               return net_conf_wrap_function(table[i].fn,
+                       if (strcasecmp_m(argv[0], table[i].funcname) == 0)
+                               return net_conf_wrap_function(c, table[i].fn,
                                                              argc-1,
                                                              argv+1);
                }
        }
 
+       d_printf(_("Usage:\n"));
        for (i=0; table[i].funcname; i++) {
-               d_printf("%s %-15s %s\n", whoami, table[i].funcname,
-                        table[i].helptext);
+               if (c->display_usage == false)
+                       d_printf("%s %-15s %s\n", whoami, table[i].funcname,
+                                table[i].description);
+               else
+                       d_printf("%s\n", table[i].usage);
        }
 
-       return -1;
+       return c->display_usage?0:-1;
 }
 
 /*
  * Entry-point for all the CONF functions.
  */
 
-int net_conf(int argc, const char **argv)
+int net_conf(struct net_context *c, int argc, const char **argv)
 {
        int ret = -1;
        struct conf_functable func_table[] = {
-               {"list", net_conf_list,
-                "Dump the complete configuration in smb.conf like format."},
-               {"import", net_conf_import,
-                "Import configuration from file in smb.conf format."},
-               {"listshares", net_conf_listshares,
-                "List the share names."},
-               {"drop", net_conf_drop,
-                "Delete the complete configuration."},
-               {"showshare", net_conf_showshare,
-                "Show the definition of a share."},
-               {"addshare", net_conf_addshare,
-                "Create a new share."},
-               {"delshare", net_conf_delshare,
-                "Delete a share."},
-               {"setparm", net_conf_setparm,
-                "Store a parameter."},
-               {"getparm", net_conf_getparm,
-                "Retrieve the value of a parameter."},
-               {"delparm", net_conf_delparm,
-                "Delete a parameter."},
-               {"getincludes", net_conf_getincludes,
-                "Show the includes of a share definition."},
-               {"setincludes", net_conf_setincludes,
-                "Set includes for a share."},
-               {"delincludes", net_conf_delincludes,
-                "Delete includes from a share definition."},
-               {NULL, NULL, NULL}
+               {
+                       "list",
+                       net_conf_list,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Dump the complete configuration in smb.conf like "
+                          "format."),
+                       N_("net conf list\n"
+                          "    Dump the complete configuration in smb.conf "
+                          "like format.")
+
+               },
+               {
+                       "import",
+                       net_conf_import,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Import configuration from file in smb.conf "
+                          "format."),
+                       N_("net conf import\n"
+                          "    Import configuration from file in smb.conf "
+                          "format.")
+               },
+               {
+                       "listshares",
+                       net_conf_listshares,
+                       NET_TRANSPORT_LOCAL,
+                       N_("List the share names."),
+                       N_("net conf listshares\n"
+                          "    List the share names.")
+               },
+               {
+                       "drop",
+                       net_conf_drop,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Delete the complete configuration."),
+                       N_("net conf drop\n"
+                          "    Delete the complete configuration.")
+               },
+               {
+                       "showshare",
+                       net_conf_showshare,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Show the definition of a share."),
+                       N_("net conf showshare\n"
+                          "    Show the definition of a share.")
+               },
+               {
+                       "addshare",
+                       net_conf_addshare,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Create a new share."),
+                       N_("net conf addshare\n"
+                          "    Create a new share.")
+               },
+               {
+                       "delshare",
+                       net_conf_delshare,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Delete a share."),
+                       N_("net conf delshare\n"
+                          "    Delete a share.")
+               },
+               {
+                       "setparm",
+                       net_conf_setparm,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Store a parameter."),
+                       N_("net conf setparm\n"
+                          "    Store a parameter.")
+               },
+               {
+                       "getparm",
+                       net_conf_getparm,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Retrieve the value of a parameter."),
+                       N_("net conf getparm\n"
+                          "    Retrieve the value of a parameter.")
+               },
+               {
+                       "delparm",
+                       net_conf_delparm,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Delete a parameter."),
+                       N_("net conf delparm\n"
+                          "    Delete a parameter.")
+               },
+               {
+                       "getincludes",
+                       net_conf_getincludes,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Show the includes of a share definition."),
+                       N_("net conf getincludes\n"
+                          "    Show the includes of a share definition.")
+               },
+               {
+                       "setincludes",
+                       net_conf_setincludes,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Set includes for a share."),
+                       N_("net conf setincludes\n"
+                          "    Set includes for a share.")
+               },
+               {
+                       "delincludes",
+                       net_conf_delincludes,
+                       NET_TRANSPORT_LOCAL,
+                       N_("Delete includes from a share definition."),
+                       N_("net conf setincludes\n"
+                          "    Delete includes from a share definition.")
+               },
+               {NULL, NULL, 0, NULL, NULL}
        };
 
-       ret = net_conf_run_function(argc, argv, "net conf", func_table);
+       ret = net_conf_run_function(c, argc, argv, "net conf", func_table);
 
        return ret;
 }