s3:net conf: reduce memory usage of "net conf import".
[ira/wip.git] / source3 / utils / net_conf.c
index 1e4ab9b3f29ac4540159543379db7917a9bbd879..38a2553e53a1280e51aeec563f95937e42c9886b 100644 (file)
  *
  **********************************************************************/
 
-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");
        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"
@@ -53,25 +55,29 @@ static int net_conf_import_usage(int argc, const char**argv)
        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");
        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");
        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");
        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"
@@ -85,30 +91,55 @@ static int net_conf_addshare_usage(int argc, const char **argv)
        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");
        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");
        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");
        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");
        return -1;
 }
 
+static int net_conf_getincludes_usage(struct net_context *c, int argc,
+                                     const char **argv)
+{
+       d_printf("USAGE: net conf getincludes <section>\n");
+       return -1;
+}
+
+static int net_conf_setincludes_usage(struct net_context *c, int argc,
+                                     const char **argv)
+{
+       d_printf("USAGE: net conf setincludes <section> [<filename>]*\n");
+       return -1;
+}
+
+static int net_conf_delincludes_usage(struct net_context *c, int argc,
+                                     const char **argv)
+{
+       d_printf("USAGE: net conf delincludes <section>\n");
+       return -1;
+}
+
 
 /**********************************************************************
  *
@@ -119,46 +150,75 @@ static int net_conf_delparm_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 WERROR import_process_service(struct net_context *c,
+                                    struct smbconf_ctx *conf_ctx,
+                                    struct smbconf_service *service)
 {
        uint32_t idx;
        WERROR werr = WERR_OK;
+       uint32_t num_includes = 0;
+       char **includes = NULL;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (opt_testmode) {
-               d_printf("[%s]\n", servicename);
-       } else {
-               if (smbconf_share_exists(conf_ctx, servicename)) {
-                       werr = smbconf_delete_share(conf_ctx, servicename);
-                       if (!W_ERROR_IS_OK(werr)) {
-                               goto done;
-                       }
+       if (c->opt_testmode) {
+               const char *indent = "";
+               if (service->name != NULL) {
+                       d_printf("[%s]\n", service->name);
+                       indent = "\t";
+               }
+               for (idx = 0; idx < service->num_params; idx++) {
+                       d_printf("%s%s = %s\n", indent,
+                                service->param_names[idx],
+                                service->param_values[idx]);
                }
-               werr = smbconf_create_share(conf_ctx, servicename);
+               d_printf("\n");
+               goto done;
+       }
+
+       if (smbconf_share_exists(conf_ctx, service->name)) {
+               werr = smbconf_delete_share(conf_ctx, service->name);
                if (!W_ERROR_IS_OK(werr)) {
                        goto done;
                }
        }
+       werr = smbconf_create_share(conf_ctx, service->name);
+       if (!W_ERROR_IS_OK(werr)) {
+               goto done;
+       }
 
-       for (idx = 0; idx < num_params; idx ++) {
-               if (opt_testmode) {
-                       d_printf("\t%s = %s\n", param_names[idx],
-                                param_values[idx]);
+       for (idx = 0; idx < service->num_params; idx ++) {
+               if (strequal(service->param_names[idx], "include")) {
+                       includes = TALLOC_REALLOC_ARRAY(mem_ctx,
+                                                       includes,
+                                                       char *,
+                                                       num_includes+1);
+                       if (includes == NULL) {
+                               werr = WERR_NOMEM;
+                               goto done;
+                       }
+                       includes[num_includes] = talloc_strdup(includes,
+                                               service->param_values[idx]);
+                       if (includes[num_includes] == NULL) {
+                               werr = WERR_NOMEM;
+                               goto done;
+                       }
+                       num_includes++;
                } else {
                        werr = smbconf_set_parameter(conf_ctx,
-                                                    servicename,
-                                                    param_names[idx],
-                                                    param_values[idx]);
+                                                    service->name,
+                                                    service->param_names[idx],
+                                                    service->param_values[idx]);
                        if (!W_ERROR_IS_OK(werr)) {
                                goto done;
                        }
                }
        }
 
+       werr = smbconf_set_includes(conf_ctx, service->name, num_includes,
+                                   (const char **)includes);
+
 done:
+       TALLOC_FREE(mem_ctx);
        return werr;
 }
 
@@ -169,42 +229,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;
        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);
+       werr = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &shares);
        if (!W_ERROR_IS_OK(werr)) {
                d_fprintf(stderr, "Error getting config: %s\n",
-                         dos_errstr(werr));
+                         win_errstr(werr));
                goto done;
        }
 
        for (share_count = 0; share_count < num_shares; share_count++) {
-               d_printf("[%s]\n", share_names[share_count]);
-               for (param_count = 0; param_count < num_params[share_count];
+               const char *indent = "";
+               if (shares[share_count]->name != NULL) {
+                       d_printf("[%s]\n", shares[share_count]->name);
+                       indent = "\t";
+               }
+               for (param_count = 0;
+                    param_count < shares[share_count]->num_params;
                     param_count++)
                {
-                       d_printf("\t%s = %s\n",
-                                param_names[share_count][param_count],
-                                param_values[share_count][param_count]);
+                       d_printf("%s%s = %s\n",
+                                indent,
+                                shares[share_count]->param_names[param_count],
+                                shares[share_count]->param_values[param_count]);
                }
                d_printf("\n");
        }
@@ -216,25 +278,33 @@ 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;
        const char *filename = NULL;
        const char *servicename = NULL;
+       char *conf_source = NULL;
        TALLOC_CTX *mem_ctx;
        struct smbconf_ctx *txt_ctx;
        WERROR werr;
 
+       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 = argv[1];
+                       servicename = talloc_strdup_lower(mem_ctx, argv[1]);
+                       if (servicename == NULL) {
+                               d_printf("error: out of memory!\n");
+                               goto done;
+                       }
                case 1:
                        filename = argv[0];
                        break;
@@ -243,74 +313,120 @@ static int net_conf_import(struct smbconf_ctx *conf_ctx,
        DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
                filename));
 
-       werr = smbconf_init_txt_simple(mem_ctx, &txt_ctx, filename);
+       conf_source = talloc_asprintf(mem_ctx, "file:%s", filename);
+       if (conf_source == NULL) {
+               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,
+                        win_errstr(werr));
                goto done;
        }
 
-       if (opt_testmode) {
+       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;
+               struct smbconf_service *service = NULL;
 
                werr = smbconf_get_share(txt_ctx, mem_ctx,
                                         servicename,
-                                        &num_params,
-                                        &param_names,
-                                        &param_values);
+                                        &service);
                if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
+                       goto cancel;
                }
-               werr = import_process_service(conf_ctx,
-                                             servicename,
-                                             num_params,
-                                             (const char **)param_names,
-                                             (const char **)param_values);
+               werr = import_process_service(c, conf_ctx, service);
                if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
+                       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,
                                          &num_shares,
-                                         &share_names,
-                                         &num_params,
-                                         &param_names,
-                                         &param_values);
+                                         &services);
                if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
+                       goto cancel;
                }
-               werr = smbconf_drop(conf_ctx);
+               if (!c->opt_testmode) {
+                       werr = smbconf_drop(conf_ctx);
+                       if (!W_ERROR_IS_OK(werr)) {
+                               goto cancel;
+                       }
+               }
+
+               /*
+                * Wrap the importing of shares into a transaction,
+                * but only 100 at a time, in order to serve 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.
+                */
+               werr = smbconf_transaction_start(conf_ctx);
                if (!W_ERROR_IS_OK(werr)) {
+                       d_printf("error starting transaction: %s\n",
+                                win_errstr(werr));
                        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]);
