Here is an example of an internationalized RPC server that exports the cs_test interface defined in Writing the Interface Definition File.
#include <stdio.h>
#include <stdlib.h>
#include <dce/rpc.h>
#include <dce/nsattrid.h>
#include <dce/dce_error.h>
#include <locale.h>
#include <pthread.h>
#include <dce/codesets.h>
#include "cs_test.h"
/*
* Macro for result checking
*/
#define CHECK_STATUS(t, func, returned_st, expected_st) \
{ \
if (returned_st == expected_st) { \
} \
else { \
dce_error_inq_text(returned_st, \
(unsigned char *)unexpected, &dce_status); \
dce_error_inq_text(expected_st,\
(unsigned char *)expected, &dce_status); \
printf("FAILED %s()\nresult: %s\nexpected: %s\n\n", \
func, unexpected, expected); \
} \
} \
static unsigned char unexpected[dce_c_error_string_len];
static unsigned char expected[dce_c_error_string_len];
static int dce_status;
int
main(int argc, char *argv[])
{
error_status_t status;
int i;
rpc_ns_handle_t inq_contxt;
rpc_binding_vector_t *binding_vector;
rpc_codeset_mgmt_p_t arr;
pthread_t this_thread = pthread_self();
sigset_t sigset;
char *nsi_entry_name;
char *server_locale_name;
error_status_t expected = rpc_s_ok;
int server_pid;
/* The environment variable I18N_SERVER_ENTRY needs
* to be set before running this program. This is
* not a DCE environment variable, so you can set up
* your own environment variable if you like.
*/
nsi_entry_name = getenv("I18N_SERVER_ENTRY");
(void)pthread_mutex_init(&mutex, pthread_mutexattr_default);
/* Set the locale. In this way, the current locale
* information is extracted from XPG/POSIX defined
* environment variable LANG or LC_ALL.
*/
setlocale(LC_ALL, "");
/*
* Get supported code sets.
*/
rpc_rgy_get_codesets (
&arr,
&status );
CHECK_STATUS(TRUE, "rpc_rgy_get_codesets", status, expected);
rpc_server_register_if (
cs_test_v1_0_s_ifspec,
NULL,
NULL,
&status );
CHECK_STATUS(TRUE, "rpc_server_register_if", status, expected);
rpc_server_use_all_protseqs (
rpc_c_protseq_max_reqs_default,
&status );
CHECK_STATUS(TRUE, "rpc_server_use_all_protseqs", status, expected);
rpc_server_inq_bindings (
&binding_vector,
&status );
CHECK_STATUS(TRUE, "rpc_server_inq_bindings", status, expected);
rpc_ns_binding_export (
rpc_c_ns_syntax_default,
(unsigned_char_p_t)nsi_entry_name,
cs_test_v1_0_s_ifspec,
binding_vector,
NULL,
&status );
CHECK_STATUS(TRUE, "rpc_ns_binding_export", status, expected);
rpc_ep_register (
cs_test_v1_0_s_ifspec,
binding_vector,
NULL,
NULL,
&status );
CHECK_STATUS(TRUE, "rpc_ep_register", status, expected);
/*
* Register the server's supported code sets into the name space.
*/
rpc_ns_mgmt_set_attribute (
rpc_c_ns_syntax_default,
(unsigned_char_p_t)nsi_entry_name,
rpc_c_attr_codesets,
(void *)arr,
&status );
CHECK_STATUS(TRUE, "rpc_ns_mgmt_set_attribute", status, expected);
/*
* Free memory allocated by getting code sets.
*/
rpc_ns_mgmt_free_codesets (&arr, &status);
CHECK_STATUS(TRUE, "rpc_ns_mgmt_free_codeset", status, expected);
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
if (pthread_signal_to_cancel_np(&sigset, &this_thread) != 0)
{
printf("pthread_signal_to_cancel_np failed\n");
exit(1);
}
TRY
{
server_pid = getpid();
printf("Listening for remote procedure calls...\n");
rpc_server_listen (
rpc_c_listen_max_calls_default,
&status );
CHECK_STATUS(TRUE, "rpc_server_listen", status, expected);
/*
* Remove code set attributes from namespace on return.
*/
rpc_ns_mgmt_remove_attribute (
rpc_c_ns_syntax_default,
(unsigned_char_p_t)nsi_entry_name,
rpc_c_attr_codesets,
&status );
CHECK_STATUS(TRUE, "rpc_ns_mgmt_remove_attribute", status, expected);
rpc_ns_binding_unexport (
rpc_c_ns_syntax_default,
(unsigned_char_p_t)nsi_entry_name,
cs_test_v1_0_s_ifspec,
(uuid_vector_p_t)NULL,
&status );
CHECK_STATUS(TRUE, "rpc_ns_binding_unexport", status, expected);
rpc_ep_unregister (
cs_test_v1_0_s_ifspec,
binding_vector,
NULL,
&status );
CHECK_STATUS(TRUE, "rpc_ep_unregister", status, expected);
rpc_binding_vector_free (
&binding_vector,
&status );
CHECK_STATUS(TRUE, "rpc_binding_vector_free", status, expected);
rpc_server_unregister_if (
cs_test_v1_0_s_ifspec,
NULL,
&status );
CHECK_STATUS(TRUE, "rpc_server_unregister_if", status, expected);
(void)pthread_mutex_destroy(&mutex);
}
CATCH_ALL
{
/*
* Remove code set attribute from namespace on a signal.
*/
rpc_ns_mgmt_remove_attribute (
rpc_c_ns_syntax_default,
(unsigned_char_p_t)nsi_entry_name,
rpc_c_attr_codesets,
&status );
CHECK_STATUS(TRUE, "rpc_ns_mgmt_remove_attribute", status, expected);
rpc_ns_binding_unexport (
rpc_c_ns_syntax_default,
(unsigned_char_p_t)nsi_entry_name,
cs_test_v1_0_s_ifspec,
(uuid_vector_p_t)NULL,
&status );
CHECK_STATUS(TRUE, "rpc_ns_binding_unexport", status, expected);
rpc_ep_unregister (
cs_test_v1_0_s_ifspec,
binding_vector,
NULL,
&status );
CHECK_STATUS(TRUE, "rpc_ep_unregister", status, expected);
rpc_binding_vector_free (
&binding_vector,
&status );
CHECK_STATUS(TRUE, "rpc_binding_vector_free", status, expected);
rpc_server_unregister_if (
cs_test_v1_0_s_ifspec,
NULL,
&status );
CHECK_STATUS(TRUE, "rpc_server_unregister_if", status, expected);
(void)pthread_mutex_destroy(&mutex);
}
ENDTRY;
}