summaryrefslogtreecommitdiffstats
path: root/src/kim/lib
diff options
context:
space:
mode:
authorAlexandra Ellwood <lxs@mit.edu>2008-09-28 19:43:47 +0000
committerAlexandra Ellwood <lxs@mit.edu>2008-09-28 19:43:47 +0000
commitb5dce4285a9330d25542528030ce93da78e36375 (patch)
treec8cbd6a729cddb99bda84991e1c7c231449434f2 /src/kim/lib
parent01a5986cbf7afdba2b805bdd16893b6b52c87f42 (diff)
downloadkrb5-b5dce4285a9330d25542528030ce93da78e36375.tar.gz
krb5-b5dce4285a9330d25542528030ce93da78e36375.tar.xz
krb5-b5dce4285a9330d25542528030ce93da78e36375.zip
Create common stream and ipc layer for CCAPI and KIM.
Will switch CCAPI to this new code later though, so as not to destabilize KfM and the Windows builds. ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20769 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/kim/lib')
-rw-r--r--src/kim/lib/mac/kim_os_ui_gui.c543
1 files changed, 234 insertions, 309 deletions
diff --git a/src/kim/lib/mac/kim_os_ui_gui.c b/src/kim/lib/mac/kim_os_ui_gui.c
index 4f629105d..7559dbed9 100644
--- a/src/kim/lib/mac/kim_os_ui_gui.c
+++ b/src/kim/lib/mac/kim_os_ui_gui.c
@@ -27,107 +27,74 @@
#ifndef LEAN_CLIENT
#include "kim_os_private.h"
-#include "kim_mig_types.h"
-#include "kim_mig.h"
-#define kKerberosAgentBundleID "edu.mit.Kerberos.KerberosAgent"
-#define kKerberosAgentPath "/System/Library/CoreServices/KerberosAgent.app/Contents/MacOS/KerberosAgent"
+#include "k5_mig_client.h"
#include <Kerberos/kipc_client.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
+#include <unistd.h>
-struct kim_ui_gui_context {
- mach_port_t port;
-};
/* ------------------------------------------------------------------------ */
-static void kim_os_ui_gui_context_free (kim_ui_gui_context *io_context)
-{
- if (io_context && *io_context) {
- free (*io_context);
- *io_context = NULL;
- }
-}
-
-/* ------------------------------------------------------------------------ */
-
-static kim_error kim_os_ui_gui_context_allocate (kim_ui_gui_context *out_context)
+kim_error kim_os_ui_gui_init (kim_ui_context *io_context)
{
kim_error err = KIM_NO_ERROR;
- kim_ui_gui_context context = NULL;
-
- if (!err && !out_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ kim_string name = NULL;
+ kim_string path = NULL;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
if (!err) {
- context = malloc (sizeof (*context));
- if (!context) { err = KIM_OUT_OF_MEMORY_ERR; }
+ err = kim_library_get_application_name (&name);
}
if (!err) {
- context->port = MACH_PORT_NULL;
-
- *out_context = context;
- context = NULL;
+ err = kim_os_library_get_application_path (&path);
}
- kim_os_ui_gui_context_free (&context);
-
- return check_error (err);
-}
-
-#pragma mark -
-
-/* ------------------------------------------------------------------------ */
-
-kim_error kim_os_ui_gui_init (kim_ui_context *io_context)
-{
- kim_error err = KIM_NO_ERROR;
- kim_ui_gui_context context = NULL;
- kim_string name = NULL;
- kim_string path = NULL;
+ if (!err) {
+ err = k5_ipc_stream_new (&request);
+ }
- if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err) {
+ err = k5_ipc_stream_write_string (request, "init");
+ }
if (!err) {
- err = kim_os_ui_gui_context_allocate (&context);
+ err = k5_ipc_stream_write_int32 (request, getpid());
}
if (!err) {
- err = kim_library_get_application_name (&name);
+ err = k5_ipc_stream_write_string (request, name);
}
if (!err) {
- err = kim_os_library_get_application_path (&path);
+ err = k5_ipc_stream_write_string (request, path);
}
-
+
if (!err) {
- err = kipc_client_lookup_server (kim_os_agent_bundle_id,
- 1 /* launch */,
- 0 /* don't use cached port */,
- &context->port);
+ err = k5_ipc_send_request (1 /* launch server */,
+ request,
+ &reply);
}
if (!err) {
- kim_mipc_error result = 0;
-
- err = kim_mipc_cli_init (context->port,
- mach_task_self (),
- name, kim_string_buflen (name),
- path, kim_string_buflen (path),
- &result);
+ int32_t result = 0;
+
+ err = k5_ipc_stream_read_int32 (reply, &result);
if (!err) { err = check_error (result); }
}
if (!err) {
- io_context->tcontext = context;
- context = NULL;
+ io_context->tcontext = NULL;
}
+ k5_ipc_stream_release (request);
+ k5_ipc_stream_release (reply);
kim_string_free (&name);
kim_string_free (&path);
- kim_os_ui_gui_context_free (&context);
return check_error (err);
}
@@ -138,29 +105,46 @@ kim_error kim_os_ui_gui_enter_identity (kim_ui_context *in_context,
kim_identity *out_identity)
{
kim_error err = KIM_NO_ERROR;
- kim_mipc_out_string identity = NULL;
- mach_msg_type_number_t identity_len = 0;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ char *identity_string = NULL;
- if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err) {
- kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext;
- kim_mipc_error result = 0;
+ err = k5_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_write_string (request, "enter_identity");
+ }
- err = kim_mipc_cli_enter_identity (context->port,
- &identity,
- &identity_len,
- &result);
+
+ if (!err) {
+ err = k5_ipc_send_request (0 /* don't launch server */,
+ request,
+ &reply);
+ if (!reply) { err = check_error (KIM_NO_SERVER_ERR); }
+ }
+
+ if (!err) {
+ int32_t result = 0;
+
+ err = k5_ipc_stream_read_int32 (reply, &result);
if (!err) { err = check_error (result); }
}
if (!err) {
- err = kim_identity_create_from_string (out_identity, identity);
+ err = k5_ipc_stream_read_string (reply, &identity_string);
+ }
+
+ if (!err) {
+ err = kim_identity_create_from_string (out_identity, identity_string);
}
- if (identity) { vm_deallocate (mach_task_self (),
- (vm_address_t) identity, identity_len); }
+ k5_ipc_stream_free_string (identity_string);
+ k5_ipc_stream_release (request);
+ k5_ipc_stream_release (reply);
return check_error (err);
}
@@ -172,232 +156,136 @@ kim_error kim_os_ui_gui_select_identity (kim_ui_context *in_context,
kim_identity *out_identity)
{
kim_error err = KIM_NO_ERROR;
- kim_options options = NULL;
- kim_time start_time = 0;
- kim_lifetime lifetime;
- kim_boolean renewable;
- kim_lifetime renewal_lifetime;
- kim_boolean forwardable;
- kim_boolean proxiable;
- kim_boolean addressless;
- kim_string service_name = NULL;
- kim_string application_id = NULL;
- kim_string explanation = NULL;
- kim_string service_identity_hint = NULL;
- kim_string client_realm_hint = NULL;
- kim_string user_hint = NULL;
- kim_string service_realm_hint = NULL;
- kim_string service_hint = NULL;
- kim_string server_hint = NULL;
- kim_mipc_out_string identity = NULL;
- mach_msg_type_number_t identity_len = 0;
-
- if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ char *identity_string = NULL;
+
if (!err && !in_hints ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err) {
- err = kim_selection_hints_get_options (in_hints, &options);
-
- if (!err && !options) {
- err = kim_options_create (&options);
- }
+ err = k5_ipc_stream_new (&request);
}
if (!err) {
- err = kim_options_get_start_time (options, &start_time);
+ err = k5_ipc_stream_write_string (request, "select_identity");
}
if (!err) {
- err = kim_options_get_lifetime (options, &lifetime);
+ //err = kim_os_selection_hints_write (in_hints, request);
}
if (!err) {
- err = kim_options_get_renewable (options, &renewable);
+ err = k5_ipc_send_request (0 /* don't launch server */,
+ request,
+ &reply);
+ if (!reply) { err = check_error (KIM_NO_SERVER_ERR); }
}
if (!err) {
- err = kim_options_get_renewal_lifetime (options, &renewal_lifetime);
- }
-
- if (!err) {
- err = kim_options_get_forwardable (options, &forwardable);
+ int32_t result = 0;
+
+ err = k5_ipc_stream_read_int32 (reply, &result);
+ if (!err) { err = check_error (result); }
}
if (!err) {
- err = kim_options_get_proxiable (options, &proxiable);
+ err = k5_ipc_stream_read_string (reply, &identity_string);
}
if (!err) {
- err = kim_options_get_addressless (options, &addressless);
+ err = kim_identity_create_from_string (out_identity, identity_string);
}
- if (!err) {
- err = kim_options_get_service_name (options, &service_name);
- }
+ k5_ipc_stream_free_string (identity_string);
+ k5_ipc_stream_release (request);
+ k5_ipc_stream_release (reply);
- if (!err) {
- err = kim_selection_hints_get_explanation (in_hints, &explanation);
- }
+ return check_error (err);
+}
+/* ------------------------------------------------------------------------ */
+
+kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context,
+ kim_identity in_identity,
+ kim_prompt_type in_type,
+ kim_boolean in_hide_reply,
+ kim_string in_title,
+ kim_string in_message,
+ kim_string in_description,
+ char **out_reply)
+{
+ kim_error err = KIM_NO_ERROR;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+ kim_string identity_string = NULL;
+
+ if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ /* in_title, in_message or in_description may be NULL */
+
if (!err) {
- err = kim_selection_hints_get_application_id (in_hints, &application_id);
+ err = kim_identity_get_string (in_identity, &identity_string);
}
if (!err) {
- err = kim_selection_hints_get_hint (in_hints,
- kim_hint_key_service_identity,
- &service_identity_hint);
+ err = k5_ipc_stream_new (&request);
}
if (!err) {
- err = kim_selection_hints_get_hint (in_hints,
- kim_hint_key_client_realm,
- &client_realm_hint);
+ err = k5_ipc_stream_write_string (request, "auth_prompt");
}
if (!err) {
- err = kim_selection_hints_get_hint (in_hints,
- kim_hint_key_user,
- &user_hint);
+ err = k5_ipc_stream_write_string (request, identity_string);
}
if (!err) {
- err = kim_selection_hints_get_hint (in_hints,
- kim_hint_key_service_realm,
- &service_realm_hint);
+ err = k5_ipc_stream_write_int32 (request, in_type);
}
if (!err) {
- err = kim_selection_hints_get_hint (in_hints,
- kim_hint_key_service,
- &service_hint);
+ err = k5_ipc_stream_write_int32 (request, in_hide_reply);
}
if (!err) {
- err = kim_selection_hints_get_hint (in_hints,
- kim_hint_key_server,
- &server_hint);
+ err = k5_ipc_stream_write_string (request,
+ in_title ? in_title : "");
}
if (!err) {
- kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext;
- kim_mipc_error result = 0;
-
- err = kim_mipc_cli_select_identity (context->port,
- application_id,
- kim_string_buflen (application_id),
- explanation,
- kim_string_buflen (explanation),
-
- start_time,
- lifetime,
- renewable,
- renewal_lifetime,
- forwardable,
- proxiable,
- addressless,
- service_name,
- kim_string_buflen (service_name),
-
- service_identity_hint,
- kim_string_buflen (service_identity_hint),
-
- client_realm_hint,
- kim_string_buflen (client_realm_hint),
-
- user_hint,
- kim_string_buflen (user_hint),
-
- service_realm_hint,
- kim_string_buflen (service_realm_hint),
-
- service_hint,
- kim_string_buflen (service_hint),
-
- server_hint,
- kim_string_buflen (server_hint),
-
- &identity,
- &identity_len,
- &result);
- if (!err) { err = check_error (result); }
+ err = k5_ipc_stream_write_string (request,
+ in_message ? in_message : "");
}
if (!err) {
- err = kim_identity_create_from_string (out_identity, identity);
+ err = k5_ipc_stream_write_string (request,
+ in_description ? in_description : "");
}
- if (identity) { vm_deallocate (mach_task_self (),
- (vm_address_t) identity, identity_len); }
-
- kim_string_free (&application_id);
- kim_string_free (&explanation);
- kim_string_free (&service_name);
- kim_string_free (&service_identity_hint);
- kim_string_free (&client_realm_hint);
- kim_string_free (&user_hint);
- kim_string_free (&service_realm_hint);
- kim_string_free (&service_hint);
- kim_string_free (&server_hint);
- kim_options_free (&options);
-
- return check_error (err);
-}
-
-/* ------------------------------------------------------------------------ */
-
-kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context,
- kim_identity in_identity,
- kim_prompt_type in_type,
- kim_boolean in_hide_reply,
- kim_string in_title,
- kim_string in_message,
- kim_string in_description,
- char **out_reply)
-{
- kim_error err = KIM_NO_ERROR;
- kim_string identity_string = NULL;
- kim_mipc_out_string reply = NULL;
- mach_msg_type_number_t reply_len = 0;
-
- if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- /* in_title, in_message or in_description may be NULL */
-
if (!err) {
- err = kim_identity_get_string (in_identity, &identity_string);
+ err = k5_ipc_send_request (0 /* don't launch server */,
+ request,
+ &reply);
+ if (!reply) { err = check_error (KIM_NO_SERVER_ERR); }
}
if (!err) {
- kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext;
- kim_mipc_error result = 0;
-
- err = kim_mipc_cli_auth_prompt (context->port,
- identity_string,
- kim_string_buflen (identity_string),
- in_type,
- in_hide_reply,
- in_title,
- kim_string_buflen (in_title),
- in_message,
- kim_string_buflen (in_message),
- in_description,
- kim_string_buflen (in_description),
- &reply,
- &reply_len,
- &result);
+ int32_t result = 0;
+
+ err = k5_ipc_stream_read_int32 (reply, &result);
if (!err) { err = check_error (result); }
}
if (!err) {
- err = kim_string_copy ((kim_string *) out_reply, reply);
- }
+ err = k5_ipc_stream_read_string (reply, out_reply);
+ }
- if (reply) { vm_deallocate (mach_task_self (), (vm_address_t) reply, reply_len); }
kim_string_free (&identity_string);
-
+
+ k5_ipc_stream_release (request);
+ k5_ipc_stream_release (reply);
+
return check_error (err);
}
@@ -408,85 +296,85 @@ kim_error kim_os_ui_gui_change_password (kim_ui_context *in_context,
kim_boolean in_old_password_expired,
char **out_old_password,
char **out_new_password,
- char **out_verify_password)
+ char **out_vfy_password)
{
kim_error err = KIM_NO_ERROR;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
kim_string identity_string = NULL;
- kim_mipc_out_string old_password_buf = NULL;
- mach_msg_type_number_t old_password_len = 0;
- kim_mipc_out_string new_password_buf = NULL;
- mach_msg_type_number_t new_password_len = 0;
- kim_mipc_out_string verify_password_buf = NULL;
- mach_msg_type_number_t verify_password_len = 0;
-
- kim_string old_password = NULL;
- kim_string new_password = NULL;
- kim_string verify_password = NULL;
+ char *old_password = NULL;
+ char *new_password = NULL;
+ char *vfy_password = NULL;
- if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !out_old_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !out_new_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !out_verify_password) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !out_old_password) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !out_new_password) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !out_vfy_password) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err) {
err = kim_identity_get_string (in_identity, &identity_string);
}
if (!err) {
- kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext;
- kim_mipc_error result = 0;
-
- err = kim_mipc_cli_change_password (context->port,
- identity_string,
- kim_string_buflen (identity_string),
- in_old_password_expired,
- &old_password_buf,
- &old_password_len,
- &new_password_buf,
- &new_password_len,
- &verify_password_buf,
- &verify_password_len,
- &result);
- if (!err) { err = check_error (result); }
+ err = k5_ipc_stream_new (&request);
}
if (!err) {
- err = kim_string_copy (&old_password, old_password_buf);
+ err = k5_ipc_stream_write_string (request, "change_password");
}
if (!err) {
- err = kim_string_copy (&new_password, new_password_buf);
+ err = k5_ipc_stream_write_string (request, identity_string);
}
if (!err) {
- err = kim_string_copy (&verify_password, verify_password_buf);
+ err = k5_ipc_stream_write_int32 (request, in_old_password_expired);
}
if (!err) {
+ err = k5_ipc_send_request (0 /* don't launch server */,
+ request,
+ &reply);
+ if (!reply) { err = check_error (KIM_NO_SERVER_ERR); }
+ }
+
+ if (!err) {
+ int32_t result = 0;
+
+ err = k5_ipc_stream_read_int32 (reply, &result);
+ if (!err) { err = check_error (result); }
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_read_string (reply, &old_password);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_read_string (reply, &new_password);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_read_string (reply, &vfy_password);
+ }
+
+ if (!err) {
*out_old_password = (char *) old_password;
old_password = NULL;
*out_new_password = (char *) new_password;
new_password = NULL;
- *out_verify_password = (char *) verify_password;
- verify_password = NULL;
- }
-
- if (old_password_buf) { vm_deallocate (mach_task_self (),
- (vm_address_t) old_password_buf,
- old_password_len); }
- if (new_password_buf) { vm_deallocate (mach_task_self (),
- (vm_address_t) new_password_buf,
- new_password_len); }
- if (verify_password_buf) { vm_deallocate (mach_task_self (),
- (vm_address_t) verify_password_buf,
- verify_password_len); }
+ *out_vfy_password = (char *) vfy_password;
+ vfy_password = NULL;
+ }
+
kim_string_free (&identity_string);
- kim_string_free (&old_password);
- kim_string_free (&new_password);
- kim_string_free (&verify_password);
+ k5_ipc_stream_free_string (old_password);
+ k5_ipc_stream_free_string (new_password);
+ k5_ipc_stream_free_string (vfy_password);
+ k5_ipc_stream_release (request);
+ k5_ipc_stream_release (reply);
+
return check_error (err);
}
@@ -499,9 +387,10 @@ kim_error kim_os_ui_gui_handle_error (kim_ui_context *in_context,
kim_string in_error_description)
{
kim_error err = KIM_NO_ERROR;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
kim_string identity_string = NULL;
- if (!err && !in_context ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err && !in_error_message ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); }
@@ -510,23 +399,48 @@ kim_error kim_os_ui_gui_handle_error (kim_ui_context *in_context,
}
if (!err) {
- kim_ui_gui_context context = (kim_ui_gui_context) in_context->tcontext;
- kim_mipc_error result = 0;
+ err = k5_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_write_string (request, "handle_error");
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_write_string (request, identity_string);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_write_int32 (request, in_error);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_write_string (request, in_error_message);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_write_string (request, in_error_description);
+ }
+
+ if (!err) {
+ err = k5_ipc_send_request (0 /* don't launch server */,
+ request,
+ &reply);
+ if (!reply) { err = check_error (KIM_NO_SERVER_ERR); }
+ }
+
+ if (!err) {
+ int32_t result = 0;
- err = kim_mipc_cli_handle_error (context->port,
- identity_string,
- kim_string_buflen (identity_string),
- in_error,
- in_error_message,
- kim_string_buflen (in_error_message),
- in_error_description,
- kim_string_buflen (in_error_description),
- &result);
- if (!err) { err = check_error (result); }
+ err = k5_ipc_stream_read_int32 (reply, &result);
+ if (!err) { err = check_error (result); }
}
kim_string_free (&identity_string);
+ k5_ipc_stream_release (request);
+ k5_ipc_stream_release (reply);
+
return check_error (err);
}
@@ -543,23 +457,34 @@ void kim_os_ui_gui_free_string (kim_ui_context *in_context,
kim_error kim_os_ui_gui_fini (kim_ui_context *io_context)
{
kim_error err = KIM_NO_ERROR;
+ k5_ipc_stream request = NULL;
+ k5_ipc_stream reply = NULL;
+
+ if (!err) {
+ err = k5_ipc_stream_new (&request);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_write_string (request, "fini");
+ }
- if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err) {
+ err = k5_ipc_send_request (0 /* don't launch server */,
+ request,
+ &reply);
+ if (!reply) { err = check_error (KIM_NO_SERVER_ERR); }
+ }
if (!err) {
- kim_ui_gui_context context = (kim_ui_gui_context) io_context->tcontext;
- kim_mipc_error result = 0;
+ int32_t result = 0;
- err = kim_mipc_cli_fini (context->port, &result);
+ err = k5_ipc_stream_read_int32 (reply, &result);
if (!err) { err = check_error (result); }
-
-
- if (!err) {
- kim_os_ui_gui_context_free (&context);
- io_context->tcontext = NULL;
- }
}
+ k5_ipc_stream_release (request);
+ k5_ipc_stream_release (reply);
+
return check_error (err);
}