+                       werr = import_process_service(c, conf_ctx,
+                                                     services[sidx]);
+                       if (!W_ERROR_IS_OK(werr)) {
+                               goto cancel;
+                       }
+
+                       if (sidx % 100) {
+                               continue;
+                       }
+
+                       werr = smbconf_transaction_commit(conf_ctx);
                        if (!W_ERROR_IS_OK(werr)) {
+                               d_printf("error committing transaction: %s\n",
+                                        win_errstr(werr));
+                               goto done;
+                       }
+                       werr = smbconf_transaction_start(conf_ctx);
+                       if (!W_ERROR_IS_OK(werr)) {
+                               d_printf("error starting transaction: %s\n",
+                                        win_errstr(werr));
                                goto done;
                        }
                }
        }
 
-       ret = 0;
+       werr = smbconf_transaction_commit(conf_ctx);
+       if (!W_ERROR_IS_OK(werr)) {
+               d_printf("error committing transaction: %s\n",
+                        win_errstr(werr));
+       } else {
+               ret = 0;
+       }
+
+       goto done;
+
+cancel:
+       werr = smbconf_transaction_cancel(conf_ctx);
+       if (!W_ERROR_IS_OK(werr)) {
+               d_printf("error cancelling transaction: %s\n",
+                        win_errstr(werr));
+       }
 
 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;
        int ret = -1;
