Add header.
[vlendec/samba-autobuild/.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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/cmdline/popt_common.h"
24 #include "scripting/ejs/smbcalls.h"
25
26
27 /*
28   usage:
29       options = GetOptions(argv, 
30                           "realm=s", 
31                           "enablexx", 
32                           "myint=i");
33
34       the special options POPT_COMMON_* options are recognised and replaced
35       with the Samba internal options
36
37       resulting parsed options are placed in the options object
38
39       additional command line arguments are placed in options.ARGV
40 */
41
42 static int ejs_GetOptions(MprVarHandle eid, int argc, struct MprVar **argv)
43 {
44         poptContext pc;
45         int opt;
46         struct {
47                 const char *name;
48                 struct poptOption *table;
49                 const char *description;
50         } tables[] = {
51                 { "POPT_AUTOHELP", poptHelpOptions, "Help options:" },
52                 { "POPT_COMMON_SAMBA", popt_common_samba, "Common Samba options:" },
53                 { "POPT_COMMON_CONNECTION", popt_common_connection, "Connection options:" },
54                 { "POPT_COMMON_CREDENTIALS", popt_common_credentials, "Authentication options:" },
55                 { "POPT_COMMON_VERSION", popt_common_version, "Common Samba options:" }
56         };
57
58         struct MprVar *options = mprInitObject(eid, "options", 0, NULL);
59
60         TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
61         struct poptOption *long_options = NULL;
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 < 1 || argv[0]->type != MPR_TYPE_OBJECT) {
70                 ejsSetErrorMsg(eid, "GetOptions invalid arguments");
71                 return -1;
72         }
73
74         opt_argv = mprToArray(tmp_ctx, argv[0]);
75         opt_argc = str_list_length(opt_argv);
76
77         long_options = talloc_array(tmp_ctx, struct poptOption, 1);
78         if (long_options == NULL) {
79                 return -1;
80         }
81
82         /* create the long_options array */
83         for (i=1;i<argc;i++) {
84                 const char *optstr = mprToString(argv[i]);
85                 int t, opt_type = POPT_ARG_NONE;
86                 const char *s;
87                 if (argv[i]->type != MPR_TYPE_STRING) {
88                         ejsSetErrorMsg(eid, "GetOptions string argument");
89                         return -1;
90                 }
91
92                 long_options = talloc_realloc(tmp_ctx, long_options, 
93                                               struct poptOption, num_options+2);
94                 if (long_options == NULL) {
95                         return -1;
96                 }
97                 ZERO_STRUCT(long_options[num_options]);
98
99                 /* see if its one of the special samba option tables */
100                 for (t=0;t<ARRAY_SIZE(tables);t++) {
101                         if (strcmp(tables[t].name, optstr) == 0) {
102                                 break;
103                         }
104                 }
105                 if (t < ARRAY_SIZE(tables)) {
106                         opt_names = str_list_add(opt_names, optstr);
107                         talloc_steal(tmp_ctx, opt_names);
108                         long_options[num_options].argInfo = POPT_ARG_INCLUDE_TABLE;
109                         long_options[num_options].arg     = tables[t].table;
110                         long_options[num_options].descrip = tables[t].description;
111                         num_options++;
112                         continue;
113                 }
114
115                 s = strchr(optstr, '=');
116                 if (s) {
117                         char *name = talloc_strndup(tmp_ctx, optstr, (int)(s-optstr));
118                         opt_names = str_list_add(opt_names, name);
119                         if (s[1] == 's') {
120                                 opt_type = POPT_ARG_STRING;
121                         } else if (s[1] == 'i') {
122                                 opt_type = POPT_ARG_INT;
123                         } else {
124                                 ejsSetErrorMsg(eid, "GetOptions invalid option type");
125                                 return -1;
126                         }
127                         talloc_free(name);
128                 } else {
129                         opt_names = str_list_add(opt_names, optstr);
130                 }
131                 talloc_steal(tmp_ctx, opt_names);
132                 if (strlen(opt_names[num_options]) == 1) {
133                         long_options[num_options].shortName = opt_names[num_options][0];
134                 } else {
135                         long_options[num_options].longName = opt_names[num_options];
136                 }
137                 long_options[num_options].argInfo = opt_type;
138                 long_options[num_options].val = num_options + BASE_OPTNUM;
139                 num_options++;
140         }
141
142         ZERO_STRUCT(long_options[num_options]);
143
144         pc = poptGetContext("smbscript", opt_argc, opt_argv, long_options, 0);
145
146         /* parse the options */
147         while((opt = poptGetNextOpt(pc)) != -1) {
148                 const char *arg;
149
150                 if (opt < BASE_OPTNUM || opt >= num_options + BASE_OPTNUM) {
151                         char *err;
152                         err = talloc_asprintf(tmp_ctx, "%s: %s",
153                                               poptBadOption(pc, POPT_BADOPTION_NOALIAS),
154                                               poptStrerror(opt));
155                         mprSetVar(options, "ERROR", mprString(err));
156                         talloc_free(tmp_ctx);
157                         mpr_Return(eid, mprCreateUndefinedVar());
158                         return 0;
159                 }
160                 opt -= BASE_OPTNUM;
161                 arg = poptGetOptArg(pc);
162                 if (arg == NULL) {
163                         mprSetVar(options, opt_names[opt], mprCreateBoolVar(1));
164                 } else if (long_options[opt].argInfo == POPT_ARG_INT) {
165                         int v = strtol(arg, NULL, 0);
166                         mprSetVar(options, opt_names[opt], mprCreateIntegerVar(v));
167                 } else {
168                         mprSetVar(options, opt_names[opt], mprString(arg));
169                 }
170         }
171
172         /* setup options.argv list */
173         mprSetVar(options, "ARGV", mprList("ARGV", poptGetArgs(pc)));
174
175         poptFreeContext(pc);
176
177         talloc_free(tmp_ctx);
178
179         /* setup methods */
180         mprSetCFunction(options, "get_credentials", ejs_credentials_cmdline);
181
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 }