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