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