@@ -320,8 +436,8 @@ 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;
        }
 
@@ -343,21 +459,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;
 
-       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));
+                         win_errstr(werr));
                goto done;
        }
 
@@ -367,40 +483,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;
        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 = argv[0];
+       sharename = talloc_strdup_lower(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);
+       werr = smbconf_get_share(conf_ctx, mem_ctx, sharename, &service);
        if (!W_ERROR_IS_OK(werr)) {
                d_printf("error getting share parameters: %s\n",
-                        dos_errstr(werr));
+                        win_errstr(werr));
                goto done;
        }
 
        d_printf("[%s]\n", sharename);
 
-       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;
@@ -416,8 +534,9 @@ 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;
@@ -427,18 +546,25 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
        const char *guest_ok = "no";
        const char *writeable = "no";
        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]) {
@@ -451,12 +577,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]) {
@@ -469,12 +595,17 @@ 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 = strdup_lower(argv[0]);
+                       sharename = talloc_strdup_lower(mem_ctx, argv[0]);
+                       if (sharename == NULL) {
+                               d_printf("error: out of memory!\n");
+                               goto done;
+                       }
+
                        break;
        }
 
@@ -493,12 +624,6 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
                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");
@@ -543,7 +668,7 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
        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));
+                         sharename, win_errstr(werr));
                goto done;
        }
 
@@ -554,7 +679,7 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
        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));
+                         "path", win_errstr(werr));
                goto done;
        }
 
@@ -563,7 +688,7 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
                                             comment);
                if (!W_ERROR_IS_OK(werr)) {
                        d_fprintf(stderr, "Error setting parameter %s: %s\n",
-                                 "comment", dos_errstr(werr));
+                                 "comment", win_errstr(werr));
                        goto done;
                }
        }
@@ -571,7 +696,7 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
        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));
+                         "'guest ok'", win_errstr(werr));
                goto done;
        }
 
@@ -579,43 +704,50 @@ static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
                                     writeable);
        if (!W_ERROR_IS_OK(werr)) {
                d_fprintf(stderr, "Error setting parameter %s: %s\n",
-                         "writeable", dos_errstr(werr));
+                         "writeable", win_errstr(werr));
                goto done;
        }
 
        ret = 0;
 
 done:
-       SAFE_FREE(sharename);
+       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;
+       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]);
+       if (sharename == NULL) {
+               d_printf("error: out of memory!\n");
                goto done;
        }
-       sharename = argv[0];
 
        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));
+                         sharename, win_errstr(werr));
                goto done;
        }
 
        ret = 0;
 done:
+       TALLOC_FREE(mem_ctx);
        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;
@@ -623,20 +755,29 @@ static int net_conf_setparm(struct smbconf_ctx *conf_ctx,
        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;
+       }
+       param = talloc_strdup_lower(mem_ctx, argv[1]);
+       if (param == NULL) {
+               d_printf("error: out of memory!\n");
                goto done;
        }
-       service = strdup_lower(argv[0]);
-       param = strdup_lower(argv[1]);
        value_str = argv[2];
 
        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));
+                                 service, win_errstr(werr));
                        goto done;
                }
        }
@@ -645,19 +786,18 @@ static int net_conf_setparm(struct smbconf_ctx *conf_ctx,
 
        if (!W_ERROR_IS_OK(werr)) {
                d_fprintf(stderr, "Error setting value '%s': %s\n",
-                         param, dos_errstr(werr));
+                         param, win_errstr(werr));
                goto done;
        }
 
        ret = 0;
 
 done:
