r8399: move the ejs and esp code closer to the directory layout used by the
[jra/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       var options = new Object();
32       result = GetOptions(argv, options, 
33                           "realm=s", 
34                           "enablexx", 
35                           "myint=i");
36
37       the special options POPT_COMMON_* options are recognised and replaced
38       with the Samba internal options
39
40       resulting parsed options are placed in the options object
41
42       additional command line arguments are placed in options.ARGV
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         TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
60         struct poptOption *long_options = NULL;
61         struct MprVar *options;
62         int i, num_options = 0;
63         int opt_argc;
64         const char **opt_argv;
65         const char **opt_names = NULL;
66         const int BASE_OPTNUM = 0x100000;
67
68         /* validate arguments */
69         if (argc < 2 ||
70             argv[0]->type != MPR_TYPE_OBJECT ||
71             argv[1]->type != MPR_TYPE_OBJECT) {
72                 ejsSetErrorMsg(eid, "GetOptions invalid arguments");
73                 return -1;
74         }
75
76         opt_argv = mprToArray(tmp_ctx, argv[0]);
77         options  = argv[1];
78         opt_argc = str_list_length(opt_argv);
79
80         long_options = talloc_array(tmp_ctx, struct poptOption, 1);
81         if (long_options == NULL) {
82                 return -1;
83         }
84
85         /* create the long_options array */
86         for (i=2;i<argc;i++) {
87                 const char *optstr = mprToString(argv[i]);
88                 int t, opt_type = POPT_ARG_NONE;
89                 const char *s;
90                 if (argv[i]->type != MPR_TYPE_STRING) {
91                         ejsSetErrorMsg(eid, "GetOptions string argument");
92                         return -1;
93                 }
94
95                 long_options = talloc_realloc(tmp_ctx, long_options, 
96                                               struct poptOption, num_options+2);
97                 if (long_options == NULL) {
98                         return -1;
99                 }
100                 ZERO_STRUCT(long_options[num_options]);
101
102                 /* see if its one of the special samba option tables */
103                 for (t=0;t<ARRAY_SIZE(tables);t++) {
104                         if (strcmp(tables[t].name, optstr) == 0) {
105                                 break;
106                         }
107                 }
108                 if (t < ARRAY_SIZE(tables)) {
109                         opt_names = str_list_add(opt_names, optstr);
110                         talloc_steal(tmp_ctx, opt_names);
111                         long_options[num_options].argInfo = POPT_ARG_INCLUDE_TABLE;
112                         long_options[num_options].arg     = tables[t].table;
113                         long_options[num_options].descrip = tables[t].description;
114                         num_options++;
115                         continue;
116                 }
117
118                 s = strchr(optstr, '=');
119                 if (s) {
120                         char *name = talloc_strndup(tmp_ctx, optstr, (int)(s-optstr));
121                         opt_names = str_list_add(opt_names, name);
122                         if (s[1] == 's') {
123                                 opt_type = POPT_ARG_STRING;
124                         } else if (s[1] == 'i') {
125                                 opt_type = POPT_ARG_INT;
126                         } else {
127                                 ejsSetErrorMsg(eid, "GetOptions invalid option type");
128                                 return -1;
129                         }
130                         talloc_free(name);
131                 } else {
132                         opt_names = str_list_add(opt_names, optstr);
133                 }
134                 talloc_steal(tmp_ctx, opt_names);
135                 if (strlen(opt_names[num_options]) == 1) {
136                         long_options[num_options].shortName = opt_names[num_options][0];
137                 } else {
138                         long_options[num_options].longName = opt_names[num_options];
139                 }
140                 long_options[num_options].argInfo = opt_type;
141                 long_options[num_options].val = num_options + BASE_OPTNUM;
142                 num_options++;
143         }
144
145         ZERO_STRUCT(long_options[num_options]);
146
147         pc = poptGetContext("smbscript", opt_argc, opt_argv, long_options, 0);
148
149         /* parse the options */
150         while((opt = poptGetNextOpt(pc)) != -1) {
151                 const char *arg;
152
153                 if (opt < BASE_OPTNUM || opt >= num_options + BASE_OPTNUM) {
154                         char *err;
155                         err = talloc_asprintf(tmp_ctx, "%s: %s",
156                                               poptBadOption(pc, POPT_BADOPTION_NOALIAS),
157                                               poptStrerror(opt));
158                         mprSetVar(options, "ERROR", mprString(err));
159                         talloc_free(tmp_ctx);
160                         mpr_Return(eid, mprCreateBoolVar(0));
161                         return 0;
162                 }
163                 opt -= BASE_OPTNUM;
164                 arg = poptGetOptArg(pc);
165                 if (arg == NULL) {
166                         mprSetVar(options, opt_names[opt], mprCreateBoolVar(1));
167                 } else if (long_options[opt].argInfo == POPT_ARG_INT) {
168                         int v = strtol(arg, NULL, 0);
169                         mprSetVar(options, opt_names[opt], mprCreateIntegerVar(v));
170                 } else {
171                         mprSetVar(options, opt_names[opt], mprString(arg));
172                 }
173         }
174
175         /* setup options.argv list */
176         mprSetVar(options, "ARGV", mprList("ARGV", poptGetArgs(pc)));
177
178         poptFreeContext(pc);
179
180         talloc_free(tmp_ctx);
181         mpr_Return(eid, mprCreateBoolVar(1));
182         return 0;
183 }
184
185
186
187 /*
188   setup C functions that be called from ejs
189 */
190 void smb_setup_ejs_options(void)
191 {
192         ejsDefineCFunction(-1, "GetOptions", ejs_GetOptions, NULL, MPR_VAR_SCRIPT_HANDLE);
193 }