r23749: Simplify prototype of reg_setvalue_internal:
[ira/wip.git] / source / 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 2 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, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
20  */
21
22 /*
23  * This is an interface to the configuration stored inside the 
24  * samba registry. In the future there might be support for other 
25  * configuration backends as well.
26  */
27
28 #include "includes.h"
29 #include "utils/net.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> [<servicename>]\n"
44                  "\t[--test|-T]    testmode - do not act, just print "
45                                    "what would be done\n"
46                  "\t<servicename>  only import service <servicename>, "
47                                    "ignore the rest\n");
48         return -1;
49 }
50
51 static int net_conf_listshares_usage(int argc, const char **argv)
52 {
53         d_printf("USAGE: net conf listshares\n");
54         return -1;
55 }
56
57 static int net_conf_drop_usage(int argc, const char **argv)
58 {
59         d_printf("USAGE: net conf drop\n");
60         return -1;
61 }
62
63 static int net_conf_showshare_usage(int argc, const char **argv)
64 {
65         d_printf("USAGE: net conf showshare <sharename>\n");
66         return -1;
67 }
68
69 static int net_conf_addshare_usage(int argc, const char **argv)
70 {
71         d_printf("USAGE: net conf addshare <sharename> <path> "
72                  "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
73                  "\t<sharename>      the new share name.\n"
74                  "\t<path>           the path on the filesystem to export.\n"
75                  "\twriteable={y|N}  set \"writeable to \"yes\" or "
76                  "\"no\" (default) on this share.\n"
77                  "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
78                  "\"no\" (default)   on this share.\n"
79                  "\t<comment>        optional comment for the new share.\n");
80         return -1;
81 }
82
83 static int net_conf_delshare_usage(int argc, const char **argv)
84 {
85         d_printf("USAGE: net conf delshare <sharename>\n");
86         return -1;
87 }
88
89 static int net_conf_setparm_usage(int argc, const char **argv)
90 {
91         d_printf("USAGE: net conf setparm <section> <param> <value>\n");
92         return -1;
93 }
94
95 static int net_conf_getparm_usage(int argc, const char **argv)
96 {
97         d_printf("USAGE: net conf getparm <section> <param>\n");
98         return -1;
99 }
100
101 static int net_conf_delparm_usage(int argc, const char **argv)
102 {
103         d_printf("USAGE: net conf delparm <section> <param>\n");
104         return -1;
105 }
106
107
108 /*
109  * Helper functions
110  */
111
112 static char *format_value(TALLOC_CTX *mem_ctx, struct registry_value *value)
113 {
114         char *result = NULL;
115
116         /* what if mem_ctx = NULL? */
117
118         switch (value->type) {
119         case REG_DWORD:
120                 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
121                 break;
122         case REG_SZ:
123         case REG_EXPAND_SZ:
124                 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
125                 break;
126         case REG_MULTI_SZ: {
127                 uint32 j;
128                 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
129                         result = talloc_asprintf(mem_ctx, "\"%s\" ", 
130                                                  value->v.multi_sz.strings[j]);
131                 }
132                 break;
133         }
134         case REG_BINARY:
135                 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
136                                          (int)value->v.binary.length);
137                 break;
138         default:
139                 result = talloc_asprintf(mem_ctx, "<unprintable>");
140                 break;
141         }
142         return result;
143 }
144
145 /*
146  * add a value to a key. 
147  */
148 static WERROR reg_setvalue_internal(struct registry_key *key,
149                                     const char *valname,
150                                     const char *valstr)
151 {
152         struct registry_value val;
153         WERROR werr = WERR_OK;
154
155         ZERO_STRUCT(val);
156
157         val.type = REG_SZ;
158         val.v.sz.str = CONST_DISCARD(char *, valstr);
159         val.v.sz.len = strlen(valstr) + 1;
160
161         if (!lp_parameter_is_valid(valname)) {
162                 d_fprintf(stderr, "Invalid parameter '%s' given.\n", valname);
163                 werr = WERR_INVALID_PARAM;
164                 goto done;
165         }
166
167         if (registry_smbconf_valname_forbidden(valname)) {
168                 d_fprintf(stderr, "Parameter '%s' not allowed in registry.\n",
169                           valname);
170                 werr = WERR_INVALID_PARAM;
171                 goto done;
172         }
173
174         if (!strequal(strrchr_m(key->key->name, '\\')+1, GLOBAL_NAME) &&
175             lp_parameter_is_global(valname))
176         {
177                 d_fprintf(stderr, "Global paramter '%s' not allowed in "
178                           "service definition ('%s').\n", valname,
179                           strrchr_m(key->key->name, '\\')+1);
180                 werr = WERR_INVALID_PARAM;
181                 goto done;
182         }
183
184         werr = reg_setvalue(key, valname, &val);
185         if (!W_ERROR_IS_OK(werr)) {
186                 d_fprintf(stderr,
187                           "Error adding value '%s' to "
188                           "key '%s': %s\n",
189                           valname, key->key->name, dos_errstr(werr));
190         }
191
192 done:
193         return werr;
194 }
195
196 /* 
197  * Open a subkey of KEY_SMBCONF (i.e a service)
198  * - variant without error output (q = quiet)-
199  */
200 static WERROR smbconf_open_path_q(TALLOC_CTX *ctx, const char *subkeyname,
201                                   uint32 desired_access, 
202                                   struct registry_key **key)
203 {
204         WERROR werr = WERR_OK;
205         char *path = NULL;
206         NT_USER_TOKEN *token;
207
208         if (!(token = registry_create_admin_token(ctx))) {
209                 DEBUG(1, ("Error creating admin token\n"));
210                 goto done;
211         }
212
213         if (subkeyname == NULL) {
214                 path = talloc_strdup(ctx, KEY_SMBCONF);
215         }
216         else {
217                 path = talloc_asprintf(ctx, "%s\\%s", KEY_SMBCONF, subkeyname);
218         }
219
220         werr = reg_open_path(ctx, path, desired_access,
221                              token, key);
222
223 done:
224         TALLOC_FREE(path);
225         return werr;
226 }
227
228 /* 
229  * Open a subkey of KEY_SMBCONF (i.e a service)
230  * - variant with error output -
231  */
232 static WERROR smbconf_open_path(TALLOC_CTX *ctx, const char *subkeyname,
233                                 uint32 desired_access, 
234                                 struct registry_key **key)
235 {
236         WERROR werr = WERR_OK;
237
238         werr = smbconf_open_path_q(ctx, subkeyname, desired_access, key);
239         if (!W_ERROR_IS_OK(werr)) {
240                 d_fprintf(stderr, "Error opening registry path '%s\\%s': %s\n",
241                           KEY_SMBCONF, 
242                           (subkeyname == NULL) ? "" : subkeyname, 
243                           dos_errstr(werr));
244         }
245
246         return werr;
247 }
248
249 /*
250  * open the base key KEY_SMBCONF
251  */
252 static WERROR smbconf_open_basepath(TALLOC_CTX *ctx, uint32 desired_access,
253                                     struct registry_key **key)
254 {
255         return smbconf_open_path(ctx, NULL, desired_access, key);
256 }
257
258 /*
259  * delete a subkey of KEY_SMBCONF
260  */
261 static WERROR reg_delkey_internal(TALLOC_CTX *ctx, const char *keyname)
262 {
263         WERROR werr = WERR_OK;
264         struct registry_key *key = NULL;
265
266         werr = smbconf_open_basepath(ctx, REG_KEY_WRITE, &key);
267         if (!W_ERROR_IS_OK(werr)) {
268                 goto done;
269         }
270
271         werr = reg_deletekey_recursive(key, key, keyname);
272         if (!W_ERROR_IS_OK(werr)) {
273                 d_fprintf(stderr, "Error deleting registry key %s\\%s: %s\n",
274                           KEY_SMBCONF, keyname, dos_errstr(werr));
275         }
276
277 done:
278         TALLOC_FREE(key);
279         return werr;
280 }
281
282 /*
283  * create a subkey of KEY_SMBCONF
284  */
285 static WERROR reg_createkey_internal(TALLOC_CTX *ctx,
286                                      const char * subkeyname,
287                                      struct registry_key **newkey)
288 {
289         WERROR werr = WERR_OK;
290         struct registry_key *create_parent = NULL;
291         TALLOC_CTX *create_ctx;
292         enum winreg_CreateAction action = REG_ACTION_NONE;
293
294         /* create a new talloc ctx for creation. it will hold
295          * the intermediate parent key (SMBCONF) for creation
296          * and will be destroyed when leaving this function... */
297         if (!(create_ctx = talloc_new(ctx))) {
298                 werr = WERR_NOMEM;
299                 goto done;
300         }
301
302         werr = smbconf_open_basepath(create_ctx, REG_KEY_WRITE, &create_parent);
303         if (!W_ERROR_IS_OK(werr)) {
304                 goto done;
305         }
306
307         werr = reg_createkey(ctx, create_parent, subkeyname, 
308                              REG_KEY_WRITE, newkey, &action);
309         if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
310                 d_fprintf(stderr, "Key '%s' already exists.\n", subkeyname);
311                 werr = WERR_ALREADY_EXISTS;
312         }
313         if (!W_ERROR_IS_OK(werr)) {
314                 d_fprintf(stderr, "Error creating key %s: %s\n",
315                          subkeyname, dos_errstr(werr));
316         }
317
318 done:
319         TALLOC_FREE(create_ctx);
320         return werr;
321 }
322
323 /*
324  * check if a subkey of KEY_SMBCONF of a given name exists
325  */
326 static BOOL smbconf_key_exists(TALLOC_CTX *ctx, const char *subkeyname)
327 {
328         BOOL ret = False;
329         WERROR werr = WERR_OK;
330         TALLOC_CTX *mem_ctx;
331         struct registry_key *key;
332
333         if (!(mem_ctx = talloc_new(ctx))) {
334                 d_fprintf(stderr, "ERROR: Out of memory...!\n");
335                 goto done;
336         }
337
338         werr = smbconf_open_path_q(mem_ctx, subkeyname, REG_KEY_READ, &key);
339         if (W_ERROR_IS_OK(werr)) {
340                 ret = True;
341         }
342
343 done:
344         TALLOC_FREE(mem_ctx);
345         return ret;
346 }
347
348 static BOOL smbconf_value_exists(TALLOC_CTX *ctx, struct registry_key *key,
349                                  const char *param)
350 {
351         BOOL ret = False;
352         WERROR werr = WERR_OK;
353         struct registry_value *value = NULL;
354
355         werr = reg_queryvalue(ctx, key, param, &value); 
356         if (W_ERROR_IS_OK(werr)) {
357                 ret = True;
358         }
359
360         TALLOC_FREE(value);
361         return ret;
362 }
363
364 static WERROR list_values(TALLOC_CTX *ctx, struct registry_key *key)
365 {
366         WERROR werr = WERR_OK;
367         uint32 idx = 0;
368         struct registry_value *valvalue = NULL;
369         char *valname = NULL;
370
371         for (idx = 0;
372              W_ERROR_IS_OK(werr = reg_enumvalue(ctx, key, idx, &valname,
373                                                 &valvalue));
374              idx++)
375         {
376                 d_printf("\t%s = %s\n", valname, format_value(ctx, valvalue));
377         }
378         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
379                 d_fprintf(stderr, "Error enumerating values: %s\n",
380                           dos_errstr(werr));
381                 goto done;
382         }
383         werr = WERR_OK;
384
385 done:
386         return werr; 
387 }
388
389 static WERROR drop_smbconf_internal(TALLOC_CTX *ctx)
390 {
391         char *path, *p;
392         WERROR werr = WERR_OK;
393         NT_USER_TOKEN *token;
394         struct registry_key *parent_key = NULL;
395         struct registry_key *new_key = NULL;
396         TALLOC_CTX* tmp_ctx = NULL;
397         enum winreg_CreateAction action;
398
399         tmp_ctx = talloc_new(ctx);
400         if (tmp_ctx == NULL) {
401                 werr = WERR_NOMEM;
402                 goto done;
403         }
404
405         if (!(token = registry_create_admin_token(tmp_ctx))) {
406                 /* what is the appropriate error code here? */
407                 werr = WERR_CAN_NOT_COMPLETE; 
408                 goto done;
409         }
410
411         path = talloc_strdup(tmp_ctx, KEY_SMBCONF);
412         if (path == NULL) {
413                 d_fprintf(stderr, "ERROR: out of memory!\n");
414                 werr = WERR_NOMEM;
415                 goto done;
416         }
417         p = strrchr(path, '\\');
418         *p = '\0';
419         werr = reg_open_path(tmp_ctx, path, REG_KEY_WRITE, token, &parent_key);
420
421         if (!W_ERROR_IS_OK(werr)) {
422                 goto done;
423         }
424
425         werr = reg_deletekey_recursive(tmp_ctx, parent_key, p+1);
426
427         if (!W_ERROR_IS_OK(werr)) {
428                 goto done;
429         }
430         
431         werr = reg_createkey(tmp_ctx, parent_key, p+1, REG_KEY_WRITE, 
432                              &new_key, &action);
433
434 done:
435         TALLOC_FREE(tmp_ctx);
436         return werr;
437 }
438
439 static char *parm_valstr(TALLOC_CTX *ctx, struct parm_struct *parm,
440                          struct share_params *share)
441 {
442         char *valstr = NULL;
443         int i = 0;
444         void *ptr = parm->ptr;
445
446         if (parm->p_class == P_LOCAL && share->service >= 0) {
447                 ptr = lp_local_ptr(share->service, ptr);
448         }
449
450         switch (parm->type) {
451         case P_CHAR:
452                 valstr = talloc_asprintf(ctx, "%c", *(char *)ptr);
453                 break;
454         case P_STRING:
455         case P_USTRING:
456                 valstr = talloc_asprintf(ctx, "%s", *(char **)ptr);
457                 break;
458         case P_GSTRING:
459         case P_UGSTRING:
460                 valstr = talloc_asprintf(ctx, "%s", (char *)ptr);
461                 break;
462         case P_BOOL:
463                 valstr = talloc_asprintf(ctx, "%s", BOOLSTR(*(BOOL *)ptr));
464                 break;
465         case P_BOOLREV:
466                 valstr = talloc_asprintf(ctx, "%s", BOOLSTR(!*(BOOL *)ptr));
467                 break;
468         case P_ENUM:
469                 for (i = 0; parm->enum_list[i].name; i++) {
470                         if (*(int *)ptr == parm->enum_list[i].value)
471                         {
472                                 valstr = talloc_asprintf(ctx, "%s",
473                                          parm->enum_list[i].name);
474                                 break;
475                         }
476                 }
477                 break;
478         case P_OCTAL:
479                 valstr = talloc_asprintf(ctx, "%s", octal_string(*(int *)ptr));
480                 break;
481         case P_LIST:
482                 valstr = talloc_strdup(ctx, "");
483                 if ((char ***)ptr && *(char ***)ptr) {
484                         char **list = *(char ***)ptr;
485                         for (; *list; list++) {
486                                 /* surround strings with whitespace
487                                  * in double quotes */
488                                 if (strchr_m(*list, ' '))
489                                 {
490                                         valstr = talloc_asprintf_append(
491                                                 valstr, "\"%s\"%s",
492                                                 *list,
493                                                  ((*(list+1))?", ":""));
494                                 }
495                                 else {
496                                         valstr = talloc_asprintf_append(
497                                                 valstr, "%s%s", *list,
498                                                  ((*(list+1))?", ":""));
499                                 }
500                         }
501                 }
502                 break;
503         case P_INTEGER:
504                 valstr = talloc_asprintf(ctx, "%d", *(int *)ptr);
505                 break;
506         case P_SEP:
507                 break;
508         default:
509                 valstr = talloc_asprintf(ctx, "<type unimplemented>\n");
510                 break;
511         }
512
513         return valstr;
514 }
515
516 static int import_process_service(TALLOC_CTX *ctx,
517                                   struct share_params *share)
518 {
519         int ret = -1;
520         struct parm_struct *parm;
521         int pnum = 0;
522         const char *servicename;
523         struct registry_key *key;
524         WERROR werr;
525         char *valstr = NULL;
526         TALLOC_CTX *tmp_ctx = NULL;
527
528         tmp_ctx = talloc_new(ctx);
529         if (tmp_ctx == NULL) {
530                 werr = WERR_NOMEM;
531                 goto done;
532         }
533
534         servicename = (share->service == GLOBAL_SECTION_SNUM)?
535                 GLOBAL_NAME : lp_servicename(share->service);
536
537         if (opt_testmode) {
538                 d_printf("[%s]\n", servicename);
539         }
540         else {
541                 if (smbconf_key_exists(tmp_ctx, servicename)) {
542                         werr = reg_delkey_internal(tmp_ctx, servicename);
543                         if (!W_ERROR_IS_OK(werr)) {
544                                 goto done;
545                         }
546                 }
547                 werr = reg_createkey_internal(tmp_ctx, servicename, &key);
548                 if (!W_ERROR_IS_OK(werr)) {
549                         goto done;
550                 }
551         }
552
553         while ((parm = lp_next_parameter(share->service, &pnum, 0)))
554         {
555                 if ((share->service < 0 && parm->p_class == P_LOCAL)
556                     && !(parm->flags & FLAG_GLOBAL))
557                         continue;
558
559                 valstr = parm_valstr(tmp_ctx, parm, share);
560
561                 if (parm->type != P_SEP) {
562                         if (opt_testmode) {
563                                 d_printf("\t%s = %s\n", parm->label, valstr);
564                         }
565                         else {
566                                 werr = reg_setvalue_internal(key, parm->label,
567                                                              valstr);
568                                 if (!W_ERROR_IS_OK(werr)) {
569                                         goto done;
570                                 }
571                         }
572                 }
573         }
574
575         if (opt_testmode) {
576                 d_printf("\n");
577         }
578
579         ret = 0;
580
581 done:
582         TALLOC_FREE(tmp_ctx);
583         return ret;
584 }
585
586
587 /*
588  * the conf functions 
589  */
590
591 int net_conf_list(int argc, const char **argv)
592 {
593         WERROR werr = WERR_OK;
594         int ret = -1;
595         TALLOC_CTX *ctx;
596         struct registry_key *base_key = NULL;
597         struct registry_key *sub_key = NULL;
598         uint32 idx_key = 0;
599         char *subkey_name = NULL;
600
601         ctx = talloc_init("list");
602
603         if (argc != 0) {
604                 net_conf_list_usage(argc, argv);
605                 goto done;
606         }
607
608         werr = smbconf_open_basepath(ctx, REG_KEY_READ, &base_key);
609         if (!W_ERROR_IS_OK(werr)) {
610                 goto done;
611         }
612
613         if (smbconf_key_exists(ctx, GLOBAL_NAME))  {
614                 werr = reg_openkey(ctx, base_key, GLOBAL_NAME, 
615                                    REG_KEY_READ, &sub_key);
616                 if (!W_ERROR_IS_OK(werr)) {
617                         d_fprintf(stderr, "Error opening subkey '%s' : %s\n",
618                                   subkey_name, dos_errstr(werr));
619                         goto done;
620                 }
621                 d_printf("[%s]\n", GLOBAL_NAME);
622                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
623                         goto done;
624                 }
625                 d_printf("\n");
626         }
627
628         for (idx_key = 0;
629              W_ERROR_IS_OK(werr = reg_enumkey(ctx, base_key, idx_key,
630                                               &subkey_name, NULL));
631              idx_key++) 
632         {
633                 if (strequal(subkey_name, GLOBAL_NAME)) {
634                         continue;
635                 }
636                 d_printf("[%s]\n", subkey_name);
637
638                 werr = reg_openkey(ctx, base_key, subkey_name, 
639                                    REG_KEY_READ, &sub_key);
640                 if (!W_ERROR_IS_OK(werr)) {
641                         d_fprintf(stderr, 
642                                   "Error opening subkey '%s': %s\n",
643                                   subkey_name, dos_errstr(werr));
644                         goto done;
645                 }
646                 if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
647                         goto done;
648                 }
649                 d_printf("\n");
650         }
651         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
652                 d_fprintf(stderr, "Error enumerating subkeys: %s\n", 
653                           dos_errstr(werr));
654                 goto done;
655         }
656
657         ret = 0;
658
659 done:
660         TALLOC_FREE(ctx);
661         return ret;
662 }
663
664 int net_conf_import(int argc, const char **argv)
665 {
666         int ret = -1;
667         const char *filename = NULL;
668         const char *servicename = NULL;
669         BOOL service_found = False;
670         TALLOC_CTX *ctx;
671         struct share_iterator *shares;
672         struct share_params *share;
673         struct share_params global_share = { GLOBAL_SECTION_SNUM };
674
675         ctx = talloc_init("net_conf_import");
676
677         switch (argc) {
678                 case 0:
679                 default:
680                         net_conf_import_usage(argc, argv);
681                         goto done;
682                 case 2:
683                         servicename = argv[1];
684                 case 1:
685                         filename = argv[0];
686                         break;
687         }
688
689         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
690                 filename));
691
692         if (!lp_load(filename, 
693                      False,     /* global_only */
694                      True,      /* save_defaults */
695                      False,     /* add_ipc */
696                      True))     /* initialize_globals */
697         {
698                 d_fprintf(stderr, "Error parsing configuration file.\n");
699                 goto done;
700         }
701
702         if (opt_testmode) {
703                 d_printf("\nTEST MODE - would import the following configuration:\n\n");
704         }
705
706         if ((servicename == NULL) || strequal(servicename, GLOBAL_NAME)) {
707                 service_found = True;
708                 if (import_process_service(ctx, &global_share) != 0) {
709                         goto done;
710                 }
711         }
712
713         if (service_found && (servicename != NULL)) {
714                 ret = 0;
715                 goto done;
716         }
717
718         if (!(shares = share_list_all(ctx))) {
719                 d_fprintf(stderr, "Could not list shares...\n");
720                 goto done;
721         }
722         while ((share = next_share(shares)) != NULL) {
723                 if ((servicename == NULL) 
724                     || strequal(servicename, lp_servicename(share->service))) 
725                 {
726                         service_found = True;
727                         if (import_process_service(ctx, share)!= 0) {
728                                 goto done;
729                         }
730                 }
731         }
732         
733         if ((servicename != NULL) && !service_found) {
734                 d_printf("Share %s not found in file %s\n", 
735                          servicename, filename);
736                 goto done;
737
738         }
739
740         ret = 0;
741         
742 done:
743         TALLOC_FREE(ctx);
744         return ret;
745 }
746
747 int net_conf_listshares(int argc, const char **argv)
748 {
749         WERROR werr = WERR_OK;
750         int ret = -1;
751         struct registry_key *key;
752         uint32 idx = 0;
753         char *subkey_name = NULL;
754         TALLOC_CTX *ctx;
755
756         ctx = talloc_init("listshares");
757
758         if (argc != 0) {
759                 net_conf_listshares_usage(argc, argv);
760                 goto done;
761         }
762
763         werr = smbconf_open_basepath(ctx, SEC_RIGHTS_ENUM_SUBKEYS, &key);
764         if (!W_ERROR_IS_OK(werr)) {
765                 goto done;
766         }
767
768         for (idx = 0;
769              W_ERROR_IS_OK(werr = reg_enumkey(ctx, key, idx,
770                                               &subkey_name, NULL));
771              idx++) 
772         {
773                 d_printf("%s\n", subkey_name);
774         }
775         if (! W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
776                 d_fprintf(stderr, "Error enumerating subkeys: %s\n", 
777                           dos_errstr(werr));
778                 goto done;
779         }
780
781         ret = 0;
782
783 done:
784         TALLOC_FREE(ctx);
785         return ret;
786 }
787
788 int net_conf_drop(int argc, const char **argv)
789 {
790         int ret = -1;
791         WERROR werr;
792
793         if (argc != 0) {
794                 net_conf_drop_usage(argc, argv);
795                 goto done;
796         }
797
798         werr = drop_smbconf_internal(NULL);
799         if (!W_ERROR_IS_OK(werr)) {
800                 d_fprintf(stderr, "Error deleting configuration: %s\n",
801                           dos_errstr(werr));
802                 goto done;
803         }
804
805         ret = 0;
806
807 done:
808         return ret;
809 }
810
811 int net_conf_showshare(int argc, const char **argv)
812 {
813         int ret = -1;
814         WERROR werr = WERR_OK;
815         struct registry_key *key = NULL;
816         TALLOC_CTX *ctx;
817
818         ctx = talloc_init("showshare");
819
820         if (argc != 1) {
821                 net_conf_showshare_usage(argc, argv);
822                 goto done;
823         }
824
825         werr = smbconf_open_path(ctx, argv[0], REG_KEY_READ, &key);
826         if (!W_ERROR_IS_OK(werr)) {
827                 goto done;
828         }
829
830         d_printf("[%s]\n", argv[0]);
831
832         if (!W_ERROR_IS_OK(list_values(ctx, key))) {
833                 goto done;
834         }
835
836         ret = 0;
837
838 done:
839         TALLOC_FREE(ctx);
840         return ret;
841 }
842
843 int net_conf_addshare(int argc, const char **argv)
844 {
845         int ret = -1;
846         WERROR werr = WERR_OK;
847         struct registry_key *newkey = NULL;
848         char *sharename = NULL;
849         const char *path = NULL;
850         const char *comment = NULL;
851         const char *guest_ok = "no";
852         const char *writeable = "no";
853         SMB_STRUCT_STAT sbuf;
854
855         switch (argc) {
856                 case 0:
857                 case 1:
858                 default: 
859                         net_conf_addshare_usage(argc, argv);
860                         goto done;
861                 case 5:
862                         comment = argv[4];
863                 case 4:
864                         if (!strnequal(argv[3], "guest_ok=", 9)) {
865                                 net_conf_addshare_usage(argc, argv);
866                                 goto done;
867                         }
868                         switch (argv[3][9]) {
869                                 case 'y':
870                                 case 'Y':
871                                         guest_ok = "yes";
872                                         break;
873                                 case 'n':
874                                 case 'N':
875                                         guest_ok = "no";
876                                         break;
877                                 default: 
878                                         net_conf_addshare_usage(argc, argv);
879                                         goto done;
880                         }
881                 case 3:
882                         if (!strnequal(argv[2], "writeable=", 10)) {
883                                 net_conf_addshare_usage(argc, argv);
884                                 goto done;
885                         }
886                         switch (argv[2][10]) {
887                                 case 'y':
888                                 case 'Y':
889                                         writeable = "yes";
890                                         break;
891                                 case 'n':
892                                 case 'N':
893                                         writeable = "no";
894                                         break;
895                                 default:
896                                         net_conf_addshare_usage(argc, argv);
897                                         goto done;
898                         }
899
900                 case 2:
901                         path = argv[1];
902                         sharename = strdup_lower(argv[0]);
903                         break;
904         }
905
906         /* 
907          * validate arguments 
908          */
909
910         /* validate share name */
911
912         if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, 
913                                strlen(sharename))) 
914         {
915                 d_fprintf(stderr, "ERROR: share name %s contains "
916                         "invalid characters (any of %s)\n",
917                         sharename, INVALID_SHARENAME_CHARS);
918                 goto done;
919         }
920
921         if (getpwnam(sharename)) {
922                 d_fprintf(stderr, "ERROR: share name %s is already a valid "
923                           "system user name.\n", sharename);
924                 goto done;
925         }
926
927         if (strequal(sharename, GLOBAL_NAME)) {
928                 d_fprintf(stderr, 
929                           "ERROR: 'global' is not a valid share name.\n");
930                 goto done;
931         }
932
933         /* validate path */
934
935         if (path[0] != '/') {
936                 d_fprintf(stderr, 
937                           "Error: path '%s' is not an absolute path.\n",
938                           path);
939                 goto done;
940         }
941
942         if (sys_stat(path, &sbuf) != 0) {
943                 d_fprintf(stderr,
944                           "ERROR: cannot stat path '%s' to ensure "
945                           "this is a directory.\n"
946                           "Error was '%s'.\n", 
947                           path, strerror(errno));
948                 goto done;
949         }
950
951         if (!S_ISDIR(sbuf.st_mode)) {
952                 d_fprintf(stderr,
953                           "ERROR: path '%s' is not a directory.\n",
954                           path);
955                 goto done;
956         }
957
958         /* 
959          * create the share 
960          */
961
962         werr = reg_createkey_internal(NULL, argv[0], &newkey);
963         if (!W_ERROR_IS_OK(werr)) {
964                 goto done;
965         }
966
967         /* add config params as values */
968
969         werr = reg_setvalue_internal(newkey, "path", path);
970         if (!W_ERROR_IS_OK(werr))
971                 goto done;
972
973         if (comment != NULL) {
974                 werr = reg_setvalue_internal(newkey, "comment", comment);
975                 if (!W_ERROR_IS_OK(werr))
976                         goto done;
977         }
978
979         werr = reg_setvalue_internal(newkey, "guest ok", guest_ok);
980         if (!W_ERROR_IS_OK(werr))
981                 goto done;
982         
983         werr = reg_setvalue_internal(newkey, "writeable", writeable);
984         if (!W_ERROR_IS_OK(werr))
985                 goto done;
986
987         ret = 0;
988
989 done:
990         TALLOC_FREE(newkey);
991         SAFE_FREE(sharename);
992         return ret;
993 }
994
995 int net_conf_delshare(int argc, const char **argv)
996 {
997         int ret = -1;
998         const char *sharename = NULL;
999
1000         if (argc != 1) {
1001                 net_conf_delshare_usage(argc, argv);
1002                 goto done;
1003         }
1004         sharename = argv[0];
1005         
1006         if (W_ERROR_IS_OK(reg_delkey_internal(NULL, sharename))) {
1007                 ret = 0;
1008         }
1009 done:
1010         return ret;
1011 }
1012
1013 static int net_conf_setparm(int argc, const char **argv)
1014 {
1015         int ret = -1;
1016         WERROR werr = WERR_OK;
1017         struct registry_key *key = NULL;
1018         char *service = NULL;
1019         char *param = NULL;
1020         const char *value_str = NULL;
1021         TALLOC_CTX *ctx;
1022
1023         ctx = talloc_init("setparm");
1024
1025         if (argc != 3) {
1026                 net_conf_setparm_usage(argc, argv);
1027                 goto done;
1028         }
1029         service = strdup_lower(argv[0]);
1030         param = strdup_lower(argv[1]);
1031         value_str = argv[2];
1032
1033         if (!smbconf_key_exists(ctx, service)) {
1034                 werr = reg_createkey_internal(ctx, service, &key);
1035         }
1036         else {
1037                 werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1038         }
1039         if (!W_ERROR_IS_OK(werr)) {
1040                 goto done;
1041         }
1042
1043         werr = reg_setvalue_internal(key, param, value_str);
1044         if (!W_ERROR_IS_OK(werr)) {
1045                 d_fprintf(stderr, "Error setting value '%s': %s\n",
1046                           param, dos_errstr(werr));
1047                 goto done;
1048         }
1049
1050
1051         ret = 0;
1052
1053 done:
1054         SAFE_FREE(service);
1055         TALLOC_FREE(ctx);
1056         return ret;
1057 }
1058
1059 static int net_conf_getparm(int argc, const char **argv)
1060 {
1061         int ret = -1;
1062         WERROR werr = WERR_OK;
1063         struct registry_key *key = NULL;
1064         char *service = NULL;
1065         char *param = NULL;
1066         struct registry_value *value = NULL;
1067         TALLOC_CTX *ctx;
1068
1069         ctx = talloc_init("getparm");
1070
1071         if (argc != 2) {
1072                 net_conf_getparm_usage(argc, argv);
1073                 goto done;
1074         }
1075         service = strdup_lower(argv[0]);
1076         param = strdup_lower(argv[1]);
1077
1078         if (!smbconf_key_exists(ctx, service)) {
1079                 d_fprintf(stderr, 
1080                           "ERROR: given service '%s' does not exist.\n",
1081                           service);
1082                 goto done;
1083         }
1084
1085         werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1086         if (!W_ERROR_IS_OK(werr)) {
1087                 goto done;
1088         }
1089
1090         werr = reg_queryvalue(ctx, key, param, &value);
1091         if (!W_ERROR_IS_OK(werr)) {
1092                 d_fprintf(stderr, "Error querying value '%s': %s.\n",
1093                           param, dos_errstr(werr));
1094                 goto done;
1095         }
1096         
1097         d_printf("%s\n", format_value(ctx, value));
1098         
1099         ret = 0;
1100 done:
1101         SAFE_FREE(service);
1102         SAFE_FREE(param);
1103         TALLOC_FREE(ctx);
1104         return ret;
1105 }
1106
1107 static int net_conf_delparm(int argc, const char **argv)
1108 {
1109         int ret = -1;
1110         WERROR werr = WERR_OK;
1111         struct registry_key *key = NULL;
1112         char *service = NULL;
1113         char *param = NULL;
1114         TALLOC_CTX *ctx;
1115
1116         ctx = talloc_init("delparm");
1117
1118         if (argc != 2) {
1119                 net_conf_delparm_usage(argc, argv);
1120                 goto done;
1121         }
1122         service = strdup_lower(argv[0]);
1123         param = strdup_lower(argv[1]);
1124
1125         if (!smbconf_key_exists(ctx, service)) {
1126                 d_fprintf(stderr, 
1127                           "Error: given service '%s' does not exist.\n",
1128                           service);
1129                 goto done;
1130         }
1131
1132         werr = smbconf_open_path(ctx, service, REG_KEY_READ, &key);
1133         if (!W_ERROR_IS_OK(werr)) {
1134                 goto done;
1135         }
1136
1137         if (!smbconf_value_exists(ctx, key, param)) {
1138                 d_fprintf(stderr, 
1139                           "Error: given parameter '%s' is not set.\n",
1140                           param);
1141                 goto done;
1142         }
1143         werr = reg_deletevalue(key, param);
1144         if (!W_ERROR_IS_OK(werr)) {
1145                 d_fprintf(stderr, "Error deleting value '%s': %s.\n",
1146                           param, dos_errstr(werr));
1147                 goto done;
1148         }
1149
1150         ret = 0;
1151
1152 done:
1153         return ret;
1154 }
1155
1156 /*
1157  * Entry-point for all the CONF functions.
1158  */
1159
1160 int net_conf(int argc, const char **argv)
1161 {
1162         int ret = -1;
1163         struct functable2 func[] = {
1164                 {"list", net_conf_list, 
1165                  "Dump the complete configuration in smb.conf like format."},
1166                 {"import", net_conf_import,
1167                  "Import configuration from file in smb.conf format."},
1168                 {"listshares", net_conf_listshares, 
1169                  "List the registry shares."},
1170                 {"drop", net_conf_drop,
1171                  "Delete the complete configuration from registry."},
1172                 {"showshare", net_conf_showshare, 
1173                  "Show the definition of a registry share."},
1174                 {"addshare", net_conf_addshare, 
1175                  "Create a new registry share."},
1176                 {"delshare", net_conf_delshare, 
1177                  "Delete a registry share."},
1178                 {"setparm", net_conf_setparm, 
1179                  "Store a parameter."},
1180                 {"getparm", net_conf_getparm, 
1181                  "Retrieve the value of a parameter."},
1182                 {"delparm", net_conf_delparm, 
1183                  "Delete a parameter."},
1184                 {NULL, NULL, NULL}
1185         };
1186
1187         if (!registry_init_regdb()) {
1188                 d_fprintf(stderr, "Error initializing the registry!\n");
1189                 goto done;
1190         }
1191
1192         ret = net_run_function2(argc, argv, "net conf", func);
1193
1194         regdb_close();
1195
1196 done:
1197         return ret;
1198 }
1199
1200 /* END */