Beispiel #1
0
/**
 * Handle system calls. Interrupts are enabled when this function is
 * called.
 *
 * @param user_context The userland context (CPU registers as they
 * where when system call instruction was called in userland)
 */
void syscall_handle(context_t *user_context)
{
    /* When a syscall is executed in userland, register a0 contains
     * the number of the syscall. Registers a1, a2 and a3 contain the
     * arguments of the syscall. The userland code expects that after
     * returning from the syscall instruction the return value of the
     * syscall is found in register v0. Before entering this function
     * the userland context has been saved to user_context and after
     * returning from this function the userland context will be
     * restored from user_context.
     */

    int retval;

    switch(user_context->cpu_regs[MIPS_REGISTER_A0]) {
    case SYSCALL_HALT:
        halt_kernel();
        break;
    case SYSCALL_EXEC:
        retval = (int) process_spawn((char*) user_context->cpu_regs[MIPS_REGISTER_A1]);
        user_context->cpu_regs[MIPS_REGISTER_V0] = retval;
        break;
    case SYSCALL_EXIT:
        /* Resources are cleaned up in process_finish(...) */
        process_finish(user_context->cpu_regs[MIPS_REGISTER_A1]);
        break;
    case SYSCALL_JOIN:
        retval = process_join(user_context->cpu_regs[MIPS_REGISTER_A1]);
        user_context->cpu_regs[MIPS_REGISTER_V0] = retval;
        break;
    case SYSCALL_READ:
        {
            int fhandle = user_context->cpu_regs[MIPS_REGISTER_A1];
            int buffer = user_context->cpu_regs[MIPS_REGISTER_A2];
            int length = user_context->cpu_regs[MIPS_REGISTER_A3];

            int retval = syscall_read(fhandle, (void *)buffer, length);
            user_context->cpu_regs[MIPS_REGISTER_V0] = retval;
        }
        break;
    case SYSCALL_WRITE:
        {
            int fhandle = user_context->cpu_regs[MIPS_REGISTER_A1];
            int buffer = user_context->cpu_regs[MIPS_REGISTER_A2];
            int length = user_context->cpu_regs[MIPS_REGISTER_A3];

            int retval = syscall_write(fhandle, (void *)buffer, length);
            user_context->cpu_regs[MIPS_REGISTER_V0] = retval;
        }
        break;
    default:
        KERNEL_PANIC("Unhandled system call\n");
    }

    /* Move to next instruction after system call */
    user_context->pc += 4;
}
Beispiel #2
0
/**
 * Handle system calls. Interrupts are enabled when this function is
 * called.
 *
 * @param user_context The userland context (CPU registers as they
 * where when system call instruction was called in userland)
 */
