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