210 |
|
|
211 |
|
|
212 |
|
|
213 |
|
static const char short_options[] = |
214 |
|
"+ib::c:a:A:e::l::u::LUn:N:m:o:s:t::IqxV:k:"; |
215 |
|
|
216 |
|
enum {OPT_NONE = 0, OPT_EXECUTE, OPT_NOEXECUTE} opt_values; |
217 |
static struct option long_options[] = |
static struct option long_options[] = |
218 |
{ |
{ |
219 |
{"no-execute", 0, NULL, 1}, |
{"execute", 0, NULL, OPT_EXECUTE}, |
220 |
{"execute", 0, NULL, 2}, |
{"no-execute", 0, NULL, OPT_NOEXECUTE}, |
221 |
{0, 0, 0, 0} |
{0, 0, NULL, OPT_NONE} |
222 |
}; |
}; |
223 |
|
|
224 |
|
|
225 |
|
|
226 |
/* Accept a `;' delimited string and break it into tokens. Allocate a return |
/* Accept a `;' delimited string and break it into tokens. Allocate a |
227 |
* string. Copy the first token into the return string. For remaining tokens, |
* return string. Copy the first token into the return string |
228 |
* convert to the long option VAL (from the global LONG_OPTIONS above) and |
* checking to be sure that each character is a valid option character |
229 |
* append that char to the return value. When long option tokens are |
* of the short_options string. For remaining tokens, convert to the |
230 |
|
* long option VAL (from the global LONG_OPTIONS above) and append |
231 |
|
* that char to the return value. When long option tokens are |
232 |
* unrecognized, a warning is printed and they are ignored. |
* unrecognized, a warning is printed and they are ignored. |
233 |
* |
* |
234 |
* i.e., S will be of the format `[SHORTOPTIONS][;LONGOPTION]...'. It is |
* i.e., S will be of the format `[SHORTOPTIONS][;LONGOPTION]...'. It is |
235 |
* perfectly acceptable for SHORTOPTIONS to resolve to the empty string, but |
* perfectly acceptable for SHORTOPTIONS to resolve to the empty string, |
236 |
* an empty LONGOPTION will cause a warning message to be printed. |
* an empty LONGOPTION will also be ignored. |
237 |
*/ |
*/ |
238 |
char * |
char * |
239 |
make_UserAdminOptions (const char *infopath, unsigned int ln, const char *s) |
make_UserAdminOptions (const char *infopath, unsigned int ln, const char *s) |
240 |
{ |
{ |
241 |
const char *p; |
const char *cur_opt, *next_opt; |
242 |
bool first = true; |
size_t len; |
243 |
char *ns = xmalloc (1); |
char *ns; |
244 |
|
|
245 |
assert (s); |
assert (s); |
246 |
|
|
247 |
p = s; |
cur_opt = s; |
248 |
|
|
249 |
|
next_opt = strchr (cur_opt, ';'); |
250 |
|
if (next_opt) |
251 |
|
len = next_opt - cur_opt; |
252 |
|
else |
253 |
|
len = strlen (cur_opt); |
254 |
|
|
255 |
|
ns = xmalloc (len + 1); |
256 |
*ns = '\0'; |
*ns = '\0'; |
257 |
do |
if (len > 0) |
258 |
{ |
{ |
259 |
struct option *found; |
const char *p; |
260 |
const char *q; |
size_t nspos = 0; |
261 |
size_t len; |
/* validate short options */ |
262 |
|
for (p = cur_opt; p < (cur_opt + len); p++) |
|
q = strchr (p, ';'); |
|
|
if (q) len = q - p; |
|
|
else len = strlen (p); |
|
|
|
|
|
if (first) |
|
263 |
{ |
{ |
264 |
first = false; |
if (*p == '+' || *p == ':' || strchr (short_options, *p) == NULL) |
265 |
found = NULL; |
error (0, 0, |
266 |
|
"%s [%u]: Unrecognized short admin option `%c'.", |
267 |
|
infopath, ln, *p); |
268 |
|
else |
269 |
|
ns[nspos++] = *p; |
270 |
} |
} |
271 |
|
ns[nspos] = '\0'; |
272 |
|
if (nspos > 0) |
273 |
|
TRACE (TRACE_FUNCTION, "Setting short UserAdminOptions `%s'", ns); |
274 |
|
} |
275 |
|
|
276 |
|
/* process long options (if any) */ |
277 |
|
while ((cur_opt = next_opt)) |
278 |
|
{ |
279 |
|
next_opt = strchr (++cur_opt, ';'); |
280 |
|
|
281 |
|
if (next_opt) |
282 |
|
len = next_opt - cur_opt; |
283 |
else |
else |
284 |
|
len = strlen (cur_opt); |
285 |
|
|
286 |
|
/* ignore empty long options (ie, ';;') */ |
287 |
|
if (len > 0) |
288 |
|
{ |
289 |
|
struct option *found; |
290 |
|
|
291 |
for (found = long_options; found->name; found++) |
for (found = long_options; found->name; found++) |
292 |
if (len == strlen (found->name) |
if (len == strlen (found->name) |
293 |
&& !strncmp (p, found->name, len)) |
&& !strncmp (cur_opt, found->name, len)) |
294 |
break; |
break; |
295 |
|
|
296 |
if (found && found->name) |
if (found->name) |
297 |
{ |
{ |
298 |
ns = xrealloc (ns, len + 2); |
size_t nslen = strlen (ns); |
299 |
ns[len++] = found->val; |
|
300 |
ns[len] = '\0'; |
assert (found->val); |
301 |
TRACE (TRACE_FUNCTION, "Adding long UserAdminOptions `%s'", |
|
302 |
found->name); |
ns = xrealloc (ns, nslen + 2); |
303 |
} |
ns[nslen++] = found->val; |
304 |
else if (first) |
ns[nslen] = '\0'; |
305 |
{ |
TRACE (TRACE_FUNCTION, "Adding long UserAdminOptions `%s'", |
306 |
size_t nslen = strlen (ns); |
found->name); |
307 |
ns = xrealloc (ns, nslen + len + 1); |
} |
308 |
strncat (ns, p, len); |
else |
309 |
ns[nslen + len] = '\0'; |
{ |
310 |
TRACE (TRACE_FUNCTION, "Appending `%s' to UserAdminOptions", |
char *tmp = xmalloc (len + 1); |
311 |
ns + nslen); |
strncpy (tmp, cur_opt, len); |
312 |
} |
tmp[len] = '\0'; |
313 |
else |
error (0, 0, |
314 |
{ |
"%s [%u]: Unrecognized long admin option `%s'.", |
315 |
char *tmp = xmalloc (len + 1); |
infopath, ln, tmp); |
316 |
strncpy (tmp, p, len); |
free (tmp); |
317 |
ns[len] = '\0'; |
} |
|
error (0, 0, |
|
|
"%s [%u]: Unrecognized long admin option `%s'.", |
|
|
infopath, ln, tmp); |
|
|
free (tmp); |
|
318 |
} |
} |
319 |
|
} |
320 |
|
|
|
p = q; |
|
|
} while (p); |
|
|
|
|
321 |
return ns; |
return ns; |
322 |
} |
} |
323 |
|
|
336 |
int i; |
int i; |
337 |
bool only_allowed_options; |
bool only_allowed_options; |
338 |
|
|
|
static const char short_options[] = |
|
|
"+ib::c:a:A:e::l::u::LUn:N:m:o:s:t::IqxV:k:"; |
|
|
|
|
339 |
if (argc <= 1) |
if (argc <= 1) |
340 |
usage (admin_usage); |
usage (admin_usage); |
341 |
|
|
362 |
|
|
363 |
switch (c) |
switch (c) |
364 |
{ |
{ |
365 |
case 1: /* --no-execute */ |
case OPT_EXECUTE: /* --execute */ |
366 |
admin_data.execute = NOEXECUTE; |
admin_data.execute = EXECUTE; |
367 |
break; |
break; |
368 |
|
|
369 |
case 2: /* --execute */ |
case OPT_NOEXECUTE: /* --no-execute */ |
370 |
admin_data.execute = EXECUTE; |
admin_data.execute = NOEXECUTE; |
371 |
break; |
break; |
372 |
|
|
373 |
case 'i': |
case 'i': |
592 |
if (grps[i] == grp->gr_gid) break; |
if (grps[i] == grp->gr_gid) break; |
593 |
free (grps); |
free (grps); |
594 |
if (i > n) |
if (i > n) |
595 |
error (1, 0, "usage is restricted to members of the group %s", |
error (1, 0, "usage is restricted to members of the group `%s'", |
596 |
CVS_ADMIN_GROUP); |
CVS_ADMIN_GROUP); |
597 |
#else |
#else |
598 |
char *me = getcaller (); |
char *me = getcaller (); |