Rename libnet_smbconf_open_basepath() to libnet_smbconf_reg_open_basepath().
[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
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 the configuration stored inside the
23  * samba registry. In the future there might be support for other
24  * configuration backends as well.
25  */
26
27 #include "includes.h"
28 #include "utils/net.h"
29 #include "libnet/libnet.h"
30
31 /*
32  * usage functions
33  */
34
35 static int net_conf_list_usage(int argc, const char **argv)
36 {
37         d_printf("USAGE: net conf list\n");
38         return -1;
39 }
40
41 static int net_conf_import_usage(int argc, const char**argv)
42 {
43         d_printf("USAGE: net conf import [--test|-T] <filename> "
44                  "[<servicename>]\n"
45                  "\t[--test|-T]    testmode - do not act, just print "
46                                    "what would be done\n"
47                  "\t<servicename>  only import service <servicename>, "
48                                    "ignore the rest\n");
49         return -1;
50 }
51
52 static int net_conf_listshares_usage(int argc, const char **argv)
53 {
54         d_printf("USAGE: net conf listshares\n");
55         return -1;
56 }
57
58 static int net_conf_drop_usage(int argc, const char **argv)
59 {
60         d_printf("USAGE: net conf drop\n");
61         return -1;
62 }
63
64 static int net_conf_showshare_usage(int argc, const char **argv)
65 {
66         d_printf("USAGE: net conf showshare <sharename>\n");
67         return -1;
68 }
69
70 static int net_conf_addshare_usage(int argc, const char **argv)
71 {
72         d_printf("USAGE: net conf addshare <sharename> <path> "
73                  "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
74                  "\t<sharename>      the new share name.\n"
75                  "\t<path>           the path on the filesystem to export.\n"
76                  "\twriteable={y|N}  set \"writeable to \"yes\" or "
77                  "\"no\" (default) on this share.\n"
78                  "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
79                  "\"no\" (default)   on this share.\n"
80                  "\t<comment>        optional comment for the new share.\n");
81         return -1;
82 }
83
84 static int net_conf_delshare_usage(int argc, const char **argv)
85 {
86         d_printf("USAGE: net conf delshare <sharename>\n");
87         return -1;
88 }
89
90 static int net_conf_setparm_usage(int argc, const char **argv)
91 {
92         d_printf("USAGE: net conf setparm <section> <param> <value>\n");
93         return -1;
94 }
95
96 static int net_conf_getparm_usage(int argc, const char **argv)
97 {
98         d_printf("USAGE: net conf getparm <section> <param>\n");
99         return -1;
100 }
101
102 static int net_conf_delparm_usage(int argc, const char **argv)
103 {
104         d_printf("USAGE: net conf delparm <section> <param>\n");
105         return -1;
106 }
107
108
109 /*
110  * Helper functions
111  */
112
113 static char *format_value(TALLOC_CTX *mem_ctx, struct registry_value *value)
114 {
115         char *result = NULL;
116
117         /* what if mem_ctx = NULL? */
118
119         switch (value->type) {
120         case REG_DWORD:
121                 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
122                 break;
123         case REG_SZ:
124         case REG_EXPAND_SZ:
125                 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
126                 break;
127         case REG_MULTI_SZ: {
128                 uint32 j;
129                 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
130                         result = talloc_asprintf(mem_ctx, "\"%s\" ",
131                                                  value->v.multi_sz.strings[j]);
132                 }
133                 break;
134         }
135         case REG_BINARY:
136                 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
137                                          (int)value->v.binary.length);
138                 break;
139         default:
140                 result = talloc_asprintf(mem_ctx, "<unprintable>");
141                 break;
142         }
143         return result;
144 }
145
146 static WERROR list_values(TALLOC_CTX *ctx, struct registry_key *key)
147 {
148         WERROR werr = WERR_OK;
149         uint32 idx = 0;
150         struct registry_value *valvalue = NULL;
151         char *valname = NULL;
152
153         for (idx = 0;
154              W_ERROR_IS_OK(werr = reg_enumvalue(ctx, key, idx, &valname,
155                                                 &valvalue));
156              idx++)
157         {
158                 d_printf("\t%s = %s\n", valname, format_value(ctx, valvalue));
159         }
160         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
161                 d_fprintf(stderr, "Error enumerating values: %s\n",
162                           dos_errstr(werr));
163                 goto done;
164         }
165         werr = WERR_OK;
166
167 done:
168         return werr;
169 }
170
171 static char *parm_valstr(TALLOC_CTX *ctx, struct parm_struct *parm,
172                          struct share_params *share)
173 {
174         char *valstr = NULL;
175         int i = 0;
176         void *ptr = parm->ptr;
177
178         if (parm->p_class == P_LOCAL && share->service >= 0) {
179                 ptr = lp_local_ptr(share->service, ptr);
180         }
181
182         switch (parm->type) {
183         case P_CHAR:
184                 valstr = talloc_asprintf(ctx, "%c", *(char *)ptr);
185                 break;
186         case P_STRING:
187         case P_USTRING:
188                 valstr = talloc_asprintf(ctx, "%s", *(char **)ptr);
189                 break;
190         case P_BOOL:
191                 valstr = talloc_asprintf(ctx, "%s", BOOLSTR(*(bool *)ptr));
192                 break;
193         case P_BOOLREV:
194                 valstr = talloc_asprintf(ctx, "%s", BOOLSTR(!*(bool *)ptr));
195                 break;
196         case P_ENUM:
197                 for (i = 0; parm->enum_list[i].name; i++) {
198                         if (*(int *)ptr == parm->enum_list[i].value)
199                         {
200                                 valstr = talloc_asprintf(ctx, "%s",
201                                          parm->enum_list[i].name);
202                                 break;
203                         }
204                 }
205                 break;
206         case P_OCTAL: {
207                 char *o = octal_string(*(int *)ptr);
208                 valstr = talloc_move(ctx, &o);
209                 break;
210         }
211         case P_LIST:
212                 valstr = talloc_strdup(ctx, "");
213                 if ((char ***)ptr && *(char ***)ptr) {
214                         char **list = *(char ***)ptr;
215                         for (; *list; list++) {
216                                 /* surround strings with whitespace
217                                  * in double quotes */
218                                 if (strchr_m(*list, ' '))
219                                 {
220                                         valstr = talloc_asprintf_append(
221                                                 valstr, "\"%s\"%s",
222                                                 *list,
223                                                  ((*(list+1))?", ":""));
224                                 } else {
225                                         valstr = talloc_asprintf_append(
226                                                 valstr, "%s%s", *list,
227                                                  ((*(list+1))?", ":""));
228                                 }
229                         }
230                 }
231                 break;
232         case P_INTEGER:
233                 valstr = talloc_asprintf(ctx, "%d", *(int *)ptr);
234                 break;
235         case P_SEP:
236                 break;
237         default:
238                 valstr = talloc_asprintf(ctx, "<type unimplemented>\n");
239                 break;
240         }
241
242         return valstr;
243 }
244
245 static int import_process_service(TALLOC_CTX *ctx,
246                                   struct share_params *share)
247 {
248         int ret = -1;
249         struct parm_struct *parm;
250         int pnum = 0;
251         const char *servicename;
252         struct registry_key *key;
253         WERROR werr;
254         char *valstr = NULL;
255         TALLOC_CTX *tmp_ctx = NULL;
256
257         tmp_ctx = talloc_new(ctx);
258         if (tmp_ctx == NULL) {
259                 werr = WERR_NOMEM;
260                 goto done;
261         }
262
263         servicename = (share->service == GLOBAL_SECTION_SNUM)?
264                 GLOBAL_NAME : lp_servicename(share->service);
265
266         if (opt_testmode) {
267                 d_printf("[%s]\n", servicename);
268         } else {
269                 if (libnet_smbconf_key_exists(servicename)) {
270                         werr = libnet_smbconf_delshare(servicename);
271                         if (!W_ERROR_IS_OK(werr)) {
272                                 goto done;
273                         }
274                 }
275                 werr = libnet_smbconf_reg_createkey_internal(tmp_ctx, servicename, &key);
276                 if (!W_ERROR_IS_OK(werr)) {
277                         goto done;
278                 }
279         }
280
281         while ((parm = lp_next_parameter(share->service, &pnum, 0)))
282         {
283                 if ((share->service < 0 && parm->p_class == P_LOCAL)
284                     && !(parm->flags & FLAG_GLOBAL))
285                         continue;
286
287                 valstr = parm_valstr(tmp_ctx, parm, share);
288
289                 if (parm->type != P_SEP) {
290                         if (opt_testmode) {
291                                 d_printf("\t%s = %s\n", parm->label, valstr);
292                         } else {
293                                 werr = libnet_smbconf_reg_setvalue_internal(key,
294                                                         parm->label, valstr);
295                                 if (!W_ERROR_IS_OK(werr)) {
296                                         goto done;
297                                 }
298                         }
299                 }
300         }
301
302         if (opt_testmode) {
303                 d_printf("\n");
304         }
305
306         ret = 0;
307
308 done:
309         TALLOC_FREE(tmp_ctx);
310         return ret;
311 }
312
313 /* return true iff there are nondefault globals */
314 static bool globals_exist(void)
315 {
316         int i = 0;
317         struct parm_struct *parm;
318
319         while ((parm = lp_next_parameter(GLOBAL_SECTION_SNUM, &i, 0)) != NULL) {
320                 if (parm->type != P_SEP) {
321                         return true;
322                 }
323         }
324         return false;
325 }
326
327 /*
328  * the conf functions
329  */
330
331 int net_conf_list(int argc, const char **argv)
332 {
333         WERROR werr = WERR_OK;
334         int ret = -1;
335         TALLOC_CTX *ctx;
336         struct registry_key *base_key = NULL;
337         struct registry_key *sub_key = NULL;
338         uint32 idx_key = 0;
339         char *subkey_name = NULL;
340
341         ctx = talloc_init("list");
342
343         if (argc != 0) {
344                 net_conf_list_usage(argc, argv);
345                 goto done;
346         }
347
348         werr = libnet_smbconf_reg_open_basepath(ctx, REG_KEY_READ, &base_key);
349         if (!W_ERROR_IS_OK(werr)) {
350                 goto done;
351         }
352
353         if (libnet_smbconf_key_exists(GLOBAL_NAME))  {
354                 werr = reg_openkey(ctx, base_key, GLOBAL_NAME,
355                                    REG_KEY_READ, &sub_key);
356                 if (!W_ERROR_IS_OK(werr)) {
357                         d_fprintf(stderr, "Error opening subkey '%s' : %s\n",
358                                   subkey_name, dos_errstr(werr));
359                         goto done;
360                 }
361                 d_printf("[%s]\n", GLOBAL_NAME);
362                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
363                         goto done;
364                 }
365                 d_printf("\n");
366         }
367
368         for (idx_key = 0;
369              W_ERROR_IS_OK(werr = reg_enumkey(ctx, base_key, idx_key,
370                                               &subkey_name, NULL));
371              idx_key++)
372         {
373                 if (strequal(subkey_name, GLOBAL_NAME)) {
374                         continue;
375                 }
376                 d_printf("[%s]\n", subkey_name);
377
378                 werr = reg_openkey(ctx, base_key, subkey_name,
379                                    REG_KEY_READ, &sub_key);
380                 if (!W_ERROR_IS_OK(werr)) {
381                         d_fprintf(stderr,
382                                   "Error opening subkey '%s': %s\n",
383                                   subkey_name, dos_errstr(werr));
384                         goto done;
385                 }
386                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
387                         goto done;
388                 }
389                 d_printf("\n");
390         }
391         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
392                 d_fprintf(stderr, "Error enumerating subkeys: %s\n",
393                           dos_errstr(werr));
394                 goto done;
395         }
396
397         ret = 0;
398
399 done:
400         TALLOC_FREE(ctx);
401         return ret;
402 }
403
404 int net_conf_import(int argc, const char **argv)
405 {
406         int ret = -1;
407         const char *filename = NULL;
408         const char *servicename = NULL;
409         bool service_found = false;
410         TALLOC_CTX *ctx;
411         struct share_iterator *shares;
412         struct share_params *share;
413         struct share_params global_share = { GLOBAL_SECTION_SNUM };
414
415         ctx = talloc_init("net_conf_import");
416
417         switch (argc) {
418                 case 0:
419                 default:
420                         net_conf_import_usage(argc, argv);
421                         goto done;
422                 case 2:
423                         servicename = argv[1];
424                 case 1:
425                         filename = argv[0];
426                         break;
427         }
428
429         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
430                 filename));
431
432         if (!lp_load(filename,
433                      false,     /* global_only */
434                      true,      /* save_defaults */
435                      false,     /* add_ipc */
436                      true))     /* initialize_globals */
437         {
438                 d_fprintf(stderr, "Error parsing configuration file.\n");
439                 goto done;
440         }
441
442         if (opt_testmode) {
443                 d_printf("\nTEST MODE - "
444                          "would import the following configuration:\n\n");
445         }
446
447         if (((servicename == NULL) && globals_exist()) ||
448             strequal(servicename, GLOBAL_NAME))
449         {
450                 service_found = true;
451                 if (import_process_service(ctx, &global_share) != 0) {
452                         goto done;
453                 }
454         }
455
456         if (service_found && (servicename != NULL)) {
457                 ret = 0;
458                 goto done;
459         }
460
461         if (!(shares = share_list_all(ctx))) {
462                 d_fprintf(stderr, "Could not list shares...\n");
463                 goto done;
464         }
465         while ((share = next_share(shares)) != NULL) {
466                 if ((servicename == NULL)
467                     || strequal(servicename, lp_servicename(share->service)))
468                 {
469                         service_found = true;
470                         if (import_process_service(ctx, share)!= 0) {
471                                 goto done;
472                         }
473                 }
474         }
475
476         if ((servicename != NULL) && !service_found) {
477                 d_printf("Share %s not found in file %s\n",
478                          servicename, filename);
479                 goto done;
480
481         }
482
483         ret = 0;
484
485 done:
486         TALLOC_FREE(ctx);
487         return ret;
488 }
489
490 int net_conf_listshares(int argc, const char **argv)
491 {
492         WERROR werr = WERR_OK;
493         int ret = -1;
494         struct registry_key *key;
495         uint32 idx = 0;
496         char *subkey_name = NULL;
497         TALLOC_CTX *ctx;
498
499         ctx = talloc_init("listshares");
500
501         if (argc != 0) {
502                 net_conf_listshares_usage(argc, argv);
503                 goto done;
504         }
505
506         werr = libnet_smbconf_reg_open_basepath(ctx, SEC_RIGHTS_ENUM_SUBKEYS,
507                                                 &key);
508         if (!W_ERROR_IS_OK(werr)) {
509                 goto done;
510         }
511
512         for (idx = 0;
513              W_ERROR_IS_OK(werr = reg_enumkey(ctx, key, idx,
514                                               &subkey_name, NULL));
515              idx++)
516         {
517                 d_printf("%s\n", subkey_name);
518         }
519         if (! W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
520                 d_fprintf(stderr, "Error enumerating subkeys: %s\n",
521                           dos_errstr(werr));
522                 goto done;
523         }
524
525         ret = 0;
526
527 done:
528         TALLOC_FREE(ctx);
529         return ret;
530 }
531
532 int net_conf_drop(int argc, const char **argv)
533 {
534         int ret = -1;
535         WERROR werr;
536
537         if (argc != 0) {
538                 net_conf_drop_usage(argc, argv);
539                 goto done;
540         }
541
542         werr = libnet_smbconf_drop();
543         if (!W_ERROR_IS_OK(werr)) {
544                 d_fprintf(stderr, "Error deleting configuration: %s\n",
545                           dos_errstr(werr));
546                 goto done;
547         }
548
549         ret = 0;
550
551 done:
552         return ret;
553 }
554
555 int net_conf_showshare(int argc, const char **argv)
556 {
557         int ret = -1;
558         WERROR werr = WERR_OK;
559         struct registry_key *key = NULL;
560         TALLOC_CTX *ctx;
561
562         ctx = talloc_init("showshare");
563
564         if (argc != 1) {
565                 net_conf_showshare_usage(argc, argv);
566                 goto done;
567         }
568
569         werr = libnet_smbconf_reg_open_path(ctx, argv[0], REG_KEY_READ, &key);
570         if (!W_ERROR_IS_OK(werr)) {
571                 goto done;
572         }
573
574         d_printf("[%s]\n", argv[0]);
575
576         if (!W_ERROR_IS_OK(list_values(ctx, key))) {
577                 goto done;
578         }
579
580         ret = 0;
581
582 done:
583         TALLOC_FREE(ctx);
584         return ret;
585 }
586
587 int net_conf_addshare(int argc, const char **argv)
588 {
589         int ret = -1;
590         WERROR werr = WERR_OK;
591         struct registry_key *newkey = NULL;
592         char *sharename = NULL;
593         const char *path = NULL;
594         const char *comment = NULL;
595         const char *guest_ok = "no";
596         const char *writeable = "no";
597         SMB_STRUCT_STAT sbuf;
598
599         switch (argc) {
600                 case 0:
601                 case 1:
602                 default:
603                         net_conf_addshare_usage(argc, argv);
604                         goto done;
605                 case 5:
606                         comment = argv[4];
607                 case 4:
608                         if (!strnequal(argv[3], "guest_ok=", 9)) {
609                                 net_conf_addshare_usage(argc, argv);
610                                 goto done;
611                         }
612                         switch (argv[3][9]) {
613                                 case 'y':
614                                 case 'Y':
615                                         guest_ok = "yes";
616                                         break;
617                                 case 'n':
618                                 case 'N':
619                                         guest_ok = "no";
620                                         break;
621                                 default:
622                                         net_conf_addshare_usage(argc, argv);
623                                         goto done;
624                         }
625                 case 3:
626                         if (!strnequal(argv[2], "writeable=", 10)) {
627                                 net_conf_addshare_usage(argc, argv);
628                                 goto done;
629                         }
630                         switch (argv[2][10]) {
631                                 case 'y':
632                                 case 'Y':
633                                         writeable = "yes";
634                                         break;
635                                 case 'n':
636                                 case 'N':
637                                         writeable = "no";
638                                         break;
639                                 default:
640                                         net_conf_addshare_usage(argc, argv);
641                                         goto done;
642                         }
643
644                 case 2:
645                         path = argv[1];
646                         sharename = strdup_lower(argv[0]);
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 (getpwnam(sharename)) {
666                 d_fprintf(stderr, "ERROR: share name %s is already a valid "
667                           "system user name.\n", sharename);
668                 goto done;
669         }
670
671         if (strequal(sharename, GLOBAL_NAME)) {
672                 d_fprintf(stderr,
673                           "ERROR: 'global' is not a valid share name.\n");
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) != 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_mode)) {
696                 d_fprintf(stderr,
697                           "ERROR: path '%s' is not a directory.\n",
698                           path);
699                 goto done;
700         }
701
702         /*
703          * create the share
704          */
705
706         werr = libnet_smbconf_reg_createkey_internal(NULL, argv[0], &newkey);
707         if (!W_ERROR_IS_OK(werr)) {
708                 goto done;
709         }
710
711         /* add config params as values */
712
713         werr = libnet_smbconf_reg_setvalue_internal(newkey, "path", path);
714         if (!W_ERROR_IS_OK(werr))
715                 goto done;
716
717         if (comment != NULL) {
718                 werr = libnet_smbconf_reg_setvalue_internal(newkey, "comment",
719                                                             comment);
720                 if (!W_ERROR_IS_OK(werr))
721                         goto done;
722         }
723
724         werr = libnet_smbconf_reg_setvalue_internal(newkey, "guest ok",
725                                                     guest_ok);
726         if (!W_ERROR_IS_OK(werr))
727                 goto done;
728
729         werr = libnet_smbconf_reg_setvalue_internal(newkey, "writeable",
730                                                     writeable);
731         if (!W_ERROR_IS_OK(werr))
732                 goto done;
733
734         ret = 0;
735
736 done:
737         TALLOC_FREE(newkey);
738         SAFE_FREE(sharename);
739         return ret;
740 }
741
742 int net_conf_delshare(int argc, const char **argv)
743 {
744         int ret = -1;
745         const char *sharename = NULL;
746         WERROR werr = WERR_OK;
747
748         if (argc != 1) {
749                 net_conf_delshare_usage(argc, argv);
750                 goto done;
751         }
752         sharename = argv[0];
753
754         werr = libnet_smbconf_delshare(sharename);
755         if (!W_ERROR_IS_OK(werr)) {
756                 d_fprintf(stderr, "Error deleting share %s: %s\n",
757                           sharename, dos_errstr(werr));
758                 goto done;
759         }
760
761         ret = 0;
762 done:
763         return ret;
764 }
765
766 static int net_conf_setparm(int argc, const char **argv)
767 {
768         int ret = -1;
769         WERROR werr = WERR_OK;
770         char *service = NULL;
771         char *param = NULL;
772         const char *value_str = NULL;
773
774         if (argc != 3) {
775                 net_conf_setparm_usage(argc, argv);
776                 goto done;
777         }
778         service = strdup_lower(argv[0]);
779         param = strdup_lower(argv[1]);
780         value_str = argv[2];
781
782         werr = libnet_smbconf_setparm(service, param, value_str);
783
784         if (!W_ERROR_IS_OK(werr)) {
785                 d_fprintf(stderr, "Error setting value '%s': %s\n",
786                           param, dos_errstr(werr));
787                 goto done;
788         }
789
790         ret = 0;
791
792 done:
793         SAFE_FREE(service);
794         SAFE_FREE(param);
795         return ret;
796 }
797
798 static int net_conf_getparm(int argc, const char **argv)
799 {
800         int ret = -1;
801         WERROR werr = WERR_OK;
802         char *service = NULL;
803         char *param = NULL;
804         struct registry_value *value = NULL;
805         TALLOC_CTX *ctx;
806
807         ctx = talloc_init("getparm");
808
809         if (argc != 2) {
810                 net_conf_getparm_usage(argc, argv);
811                 goto done;
812         }
813         service = strdup_lower(argv[0]);
814         param = strdup_lower(argv[1]);
815
816         werr = libnet_smbconf_getparm(ctx, service, param, &value);
817
818         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
819                 d_fprintf(stderr,
820                           "Error: given service '%s' does not exist.\n",
821                           service);
822                 goto done;
823         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
824                 d_fprintf(stderr,
825                           "Error: given parameter '%s' is not set.\n",
826                           param);
827                 goto done;
828         } else if (!W_ERROR_IS_OK(werr)) {
829                 d_fprintf(stderr, "Error getting value '%s': %s.\n",
830                           param, dos_errstr(werr));
831                 goto done;
832         }
833
834         d_printf("%s\n", format_value(ctx, value));
835
836         ret = 0;
837 done:
838         SAFE_FREE(service);
839         SAFE_FREE(param);
840         TALLOC_FREE(ctx);
841         return ret;
842 }
843
844 static int net_conf_delparm(int argc, const char **argv)
845 {
846         int ret = -1;
847         WERROR werr = WERR_OK;
848         char *service = NULL;
849         char *param = NULL;
850
851         if (argc != 2) {
852                 net_conf_delparm_usage(argc, argv);
853                 goto done;
854         }
855         service = strdup_lower(argv[0]);
856         param = strdup_lower(argv[1]);
857
858         werr = libnet_smbconf_delparm(service, param);
859
860         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
861                 d_fprintf(stderr,
862                           "Error: given service '%s' does not exist.\n",
863                           service);
864                 goto done;
865         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
866                 d_fprintf(stderr,
867                           "Error: given parameter '%s' is not set.\n",
868                           param);
869                 goto done;
870         } else if (!W_ERROR_IS_OK(werr)) {
871                 d_fprintf(stderr, "Error deleting value '%s': %s.\n",
872                           param, dos_errstr(werr));
873                 goto done;
874         }
875
876         ret = 0;
877
878 done:
879         SAFE_FREE(service);
880         SAFE_FREE(param);
881         return ret;
882 }
883
884 /*
885  * Entry-point for all the CONF functions.
886  */
887
888 int net_conf(int argc, const char **argv)
889 {
890         int ret = -1;
891         struct functable2 func[] = {
892                 {"list", net_conf_list,
893                  "Dump the complete configuration in smb.conf like format."},
894                 {"import", net_conf_import,
895                  "Import configuration from file in smb.conf format."},
896                 {"listshares", net_conf_listshares,
897                  "List the registry shares."},
898                 {"drop", net_conf_drop,
899                  "Delete the complete configuration from registry."},
900                 {"showshare", net_conf_showshare,
901                  "Show the definition of a registry share."},
902                 {"addshare", net_conf_addshare,
903                  "Create a new registry share."},
904                 {"delshare", net_conf_delshare,
905                  "Delete a registry share."},
906                 {"setparm", net_conf_setparm,
907                  "Store a parameter."},
908                 {"getparm", net_conf_getparm,
909                  "Retrieve the value of a parameter."},
910                 {"delparm", net_conf_delparm,
911                  "Delete a parameter."},
912                 {NULL, NULL, NULL}
913         };
914
915         if (!registry_init_regdb()) {
916                 d_fprintf(stderr, "Error initializing the registry!\n");
917                 goto done;
918         }
919
920         ret = net_run_function2(argc, argv, "net conf", func);
921
922         regdb_close();
923
924 done:
925         return ret;
926 }
927