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