smbconf: only include smbconf headers where needed.
[samba.git] / source3 / utils / net_conf.c
1 /*
2  *  Samba Unix/Linux SMB client library
3  *  Distributed SMB/CIFS Server Management Utility
4  *  Local configuration interface
5  *  Copyright (C) Michael Adam 2007-2008
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22  * This is an interface to Samba's configuration as made available
23  * by the libsmbconf interface (source/lib/smbconf/smbconf.c).
24  *
25  * This currently supports local interaction with the configuration
26  * stored in the registry. But other backends and remote access via
27  * rpc might get implemented in the future.
28  */
29
30 #include "includes.h"
31 #include "utils/net.h"
32 #include "lib/smbconf/smbconf.h"
33 #include "lib/smbconf/smbconf_init.h"
34 #include "lib/smbconf/smbconf_reg.h"
35
36 /**********************************************************************
37  *
38  * usage functions
39  *
40  **********************************************************************/
41
42 static int net_conf_list_usage(struct net_context *c, int argc,
43                                const char **argv)
44 {
45         d_printf("%s net conf list\n", _("Usage:"));
46         return -1;
47 }
48
49 static int net_conf_import_usage(struct net_context *c, int argc,
50                                  const char**argv)
51 {
52         d_printf("%s\n%s",
53                  _("Usage:"),
54                  _(" net conf import [--test|-T] <filename> "
55                    "[<servicename>]\n"
56                    "\t[--test|-T]    testmode - do not act, just print "
57                         "what would be done\n"
58                    "\t<servicename>  only import service <servicename>, "
59                         "ignore the rest\n"));
60         return -1;
61 }
62
63 static int net_conf_listshares_usage(struct net_context *c, int argc,
64                                      const char **argv)
65 {
66         d_printf("%s\nnet conf listshares\n", _("Usage:"));
67         return -1;
68 }
69
70 static int net_conf_drop_usage(struct net_context *c, int argc,
71                                const char **argv)
72 {
73         d_printf("%s\nnet conf drop\n", _("Usage:"));
74         return -1;
75 }
76
77 static int net_conf_showshare_usage(struct net_context *c, int argc,
78                                     const char **argv)
79 {
80         d_printf("%s\n%s",
81                  _("Usage:"),
82                  _("net conf showshare <sharename>\n"));
83         return -1;
84 }
85
86 static int net_conf_addshare_usage(struct net_context *c, int argc,
87                                    const char **argv)
88 {
89         d_printf("%s\n%s",
90                  _("Usage:"),
91                  _(" net conf addshare <sharename> <path> "
92                    "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
93                    "\t<sharename>      the new share name.\n"
94                    "\t<path>           the path on the filesystem to export.\n"
95                    "\twriteable={y|N}  set \"writeable to \"yes\" or "
96                    "\"no\" (default) on this share.\n"
97                    "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
98                    "\"no\" (default)   on this share.\n"
99                    "\t<comment>        optional comment for the new share.\n"));
100         return -1;
101 }
102
103 static int net_conf_delshare_usage(struct net_context *c, int argc,
104                                    const char **argv)
105 {
106         d_printf("%s\n%s",
107                  _("Usage:"),
108                  _("net conf delshare <sharename>\n"));
109         return -1;
110 }
111
112 static int net_conf_setparm_usage(struct net_context *c, int argc,
113                                   const char **argv)
114 {
115         d_printf("%s\n%s",
116                  _("Usage:"),
117                  _(" net conf setparm <section> <param> <value>\n"));
118         return -1;
119 }
120
121 static int net_conf_getparm_usage(struct net_context *c, int argc,
122                                   const char **argv)
123 {
124         d_printf("%s\n%s",
125                  _("Usage:"),
126                  _(" net conf getparm <section> <param>\n"));
127         return -1;
128 }
129
130 static int net_conf_delparm_usage(struct net_context *c, int argc,
131                                   const char **argv)
132 {
133         d_printf("%s\n%s",
134                  _("Usage:"),
135                  _(" net conf delparm <section> <param>\n"));
136         return -1;
137 }
138
139 static int net_conf_getincludes_usage(struct net_context *c, int argc,
140                                       const char **argv)
141 {
142         d_printf("%s\n%s",
143                  _("Usage:"),
144                  _(" net conf getincludes <section>\n"));
145         return -1;
146 }
147
148 static int net_conf_setincludes_usage(struct net_context *c, int argc,
149                                       const char **argv)
150 {
151         d_printf("%s\n%s",
152                  _("Usage:"),
153                  _(" net conf setincludes <section> [<filename>]*\n"));
154         return -1;
155 }
156
157 static int net_conf_delincludes_usage(struct net_context *c, int argc,
158                                       const char **argv)
159 {
160         d_printf("%s\n%s",
161                 _("Usage:"),
162                 _(" net conf delincludes <section>\n"));
163         return -1;
164 }
165
166
167 /**********************************************************************
168  *
169  * Helper functions
170  *
171  **********************************************************************/
172
173 /**
174  * This functions process a service previously loaded with libsmbconf.
175  */
176 static WERROR import_process_service(struct net_context *c,
177                                      struct smbconf_ctx *conf_ctx,
178                                      struct smbconf_service *service)
179 {
180         uint32_t idx;
181         WERROR werr = WERR_OK;
182         uint32_t num_includes = 0;
183         char **includes = NULL;
184         TALLOC_CTX *mem_ctx = talloc_stackframe();
185
186         if (c->opt_testmode) {
187                 const char *indent = "";
188                 if (service->name != NULL) {
189                         d_printf("[%s]\n", service->name);
190                         indent = "\t";
191                 }
192                 for (idx = 0; idx < service->num_params; idx++) {
193                         d_printf("%s%s = %s\n", indent,
194                                  service->param_names[idx],
195                                  service->param_values[idx]);
196                 }
197                 d_printf("\n");
198                 goto done;
199         }
200
201         if (smbconf_share_exists(conf_ctx, service->name)) {
202                 werr = smbconf_delete_share(conf_ctx, service->name);
203                 if (!W_ERROR_IS_OK(werr)) {
204                         goto done;
205                 }
206         }
207         werr = smbconf_create_share(conf_ctx, service->name);
208         if (!W_ERROR_IS_OK(werr)) {
209                 goto done;
210         }
211
212         for (idx = 0; idx < service->num_params; idx ++) {
213                 if (strequal(service->param_names[idx], "include")) {
214                         includes = TALLOC_REALLOC_ARRAY(mem_ctx,
215                                                         includes,
216                                                         char *,
217                                                         num_includes+1);
218                         if (includes == NULL) {
219                                 werr = WERR_NOMEM;
220                                 goto done;
221                         }
222                         includes[num_includes] = talloc_strdup(includes,
223                                                 service->param_values[idx]);
224                         if (includes[num_includes] == NULL) {
225                                 werr = WERR_NOMEM;
226                                 goto done;
227                         }
228                         num_includes++;
229                 } else {
230                         werr = smbconf_set_parameter(conf_ctx,
231                                                      service->name,
232                                                      service->param_names[idx],
233                                                      service->param_values[idx]);
234                         if (!W_ERROR_IS_OK(werr)) {
235                                 d_fprintf(stderr,
236                                           _("Error in section [%s], parameter \"%s\": %s\n"),
237                                           service->name, service->param_names[idx],
238                                           win_errstr(werr));
239                                 goto done;
240                         }
241                 }
242         }
243
244         werr = smbconf_set_includes(conf_ctx, service->name, num_includes,
245                                     (const char **)includes);
246
247 done:
248         TALLOC_FREE(mem_ctx);
249         return werr;
250 }
251
252
253 /**********************************************************************
254  *
255  * the main conf functions
256  *
257  **********************************************************************/
258
259 static int net_conf_list(struct net_context *c, struct smbconf_ctx *conf_ctx,
260                          int argc, const char **argv)
261 {
262         WERROR werr = WERR_OK;
263         int ret = -1;
264         TALLOC_CTX *mem_ctx;
265         uint32_t num_shares;
266         uint32_t share_count, param_count;
267         struct smbconf_service **shares = NULL;
268
269         mem_ctx = talloc_stackframe();
270
271         if (argc != 0 || c->display_usage) {
272                 net_conf_list_usage(c, argc, argv);
273                 goto done;
274         }
275
276         werr = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &shares);
277         if (!W_ERROR_IS_OK(werr)) {
278                 d_fprintf(stderr, _("Error getting config: %s\n"),
279                           win_errstr(werr));
280                 goto done;
281         }
282
283         for (share_count = 0; share_count < num_shares; share_count++) {
284                 const char *indent = "";
285                 if (shares[share_count]->name != NULL) {
286                         d_printf("[%s]\n", shares[share_count]->name);
287                         indent = "\t";
288                 }
289                 for (param_count = 0;
290                      param_count < shares[share_count]->num_params;
291                      param_count++)
292                 {
293                         d_printf("%s%s = %s\n",
294                                  indent,
295                                  shares[share_count]->param_names[param_count],
296                                  shares[share_count]->param_values[param_count]);
297                 }
298                 d_printf("\n");
299         }
300
301         ret = 0;
302
303 done:
304         TALLOC_FREE(mem_ctx);
305         return ret;
306 }
307
308 static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
309                            int argc, const char **argv)
310 {
311         int ret = -1;
312         const char *filename = NULL;
313         const char *servicename = NULL;
314         char *conf_source = NULL;
315         TALLOC_CTX *mem_ctx;
316         struct smbconf_ctx *txt_ctx;
317         WERROR werr;
318
319         if (c->display_usage)
320                 return net_conf_import_usage(c, argc, argv);
321
322         mem_ctx = talloc_stackframe();
323
324         switch (argc) {
325                 case 0:
326                 default:
327                         net_conf_import_usage(c, argc, argv);
328                         goto done;
329                 case 2:
330                         servicename = talloc_strdup(mem_ctx, argv[1]);
331                         if (servicename == NULL) {
332                                 d_printf(_("error: out of memory!\n"));
333                                 goto done;
334                         }
335                 case 1:
336                         filename = argv[0];
337                         break;
338         }
339
340         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
341                 filename));
342
343         conf_source = talloc_asprintf(mem_ctx, "file:%s", filename);
344         if (conf_source == NULL) {
345                 d_printf(_("error: out of memory!\n"));
346                 goto done;
347         }
348
349         werr = smbconf_init(mem_ctx, &txt_ctx, conf_source);
350         if (!W_ERROR_IS_OK(werr)) {
351                 d_printf(_("error loading file '%s': %s\n"), filename,
352                          win_errstr(werr));
353                 goto done;
354         }
355
356         if (c->opt_testmode) {
357                 d_printf(_("\nTEST MODE - "
358                          "would import the following configuration:\n\n"));
359         }
360
361         if (servicename != NULL) {
362                 struct smbconf_service *service = NULL;
363
364                 werr = smbconf_get_share(txt_ctx, mem_ctx,
365                                          servicename,
366                                          &service);
367                 if (!W_ERROR_IS_OK(werr)) {
368                         goto cancel;
369                 }
370
371                 werr = smbconf_transaction_start(conf_ctx);
372                 if (!W_ERROR_IS_OK(werr)) {
373                         d_printf(_("error starting transaction: %s\n"),
374                                  win_errstr(werr));
375                         goto done;
376                 }
377
378                 werr = import_process_service(c, conf_ctx, service);
379                 if (!W_ERROR_IS_OK(werr)) {
380                         goto cancel;
381                 }
382         } else {
383                 struct smbconf_service **services = NULL;
384                 uint32_t num_shares, sidx;
385
386                 werr = smbconf_get_config(txt_ctx, mem_ctx,
387                                           &num_shares,
388                                           &services);
389                 if (!W_ERROR_IS_OK(werr)) {
390                         goto cancel;
391                 }
392                 if (!c->opt_testmode) {
393                         werr = smbconf_drop(conf_ctx);
394                         if (!W_ERROR_IS_OK(werr)) {
395                                 goto cancel;
396                         }
397                 }
398
399                 /*
400                  * Wrap the importing of shares into a transaction,
401                  * but only 100 at a time, in order to serve memory.
402                  * The allocated memory accumulates across the actions
403                  * within the transaction, and for me, some 1500
404                  * imported shares, the MAX_TALLOC_SIZE of 256 MB
405                  * was exceeded.
406                  */
407                 werr = smbconf_transaction_start(conf_ctx);
408                 if (!W_ERROR_IS_OK(werr)) {
409                         d_printf(_("error starting transaction: %s\n"),
410                                  win_errstr(werr));
411                         goto done;
412                 }
413
414                 for (sidx = 0; sidx < num_shares; sidx++) {
415                         werr = import_process_service(c, conf_ctx,
416                                                       services[sidx]);
417                         if (!W_ERROR_IS_OK(werr)) {
418                                 goto cancel;
419                         }
420
421                         if (sidx % 100) {
422                                 continue;
423                         }
424
425                         werr = smbconf_transaction_commit(conf_ctx);
426                         if (!W_ERROR_IS_OK(werr)) {
427                                 d_printf(_("error committing transaction: "
428                                            "%s\n"),
429                                          win_errstr(werr));
430                                 goto done;
431                         }
432                         werr = smbconf_transaction_start(conf_ctx);
433                         if (!W_ERROR_IS_OK(werr)) {
434                                 d_printf(_("error starting transaction: %s\n"),
435                                          win_errstr(werr));
436                                 goto done;
437                         }
438                 }
439         }
440
441         werr = smbconf_transaction_commit(conf_ctx);
442         if (!W_ERROR_IS_OK(werr)) {
443                 d_printf(_("error committing transaction: %s\n"),
444                          win_errstr(werr));
445         } else {
446                 ret = 0;
447         }
448
449         goto done;
450
451 cancel:
452         werr = smbconf_transaction_cancel(conf_ctx);
453         if (!W_ERROR_IS_OK(werr)) {
454                 d_printf(_("error cancelling transaction: %s\n"),
455                          win_errstr(werr));
456         }
457
458 done:
459         TALLOC_FREE(mem_ctx);
460         return ret;
461 }
462
463 static int net_conf_listshares(struct net_context *c,
464                                struct smbconf_ctx *conf_ctx, int argc,
465                                const char **argv)
466 {
467         WERROR werr = WERR_OK;
468         int ret = -1;
469         uint32_t count, num_shares = 0;
470         char **share_names = NULL;
471         TALLOC_CTX *mem_ctx;
472
473         mem_ctx = talloc_stackframe();
474
475         if (argc != 0 || c->display_usage) {
476                 net_conf_listshares_usage(c, argc, argv);
477                 goto done;
478         }
479
480         werr = smbconf_get_share_names(conf_ctx, mem_ctx, &num_shares,
481                                        &share_names);
482         if (!W_ERROR_IS_OK(werr)) {
483                 goto done;
484         }
485
486         for (count = 0; count < num_shares; count++)
487         {
488                 d_printf("%s\n", share_names[count]);
489         }
490
491         ret = 0;
492
493 done:
494         TALLOC_FREE(mem_ctx);
495         return ret;
496 }
497
498 static int net_conf_drop(struct net_context *c, struct smbconf_ctx *conf_ctx,
499                          int argc, const char **argv)
500 {
501         int ret = -1;
502         WERROR werr;
503
504         if (argc != 0 || c->display_usage) {
505                 net_conf_drop_usage(c, argc, argv);
506                 goto done;
507         }
508
509         werr = smbconf_drop(conf_ctx);
510         if (!W_ERROR_IS_OK(werr)) {
511                 d_fprintf(stderr, _("Error deleting configuration: %s\n"),
512                           win_errstr(werr));
513                 goto done;
514         }
515
516         ret = 0;
517
518 done:
519         return ret;
520 }
521
522 static int net_conf_showshare(struct net_context *c,
523                               struct smbconf_ctx *conf_ctx, int argc,
524                               const char **argv)
525 {
526         int ret = -1;
527         WERROR werr = WERR_OK;
528         const char *sharename = NULL;
529         TALLOC_CTX *mem_ctx;
530         uint32_t count;
531         struct smbconf_service *service = NULL;
532
533         mem_ctx = talloc_stackframe();
534
535         if (argc != 1 || c->display_usage) {
536                 net_conf_showshare_usage(c, argc, argv);
537                 goto done;
538         }
539
540         sharename = talloc_strdup(mem_ctx, argv[0]);
541         if (sharename == NULL) {
542                 d_printf("error: out of memory!\n");
543                 goto done;
544         }
545
546         werr = smbconf_get_share(conf_ctx, mem_ctx, sharename, &service);
547         if (!W_ERROR_IS_OK(werr)) {
548                 d_printf(_("error getting share parameters: %s\n"),
549                          win_errstr(werr));
550                 goto done;
551         }
552
553         d_printf("[%s]\n", service->name);
554
555         for (count = 0; count < service->num_params; count++) {
556                 d_printf("\t%s = %s\n", service->param_names[count],
557                          service->param_values[count]);
558         }
559
560         ret = 0;
561
562 done:
563         TALLOC_FREE(mem_ctx);
564         return ret;
565 }
566
567 /**
568  * Add a share, with a couple of standard parameters, partly optional.
569  *
570  * This is a high level utility function of the net conf utility,
571  * not a direct frontend to the smbconf API.
572  */
573 static int net_conf_addshare(struct net_context *c,
574                              struct smbconf_ctx *conf_ctx, int argc,
575                              const char **argv)
576 {
577         int ret = -1;
578         WERROR werr = WERR_OK;
579         char *sharename = NULL;
580         const char *path = NULL;
581         const char *comment = NULL;
582         const char *guest_ok = "no";
583         const char *writeable = "no";
584         SMB_STRUCT_STAT sbuf;
585         TALLOC_CTX *mem_ctx = talloc_stackframe();
586
587         if (c->display_usage) {
588                 net_conf_addshare_usage(c, argc, argv);
589                 ret = 0;
590                 goto done;
591         }
592
593         switch (argc) {
594                 case 0:
595                 case 1:
596                 default:
597                         net_conf_addshare_usage(c, argc, argv);
598                         goto done;
599                 case 5:
600                         comment = argv[4];
601                 case 4:
602                         if (!strnequal(argv[3], "guest_ok=", 9)) {
603                                 net_conf_addshare_usage(c, argc, argv);
604                                 goto done;
605                         }
606                         switch (argv[3][9]) {
607                                 case 'y':
608                                 case 'Y':
609                                         guest_ok = "yes";
610                                         break;
611                                 case 'n':
612                                 case 'N':
613                                         guest_ok = "no";
614                                         break;
615                                 default:
616                                         net_conf_addshare_usage(c, argc, argv);
617                                         goto done;
618                         }
619                 case 3:
620                         if (!strnequal(argv[2], "writeable=", 10)) {
621                                 net_conf_addshare_usage(c, argc, argv);
622                                 goto done;
623                         }
624                         switch (argv[2][10]) {
625                                 case 'y':
626                                 case 'Y':
627                                         writeable = "yes";
628                                         break;
629                                 case 'n':
630                                 case 'N':
631                                         writeable = "no";
632                                         break;
633                                 default:
634                                         net_conf_addshare_usage(c, argc, argv);
635                                         goto done;
636                         }
637                 case 2:
638                         path = argv[1];
639                         sharename = talloc_strdup(mem_ctx, argv[0]);
640                         if (sharename == NULL) {
641                                 d_printf(_("error: out of memory!\n"));
642                                 goto done;
643                         }
644
645                         break;
646         }
647
648         /*
649          * validate arguments
650          */
651
652         /* validate share name */
653
654         if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
655                                strlen(sharename)))
656         {
657                 d_fprintf(stderr, _("ERROR: share name %s contains "
658                         "invalid characters (any of %s)\n"),
659                         sharename, INVALID_SHARENAME_CHARS);
660                 goto done;
661         }
662
663         if (strequal(sharename, GLOBAL_NAME)) {
664                 d_fprintf(stderr,
665                           _("ERROR: 'global' is not a valid share name.\n"));
666                 goto done;
667         }
668
669         if (smbconf_share_exists(conf_ctx, sharename)) {
670                 d_fprintf(stderr, _("ERROR: share %s already exists.\n"),
671                           sharename);
672                 goto done;
673         }
674
675         /* validate path */
676
677         if (path[0] != '/') {
678                 d_fprintf(stderr,
679                           _("Error: path '%s' is not an absolute path.\n"),
680                           path);
681                 goto done;
682         }
683
684         if (sys_stat(path, &sbuf, false) != 0) {
685                 d_fprintf(stderr,
686                           _("ERROR: cannot stat path '%s' to ensure "
687                             "this is a directory.\n"
688                             "Error was '%s'.\n"),
689                           path, strerror(errno));
690                 goto done;
691         }
692
693         if (!S_ISDIR(sbuf.st_ex_mode)) {
694                 d_fprintf(stderr,
695                           _("ERROR: path '%s' is not a directory.\n"),
696                           path);
697                 goto done;
698         }
699
700         /*
701          * start a transaction
702          */
703
704         werr = smbconf_transaction_start(conf_ctx);
705         if (!W_ERROR_IS_OK(werr)) {
706                 d_printf("error starting transaction: %s\n",
707                          win_errstr(werr));
708                 goto done;
709         }
710
711         /*
712          * create the share
713          */
714
715         werr = smbconf_create_share(conf_ctx, sharename);
716         if (!W_ERROR_IS_OK(werr)) {
717                 d_fprintf(stderr, _("Error creating share %s: %s\n"),
718                           sharename, win_errstr(werr));
719                 goto cancel;
720         }
721
722         /*
723          * fill the share with parameters
724          */
725
726         werr = smbconf_set_parameter(conf_ctx, sharename, "path", path);
727         if (!W_ERROR_IS_OK(werr)) {
728                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
729                           "path", win_errstr(werr));
730                 goto cancel;
731         }
732
733         if (comment != NULL) {
734                 werr = smbconf_set_parameter(conf_ctx, sharename, "comment",
735                                              comment);
736                 if (!W_ERROR_IS_OK(werr)) {
737                         d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
738                                   "comment", win_errstr(werr));
739                         goto cancel;
740                 }
741         }
742
743         werr = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
744         if (!W_ERROR_IS_OK(werr)) {
745                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
746                           "'guest ok'", win_errstr(werr));
747                 goto cancel;
748         }
749
750         werr = smbconf_set_parameter(conf_ctx, sharename, "writeable",
751                                      writeable);
752         if (!W_ERROR_IS_OK(werr)) {
753                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
754                           "writeable", win_errstr(werr));
755                 goto cancel;
756         }
757
758         /*
759          * commit the whole thing
760          */
761
762         werr = smbconf_transaction_commit(conf_ctx);
763         if (!W_ERROR_IS_OK(werr)) {
764                 d_printf("error committing transaction: %s\n",
765                          win_errstr(werr));
766         } else {
767                 ret = 0;
768         }
769
770         goto done;
771
772 cancel:
773         werr = smbconf_transaction_cancel(conf_ctx);
774         if (!W_ERROR_IS_OK(werr)) {
775                 d_printf("error cancelling transaction: %s\n",
776                          win_errstr(werr));
777         }
778
779 done:
780         TALLOC_FREE(mem_ctx);
781         return ret;
782 }
783
784 static int net_conf_delshare(struct net_context *c,
785                              struct smbconf_ctx *conf_ctx, int argc,
786                              const char **argv)
787 {
788         int ret = -1;
789         const char *sharename = NULL;
790         WERROR werr = WERR_OK;
791         TALLOC_CTX *mem_ctx = talloc_stackframe();
792
793         if (argc != 1 || c->display_usage) {
794                 net_conf_delshare_usage(c, argc, argv);
795                 goto done;
796         }
797         sharename = talloc_strdup(mem_ctx, argv[0]);
798         if (sharename == NULL) {
799                 d_printf(_("error: out of memory!\n"));
800                 goto done;
801         }
802
803         werr = smbconf_delete_share(conf_ctx, sharename);
804         if (!W_ERROR_IS_OK(werr)) {
805                 d_fprintf(stderr, _("Error deleting share %s: %s\n"),
806                           sharename, win_errstr(werr));
807                 goto done;
808         }
809
810         ret = 0;
811 done:
812         TALLOC_FREE(mem_ctx);
813         return ret;
814 }
815
816 static int net_conf_setparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
817                             int argc, const char **argv)
818 {
819         int ret = -1;
820         WERROR werr = WERR_OK;
821         char *service = NULL;
822         char *param = NULL;
823         const char *value_str = NULL;
824         TALLOC_CTX *mem_ctx = talloc_stackframe();
825
826         if (argc != 3 || c->display_usage) {
827                 net_conf_setparm_usage(c, argc, argv);
828                 goto done;
829         }
830         /*
831          * NULL service name means "dangling parameters" to libsmbconf.
832          * We use the empty string from the command line for this purpose.
833          */
834         if (strlen(argv[0]) != 0) {
835                 service = talloc_strdup(mem_ctx, argv[0]);
836                 if (service == NULL) {
837                         d_printf(_("error: out of memory!\n"));
838                         goto done;
839                 }
840         }
841         param = strlower_talloc(mem_ctx, argv[1]);
842         if (param == NULL) {
843                 d_printf(_("error: out of memory!\n"));
844                 goto done;
845         }
846         value_str = argv[2];
847
848         werr = smbconf_transaction_start(conf_ctx);
849         if (!W_ERROR_IS_OK(werr)) {
850                 d_printf(_("error starting transaction: %s\n"),
851                          win_errstr(werr));
852                 goto done;
853         }
854
855         if (!smbconf_share_exists(conf_ctx, service)) {
856                 werr = smbconf_create_share(conf_ctx, service);
857                 if (!W_ERROR_IS_OK(werr)) {
858                         d_fprintf(stderr, _("Error creating share '%s': %s\n"),
859                                   service, win_errstr(werr));
860                         goto cancel;
861                 }
862         }
863
864         werr = smbconf_set_parameter(conf_ctx, service, param, value_str);
865
866         if (!W_ERROR_IS_OK(werr)) {
867                 d_fprintf(stderr, _("Error setting value '%s': %s\n"),
868                           param, win_errstr(werr));
869                 goto cancel;
870         }
871
872         werr = smbconf_transaction_commit(conf_ctx);
873         if (!W_ERROR_IS_OK(werr)) {
874                 d_printf(_("error committing transaction: %s\n"),
875                          win_errstr(werr));
876         } else {
877                 ret = 0;
878         }
879
880         goto done;
881
882 cancel:
883         werr = smbconf_transaction_cancel(conf_ctx);
884         if (!W_ERROR_IS_OK(werr)) {
885                 d_printf(_("error cancelling transaction: %s\n"),
886                          win_errstr(werr));
887         }
888
889 done:
890         TALLOC_FREE(mem_ctx);
891         return ret;
892 }
893
894 static int net_conf_getparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
895                             int argc, const char **argv)
896 {
897         int ret = -1;
898         WERROR werr = WERR_OK;
899         char *service = NULL;
900         char *param = NULL;
901         char *valstr = NULL;
902         TALLOC_CTX *mem_ctx;
903
904         mem_ctx = talloc_stackframe();
905
906         if (argc != 2 || c->display_usage) {
907                 net_conf_getparm_usage(c, argc, argv);
908                 goto done;
909         }
910         /*
911          * NULL service name means "dangling parameters" to libsmbconf.
912          * We use the empty string from the command line for this purpose.
913          */
914         if (strlen(argv[0]) != 0) {
915                 service = talloc_strdup(mem_ctx, argv[0]);
916                 if (service == NULL) {
917                         d_printf(_("error: out of memory!\n"));
918                         goto done;
919                 }
920         }
921         param = strlower_talloc(mem_ctx, argv[1]);
922         if (param == NULL) {
923                 d_printf(_("error: out of memory!\n"));
924                 goto done;
925         }
926
927         werr = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
928
929         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
930                 d_fprintf(stderr,
931                           _("Error: given service '%s' does not exist.\n"),
932                           service);
933                 goto done;
934         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
935                 d_fprintf(stderr,
936                           _("Error: given parameter '%s' is not set.\n"),
937                           param);
938                 goto done;
939         } else if (!W_ERROR_IS_OK(werr)) {
940                 d_fprintf(stderr, _("Error getting value '%s': %s.\n"),
941                           param, win_errstr(werr));
942                 goto done;
943         }
944
945         d_printf("%s\n", valstr);
946
947         ret = 0;
948 done:
949         TALLOC_FREE(mem_ctx);
950         return ret;
951 }
952
953 static int net_conf_delparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
954                             int argc, const char **argv)
955 {
956         int ret = -1;
957         WERROR werr = WERR_OK;
958         char *service = NULL;
959         char *param = NULL;
960         TALLOC_CTX *mem_ctx = talloc_stackframe();
961
962         if (argc != 2 || c->display_usage) {
963                 net_conf_delparm_usage(c, argc, argv);
964                 goto done;
965         }
966         /*
967          * NULL service name means "dangling parameters" to libsmbconf.
968          * We use the empty string from the command line for this purpose.
969          */
970         if (strlen(argv[0]) != 0) {
971                 service = talloc_strdup(mem_ctx, argv[0]);
972                 if (service == NULL) {
973                         d_printf(_("error: out of memory!\n"));
974                         goto done;
975                 }
976         }
977         param = strlower_talloc(mem_ctx, argv[1]);
978         if (param == NULL) {
979                 d_printf("error: out of memory!\n");
980                 goto done;
981         }
982
983         werr = smbconf_delete_parameter(conf_ctx, service, param);
984
985         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
986                 d_fprintf(stderr,
987                           _("Error: given service '%s' does not exist.\n"),
988                           service);
989                 goto done;
990         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
991                 d_fprintf(stderr,
992                           _("Error: given parameter '%s' is not set.\n"),
993                           param);
994                 goto done;
995         } else if (!W_ERROR_IS_OK(werr)) {
996                 d_fprintf(stderr, _("Error deleting value '%s': %s.\n"),
997                           param, win_errstr(werr));
998                 goto done;
999         }
1000
1001         ret = 0;
1002
1003 done:
1004         TALLOC_FREE(mem_ctx);
1005         return ret;
1006 }
1007
1008 static int net_conf_getincludes(struct net_context *c,
1009                                 struct smbconf_ctx *conf_ctx,
1010                                 int argc, const char **argv)
1011 {
1012         WERROR werr;
1013         uint32_t num_includes;
1014         uint32_t count;
1015         char *service;
1016         char **includes = NULL;
1017         int ret = -1;
1018         TALLOC_CTX *mem_ctx = talloc_stackframe();
1019
1020         if (argc != 1 || c->display_usage) {
1021                 net_conf_getincludes_usage(c, argc, argv);
1022                 goto done;
1023         }
1024
1025         service = talloc_strdup(mem_ctx, argv[0]);
1026         if (service == NULL) {
1027                 d_printf(_("error: out of memory!\n"));
1028                 goto done;
1029         }
1030
1031         werr = smbconf_get_includes(conf_ctx, mem_ctx, service,
1032                                     &num_includes, &includes);
1033         if (!W_ERROR_IS_OK(werr)) {
1034                 d_printf(_("error getting includes: %s\n"), win_errstr(werr));
1035                 goto done;
1036         }
1037
1038         for (count = 0; count < num_includes; count++) {
1039                 d_printf("include = %s\n", includes[count]);
1040         }
1041
1042         ret = 0;
1043
1044 done:
1045         TALLOC_FREE(mem_ctx);
1046         return ret;
1047 }
1048
1049 static int net_conf_setincludes(struct net_context *c,
1050                                 struct smbconf_ctx *conf_ctx,
1051                                 int argc, const char **argv)
1052 {
1053         WERROR werr;
1054         char *service;
1055         uint32_t num_includes;
1056         const char **includes;
1057         int ret = -1;
1058         TALLOC_CTX *mem_ctx = talloc_stackframe();
1059
1060         if (argc < 1 || c->display_usage) {
1061                 net_conf_setincludes_usage(c, argc, argv);
1062                 goto done;
1063         }
1064
1065         service = talloc_strdup(mem_ctx, argv[0]);
1066         if (service == NULL) {
1067                 d_printf(_("error: out of memory!\n"));
1068                 goto done;
1069         }
1070
1071         num_includes = argc - 1;
1072         if (num_includes == 0) {
1073                 includes = NULL;
1074         } else {
1075                 includes = argv + 1;
1076         }
1077
1078         werr = smbconf_set_includes(conf_ctx, service, num_includes, includes);
1079         if (!W_ERROR_IS_OK(werr)) {
1080                 d_printf(_("error setting includes: %s\n"), win_errstr(werr));
1081                 goto done;
1082         }
1083
1084         ret = 0;
1085
1086 done:
1087         TALLOC_FREE(mem_ctx);
1088         return ret;
1089 }
1090
1091 static int net_conf_delincludes(struct net_context *c,
1092                                 struct smbconf_ctx *conf_ctx,
1093                                 int argc, const char **argv)
1094 {
1095         WERROR werr;
1096         char *service;
1097         int ret = -1;
1098         TALLOC_CTX *mem_ctx = talloc_stackframe();
1099
1100         if (argc != 1 || c->display_usage) {
1101                 net_conf_delincludes_usage(c, argc, argv);
1102                 goto done;
1103         }
1104
1105         service = talloc_strdup(mem_ctx, argv[0]);
1106         if (service == NULL) {
1107                 d_printf(_("error: out of memory!\n"));
1108                 goto done;
1109         }
1110
1111         werr = smbconf_delete_includes(conf_ctx, service);
1112         if (!W_ERROR_IS_OK(werr)) {
1113                 d_printf(_("error deleting includes: %s\n"), win_errstr(werr));
1114                 goto done;
1115         }
1116
1117         ret = 0;
1118
1119 done:
1120         TALLOC_FREE(mem_ctx);
1121         return ret;
1122 }
1123
1124
1125 /**********************************************************************
1126  *
1127  * Wrapper and net_conf_run_function mechanism.
1128  *
1129  **********************************************************************/
1130
1131 /**
1132  * Wrapper function to call the main conf functions.
1133  * The wrapper calls handles opening and closing of the
1134  * configuration.
1135  */
1136 static int net_conf_wrap_function(struct net_context *c,
1137                                   int (*fn)(struct net_context *,
1138                                             struct smbconf_ctx *,
1139                                             int, const char **),
1140                                   int argc, const char **argv)
1141 {
1142         WERROR werr;
1143         TALLOC_CTX *mem_ctx = talloc_stackframe();
1144         struct smbconf_ctx *conf_ctx;
1145         int ret = -1;
1146
1147         werr = smbconf_init(mem_ctx, &conf_ctx, "registry:");
1148
1149         if (!W_ERROR_IS_OK(werr)) {
1150                 return -1;
1151         }
1152
1153         ret = fn(c, conf_ctx, argc, argv);
1154
1155         smbconf_shutdown(conf_ctx);
1156
1157         return ret;
1158 }
1159
1160 /*
1161  * We need a functable struct of our own, because the
1162  * functions are called through a wrapper that handles
1163  * the opening and closing of the configuration, and so on.
1164  */
1165 struct conf_functable {
1166         const char *funcname;
1167         int (*fn)(struct net_context *c, struct smbconf_ctx *ctx, int argc,
1168                   const char **argv);
1169         int valid_transports;
1170         const char *description;
1171         const char *usage;
1172 };
1173
1174 /**
1175  * This imitates net_run_function but calls the main functions
1176  * through the wrapper net_conf_wrap_function().
1177  */
1178 static int net_conf_run_function(struct net_context *c, int argc,
1179                                  const char **argv, const char *whoami,
1180                                  struct conf_functable *table)
1181 {
1182         int i;
1183
1184         if (argc != 0) {
1185                 for (i=0; table[i].funcname; i++) {
1186                         if (StrCaseCmp(argv[0], table[i].funcname) == 0)
1187                                 return net_conf_wrap_function(c, table[i].fn,
1188                                                               argc-1,
1189                                                               argv+1);
1190                 }
1191         }
1192
1193         d_printf(_("Usage:\n"));
1194         for (i=0; table[i].funcname; i++) {
1195                 if (c->display_usage == false)
1196                         d_printf("%s %-15s %s\n", whoami, table[i].funcname,
1197                                  table[i].description);
1198                 else
1199                         d_printf("%s\n", table[i].usage);
1200         }
1201
1202         return c->display_usage?0:-1;
1203 }
1204
1205 /*
1206  * Entry-point for all the CONF functions.
1207  */
1208
1209 int net_conf(struct net_context *c, int argc, const char **argv)
1210 {
1211         int ret = -1;
1212         struct conf_functable func_table[] = {
1213                 {
1214                         "list",
1215                         net_conf_list,
1216                         NET_TRANSPORT_LOCAL,
1217                         N_("Dump the complete configuration in smb.conf like "
1218                            "format."),
1219                         N_("net conf list\n"
1220                            "    Dump the complete configuration in smb.conf "
1221                            "like format.")
1222
1223                 },
1224                 {
1225                         "import",
1226                         net_conf_import,
1227                         NET_TRANSPORT_LOCAL,
1228                         N_("Import configuration from file in smb.conf "
1229                            "format."),
1230                         N_("net conf import\n"
1231                            "    Import configuration from file in smb.conf "
1232                            "format.")
1233                 },
1234                 {
1235                         "listshares",
1236                         net_conf_listshares,
1237                         NET_TRANSPORT_LOCAL,
1238                         N_("List the share names."),
1239                         N_("net conf listshares\n"
1240                            "    List the share names.")
1241                 },
1242                 {
1243                         "drop",
1244                         net_conf_drop,
1245                         NET_TRANSPORT_LOCAL,
1246                         N_("Delete the complete configuration."),
1247                         N_("net conf drop\n"
1248                            "    Delete the complete configuration.")
1249                 },
1250                 {
1251                         "showshare",
1252                         net_conf_showshare,
1253                         NET_TRANSPORT_LOCAL,
1254                         N_("Show the definition of a share."),
1255                         N_("net conf showshare\n"
1256                            "    Show the definition of a share.")
1257                 },
1258                 {
1259                         "addshare",
1260                         net_conf_addshare,
1261                         NET_TRANSPORT_LOCAL,
1262                         N_("Create a new share."),
1263                         N_("net conf addshare\n"
1264                            "    Create a new share.")
1265                 },
1266                 {
1267                         "delshare",
1268                         net_conf_delshare,
1269                         NET_TRANSPORT_LOCAL,
1270                         N_("Delete a share."),
1271                         N_("net conf delshare\n"
1272                            "    Delete a share.")
1273                 },
1274                 {
1275                         "setparm",
1276                         net_conf_setparm,
1277                         NET_TRANSPORT_LOCAL,
1278                         N_("Store a parameter."),
1279                         N_("net conf setparm\n"
1280                            "    Store a parameter.")
1281                 },
1282                 {
1283                         "getparm",
1284                         net_conf_getparm,
1285                         NET_TRANSPORT_LOCAL,
1286                         N_("Retrieve the value of a parameter."),
1287                         N_("net conf getparm\n"
1288                            "    Retrieve the value of a parameter.")
1289                 },
1290                 {
1291                         "delparm",
1292                         net_conf_delparm,
1293                         NET_TRANSPORT_LOCAL,
1294                         N_("Delete a parameter."),
1295                         N_("net conf delparm\n"
1296                            "    Delete a parameter.")
1297                 },
1298                 {
1299                         "getincludes",
1300                         net_conf_getincludes,
1301                         NET_TRANSPORT_LOCAL,
1302                         N_("Show the includes of a share definition."),
1303                         N_("net conf getincludes\n"
1304                            "    Show the includes of a share definition.")
1305                 },
1306                 {
1307                         "setincludes",
1308                         net_conf_setincludes,
1309                         NET_TRANSPORT_LOCAL,
1310                         N_("Set includes for a share."),
1311                         N_("net conf setincludes\n"
1312                            "    Set includes for a share.")
1313                 },
1314                 {
1315                         "delincludes",
1316                         net_conf_delincludes,
1317                         NET_TRANSPORT_LOCAL,
1318                         N_("Delete includes from a share definition."),
1319                         N_("net conf setincludes\n"
1320                            "    Delete includes from a share definition.")
1321                 },
1322                 {NULL, NULL, 0, NULL, NULL}
1323         };
1324
1325         ret = net_conf_run_function(c, argc, argv, "net conf", func_table);
1326
1327         return ret;
1328 }
1329