/* Editor Settings: expandtabs and use 4 spaces for indentation
* ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
* -*- mode: c, c-basic-offset: 4 -*- */
/*
* Copyright Likewise Software
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. You should have received a copy of the GNU General
* Public License along with this program. If not, see
* .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
#include
#include
#include
#include
#include
#include
#include
#include "params.h"
#if !defined(HAVE_STRNDUP)
char* strndup(const char *s, size_t maxlen)
{
char *ret;
size_t len, size;
len = strlen(s);
len = (len > maxlen) ? maxlen : len;
size = (len + 1) * sizeof(char);
ret = (char*) malloc(size);
strncpy(ret, s, len);
/* ensure null termination */
ret[len] = '\0';
return ret;
}
#endif
static char* cleanup_sep(char *s, char sep)
{
char *seppos;
char sepstr[3] = {0};
int i = 0;
if (s == NULL) return s;
sepstr[0] = '\\';
sepstr[1] = sep;
seppos = strstr(s, sepstr);
while (seppos) {
while (*seppos) seppos[0] = (seppos++)[1];
seppos = strstr(s, sepstr);
}
return s;
}
char** get_string_list(char *list, const char sep)
{
char **ret;
char *start, *end = NULL;
int i, count = 1;
/* count the elements */
start = list;
end = strchr(list, sep);
while (end++) {
end = strchr(end, sep);
/* skip any "escaped" separator */
if (end > start && *(end-1) == '\\') continue;
count++;
}
ret = (char**) malloc(sizeof(char*) * (count + 1));
if (!ret) return NULL;
memset((void*)ret, 0, sizeof(char*) * (count + 1));
/* copy elements to the array */
start = list;
for (i = 0; i < count; i++) {
end = strchr(start, sep);
/* skip any "escaped" separator */
while (start && end > start && *(end-1) == '\\') {
char *pos = (char*)(end+1);
end = strchr(pos,sep);
}
if (end) {
ret[i] = strndup(start, (size_t)(end - start));
start = &end[1];
} else if (strlen(start)) {
ret[i] = strdup(start);
}
ret[i] = cleanup_sep(ret[i], sep);
}
return ret;
}
struct parameter* get_optional_params(char *opt, int *count)
{
const char separator = ',';
const char equal = '=';
struct parameter *params;
char **opts;
int i;
if (!opt) {
if (count) *count = 0;
return NULL;
}
if (!count) return NULL;
*count = 0;
i = 0;
opts = get_string_list(opt, separator);
while (opts[(*count)]) (*count)++;
params = (struct parameter*) malloc(sizeof(struct parameter) * (*count));
while (opts[i]) {
size_t key_size, val_size;
char *param = opts[i];
char *value = strchr(param, equal);
if (param) {
key_size = (size_t)(value - param);
params[i].key = strndup(param, key_size);
if (value) {
val_size = strlen(param) - key_size - 1; /* equal char doesn't count */
params[i].val = strndup((char*)(value + sizeof(char)), val_size);
} else {
/* if param is specified but does not equal to anything we can
assume it's a boolean flag set */
params[i].val = strdup("1");
}
i++;
}
}
return params;
}
const char* find_value(struct parameter *params, int count, const char *key)
{
int i;
for (i = 0; i < count; i++) {
if (strstr(params[i].key, key)) return params[i].val;
}
return NULL;
}
enum param_err fetch_value(struct parameter *params, int count,
const char *key, enum param_type type,
void *val, const void *def)
{
const char *value;
NTSTATUS status;
char **valstr, **defstr;
char *valchar, *defchar;
wchar16_t **valw16str, **defw16str;
int *valint, *defint;
unsigned int *valuint, *defuint;
PSID* valsid;
enum param_err ret = perr_success;
if (params && !key) return perr_nullptr_passed;
if (!val) return perr_invalid_out_param;
value = find_value(params, count, key);
if (!value && !def) return perr_not_found;
switch (type) {
case pt_string:
valstr = (char**)val;
defstr = (char**)def;
*valstr = (value) ? strdup(value) : strdup(*defstr);
break;
case pt_w16string:
valw16str = (wchar16_t**)val;
defstr = (char**)def;
*valw16str = (value) ? ambstowc16s(value) : ambstowc16s(*defstr);
break;
case pt_char:
valchar = (char*)val;
defchar = (char*)def;
*valchar = (value) ? value[0] : *defchar;
break;
case pt_int32:
valint = (int*)val;
defint = (int*)def;
*valint = (value) ? atoi(value) : *defint;
break;
case pt_uint32:
valuint = (unsigned int*)val;
defuint = (unsigned int*)def;
*valuint = (unsigned int)((value) ? atol(value) : *defuint);
break;
#if 0
case pt_sid:
valsid = (DomSid**)val;
/* default SID is passed as string here for convenience */
defstr = (char**)def;
status = ParseSidString(valsid,
((value) ? (const char*)value : *defstr));
if (status != STATUS_SUCCESS) return perr_invalid_out_param;
break;
#endif
default:
return perr_unknown_type;
break;
}
return ret;
}
const char *param_errstr(enum param_err perr)
{
const errcount = sizeof(param_errstr_maps)/sizeof(struct param_errstr_map);
int i = 0;
while (i < errcount && perr != param_errstr_maps[i].perr) i++;
return param_errstr_maps[i].desc;
}
/*
local variables:
mode: c
c-basic-offset: 4
indent-tabs-mode: nil
tab-width: 4
end:
*/