r9735: More work on generating a valid Samba4 configuration using the
[samba.git] / source4 / scripting / ejs / smbcalls_options.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    provide a command line options parsing function for ejs
5
6    Copyright (C) Andrew Tridgell 2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "lib/cmdline/popt_common.h"
25 #include "scripting/ejs/smbcalls.h"
26 #include "lib/appweb/ejs/ejs.h"
27
28
29 /*
30   usage:
31       options = GetOptions(argv, 
32                           "realm=s", 
33                           "enablexx", 
34                           "myint=i");
35
36       the special options POPT_COMMON_* options are recognised and replaced
37       with the Samba internal options
38
39       resulting parsed options are placed in the options object
40
41       additional command line arguments are placed in options.ARGV
42 */
43
44 static int ejs_GetOptions(MprVarHandle eid, int argc, struct MprVar **argv)
45 {
46         poptContext pc;
47         int opt;
48         struct {
49                 const char *name;
50                 struct poptOption *table;
51                 const char *description;
52         } tables[] = {
53                 { "POPT_AUTOHELP", poptHelpOptions, "Help options:" },
54                 { "POPT_COMMON_SAMBA", popt_common_samba, "Common Samba options:" },
55                 { "POPT_COMMON_CONNECTION", popt_common_connection, "Connection options:" },
56                 { "POPT_COMMON_CREDENTIALS", popt_common_credentials, "Authentication options:" },
57                 { "POPT_COMMON_VERSION", popt_common_version, "Common Samba options:" }
58         };
59
60         struct MprVar *options = mprInitObject(eid, "options", 0, NULL);
61
62         TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
63         struct poptOption *long_options = NULL;
64         int i, num_options = 0;
65         int opt_argc;
66         const char **opt_argv;
67         const char **opt_names = NULL;
68         const int BASE_OPTNUM = 0x100000;
69
70         /* validate arguments */
71         if (argc < 1 || argv[0]->type != MPR_TYPE_OBJECT) {
72                 ejsSetErrorMsg(eid, "GetOptions invalid arguments");
73                 return -1;
74         }
75
76         opt_argv = mprToArray(tmp_ctx, argv[0]);
77         opt_argc = str_list_length(opt_argv);
78
79         long_options = talloc_array(tmp_ctx, struct poptOption, 1);
80         if (long_options == NULL) {
81                 return -1;
82         }
83
84         /* create the long_options array */
85         for (i=1;i<argc;i++) {
86                 const char *optstr = mprToString(argv[i]);
87                 int t, opt_type = POPT_ARG_NONE;
88                 const char *s;
89                 if (argv[i]->type != MPR_TYPE_STRING) {
90                         ejsSetErrorMsg(eid, "GetOptions string argument");
91                         return -1;
92                 }
93
94                 long_options = talloc_realloc(tmp_ctx, long_options, 
95                                               struct poptOption, num_options+2);
96                 if (long_options == NULL) {
97                         return -1;
98                 }
99                 ZERO_STRUCT(long_options[num_options]);
100
101                 /* see if its one of the special samba option tables */
102                 for (t=0;t<ARRAY_SIZE(tables);t++) {
103                         if (strcmp(tables[t].name, optstr) == 0) {
104                                 break;
105                         }
106                 }
107                 if (t < ARRAY_SIZE(tables)) {
108                         opt_names = str_list_add(opt_names, optstr);
109                         talloc_steal(tmp_ctx, opt_names);
110                         long_options[num_options].argInfo = POPT_ARG_INCLUDE_TABLE;
111                         long_options[num_options].arg     = tables[t].table;
112                         long_options[num_options].descrip = tables[t].description;
113                         num_options++;
114                         continue;
115                 }
116
117                 s = strchr(optstr, '=');
118                 if (s) {
119                         char *name = talloc_strndup(tmp_ctx, optstr, (int)(s-optstr));
120                         opt_names = str_list_add(opt_names, name);
121                         if (s[1] == 's') {
122                                 opt_type = POPT_ARG_STRING;
123                         } else if (s[1] == 'i') {
124                                 opt_type = POPT_ARG_INT;
125                         } else {
126                                 ejsSetErrorMsg(eid, "GetOptions invalid option type");
127                                 return -1;
128                         }
129                         talloc_free(name);
130                 } else {
131                         opt_names = str_list_add(opt_names, optstr);
132                 }
133                 talloc_steal(tmp_ctx, opt_names);
134                 if (strlen(opt_names[num_options]) == 1) {
135                         long_options[num_options].shortName = opt_names[num_options][0];
136                 } else {
137                         long_options[num_options].longName = opt_names[num_options];
138                 }
139                 long_options[num_options].argInfo = opt_type;
140                 long_options[num_options].val = num_options + BASE_OPTNUM;
141                 num_options++;
142         }
143
144         ZERO_STRUCT(long_options[num_options]);
145
146         pc = poptGetContext("smbscript", opt_argc, opt_argv, long_options, 0);
147
148         /* parse the options */
149         while((opt = poptGetNextOpt(pc)) != -1) {
150                 const char *arg;
151
152                 if (opt < BASE_OPTNUM || opt >= num_options + BASE_OPTNUM) {
153                         char *err;
154                         err = talloc_asprintf(tmp_ctx, "%s: %s",
155                                               poptBadOption(pc, POPT_BADOPTION_NOALIAS),
156                                               poptStrerror(opt));
157                         mprSetVar(options, "ERROR", mprString(err));
158                         talloc_free(tmp_ctx);
159                         mpr_Return(eid, mprCreateUndefinedVar());
160                         return 0;
161                 }
162                 opt -= BASE_OPTNUM;
163                 arg = poptGetOptArg(pc);
164                 if (arg == NULL) {
165                         mprSetVar(options, opt_names[opt], mprCreateBoolVar(1));
166                 } else if (long_options[opt].argInfo == POPT_ARG_INT) {
167                         int v = strtol(arg, NULL, 0);
168                         mprSetVar(options, opt_names[opt], mprCreateIntegerVar(v));
169                 } else {
170                         mprSetVar(options, opt_names[opt], mprString(arg));
171                 }
172         }
173
174         /* setup options.argv list */
175         mprSetVar(options, "ARGV", mprList("ARGV", poptGetArgs(pc)));
176
177         poptFreeContext(pc);
178
179         talloc_free(tmp_ctx);
180
181         /* setup methods */
182         mprSetCFunction(options, "get_credentials", ejs_credentials_cmdline);
183
184         return 0;
185 }
186
187
188
189 /*
190   setup C functions that be called from ejs
191 */
192 void smb_setup_ejs_options(void)
193 {
194         ejsDefineCFunction(-1, "GetOptions", ejs_GetOptions, NULL, MPR_VAR_SCRIPT_HANDLE);
195 }