/*
 * This program prints out log messages from the kernel server named 
 * "mydriver".
 */
 
#import <mach.h>
#import <cthreads.h>
#import <kernserv/kern_loader_reply_handler.h>
#import <syslog.h>
#import <stdio.h>

void listen(port_name_t port);

kern_return_t log_data(void *arg, printf_data_t log_data, unsigned int log_data_count);

port_name_t server_com_port, kl_port, reply_port;

main()
{
    kern_return_t   r;
    port_name_t kern_port, mydriver_port;

    /* Allocate a port for reply messages from kern_loader. */
    r = port_allocate(task_self(), &reply_port);
    if (r != KERN_SUCCESS) {
        mach_error("Can't allocate reply port", r);
        exit(1);
    }

    /* Find kern_loader's port. */
    r = kern_loader_look_up(&kl_port);
    if (r != KERN_SUCCESS) {
        mach_error("Can't find kernel loader", r);
        exit(1);
    }

    /* Get the server's communication port. */
    r = task_by_unix_pid(task_self(), 0, &kern_port);
    if (r != KERN_SUCCESS) {
        mach_error("Error looking up kernel's port", r);
        exit(1);
    }
    r = kern_loader_server_com_port(kl_port, kern_port, "mydriver",
        &server_com_port);
    if (r != KERN_SUCCESS) {
        kern_loader_error("Error looking up server com port", r);
        exit(1);
    }
        
    /* Set the log level so we'll get log messages. */
    r = kern_loader_log_level(kl_port, server_com_port, LOG_NOTICE);
    if (r != KERN_SUCCESS) {
        kern_loader_error("Can't change log level", r);
        exit(1);
    }
    
    /* Wait for the log level to change. */
    printf("Waiting for the log level to change before calling mydriver_do_log()...\n");
    sleep(5);   
        
    /* Look up the advertised port of mydriver. */
    r = netname_look_up(name_server_port, "", "mydriver0", &mydriver_port);
    if (r != KERN_SUCCESS) {
        mach_error("Can't find mydriver's advertised port", r);
        exit(1);
    }
    
    printf("Calling mydriver_do_log().\n");
    /* Make the driver log a message. */
    r = mydriver_do_log(mydriver_port);
    if (r != KERN_SUCCESS) {
        mach_error("Error calling mydriver_do_log", r);
        exit(1);
    }
    
    printf("Calling kern_loader_get_log().\n");
    /* Put this message into the message log. */
    r = kern_loader_get_log(kl_port, server_com_port, reply_port);
    if (r != KERN_SUCCESS) {
        kern_loader_error("Error calling kern_loader_get_log", r);
        exit(1);
    }
    
    listen(reply_port);
}

kern_loader_reply_t kern_loader_reply = {
    0,          /* argument to pass to function */
    0,          /* timeout for rpc return msg_send */
    0,          /* string function */
    0,          /* ping function */
    log_data    /* log_data function */
};

#define KERN_LOADER_REPLY_INMSG_SIZE (MACH_MSG_SIZE_MAX)

void listen(port_name_t port)
{
    char          msg_buf[KERN_LOADER_REPLY_INMSG_SIZE];
    msg_header_t *msg = (msg_header_t *)msg_buf;
    kern_return_t r;

    /* Receive the next message in the queue. */
    msg->msg_size = KERN_LOADER_REPLY_INMSG_SIZE;
    msg->msg_local_port = port;
    r = msg_receive(msg, MSG_OPTION_NONE, 0);

    printf("Received a message on the reply port.\n");
    if (r != KERN_SUCCESS) {
        mach_error("listen msg_receive", r);
        exit(1);
    }
            
    /* Handle the message we just received. */
    printf("Calling kern_loader_reply_handler().\n");
    kern_loader_reply_handler(msg, &kern_loader_reply);
}
    

kern_return_t log_data(void *arg, printf_data_t log_data, unsigned int log_data_count)
{
    kern_return_t r;
        
    /* Print the string we were passed, with our own special prefix. */
    printf("log_data: %s\n", log_data);
    vm_deallocate(task_self(), (vm_address_t)log_data, 
        log_data_count*sizeof(*log_data));

#ifdef NOTDEF
    /* 
     * If this were a real program, we'd probably want to request
     * the next log message. 
     */
    r = kern_loader_get_log(kl_port, server_com_port, reply_port);
    if (r != KERN_SUCCESS) {
        kern_loader_error("log_data:  Error calling kern_loader_get_log", r);
        exit(1);
    }
#endif

    return KERN_SUCCESS;
}

/*** log.c                            -- 2003-08-25 05:07:48 -- pascal   ***/
