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