#include "RxI.h"
#define RX_DEFAULT_VERSION 1
#define RX_DEFAULT_REVISION 0
typedef struct {
char *string;
int length;
int index;
} Token;
#define TOKEN(s, i) { s, sizeof(s) - 1, i }
#define NULLTOKEN { NULL, 0, 0 }
static Token RxServices[] = {
TOKEN(RX_UI, UI),
TOKEN(RX_PRINT, Print),
NULLTOKEN
};
static Token RxUIs[] = {
TOKEN("X", XUI),
NULLTOKEN
};
static Token RxPrints[] = {
TOKEN("XPrint", XPrint),
NULLTOKEN
};
static Token RxXAuthentications[] = {
TOKEN("MIT-MAGIC-COOKIE-1", MitMagicCookie1),
NULLTOKEN
};
#ifdef NEED_STRCASECMP
int
_RxStrcasecmp(register const char *s1, register const char *s2)
{
register int c1, c2;
while (*s1 && *s2) {
c1 = tolower(*s1);
c2 = tolower(*s2);
if (c1 != c2)
return (c1 - c2);
s1++;
s2++;
}
return (int) (*s1 - *s2);
}
int
_RxStrncasecmp(register const char *s1, register const char *s2, size_t n)
{
register int c1, c2;
const char *l1 = s1 + n;
const char *l2 = s2 + n;
while (*s1 && *s2 && s1 < l1 && s2 < l2) {
c1 = tolower(*s1);
c2 = tolower(*s2);
if (c1 != c2)
return (c1 - c2);
s1++;
s2++;
}
if (s1 < l1 && s2 < l2)
return (int) (*s1 - *s2);
else if (s1 < l1)
return (int) *s1;
else if (s2 < l2)
return (int) *s2;
return 0;
}
#endif
static char *
strcopy(char *src)
{
char *cpy = (char *)Malloc(strlen(src) + 1);
if (cpy)
strcpy(cpy, src);
return cpy;
}
static char *
strncopy(char *src, int n)
{
char *cpy = (char *)Malloc(n + 1);
if (cpy) {
strncpy(cpy, src, n);
cpy[n] = '\0';
}
return cpy;
}
#define WARNING(m, p) if (debug != 0) Warning(m, p)
static void
Warning(char *message, char *param)
{
fprintf(stderr, "Warning: %s%s\n", message, param);
}
#define WARNINGN(m, p, n) if (debug != 0) WarningN(m, p, n)
static void
WarningN(char *message, char *param, int param_len)
{
fprintf(stderr, "Warning: %s", message);
fwrite((void *)param, sizeof(char), param_len, stderr);
putc('\n', stderr);
}
static void
Error(char *message, char *param)
{
fprintf(stderr, "Error: %s%s\n", message, param);
}
static int
LookForToken(char *string, Token *token)
{
for (; token->string != NULL; token++)
if (Strncasecmp(string, token->string, token->length) == 0)
return token->index;
return 0;
}
static int
ParseList(char *value, Token *tokens, int *indices, int debug)
{
char *next;
int token;
int n = 0;
do {
token = LookForToken(value, tokens);
next = strchr(value, ',');
if (token == 0) {
if (next != NULL) {
char buf[BUFSIZ];
int len = (next - value < BUFSIZ) ? next - value : BUFSIZ;
strncpy(buf, value, len);
buf[len] = '\0';
WARNING("unknown parameter value: ", buf);
} else
WARNING("unknown parameter value: ", value);
} else
indices[n++] = token;
if (next != NULL)
value = next + 1;
} while (next);
indices[n] = 0;
return n;
}
static int
ParseAuthList(char *value, Token *tokens, int *indices, char **values,
int debug)
{
char *next, *ptr;
int token;
int n = 0;
do {
token = LookForToken(value, tokens);
ptr = strchr(value, ':');
next = strchr(((ptr != NULL) ? ptr : value), ',');
if (token == 0) {
if (next != NULL) {
char buf[BUFSIZ];
int len = (next - value < BUFSIZ) ? next - value : BUFSIZ;
strncpy(buf, value, len);
buf[len] = '\0';
WARNING("unknown parameter value: ", buf);
} else
WARNING("unknown parameter value: ", value);
} else {
indices[n] = token;
if (ptr != NULL) {
if (next != NULL)
values[n++] = strncopy(ptr + 1, next - ptr);
else
values[n++] = strcopy(ptr + 1);
} else
values[n++] = NULL;
}
if (next != NULL)
value = next + 1;
} while (next);
indices[n] = 0;
return n;
}
static int
ParseBoolean(char *strvalue, RxBool *value_ret)
{
if (Strcasecmp(strvalue, RX_YES) == 0) {
*value_ret = RxTrue;
return 0;
} else if (Strcasecmp(strvalue, RX_NO) == 0) {
*value_ret = RxFalse;
return 0;
}
return 1;
}
static int
ParseXInputMethod(char *value,
RxBool *input_method_ret, char **input_method_url_ret,
int debug)
{
char *url;
url = strchr(value, ';');
if (url != NULL) {
if (strncmp(value, RX_YES, sizeof(RX_YES) - 1) == 0) {
*input_method_ret = RxTrue;
*input_method_url_ret = strcopy(url + 1);
} else if (strncmp(value, RX_YES, sizeof(RX_YES) - 1) == 0)
*input_method_ret = RxFalse;
else
WARNINGN("not a boolean value: ", value, url - value);
} else {
if (ParseBoolean(value, input_method_ret) != 0)
WARNING("not a boolean value: ", value);
}
return 0;
}
static int
ParseParam(char *name, char *value, RxParams *params, int debug)
{
if (Strcasecmp(name, RX_ACTION) == 0) {
Free(params->action);
params->action = strcopy(value);
} else if (Strcasecmp(name, RX_EMBEDDED) == 0) {
if (ParseBoolean(value, ¶ms->embedded) != 0)
WARNING("not a boolean value: ", value);
} else if (Strcasecmp(name, RX_AUTO_START) == 0) {
if (ParseBoolean(value, ¶ms->auto_start) != 0)
WARNING("not a boolean value: ", value);
} else if (Strcasecmp(name, RX_WIDTH) == 0)
params->width = atoi(value);
else if (Strcasecmp(name, RX_HEIGHT) == 0)
params->height = atoi(value);
else if (Strcasecmp(name, RX_APP_GROUP) == 0) {
Free(params->app_group);
params->app_group = strcopy(value);
} else if (Strcasecmp(name, RX_REQUIRED_SERVICES) == 0)
ParseList(value, RxServices, (int*)params->required_services, debug);
else if (Strcasecmp(name, RX_UI) == 0)
ParseList(value, RxUIs, (int*)params->ui, debug);
else if (Strcasecmp(name, RX_PRINT) == 0)
ParseList(value, RxPrints, (int*)params->print, debug);
else if (Strcasecmp(name, RX_X_UI_INPUT_METHOD) == 0)
ParseXInputMethod(value, ¶ms->x_ui_input_method,
¶ms->x_ui_input_method_url, debug);
else if (Strcasecmp(name, RX_X_AUTH) == 0)
ParseAuthList(value, RxXAuthentications,
(int*)params->x_auth, params->x_auth_data, debug);
else if (Strcasecmp(name, RX_X_UI_AUTH) == 0)
ParseAuthList(value, RxXAuthentications,
(int*)params->x_ui_auth, params->x_ui_auth_data, debug);
else if (Strcasecmp(name, RX_X_PRINT_AUTH) == 0)
ParseAuthList(value, RxXAuthentications,
(int*)params->x_print_auth, params->x_print_auth_data,
debug);
else if (Strcasecmp(name, RX_X_UI_LBX_AUTH) == 0)
ParseAuthList(value, RxXAuthentications,
(int*)params->x_ui_lbx_auth,
params->x_ui_lbx_auth_data, debug);
else if (Strcasecmp(name, RX_X_PRINT_LBX_AUTH) == 0)
ParseAuthList(value, RxXAuthentications,
(int*)params->x_print_lbx_auth,
params->x_print_lbx_auth_data,
debug);
else if (Strcasecmp(name, RX_X_UI_LBX) == 0) {
if (ParseBoolean(value, ¶ms->x_ui_lbx) != 0)
WARNING("not a boolean value: ", value);
} else if (Strcasecmp(name, RX_X_PRINT_LBX) == 0) {
if (ParseBoolean(value, ¶ms->x_print_lbx) != 0)
WARNING("not a boolean value: ", value);
} else
WARNING("unknown parameter name: ", name);
return 0;
}
int
RxParseParams(char *argn[], char *argv[], int argc, RxParams *params,
int debug)
{
int i;
int version, revision;
if (argc == 0)
return 0;
if (Strcasecmp(argn[0], RX_VERSION) == 0) {
if (sscanf(argv[0], "%d.%d", &version, &revision) == 2) {
params->version = version;
params->revision = revision;
} else {
Error("invalid version identifier: ", argv[0]);
return 1;
}
argn++;
argv++;
i = 1;
} else {
params->version = RX_DEFAULT_VERSION;
params->revision = RX_DEFAULT_REVISION;
i = 0;
}
for (; i < argc; i++, argn++, argv++)
if (ParseParam(*argn, *argv, params, debug))
return 1;
return 0;
}
void
RxInitializeParams(RxParams *params)
{
memset(params, 0, sizeof(RxParams));
params->embedded = RxUndef;
params->auto_start = RxUndef;
params->width = RxUndef;
params->height = RxUndef;
params->x_ui_input_method = RxUndef;
params->x_ui_input_method_url = NULL;
params->x_ui_lbx = RxUndef;
params->x_print_lbx = RxUndef;
}
void
FreeAuthListData(char **list)
{
while (*list != NULL)
Free(*list++);
}
int
RxFreeParams(RxParams *params)
{
Free(params->action);
Free(params->app_group);
Free(params->x_ui_input_method_url);
FreeAuthListData(params->x_auth_data);
FreeAuthListData(params->x_ui_auth_data);
FreeAuthListData(params->x_print_auth_data);
FreeAuthListData(params->x_ui_lbx_auth_data);
FreeAuthListData(params->x_print_lbx_auth_data);
return 0;
}
int
RxFreeReturnParams(RxReturnParams *params)
{
Free(params->ui);
Free(params->print);
Free(params->x_ui_lbx_auth);
Free(params->x_print_lbx_auth);
return 0;
}