192088c6ba5eeabaafc30dab4d9492971d93ec6e
[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         sbcErr err;
320
321         if (c->display_usage)
322                 return net_conf_import_usage(c, argc, argv);
323
324         mem_ctx = talloc_stackframe();
325
326         switch (argc) {
327                 case 0:
328                 default:
329                         net_conf_import_usage(c, argc, argv);
330                         goto done;
331                 case 2:
332                         servicename = talloc_strdup(mem_ctx, argv[1]);
333                         if (servicename == NULL) {
334                                 d_printf(_("error: out of memory!\n"));
335                                 goto done;
336                         }
337                 case 1:
338                         filename = argv[0];
339                         break;
340         }
341
342         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
343                 filename));
344
345         conf_source = talloc_asprintf(mem_ctx, "file:%s", filename);
346         if (conf_source == NULL) {
347                 d_printf(_("error: out of memory!\n"));
348                 goto done;
349         }
350
351         err = smbconf_init(mem_ctx, &txt_ctx, conf_source);
352         if (!SBC_ERROR_IS_OK(err)) {
353                 d_printf(_("error loading file '%s': %s\n"), filename,
354                          sbcErrorString(err));
355                 werr = WERR_NO_SUCH_SERVICE;
356                 goto done;
357         }
358
359         if (c->opt_testmode) {
360                 d_printf(_("\nTEST MODE - "
361                          "would import the following configuration:\n\n"));
362         }
363
364         if (servicename != NULL) {
365                 struct smbconf_service *service = NULL;
366
367                 werr = smbconf_get_share(txt_ctx, mem_ctx,
368                                          servicename,
369                                          &service);
370                 if (!W_ERROR_IS_OK(werr)) {
371                         goto cancel;
372                 }
373
374                 werr = smbconf_transaction_start(conf_ctx);
375                 if (!W_ERROR_IS_OK(werr)) {
376                         d_printf(_("error starting transaction: %s\n"),
377                                  win_errstr(werr));
378                         goto done;
379                 }
380
381                 werr = import_process_service(c, conf_ctx, service);
382                 if (!W_ERROR_IS_OK(werr)) {
383                         goto cancel;
384                 }
385         } else {
386                 struct smbconf_service **services = NULL;
387                 uint32_t num_shares, sidx;
388
389                 werr = smbconf_get_config(txt_ctx, mem_ctx,
390                                           &num_shares,
391                                           &services);
392                 if (!W_ERROR_IS_OK(werr)) {
393                         goto cancel;
394                 }
395                 if (!c->opt_testmode) {
396                         if (!SBC_ERROR_IS_OK(smbconf_drop(conf_ctx))) {
397                                 goto cancel;
398                         }
399                 }
400
401                 /*
402                  * Wrap the importing of shares into a transaction,
403                  * but only 100 at a time, in order to save memory.
404                  * The allocated memory accumulates across the actions
405                  * within the transaction, and for me, some 1500
406                  * imported shares, the MAX_TALLOC_SIZE of 256 MB
407                  * was exceeded.
408                  */
409                 werr = smbconf_transaction_start(conf_ctx);
410                 if (!W_ERROR_IS_OK(werr)) {
411                         d_printf(_("error starting transaction: %s\n"),
412                                  win_errstr(werr));
413                         goto done;
414                 }
415
416                 for (sidx = 0; sidx < num_shares; sidx++) {
417                         werr = import_process_service(c, conf_ctx,
418                                                       services[sidx]);
419                         if (!W_ERROR_IS_OK(werr)) {
420                                 goto cancel;
421                         }
422
423                         if (sidx % 100) {
424                                 continue;
425                         }
426
427                         werr = smbconf_transaction_commit(conf_ctx);
428                         if (!W_ERROR_IS_OK(werr)) {
429                                 d_printf(_("error committing transaction: "
430                                            "%s\n"),
431                                          win_errstr(werr));
432                                 goto done;
433                         }
434                         werr = smbconf_transaction_start(conf_ctx);
435                         if (!W_ERROR_IS_OK(werr)) {
436                                 d_printf(_("error starting transaction: %s\n"),
437                                          win_errstr(werr));
438                                 goto done;
439                         }
440                 }
441         }
442
443         werr = smbconf_transaction_commit(conf_ctx);
444         if (!W_ERROR_IS_OK(werr)) {
445                 d_printf(_("error committing transaction: %s\n"),
446                          win_errstr(werr));
447         } else {
448                 ret = 0;
449         }
450
451         goto done;
452
453 cancel:
454         werr = smbconf_transaction_cancel(conf_ctx);
455         if (!W_ERROR_IS_OK(werr)) {
456                 d_printf(_("error cancelling transaction: %s\n"),
457                          win_errstr(werr));
458         }
459
460 done:
461         TALLOC_FREE(mem_ctx);
462         return ret;
463 }
464
465 static int net_conf_listshares(struct net_context *c,
466                                struct smbconf_ctx *conf_ctx, int argc,
467                                const char **argv)
468 {
469         sbcErr err;
470         int ret = -1;
471         uint32_t count, num_shares = 0;
472         char **share_names = NULL;
473         TALLOC_CTX *mem_ctx;
474
475         mem_ctx = talloc_stackframe();
476
477         if (argc != 0 || c->display_usage) {
478                 net_conf_listshares_usage(c, argc, argv);
479                 goto done;
480         }
481
482         err = smbconf_get_share_names(conf_ctx, mem_ctx, &num_shares,
483                                       &share_names);
484         if (!SBC_ERROR_IS_OK(err)) {
485                 goto done;
486         }
487
488         for (count = 0; count < num_shares; count++)
489         {
490                 d_printf("%s\n", share_names[count]);
491         }
492
493         ret = 0;
494
495 done:
496         TALLOC_FREE(mem_ctx);
497         return ret;
498 }
499
500 static int net_conf_drop(struct net_context *c, struct smbconf_ctx *conf_ctx,
501                          int argc, const char **argv)
502 {
503         int ret = -1;
504         sbcErr err;
505
506         if (argc != 0 || c->display_usage) {
507                 net_conf_drop_usage(c, argc, argv);
508                 goto done;
509         }
510
511         err = smbconf_drop(conf_ctx);
512         if (!SBC_ERROR_IS_OK(err)) {
513                 d_fprintf(stderr, _("Error deleting configuration: %s\n"),
514                           sbcErrorString(err));
515                 goto done;
516         }
517
518         ret = 0;
519
520 done:
521         return ret;
522 }
523
524 static int net_conf_showshare(struct net_context *c,
525                               struct smbconf_ctx *conf_ctx, int argc,
526                               const char **argv)
527 {
528         int ret = -1;
529         WERROR werr = WERR_OK;
530         const char *sharename = NULL;
531         TALLOC_CTX *mem_ctx;
532         uint32_t count;
533         struct smbconf_service *service = NULL;
534
535         mem_ctx = talloc_stackframe();
536
537         if (argc != 1 || c->display_usage) {
538                 net_conf_showshare_usage(c, argc, argv);
539                 goto done;
540         }
541
542         sharename = talloc_strdup(mem_ctx, argv[0]);
543         if (sharename == NULL) {
544                 d_printf("error: out of memory!\n");
545                 goto done;
546         }
547
548         werr = smbconf_get_share(conf_ctx, mem_ctx, sharename, &service);
549         if (!W_ERROR_IS_OK(werr)) {
550                 d_printf(_("error getting share parameters: %s\n"),
551                          win_errstr(werr));
552                 goto done;
553         }
554
555         d_printf("[%s]\n", service->name);
556
557         for (count = 0; count < service->num_params; count++) {
558                 d_printf("\t%s = %s\n", service->param_names[count],
559                          service->param_values[count]);
560         }
561
562         ret = 0;
563
564 done:
565         TALLOC_FREE(mem_ctx);
566         return ret;
567 }
568
569 /**
570  * Add a share, with a couple of standard parameters, partly optional.
571  *
572  * This is a high level utility function of the net conf utility,
573  * not a direct frontend to the smbconf API.
574  */
575 static int net_conf_addshare(struct net_context *c,
576                              struct smbconf_ctx *conf_ctx, int argc,
577                              const char **argv)
578 {
579         int ret = -1;
580         WERROR werr = WERR_OK;
581         char *sharename = NULL;
582         const char *path = NULL;
583         const char *comment = NULL;
584         const char *guest_ok = "no";
585         const char *writeable = "no";
586         SMB_STRUCT_STAT sbuf;
587         TALLOC_CTX *mem_ctx = talloc_stackframe();
588
589         if (c->display_usage) {
590                 net_conf_addshare_usage(c, argc, argv);
591                 ret = 0;
592                 goto done;
593         }
594
595         switch (argc) {
596                 case 0:
597                 case 1:
598                 default:
599                         net_conf_addshare_usage(c, argc, argv);
600                         goto done;
601                 case 5:
602                         comment = argv[4];
603                 case 4:
604                         if (!strnequal(argv[3], "guest_ok=", 9)) {
605                                 net_conf_addshare_usage(c, argc, argv);
606                                 goto done;
607                         }
608                         switch (argv[3][9]) {
609                                 case 'y':
610                                 case 'Y':
611                                         guest_ok = "yes";
612                                         break;
613                                 case 'n':
614                                 case 'N':
615                                         guest_ok = "no";
616                                         break;
617                                 default:
618                                         net_conf_addshare_usage(c, argc, argv);
619                                         goto done;
620                         }
621                 case 3:
622                         if (!strnequal(argv[2], "writeable=", 10)) {
623                                 net_conf_addshare_usage(c, argc, argv);
624                                 goto done;
625                         }
626                         switch (argv[2][10]) {
627                                 case 'y':
628                                 case 'Y':
629                                         writeable = "yes";
630                                         break;
631                                 case 'n':
632                                 case 'N':
633                                         writeable = "no";
634                                         break;
635                                 default:
636                                         net_conf_addshare_usage(c, argc, argv);
637                                         goto done;
638                         }
639                 case 2:
640                         path = argv[1];
641                         sharename = talloc_strdup(mem_ctx, argv[0]);
642                         if (sharename == NULL) {
643                                 d_printf(_("error: out of memory!\n"));
644                                 goto done;
645                         }
646
647                         break;
648         }
649
650         /*
651          * validate arguments
652          */
653
654         /* validate share name */
655
656         if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
657                                strlen(sharename)))
658         {
659                 d_fprintf(stderr, _("ERROR: share name %s contains "
660                         "invalid characters (any of %s)\n"),
661                         sharename, INVALID_SHARENAME_CHARS);
662                 goto done;
663         }
664
665         if (strequal(sharename, GLOBAL_NAME)) {
666                 d_fprintf(stderr,
667                           _("ERROR: 'global' is not a valid share name.\n"));
668                 goto done;
669         }
670
671         if (smbconf_share_exists(conf_ctx, sharename)) {
672                 d_fprintf(stderr, _("ERROR: share %s already exists.\n"),
673                           sharename);
674                 goto done;
675         }
676
677         /* validate path */
678
679         if (path[0] != '/') {
680                 d_fprintf(stderr,
681                           _("Error: path '%s' is not an absolute path.\n"),
682                           path);
683                 goto done;
684         }
685
686         if (sys_stat(path, &sbuf, false) != 0) {
687                 d_fprintf(stderr,
688                           _("ERROR: cannot stat path '%s' to ensure "
689                             "this is a directory.\n"
690                             "Error was '%s'.\n"),
691                           path, strerror(errno));
692                 goto done;
693         }
694
695         if (!S_ISDIR(sbuf.st_ex_mode)) {
696                 d_fprintf(stderr,
697                           _("ERROR: path '%s' is not a directory.\n"),
698                           path);
699                 goto done;
700         }
701
702         /*
703          * start a transaction
704          */
705
706         werr = smbconf_transaction_start(conf_ctx);
707         if (!W_ERROR_IS_OK(werr)) {
708                 d_printf("error starting transaction: %s\n",
709                          win_errstr(werr));
710                 goto done;
711         }
712
713         /*
714          * create the share
715          */
716
717         werr = smbconf_create_share(conf_ctx, sharename);
718         if (!W_ERROR_IS_OK(werr)) {
719                 d_fprintf(stderr, _("Error creating share %s: %s\n"),
720                           sharename, win_errstr(werr));
721                 goto cancel;
722         }
723
724         /*
725          * fill the share with parameters
726          */
727
728         werr = smbconf_set_parameter(conf_ctx, sharename, "path", path);
729         if (!W_ERROR_IS_OK(werr)) {
730                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
731                           "path", win_errstr(werr));
732                 goto cancel;
733         }
734
735         if (comment != NULL) {
736                 werr = smbconf_set_parameter(conf_ctx, sharename, "comment",
737                                              comment);
738                 if (!W_ERROR_IS_OK(werr)) {
739                         d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
740                                   "comment", win_errstr(werr));
741                         goto cancel;
742                 }
743         }
744
745         werr = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
746         if (!W_ERROR_IS_OK(werr)) {
747                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
748                           "'guest ok'", win_errstr(werr));
749                 goto cancel;
750         }
751
752         werr = smbconf_set_parameter(conf_ctx, sharename, "writeable",
753                                      writeable);
754         if (!W_ERROR_IS_OK(werr)) {
755                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
756                           "writeable", win_errstr(werr));
757                 goto cancel;
758         }
759
760         /*
761          * commit the whole thing
762          */
763
764         werr = smbconf_transaction_commit(conf_ctx);
765         if (!W_ERROR_IS_OK(werr)) {
766                 d_printf("error committing transaction: %s\n",
767                          win_errstr(werr));
768         } else {
769                 ret = 0;
770         }
771
772         goto done;
773
774 cancel:
775         werr = smbconf_transaction_cancel(conf_ctx);
776         if (!W_ERROR_IS_OK(werr)) {
777                 d_printf("error cancelling transaction: %s\n",
778                          win_errstr(werr));
779         }
780
781 done:
782         TALLOC_FREE(mem_ctx);
783         return ret;
784 }
785
786 static int net_conf_delshare(struct net_context *c,
787                              struct smbconf_ctx *conf_ctx, int argc,
788                              const char **argv)
789 {
790         int ret = -1;
791         const char *sharename = NULL;
792         WERROR werr = WERR_OK;
793         TALLOC_CTX *mem_ctx = talloc_stackframe();
794
795         if (argc != 1 || c->display_usage) {
796                 net_conf_delshare_usage(c, argc, argv);
797                 goto done;
798         }
799         sharename = talloc_strdup(mem_ctx, argv[0]);
800         if (sharename == NULL) {
801                 d_printf(_("error: out of memory!\n"));
802                 goto done;
803         }
804
805         werr = smbconf_delete_share(conf_ctx, sharename);
806         if (!W_ERROR_IS_OK(werr)) {
807                 d_fprintf(stderr, _("Error deleting share %s: %s\n"),
808                           sharename, win_errstr(werr));
809                 goto done;
810         }
811
812         ret = 0;
813 done:
814         TALLOC_FREE(mem_ctx);
815         return ret;
816 }
817
818 static int net_conf_setparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
819                             int argc, const char **argv)
820 {
821         int ret = -1;
822         WERROR werr = WERR_OK;
823         char *service = NULL;
824         char *param = NULL;
825         const char *value_str = NULL;
826         TALLOC_CTX *mem_ctx = talloc_stackframe();
827
828         if (argc != 3 || c->display_usage) {
829                 net_conf_setparm_usage(c, argc, argv);
830                 goto done;
831         }
832         /*
833          * NULL service name means "dangling parameters" to libsmbconf.
834          * We use the empty string from the command line for this purpose.
835          */
836         if (strlen(argv[0]) != 0) {
837                 service = talloc_strdup(mem_ctx, argv[0]);
838                 if (service == NULL) {
839                         d_printf(_("error: out of memory!\n"));
840                         goto done;
841                 }
842         }
843         param = strlower_talloc(mem_ctx, argv[1]);
844         if (param == NULL) {
845                 d_printf(_("error: out of memory!\n"));
846                 goto done;
847         }
848         value_str = argv[2];
849
850         werr = smbconf_transaction_start(conf_ctx);
851         if (!W_ERROR_IS_OK(werr)) {
852                 d_printf(_("error starting transaction: %s\n"),
853                          win_errstr(werr));
854                 goto done;
855         }
856
857         if (!smbconf_share_exists(conf_ctx, service)) {
858                 werr = smbconf_create_share(conf_ctx, service);
859                 if (!W_ERROR_IS_OK(werr)) {
860                         d_fprintf(stderr, _("Error creating share '%s': %s\n"),
861                                   service, win_errstr(werr));
862                         goto cancel;
863                 }
864         }
865
866         werr = smbconf_set_parameter(conf_ctx, service, param, value_str);
867
868         if (!W_ERROR_IS_OK(werr)) {
869                 d_fprintf(stderr, _("Error setting value '%s': %s\n"),
870                           param, win_errstr(werr));
871                 goto cancel;
872         }
873
874         werr = smbconf_transaction_commit(conf_ctx);
875         if (!W_ERROR_IS_OK(werr)) {
876                 d_printf(_("error committing transaction: %s\n"),
877                          win_errstr(werr));
878         } else {
879                 ret = 0;
880         }
881
882         goto done;
883
884 cancel:
885         werr = smbconf_transaction_cancel(conf_ctx);
886         if (!W_ERROR_IS_OK(werr)) {
887                 d_printf(_("error cancelling transaction: %s\n"),
888                          win_errstr(werr));
889         }
890
891 done:
892         TALLOC_FREE(mem_ctx);
893         return ret;
894 }
895
896 static int net_conf_getparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
897                             int argc, const char **argv)
898 {
899         int ret = -1;
900         WERROR werr = WERR_OK;
901         char *service = NULL;
902         char *param = NULL;
903         char *valstr = NULL;
904         TALLOC_CTX *mem_ctx;
905
906         mem_ctx = talloc_stackframe();
907
908         if (argc != 2 || c->display_usage) {
909                 net_conf_getparm_usage(c, argc, argv);
910                 goto done;
911         }
912         /*
913          * NULL service name means "dangling parameters" to libsmbconf.
914          * We use the empty string from the command line for this purpose.
915          */
916         if (strlen(argv[0]) != 0) {
917                 service = talloc_strdup(mem_ctx, argv[0]);
918                 if (service == NULL) {
919                         d_printf(_("error: out of memory!\n"));
920                         goto done;
921                 }
922         }
923         param = strlower_talloc(mem_ctx, argv[1]);
924         if (param == NULL) {
925                 d_printf(_("error: out of memory!\n"));
926                 goto done;
927         }
928
929         werr = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
930
931         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
932                 d_fprintf(stderr,
933                           _("Error: given service '%s' does not exist.\n"),
934                           service);
935                 goto done;
936         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
937                 d_fprintf(stderr,
938                           _("Error: given parameter '%s' is not set.\n"),
939                           param);
940                 goto done;
941         } else if (!W_ERROR_IS_OK(werr)) {
942                 d_fprintf(stderr, _("Error getting value '%s': %s.\n"),
943                           param, win_errstr(werr));
944                 goto done;
945         }
946
947         d_printf("%s\n", valstr);
948
949         ret = 0;
950 done:
951         TALLOC_FREE(mem_ctx);
952         return ret;
953 }
954
955 static int net_conf_delparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
956                             int argc, const char **argv)
957 {
958         int ret = -1;
959         WERROR werr = WERR_OK;
960         char *service = NULL;
961         char *param = NULL;
962         TALLOC_CTX *mem_ctx = talloc_stackframe();
963
964         if (argc != 2 || c->display_usage) {
965                 net_conf_delparm_usage(c, argc, argv);
966                 goto done;
967         }
968         /*
969          * NULL service name means "dangling parameters" to libsmbconf.
970          * We use the empty string from the command line for this purpose.
971          */
972         if (strlen(argv[0]) != 0) {
973                 service = talloc_strdup(mem_ctx, argv[0]);
974                 if (service == NULL) {
975                         d_printf(_("error: out of memory!\n"));
976                         goto done;
977                 }
978         }
979         param = strlower_talloc(mem_ctx, argv[1]);
980         if (param == NULL) {
981                 d_printf("error: out of memory!\n");
982                 goto done;
983         }
984
985         werr = smbconf_delete_parameter(conf_ctx, service, param);
986
987         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
988                 d_fprintf(stderr,
989                           _("Error: given service '%s' does not exist.\n"),
990                           service);
991                 goto done;
992         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
993                 d_fprintf(stderr,
994                           _("Error: given parameter '%s' is not set.\n"),
995                           param);
996                 goto done;
997         } else if (!W_ERROR_IS_OK(werr)) {
998                 d_fprintf(stderr, _("Error deleting value '%s': %s.\n"),
999                           param, win_errstr(werr));
1000                 goto done;
1001         }
1002
1003         ret = 0;
1004
1005 done:
1006         TALLOC_FREE(mem_ctx);
1007         return ret;
1008 }
1009
1010 static int net_conf_getincludes(struct net_context *c,
1011                                 struct smbconf_ctx *conf_ctx,
1012                                 int argc, const char **argv)
1013 {
1014         WERROR werr;
1015         uint32_t num_includes;
1016         uint32_t count;
1017         char *service;
1018         char **includes = NULL;
1019         int ret = -1;
1020         TALLOC_CTX *mem_ctx = talloc_stackframe();
1021
1022         if (argc != 1 || c->display_usage) {
1023                 net_conf_getincludes_usage(c, argc, argv);
1024                 goto done;
1025         }
1026
1027         service = talloc_strdup(mem_ctx, argv[0]);
1028         if (service == NULL) {
1029                 d_printf(_("error: out of memory!\n"));
1030                 goto done;
1031         }
1032
1033         werr = smbconf_get_includes(conf_ctx, mem_ctx, service,
1034                                     &num_includes, &includes);
1035         if (!W_ERROR_IS_OK(werr)) {
1036                 d_printf(_("error getting includes: %s\n"), win_errstr(werr));
1037                 goto done;
1038         }
1039
1040         for (count = 0; count < num_includes; count++) {
1041                 d_printf("include = %s\n", includes[count]);
1042         }
1043
1044         ret = 0;
1045
1046 done:
1047         TALLOC_FREE(mem_ctx);
1048         return ret;
1049 }
1050
1051 static int net_conf_setincludes(struct net_context *c,
1052                                 struct smbconf_ctx *conf_ctx,
1053                                 int argc, const char **argv)
1054 {
1055         WERROR werr;
1056         char *service;
1057         uint32_t num_includes;
1058         const char **includes;
1059         int ret = -1;
1060         TALLOC_CTX *mem_ctx = talloc_stackframe();
1061
1062         if (argc < 1 || c->display_usage) {
1063                 net_conf_setincludes_usage(c, argc, argv);
1064                 goto done;
1065         }
1066
1067         service = talloc_strdup(mem_ctx, argv[0]);
1068         if (service == NULL) {
1069                 d_printf(_("error: out of memory!\n"));
1070                 goto done;
1071         }
1072
1073         num_includes = argc - 1;
1074         if (num_includes == 0) {
1075                 includes = NULL;
1076         } else {
1077                 includes = argv + 1;
1078         }
1079
1080         werr = smbconf_set_includes(conf_ctx, service, num_includes, includes);
1081         if (!W_ERROR_IS_OK(werr)) {
1082                 d_printf(_("error setting includes: %s\n"), win_errstr(werr));
1083                 goto done;
1084         }
1085
1086         ret = 0;
1087
1088 done:
1089         TALLOC_FREE(mem_ctx);
1090         return ret;
1091 }
1092
1093 static int net_conf_delincludes(struct net_context *c,
1094                                 struct smbconf_ctx *conf_ctx,
1095                                 int argc, const char **argv)
1096 {
1097         WERROR werr;
1098         char *service;
1099         int ret = -1;
1100         TALLOC_CTX *mem_ctx = talloc_stackframe();
1101
1102         if (argc != 1 || c->display_usage) {
1103                 net_conf_delincludes_usage(c, argc, argv);
1104                 goto done;
1105         }
1106
1107         service = talloc_strdup(mem_ctx, argv[0]);
1108         if (service == NULL) {
1109                 d_printf(_("error: out of memory!\n"));
1110                 goto done;
1111         }
1112
1113         werr = smbconf_delete_includes(conf_ctx, service);
1114         if (!W_ERROR_IS_OK(werr)) {
1115                 d_printf(_("error deleting includes: %s\n"), win_errstr(werr));
1116                 goto done;
1117         }
1118
1119         ret = 0;
1120
1121 done:
1122         TALLOC_FREE(mem_ctx);
1123         return ret;
1124 }
1125
1126
1127 /**********************************************************************
1128  *
1129  * Wrapper and net_conf_run_function mechanism.
1130  *
1131  **********************************************************************/
1132
1133 /**
1134  * Wrapper function to call the main conf functions.
1135  * The wrapper calls handles opening and closing of the
1136  * configuration.
1137  */
1138 static int net_conf_wrap_function(struct net_context *c,
1139                                   int (*fn)(struct net_context *,
1140                                             struct smbconf_ctx *,
1141                                             int, const char **),
1142                                   int argc, const char **argv)
1143 {
1144         sbcErr err;
1145         TALLOC_CTX *mem_ctx = talloc_stackframe();
1146         struct smbconf_ctx *conf_ctx;
1147         int ret = -1;
1148
1149         err = smbconf_init(mem_ctx, &conf_ctx, "registry:");
1150         if (!SBC_ERROR_IS_OK(err)) {
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