-       SAFE_FREE(service);
-       SAFE_FREE(param);
+       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;
@@ -669,12 +809,20 @@ 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;
+       }
+       param = talloc_strdup_lower(mem_ctx, argv[1]);
+       if (param == NULL) {
+               d_printf("error: out of memory!\n");
                goto done;
        }
-       service = strdup_lower(argv[0]);
-       param = strdup_lower(argv[1]);
 
        werr = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
 
@@ -690,7 +838,7 @@ static int net_conf_getparm(struct smbconf_ctx *conf_ctx,
                goto done;
        } else if (!W_ERROR_IS_OK(werr)) {
                d_fprintf(stderr, "Error getting value '%s': %s.\n",
-                         param, dos_errstr(werr));
+                         param, win_errstr(werr));
                goto done;
        }
 
@@ -698,26 +846,33 @@ static int net_conf_getparm(struct smbconf_ctx *conf_ctx,
 
        ret = 0;
 done:
-       SAFE_FREE(service);
-       SAFE_FREE(param);
        TALLOC_FREE(mem_ctx);
        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;
        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;
+       }
+       param = talloc_strdup_lower(mem_ctx, argv[1]);
+       if (param == NULL) {
+               d_printf("error: out of memory!\n");
                goto done;
        }
-       service = strdup_lower(argv[0]);
-       param = strdup_lower(argv[1]);
 
        werr = smbconf_delete_parameter(conf_ctx, service, param);
 
@@ -733,15 +888,130 @@ static int net_conf_delparm(struct smbconf_ctx *conf_ctx,
                goto done;
        } else if (!W_ERROR_IS_OK(werr)) {
                d_fprintf(stderr, "Error deleting value '%s': %s.\n",
-                         param, dos_errstr(werr));
+                         param, win_errstr(werr));
+               goto done;
+       }
+
+       ret = 0;
+
+done:
+       TALLOC_FREE(mem_ctx);
+       return ret;
+}
+
+static int net_conf_getincludes(struct net_context *c,
+                               struct smbconf_ctx *conf_ctx,
+                               int argc, const char **argv)
+{
+       WERROR werr;
+       uint32_t num_includes;
+       uint32_t count;
+       char *service;
+       char **includes = NULL;
+       int ret = -1;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (argc != 1 || c->display_usage) {
+               net_conf_getincludes_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;
+       }
+
+       werr = smbconf_get_includes(conf_ctx, mem_ctx, service,
+                                   &num_includes, &includes);
+       if (!W_ERROR_IS_OK(werr)) {
+               d_printf("error getting includes: %s\n", win_errstr(werr));
+               goto done;
+       }
+
+       for (count = 0; count < num_includes; count++) {
+               d_printf("include = %s\n", includes[count]);
+       }
+
+       ret = 0;
+
+done:
+       TALLOC_FREE(mem_ctx);
+       return ret;
+}
+
+static int net_conf_setincludes(struct net_context *c,
+                               struct smbconf_ctx *conf_ctx,
+                               int argc, const char **argv)
+{
+       WERROR werr;
+       char *service;
+       uint32_t num_includes;
+       const char **includes;
+       int ret = -1;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (argc < 1 || c->display_usage) {
+               net_conf_setincludes_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;
+       }
+
+       num_includes = argc - 1;
+       if (num_includes == 0) {
+               includes = NULL;
+       } else {
+               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", win_errstr(werr));
+               goto done;
+       }
+
+       ret = 0;
+
+done:
+       TALLOC_FREE(mem_ctx);
+       return ret;
+}
+
+static int net_conf_delincludes(struct net_context *c,
+                               struct smbconf_ctx *conf_ctx,
+                               int argc, const char **argv)
+{
+       WERROR werr;
+       char *service;
+       int ret = -1;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (argc != 1 || c->display_usage) {
+               net_conf_delincludes_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;
+       }
+
+       werr = smbconf_delete_includes(conf_ctx, service);
+       if (!W_ERROR_IS_OK(werr)) {
+               d_printf("error deleting includes: %s\n", win_errstr(werr));
                goto done;
        }
 
        ret = 0;
 
 done:
-       SAFE_FREE(service);
-       SAFE_FREE(param);
+       TALLOC_FREE(mem_ctx);
        return ret;
 }
 
