Ejemplo n.º 1
0
/* Process incoming commands */
void cmd_process_msg()
{
	struct pm_msg_generic msg;
	INT32 task_id, retval;
	struct pm_task *tsk;
	struct pm_thread *thr;
	UINT16 destroy_task_id;
	struct pending_command *cmd = NULL, *ocmd = NULL;
    struct pm_msg_phymem_response pres;
				
	/*
	For some commands like FMAP, we should only process one command at the same time for each task. 
	*/

	/* Add commands to the queue. */
	while(get_msg_count(PMAN_COMMAND_PORT) > 0) 
	{
		if(shutting_down)
		{
			cmd_shutdown_step();
		}
		else if(get_msg(PMAN_COMMAND_PORT, &msg, &task_id) == SUCCESS) 
		{			
			switch(msg.pm_type) 
			{   
                case PM_LOADER_READY:
                {
                    // destroy the SMO sent to the task for phdrs
                    tsk = tsk_get(task_id);

                    if(tsk != NULL)
                    {
                        loader_ready(tsk);
                    }
                    break;
                }
                case PM_PHYMEM: 
				{
					/* if it's a service, it's entitled to know 
                    it's physical memory base address. */
                    tsk = tsk_get(task_id);

                    if(tsk != NULL && (tsk->flags & (TSK_FLAG_SERVICE|TSK_LOW_MEM))==(TSK_FLAG_SERVICE|TSK_LOW_MEM))
                    {
					    pres.pm_type = msg.pm_type;
	                    pres.req_id  = msg.req_id;
	                    pres.physical  = (UINT32)vmm_get_physical(task_id, (ADDR)((UINT32)((struct pm_msg_phymem*)&msg)->linear + SARTORIS_PROCBASE_LINEAR));
	
	                    send_msg(task_id, msg.response_port, &pres);
                    }
					break;
				}
				case PM_SHUTDOWN: 
				{
					/* Begin shutdown */
					cmd_shutdown_step();
					break;
				}                
                case PM_DBG_ATTACH:
                {
                    cmd_begin_debug(task_id, (struct pm_msg_dbgattach*)&msg);
                    break;
                }
                case PM_DBG_END:
                {
                    cmd_end_debug(task_id, (struct pm_msg_dbgend*)&msg);
                    break;
                }
                case PM_DBG_TRESUME:
                {
                    cmd_resumethr_debug(task_id, (struct pm_msg_dbgtresume*)&msg);
                    break;
                }
                case PM_LOAD_LIBRARY:
                {
                    tsk = tsk_get(task_id);
                    if(!tsk) break;
                    cmd_load_library((struct pm_msg_loadlib *)&msg, task_id);
                    break;
                }
			    case PM_CREATE_TASK: 
			    {
                    tsk = tsk_get(task_id);

                    if(!tsk) break;
                    
				    cmd_create_task((struct pm_msg_create_task *)&msg, tsk);
				    break;
			    }
				case PM_CREATE_THREAD: 
				{
					cmd_create_thread((struct pm_msg_create_thread*)&msg, task_id);
					break;
				}
				case PM_DESTROY_TASK: 
				{
					destroy_task_id = ((struct pm_msg_destroy_task*)&msg)->task_id;

					// If sender is the task itself ignore it
					if(task_id == destroy_task_id)
						break;

					/* Trying to destroy PMAN? */
					if(destroy_task_id == PMAN_TASK)
					{
						/* Suffer The concecuences!!!!!! */
						fatal_exception(task_id, PMAN_RULEZ);
						break;
					}

					tsk = tsk_get(destroy_task_id);

                    // if it's not the creator task, ignore it
                    if(tsk->creator_task != task_id)
                    {
                        cmd_inform_result(&msg, task_id, PM_ERROR, 0, 0);
                        break;
                    }

					if(tsk && tsk->state != TSK_KILLING && tsk->state != TSK_KILLED) 
					{
						// If task is executing a command, fail
						if(tsk->command_inf.executing != NULL)
						{
							cmd_inform_result(&msg, task_id, PM_TASK_RETRY_LATER, 0, 0);
							break;
						}

                        // deactivate task threads
                        thr = tsk->first_thread;

                        while(thr)
                        {
                            sch_deactivate(thr);
                            thr = thr->next_thread;
                        }

						/* Remove all pending commands on the queue for this task */
						cmd_queue_remove_bytask(tsk);

						tsk->command_inf.ret_value = ((struct pm_msg_destroy_task*)&msg)->ret_value;
						tsk->command_inf.command_sender_id = task_id;
						tsk->command_inf.command_req_id = msg.req_id;
						tsk->command_inf.command_ret_port = msg.response_port;
						tsk->state = TSK_KILLING;
						
						tsk->io_finished.callback = cmd_task_fileclosed_callback;
						io_begin_close( &tsk->io_event_src );
					}
					else
					{
						cmd_inform_result(&msg, task_id, PM_TASK_ID_INVALID, 0, 0);
					}

					break;
				}
				case PM_DESTROY_THREAD: 
				{
					tsk = NULL;
					thr = thr_get(((struct pm_msg_destroy_thread*)&msg)->thread_id);

					destroy_task_id = thr->task_id;
					thr = NULL;

					/* Trying to destroy PMAN threads? */
					if(destroy_task_id == PMAN_TASK)
					{
						/* Suffer The concecuences!!!!!! */
						fatal_exception(task_id, PMAN_RULEZ);
						break;
					}

                    /* Is it a request from a different process? */
                    if(destroy_task_id != task_id)
                    {
                        cmd_inform_result(&msg, task_id, PM_ERROR, 0, 0);
                        break;
                    }

					tsk = tsk_get(destroy_task_id);
                    
                    struct dbg_message dbg_msg;
                    
					if(tsk && tsk->state == TSK_NORMAL)
					{                        
						if(thr_destroy_thread(((struct pm_msg_destroy_thread*)&msg)->thread_id))
                        {
                            if(tsk->flags & TSK_DEBUG)
                            {
                                dbg_msg.task = destroy_task_id;
                                dbg_msg.thread = thr->id;
                                dbg_msg.command = DEBUG_THR_DESTROYED;
                                send_msg(tsk->dbg_task, tsk->dbg_port, &dbg_msg);                                
                            }
							cmd_inform_result(&msg, task_id, PM_OK, 0, 0);
                        }
						else
							cmd_inform_result(&msg, task_id, PM_ERROR, 0, 0);
					}
                    else
                    {
                        if(!tsk)
                            cmd_inform_result(&msg, task_id, PM_TASK_ID_INVALID, 0, 0);
                        else
                            cmd_inform_result(&msg, task_id, PM_ERROR, 0, 0);
                    }
					
					break;
				}
				case PM_TASK_FINISHED: 
				{
                    tsk = tsk_get(task_id);

					if(tsk != NULL && tsk->state == TSK_NORMAL) 
					{
						tsk->command_inf.ret_value = ((struct pm_msg_finished*)&msg)->ret_value;
						tsk->command_inf.command_sender_id = 0;
						tsk->command_inf.command_req_id = -1;
						tsk->command_inf.command_ret_port = -1;

                        // deactivate task threads
                        thr = tsk->first_thread;

                        while(thr)
                        {
                            sch_deactivate(thr);
                            thr = thr->next_thread;
                        }

                        cmd_queue_remove_bytask(tsk);

						tsk->state = TSK_KILLING;
						
						tsk->io_finished.callback = cmd_task_fileclosed_callback;
						io_begin_close( &tsk->io_event_src );
					}
                    else
                    {
                        if(!tsk)
                            cmd_inform_result(&msg, task_id, PM_TASK_ID_INVALID, 0, 0);
                        else
                            cmd_inform_result(&msg, task_id, PM_ERROR, 0, 0);
                    }
					break;
				}
				default:
				{
					tsk = tsk_get(task_id);

					if(tsk != NULL && tsk->state == TSK_NORMAL)
					{
						if(!cmd_queue_add(&msg, (UINT16)task_id))
						{
							cmd_inform_result(&msg, task_id, PM_NOT_ENOUGH_MEM, 0, 0);
						}
					}
					else
					{
						cmd_inform_result(&msg, task_id, PM_TASK_ID_INVALID, 0, 0);	
					}					
				}
			}
		}
	}

	/* 
    Attempt to process commands on the queue. 
    */
	cmd = command_queue.first;

	while(cmd != NULL) 
	{
		pman_print_dbg("COMMAND.c: Got a queue COMMAND! task: %i cmd: %i\n",  (cmd->sender_task & 0x0000FFFF), msg.pm_type);
                
        if(process_queue_msg(cmd))
        {
            ocmd = cmd;
            cmd = cmd->next;
		    cmd_queue_remove(ocmd);
        }
        else
        {
            cmd = cmd->next;
        }
	}
}
Ejemplo n.º 2
0
static void mapidcom()
//Communicates with clients through IPC
{
	fd_set active_fd_set; // active file descriptor list
	fd_set read_fd_set; // temp file descriptor list for select()
	int fdmax; // maximum file descriptor number
	int yes = 1; // for setsockopt() SO_REUSEADDR, below
	struct sockaddr_un mapidaddr;
	struct sockaddr_un remoteaddr;
	struct mapiipcbuf qbuf;
	socklen_t addrlen;
	int nbytes, len, s;
	struct client *cl= NULL;
	flist_node_t *tmpnode;
	conf_category_entry_t *cat=NULL;
	char *local;
	struct group *mapi_group;
  conf_category_t *conf;

	mapidsocket=strdup(MAPIDSOCKGLOBAL);

	if ((conf = pc_load(mapid_conf)) != NULL) {
		cat = pc_get_category(conf, "");
		local=pc_get_param(cat, "local");
		if (local!=NULL && strcmp(local, "1")==0) {
			free(mapidsocket);
			mapidsocket=printf_string(MAPIDSOCKHOME, getenv("HOME") );
		}
		pc_close(conf);

	}
	//  create the listener socket
	if ((listenerfd = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) {
		DEBUG_CMD(Debug_Message("ERROR: socket: %s", strerror(errno)));
		exit(EXIT_FAILURE);
	}
	// avoid "address already in use" error message
	if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))
			== -1) {
		DEBUG_CMD(Debug_Message("ERROR: setsockopt: %s", strerror(errno)));
		exit(EXIT_FAILURE);
	}
	//  set up the address we will be binding to
	memset(&mapidaddr, 0, sizeof (mapidaddr));
	mapidaddr.sun_family = AF_LOCAL;

	memcpy(mapidaddr.sun_path, mapidsocket, strlen(mapidsocket)+1);
	unlink(mapidsocket);

	len = sizeof mapidaddr.sun_family + strlen(mapidaddr.sun_path);
	if (bind(listenerfd, (struct sockaddr *) &mapidaddr, len)) {
		DEBUG_CMD(Debug_Message("ERROR: bind: %s", strerror(errno)));
		exit(EXIT_FAILURE);
	}

	// allow any member of our own group to connect
	chmod(mapidsocket, S_IRWXU | S_IRWXG);

	// if a mapi user group exists, set group permissions accordingly,
	// otherwise the group ID will be equal to the user ID of the user that
	// invoked mapid
	mapi_group = getgrnam(MAPI_GROUP_NAME);
	if (mapi_group != NULL) {
		chown(mapidsocket, -1, mapi_group->gr_gid);
	}

	if (listen(listenerfd, BACKLOG) == -1) {
		DEBUG_CMD(Debug_Message("ERROR: listen: %s", strerror(errno)));
		exit(EXIT_FAILURE);
	}

	FD_ZERO (&active_fd_set);
	// add the listener to the active set
	FD_SET (listenerfd, &active_fd_set)
