Create common stream and ipc layer for CCAPI and KIM.
authorAlexandra Ellwood <lxs@mit.edu>
Sun, 28 Sep 2008 19:43:47 +0000 (19:43 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Sun, 28 Sep 2008 19:43:47 +0000 (19:43 +0000)
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

19 files changed:
src/include/k5-ipc_stream.h [new file with mode: 0644]
src/include/k5-thread.h
src/include/kim/kim_ui_plugin.h
src/kim/agent/mac/ServerDemux.h [new file with mode: 0644]
src/kim/agent/mac/ServerDemux.m
src/kim/agent/mac/ServerThread.h [deleted file]
src/kim/agent/mac/ServerThread.m [deleted file]
src/kim/agent/mac/main.m
src/kim/lib/mac/kim_os_ui_gui.c
src/kim/mac/kim_mig.defs [deleted file]
src/util/mac/k5_mig.defs [new file with mode: 0644]
src/util/mac/k5_mig_client.c [new file with mode: 0644]
src/util/mac/k5_mig_client.h [moved from src/kim/mac/kim_mig_types.h with 73% similarity]
src/util/mac/k5_mig_reply.defs [new file with mode: 0644]
src/util/mac/k5_mig_request.defs [new file with mode: 0644]
src/util/mac/k5_mig_server.c [new file with mode: 0644]
src/util/mac/k5_mig_server.h [new file with mode: 0644]
src/util/mac/k5_mig_types.h [new file with mode: 0644]
src/util/support/ipc_stream.c [new file with mode: 0644]

diff --git a/src/include/k5-ipc_stream.h b/src/include/k5-ipc_stream.h
new file mode 100644 (file)
index 0000000..55397ef
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef K5_IPC_STREAM_H
+#define K5_IPC_STREAM_H
+
+#include "k5-platform.h"
+
+struct k5_ipc_stream;
+typedef struct k5_ipc_stream *k5_ipc_stream;
+
+
+int32_t k5_ipc_stream_new (k5_ipc_stream *out_stream);
+
+uint32_t k5_ipc_stream_release (k5_ipc_stream io_stream);
+
+uint64_t k5_ipc_stream_size (k5_ipc_stream in_stream);
+
+const char *k5_ipc_stream_data (k5_ipc_stream in_stream);
+
+uint32_t k5_ipc_stream_read (k5_ipc_stream  in_stream, 
+                             void          *io_data,
+                             uint64_t       in_size);
+uint32_t k5_ipc_stream_write (k5_ipc_stream  in_stream, 
+                              const void    *in_data,
+                              uint64_t       in_size);
+
+uint32_t k5_ipc_stream_read_string (k5_ipc_stream   io_stream, 
+                                    char          **out_string);
+uint32_t k5_ipc_stream_write_string (k5_ipc_stream  io_stream, 
+                                     const char    *in_string);
+void k5_ipc_stream_free_string (char *in_string);
+
+uint32_t k5_ipc_stream_read_int32 (k5_ipc_stream  io_stream, 
+                                   int32_t       *out_int32);
+uint32_t k5_ipc_stream_write_int32 (k5_ipc_stream io_stream, 
+                                    int32_t       in_int32);
+
+uint32_t k5_ipc_stream_read_uint32 (k5_ipc_stream  io_stream, 
+                                    uint32_t      *out_uint32);
+uint32_t k5_ipc_stream_write_uint32 (k5_ipc_stream io_stream, 
+                                     uint32_t      in_uint32);
+
+uint32_t k5_ipc_stream_read_int64 (k5_ipc_stream  io_stream, 
+                                   int64_t       *out_int64);
+uint32_t k5_ipc_stream_write_int64 (k5_ipc_stream io_stream, 
+                                    int64_t       in_int64);
+
+uint32_t k5_ipc_stream_read_uint64 (k5_ipc_stream  io_stream, 
+                                    uint64_t      *out_uint64);
+uint32_t k5_ipc_stream_write_uint64 (k5_ipc_stream io_stream, 
+                                     uint64_t      in_uint64);
+
+uint32_t k5_ipc_stream_read_time (k5_ipc_stream  io_stream, 
+                                  time_t        *out_time);
+uint32_t k5_ipc_stream_write_time (k5_ipc_stream io_stream, 
+                                   time_t        in_time);
+
+#endif /* K5_IPC_STREAM_H */
index c2d4f4bf283f1b24a161fba2717c3cb4bea27115..57aa78f4b9e072e31352807903124be9e23a2b04 100644 (file)
@@ -414,6 +414,9 @@ typedef enum {
     K5_KEY_CCAPI_REQUEST_PORT,
     K5_KEY_CCAPI_REPLY_STREAM,
     K5_KEY_CCAPI_SERVER_DIED,
+    K5_KEY_IPC_REQUEST_PORT,
+    K5_KEY_IPC_REPLY_STREAM,
+    K5_KEY_IPC_SERVER_DIED,
     K5_KEY_COM_ERR_REENTER,
 #endif
     K5_KEY_MAX
index b7d48ad89a09dc46c3074a30e3c6bb15200b6d59..0f6895ffc606abd4d5f8f5fe1b19d14a1cd30989 100644 (file)
@@ -40,7 +40,7 @@ enum kim_prompt_type_enum {
     kim_prompt_type_password = 0,
     kim_prompt_type_preauth = 1
 };
-    
+
 /*
  * Plugins for Controlling Identity Selection and Credential Acquisition
  * 
diff --git a/src/kim/agent/mac/ServerDemux.h b/src/kim/agent/mac/ServerDemux.h
new file mode 100644 (file)
index 0000000..12afa36
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#import "k5_mig_requestServer.h"
+#import "k5_mig_reply.h"
+#import "k5-ipc_stream.h"
+#import "k5_mig_server.h"
+
+
+int32_t kim_agent_listen_loop (void);
+
+int32_t kim_handle_reply_init (mach_port_t   in_reply_port, 
+                               int32_t       in_error);
+
+int32_t kim_handle_reply_enter_identity (mach_port_t   in_reply_port, 
+                                         kim_identity  in_identity,
+                                         int32_t       in_error);
+
+int32_t kim_handle_reply_select_identity (mach_port_t   in_reply_port, 
+                                          kim_identity  in_identity,
+                                          int32_t       in_error);
+
+int32_t kim_handle_reply_auth_prompt (mach_port_t   in_reply_port, 
+                                      kim_string    in_prompt_response,
+                                      int32_t       in_error);
+
+int32_t kim_handle_reply_change_password (mach_port_t   in_reply_port, 
+                                          kim_string    in_old_password,
+                                          kim_string    in_new_password,
+                                          kim_string    in_vfy_password,
+                                          int32_t       in_error);
+
+int32_t kim_handle_reply_handle_error (mach_port_t   in_reply_port, 
+                                       int32_t       in_error);
+
+int32_t kim_handle_reply_fini (mach_port_t   in_reply_port, 
+                               int32_t       in_error);
index b7f20841775ce18e011a9937332059b2d842fc24..7c2e4f0842f5f320e01b6cda110c9590f4f3bdea 100644 (file)
  * or implied warranty.
  */
 
-#import "kim_migServer.h"
-#import "ServerThread.h"
+#import "ServerDemux.h"
 
 // ---------------------------------------------------------------------------
 
-static kim_boolean caller_is_front_process (task_t    in_task
+static kim_boolean caller_is_front_process (pid_t    in_pid
                                             NSString *in_path)
 {
     kim_error err = KIM_NO_ERROR;
-    Boolean is_front_process;
-    pid_t task_pid;
-    ProcessSerialNumber task_psn, front_psn;
+    kim_boolean is_front_process = FALSE;
+    NSNumber *active_pid = NULL;
     
     NSBundle *bundle = [NSBundle bundleWithPath: in_path];
     if (bundle) {
@@ -46,573 +44,553 @@ static kim_boolean caller_is_front_process (task_t    in_task,
     }
     
     if (!err) {
-        err = pid_for_task (in_task, &task_pid);
+        NSDictionary *activeApplication = [[NSWorkspace sharedWorkspace] activeApplication];
+        if (activeApplication) {
+            active_pid = [activeApplication objectForKey: @"NSApplicationProcessIdentifier"];
+        }
+    }
+    
+    if (!err && active_pid) {
+        is_front_process = ([active_pid intValue] == in_pid);
     }
     
+    return is_front_process;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static int32_t kim_handle_request_init (mach_port_t   in_client_port, 
+                                        mach_port_t   in_reply_port, 
+                                        k5_ipc_stream in_request_stream)
+{
+    int32_t err = 0;
+    int32_t pid = 0;
+    char *name = NULL;
+    char *path = NULL;
+    bool isFrontProcess = 0;
+
     if (!err) {
-        err = GetProcessForPID (task_pid, &task_psn);
+        err = k5_ipc_stream_read_int32 (in_request_stream, &pid);
     }
     
     if (!err) {
-        err = GetFrontProcess (&front_psn);
+        err = k5_ipc_stream_read_string (in_request_stream, &name);
+    }    
+    
+    if (!err) {
+        err = k5_ipc_stream_read_string (in_request_stream, &path);
+    } 
+    
+    
+    if (!err) {
+        isFrontProcess = caller_is_front_process (pid, 
+                                                  [NSString stringWithUTF8String: path]);
     }
     
     if (!err) {
-        err = SameProcess (&task_psn, &front_psn, &is_front_process);
+#warning Send init message to main thread with 2 ports, name and path
     }
     
-    return !err ? is_front_process : FALSE;
-}
+    k5_ipc_stream_free_string (name);    
+    k5_ipc_stream_free_string (path);
 
-#pragma mark -
+    return err;   
+}
 
 /* ------------------------------------------------------------------------ */
 
-kern_return_t kim_mipc_srv_init (mach_port_t             in_server_port,
-                                 task_t                  in_application_task,
-                                 kim_mipc_in_string      in_application_name,
-                                 mach_msg_type_number_t  in_application_nameCnt,
-                                 kim_mipc_in_string      in_application_path,
-                                 mach_msg_type_number_t  in_application_pathCnt,
-                                 kim_mipc_error         *out_error)
+int32_t kim_handle_reply_init (mach_port_t   in_reply_port, 
+                               int32_t       in_error)
 {
-    kern_return_t err = 0;
-    ServerThread *sthread = NULL;
+    int32_t err = 0;
+    k5_ipc_stream reply = NULL;
     
     if (!err) {
-        sthread = [ServerThread sharedServerThread];
-        if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; }
+        err = k5_ipc_stream_new (&reply);
     }
     
     if (!err) {
-        kim_mipc_error result = KIM_NO_ERROR;
-        NSString *name = NULL;
-        NSString *path = NULL;
+        err = k5_ipc_stream_write_int32 (reply, in_error);
+    }
+    
+    if (!err) {
+        err = k5_ipc_server_send_reply (in_reply_port, reply);
+    }
+    
+    k5_ipc_stream_release (reply);
+    
+    return err;   
+}
 
-        if (in_application_name) {
-            name = [NSString stringWithUTF8String: in_application_name];
-        }
+#pragma mark -
 
-        if (in_application_path) {
-            path = [NSString stringWithUTF8String: in_application_path];
-        }
-        
-        [sthread addConnectionWithPort: in_server_port
-                                  name: name
-                                  path: path
-                          frontProcess: caller_is_front_process (in_application_task, 
-                                                                 path)];
-        *out_error = result;
+/* ------------------------------------------------------------------------ */
+
+static int32_t kim_handle_request_enter_identity (mach_port_t   in_client_port, 
+                                                  mach_port_t   in_reply_port, 
+                                                  k5_ipc_stream in_request_stream)
+{
+    int32_t err = 0;
+    
+    if (!err) {
+#warning Send enter identity message to main thread with 2 ports
     }
     
-    return err;
+    return err;   
 }
 
 /* ------------------------------------------------------------------------ */
 
-kern_return_t kim_mipc_srv_enter_identity (mach_port_t             in_server_port,
-                                           kim_mipc_out_string    *out_identity,
-                                           mach_msg_type_number_t *out_identityCnt,
-                                           kim_mipc_error         *out_error)
+int32_t kim_handle_reply_enter_identity (mach_port_t   in_reply_port, 
+                                         kim_identity  in_identity,
+                                         int32_t       in_error)
 {
-    kern_return_t err = 0;
-    kim_error result = KIM_NO_ERROR;
-    ClientConnection *client = NULL;
-    kim_identity identity = NULL;
+    int32_t err = 0;
+    k5_ipc_stream reply = NULL;
     kim_string identity_string = NULL;
-    mach_msg_type_number_t identity_len = 0;
-    kim_mipc_out_string identity_buf = NULL;
     
     if (!err) {
-        ServerThread *sthread = [ServerThread sharedServerThread];
-        if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; }
-
-        if (!err) {
-            client = [sthread connectionForPort: in_server_port];
-            if (!client) { err = KIM_OUT_OF_MEMORY_ERR; }
-        }
+        err = kim_identity_get_string (in_identity, &identity_string);
     }
     
     if (!err) {
-        identity = [client enterIdentityWithError: &result];
+        err = k5_ipc_stream_new (&reply);
     }
     
-    if (!err && !result) {
-        err = kim_identity_get_string (identity, &identity_string);
-    }
-    
-    if (!err && !result && identity_string) {
-        identity_len = strlen (identity_string) + 1;
-        err = vm_allocate (mach_task_self (), 
-                           (vm_address_t *) &identity_buf, identity_len, TRUE);
-        
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (reply, in_error);
     }
     
-    if (!err && !result) {
-        memmove (identity_buf, identity_string, identity_len);
-        *out_identity = identity_buf;
-        *out_identityCnt = identity_len;
-        identity_buf = NULL;
+    if (!err && !in_error) {
+        err = k5_ipc_stream_write_string (reply, identity_string);
     }
     
     if (!err) {
-        *out_error = result;
+        err = k5_ipc_server_send_reply (in_reply_port, reply);
     }
     
-    if (identity_buf) { vm_deallocate (mach_task_self (), (vm_address_t) identity_buf, identity_len); }
     kim_string_free (&identity_string);
-    kim_identity_free (&identity);
+    k5_ipc_stream_release (reply);
     
-    return err;
+    return err;   
 }
 
+#pragma mark -
+
 /* ------------------------------------------------------------------------ */
 
-kern_return_t kim_mipc_srv_select_identity (mach_port_t             in_server_port,
-                                            kim_mipc_in_string      in_application_id,
-                                            mach_msg_type_number_t  in_application_idCnt,
-                                            kim_mipc_in_string      in_explanation,
-                                            mach_msg_type_number_t  in_explanationCnt,
-                                            kim_mipc_time           in_start_time,
-                                            kim_mipc_lifetime       in_lifetime,
-                                            kim_mipc_boolean        in_renewable,
-                                            kim_mipc_lifetime       in_renewal_lifetime,
-                                            kim_mipc_boolean        in_forwardable,
-                                            kim_mipc_boolean        in_proxiable,
-                                            kim_mipc_boolean        in_addressless,
-                                            kim_mipc_in_string      in_service_name,
-                                            mach_msg_type_number_t  in_service_nameCnt,
-                                            kim_mipc_in_string      in_service_identity_hint,
-                                            mach_msg_type_number_t  in_service_identity_hintCnt,
-                                            kim_mipc_in_string      in_client_realm_hint,
-                                            mach_msg_type_number_t  in_client_realm_hintCnt,
-                                            kim_mipc_in_string      in_user_hint,
-                                            mach_msg_type_number_t  in_user_hintCnt,
-                                            kim_mipc_in_string      in_service_realm_hint,
-                                            mach_msg_type_number_t  in_service_realm_hintCnt,
-                                            kim_mipc_in_string      in_service_hint,
-                                            mach_msg_type_number_t  in_service_hintCnt,
-                                            kim_mipc_in_string      in_server_hint,
-                                            mach_msg_type_number_t  in_server_hintCnt,
-                                            kim_mipc_out_string    *out_identity,
-                                            mach_msg_type_number_t *out_identityCnt,
-                                            kim_mipc_error         *out_error)
+static int32_t kim_handle_request_select_identity (mach_port_t   in_client_port, 
+                                                   mach_port_t   in_reply_port, 
+                                                   k5_ipc_stream in_request_stream)
 {
-    kern_return_t err = 0;
-    kim_error result = KIM_NO_ERROR;
-    ClientConnection *client = NULL;
+    int32_t err = 0;
     kim_selection_hints hints = NULL;
-    kim_identity identity = NULL;
-    kim_string identity_string = NULL;
-    mach_msg_type_number_t identity_len = 0;
-    kim_mipc_out_string identity_buf = NULL;
     
     if (!err) {
-        err = kim_selection_hints_create (&hints, in_application_id);
-    }
+        //err = kim_os_selection_hints_read (out_hints, in_request_stream);
+    }    
     
     if (!err) {
-        kim_options options = NULL;
-        
-        err = kim_options_create (&options);
-        
-        if (!err) {
-            err = kim_options_set_start_time (options, in_start_time);
-        }
-        
-        if (!err) {
-            err = kim_options_set_lifetime (options, in_lifetime);
-        }
-        
-        if (!err) {
-            err = kim_options_set_renewable (options, in_renewable);
-        }
-        
-        if (!err) {
-            err = kim_options_set_renewal_lifetime (options, in_renewal_lifetime);
-        }
-        
-        if (!err) {
-            err = kim_options_set_forwardable (options, in_forwardable);
-        }
-        
-        if (!err) {
-            err = kim_options_set_proxiable (options, in_proxiable);
-        }
-        
-        if (!err) {
-            err = kim_options_set_addressless (options, in_addressless);
-        }
-        
-        if (!err) {
-            err = kim_options_set_service_name (options, in_service_name);
-        }
-        
-        if (!err) {
-            err = kim_selection_hints_set_options (hints, options);
-        }
-        
-        kim_options_free (&options);
+#warning Send select identity message to main thread with 2 ports
     }
     
+    kim_selection_hints_free (&hints);
+    
+    return err;   
+}
+
+/* ------------------------------------------------------------------------ */
+
+int32_t kim_handle_reply_select_identity (mach_port_t   in_reply_port, 
+                                          kim_identity  in_identity,
+                                          int32_t       in_error)
+{
+    int32_t err = 0;
+    k5_ipc_stream reply = NULL;
+    kim_string identity_string = NULL;
+    
     if (!err) {
-        err = kim_selection_hints_set_explanation (hints, in_explanation);
+        err = kim_identity_get_string (in_identity, &identity_string);
     }
     
-    if (!err && in_service_identity_hint) {
-        err = kim_selection_hints_set_hint (hints, 
-                                            kim_hint_key_service_identity,
-                                            in_service_identity_hint);
+    if (!err) {
+        err = k5_ipc_stream_new (&reply);
     }
     
-    if (!err && in_client_realm_hint) {
-        err = kim_selection_hints_set_hint (hints, 
-                                            kim_hint_key_client_realm,
-                                            in_client_realm_hint);
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (reply, in_error);
     }
     
-    if (!err && in_user_hint) {
-        err = kim_selection_hints_set_hint (hints, 
-                                            kim_hint_key_user,
-                                            in_user_hint);
+    if (!err && !in_error) {
+        err = k5_ipc_stream_write_string (reply, identity_string);
     }
     
-    if (!err && in_service_realm_hint) {
-        err = kim_selection_hints_set_hint (hints, 
-                                            kim_hint_key_service_realm,
-                                            in_service_realm_hint);
+    if (!err) {
+        err = k5_ipc_server_send_reply (in_reply_port, reply);
     }
     
-    if (!err && in_service_hint) {
-        err = kim_selection_hints_set_hint (hints, 
-                                            kim_hint_key_service,
-                                            in_service_hint);
-    }
+    kim_string_free (&identity_string);
+    k5_ipc_stream_release (reply);
     
-    if (!err && in_server_hint) {
-        err = kim_selection_hints_set_hint (hints, 
-                                            kim_hint_key_server,
-                                            in_server_hint);
-    }
+    return err;   
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static int32_t kim_handle_request_auth_prompt (mach_port_t   in_client_port, 
+                                               mach_port_t   in_reply_port, 
+                                               k5_ipc_stream in_request_stream)
+{
+    int32_t err = 0;
+    char *identity_string = NULL;
+    int32_t type = 0;
+    int32_t hide_reply = 0;
+    char *title = NULL;
+    char *message = NULL;
+    char *description = NULL;
     
     if (!err) {
-        ServerThread *sthread = [ServerThread sharedServerThread];
-        if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; }
-        
-        if (!err) {
-            client = [sthread connectionForPort: in_server_port];
-            if (!client) { err = KIM_OUT_OF_MEMORY_ERR; }
-        }
-    }
+        err = k5_ipc_stream_read_string (in_request_stream, &identity_string);
+    }    
     
     if (!err) {
-        identity = [client selectIdentityWithHints: hints
-                                             error: &result];
-    }
+        err = k5_ipc_stream_read_int32 (in_request_stream, &type);
+    }    
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int32 (in_request_stream, &hide_reply);
+    }    
+    
+    if (!err) {
+        err = k5_ipc_stream_read_string (in_request_stream, &title);
+    }    
+    
+    if (!err) {
+        err = k5_ipc_stream_read_string (in_request_stream, &message);
+    }    
     
-    if (!err && !result) {
-        err = kim_identity_get_string (identity, &identity_string);
+    if (!err) {
+        err = k5_ipc_stream_read_string (in_request_stream, &description);
+    }    
+    
+    if (!err) {
+#warning Send auth prompt message to main thread with 2 ports and arguments
     }
+    
+    k5_ipc_stream_free_string (identity_string);    
+    k5_ipc_stream_free_string (title);    
+    k5_ipc_stream_free_string (message);    
+    k5_ipc_stream_free_string (description);    
+    
+    return err;   
+}
 
-    if (!err && !result && identity_string) {
-        identity_len = strlen (identity_string) + 1;
-        err = vm_allocate (mach_task_self (), 
-                           (vm_address_t *) &identity_buf, identity_len, TRUE);
+/* ------------------------------------------------------------------------ */
+
+int32_t kim_handle_reply_auth_prompt (mach_port_t   in_reply_port, 
+                                      kim_string    in_prompt_response,
+                                      int32_t       in_error)
+{
+    int32_t err = 0;
+    k5_ipc_stream reply = NULL;
+    
+    if (!err) {
+        err = k5_ipc_stream_new (&reply);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (reply, in_error);
     }
     
-    if (!err && !result) {
-        memmove (identity_buf, identity_string, identity_len);
-        *out_identity = identity_buf;
-        *out_identityCnt = identity_len;
-        identity_buf = NULL;
+    if (!err && !in_error) {
+        err = k5_ipc_stream_write_string (reply, in_prompt_response);
     }
-        
+    
     if (!err) {
-        *out_error = result;
+        err = k5_ipc_server_send_reply (in_reply_port, reply);
     }
     
-    if (identity_buf) { vm_deallocate (mach_task_self (), 
-                                       (vm_address_t) identity_buf, 
-                                       identity_len); }
-    kim_string_free (&identity_string);
-    kim_identity_free (&identity);
-    kim_selection_hints_free (&hints);
-
-    return err;
+    k5_ipc_stream_release (reply);
+    
+    return err;   
 }
 
+#pragma mark -
+
 /* ------------------------------------------------------------------------ */
 
-kern_return_t kim_mipc_srv_auth_prompt (mach_port_t             in_server_port,
-                                        kim_mipc_in_string      in_identity,
-                                        mach_msg_type_number_t  in_identityCnt,
-                                        kim_mipc_prompt_type    in_prompt_type,
-                                        kim_mipc_boolean        in_hide_reply,
-                                        kim_mipc_in_string      in_title,
-                                        mach_msg_type_number_t  in_titleCnt,
-                                        kim_mipc_in_string      in_message,
-                                        mach_msg_type_number_t  in_messageCnt,
-                                        kim_mipc_in_string      in_description,
-                                        mach_msg_type_number_t  in_descriptionCnt,
-                                        kim_mipc_out_string    *out_response,
-                                        mach_msg_type_number_t *out_responseCnt,
-                                        kim_mipc_error         *out_error)
+static int32_t kim_handle_request_change_password (mach_port_t   in_client_port, 
+                                                   mach_port_t   in_reply_port, 
+                                                   k5_ipc_stream in_request_stream)
 {
-    kern_return_t err = 0;
-    kim_error result = KIM_NO_ERROR;
-    ClientConnection *client = NULL;
-    kim_identity identity = NULL;
-    const char *response_string = NULL;
-    mach_msg_type_number_t response_len = 0;
-    kim_mipc_out_string response_buf = NULL;
-    
-    if (!err) {
-        ServerThread *sthread = [ServerThread sharedServerThread];
-        if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; }
-        
-        if (!err) {
-            client = [sthread connectionForPort: in_server_port];
-            if (!client) { err = KIM_OUT_OF_MEMORY_ERR; }
-        }
+    int32_t err = 0;
+    char *identity_string = NULL;
+    int32_t old_password_expired = 0;
+    
+    if (!err) {
+        err = k5_ipc_stream_read_string (in_request_stream, &identity_string);
+    }    
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int32 (in_request_stream, 
+                                        &old_password_expired);
+    }    
+    
+    if (!err) {
+#warning Send change password message to main thread with 2 ports and arguments
     }
     
+    k5_ipc_stream_free_string (identity_string);   
+    
+    return err;   
+}
+
+/* ------------------------------------------------------------------------ */
+
+int32_t kim_handle_reply_change_password (mach_port_t   in_reply_port, 
+                                          kim_string    in_old_password,
+                                          kim_string    in_new_password,
+                                          kim_string    in_vfy_password,
+                                          int32_t       in_error)
+{
+    int32_t err = 0;
+    k5_ipc_stream reply = NULL;
+    
     if (!err) {
-        err = kim_identity_create_from_string (&identity, in_identity);
+        err = k5_ipc_stream_new (&reply);
     }
     
     if (!err) {
-        NSString *title = NULL;
-        NSString *message = NULL;
-        NSString *description = NULL;
-        
-        if (in_title) {
-            title = [NSString stringWithUTF8String: in_title];
-        }
-        
-        if (in_message) {
-            message = [NSString stringWithUTF8String: in_message];
-        }
-        
-        if (in_description) {
-            description = [NSString stringWithUTF8String: in_description];
-        }
-        
-        response_string = [[client authPromptWithIdentity: identity
-                                                     type: in_prompt_type
-                                                hideReply: in_hide_reply
-                                                    title: title
-                                                  message: message
-                                              description: description
-                                                    error: &result] UTF8String];
+        err = k5_ipc_stream_write_int32 (reply, in_error);
+    }
+    
+    if (!err && !in_error) {
+        err = k5_ipc_stream_write_string (reply, in_old_password);
     }
     
-    if (!err && !result && response_string) {
-        response_len = strlen (response_string) + 1;
-        err = vm_allocate (mach_task_self (), 
-                           (vm_address_t *) &response_buf, response_len, TRUE);
-        
+    if (!err && !in_error) {
+        err = k5_ipc_stream_write_string (reply, in_new_password);
     }
     
-    if (!err && !result) {
-        memmove (response_buf, response_string, response_len);
-        *out_response = response_buf;
-        *out_responseCnt = response_len;
-        response_buf = NULL;
+    if (!err && !in_error) {
+        err = k5_ipc_stream_write_string (reply, in_vfy_password);
     }
     
     if (!err) {
-        *out_error = result;
+        err = k5_ipc_server_send_reply (in_reply_port, reply);
     }
     
-    if (response_buf) { vm_deallocate (mach_task_self (), 
-                                       (vm_address_t) response_buf, 
-                                       response_len); }
-    kim_identity_free (&identity);
+    k5_ipc_stream_release (reply);
     
-    return err;
+    return err;   
 }
 
+#pragma mark -
+
 /* ------------------------------------------------------------------------ */
 
-kern_return_t kim_mipc_srv_change_password (mach_port_t             in_server_port,
-                                            kim_mipc_in_string      in_identity,
-                                            mach_msg_type_number_t  in_identityCnt,
-                                            kim_mipc_boolean        in_old_password_expired,
-                                            kim_mipc_out_string    *out_old_password,
-                                            mach_msg_type_number_t *out_old_passwordCnt,
-                                            kim_mipc_out_string    *out_new_password,
-                                            mach_msg_type_number_t *out_new_passwordCnt,
-                                            kim_mipc_out_string    *out_vfy_password,
-                                            mach_msg_type_number_t *out_vfy_passwordCnt,
-                                            kim_mipc_error         *out_error)
+static int32_t kim_handle_request_handle_error (mach_port_t   in_client_port, 
+                                                mach_port_t   in_reply_port, 
+                                                k5_ipc_stream in_request_stream)
 {
-    kern_return_t err = 0;
-    kim_error result = KIM_NO_ERROR;
-    ClientConnection *client = NULL;
-    kim_identity identity = NULL;
-    NSArray *passwords = NULL;
-    const char *old_password_string = NULL;
-    const char *new_password_string = NULL;
-    const char *vfy_password_string = NULL;
-    mach_msg_type_number_t old_password_len = 0;
-    mach_msg_type_number_t new_password_len = 0;
-    mach_msg_type_number_t vfy_password_len = 0;
-    kim_mipc_out_string old_password_buf = NULL;
-    kim_mipc_out_string new_password_buf = NULL;
-    kim_mipc_out_string vfy_password_buf = NULL;
-    
-    if (!err) {
-        ServerThread *sthread = [ServerThread sharedServerThread];
-        if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; }
-        
-        if (!err) {
-            client = [sthread connectionForPort: in_server_port];
-            if (!client) { err = KIM_OUT_OF_MEMORY_ERR; }
-        }
-    }
+    int32_t err = 0;
+    char *identity_string = NULL;
+    int32_t error = 0;
+    char *message = NULL;
+    char *description = NULL;
     
     if (!err) {
-        err = kim_identity_create_from_string (&identity, in_identity);
-    }
+        err = k5_ipc_stream_read_string (in_request_stream, &identity_string);
+    }    
     
     if (!err) {
-        passwords = [client changePasswordWithIdentity: identity
-                                   oldPasswordIsExpired: in_old_password_expired
-                                                  error: &result];
-    }
+        err = k5_ipc_stream_read_int32 (in_request_stream, &error);
+    }    
     
-    if (!err && !result) {
-        if (passwords && [passwords count] == 3) {
-            old_password_string = [[passwords objectAtIndex: 1] UTF8String];
-            new_password_string = [[passwords objectAtIndex: 2] UTF8String];
-            vfy_password_string = [[passwords objectAtIndex: 3] UTF8String];
-        } else {
-            err = KIM_OUT_OF_MEMORY_ERR;
-        }
-    }
-        
-    if (!err && !result && old_password_string) {
-        old_password_len = strlen (old_password_string) + 1;
-        err = vm_allocate (mach_task_self (), (vm_address_t *) &old_password_buf, old_password_len, TRUE);
-        
+    if (!err) {
+        err = k5_ipc_stream_read_string (in_request_stream, &message);
+    }    
+    
+    if (!err) {
+        err = k5_ipc_stream_read_string (in_request_stream, &description);
+    }    
+    
+    if (!err) {
+#warning Send handle error message to main thread with 2 ports and arguments
     }
+    
+    k5_ipc_stream_free_string (identity_string);   
+    k5_ipc_stream_free_string (message);   
+    k5_ipc_stream_free_string (description);   
+    
+    return err;   
+}
 
-    if (!err && !result && new_password_string) {
-        new_password_len = strlen (new_password_string) + 1;
-        err = vm_allocate (mach_task_self (), (vm_address_t *) &new_password_buf, new_password_len, TRUE);
-        
-    }
+/* ------------------------------------------------------------------------ */
+
+int32_t kim_handle_reply_handle_error (mach_port_t   in_reply_port, 
+                                       int32_t       in_error)
+{
+    int32_t err = 0;
+    k5_ipc_stream reply = NULL;
     
-    if (!err && !result && vfy_password_string) {
-        vfy_password_len = strlen (vfy_password_string) + 1;
-        err = vm_allocate (mach_task_self (), (vm_address_t *) &vfy_password_buf, vfy_password_len, TRUE);
+    if (!err) {
+        err = k5_ipc_stream_new (&reply);
     }
     
-    if (!err && !result) {
-        memmove (old_password_buf, old_password_string, old_password_len);
-        memmove (new_password_buf, new_password_string, new_password_len);
-        memmove (vfy_password_buf, vfy_password_string, vfy_password_len);
-        *out_old_password = old_password_buf;
-        *out_new_password = new_password_buf;
-        *out_vfy_password = vfy_password_buf;
-        *out_old_passwordCnt = old_password_len;
-        *out_new_passwordCnt = new_password_len;
-        *out_vfy_passwordCnt = vfy_password_len;
-        old_password_buf = NULL;
-        new_password_buf = NULL;
-        vfy_password_buf = NULL;
+    if (!err) {
+        err = k5_ipc_stream_write_int32 (reply, in_error);
     }
-    
+
     if (!err) {
-        *out_error = result;
+        err = k5_ipc_server_send_reply (in_reply_port, reply);
     }
     
-    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 (vfy_password_buf) { vm_deallocate (mach_task_self (), (vm_address_t) vfy_password_buf, vfy_password_len); }
-    kim_identity_free (&identity);
+    k5_ipc_stream_release (reply);
     
-    return err;
+    return err;   
 }
 
+#pragma mark -
+
 /* ------------------------------------------------------------------------ */
 
-kern_return_t kim_mipc_srv_handle_error (mach_port_t             in_server_port,
-                                         kim_mipc_in_string      in_identity,
-                                         mach_msg_type_number_t  in_identityCnt,
-                                         kim_mipc_error          in_error,
-                                         kim_mipc_in_string      in_message,
-                                         mach_msg_type_number_t  in_messageCnt,
-                                         kim_mipc_in_string      in_description,
-                                         mach_msg_type_number_t  in_descriptionCnt,
-                                         kim_mipc_error         *out_error)
+static int32_t kim_handle_request_fini (mach_port_t   in_client_port, 
+                                        mach_port_t   in_reply_port, 
+                                        k5_ipc_stream in_request_stream)
 {
-    kern_return_t err = 0;
-    kim_error result = KIM_NO_ERROR;
-    ClientConnection *client = NULL;
-    kim_identity identity = NULL;
-    
-    if (!err) {
-        ServerThread *sthread = [ServerThread sharedServerThread];
-        if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; }
-        
-        if (!err) {
-            client = [sthread connectionForPort: in_server_port];
-            if (!client) { err = KIM_OUT_OF_MEMORY_ERR; }
-        }
+    int32_t err = 0;
+    
+    if (!err) {
+#warning Send fini message to main thread with 2 ports
     }
     
+    return err;   
+}
+
+/* ------------------------------------------------------------------------ */
+
+int32_t kim_handle_reply_fini (mach_port_t   in_reply_port, 
+                               int32_t       in_error)
+{
+    int32_t err = 0;
+    k5_ipc_stream reply = NULL;
+    
     if (!err) {
-        err = kim_identity_create_from_string (&identity, in_identity);
+        err = k5_ipc_stream_new (&reply);
     }
     
     if (!err) {
-        NSString *message = NULL;
-        NSString *description = NULL;
-        
-        if (in_message) {
-            message = [NSString stringWithUTF8String: in_message];
-        }
-        
-        if (in_description) {
-            description = [NSString stringWithUTF8String: in_description];
-        }
-        
-        result = [client handleError: in_error
-                            identity: identity
-                             message: message
-                         description: description];
+        err = k5_ipc_stream_write_int32 (reply, in_error);
     }
     
     if (!err) {
-        *out_error = result;
+        err = k5_ipc_server_send_reply (in_reply_port, reply);
     }
     
-    kim_identity_free (&identity);
+    k5_ipc_stream_release (reply);
+    
+    return err;   
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+int32_t k5_ipc_server_add_client (mach_port_t in_client_port)
+{
+    int32_t err = 0;
+    
+    if (!err) {
+        /* Don't need to do anything here since we have an init message */
+    }
     
     return err;
 }
 
 /* ------------------------------------------------------------------------ */
 
-kern_return_t kim_mipc_srv_fini (mach_port_t     in_server_port,
-                                 kim_mipc_error *out_error)
+int32_t k5_ipc_server_remove_client (mach_port_t in_client_port)
 {
-    kern_return_t err = 0;
-    ServerThread *sthread = NULL;
+    int32_t err = 0;    
     
     if (!err) {
-        sthread = [ServerThread sharedServerThread];
-        if (!sthread) { err = KIM_OUT_OF_MEMORY_ERR; }
+        /* Client exited.  Main thread should check for windows belonging to
+         * in_client_port and close any it finds. */
+#warning Insert code to handle client death here
     }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
 
+int32_t k5_ipc_server_handle_request (mach_port_t   in_client_port, 
+                                      mach_port_t   in_reply_port, 
+                                      k5_ipc_stream in_request_stream)
+{
+    int32_t err = 0;
+    char *message_type = NULL;
+    
     if (!err) {
-        [sthread removeConnectionWithPort: in_server_port];
+        err = k5_ipc_stream_read_string (in_request_stream, &message_type);
     }
     
     if (!err) {
-        *out_error = KIM_NO_ERROR;
+        if (!strcmp (message_type, "init")) {
+            err = kim_handle_request_init (in_client_port,
+                                           in_reply_port,
+                                           in_request_stream);
+            
+        } else if (!strcmp (message_type, "enter_identity")) {
+            err = kim_handle_request_enter_identity (in_client_port,
+                                                     in_reply_port,
+                                                     in_request_stream);
+            
+        } else if (!strcmp (message_type, "select_identity")) {
+            err = kim_handle_request_select_identity (in_client_port,
+                                                      in_reply_port,
+                                                      in_request_stream);
+            
+        } else if (!strcmp (message_type, "auth_prompt")) {
+            err = kim_handle_request_auth_prompt (in_client_port,
+                                                  in_reply_port,
+                                                  in_request_stream);
+            
+        } else if (!strcmp (message_type, "change_password")) {
+            err = kim_handle_request_change_password (in_client_port,
+                                                      in_reply_port,
+                                                      in_request_stream);
+            
+        } else if (!strcmp (message_type, "handle_error")) {
+            err = kim_handle_request_handle_error (in_client_port,
+                                                   in_reply_port,
+                                                   in_request_stream);
+            
+        } else if (!strcmp (message_type, "fini")) {
+            err = kim_handle_request_fini (in_client_port,
+                                           in_reply_port,
+                                           in_request_stream);
+            
+        } else {
+            err = EINVAL;
+        }
     }
     
+    k5_ipc_stream_free_string (message_type);
+    
     return err;
 }
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+int32_t kim_agent_listen_loop (void)
+{
+    return k5_ipc_server_listen_loop ();
+}
diff --git a/src/kim/agent/mac/ServerThread.h b/src/kim/agent/mac/ServerThread.h
deleted file mode 100644 (file)
index 4457f2a..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2008 Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-
-#include <Kerberos/kim.h>
-#include <Kerberos/kim_ui_plugin.h>
-
-@interface ClientConnection : NSObject {
-    mach_port_t port;
-    bool callerIsFrontProcess;
-    NSString *applicationName;
-    NSString *applicationPath;
-}
-
-@property(readonly) mach_port_t port;
-
-- (id) initWithPort: (mach_port_t) port
-               name: (NSString *) name
-               path: (NSString *) path
-      front_process: (bool) frontProcess;
-
-- (kim_identity) enterIdentityWithError: (kim_error *) outError;
-
-- (kim_identity) selectIdentityWithHints: (kim_selection_hints) hints
-                                   error: (kim_error *) outError;
-
-- (NSString *) authPromptWithIdentity: (kim_identity) identity
-                                 type: (kim_prompt_type) type
-                            hideReply: (bool) hideReply
-                                title: (NSString *) title
-                              message: (NSString *) message
-                          description: (NSString *) description
-                                error: (kim_error *) outError;
-
-- (NSArray *) changePasswordWithIdentity: (kim_identity) identity
-                    oldPasswordIsExpired: (bool) oldPasswordIsExpired
-                                   error: (kim_error *) outError;
-
-- (kim_error) handleError: (kim_error) error
-                 identity: (kim_identity) identity
-                  message: (NSString *) message
-              description: (NSString *) description;
-
-- (void) dealloc;
-
-@end
-
-/* ------------------------------------------------------------------------ */
-
-@interface ServerThread : NSObject {
-    NSMutableArray *connections;
-}
-
-+ (ServerThread *) sharedServerThread;
-   
-- (id) init;
-
-- (void) dealloc;
-
-- (kern_return_t) listen;
-
-- (void) addConnectionWithPort: (mach_port_t) port
-                          name: (NSString *) name
-                          path: (NSString *) path
-                  frontProcess: (bool) frontProcess;
-
-- (void) removeConnectionWithPort: (mach_port_t) port;
-
-
-- (ClientConnection *) connectionForPort: (mach_port_t) port;
-
-@end
diff --git a/src/kim/agent/mac/ServerThread.m b/src/kim/agent/mac/ServerThread.m
deleted file mode 100644 (file)
index 6d5ba5e..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright 2008 Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-#import "ServerThread.h"
-#import <Kerberos/kim.h>
-#import <Kerberos/kipc_server.h>
-#import "kim_migServer.h"
-
-
-@implementation ClientConnection
-
-@synthesize port;
-
-/* ------------------------------------------------------------------------ */
-
-- (id) initWithPort: (mach_port_t) connectionPort
-               name: (NSString *) name
-               path: (NSString *) path
-      front_process: (bool) frontProcess
-{
-    if ((self = [super init])) {
-        port = connectionPort;
-        callerIsFrontProcess = frontProcess;
-        applicationName = [name retain];
-        applicationPath = [path retain];
-    }
-    
-    return self;
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (kim_identity) enterIdentityWithError: (kim_error *) outError
-{
-    kim_error err = KIM_NO_ERROR;
-    kim_identity identity = NULL;
-    
-    *outError = err;
-    return identity;
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (kim_identity) selectIdentityWithHints: (kim_selection_hints) hints
-                                 error: (kim_error *) outError
-{
-    kim_error err = KIM_NO_ERROR;
-    kim_identity identity = NULL;
-    
-    *outError = err;
-    return identity;
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (NSString *) authPromptWithIdentity: (kim_identity) identity
-                                 type: (kim_prompt_type) type
-                            hideReply: (bool) hideReply
-                                title: (NSString *) title
-                              message: (NSString *) message
-                          description: (NSString *) description
-                                error: (kim_error *) outError
-{
-    kim_error err = KIM_NO_ERROR;
-    NSString *reply = @"A reply";
-    
-    *outError = err;
-    return reply;
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (NSArray *) changePasswordWithIdentity: (kim_identity) identity
-                    oldPasswordIsExpired: (bool) oldPasswordIsExpired
-                                   error: (kim_error *) outError
-{
-    kim_error err = KIM_NO_ERROR;
-    NSString *oldPassword = @"an old password";
-    NSString *newPassword = @"a new password";
-    NSString *verifyPassword = @"a verify password";
-    
-    *outError = err;
-    return !err ? [NSArray arrayWithObjects: oldPassword, newPassword, verifyPassword, NULL] : NULL;    
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (kim_error) handleError: (kim_error) error
-                 identity: (kim_identity) identity
-                  message: (NSString *) message
-              description: (NSString *) description
-{
-    kim_error err = KIM_NO_ERROR;
-    
-    return err;
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (void) dealloc
-{
-    [applicationName release];
-    [applicationPath release];
-    [super dealloc];
-}
-
-@end
-
-@implementation ServerThread
-
-/* ------------------------------------------------------------------------ */
-
-+ (ServerThread *) sharedServerThread
-{
-    static ServerThread *gServerThread = NULL;
-    
-    if (!gServerThread) {
-        gServerThread = [[ServerThread alloc] init];
-    }
-    
-    return gServerThread;
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (id) init
-{
-    if ((self = [super init])) {
-        connections = [[NSMutableArray alloc] init];
-        if (!connections) {
-            [self release];
-            self = nil;
-        }
-    }
-    
-    return self;
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (void) dealloc
-{
-    [connections release];
-    [super dealloc];
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (kern_return_t) listen
-{
-    return kipc_server_run_server (kim_server);
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (void) addConnectionWithPort: (mach_port_t) port
-                          name: (NSString *) name
-                          path: (NSString *) path
-                  frontProcess: (bool) frontProcess
-{
-    ClientConnection *client = [[ClientConnection alloc] initWithPort: port
-                                                                 name: name
-                                                                 path: path
-                                                        front_process: frontProcess];
-    if (client) {
-        [connections addObject: client];
-    }
-    
-    [client release];
-}
-
-/* ------------------------------------------------------------------------ */
-
-- (void) removeConnectionWithPort: (mach_port_t) port
-{
-    for (ClientConnection *client in connections) {
-        if (client.port == port) {
-            [connections removeObject: client];
-        }
-    }
-    
-    if (![connections count]) {
-        kipc_server_quit ();
-    }
-}
-
-
-/* ------------------------------------------------------------------------ */
-
-- (ClientConnection *) connectionForPort: (mach_port_t) port
-{
-    for (ClientConnection *client in connections) {
-        if (client.port == port) {
-            return client;
-        }
-    }    
-    return NULL;
-}
-
-@end
-
index fb0b9dfd37f6613bee04759956b4ee175c1bbe24..a6ffad1d0e31c4fe4c7c7d419aea989fa69d92ab 100644 (file)
@@ -1,6 +1,19 @@
 #import <Cocoa/Cocoa.h>
+#import "k5_mig_server.h"
 
-int main(int argc, char *argv[])
+int main(int argc, const char *argv[])
 {
-    return NSApplicationMain(argc, (const char **) argv);
+    int err = 0;
+    
+    err = k5_ipc_server_initialize (argc, argv);
+    
+    if (!err) {
+        err = NSApplicationMain(argc, argv);
+    }
+    
+    if (!err) {
+        err = k5_ipc_server_cleanup (argc, argv);
+    }
+    
+    return err;
 }
index 4f629105d9d1b3e6c55f24a4477670d5b574f5f3..7559dbed949410d76eb053081a82c9f43529bd30 100644 (file)
 #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);
 }
 
diff --git a/src/kim/mac/kim_mig.defs b/src/kim/mac/kim_mig.defs
deleted file mode 100644 (file)
index 8d041cf..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * $Header$
- *
- * Copyright 2006-2008 Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- */
-#include <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-import "kim_mig_types.h";
-
-subsystem kim 100;
-
-serverprefix kim_mipc_srv_;
-userprefix kim_mipc_cli_;
-
-type kim_mipc_in_string   = array [] of char;
-type kim_mipc_out_string  = array [] of char;
-type kim_mipc_error       = int32_t;
-type kim_mipc_boolean     = boolean_t;
-type kim_mipc_time        = uint32_t;
-type kim_mipc_lifetime    = uint32_t;
-type kim_mipc_prompt_type = uint32_t;
-
-routine init (in_server_port : mach_port_t;
-         in_application_task : task_t;
-         in_application_name : kim_mipc_in_string;
-         in_application_path : kim_mipc_in_string;
-               out out_error : kim_mipc_error);
-
-routine fini (in_server_port : mach_port_t;
-               out out_error : kim_mipc_error);
-
-
-routine enter_identity (in_server_port : mach_port_t;
-                      out out_identity : kim_mipc_out_string;
-                         out out_error : kim_mipc_error);
-
-routine select_identity (in_server_port : mach_port_t;
-                      in_application_id : kim_mipc_in_string;
-                         in_explanation : kim_mipc_in_string;
-                         
-                          in_start_time : kim_mipc_time;
-                            in_lifetime : kim_mipc_lifetime;
-                           in_renewable : kim_mipc_boolean;
-                    in_renewal_lifetime : kim_mipc_lifetime;
-                         in_forwardable : kim_mipc_boolean;
-                           in_proxiable : kim_mipc_boolean;
-                         in_addressless : kim_mipc_boolean;
-                        in_service_name : kim_mipc_in_string;
-
-               in_service_identity_hint : kim_mipc_in_string;
-                   in_client_realm_hint : kim_mipc_in_string;
-                           in_user_hint : kim_mipc_in_string;
-                  in_service_realm_hint : kim_mipc_in_string;
-                        in_service_hint : kim_mipc_in_string;
-                         in_server_hint : kim_mipc_in_string;
-
-                       out out_identity : kim_mipc_out_string;
-                          out out_error : kim_mipc_error);
-                         
-routine auth_prompt (in_server_port : mach_port_t;
-                        in_identity : kim_mipc_in_string;
-                     in_prompt_type : kim_mipc_prompt_type;
-                      in_hide_reply : kim_mipc_boolean;
-                           in_title : kim_mipc_in_string;
-                         in_message : kim_mipc_in_string;
-                     in_description : kim_mipc_in_string;
-                   out out_response : kim_mipc_out_string;
-                      out out_error : kim_mipc_error);
-
-routine change_password (in_server_port : mach_port_t;
-                            in_identity : kim_mipc_in_string;
-                in_old_password_expired : kim_mipc_boolean;
-                   out out_old_password : kim_mipc_out_string;
-                   out out_new_password : kim_mipc_out_string;
-                out out_verify_password : kim_mipc_out_string;
-                          out out_error : kim_mipc_error);
-                   
- routine handle_error (in_server_port : mach_port_t;
-                          in_identity : kim_mipc_in_string;
-                             in_error : kim_mipc_error;
-                           in_message : kim_mipc_in_string;
-                       in_description : kim_mipc_in_string;
-                        out out_error : kim_mipc_error);
-                       
-                          
diff --git a/src/util/mac/k5_mig.defs b/src/util/mac/k5_mig.defs
new file mode 100644 (file)
index 0000000..6349eb8
--- /dev/null
@@ -0,0 +1,54 @@
+/* $Copyright:
+ *
+ * Copyright 2004-2006 by the Massachusetts Institute of Technology.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require a
+ * specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+ * this software and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of M.I.T. not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Furthermore if you
+ * modify this software you must label your software as modified software
+ * and not distribute it in such a fashion that it might be confused with
+ * the original MIT software. M.I.T. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Individual source code files are copyright MIT, Cygnus Support,
+ * OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+ * 
+ * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+ * and Zephyr are trademarks of the Massachusetts Institute of Technology
+ * (MIT).  No commercial use of these trademarks may be made without prior
+ * written permission of MIT.
+ * 
+ * "Commercial use" means use of a name in a product or other for-profit
+ * manner.  It does NOT prevent a commercial firm from referring to the MIT
+ * trademarks in order to convey information (although in doing so,
+ * recognition of their trademark status should be given).
+ * $
+ */
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+import "k5_mig_types.h";
+
+/* Note the 1024 must be the same as K5_IPC_MAX_MSG_SIZE */
+type k5_ipc_inl_request_t = array [ * : 1024 ] of char;
+type k5_ipc_ool_request_t = array [] of char;
+
+type k5_ipc_inl_reply_t = array [ * : 1024 ] of char;
+type k5_ipc_ool_reply_t = array [] of char;
diff --git a/src/util/mac/k5_mig_client.c b/src/util/mac/k5_mig_client.c
new file mode 100644 (file)
index 0000000..5ffe7de
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5_mig_client.h"
+
+#include <Kerberos/kipc_client.h>
+#include "k5_mig_request.h"
+#include "k5_mig_replyServer.h"
+#include "k5-thread.h"
+
+MAKE_INIT_FUNCTION(k5_cli_ipc_thread_init);
+MAKE_FINI_FUNCTION(k5_cli_ipc_thread_fini);
+
+/* ------------------------------------------------------------------------ */
+
+static int k5_cli_ipc_thread_init (void)
+{
+    int err = 0;
+
+    err = k5_key_register (K5_KEY_IPC_REQUEST_PORT, free);
+    
+    if (!err) {
+        err = k5_key_register (K5_KEY_IPC_REPLY_STREAM, NULL);
+    }
+    
+    if (!err) {
+        err = k5_key_register (K5_KEY_IPC_SERVER_DIED, NULL);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void k5_cli_ipc_thread_fini (void)
+{    
+    k5_key_delete (K5_KEY_IPC_REQUEST_PORT);
+    k5_key_delete (K5_KEY_IPC_REPLY_STREAM);
+    k5_key_delete (K5_KEY_IPC_SERVER_DIED);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static boolean_t k5_ipc_reply_demux (mach_msg_header_t *request, 
+                                     mach_msg_header_t *reply) 
+{
+    boolean_t handled = 0;
+    
+    if (CALL_INIT_FUNCTION (k5_cli_ipc_thread_init) != 0) {
+        return 0;
+    }    
+    
+    if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
+        int32_t *server_died = k5_getspecific (K5_KEY_IPC_SERVER_DIED);
+        if (!server_died) { 
+            *server_died = 1;
+        }
+        
+        handled = 1; /* server died */
+    }
+    
+    if (!handled) {
+        handled = k5_ipc_reply_server (request, reply);
+    }
+    
+    return handled;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+kern_return_t k5_ipc_client_reply (mach_port_t             in_reply_port,
+                                   k5_ipc_inl_reply_t      in_inl_reply,
+                                   mach_msg_type_number_t  in_inl_replyCnt,
+                                   k5_ipc_ool_reply_t      in_ool_reply,
+                                   mach_msg_type_number_t  in_ool_replyCnt)
+{
+    kern_return_t err = KERN_SUCCESS;
+    k5_ipc_stream reply_stream = NULL;
+    
+    if (!err) {
+        err = CALL_INIT_FUNCTION (k5_cli_ipc_thread_init);
+    }
+    
+    if (!err) {
+        reply_stream = k5_getspecific (K5_KEY_IPC_REPLY_STREAM);
+        if (!reply_stream) { err = EINVAL; }
+    }
+    
+    if (!err) {
+        if (in_inl_replyCnt) {
+            err = k5_ipc_stream_write (reply_stream, in_inl_reply, in_inl_replyCnt);
+            
+        } else if (in_ool_replyCnt) {
+            err = k5_ipc_stream_write (reply_stream, in_ool_reply, in_ool_replyCnt);
+            
+        } else {
+            err = EINVAL;
+        }
+    }
+    
+    if (in_ool_replyCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_reply, in_ool_replyCnt); }
+    
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+int32_t k5_ipc_send_request (int32_t        in_launch_server,
+                             k5_ipc_stream  in_request_stream,
+                             k5_ipc_stream *out_reply_stream)
+{
+    int err = 0;
+    int32_t done = 0;
+    int32_t try_count = 0;
+    int32_t server_died = 0;
+    mach_port_t server_port = MACH_PORT_NULL;
+    mach_port_t *request_port = NULL;
+    mach_port_t reply_port = MACH_PORT_NULL;
+    const char *inl_request = NULL; /* char * so we can pass the buffer in directly */
+    mach_msg_type_number_t inl_request_length = 0;
+    k5_ipc_ool_request_t ool_request = NULL;
+    mach_msg_type_number_t ool_request_length = 0;
+    k5_ipc_stream reply_stream = NULL;
+    
+    if (!in_request_stream) { err = EINVAL; }
+    if (!out_reply_stream ) { err = EINVAL; }
+    
+    if (!err) {
+        err = CALL_INIT_FUNCTION (k5_cli_ipc_thread_init);
+    }    
+    
+    if (!err) {
+        /* depending on how big the message is, use the fast inline buffer or  
+         * the slow dynamically allocated buffer */
+        mach_msg_type_number_t request_length = k5_ipc_stream_size (in_request_stream);
+        
+        if (request_length > K5_IPC_MAX_MSG_SIZE) {
+            //dprintf ("%s choosing out of line buffer (size is %d)", 
+            //                  __FUNCTION__, request_length);
+            
+            err = vm_read (mach_task_self (), 
+                           (vm_address_t) k5_ipc_stream_data (in_request_stream), request_length, 
+                           (vm_address_t *) &ool_request, &ool_request_length);        
+        } else {
+            //dprintf ("%s choosing in line buffer (size is %d)",
+            //                  __FUNCTION__, request_length);
+            
+            inl_request_length = request_length;
+            inl_request = k5_ipc_stream_data (in_request_stream);
+        }
+    }
+
+    if (!err) {
+        request_port = k5_getspecific (K5_KEY_IPC_REQUEST_PORT);
+        
+        if (!request_port) {
+            request_port = malloc (sizeof (mach_port_t));
+            if (!request_port) { err = ENOMEM; }
+            
+            if (!err) {
+                *request_port = MACH_PORT_NULL;
+                err = k5_setspecific (K5_KEY_IPC_REQUEST_PORT, request_port);
+            }
+        }
+    }
+    
+    if (!err) {
+        err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &reply_port);
+    }
+
+    if (!err) {
+        err = kipc_client_lookup_server (K5_IPC_SERVER_ID, 
+                                         in_launch_server, TRUE, &server_port);
+    }
+    
+    while (!err && !done) {
+        if (!err && !MACH_PORT_VALID (*request_port)) {
+            err = k5_ipc_client_create_client_connection (server_port, request_port);
+        }
+        
+        if (!err) {
+            err = k5_ipc_client_request (*request_port, reply_port,
+                                         inl_request, inl_request_length,
+                                         ool_request, ool_request_length);
+            
+        }
+        
+        if (err == MACH_SEND_INVALID_DEST) {
+            if (try_count < 2) { 
+                try_count++;
+                err = 0;
+            }
+
+            if (request_port && MACH_PORT_VALID (*request_port)) {
+                mach_port_mod_refs (mach_task_self(), *request_port, MACH_PORT_RIGHT_SEND, -1 );
+                *request_port = MACH_PORT_NULL;
+            }    
+            
+            /* Look up server name again without using the cached copy */
+            err = kipc_client_lookup_server (K5_IPC_SERVER_ID,  
+                                             in_launch_server, FALSE, &server_port);
+            
+        } else {
+            /* Talked to server, though we may have gotten an error */
+            done = 1;
+            
+            /* Because we use ",dealloc" ool_request will be freed by mach. 
+            * Don't double free it. */
+            ool_request = NULL; 
+            ool_request_length = 0;                
+        }            
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_new (&reply_stream);
+    }
+    
+    if (!err) {
+        err = k5_setspecific (K5_KEY_IPC_REPLY_STREAM, reply_stream);
+    }
+    
+    if (!err) {
+        err = k5_setspecific (K5_KEY_IPC_SERVER_DIED, &server_died);
+    }
+    
+    if (!err) {
+        mach_port_t old_notification_target = MACH_PORT_NULL;
+
+        /* request no-senders notification so we can get a message when server dies */
+        err = mach_port_request_notification (mach_task_self (), reply_port, 
+                                              MACH_NOTIFY_NO_SENDERS, 1, reply_port, 
+                                              MACH_MSG_TYPE_MAKE_SEND_ONCE, 
+                                              &old_notification_target);
+        
+        if (!err && old_notification_target != MACH_PORT_NULL) {
+            mach_port_deallocate (mach_task_self (), old_notification_target);
+        }
+    }
+    
+    if (!err) {
+        err = mach_msg_server_once (k5_ipc_reply_demux, kkipc_max_message_size, 
+                                    reply_port, MACH_MSG_TIMEOUT_NONE);
+    }
+    
+    if (!err && server_died) {
+        err = ENOTCONN;
+    }
+    
+    if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) {
+        err = 0;  /* If the server is not running just return an empty stream. */
+    }
+    
+    if (!err) {
+        *out_reply_stream = reply_stream;
+        reply_stream = NULL;
+    }
+    
+    k5_setspecific (K5_KEY_IPC_REPLY_STREAM, NULL);
+    k5_setspecific (K5_KEY_IPC_SERVER_DIED, NULL);
+    if (reply_port != MACH_PORT_NULL) { mach_port_destroy (mach_task_self (), reply_port); }
+    if (ool_request_length          ) { vm_deallocate (mach_task_self (), (vm_address_t) ool_request, ool_request_length); }
+    if (reply_stream                ) { k5_ipc_stream_release (reply_stream); }
+    
+    return err;    
+}
similarity index 73%
rename from src/kim/mac/kim_mig_types.h
rename to src/util/mac/k5_mig_client.h
index 189fe06ebfd96a2faa2f24bbfe26de00a1e3d162..b5eefdc3af781b369dece1bb6659a1779e0c38bb 100644 (file)
@@ -1,14 +1,14 @@
 /*
  * $Header$
  *
- * Copyright 2006-2008 Massachusetts Institute of Technology.
+ * Copyright 2006 Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
  * require a specific license from the United States Government.
  * It is the responsibility of any person or organization contemplating
  * export to obtain such a license before exporting.
- * 
+ *
  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  * distribute this software and its documentation for any purpose and
  * without fee is hereby granted, provided that the above copyright
  * or implied warranty.
  */
 
-#ifndef KIM_MIG_H
-#define KIM_MIG_H
+#ifndef K5_MIG_CLIENT_H
+#define K5_MIG_CLIENT_H
 
-#include <kim/kim.h>
+#include "k5-ipc_stream.h"
 
-typedef const char *kim_mipc_in_string;
-typedef char       *kim_mipc_out_string;
-typedef int32_t     kim_mipc_error;
-typedef boolean_t   kim_mipc_boolean;
-typedef uint32_t    kim_mipc_lifetime;
-typedef uint32_t    kim_mipc_time;
-typedef uint32_t    kim_mipc_prompt_type;
+int32_t k5_ipc_send_request (int32_t        in_launch_server,
+                             k5_ipc_stream  in_request_stream,
+                             k5_ipc_stream *out_reply_stream);
 
-#endif /* KIM_MIG_H */
+#endif /* K5_MIG_CLIENT_H */
diff --git a/src/util/mac/k5_mig_reply.defs b/src/util/mac/k5_mig_reply.defs
new file mode 100644 (file)
index 0000000..301778e
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Copyright:
+ *
+ * Copyright 2004-2006 by the Massachusetts Institute of Technology.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require a
+ * specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+ * this software and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of M.I.T. not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Furthermore if you
+ * modify this software you must label your software as modified software
+ * and not distribute it in such a fashion that it might be confused with
+ * the original MIT software. M.I.T. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Individual source code files are copyright MIT, Cygnus Support,
+ * OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+ * 
+ * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+ * and Zephyr are trademarks of the Massachusetts Institute of Technology
+ * (MIT).  No commercial use of these trademarks may be made without prior
+ * written permission of MIT.
+ * 
+ * "Commercial use" means use of a name in a product or other for-profit
+ * manner.  It does NOT prevent a commercial firm from referring to the MIT
+ * trademarks in order to convey information (although in doing so,
+ * recognition of their trademark status should be given).
+ * $
+ */
+#include "k5_mig.defs"
+subsystem k5_ipc_reply 200;
+
+serverprefix k5_ipc_client_;
+userprefix k5_ipc_server_;
+
+/* ",dealloc" means that the vm_read() memory will be moved to 
+ * the other process rather than copied.  This is necessary on the
+ * client side because we can't know when server has copied our
+ * buffers so we can't vm_deallocate() them ourselves. */
+simpleroutine reply (in_reply_port : mach_port_move_send_once_t;
+                     in_inl_reply  : k5_ipc_inl_reply_t;
+                     in_ool_reply  : k5_ipc_ool_reply_t, dealloc);
diff --git a/src/util/mac/k5_mig_request.defs b/src/util/mac/k5_mig_request.defs
new file mode 100644 (file)
index 0000000..bbb23f0
--- /dev/null
@@ -0,0 +1,62 @@
+/* $Copyright:
+ *
+ * Copyright 2004-2006 by the Massachusetts Institute of Technology.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require a
+ * specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+ * this software and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of M.I.T. not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Furthermore if you
+ * modify this software you must label your software as modified software
+ * and not distribute it in such a fashion that it might be confused with
+ * the original MIT software. M.I.T. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Individual source code files are copyright MIT, Cygnus Support,
+ * OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+ * 
+ * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+ * and Zephyr are trademarks of the Massachusetts Institute of Technology
+ * (MIT).  No commercial use of these trademarks may be made without prior
+ * written permission of MIT.
+ * 
+ * "Commercial use" means use of a name in a product or other for-profit
+ * manner.  It does NOT prevent a commercial firm from referring to the MIT
+ * trademarks in order to convey information (although in doing so,
+ * recognition of their trademark status should be given).
+ * $
+ */
+#include "k5_mig.defs"
+
+subsystem k5_ipc_request 100;
+
+serverprefix k5_ipc_server_;
+userprefix k5_ipc_client_;
+
+routine create_client_connection (in_server_port     : mach_port_t;
+                             out out_connection_port : mach_port_t = MACH_MSG_TYPE_MAKE_SEND);
+
+/* ",dealloc" means that the vm_read() memory will be moved to 
+ * the other process rather than copied.  This is necessary on the
+ * server side because we can't know when client has copied our
+ * buffers so we can't vm_deallocate() them ourselves. */
+
+simpleroutine request (in_connection_port : mach_port_t;
+                       in_reply_port      : mach_port_make_send_once_t;
+                       in_inl_request     : k5_ipc_inl_request_t;
+                       in_ool_request     : k5_ipc_ool_request_t, dealloc);
diff --git a/src/util/mac/k5_mig_server.c b/src/util/mac/k5_mig_server.c
new file mode 100644 (file)
index 0000000..ddf81ce
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5_mig_server.h"
+
+#include <syslog.h>
+#include <Kerberos/kipc_server.h>
+#include "k5_mig_requestServer.h"
+#include "k5_mig_reply.h"
+
+
+/* ------------------------------------------------------------------------ */
+
+static boolean_t k5_ipc_request_demux (mach_msg_header_t *request, 
+                                       mach_msg_header_t *reply) 
+{
+    boolean_t handled = false;
+    
+    if (!handled) {
+        handled = k5_ipc_request_server (request, reply);
+    }
+    
+    if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
+        kern_return_t err = KERN_SUCCESS;
+        
+        err = k5_ipc_server_remove_client (request->msgh_local_port);
+        
+        if (!err) {
+            /* Check here for a client in our table and free rights associated with it */
+            err = mach_port_mod_refs (mach_task_self (), request->msgh_local_port, 
+                                      MACH_PORT_RIGHT_RECEIVE, -1);
+        }
+        
+        if (!err) {
+            handled = 1;  /* was a port we are tracking */
+        }
+    }
+    
+    return handled;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+kern_return_t k5_ipc_server_create_client_connection (mach_port_t    in_server_port,
+                                                      mach_port_t   *out_connection_port)
+{
+    kern_return_t err = KERN_SUCCESS;
+    mach_port_t connection_port = MACH_PORT_NULL;
+    mach_port_t old_notification_target = MACH_PORT_NULL;
+    
+    if (!err) {
+        err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &connection_port);
+    }
+    
+    if (!err) {
+        err = mach_port_move_member (mach_task_self (), connection_port, kipc_server_get_listen_portset ());
+    }
+    
+    if (!err) {
+        /* request no-senders notification so we can tell when client quits/crashes */
+        err = mach_port_request_notification (mach_task_self (), connection_port, 
+                                              MACH_NOTIFY_NO_SENDERS, 1, connection_port, 
+                                              MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_notification_target );
+    }
+    
+    if (!err) {
+        err = k5_ipc_server_add_client (connection_port);
+    }
+    
+    if (!err) {
+        *out_connection_port = connection_port;
+        connection_port = MACH_PORT_NULL;
+    }
+    
+    if (MACH_PORT_VALID (connection_port)) { mach_port_deallocate (mach_task_self (), connection_port); }
+    
+    return err;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+kern_return_t k5_ipc_server_request (mach_port_t             in_connection_port,
+                                     mach_port_t             in_reply_port,
+                                     k5_ipc_inl_request_t    in_inl_request,
+                                     mach_msg_type_number_t  in_inl_requestCnt,
+                                     k5_ipc_ool_request_t    in_ool_request,
+                                     mach_msg_type_number_t  in_ool_requestCnt)
+{
+    kern_return_t err = KERN_SUCCESS;
+    k5_ipc_stream request_stream = NULL;
+    
+    if (!err) {
+        err = k5_ipc_stream_new (&request_stream);
+    }
+    
+    if (!err) {
+        if (in_inl_requestCnt) {
+            err = k5_ipc_stream_write (request_stream, in_inl_request, in_inl_requestCnt);
+            
+        } else if (in_ool_requestCnt) {
+            err = k5_ipc_stream_write (request_stream, in_ool_request, in_ool_requestCnt);
+            
+        } else {
+            err = EINVAL;
+        }
+    }
+    
+    if (!err) {
+        err = k5_ipc_server_handle_request (in_connection_port, in_reply_port, request_stream);
+    }
+    
+    k5_ipc_stream_release (request_stream);
+    if (in_ool_requestCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_request, in_ool_requestCnt); }
+    
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+int32_t k5_ipc_server_initialize (int argc, const char *argv[])
+{
+    int32_t err = 0;
+    
+    openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH);
+    syslog (LOG_INFO, "Starting up.");   
+    
+    syslog (LOG_NOTICE, "Exiting: %s (%d)", kipc_error_string (err), err);
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int32_t k5_ipc_server_cleanup (int argc, const char *argv[])
+{
+    int32_t err = 0;
+    
+    openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH);
+    syslog (LOG_INFO, "Starting up.");   
+    
+    syslog (LOG_NOTICE, "Exiting: %s (%d)", kipc_error_string (err), err);
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int32_t k5_ipc_server_listen_loop (void)
+{
+    /* Run the Mach IPC listen loop.  
+     * This will call k5_ipc_server_create_client_connection for new clients
+     * and k5_ipc_server_request for existing clients */
+    
+    return kipc_server_run_server (k5_ipc_request_demux);
+}
+
+/* ------------------------------------------------------------------------ */
+
+int32_t k5_ipc_server_send_reply (mach_port_t   in_reply_port,
+                                  k5_ipc_stream in_reply_stream)
+{
+    kern_return_t err = KERN_SUCCESS;
+    k5_ipc_inl_reply_t inl_reply;
+    mach_msg_type_number_t inl_reply_length = 0;
+    k5_ipc_ool_reply_t ool_reply = NULL;
+    mach_msg_type_number_t ool_reply_length = 0;
+    
+    if (!MACH_PORT_VALID (in_reply_port)) { err = EINVAL; }
+    if (!in_reply_stream                ) { err = EINVAL; }
+    
+    if (!err) {
+        /* depending on how big the message is, use the fast inline buffer or  
+         * the slow dynamically allocated buffer */
+        mach_msg_type_number_t reply_length = k5_ipc_stream_size (in_reply_stream);
+        
+        if (reply_length > K5_IPC_MAX_MSG_SIZE) {            
+            //dprintf ("%s choosing out of line buffer (size is %d)", 
+            //                  __FUNCTION__, reply_length);
+            
+            err = vm_read (mach_task_self (), 
+                           (vm_address_t) k5_ipc_stream_data (in_reply_stream), reply_length, 
+                           (vm_address_t *) &ool_reply, &ool_reply_length);
+            
+        } else {
+            //cci_debug_printf ("%s choosing in line buffer (size is %d)",
+            //                  __FUNCTION__, reply_length);
+            
+            inl_reply_length = reply_length;
+            memcpy (inl_reply, k5_ipc_stream_data (in_reply_stream), reply_length);
+        }
+    }
+    
+    if (!err) {
+        err = k5_ipc_server_reply (in_reply_port, 
+                                   inl_reply, inl_reply_length,
+                                   ool_reply, ool_reply_length);
+    }
+    
+    if (!err) {
+        /* Because we use ",dealloc" ool_reply will be freed by mach. Don't double free it. */
+        ool_reply = NULL;
+        ool_reply_length = 0;
+    }
+    
+    if (ool_reply_length) { vm_deallocate (mach_task_self (), (vm_address_t) ool_reply, ool_reply_length); }
+    
+    return err;
+}
diff --git a/src/util/mac/k5_mig_server.h b/src/util/mac/k5_mig_server.h
new file mode 100644 (file)
index 0000000..c98d1dc
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef K5_MIG_SERVER
+#define K5_MIG_SERVER
+
+#include "k5-ipc_stream.h"
+
+/* Defined by caller */
+
+int32_t k5_ipc_server_add_client (mach_port_t in_client_port);
+
+int32_t k5_ipc_server_remove_client (mach_port_t in_client_port);
+
+int32_t k5_ipc_server_handle_request (mach_port_t   in_connection_port, 
+                                      mach_port_t   in_reply_port, 
+                                      k5_ipc_stream in_request_stream);
+
+/* Server control functions */
+
+int32_t k5_ipc_server_initialize (int argc, const char *argv[]);
+
+int32_t k5_ipc_server_cleanup (int argc, const char *argv[]);
+
+int32_t k5_ipc_server_listen_loop (void);
+
+int32_t k5_ipc_server_send_reply (mach_port_t   in_reply_pipe,
+                                  k5_ipc_stream in_reply_stream);
+
+#endif /* K5_MIG_SERVER */
diff --git a/src/util/mac/k5_mig_types.h b/src/util/mac/k5_mig_types.h
new file mode 100644 (file)
index 0000000..4c8ddb7
--- /dev/null
@@ -0,0 +1,55 @@
+/* $Copyright:
+*
+* Copyright 2004-2006 by the Massachusetts Institute of Technology.
+* 
+* All rights reserved.
+* 
+* Export of this software from the United States of America may require a
+* specific license from the United States Government.  It is the
+* responsibility of any person or organization contemplating export to
+* obtain such a license before exporting.
+* 
+* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+* this software and its documentation for any purpose and without fee is
+* hereby granted, provided that the above copyright notice appear in all
+* copies and that both that copyright notice and this permission notice
+* appear in supporting documentation, and that the name of M.I.T. not be
+* used in advertising or publicity pertaining to distribution of the
+* software without specific, written prior permission.  Furthermore if you
+* modify this software you must label your software as modified software
+* and not distribute it in such a fashion that it might be confused with
+* the original MIT software. M.I.T. makes no representations about the
+* suitability of this software for any purpose.  It is provided "as is"
+* without express or implied warranty.
+* 
+* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+* 
+* Individual source code files are copyright MIT, Cygnus Support,
+* OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+* 
+* Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+* and Zephyr are trademarks of the Massachusetts Institute of Technology
+* (MIT).  No commercial use of these trademarks may be made without prior
+* written permission of MIT.
+* 
+* "Commercial use" means use of a name in a product or other for-profit
+* manner.  It does NOT prevent a commercial firm from referring to the MIT
+* trademarks in order to convey information (although in doing so,
+* recognition of their trademark status should be given).
+* $
+*/
+
+#ifndef K5_MIG_TYPES_H
+#define K5_MIG_TYPES_H
+
+
+#define K5_IPC_MAX_MSG_SIZE 1024
+
+typedef const char  k5_ipc_inl_request_t[K5_IPC_MAX_MSG_SIZE];
+typedef const char *k5_ipc_ool_request_t;
+typedef char        k5_ipc_inl_reply_t[K5_IPC_MAX_MSG_SIZE];
+typedef char       *k5_ipc_ool_reply_t;
+
+#endif /* K5_MIG_TYPES_H */
diff --git a/src/util/support/ipc_stream.c b/src/util/support/ipc_stream.c
new file mode 100644 (file)
index 0000000..608e0fb
--- /dev/null
@@ -0,0 +1,507 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006, 2007 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-ipc_stream.h"
+
+#if !defined(htonll)
+#define htonll(x) k5_htonll(x)
+#endif
+
+#if !defined(ntohll)
+#define ntohll(x) k5_ntohll(x)
+#endif
+
+/* Add debugging later */
+#define k5_check_error(x) (x)
+
+struct k5_ipc_stream {
+    char *data;
+    uint64_t size;
+    uint64_t max_size;
+};
+
+const struct k5_ipc_stream k5_ipc_stream_initializer = { NULL, 0, 0 };
+
+#define K5_IPC_STREAM_SIZE_INCREMENT 128
+
+/* ------------------------------------------------------------------------ */
+
+static uint32_t k5_ipc_stream_reallocate (k5_ipc_stream io_stream,
+                                          uint64_t      in_new_size)
+{
+    int32_t err = 0;
+    uint64_t new_max_size = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        uint64_t old_max_size = io_stream->max_size;
+        new_max_size = io_stream->max_size;
+        
+        if (in_new_size > old_max_size) {
+            /* Expand the stream */
+            while (in_new_size > new_max_size) {
+                new_max_size += K5_IPC_STREAM_SIZE_INCREMENT;
+            }
+            
+            
+        } else if ((in_new_size + K5_IPC_STREAM_SIZE_INCREMENT) < old_max_size) {
+            /* Shrink the array, but never drop below K5_IPC_STREAM_SIZE_INCREMENT */
+            while ((in_new_size + K5_IPC_STREAM_SIZE_INCREMENT) < new_max_size &&
+                   (new_max_size > K5_IPC_STREAM_SIZE_INCREMENT)) {
+                new_max_size -= K5_IPC_STREAM_SIZE_INCREMENT;
+            }
+        }
+    }
+    
+    if (!err && new_max_size != io_stream->max_size) {
+        char *data = io_stream->data;
+        
+        if (!data) {
+            data = malloc (new_max_size * sizeof (*data));
+        } else {
+            data = realloc (data, new_max_size * sizeof (*data));
+        }
+        
+        if (data) { 
+            io_stream->data = data;
+            io_stream->max_size = new_max_size;
+        } else {
+            err = k5_check_error (ENOMEM); 
+        }
+    }
+    
+    return k5_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+int32_t k5_ipc_stream_new (k5_ipc_stream *out_stream)
+{
+    int32_t err = 0;
+    k5_ipc_stream stream = NULL;
+    
+    if (!out_stream) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        stream = malloc (sizeof (*stream));
+        if (stream) { 
+            *stream = k5_ipc_stream_initializer;
+        } else {
+            err = k5_check_error (ENOMEM); 
+        }
+    }
+    
+    if (!err) {
+        *out_stream = stream;
+        stream = NULL;
+    }
+    
+    k5_ipc_stream_release (stream);
+    
+    return k5_check_error (err);    
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_release (k5_ipc_stream io_stream)
+{      
+    int32_t err = 0;
+    
+    if (!err && io_stream) {
+        free (io_stream->data);
+        free (io_stream);
+    }
+    
+    return err;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint64_t k5_ipc_stream_size (k5_ipc_stream in_stream)
+{
+    return in_stream ? in_stream->size : 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+const char *k5_ipc_stream_data (k5_ipc_stream in_stream)
+{
+    return in_stream ? in_stream->data : NULL;
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read (k5_ipc_stream  io_stream, 
+                             void         *io_data, 
+                             uint64_t     in_size)
+{
+    int32_t err = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    if (!io_data  ) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        if (in_size > io_stream->size) { 
+            err = k5_check_error (EINVAL); 
+        }
+    }
+    
+    if (!err) {
+        memcpy (io_data, io_stream->data, in_size);
+        memmove (io_stream->data, &io_stream->data[in_size], 
+                 io_stream->size - in_size);
+        
+        err = k5_ipc_stream_reallocate (io_stream, io_stream->size - in_size);
+        
+        if (!err) {
+            io_stream->size -= in_size;
+        }
+    }
+    
+    return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write (k5_ipc_stream  io_stream,
+                              const void   *in_data, 
+                              uint64_t     in_size)
+{
+    int32_t err = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    if (!in_data  ) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        /* Security check: Do not let the caller overflow the length */
+        if (in_size > (UINT64_MAX - io_stream->size)) {
+            err = k5_check_error (EINVAL);
+        }
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_reallocate (io_stream, io_stream->size + in_size);
+    }
+    
+    if (!err) {
+        memcpy (&io_stream->data[io_stream->size], in_data, in_size);
+        io_stream->size += in_size;
+    }
+    
+    return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+void k5_ipc_stream_free_string (char *in_string)
+{
+    free (in_string);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_string (k5_ipc_stream   io_stream, 
+                                    char         **out_string)
+{
+    int32_t err = 0;
+    uint32_t length = 0;
+    char *string = NULL;
+    
+    if (!io_stream ) { err = k5_check_error (EINVAL); }
+    if (!out_string) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_uint32 (io_stream, &length);
+    }
+    
+    if (!err) {
+        string = malloc (length);
+        if (!string) { err = k5_check_error (ENOMEM); }
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, string, length);
+    }
+    
+    if (!err) {
+        *out_string = string;
+        string = NULL;
+    }
+    
+    free (string);
+    
+    return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_string (k5_ipc_stream  io_stream, 
+                                     const char    *in_string)
+{
+    int32_t err = 0;
+    uint32_t length = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    if (!in_string) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        length = strlen (in_string) + 1;
+        
+        err = k5_ipc_stream_write_uint32 (io_stream, length);
+    }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, in_string, length);
+    }
+    
+    return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_int32 (k5_ipc_stream  io_stream, 
+                                   int32_t       *out_int32)
+{
+    int32_t err = 0;
+    int32_t int32 = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    if (!out_int32) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, &int32, sizeof (int32));
+    }
+    
+    if (!err) {
+        *out_int32 = ntohl (int32);
+    }
+    
+    return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_int32 (k5_ipc_stream io_stream, 
+                                    int32_t       in_int32)
+{
+    int32_t err = 0;
+    int32_t int32 = htonl (in_int32);
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, &int32, sizeof (int32));
+    }
+    
+    return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_uint32 (k5_ipc_stream  io_stream, 
+                                    uint32_t      *out_uint32)
+{
+    int32_t err = 0;
+    uint32_t uint32 = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    if (!out_uint32) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, &uint32, sizeof (uint32));
+    }
+    
+    if (!err) {
+        *out_uint32 = ntohl (uint32);
+    }
+    
+    return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_uint32 (k5_ipc_stream io_stream, 
+                                     uint32_t      in_uint32)
+{
+    int32_t err = 0;
+    int32_t uint32 = htonl (in_uint32);
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, &uint32, sizeof (uint32));
+    }
+    
+    return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_int64 (k5_ipc_stream  io_stream, 
+                                   int64_t       *out_int64)
+{
+    int32_t err = 0;
+    uint64_t int64 = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    if (!out_int64) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, &int64, sizeof (int64));
+    }
+    
+    if (!err) {
+        *out_int64 = ntohll (int64);
+    }
+    
+    return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_int64 (k5_ipc_stream io_stream, 
+                                    int64_t     in_int64)
+{
+    int32_t err = 0;
+    int64_t int64 = htonll (in_int64);
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, &int64, sizeof (int64));
+    }
+    
+    return k5_check_error (err);
+}
+
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_uint64 (k5_ipc_stream  io_stream, 
+                                    uint64_t     *out_uint64)
+{
+    int32_t err = 0;
+    uint64_t uint64 = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    if (!out_uint64) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read (io_stream, &uint64, sizeof (uint64));
+    }
+    
+    if (!err) {
+        *out_uint64 = ntohll (uint64);
+    }
+    
+    return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_uint64 (k5_ipc_stream io_stream, 
+                                     uint64_t     in_uint64)
+{
+    int32_t err = 0;
+    int64_t uint64 = htonll (in_uint64);
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write (io_stream, &uint64, sizeof (uint64));
+    }
+    
+    return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_time (k5_ipc_stream  io_stream, 
+                                  time_t        *out_time)
+{
+    int32_t err = 0;
+    int64_t t = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    if (!out_time ) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_read_int64 (io_stream, &t);
+    }
+    
+    if (!err) {
+        *out_time = t;
+    }
+    
+    return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_time (k5_ipc_stream io_stream, 
+                                   time_t        in_time)
+{
+    int32_t err = 0;
+    
+    if (!io_stream) { err = k5_check_error (EINVAL); }
+    
+    if (!err) {
+        err = k5_ipc_stream_write_int64 (io_stream, in_time);
+    }
+    
+    return k5_check_error (err);
+}