void syscall_handle(context_t *user_context)
{
    int retval;

    /* When a syscall is executed in userland, register a0 contains
     * the number of the syscall. Registers a1, a2 and a3 contain the
     * arguments of the syscall. The userland code expects that after
     * returning from the syscall instruction the return value of the
     * syscall is found in register v0. Before entering this function
     * the userland context has been saved to user_context and after
     * returning from this function the userland context will be
     * restored from user_context.
     */
    switch(user_context->cpu_regs[MIPS_REGISTER_A0]) {
    case SYSCALL_HALT:
        halt_kernel();
        break;
    case SYSCALL_READ:
	retval = read_file((int)user_context->cpu_regs[MIPS_REGISTER_A1], 
			   (void *)user_context->cpu_regs[MIPS_REGISTER_A2], 
			   (int)user_context->cpu_regs[MIPS_REGISTER_A3]);
	user_context->cpu_regs[MIPS_REGISTER_V0] = retval;
	break;
    case SYSCALL_WRITE:
	retval = write_file((int)user_context->cpu_regs[MIPS_REGISTER_A1], 
			   (void *)user_context->cpu_regs[MIPS_REGISTER_A2], 
			   (int)user_context->cpu_regs[MIPS_REGISTER_A3]);
	user_context->cpu_regs[MIPS_REGISTER_V0] = retval;
	break;
    case SYSCALL_EXIT:
	process_finish(user_context->cpu_regs[MIPS_REGISTER_A1]);
	break;
    case SYSCALL_EXEC:
	retval = exec((char *)user_context->cpu_regs[MIPS_REGISTER_A1]);
	user_context->cpu_regs[MIPS_REGISTER_V0] = retval;
	break;
    case SYSCALL_JOIN:
	retval = join((int)user_context->cpu_regs[MIPS_REGISTER_A1]);
	user_context->cpu_regs[MIPS_REGISTER_V0] = retval;
	break;
    default: 
        KERNEL_PANIC("Unhandled system call\n");
    }

    /* Move to next instruction after system call */
    user_context->pc += 4;
}
Beispiel #3
0
static void hash_command_handler(void *cmd_body,
				size_t cmd_size,
				size_t *response_size)
{
	int mode;
	int hash_mode;
	int handle;
	uint16_t text_len;
	uint8_t *cmd;
	size_t response_room = *response_size;
	TPM_ALG_ID alg;

	cmd = cmd_body;

	/*
	 * Empty response is sent as a success indication when the digest is
	 * not yet expected (i.e. in response to 'start' and 'cont' commands,
	 * as defined below).
	 *
	 * Single byte responses indicate errors, test successes are
	 * communicated as responses of the size of the appropriate digests.
	 */
	*response_size = 0;

	/*
	 * Command structure, shared out of band with the test driver running
	 * on the host:
	 *
	 * field     |    size  |                  note
	 * ===================================================================
	 * mode      |    1     | 0 - start, 1 - cont., 2 - finish, 3 - single
	 * hash_mode |    1     | 0 - sha1, 1 - sha256
	 * handle    |    1     | seassion handle, ignored in 'single' mode
	 * text_len  |    2     | size of the text to process, big endian
	 * text      | text_len | text to hash
	 */

	mode = *cmd++;
	hash_mode = *cmd++;
	handle = *cmd++;
	text_len = *cmd++;
	text_len = text_len * 256 + *cmd++;

	switch (hash_mode) {
	case 0:
		alg = TPM_ALG_SHA1;
		break;
	case 1:
		alg = TPM_ALG_SHA256;
		break;

	default:
		return;
	}

	switch (mode) {
	case 0: /* Start a new hash context. */
		process_start(alg, handle, cmd_body, response_size);
		if (*response_size)
			break; /* Something went wrong. */
		process_continue(handle, cmd, text_len,
				 cmd_body, response_size);
		break;

	case 1:
		process_continue(handle, cmd, text_len,
				 cmd_body, response_size);
		break;

	case 2:
		process_continue(handle, cmd, text_len,
				 cmd_body, response_size);
		if (*response_size)
			break;  /* Something went wrong. */

		process_finish(handle, cmd_body, response_size);
		CPRINTF("%s:%d response size %d\n", __func__, __LINE__,
			*response_size);
		break;

	case 3: /* Process a buffer in a single shot. */
		if (!text_len)
			break;
		/*
		 * Error responses are just 1 byte in size, valid responses
		 * are of various hash sizes.
		 */
		*response_size = _cpri__HashBlock(alg, text_len,
						  cmd, response_room, cmd_body);
		CPRINTF("%s:%d response size %d\n", __func__,
			__LINE__, *response_size);
		break;
	default:
		break;
	}
}
Beispiel #4
0
int main(void) {

	BYTE flgRestart = FALSE;					// if TRUE, restart main loop
	
	struct ifreq interface;						// ioctls to configure network interface
	
	struct sockaddr_in myinterface;				// Interface address
	struct sockaddr_in mynetmask;				// Interface netmask
	struct sockaddr_in mybroadcast;				// Interface broadcast address
	
	int server_sockfd;							// Server socket
	struct sockaddr_in server_address;			// Server address and port
	int heartbeat_sockfd;						// Heartbeat socket
	struct sockaddr_in heartbeat_addr;			// Heartbeat address and port
	int tx_sockfd;								// Tx socket
	int optval, optlen;							// Vars for socket options
		
	time_t timenow;								// Current time
	time_t xaptick;								// Last tick
	time_t heartbeattick;						// Time for next hearbeat tick
	
	char heartbeat_msg[1500];					// Buffer for heartbeat messages
	char buff[1500];							// Buffer for messages
	
	fd_set rdfs;								// Vars for attent to clients
	struct timeval tv;
	struct sockaddr_in client_address;			// 	client address and port
	socklen_t client_len;
		
	int i; 										// Auxiliary variable

	// Header verbage
	//printf("\nHomected xAP-Hub Connector\n");
	//printf("Copyright (C) Jose Luis Galindo, 2012\n");
	
	// Create shared memory areas
	if (!hubSharedMemSetup()) {
		syslog(LOG_ERR, "main: Error allocating shared resources");
		logError("main: Error allocating shared resources");
	}
	
	// Initialize application
	init();
	logInit(LOG_EVENTS_FILE, LOG_ERRORS_FILE);
	LIBXML_TEST_VERSION
	
	// Create the process
	process_init("xap-hub", pid_filepath);
	
	while(process_state == PROC_RUNNING) {
	
		// Load xml file with general settings
		if (parseXmlSettings(SETTINGS_FILE) > 0) {
			syslog(LOG_ERR, "main: Failed to parse xml settings document, default values loaded");
			logError("main: Failed to parse xml settings document, default values loaded");
			if (saveXmlSettings(SETTINGS_FILE) > 0) {
				syslog(LOG_ERR, "main: Error saving settings file");
				logError("main: Error saving settings file");
			}
		}

		// Use the server socket to get interface properties
		server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
		if (server_sockfd == -1) {
			syslog(LOG_ERR, "main: Error trying to get interface properties");
			logError("main: Error trying to get interface properties");
			unlink(pid_filepath);
			exit(EXIT_FAILURE);
		}

		// Set options for the socket
		optval=1;
		optlen=sizeof(int);
		if (setsockopt(server_sockfd, SOL_SOCKET, SO_BROADCAST, (char*)&optval, optlen)) {
			syslog(LOG_ERR, "main: Error trying to get interface properties");
			logError("main: Error trying to get interface properties");
			unlink(pid_filepath);
			exit(EXIT_FAILURE);
		}
		
		optval=1;
		optlen=sizeof(int);
		if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, optlen)) {
			syslog(LOG_ERR, "main: Error trying to get interface properties");
			logError("main: Error trying to get interface properties");
			unlink(pid_filepath);
			exit(EXIT_FAILURE);
		}

		// Query the low-level capabilities of the network interface to get address and netmask
		memset((char*)&interface, sizeof(interface),0);
		strcpy(interface.ifr_name, hubConfig->interfacename);
		
		// Get the interface address
		interface.ifr_addr.sa_family = AF_INET; 
		if (ioctl(server_sockfd, SIOCGIFADDR, &interface) != 0) {
			syslog(LOG_ERR, "main: Could not determine IP address for interface %s", hubConfig->interfacename);
			logError("main: Could not determine IP address for interface %s", hubConfig->interfacename);
			unlink(pid_filepath);
			exit(EXIT_FAILURE);
		}
		myinterface.sin_addr.s_addr = ((struct sockaddr_in*)&interface.ifr_broadaddr)->sin_addr.s_addr;
		//printf("%s: address %s\n", interface.ifr_name, inet_ntoa(((struct sockaddr_in*)&interface.ifr_addr)->sin_addr));
		logEvent(TRUE, "main: %s: address %s", interface.ifr_name, inet_ntoa(((struct sockaddr_in*)&interface.ifr_addr)->sin_addr));
		
		// Get the interface netmask
		interface.ifr_broadaddr.sa_family = AF_INET; 
		if (ioctl(server_sockfd, SIOCGIFNETMASK, &interface) != 0) {
			syslog(LOG_ERR, "Unable to determine netmask for interface %s", hubConfig->interfacename);
			logError("main: Unable to determine netmask for interface %s", hubConfig->interfacename);
			unlink(pid_filepath);
			exit(EXIT_FAILURE);
		}
		mynetmask.sin_addr.s_addr = ((struct sockaddr_in*)&interface.ifr_broadaddr)->sin_addr.s_addr;
		//printf("%s: netmask %s\n", interface.ifr_name, inet_ntoa(((struct sockaddr_in*)&interface.ifr_netmask)->sin_addr));
		logEvent(TRUE, "main: %s: netmask %s", interface.ifr_name, inet_ntoa(((struct sockaddr_in*)&interface.ifr_netmask)->sin_addr));
		
		// Determine the interface broadcast address 
		long int inverted_netmask;
		inverted_netmask=~mynetmask.sin_addr.s_addr;
		mybroadcast.sin_addr.s_addr = inverted_netmask | myinterface.sin_addr.s_addr;
		//printf("%s: broadcast %s\n", interface.ifr_name, inet_ntoa(mybroadcast.sin_addr));
		logEvent(TRUE, "main: %s: broadcast %s", interface.ifr_name, inet_ntoa(mybroadcast.sin_addr));

		// Set the server socket
		server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
		
		// Set server address and port
		memset((char *) &server_address, 0, sizeof(server_address));
		server_address.sin_family = AF_INET; 	
		server_address.sin_addr.s_addr = htonl(INADDR_ANY);		// Receive from any address
		server_address.sin_port = htons(hubConfig->xap_port);	// on this port (Default 3639)
		
		// Bind the server socket with the server IP address and port
		fcntl(server_sockfd, F_SETFL, O_NONBLOCK);
		if (bind(server_sockfd, (struct sockaddr*)&server_address, sizeof(server_address)) !=0 ) {
			// if fails then we can assume that a hub is active on this host
			syslog(LOG_ERR, "main: Port %d is in use", hubConfig->xap_port);
			syslog(LOG_ERR, "main: Assuming other local hub is active on this host");
			logError("main: Port %d is in use", hubConfig->xap_port);
			logError("main: Assuming other local hub is active on this host");
			unlink(pid_filepath);
			exit(EXIT_FAILURE);
		}
		//printf("Listening for messages on port %d\n", g_xap_port);
		logEvent(TRUE, "main: Listening for messages on port %d", hubConfig->xap_port);

		// Set the server socket to listen
		listen(server_sockfd, MAX_QUEUE_BACKLOG);
		
		// Set up the Tx socket
		tx_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

		// Set up the heartbeat socket, on which we tell the world we are alive and well
		heartbeat_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
		if (heartbeat_sockfd == -1) {
			syslog(LOG_ERR, "main: Heartbeat socket cannot be created");
			logError("main: Heartbeat socket cannot be created");
			unlink(pid_filepath);
			exit(EXIT_FAILURE);
		}
		
		// Set options for the heartbeat socket
		optval = 1;
		optlen = sizeof(int);
		if (setsockopt(heartbeat_sockfd, SOL_SOCKET, SO_BROADCAST, (char*)&optval, optlen)) {
			syslog(LOG_ERR, "main: Unable to set heartbeat socket options");
			logError("main: Unable to set heartbeat socket options");
			unlink(pid_filepath);
			exit(EXIT_FAILURE);
		}
		
		// Set up heartbeat address and port
		memset((char *) &heartbeat_addr, 0, sizeof(heartbeat_addr));
		heartbeat_addr.sin_family = AF_INET;
		heartbeat_addr.sin_port = htons(hubConfig->xap_port);
		heartbeat_addr.sin_addr.s_addr = mybroadcast.sin_addr.s_addr;
		//printf("Set heartbeat broadcast on %s:%d\n", inet_ntoa(heartbeat_addr.sin_addr), g_xap_port);
		logEvent(TRUE, "main: Set heartbeat broadcast on %s:%d", inet_ntoa(heartbeat_addr.sin_addr), hubConfig->xap_port);

		xaptick = time((time_t*)0);
		heartbeattick = time((time_t*)0); // force heartbeat on startup
		//printf("Running...\n");
		logEvent(TRUE, "main: Running...");

		// Parse heartbeat messages received on broadcast interface
		// If they originated from this host, add the port number to the list of known ports
		// Otherwise ignore.
		// If ordinary header then pass to all known listeners
		while (!flgRestart && (process_state == PROC_RUNNING)) {

			// Get current time
			timenow = time((time_t*)0);
			
			// Hub tick, check for alive devices
			if (timenow - xaptick >= 1) {
				xaphub_tick(timenow - xaptick);
				xaptick = timenow;
			}
			
			// Heartbeat tick
			if (timenow >= heartbeattick) {
				//printf("Outgoing heartbeat tick %d\n",(int)timenow);
				logEvent(TRUE, "main: Outgoing heartbeat tick %d",(int)timenow);
				
				// Create the heartbeat message
				xaphub_build_heartbeat(heartbeat_msg);
				//printf("%s", heartbeat_msg);

				// Send heartbeat to all external listeners
				sendto(heartbeat_sockfd, heartbeat_msg, strlen(heartbeat_msg), 0, (struct sockaddr *) &heartbeat_addr, sizeof(heartbeat_addr));

				// Send heartbeat to all locally connected apps
				xaphub_relay(tx_sockfd, heartbeat_msg);
				
				// Set next tick
				heartbeattick = timenow + hubConfig->xap_hbeat;
			}
			
			// Prepare to attent to the clients
			FD_ZERO(&rdfs);
			FD_SET(server_sockfd, &rdfs);
			tv.tv_sec = hubConfig->xap_hbeat;
			tv.tv_usec = 0;
			select(server_sockfd + 1, &rdfs, NULL, NULL, &tv);
			
			// Select either timed out, or there was data - go look for it.
			client_len = sizeof(struct sockaddr);
			i = recvfrom(server_sockfd, buff, sizeof(buff), 0, (struct sockaddr*) &client_address, &client_len);

			// Check if a message was received
			if (i != -1) {
				buff[i]='\0';	// Add NULL to the end of message
			
				//printf("Message from client %s:%d\n", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));
				logEvent(TRUE, "main: Message from client %s:%d", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));
				
				// Message from my interface
				if (client_address.sin_addr.s_addr == myinterface.sin_addr.s_addr) {
					//printf("Message originated from my interface\n");

					// If the message received is a heartbeat message, add the client to the relay list
					xap_handler(buff);
						
					// Relay the message to all local apps, the originator will see his own message
					xaphub_relay(tx_sockfd, buff);
				}
				// Message from local client received
				else if (client_address.sin_addr.s_addr == inet_addr("127.0.0.1")) {
					//printf("Message from local client\n");
				}
				// Remote message
				else {
					//printf("Message originated remotely, relay\n");

					// Relay the message to all local apps
					xaphub_relay(tx_sockfd, buff);
				}
				
				// Clear message
				memset(buff, 0, sizeof(buff));
			}
			
			// Check if has to save settings
			if (hubConfig->saveFlag) {
				hubConfig->saveFlag = FALSE;				// Reset flag
				if (saveXmlSettings(SETTINGS_FILE) > 0) {
					syslog(LOG_ERR, "main: Error saving settings file");
					logError("main: Error saving settings file");
				}
			}
			
			// Check if has to restart
			if (hubConfig->restartFlag) {
				hubConfig->restartFlag = FALSE;				// Reset flag
				flgRestart = TRUE;
			}
		}
		
		// Restore flgRestart
		flgRestart = FALSE;
		
		// Save xml settings
		if (saveXmlSettings(SETTINGS_FILE) > 0) {
			syslog(LOG_ERR, "main: Error saving settings file");
			logError("main: Error saving settings file");
		}
			
		// Build a xAP shutdown message
		xaphub_build_heartbeat_shutdown(heartbeat_msg);
		
		// Send shutdown heartbeat message to all external listeners
		sendto(heartbeat_sockfd, heartbeat_msg, strlen(heartbeat_msg), 0, (struct sockaddr *) &heartbeat_addr, sizeof(heartbeat_addr));
		
		// Send shutdown heartbeat message to all locally connected apps
		xaphub_relay(tx_sockfd, heartbeat_msg);

		// Close xAP communications
		close(server_sockfd);					// Close Server socket
		close(heartbeat_sockfd);				// Close Heartbeat socket
		close(tx_sockfd);						// Close Tx socket
	}
	
	// Close shared memory areas
	hubSharedMemClose();
		
	// Destroy the process
	process_finish();
	
	return 0;
}
Beispiel #5
0
void syscall_exit(int retval){
    process_finish(retval);
}
void
run_process(void *ptr, unsigned long num)
{
    (void)num;
    int result;
	vaddr_t entrypoint, stackptr;
    
    // extract and free passed-in context
    struct new_process_context *ctxt = (struct new_process_context *)ptr;
    struct process *proc = ctxt->proc;
    struct vnode *v = ctxt->executable;
    int nargs = ctxt->nargs;
    char **args = ctxt->args;
    kfree(ctxt);
    
    // attach process to thread
    curthread->t_proc = proc;
    proc->ps_thread = curthread;
    
	// Activate address space
	as_activate(proc->ps_addrspace);
    
	// Load the executable
	result = load_elf(v, &entrypoint);
	if (result) {
		vfs_close(v);
        kprintf("runprogram failed: %s\n", strerror(result));
        // alert the kernel menu that the process aborted
        process_finish(proc, _MKWAIT_SIG(SIGABRT));
		return;
	}
    
	// Done with the file now
	vfs_close(v);
    
	// Define the user stack in the address space
	result = as_define_stack(proc->ps_addrspace, &stackptr);
	if (result) {
        kprintf("runprogram failed: %s\n", strerror(result));
        // alert the kernel menu that the process aborted
        process_finish(proc, _MKWAIT_SIG(SIGABRT));
		return;
	}
	
	// Copy out arguments
	userptr_t uargv[nargs + 1];
    for (int i = 0; i < nargs; i++)
    {
        int aligned_length = WORD_ALIGN(strlen(args[i]) + 1);
        stackptr -= aligned_length;
        uargv[i] = (userptr_t)stackptr;
        size_t arg_len;
        result = copyoutstr(args[i], uargv[i], strlen(args[i]) + 1, &arg_len);
        if (result) {
            kprintf("runprogram failed: %s\n", strerror(result));
            // alert the kernel menu that the process aborted
            process_finish(proc, _MKWAIT_SIG(SIGABRT));
            return;
        }
    }
    uargv[nargs] =(userptr_t)NULL;
    
    // Copy out the argv array itself
	stackptr -= (nargs + 1) * sizeof(userptr_t);
	result = copyout(uargv, (userptr_t)stackptr,
                     (nargs + 1) * sizeof(userptr_t));
	if (result) {
        kprintf("runprogram failed: %s\n", strerror(result));
        // alert the kernel menu that the process aborted
        process_finish(proc, _MKWAIT_SIG(SIGABRT));
	    return;
	}
    
    enter_new_process(nargs, (userptr_t)stackptr, stackptr, entrypoint);
    
    // enter_new_process() does not return
	panic("enter_new_process returned\n");
}
int main(void) {

    BYTE flgRestart = FALSE;					// if TRUE, restart main loop

    time_t timenow;								// Current time
    time_t cosmtick;							// Time for next upload
    time_t newvalue;

    t_UPDATER_MSG updater_msg;					// Messsage for updater

    // Header verbage
#ifdef DEBUG_APP
    printf("\nHomected xAP-Cosm Connector (Updater)\n");
    printf("Copyright (C) Jose Luis Galindo, 2012\n");
#endif

    // Create shared memory areas
    if (!cosmSharedMemSetup()) {
#ifdef DEBUG_APP
        printf("Error allocating shared resources\n");
#endif
        logError("main: Error allocating shared resources");
        unlink(pid_filepath);
        exit(EXIT_FAILURE);
    }

    // Initialize application
    purge_update_list();
    logInit(LOG_EVENTS_FILE, LOG_ERRORS_FILE);
    LIBXML_TEST_VERSION

    // Connect to the message queue to communicate with xap-cosm
    if ((g_msg_queue = msgget(COSM_MSGQUEUE, 0644)) == -1) {
#ifdef DEBUG_APP
        printf("Error connecting to message queue\n");
#endif
        logError("main: Error connecting to message queue");
        unlink(pid_filepath);
        exit(EXIT_FAILURE);
    }

    // Create the process
#ifndef DEBUG_APP
    process_init("xap-cosm-updater", pid_filepath);
#endif

    while(process_state == PROC_RUNNING) {

#ifdef DEBUG_APP
        printf("Running...\n");
#endif
        logEvent(TRUE, "updater: Running...");

        while (!flgRestart && (process_state == PROC_RUNNING)) {

            // Wait for application enabled
            if (!cosmConfig->enabled) {
#ifdef DEBUG_APP
                printf("Device is not enabled, wait\n");
#endif
                logEvent(TRUE, "main: Device is not enabled, wait");
                while(!cosmConfig->enabled)
                    sleep(1);
            }

            // Get current time
            timenow = time((time_t*)0);

            // Wait for an incomining message
            if (msgrcv(g_msg_queue, (struct msgbuf *)&updater_msg, sizeof(updater_msg.ds)+sizeof(updater_msg.timestamp)+sizeof(updater_msg.curr_value), COSM_MSGQUEUE_MSG_ID,  IPC_NOWAIT) != -1) {
                // Add message data to update list
                g_update_list[g_update_list_count].sent = FALSE;
                g_update_list[g_update_list_count].ds = updater_msg.ds;
                g_update_list[g_update_list_count].timestamp = updater_msg.timestamp;
                strcpy(g_update_list[g_update_list_count].curr_value, updater_msg.curr_value);
#ifdef DEBUG_APP
                printf("ds:%d added value %s to Cosm update list queue (pos=%d)\n", g_update_list[g_update_list_count].ds, g_update_list[g_update_list_count].curr_value, g_update_list_count);
#endif
                logEvent(TRUE, "updater: (ds:%d) added value %s to Cosm update list queue (pos=%d)", g_update_list[g_update_list_count].ds, g_update_list[g_update_list_count].curr_value, g_update_list_count);
                g_update_list_count++;
            }
            usleep(10000); //convert to microseconds

            // Cosm tick
            if (timenow >= cosmtick) {
#ifdef DEBUG_APP
                printf("Outgoing cosm tick %d\n",(int)timenow);
#endif
                logEvent(TRUE, "updater: Outgoing cosm tick %d",(int)timenow);

                // Upload update list to cosm
                send_list_to_cosm();

                // Clear update list
                purge_update_list();

                // Set next tick
                cosmtick = timenow + cosmConfig->updatef;
            }

            // Check if has to restart
            if (cosmConfig->restartFlag) {
                cosmConfig->restartFlag = FALSE;			// Reset flag
                flgRestart = TRUE;
            }
        }

        // Restore flgRestart
        flgRestart = FALSE;

    }

    // Close shared memory areas
    cosmSharedMemClose();

    // Destroy the process
#ifndef DEBUG_APP
    process_finish();
#endif

    return 0;
}