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