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