;
  // keep track of the biggest file descriptor
  		fdmax = listenerfd; // so far, it's just this one

	// wait for commands from the mapi stub, for ever...
	while (1) {
		read_fd_set = active_fd_set; // copy it
		if (select(fdmax + 1, &read_fd_set, NULL, NULL, NULL) == -1) {
			DEBUG_CMD(Debug_Message("ERROR: select: %s", strerror(errno)));
			break;
		}

		// run through the existing connections
		for (s = 0; s <= fdmax; s++) {
			if (FD_ISSET (s, &read_fd_set)) {

				// connection on the original listener socket
				if (s == listenerfd) {
					addrlen = sizeof (remoteaddr);
					if ((newfd = accept(listenerfd,
							(struct sockaddr *) &remoteaddr, &addrlen)) == -1) {
						DEBUG_CMD(Debug_Message("accept: %s", strerror(errno)));
					} else {
						FD_SET (newfd, &active_fd_set)
;						// add to active set
						if (newfd > fdmax)
						{ // keep track of the maximum
							fdmax = newfd;
						}
					}
				}
				// handle data from an existing client
				else
				{
					if ((nbytes = recv (s, &qbuf, MAX_SEND_SIZE, 0)) <= 0)
					{
						if (nbytes == 0)
						{
							// connection closed - find client's pid
							while(__sync_lock_test_and_set(&clientlist_lock,1));
							tmpnode = (flist_node_t *) flist_head (clientlist);

							cl = NULL;
							while (tmpnode != NULL)
							{
								if (((struct client *) tmpnode->data)->sock == s)
								{
									cl = (struct client *) tmpnode->data;
									break;
								}
								tmpnode = flist_next (tmpnode);
							}
							clientlist_lock = 0;

							if (cl == NULL)
							{/* This is not interesting, as it will occur upon requests from clients without flows etc.
							 WARNING_CMD (printf
							 ("WARNING: Zero bytes from socket %d [%s:%d]\n",
							 s, __FILE__, __LINE__));
							 */
								/* shouldn't really exit here? 
								 * this will cause the program to exit on errors with an empty
								 * client-list which isn't really an error (IMHO)
								 */
								//exit(EXIT_FAILURE);
							}
							else
							{
								while(__sync_lock_test_and_set(&clientlist_lock,1));
								//clean up any remaining flows
								tmpnode = (flist_node_t *) flist_head (cl->flowlist);
								while (tmpnode != NULL)
								{
									cleanup_flow ((struct flow *) tmpnode->data);
									tmpnode = flist_next (tmpnode);
								}
								tmpnode = (flist_node_t *) flist_head (cl->devicelist);
								while (tmpnode != NULL)
								{
									mapidrv_delete_device = get_drv_funct (tmpnode->data, "mapidrv_delete_device");
									mapidrv_delete_device (tmpnode->id);
									tmpnode = flist_next (tmpnode);
								}
								flist_destroy (cl->flowlist);
								flist_destroy (cl->devicelist);
								free(cl->devicelist);
								free (cl->flowlist);
								//remove this client from global client list
								free(flist_remove (clientlist, cl->pid));
								clientlist_lock = 0;
							}
						}
						else
						{
							DEBUG_CMD(Debug_Message("WARNING: recv: %s at", strerror (errno)));
						}
						close (s);
						FD_CLR (s, &active_fd_set); // remove it from active set
					}
					else
					{
						// we got some data from a client: process request
						switch (qbuf.cmd)
						{
							case GET_LIBS:
							cmd_get_libs (qbuf.pid, s);
							break;
							case GET_LIBPATH:
							cmd_get_libpath (qbuf.pid, s);
							break;
							case CREATE_FLOW:
							cmd_create_flow ((char *)qbuf.data, qbuf.pid, qbuf.uid, s);
							break;
							case CLOSE_FLOW:
							cmd_close_flow (qbuf.fd, qbuf.pid, s, 1);
							break;
							case GET_FLOW_INFO:
							cmd_get_flow_info (qbuf.fd, qbuf.pid, s);
							break;
							case GET_FUNCTION_INFO:
							cmd_get_function_info (qbuf.fd, qbuf.fid, qbuf.pid, s);
							break;
							case GET_NEXT_FUNCTION_INFO:
							cmd_get_next_function_info (qbuf.fd, qbuf.fid, qbuf.pid, s);
							break;
							case GET_NEXT_FLOW_INFO:
							cmd_get_next_flow_info (qbuf.fd, qbuf.pid, s);
							break;
							case GET_NEXT_DEVICE_INFO:
							cmd_get_next_device_info (qbuf.fd, qbuf.pid, s);
							break;
							case GET_DEVICE_INFO:
							cmd_get_device_info (qbuf.fd, qbuf.pid, s);
							break;
						case MAPI_STATS:
						  cmd_stats ((char *)qbuf.data, qbuf.pid, qbuf.uid, s);
						  break;
							case APPLY_FUNCTION:
							cmd_apply_function (&qbuf, qbuf.pid, s);
							break;
							case READ_RESULT:
							cmd_read_results (qbuf.fd, qbuf.fid, qbuf.pid, s);
							break;
							case CONNECT:
							cmd_connect (qbuf.fd, qbuf.pid, s);
							break;
							case CREATE_FLOW_ACK:
							case APPLY_FUNCTION_ACK:
							case READ_RESULT_ACK:
							case CONNECT_ACK:
							case CLOSE_FLOW_ACK:
							case SET_AUTHDATA_ACK:
							break;
							case READ_ERROR_ACK:
							break;
							case ERROR_ACK:
							break;
							case CREATE_OFFLINE_DEVICE:
							cmd_create_offline_device ((char *)qbuf.data, qbuf.fid, qbuf.pid, s);
							break;
							case CREATE_OFFLINE_DEVICE_ACK:
							break;
							case START_OFFLINE_DEVICE:
							cmd_start_offline_device ((char *)qbuf.data, qbuf.pid, s);
							break;
							case START_OFFLINE_DEVICE_ACK:
							break;
							case DELETE_OFFLINE_DEVICE:
							cmd_delete_offline_device ((char *)qbuf.data, qbuf.pid, s);
							break;
							case DELETE_OFFLINE_DEVICE_ACK:
							break;
							case CREATE_OFFLINE_FLOW_ACK:
							break;
							case LOAD_LIBRARY:
							cmd_load_library ((char *)qbuf.data, qbuf.pid, s);
							default:
							break;
						}
					}
				}
			}
		} // for
	} // while(1)
}