#include <stdio.h>
#include <stdlib.h>
#include <dce/rpc.h>
#include <dce/csrc.h>
#include <unistd.h>
#include <fcntl.h>
#include <commonp.h>
#include <dce/dce_cf.h>
#include <langinfo.h>
static boolean rpc_g_codesets_did_read;
static dcethread_mutex rpc_g_codesets_mutex;
static dcethread_oncectl rpc_g_codesets_once_block = DCETHREAD_ONCE_INIT;
static entry_t *rpc_g_codesets_list;
static entry_t *rpc_g_codesets_effective_ids;
static entry_t **rpc_g_codesets_sort_by_priority;
static entry_t **rpc_g_codesets_sort_by_name;
static entry_t **rpc_g_codesets_sort_by_id;
static int rpc_g_codesets_entry_count;
static int rpc_g_codesets_effective_count;
static error_status_t rpc_g_codesets_status;
PRIVATE
void name_sort
(
entry_t **codesets,
int entry_count
)
{
int i, j, k;
entry_t *temp;
if (entry_count <= 1)
return;
for (i = 1; i < entry_count; i++)
{
temp = codesets[i];
j = i - 1;
while (j >= 0)
{
if ((k = strcoll(codesets[j]->code_set_name, (const char *)temp->code_set_name)) > 0)
{
codesets[j + 1] = codesets[j];
codesets[j] = temp;
}
j--;
}
}
}
PRIVATE
void priority_sort
(
entry_t **codesets,
int entry_count
)
{
int i, j, k;
entry_t *temp;
if (entry_count <= 1)
return;
for (i = 1; i < entry_count; i++)
{
temp = codesets[i];
j = i - 1;
while (j >= 0)
{
if (codesets[j]->priority > temp->priority)
{
codesets[j + 1] = codesets[j];
codesets[j] = temp;
}
j--;
}
}
}
PRIVATE
void c_binary_search
(
entry_t **codesets,
int low,
int high,
long key_value,
entry_t **code_entry
)
{
int middle;
long code1, code2;
if (key_value < 0)
code1 = key_value * -1;
else
code1 = key_value;
if (low <= high)
{
middle = (low + high) / 2;
if (codesets[middle]->code_set < 0)
code2 = codesets[middle]->code_set * -1;
else
code2 = codesets[middle]->code_set;
if (code1 == code2)
{
*code_entry = codesets[middle];
return;
}
else
{
if (code1 < code2)
c_binary_search(codesets, low, middle-1, key_value, code_entry);
else
c_binary_search(codesets, middle+1, high, key_value, code_entry);
}
}
}
PRIVATE
void n_binary_search
(
entry_t **codesets,
int low,
int high,
char *key_name,
entry_t **code_entry
)
{
int middle, k;
if (low <= high)
{
middle = (low + high) / 2;
if ((k = strcoll(key_name, codesets[middle]->code_set_name)) == 0)
{
*code_entry = codesets[middle];
return;
}
else
{
if (k < 0)
n_binary_search(codesets, low, middle-1, key_name, code_entry);
else
n_binary_search(codesets, middle+1, high, key_name, code_entry);
}
}
}
PRIVATE
rpc__codesets_really_read_file
(
void
)
{
int i, j, k;
entry_t *ep;
entry_t *effective_ep;
int CsrFile;
char *code_set_registry_file;
dce_cf_get_csrgy_filename(&code_set_registry_file, &rpc_g_codesets_status);
if (rpc_g_codesets_status != dce_cf_st_ok)
{
return;
}
CsrFile = open(code_set_registry_file, O_RDONLY, 0);
free (code_set_registry_file);
if (CsrFile == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_open_file;
return;
}
if ((read (CsrFile, (char *)(&rpc_g_codesets_entry_count), sizeof(rpc_g_codesets_entry_count))) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
if ((read (CsrFile, (char *)(&rpc_g_codesets_effective_count), sizeof(rpc_g_codesets_entry_count))) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
if ((rpc_g_codesets_list = (entry_t *)malloc(sizeof(entry_t) * rpc_g_codesets_entry_count)) == NULL)
{
rpc_g_codesets_status = dce_cs_c_cannot_allocate_memory;
return;
}
if ((rpc_g_codesets_effective_ids = (entry_t *)malloc(sizeof(entry_t) * rpc_g_codesets_effective_count)) == NULL)
{
rpc_g_codesets_status = dce_cs_c_cannot_allocate_memory;
return;
}
ep = rpc_g_codesets_list;
i = rpc_g_codesets_entry_count;
effective_ep = rpc_g_codesets_effective_ids;
while (i--)
{
if ((read (CsrFile, (char *)(&ep->code_set), sizeof(ep->code_set))) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
if ((read (CsrFile, (char *)(&ep->code_name_len), sizeof(ep->code_name_len))) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
if ((ep->code_set_name = (char *)malloc(ep->code_name_len + 1)) == NULL)
{
rpc_g_codesets_status = dce_cs_c_cannot_allocate_memory;
return;
}
if ((read (CsrFile, (char *)ep->code_set_name, ep->code_name_len + 1)) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
if ((read (CsrFile, (char *)(&ep->char_sets_num), sizeof(ep->char_sets_num))) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
for (j = 0; j < ep->char_sets_num; j++)
{
if ((read (CsrFile, (char *)(&ep->char_sets[j]), sizeof(ep->char_sets[j]))) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
}
if ((read (CsrFile, (char *)(&ep->max_bytes), sizeof(ep->max_bytes))) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
if ((read (CsrFile, (char *)(&ep->priority), sizeof(ep->priority))) == -1)
{
rpc_g_codesets_status = dce_cs_c_cannot_read_file;
return;
}
if ((k = strcoll(ep->code_set_name, "NONE")) != 0)
{
effective_ep->code_set = ep->code_set;
effective_ep->code_name_len = ep->code_name_len;
effective_ep->code_set_name = ep->code_set_name;
effective_ep->char_sets_num = ep->char_sets_num;
for (j = 0; j < ep->char_sets_num; j++)
effective_ep->char_sets[j] = ep->char_sets[j];
effective_ep->max_bytes = ep->max_bytes;
effective_ep->priority = ep->priority;
effective_ep++;
}
ep++;
}
close (CsrFile);
rpc_g_codesets_status = rpc_s_ok;
rpc_g_codesets_did_read = TRUE;
}
PRIVATE
rpc__codesets_read_registry_file
(
error_status_t *status
)
{
entry_t **sort_name_codesets;
entry_t **sort_name_save;
entry_t **sort_id_codesets;
entry_t **sort_id_save;
entry_t **sort_priority_codesets;
entry_t **sort_priority_save;
int i;
entry_t *ep;
if (!rpc_g_codesets_did_read)
{
dcethread_once_throw(&rpc_g_codesets_once_block,
(dcethread_initroutine)rpc__codesets_really_read_file);
if (rpc_g_codesets_status != rpc_s_ok)
{
*status = rpc_g_codesets_status;
return;
}
}
if ((sort_name_save = (entry_t **)malloc(sizeof(entry_t *) * rpc_g_codesets_entry_count)) == NULL)
{
*status = dce_cs_c_cannot_allocate_memory;
return;
}
ep = rpc_g_codesets_list;
i = rpc_g_codesets_entry_count;
sort_name_codesets = sort_name_save;
while (i--)
{
*sort_name_codesets++ = ep++;
}
rpc_g_codesets_sort_by_name = sort_name_save;
sort_name_codesets = sort_name_save;
name_sort(sort_name_codesets, rpc_g_codesets_entry_count);
if ((sort_priority_save = (entry_t **)malloc(sizeof(entry_t *) * rpc_g_codesets_effective_count)) == NULL)
{
*status = dce_cs_c_cannot_allocate_memory;
return;
}
ep = rpc_g_codesets_effective_ids;
i = rpc_g_codesets_effective_count;
sort_priority_codesets = sort_priority_save;
while (i--)
{
*sort_priority_codesets++ = ep++;
}
rpc_g_codesets_sort_by_priority = sort_priority_save;
sort_priority_codesets = sort_priority_save;
priority_sort(sort_priority_codesets, rpc_g_codesets_effective_count);
if ((sort_id_save = (entry_t **)malloc(sizeof(entry_t *) * rpc_g_codesets_entry_count)) == NULL)
{
*status = dce_cs_c_cannot_allocate_memory;
return;
}
ep = rpc_g_codesets_list;
i = rpc_g_codesets_entry_count;
sort_id_codesets = sort_id_save;
while (i--)
{
*sort_id_codesets++ = ep++;
}
rpc_g_codesets_sort_by_id = sort_id_save;
*status = rpc_s_ok;
}
PUBLIC
void dce_cs_loc_to_rgy
(
idl_char *local_code_set_name,
unsigned32 *rgy_code_set_value,
unsigned16 *rgy_char_sets_number,
unsigned16 **rgy_char_sets_value,
error_status_t *status
)
{
entry_t **epp;
entry_t *found = NULL;
int i;
unsigned16 *char_array;
CODING_ERROR (status);
rpc__codesets_read_registry_file(status);
if (*status != rpc_s_ok)
{
return;
}
epp = rpc_g_codesets_sort_by_name;
n_binary_search(epp, 0, rpc_g_codesets_entry_count-1, (char *)local_code_set_name, &found);
if (found == NULL)
{
*status = dce_cs_c_unknown;
return;
}
if (rgy_char_sets_number != NULL)
{
*rgy_char_sets_number = found->char_sets_num;
}
if (rgy_char_sets_value != NULL)
{
if ((char_array = (unsigned16 *)malloc(sizeof(unsigned16) * found->char_sets_num)) == NULL)
{
*status = dce_cs_c_cannot_allocate_memory;
return;
}
*rgy_char_sets_value = char_array;
for (i = 0; i < found->char_sets_num; i++)
{
*char_array++ = found->char_sets[i];
}
}
*rgy_code_set_value = (unsigned32)found->code_set;
*status = dce_cs_c_ok;
return;
}
PUBLIC
void dce_cs_rgy_to_loc
(
unsigned32 rgy_code_set_value,
idl_char **local_code_set_name,
unsigned16 *rgy_char_sets_number,
unsigned16 **rgy_char_sets_value,
error_status_t *status
)
{
entry_t **epp;
entry_t *found = NULL;
int i;
unsigned16 *char_array;
CODING_ERROR (status);
rpc__codesets_read_registry_file(status);
if (*status != rpc_s_ok)
{
return;
}
epp = rpc_g_codesets_sort_by_id;
i = rpc_g_codesets_entry_count;
c_binary_search(epp, 0, rpc_g_codesets_entry_count-1, rgy_code_set_value, &found);
if (found == NULL)
{
*status = dce_cs_c_unknown;
return;
}
if ((i = strcoll(found->code_set_name, "NONE")) == 0)
{
*status = dce_cs_c_notfound;
return;
}
if (rgy_char_sets_number != NULL)
{
*rgy_char_sets_number = found->char_sets_num;
}
if (rgy_char_sets_value != NULL)
{
if ((char_array = (unsigned16 *)malloc(sizeof(unsigned16) * found->char_sets_num)) == NULL)
{
*status = dce_cs_c_cannot_allocate_memory;
return;
}
*rgy_char_sets_value = char_array;
for (i = 0; i < found->char_sets_num; i++)
{
*char_array++ = found->char_sets[i];
}
}
*local_code_set_name = (idl_char *)found->code_set_name;
*status = dce_cs_c_ok;
return;
}
PUBLIC
void rpc_rgy_get_max_bytes
(
unsigned32 tag,
unsigned16 *max_bytes,
error_status_t *status
)
{
entry_t **epp;
entry_t *found = NULL;
int i;
unsigned16 *char_array;
CODING_ERROR (status);
rpc__codesets_read_registry_file(status);
if (*status != rpc_s_ok)
{
return;
}
epp = rpc_g_codesets_sort_by_id;
i = rpc_g_codesets_entry_count;
c_binary_search(epp, 0, rpc_g_codesets_entry_count-1, tag, &found);
if (found == NULL)
{
*status = dce_cs_c_unknown;
return;
}
if ((i = strcoll(found->code_set_name, "NONE")) == 0)
{
*status = dce_cs_c_notfound;
return;
}
*max_bytes = found->max_bytes;
*status = rpc_s_ok;
return;
}
PUBLIC
void rpc_rgy_get_codesets
(
rpc_codeset_mgmt_p_t *codesets_p,
error_status_t *status
)
{
int i;
entry_t **epp;
char *current_codeset;
unsigned32 current_rgy_codeset;
CODING_ERROR (status);
rpc__codesets_read_registry_file(status);
if (*status != rpc_s_ok)
{
return;
}
epp = rpc_g_codesets_sort_by_priority;
RPC_MEM_ALLOC (
*codesets_p,
rpc_codeset_mgmt_p_t,
sizeof(rpc_codeset_mgmt_t) +
(sizeof(rpc_cs_c_set_t) * (rpc_g_codesets_effective_count - 1)),
RPC_C_MEM_CDS_ATTR,
RPC_C_MEM_WAITOK);
(*codesets_p)->count = rpc_g_codesets_effective_count;
current_codeset = nl_langinfo(CODESET);
dce_cs_loc_to_rgy(
(unsigned_char_p_t)current_codeset,
¤t_rgy_codeset,
NULL, NULL,
status);
if (*status != dce_cs_c_ok)
{
*status = rpc_s_ok;
return;
}
(*codesets_p)->codesets[0].c_set = current_rgy_codeset;
for (i = 1; i < rpc_g_codesets_effective_count; i++)
{
if ((*epp)->code_set != (*codesets_p)->codesets[0].c_set)
{
(*codesets_p)->codesets[i].c_set = (*epp)->code_set;
(*codesets_p)->codesets[i].c_max_bytes = (*epp)->max_bytes;
}
else
{
(*codesets_p)->codesets[0].c_max_bytes = (*epp)->max_bytes;
i--;
}
epp++;
}
*status = rpc_s_ok;
}