libsmbconf: change the API to always take the smbconf_ctx parameter first.
[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 "utils/net.h"
32
33 /**********************************************************************
34  *
35  * usage functions
36  *
37  **********************************************************************/
38
39 static int net_conf_list_usage(int argc, const char **argv)
40 {
41         d_printf("USAGE: net conf list\n");
42         return -1;
43 }
44
45 static int net_conf_import_usage(int argc, const char**argv)
46 {
47         d_printf("USAGE: net conf import [--test|-T] <filename> "
48                  "[<servicename>]\n"
49                  "\t[--test|-T]    testmode - do not act, just print "
50                         "what would be done\n"
51                  "\t<servicename>  only import service <servicename>, "
52                         "ignore the rest\n");
53         return -1;
54 }
55
56 static int net_conf_listshares_usage(int argc, const char **argv)
57 {
58         d_printf("USAGE: net conf listshares\n");
59         return -1;
60 }
61
62 static int net_conf_drop_usage(int argc, const char **argv)
63 {
64         d_printf("USAGE: net conf drop\n");
65         return -1;
66 }
67
68 static int net_conf_showshare_usage(int argc, const char **argv)
69 {
70         d_printf("USAGE: net conf showshare <sharename>\n");
71         return -1;
72 }
73
74 static int net_conf_addshare_usage(int argc, const char **argv)
75 {
76         d_printf("USAGE: net conf addshare <sharename> <path> "
77                  "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
78                  "\t<sharename>      the new share name.\n"
79                  "\t<path>           the path on the filesystem to export.\n"
80                  "\twriteable={y|N}  set \"writeable to \"yes\" or "
81                  "\"no\" (default) on this share.\n"
82                  "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
83                  "\"no\" (default)   on this share.\n"
84                  "\t<comment>        optional comment for the new share.\n");
85         return -1;
86 }
87
88 static int net_conf_delshare_usage(int argc, const char **argv)
89 {
90         d_printf("USAGE: net conf delshare <sharename>\n");
91         return -1;
92 }
93
94 static int net_conf_setparm_usage(int argc, const char **argv)
95 {
96         d_printf("USAGE: net conf setparm <section> <param> <value>\n");
97         return -1;
98 }
99
100 static int net_conf_getparm_usage(int argc, const char **argv)
101 {
102         d_printf("USAGE: net conf getparm <section> <param>\n");
103         return -1;
104 }
105
106 static int net_conf_delparm_usage(int argc, const char **argv)
107 {
108         d_printf("USAGE: net conf delparm <section> <param>\n");
109         return -1;
110 }
111
112
113 /**********************************************************************
114  *
115  * Helper functions
116  *
117  **********************************************************************/
118
119 /**
120  * This formats an in-memory smbconf parameter to a string.
121  * The result string is allocated with talloc.
122  */
123 static char *parm_valstr(TALLOC_CTX *ctx, struct parm_struct *parm,
124                          struct share_params *share)
125 {
126         char *valstr = NULL;
127         int i = 0;
128         void *ptr = parm->ptr;
129
130         if (parm->p_class == P_LOCAL && share->service >= 0) {
131                 ptr = lp_local_ptr(share->service, ptr);
132         }
133
134         switch (parm->type) {
135         case P_CHAR:
136                 valstr = talloc_asprintf(ctx, "%c", *(char *)ptr);
137                 break;
138         case P_STRING:
139         case P_USTRING:
140                 valstr = talloc_asprintf(ctx, "%s", *(char **)ptr);
141                 break;
142         case P_BOOL:
143                 valstr = talloc_asprintf(ctx, "%s", BOOLSTR(*(bool *)ptr));
144                 break;
145         case P_BOOLREV:
146                 valstr = talloc_asprintf(ctx, "%s", BOOLSTR(!*(bool *)ptr));
147                 break;
148         case P_ENUM:
149                 for (i = 0; parm->enum_list[i].name; i++) {
150                         if (*(int *)ptr == parm->enum_list[i].value)
151                         {
152                                 valstr = talloc_asprintf(ctx, "%s",
153                                         parm->enum_list[i].name);
154                                 break;
155                         }
156                 }
157                 break;
158         case P_OCTAL: {
159                 char *o = octal_string(*(int *)ptr);
160                 valstr = talloc_move(ctx, &o);
161                 break;
162         }
163         case P_LIST:
164                 valstr = talloc_strdup(ctx, "");
165                 if ((char ***)ptr && *(char ***)ptr) {
166                         char **list = *(char ***)ptr;
167                         for (; *list; list++) {
168                                 /* surround strings with whitespace
169                                  * in double quotes */
170                                 if (strchr_m(*list, ' '))
171                                 {
172                                         valstr = talloc_asprintf_append(
173                                                 valstr, "\"%s\"%s",
174                                                 *list,
175                                                  ((*(list+1))?", ":""));
176                                 } else {
177                                         valstr = talloc_asprintf_append(
178                                                 valstr, "%s%s", *list,
179                                                  ((*(list+1))?", ":""));
180                                 }
181                         }
182                 }
183                 break;
184         case P_INTEGER:
185                 valstr = talloc_asprintf(ctx, "%d", *(int *)ptr);
186                 break;
187         case P_SEP:
188                 break;
189         default:
190                 valstr = talloc_asprintf(ctx, "<type unimplemented>\n");
191                 break;
192         }
193
194         return valstr;
195 }
196
197 /**
198  * This functions imports a configuration that has previously
199  * been loaded with lp_load() to registry.
200  */
201 static int import_process_service(TALLOC_CTX *ctx,
202                                   struct smbconf_ctx *conf_ctx,
203                                   struct share_params *share)
204 {
205         int ret = -1;
206         struct parm_struct *parm;
207         int pnum = 0;
208         const char *servicename;
209         WERROR werr;
210         char *valstr = NULL;
211         TALLOC_CTX *tmp_ctx = NULL;
212
213         tmp_ctx = talloc_new(ctx);
214         if (tmp_ctx == NULL) {
215                 werr = WERR_NOMEM;
216                 goto done;
217         }
218
219         servicename = (share->service == GLOBAL_SECTION_SNUM)?
220                 GLOBAL_NAME : lp_servicename(share->service);
221
222         if (opt_testmode) {
223                 d_printf("[%s]\n", servicename);
224         } else {
225                 if (smbconf_share_exists(conf_ctx, servicename)) {
226                         werr = smbconf_delete_share(conf_ctx, servicename);
227                         if (!W_ERROR_IS_OK(werr)) {
228                                 goto done;
229                         }
230                 }
231                 werr = smbconf_create_share(conf_ctx, servicename);
232                 if (!W_ERROR_IS_OK(werr)) {
233                         goto done;
234                 }
235         }
236
237         while ((parm = lp_next_parameter(share->service, &pnum, 0)))
238         {
239                 if ((share->service < 0) && (parm->p_class == P_LOCAL)
240                     && !(parm->flags & FLAG_GLOBAL))
241                 {
242                         continue;
243                 }
244
245                 valstr = parm_valstr(tmp_ctx, parm, share);
246
247                 if (parm->type != P_SEP) {
248                         if (opt_testmode) {
249                                 d_printf("\t%s = %s\n", parm->label, valstr);
250                         } else {
251                                 werr = smbconf_set_parameter(conf_ctx,
252                                                              servicename,
253                                                              parm->label,
254                                                              valstr);
255                                 if (!W_ERROR_IS_OK(werr)) {
256                                         d_fprintf(stderr,
257                                                   "Error setting parameter '%s'"
258                                                   ": %s\n", parm->label,
259                                                    dos_errstr(werr));
260                                         goto done;
261                                 }
262                         }
263                 }
264         }
265
266         if (opt_testmode) {
267                 d_printf("\n");
268         }
269
270         ret = 0;
271
272 done:
273         TALLOC_FREE(tmp_ctx);
274         return ret;
275 }
276
277 /**
278  * Return true iff there are nondefault globals in the
279  * currently loaded configuration.
280  */
281 static bool globals_exist(void)
282 {
283         int i = 0;
284         struct parm_struct *parm;
285
286         while ((parm = lp_next_parameter(GLOBAL_SECTION_SNUM, &i, 0)) != NULL) {
287                 if (parm->type != P_SEP) {
288                         return true;
289                 }
290         }
291         return false;
292 }
293
294
295 /**********************************************************************
296  *
297  * the main conf functions
298  *
299  **********************************************************************/
300
301 static int net_conf_list(struct smbconf_ctx *conf_ctx,
302                          int argc, const char **argv)
303 {
304         WERROR werr = WERR_OK;
305         int ret = -1;
306         TALLOC_CTX *ctx;
307         uint32_t num_shares;
308         char **share_names;
309         uint32_t *num_params;
310         char ***param_names;
311         char ***param_values;
312         uint32_t share_count, param_count;
313
314         ctx = talloc_init("list");
315
316         if (argc != 0) {
317                 net_conf_list_usage(argc, argv);
318                 goto done;
319         }
320
321         werr = smbconf_get_config(conf_ctx, ctx, &num_shares, &share_names,
322                                   &num_params, &param_names, &param_values);
323         if (!W_ERROR_IS_OK(werr)) {
324                 d_fprintf(stderr, "Error getting config: %s\n",
325                           dos_errstr(werr));
326                 goto done;
327         }
328
329         for (share_count = 0; share_count < num_shares; share_count++) {
330                 d_printf("[%s]\n", share_names[share_count]);
331                 for (param_count = 0; param_count < num_params[share_count];
332                      param_count++)
333                 {
334                         d_printf("\t%s = %s\n",
335                                  param_names[share_count][param_count],
336                                  param_values[share_count][param_count]);
337                 }
338                 d_printf("\n");
339         }
340
341         ret = 0;
342
343 done:
344         TALLOC_FREE(ctx);
345         return ret;
346 }
347
348 static int net_conf_import(struct smbconf_ctx *conf_ctx,
349                            int argc, const char **argv)
350 {
351         int ret = -1;
352         const char *filename = NULL;
353         const char *servicename = NULL;
354         bool service_found = false;
355         TALLOC_CTX *ctx;
356         struct share_iterator *shares;
357         struct share_params *share;
358         struct share_params global_share = { GLOBAL_SECTION_SNUM };
359
360         ctx = talloc_init("net_conf_import");
361
362         switch (argc) {
363                 case 0:
364                 default:
365                         net_conf_import_usage(argc, argv);
366                         goto done;
367                 case 2:
368                         servicename = argv[1];
369                 case 1:
370                         filename = argv[0];
371                         break;
372         }
373
374         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
375                 filename));
376
377         if (!lp_load(filename,
378                      false,     /* global_only */
379                      true,      /* save_defaults */
380                      false,     /* add_ipc */
381                      true))     /* initialize_globals */
382         {
383                 d_fprintf(stderr, "Error parsing configuration file.\n");
384                 goto done;
385         }
386
387         if (opt_testmode) {
388                 d_printf("\nTEST MODE - "
389                          "would import the following configuration:\n\n");
390         }
391
392         if (((servicename == NULL) && globals_exist()) ||
393             strequal(servicename, GLOBAL_NAME))
394         {
395                 service_found = true;
396                 if (import_process_service(ctx, conf_ctx, &global_share) != 0) {
397                         goto done;
398                 }
399         }
400
401         if (service_found && (servicename != NULL)) {
402                 ret = 0;
403                 goto done;
404         }
405
406         if (!(shares = share_list_all(ctx))) {
407                 d_fprintf(stderr, "Could not list shares...\n");
408                 goto done;
409         }
410         while ((share = next_share(shares)) != NULL) {
411                 if ((servicename == NULL)
412                     || strequal(servicename, lp_servicename(share->service)))
413                 {
414                         service_found = true;
415                         if (import_process_service(ctx, conf_ctx, share)!= 0) {
416                                 goto done;
417                         }
418                 }
419         }
420
421         if ((servicename != NULL) && !service_found) {
422                 d_printf("Share %s not found in file %s\n",
423                          servicename, filename);
424                 goto done;
425
426         }
427
428         ret = 0;
429
430 done:
431         TALLOC_FREE(ctx);
432         return ret;
433 }
434
435 static int net_conf_listshares(struct smbconf_ctx *conf_ctx,
436                                int argc, const char **argv)
437 {
438         WERROR werr = WERR_OK;
439         int ret = -1;
440         uint32_t count, num_shares = 0;
441         char **share_names = NULL;
442         TALLOC_CTX *ctx;
443
444         ctx = talloc_init("listshares");
445
446         if (argc != 0) {
447                 net_conf_listshares_usage(argc, argv);
448                 goto done;
449         }
450
451         werr = smbconf_get_share_names(conf_ctx, ctx, &num_shares,
452                                        &share_names);
453         if (!W_ERROR_IS_OK(werr)) {
454                 goto done;
455         }
456
457         for (count = 0; count < num_shares; count++)
458         {
459                 d_printf("%s\n", share_names[count]);
460         }
461
462         ret = 0;
463
464 done:
465         TALLOC_FREE(ctx);
466         return ret;
467 }
468
469 static int net_conf_drop(struct smbconf_ctx *conf_ctx,
470                          int argc, const char **argv)
471 {
472         int ret = -1;
473         WERROR werr;
474
475         if (argc != 0) {
476                 net_conf_drop_usage(argc, argv);
477                 goto done;
478         }
479
480         werr = smbconf_drop(conf_ctx);
481         if (!W_ERROR_IS_OK(werr)) {
482                 d_fprintf(stderr, "Error deleting configuration: %s\n",
483                           dos_errstr(werr));
484                 goto done;
485         }
486
487         ret = 0;
488
489 done:
490         return ret;
491 }
492
493 static int net_conf_showshare(struct smbconf_ctx *conf_ctx,
494                               int argc, const char **argv)
495 {
496         int ret = -1;
497         WERROR werr = WERR_OK;
498         const char *sharename = NULL;
499         TALLOC_CTX *ctx;
500         uint32_t num_params;
501         uint32_t count;
502         char **param_names;
503         char **param_values;
504
505         ctx = talloc_init("showshare");
506
507         if (argc != 1) {
508                 net_conf_showshare_usage(argc, argv);
509                 goto done;
510         }
511
512         sharename = argv[0];
513
514         werr = smbconf_get_share(conf_ctx, ctx, sharename, &num_params,
515                                  &param_names, &param_values);
516         if (!W_ERROR_IS_OK(werr)) {
517                 d_printf("error getting share parameters: %s\n",
518                          dos_errstr(werr));
519                 goto done;
520         }
521
522         d_printf("[%s]\n", sharename);
523
524         for (count = 0; count < num_params; count++) {
525                 d_printf("\t%s = %s\n", param_names[count],
526                          param_values[count]);
527         }
528
529         ret = 0;
530
531 done:
532         TALLOC_FREE(ctx);
533         return ret;
534 }
535
536 /**
537  * Add a share, with a couple of standard parameters, partly optional.
538  *
539  * This is a high level utility function of the net conf utility,
540  * not a direct frontend to the smbconf API.
541  */
542 static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
543                              int argc, const char **argv)
544 {
545         int ret = -1;
546         WERROR werr = WERR_OK;
547         char *sharename = NULL;
548         const char *path = NULL;
549         const char *comment = NULL;
550         const char *guest_ok = "no";
551         const char *writeable = "no";
552         SMB_STRUCT_STAT sbuf;
553
554         switch (argc) {
555                 case 0:
556                 case 1:
557                 default:
558                         net_conf_addshare_usage(argc, argv);
559                         goto done;
560                 case 5:
561                         comment = argv[4];
562                 case 4:
563                         if (!strnequal(argv[3], "guest_ok=", 9)) {
564                                 net_conf_addshare_usage(argc, argv);
565                                 goto done;
566                         }
567                         switch (argv[3][9]) {
568                                 case 'y':
569                                 case 'Y':
570                                         guest_ok = "yes";
571                                         break;
572                                 case 'n':
573                                 case 'N':
574                                         guest_ok = "no";
575                                         break;
576                                 default:
577                                         net_conf_addshare_usage(argc, argv);
578                                         goto done;
579                         }
580                 case 3:
581                         if (!strnequal(argv[2], "writeable=", 10)) {
582                                 net_conf_addshare_usage(argc, argv);
583                                 goto done;
584                         }
585                         switch (argv[2][10]) {
586                                 case 'y':
587                                 case 'Y':
588                                         writeable = "yes";
589                                         break;
590                                 case 'n':
591                                 case 'N':
592                                         writeable = "no";
593                                         break;
594                                 default:
595                                         net_conf_addshare_usage(argc, argv);
596                                         goto done;
597                         }
598                 case 2:
599                         path = argv[1];
600                         sharename = strdup_lower(argv[0]);
601                         break;
602         }
603
604         /*
605          * validate arguments
606          */
607
608         /* validate share name */
609
610         if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
611                                strlen(sharename)))
612         {
613                 d_fprintf(stderr, "ERROR: share name %s contains "
614                         "invalid characters (any of %s)\n",
615                         sharename, INVALID_SHARENAME_CHARS);
616                 goto done;
617         }
618
619         if (getpwnam(sharename)) {
620                 d_fprintf(stderr, "ERROR: share name %s is already a valid "
621                           "system user name.\n", sharename);
622                 goto done;
623         }
624
625         if (strequal(sharename, GLOBAL_NAME)) {
626                 d_fprintf(stderr,
627                           "ERROR: 'global' is not a valid share name.\n");
628                 goto done;
629         }
630
631         if (smbconf_share_exists(conf_ctx, sharename)) {
632                 d_fprintf(stderr, "ERROR: share %s already exists.\n",
633                           sharename);
634                 goto done;
635         }
636
637         /* validate path */
638
639         if (path[0] != '/') {
640                 d_fprintf(stderr,
641                           "Error: path '%s' is not an absolute path.\n",
642                           path);
643                 goto done;
644         }
645
646         if (sys_stat(path, &sbuf) != 0) {
647                 d_fprintf(stderr,
648                           "ERROR: cannot stat path '%s' to ensure "
649                           "this is a directory.\n"
650                           "Error was '%s'.\n",
651                           path, strerror(errno));
652                 goto done;
653         }
654
655         if (!S_ISDIR(sbuf.st_mode)) {
656                 d_fprintf(stderr,
657                           "ERROR: path '%s' is not a directory.\n",
658                           path);
659                 goto done;
660         }
661
662         /*
663          * create the share
664          */
665
666         werr = smbconf_create_share(conf_ctx, sharename);
667         if (!W_ERROR_IS_OK(werr)) {
668                 d_fprintf(stderr, "Error creating share %s: %s\n",
669                           sharename, dos_errstr(werr));
670                 goto done;
671         }
672
673         /*
674          * fill the share with parameters
675          */
676
677         werr = smbconf_set_parameter(conf_ctx, sharename, "path", path);
678         if (!W_ERROR_IS_OK(werr)) {
679                 d_fprintf(stderr, "Error setting parameter %s: %s\n",
680                           "path", dos_errstr(werr));
681                 goto done;
682         }
683
684         if (comment != NULL) {
685                 werr = smbconf_set_parameter(conf_ctx, sharename, "comment",
686                                              comment);
687                 if (!W_ERROR_IS_OK(werr)) {
688                         d_fprintf(stderr, "Error setting parameter %s: %s\n",
689                                   "comment", dos_errstr(werr));
690                         goto done;
691                 }
692         }
693
694         werr = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
695         if (!W_ERROR_IS_OK(werr)) {
696                 d_fprintf(stderr, "Error setting parameter %s: %s\n",
697                           "'guest ok'", dos_errstr(werr));
698                 goto done;
699         }
700
701         werr = smbconf_set_parameter(conf_ctx, sharename, "writeable",
702                                      writeable);
703         if (!W_ERROR_IS_OK(werr)) {
704                 d_fprintf(stderr, "Error setting parameter %s: %s\n",
705                           "writeable", dos_errstr(werr));
706                 goto done;
707         }
708
709         ret = 0;
710
711 done:
712         SAFE_FREE(sharename);
713         return ret;
714 }
715
716 static int net_conf_delshare(struct smbconf_ctx *conf_ctx,
717                              int argc, const char **argv)
718 {
719         int ret = -1;
720         const char *sharename = NULL;
721         WERROR werr = WERR_OK;
722
723         if (argc != 1) {
724                 net_conf_delshare_usage(argc, argv);
725                 goto done;
726         }
727         sharename = argv[0];
728
729         werr = smbconf_delete_share(conf_ctx, sharename);
730         if (!W_ERROR_IS_OK(werr)) {
731                 d_fprintf(stderr, "Error deleting share %s: %s\n",
732                           sharename, dos_errstr(werr));
733                 goto done;
734         }
735
736         ret = 0;
737 done:
738         return ret;
739 }
740
741 static int net_conf_setparm(struct smbconf_ctx *conf_ctx,
742                             int argc, const char **argv)
743 {
744         int ret = -1;
745         WERROR werr = WERR_OK;
746         char *service = NULL;
747         char *param = NULL;
748         const char *value_str = NULL;
749
750         if (argc != 3) {
751                 net_conf_setparm_usage(argc, argv);
752                 goto done;
753         }
754         service = strdup_lower(argv[0]);
755         param = strdup_lower(argv[1]);
756         value_str = argv[2];
757
758         if (!smbconf_share_exists(conf_ctx, service)) {
759                 werr = smbconf_create_share(conf_ctx, service);
760                 if (!W_ERROR_IS_OK(werr)) {
761                         d_fprintf(stderr, "Error creating share '%s': %s\n",
762                                   service, dos_errstr(werr));
763                         goto done;
764                 }
765         }
766
767         werr = smbconf_set_parameter(conf_ctx, service, param, value_str);
768
769         if (!W_ERROR_IS_OK(werr)) {
770                 d_fprintf(stderr, "Error setting value '%s': %s\n",
771                           param, dos_errstr(werr));
772                 goto done;
773         }
774
775         ret = 0;
776
777 done:
778         SAFE_FREE(service);
779         SAFE_FREE(param);
780         return ret;
781 }
782
783 static int net_conf_getparm(struct smbconf_ctx *conf_ctx,
784                             int argc, const char **argv)
785 {
786         int ret = -1;
787         WERROR werr = WERR_OK;
788         char *service = NULL;
789         char *param = NULL;
790         char *valstr = NULL;
791         TALLOC_CTX *ctx;
792
793         ctx = talloc_init("getparm");
794
795         if (argc != 2) {
796                 net_conf_getparm_usage(argc, argv);
797                 goto done;
798         }
799         service = strdup_lower(argv[0]);
800         param = strdup_lower(argv[1]);
801
802         werr = smbconf_get_parameter(conf_ctx, ctx, service, param, &valstr);
803
804         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
805                 d_fprintf(stderr,
806                           "Error: given service '%s' does not exist.\n",
807                           service);
808                 goto done;
809         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
810                 d_fprintf(stderr,
811                           "Error: given parameter '%s' is not set.\n",
812                           param);
813                 goto done;
814         } else if (!W_ERROR_IS_OK(werr)) {
815                 d_fprintf(stderr, "Error getting value '%s': %s.\n",
816                           param, dos_errstr(werr));
817                 goto done;
818         }
819
820         d_printf("%s\n", valstr);
821
822         ret = 0;
823 done:
824         SAFE_FREE(service);
825         SAFE_FREE(param);
826         TALLOC_FREE(ctx);
827         return ret;
828 }
829
830 static int net_conf_delparm(struct smbconf_ctx *conf_ctx,
831                             int argc, const char **argv)
832 {
833         int ret = -1;
834         WERROR werr = WERR_OK;
835         char *service = NULL;
836         char *param = NULL;
837
838         if (argc != 2) {
839                 net_conf_delparm_usage(argc, argv);
840                 goto done;
841         }
842         service = strdup_lower(argv[0]);
843         param = strdup_lower(argv[1]);
844
845         werr = smbconf_delete_parameter(conf_ctx, service, param);
846
847         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
848                 d_fprintf(stderr,
849                           "Error: given service '%s' does not exist.\n",
850                           service);
851                 goto done;
852         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
853                 d_fprintf(stderr,
854                           "Error: given parameter '%s' is not set.\n",
855                           param);
856                 goto done;
857         } else if (!W_ERROR_IS_OK(werr)) {
858                 d_fprintf(stderr, "Error deleting value '%s': %s.\n",
859                           param, dos_errstr(werr));
860                 goto done;
861         }
862
863         ret = 0;
864
865 done:
866         SAFE_FREE(service);
867         SAFE_FREE(param);
868         return ret;
869 }
870
871
872 /**********************************************************************
873  *
874  * Wrapper and net_conf_run_function mechanism.
875  *
876  **********************************************************************/
877
878 /**
879  * Wrapper function to call the main conf functions.
880  * The wrapper calls handles opening and closing of the
881  * configuration.
882  */
883 static int net_conf_wrap_function(int (*fn)(struct smbconf_ctx *,
884                                             int, const char **),
885                                   int argc, const char **argv)
886 {
887         WERROR werr;
888         TALLOC_CTX *mem_ctx = talloc_stackframe();
889         struct smbconf_ctx *conf_ctx;
890         int ret = -1;
891
892         werr = smbconf_open(mem_ctx, &conf_ctx);
893
894         if (!W_ERROR_IS_OK(werr)) {
895                 return -1;
896         }
897
898         ret = fn(conf_ctx, argc, argv);
899
900         smbconf_close(conf_ctx);
901
902         return ret;
903 }
904
905 /*
906  * We need a functable struct of our own, because the
907  * functions are called through a wrapper that handles
908  * the opening and closing of the configuration, and so on.
909  */
910 struct conf_functable {
911         const char *funcname;
912         int (*fn)(struct smbconf_ctx *ctx, int argc, const char **argv);
913         const char *helptext;
914 };
915
916 /**
917  * This imitates net_run_function2 but calls the main functions
918  * through the wrapper net_conf_wrap_function().
919  */
920 static int net_conf_run_function(int argc, const char **argv,
921                                  const char *whoami,
922                                  struct conf_functable *table)
923 {
924         int i;
925
926         if (argc != 0) {
927                 for (i=0; table[i].funcname; i++) {
928                         if (StrCaseCmp(argv[0], table[i].funcname) == 0)
929                                 return net_conf_wrap_function(table[i].fn,
930                                                               argc-1,
931                                                               argv+1);
932                 }
933         }
934
935         for (i=0; table[i].funcname; i++) {
936                 d_printf("%s %-15s %s\n", whoami, table[i].funcname,
937                          table[i].helptext);
938         }
939
940         return -1;
941 }
942
943 /*
944  * Entry-point for all the CONF functions.
945  */
946
947 int net_conf(int argc, const char **argv)
948 {
949         int ret = -1;
950         struct conf_functable func_table[] = {
951                 {"list", net_conf_list,
952                  "Dump the complete configuration in smb.conf like format."},
953                 {"import", net_conf_import,
954                  "Import configuration from file in smb.conf format."},
955                 {"listshares", net_conf_listshares,
956                  "List the share names."},
957                 {"drop", net_conf_drop,
958                  "Delete the complete configuration."},
959                 {"showshare", net_conf_showshare,
960                  "Show the definition of a share."},
961                 {"addshare", net_conf_addshare,
962                  "Create a new share."},
963                 {"delshare", net_conf_delshare,
964                  "Delete a share."},
965                 {"setparm", net_conf_setparm,
966                  "Store a parameter."},
967                 {"getparm", net_conf_getparm,
968                  "Retrieve the value of a parameter."},
969                 {"delparm", net_conf_delparm,
970                  "Delete a parameter."},
971                 {NULL, NULL, NULL}
972         };
973
974         ret = net_conf_run_function(argc, argv, "net conf", func_table);
975
976         return ret;
977 }
978