Cleanup syscall code to look more like it's mips64 equivalent.
[linux-2.6/linux-mips.git] / kernel / params.c
blob2ad478068887117933c30ced6ea0dd9982d4b277
1 /* Helpers for initial module or kernel cmdline parsing
2 Copyright (C) 2001 Rusty Russell.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include <linux/moduleparam.h>
19 #include <linux/kernel.h>
20 #include <linux/string.h>
21 #include <linux/errno.h>
22 #include <linux/module.h>
24 #if 0
25 #define DEBUGP printk
26 #else
27 #define DEBUGP(fmt, a...)
28 #endif
30 static inline int dash2underscore(char c)
32 if (c == '-')
33 return '_';
34 return c;
37 static inline int parameq(const char *input, const char *paramname)
39 unsigned int i;
40 for (i = 0; dash2underscore(input[i]) == paramname[i]; i++)
41 if (input[i] == '\0')
42 return 1;
43 return 0;
46 static int parse_one(char *param,
47 char *val,
48 struct kernel_param *params,
49 unsigned num_params,
50 int (*handle_unknown)(char *param, char *val))
52 unsigned int i;
54 /* Find parameter */
55 for (i = 0; i < num_params; i++) {
56 if (parameq(param, params[i].name)) {
57 DEBUGP("They are equal! Calling %p\n",
58 params[i].set);
59 return params[i].set(val, &params[i]);
63 if (handle_unknown) {
64 DEBUGP("Unknown argument: calling %p\n", handle_unknown);
65 return handle_unknown(param, val);
68 DEBUGP("Unknown argument `%s'\n", param);
69 return -ENOENT;
72 /* You can use " around spaces, but can't escape ". */
73 /* Hyphens and underscores equivalent in parameter names. */
74 static char *next_arg(char *args, char **param, char **val)
76 unsigned int i, equals = 0;
77 int in_quote = 0;
79 /* Chew any extra spaces */
80 while (*args == ' ') args++;
82 for (i = 0; args[i]; i++) {
83 if (args[i] == ' ' && !in_quote)
84 break;
85 if (equals == 0) {
86 if (args[i] == '=')
87 equals = i;
89 if (args[i] == '"')
90 in_quote = !in_quote;
93 *param = args;
94 if (!equals)
95 *val = NULL;
96 else {
97 args[equals] = '\0';
98 *val = args + equals + 1;
101 if (args[i]) {
102 args[i] = '\0';
103 return args + i + 1;
104 } else
105 return args + i;
108 /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
109 int parse_args(const char *name,
110 char *args,
111 struct kernel_param *params,
112 unsigned num,
113 int (*unknown)(char *param, char *val))
115 char *param, *val;
117 DEBUGP("Parsing ARGS: %s\n", args);
119 while (*args) {
120 int ret;
122 args = next_arg(args, &param, &val);
123 ret = parse_one(param, val, params, num, unknown);
124 switch (ret) {
125 case -ENOENT:
126 printk(KERN_ERR "%s: Unknown parameter `%s'\n",
127 name, param);
128 return ret;
129 case -ENOSPC:
130 printk(KERN_ERR
131 "%s: `%s' too large for parameter `%s'\n",
132 name, val ?: "", param);
133 return ret;
134 case 0:
135 break;
136 default:
137 printk(KERN_ERR
138 "%s: `%s' invalid for parameter `%s'\n",
139 name, val ?: "", param);
140 return ret;
144 /* All parsed OK. */
145 return 0;
148 /* Lazy bastard, eh? */
149 #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
150 int param_set_##name(const char *val, struct kernel_param *kp) \
152 char *endp; \
153 tmptype l; \
155 if (!val) return -EINVAL; \
156 l = strtolfn(val, &endp, 0); \
157 if (endp == val || *endp || ((type)l != l)) \
158 return -EINVAL; \
159 *((type *)kp->arg) = l; \
160 return 0; \
162 int param_get_##name(char *buffer, struct kernel_param *kp) \
164 return sprintf(buffer, format, *((type *)kp->arg)); \
167 STANDARD_PARAM_DEF(short, short, "%hi", long, simple_strtol);
168 STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", long, simple_strtol);
169 STANDARD_PARAM_DEF(int, int, "%i", long, simple_strtol);
170 STANDARD_PARAM_DEF(uint, unsigned int, "%u", long, simple_strtol);
171 STANDARD_PARAM_DEF(long, long, "%li", long, simple_strtol);
172 STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, simple_strtoul);
174 int param_set_charp(const char *val, struct kernel_param *kp)
176 if (!val) {
177 printk(KERN_ERR "%s: string parameter expected\n",
178 kp->name);
179 return -EINVAL;
182 if (strlen(val) > 1024) {
183 printk(KERN_ERR "%s: string parameter too long\n",
184 kp->name);
185 return -ENOSPC;
188 *(char **)kp->arg = (char *)val;
189 return 0;
192 int param_get_charp(char *buffer, struct kernel_param *kp)
194 return sprintf(buffer, "%s", *((char **)kp->arg));
197 int param_set_bool(const char *val, struct kernel_param *kp)
199 /* No equals means "set"... */
200 if (!val) val = "1";
202 /* One of =[yYnN01] */
203 switch (val[0]) {
204 case 'y': case 'Y': case '1':
205 *(int *)kp->arg = 1;
206 return 0;
207 case 'n': case 'N': case '0':
208 *(int *)kp->arg = 0;
209 return 0;
211 return -EINVAL;
214 int param_get_bool(char *buffer, struct kernel_param *kp)
216 /* Y and N chosen as being relatively non-coder friendly */
217 return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'Y' : 'N');
220 int param_set_invbool(const char *val, struct kernel_param *kp)
222 int boolval, ret;
223 struct kernel_param dummy = { .arg = &boolval };
225 ret = param_set_bool(val, &dummy);
226 if (ret == 0)
227 *(int *)kp->arg = !boolval;
228 return ret;
231 int param_get_invbool(char *buffer, struct kernel_param *kp)
233 int val;
234 struct kernel_param dummy = { .arg = &val };
236 val = !*(int *)kp->arg;
237 return param_get_bool(buffer, &dummy);
240 /* We cheat here and temporarily mangle the string. */
241 int param_array(const char *name,
242 const char *val,
243 unsigned int min, unsigned int max,
244 void *elem, int elemsize,
245 int (*set)(const char *, struct kernel_param *kp))
247 int ret;
248 unsigned int count = 0;
249 struct kernel_param kp;
250 char save;
252 /* Get the name right for errors. */
253 kp.name = name;
254 kp.arg = elem;
256 /* No equals sign? */
257 if (!val) {
258 printk(KERN_ERR "%s: expects arguments\n", name);
259 return -EINVAL;
262 /* We expect a comma-separated list of values. */
263 do {
264 int len;
266 if (count > max) {
267 printk(KERN_ERR "%s: can only take %i arguments\n",
268 name, max);
269 return -EINVAL;
271 len = strcspn(val, ",");
273 /* nul-terminate and parse */
274 save = val[len];
275 ((char *)val)[len] = '\0';
276 ret = set(val, &kp);
278 if (ret != 0)
279 return ret;
280 kp.arg += elemsize;
281 val += len+1;
282 count++;
283 } while (save == ',');
285 if (count < min) {
286 printk(KERN_ERR "%s: needs at least %i arguments\n",
287 name, min);
288 return -EINVAL;
290 return 0;
293 /* First two elements are the max and min array length (which don't change) */
294 int param_set_intarray(const char *val, struct kernel_param *kp)
296 int *array;
298 /* Grab min and max as first two elements */
299 array = kp->arg;
300 return param_array(kp->name, val, array[0], array[1], &array[2],
301 sizeof(int), param_set_int);
304 int param_get_intarray(char *buffer, struct kernel_param *kp)
306 int max;
307 int *array;
308 unsigned int i;
310 array = kp->arg;
311 max = array[1];
313 for (i = 2; i < max + 2; i++)
314 sprintf(buffer, "%s%i", i > 2 ? "," : "", array[i]);
315 return strlen(buffer);
318 int param_set_copystring(const char *val, struct kernel_param *kp)
320 struct kparam_string *kps = kp->arg;
322 if (strlen(val)+1 > kps->maxlen) {
323 printk(KERN_ERR "%s: string doesn't fit in %u chars.\n",
324 kp->name, kps->maxlen-1);
325 return -ENOSPC;
327 strcpy(kps->string, val);
328 return 0;
331 EXPORT_SYMBOL(param_set_short);
332 EXPORT_SYMBOL(param_get_short);
333 EXPORT_SYMBOL(param_set_ushort);
334 EXPORT_SYMBOL(param_get_ushort);
335 EXPORT_SYMBOL(param_set_int);
336 EXPORT_SYMBOL(param_get_int);
337 EXPORT_SYMBOL(param_set_uint);
338 EXPORT_SYMBOL(param_get_uint);
339 EXPORT_SYMBOL(param_set_long);
340 EXPORT_SYMBOL(param_get_long);
341 EXPORT_SYMBOL(param_set_ulong);
342 EXPORT_SYMBOL(param_get_ulong);
343 EXPORT_SYMBOL(param_set_charp);
344 EXPORT_SYMBOL(param_get_charp);
345 EXPORT_SYMBOL(param_set_bool);
346 EXPORT_SYMBOL(param_get_bool);
347 EXPORT_SYMBOL(param_set_invbool);
348 EXPORT_SYMBOL(param_get_invbool);
349 EXPORT_SYMBOL(param_set_intarray);
350 EXPORT_SYMBOL(param_get_intarray);
351 EXPORT_SYMBOL(param_set_copystring);