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