net conf: fix import to correctly add includes (at the end)
[Samba.git] / source / utils / net_conf.c
blobc01a326c640026ea65128ed10314c813f2842700
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-2008
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 * This is an interface to Samba's configuration as made available
23 * by the libsmbconf interface (source/lib/smbconf/smbconf.c).
25 * This currently supports local interaction with the configuration
26 * stored in the registry. But other backends and remote access via
27 * rpc might get implemented in the future.
30 #include "includes.h"
31 #include "utils/net.h"
33 /**********************************************************************
35 * usage functions
37 **********************************************************************/
39 static int net_conf_list_usage(int argc, const char **argv)
41 d_printf("USAGE: net conf list\n");
42 return -1;
45 static int net_conf_import_usage(int argc, const char**argv)
47 d_printf("USAGE: net conf import [--test|-T] <filename> "
48 "[<servicename>]\n"
49 "\t[--test|-T] testmode - do not act, just print "
50 "what would be done\n"
51 "\t<servicename> only import service <servicename>, "
52 "ignore the rest\n");
53 return -1;
56 static int net_conf_listshares_usage(int argc, const char **argv)
58 d_printf("USAGE: net conf listshares\n");
59 return -1;
62 static int net_conf_drop_usage(int argc, const char **argv)
64 d_printf("USAGE: net conf drop\n");
65 return -1;
68 static int net_conf_showshare_usage(int argc, const char **argv)
70 d_printf("USAGE: net conf showshare <sharename>\n");
71 return -1;
74 static int net_conf_addshare_usage(int argc, const char **argv)
76 d_printf("USAGE: net conf addshare <sharename> <path> "
77 "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
78 "\t<sharename> the new share name.\n"
79 "\t<path> the path on the filesystem to export.\n"
80 "\twriteable={y|N} set \"writeable to \"yes\" or "
81 "\"no\" (default) on this share.\n"
82 "\tguest_ok={y|N} set \"guest ok\" to \"yes\" or "
83 "\"no\" (default) on this share.\n"
84 "\t<comment> optional comment for the new share.\n");
85 return -1;
88 static int net_conf_delshare_usage(int argc, const char **argv)
90 d_printf("USAGE: net conf delshare <sharename>\n");
91 return -1;
94 static int net_conf_setparm_usage(int argc, const char **argv)
96 d_printf("USAGE: net conf setparm <section> <param> <value>\n");
97 return -1;
100 static int net_conf_getparm_usage(int argc, const char **argv)
102 d_printf("USAGE: net conf getparm <section> <param>\n");
103 return -1;
106 static int net_conf_delparm_usage(int argc, const char **argv)
108 d_printf("USAGE: net conf delparm <section> <param>\n");
109 return -1;
113 /**********************************************************************
115 * Helper functions
117 **********************************************************************/
120 * This functions process a service previously loaded with libsmbconf.
122 static WERROR import_process_service(struct smbconf_ctx *conf_ctx,
123 const char *servicename,
124 const uint32_t num_params,
125 const char **param_names,
126 const char **param_values)
128 uint32_t idx;
129 WERROR werr = WERR_OK;
130 uint32_t num_includes = 0;
131 char **includes = NULL;
132 TALLOC_CTX *mem_ctx = talloc_stackframe();
134 if (opt_testmode) {
135 d_printf("[%s]\n", servicename);
136 } else {
137 if (smbconf_share_exists(conf_ctx, servicename)) {
138 werr = smbconf_delete_share(conf_ctx, servicename);
139 if (!W_ERROR_IS_OK(werr)) {
140 goto done;
143 werr = smbconf_create_share(conf_ctx, servicename);
144 if (!W_ERROR_IS_OK(werr)) {
145 goto done;
149 for (idx = 0; idx < num_params; idx ++) {
150 if (opt_testmode) {
151 d_printf("\t%s = %s\n", param_names[idx],
152 param_values[idx]);
153 } else {
154 if (strequal(param_names[idx], "include")) {
155 includes = TALLOC_REALLOC_ARRAY(mem_ctx,
156 includes,
157 char *,
158 num_includes+1);
159 if (includes == NULL) {
160 werr = WERR_NOMEM;
161 goto done;
163 includes[num_includes] =
164 talloc_strdup(includes,
165 param_values[idx]);
166 if (includes[num_includes] == NULL) {
167 werr = WERR_NOMEM;
168 goto done;
170 num_includes++;
171 } else {
172 werr = smbconf_set_parameter(conf_ctx,
173 servicename,
174 param_names[idx],
175 param_values[idx]);
176 if (!W_ERROR_IS_OK(werr)) {
177 goto done;
183 if (!opt_testmode) {
184 werr = smbconf_set_includes(conf_ctx, servicename, num_includes,
185 (const char **)includes);
188 done:
189 TALLOC_FREE(mem_ctx);
190 return werr;
194 /**********************************************************************
196 * the main conf functions
198 **********************************************************************/
200 static int net_conf_list(struct smbconf_ctx *conf_ctx,
201 int argc, const char **argv)
203 WERROR werr = WERR_OK;
204 int ret = -1;
205 TALLOC_CTX *mem_ctx;
206 uint32_t num_shares;
207 char **share_names;
208 uint32_t *num_params;
209 char ***param_names;
210 char ***param_values;
211 uint32_t share_count, param_count;
213 mem_ctx = talloc_stackframe();
215 if (argc != 0) {
216 net_conf_list_usage(argc, argv);
217 goto done;
220 werr = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &share_names,
221 &num_params, &param_names, &param_values);
222 if (!W_ERROR_IS_OK(werr)) {
223 d_fprintf(stderr, "Error getting config: %s\n",
224 dos_errstr(werr));
225 goto done;
228 for (share_count = 0; share_count < num_shares; share_count++) {
229 d_printf("[%s]\n", share_names[share_count]);
230 for (param_count = 0; param_count < num_params[share_count];
231 param_count++)
233 d_printf("\t%s = %s\n",
234 param_names[share_count][param_count],
235 param_values[share_count][param_count]);
237 d_printf("\n");
240 ret = 0;
242 done:
243 TALLOC_FREE(mem_ctx);
244 return ret;
247 static int net_conf_import(struct smbconf_ctx *conf_ctx,
248 int argc, const char **argv)
250 int ret = -1;
251 const char *filename = NULL;
252 const char *servicename = NULL;
253 TALLOC_CTX *mem_ctx;
254 struct smbconf_ctx *txt_ctx;
255 WERROR werr;
257 mem_ctx = talloc_stackframe();
259 switch (argc) {
260 case 0:
261 default:
262 net_conf_import_usage(argc, argv);
263 goto done;
264 case 2:
265 servicename = argv[1];
266 case 1:
267 filename = argv[0];
268 break;
271 DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
272 filename));
274 werr = smbconf_init_txt_simple(mem_ctx, &txt_ctx, filename, true);
275 if (!W_ERROR_IS_OK(werr)) {
276 goto done;
279 if (opt_testmode) {
280 d_printf("\nTEST MODE - "
281 "would import the following configuration:\n\n");
284 if (servicename != NULL) {
285 char **param_names, **param_values;
286 uint32_t num_params;
288 werr = smbconf_get_share(txt_ctx, mem_ctx,
289 servicename,
290 &num_params,
291 &param_names,
292 &param_values);
293 if (!W_ERROR_IS_OK(werr)) {
294 goto done;
296 werr = import_process_service(conf_ctx,
297 servicename,
298 num_params,
299 (const char **)param_names,
300 (const char **)param_values);
301 if (!W_ERROR_IS_OK(werr)) {
302 goto done;
304 } else {
305 char **share_names, ***param_names, ***param_values;
306 uint32_t num_shares, *num_params, sidx;
308 werr = smbconf_get_config(txt_ctx, mem_ctx,
309 &num_shares,
310 &share_names,
311 &num_params,
312 &param_names,
313 &param_values);
314 if (!W_ERROR_IS_OK(werr)) {
315 goto done;
317 werr = smbconf_drop(conf_ctx);
318 if (!W_ERROR_IS_OK(werr)) {
319 goto done;
321 for (sidx = 0; sidx < num_shares; sidx++) {
322 werr = import_process_service(conf_ctx,
323 share_names[sidx],
324 num_params[sidx],
325 (const char **)param_names[sidx],
326 (const char **)param_values[sidx]);
327 if (!W_ERROR_IS_OK(werr)) {
328 goto done;
333 ret = 0;
335 done:
336 TALLOC_FREE(mem_ctx);
337 return ret;
340 static int net_conf_listshares(struct smbconf_ctx *conf_ctx,
341 int argc, const char **argv)
343 WERROR werr = WERR_OK;
344 int ret = -1;
345 uint32_t count, num_shares = 0;
346 char **share_names = NULL;
347 TALLOC_CTX *mem_ctx;
349 mem_ctx = talloc_stackframe();
351 if (argc != 0) {
352 net_conf_listshares_usage(argc, argv);
353 goto done;
356 werr = smbconf_get_share_names(conf_ctx, mem_ctx, &num_shares,
357 &share_names);
358 if (!W_ERROR_IS_OK(werr)) {
359 goto done;
362 for (count = 0; count < num_shares; count++)
364 d_printf("%s\n", share_names[count]);
367 ret = 0;
369 done:
370 TALLOC_FREE(mem_ctx);
371 return ret;
374 static int net_conf_drop(struct smbconf_ctx *conf_ctx,
375 int argc, const char **argv)
377 int ret = -1;
378 WERROR werr;
380 if (argc != 0) {
381 net_conf_drop_usage(argc, argv);
382 goto done;
385 werr = smbconf_drop(conf_ctx);
386 if (!W_ERROR_IS_OK(werr)) {
387 d_fprintf(stderr, "Error deleting configuration: %s\n",
388 dos_errstr(werr));
389 goto done;
392 ret = 0;
394 done:
395 return ret;
398 static int net_conf_showshare(struct smbconf_ctx *conf_ctx,
399 int argc, const char **argv)
401 int ret = -1;
402 WERROR werr = WERR_OK;
403 const char *sharename = NULL;
404 TALLOC_CTX *mem_ctx;
405 uint32_t num_params;
406 uint32_t count;
407 char **param_names;
408 char **param_values;
410 mem_ctx = talloc_stackframe();
412 if (argc != 1) {
413 net_conf_showshare_usage(argc, argv);
414 goto done;
417 sharename = argv[0];
419 werr = smbconf_get_share(conf_ctx, mem_ctx, sharename, &num_params,
420 &param_names, &param_values);
421 if (!W_ERROR_IS_OK(werr)) {
422 d_printf("error getting share parameters: %s\n",
423 dos_errstr(werr));
424 goto done;
427 d_printf("[%s]\n", sharename);
429 for (count = 0; count < num_params; count++) {
430 d_printf("\t%s = %s\n", param_names[count],
431 param_values[count]);
434 ret = 0;
436 done:
437 TALLOC_FREE(mem_ctx);
438 return ret;
442 * Add a share, with a couple of standard parameters, partly optional.
444 * This is a high level utility function of the net conf utility,
445 * not a direct frontend to the smbconf API.
447 static int net_conf_addshare(struct smbconf_ctx *conf_ctx,
448 int argc, const char **argv)
450 int ret = -1;
451 WERROR werr = WERR_OK;
452 char *sharename = NULL;
453 const char *path = NULL;
454 const char *comment = NULL;
455 const char *guest_ok = "no";
456 const char *writeable = "no";
457 SMB_STRUCT_STAT sbuf;
459 switch (argc) {
460 case 0:
461 case 1:
462 default:
463 net_conf_addshare_usage(argc, argv);
464 goto done;
465 case 5:
466 comment = argv[4];
467 case 4:
468 if (!strnequal(argv[3], "guest_ok=", 9)) {
469 net_conf_addshare_usage(argc, argv);
470 goto done;
472 switch (argv[3][9]) {
473 case 'y':
474 case 'Y':
475 guest_ok = "yes";
476 break;
477 case 'n':
478 case 'N':
479 guest_ok = "no";
480 break;
481 default:
482 net_conf_addshare_usage(argc, argv);
483 goto done;
485 case 3:
486 if (!strnequal(argv[2], "writeable=", 10)) {
487 net_conf_addshare_usage(argc, argv);
488 goto done;
490 switch (argv[2][10]) {
491 case 'y':
492 case 'Y':
493 writeable = "yes";
494 break;
495 case 'n':
496 case 'N':
497 writeable = "no";
498 break;
499 default:
500 net_conf_addshare_usage(argc, argv);
501 goto done;
503 case 2:
504 path = argv[1];
505 sharename = strdup_lower(argv[0]);
506 break;
510 * validate arguments
513 /* validate share name */
515 if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
516 strlen(sharename)))
518 d_fprintf(stderr, "ERROR: share name %s contains "
519 "invalid characters (any of %s)\n",
520 sharename, INVALID_SHARENAME_CHARS);
521 goto done;
524 if (getpwnam(sharename)) {
525 d_fprintf(stderr, "ERROR: share name %s is already a valid "
526 "system user name.\n", sharename);
527 goto done;
530 if (strequal(sharename, GLOBAL_NAME)) {
531 d_fprintf(stderr,
532 "ERROR: 'global' is not a valid share name.\n");
533 goto done;
536 if (smbconf_share_exists(conf_ctx, sharename)) {
537 d_fprintf(stderr, "ERROR: share %s already exists.\n",
538 sharename);
539 goto done;
542 /* validate path */
544 if (path[0] != '/') {
545 d_fprintf(stderr,
546 "Error: path '%s' is not an absolute path.\n",
547 path);
548 goto done;
551 if (sys_stat(path, &sbuf) != 0) {
552 d_fprintf(stderr,
553 "ERROR: cannot stat path '%s' to ensure "
554 "this is a directory.\n"
555 "Error was '%s'.\n",
556 path, strerror(errno));
557 goto done;
560 if (!S_ISDIR(sbuf.st_mode)) {
561 d_fprintf(stderr,
562 "ERROR: path '%s' is not a directory.\n",
563 path);
564 goto done;
568 * create the share
571 werr = smbconf_create_share(conf_ctx, sharename);
572 if (!W_ERROR_IS_OK(werr)) {
573 d_fprintf(stderr, "Error creating share %s: %s\n",
574 sharename, dos_errstr(werr));
575 goto done;
579 * fill the share with parameters
582 werr = smbconf_set_parameter(conf_ctx, sharename, "path", path);
583 if (!W_ERROR_IS_OK(werr)) {
584 d_fprintf(stderr, "Error setting parameter %s: %s\n",
585 "path", dos_errstr(werr));
586 goto done;
589 if (comment != NULL) {
590 werr = smbconf_set_parameter(conf_ctx, sharename, "comment",
591 comment);
592 if (!W_ERROR_IS_OK(werr)) {
593 d_fprintf(stderr, "Error setting parameter %s: %s\n",
594 "comment", dos_errstr(werr));
595 goto done;
599 werr = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
600 if (!W_ERROR_IS_OK(werr)) {
601 d_fprintf(stderr, "Error setting parameter %s: %s\n",
602 "'guest ok'", dos_errstr(werr));
603 goto done;
606 werr = smbconf_set_parameter(conf_ctx, sharename, "writeable",
607 writeable);
608 if (!W_ERROR_IS_OK(werr)) {
609 d_fprintf(stderr, "Error setting parameter %s: %s\n",
610 "writeable", dos_errstr(werr));
611 goto done;
614 ret = 0;
616 done:
617 SAFE_FREE(sharename);
618 return ret;
621 static int net_conf_delshare(struct smbconf_ctx *conf_ctx,
622 int argc, const char **argv)
624 int ret = -1;
625 const char *sharename = NULL;
626 WERROR werr = WERR_OK;
628 if (argc != 1) {
629 net_conf_delshare_usage(argc, argv);
630 goto done;
632 sharename = argv[0];
634 werr = smbconf_delete_share(conf_ctx, sharename);
635 if (!W_ERROR_IS_OK(werr)) {
636 d_fprintf(stderr, "Error deleting share %s: %s\n",
637 sharename, dos_errstr(werr));
638 goto done;
641 ret = 0;
642 done:
643 return ret;
646 static int net_conf_setparm(struct smbconf_ctx *conf_ctx,
647 int argc, const char **argv)
649 int ret = -1;
650 WERROR werr = WERR_OK;
651 char *service = NULL;
652 char *param = NULL;
653 const char *value_str = NULL;
655 if (argc != 3) {
656 net_conf_setparm_usage(argc, argv);
657 goto done;
659 service = strdup_lower(argv[0]);
660 param = strdup_lower(argv[1]);
661 value_str = argv[2];
663 if (!smbconf_share_exists(conf_ctx, service)) {
664 werr = smbconf_create_share(conf_ctx, service);
665 if (!W_ERROR_IS_OK(werr)) {
666 d_fprintf(stderr, "Error creating share '%s': %s\n",
667 service, dos_errstr(werr));
668 goto done;
672 werr = smbconf_set_parameter(conf_ctx, service, param, value_str);
674 if (!W_ERROR_IS_OK(werr)) {
675 d_fprintf(stderr, "Error setting value '%s': %s\n",
676 param, dos_errstr(werr));
677 goto done;
680 ret = 0;
682 done:
683 SAFE_FREE(service);
684 SAFE_FREE(param);
685 return ret;
688 static int net_conf_getparm(struct smbconf_ctx *conf_ctx,
689 int argc, const char **argv)
691 int ret = -1;
692 WERROR werr = WERR_OK;
693 char *service = NULL;
694 char *param = NULL;
695 char *valstr = NULL;
696 TALLOC_CTX *mem_ctx;
698 mem_ctx = talloc_stackframe();
700 if (argc != 2) {
701 net_conf_getparm_usage(argc, argv);
702 goto done;
704 service = strdup_lower(argv[0]);
705 param = strdup_lower(argv[1]);
707 werr = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
709 if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
710 d_fprintf(stderr,
711 "Error: given service '%s' does not exist.\n",
712 service);
713 goto done;
714 } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
715 d_fprintf(stderr,
716 "Error: given parameter '%s' is not set.\n",
717 param);
718 goto done;
719 } else if (!W_ERROR_IS_OK(werr)) {
720 d_fprintf(stderr, "Error getting value '%s': %s.\n",
721 param, dos_errstr(werr));
722 goto done;
725 d_printf("%s\n", valstr);
727 ret = 0;
728 done:
729 SAFE_FREE(service);
730 SAFE_FREE(param);
731 TALLOC_FREE(mem_ctx);
732 return ret;
735 static int net_conf_delparm(struct smbconf_ctx *conf_ctx,
736 int argc, const char **argv)
738 int ret = -1;
739 WERROR werr = WERR_OK;
740 char *service = NULL;
741 char *param = NULL;
743 if (argc != 2) {
744 net_conf_delparm_usage(argc, argv);
745 goto done;
747 service = strdup_lower(argv[0]);
748 param = strdup_lower(argv[1]);
750 werr = smbconf_delete_parameter(conf_ctx, service, param);
752 if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
753 d_fprintf(stderr,
754 "Error: given service '%s' does not exist.\n",
755 service);
756 goto done;
757 } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
758 d_fprintf(stderr,
759 "Error: given parameter '%s' is not set.\n",
760 param);
761 goto done;
762 } else if (!W_ERROR_IS_OK(werr)) {
763 d_fprintf(stderr, "Error deleting value '%s': %s.\n",
764 param, dos_errstr(werr));
765 goto done;
768 ret = 0;
770 done:
771 SAFE_FREE(service);
772 SAFE_FREE(param);
773 return ret;
777 /**********************************************************************
779 * Wrapper and net_conf_run_function mechanism.
781 **********************************************************************/
784 * Wrapper function to call the main conf functions.
785 * The wrapper calls handles opening and closing of the
786 * configuration.
788 static int net_conf_wrap_function(int (*fn)(struct smbconf_ctx *,
789 int, const char **),
790 int argc, const char **argv)
792 WERROR werr;
793 TALLOC_CTX *mem_ctx = talloc_stackframe();
794 struct smbconf_ctx *conf_ctx;
795 int ret = -1;
797 werr = smbconf_init_reg(mem_ctx, &conf_ctx, NULL);
799 if (!W_ERROR_IS_OK(werr)) {
800 return -1;
803 ret = fn(conf_ctx, argc, argv);
805 smbconf_shutdown(conf_ctx);
807 return ret;
811 * We need a functable struct of our own, because the
812 * functions are called through a wrapper that handles
813 * the opening and closing of the configuration, and so on.
815 struct conf_functable {
816 const char *funcname;
817 int (*fn)(struct smbconf_ctx *ctx, int argc, const char **argv);
818 const char *helptext;
822 * This imitates net_run_function2 but calls the main functions
823 * through the wrapper net_conf_wrap_function().
825 static int net_conf_run_function(int argc, const char **argv,
826 const char *whoami,
827 struct conf_functable *table)
829 int i;
831 if (argc != 0) {
832 for (i=0; table[i].funcname; i++) {
833 if (StrCaseCmp(argv[0], table[i].funcname) == 0)
834 return net_conf_wrap_function(table[i].fn,
835 argc-1,
836 argv+1);
840 for (i=0; table[i].funcname; i++) {
841 d_printf("%s %-15s %s\n", whoami, table[i].funcname,
842 table[i].helptext);
845 return -1;
849 * Entry-point for all the CONF functions.
852 int net_conf(int argc, const char **argv)
854 int ret = -1;
855 struct conf_functable func_table[] = {
856 {"list", net_conf_list,
857 "Dump the complete configuration in smb.conf like format."},
858 {"import", net_conf_import,
859 "Import configuration from file in smb.conf format."},
860 {"listshares", net_conf_listshares,
861 "List the share names."},
862 {"drop", net_conf_drop,
863 "Delete the complete configuration."},
864 {"showshare", net_conf_showshare,
865 "Show the definition of a share."},
866 {"addshare", net_conf_addshare,
867 "Create a new share."},
868 {"delshare", net_conf_delshare,
869 "Delete a share."},
870 {"setparm", net_conf_setparm,
871 "Store a parameter."},
872 {"getparm", net_conf_getparm,
873 "Retrieve the value of a parameter."},
874 {"delparm", net_conf_delparm,
875 "Delete a parameter."},
876 {NULL, NULL, NULL}
879 ret = net_conf_run_function(argc, argv, "net conf", func_table);
881 return ret;