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