@@ -757,7 +1027,9 @@ 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)
 {
@@ -766,13 +1038,13 @@ static int net_conf_wrap_function(int (*fn)(struct smbconf_ctx *,
        struct smbconf_ctx *conf_ctx;
        int ret = -1;
 
-       werr = smbconf_init_reg(mem_ctx, &conf_ctx, NULL);
+       werr = smbconf_init(mem_ctx, &conf_ctx, "registry:");
 
        if (!W_ERROR_IS_OK(werr)) {
                return -1;
        }
 
-       ret = fn(conf_ctx, argc, argv);
+       ret = fn(c, conf_ctx, argc, argv);
 
        smbconf_shutdown(conf_ctx);
 
@@ -786,16 +1058,19 @@ 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;
@@ -803,52 +1078,143 @@ static int net_conf_run_function(int argc, const char **argv,
        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,
+                               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."},
-               {NULL, NULL, NULL}
+               {
+                       "list",
+                       net_conf_list,
+                       NET_TRANSPORT_LOCAL,
+                       "Dump the complete configuration in smb.conf like "
+                       "format.",
+                       "net conf list\n"
+                       "    Dump the complete configuration in smb.conf like "
+                       "format."
+
+               },
+               {
+                       "import",
+                       net_conf_import,
+                       NET_TRANSPORT_LOCAL,
+                       "Import configuration from file in smb.conf format.",
+                       "net conf import\n"
+                       "    Import configuration from file in smb.conf format."
+               },
+               {
+                       "listshares",
+                       net_conf_listshares,
+                       NET_TRANSPORT_LOCAL,
+                       "List the share names.",
+                       "net conf listshares\n"
+                       "    List the share names."
+               },
+               {
+                       "drop",
+                       net_conf_drop,
+                       NET_TRANSPORT_LOCAL,
+                       "Delete the complete configuration.",
+                       "net conf drop\n"
+                       "    Delete the complete configuration."
+               },
+               {
+                       "showshare",
+                       net_conf_showshare,
+                       NET_TRANSPORT_LOCAL,
+                       "Show the definition of a share.",
+                       "net conf showshare\n"
+                       "    Show the definition of a share."
+               },
+               {
+                       "addshare",
+                       net_conf_addshare,
+                       NET_TRANSPORT_LOCAL,
+                       "Create a new share.",
+                       "net conf addshare\n"
+                       "    Create a new share."
+               },
+               {
+                       "delshare",
+                       net_conf_delshare,
+                       NET_TRANSPORT_LOCAL,
+                       "Delete a share.",
+                       "net conf delshare\n"
+                       "    Delete a share."
+               },
+               {
+                       "setparm",
+                       net_conf_setparm,
+                       NET_TRANSPORT_LOCAL,
+                       "Store a parameter.",
+                       "net conf setparm\n"
+                       "    Store a parameter."
+               },
+               {
+                       "getparm",
+                       net_conf_getparm,
+                       NET_TRANSPORT_LOCAL,
+                       "Retrieve the value of a parameter.",
+                       "net conf getparm\n"
+                       "    Retrieve the value of a parameter."
+               },
+               {
+                       "delparm",
+                       net_conf_delparm,
+                       NET_TRANSPORT_LOCAL,
+                       "Delete a parameter.",
+                       "net conf delparm\n"
+                       "    Delete a parameter."
+               },
+               {
+                       "getincludes",
+                       net_conf_getincludes,
+                       NET_TRANSPORT_LOCAL,
+                       "Show the includes of a share definition.",
+                       "net conf getincludes\n"
+                       "    Show the includes of a share definition."
+               },
+               {
+                       "setincludes",
+                       net_conf_setincludes,
+                       NET_TRANSPORT_LOCAL,
+                       "Set includes for a share.",
+                       "net conf setincludes\n"
+                       "    Set includes for a share."
+               },
+               {
+                       "delincludes",
+                       net_conf_delincludes,
+                       NET_TRANSPORT_LOCAL,
+                       "Delete includes from a share definition.",
+                       "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;
 }