ERROR_CODE run_service_s(char *program_name, struct hash_map_t *arguments) { /* allocates space for the error value that will be used to check for an error in the call */ ERROR_CODE return_value; /* initializes the service creating the structures and starting the values for the configuration of it */ return_value = init_service(program_name, arguments); if(IS_ERROR_CODE(return_value)) { RAISE_AGAIN(return_value); } /* run the service, blocking the call until the service is finished, the retrives the return value from it */ return_value = run_service(); if(IS_ERROR_CODE(return_value)) { RAISE_AGAIN(return_value); } /* destroys the service eliminating any structures that have been created in the service life-time */ return_value = destroy_service(); if(IS_ERROR_CODE(return_value)) { RAISE_AGAIN(return_value); } /* raises no error as the execution of the service went normally and no problems have been issued */ RAISE_NO_ERROR; }
ERROR_CODE ran_service() { /* allocates the return value */ ERROR_CODE return_value; /* in case the service status is open */ if(service->status == STATUS_CLOSED) { /* prints a debug message */ V_DEBUG("No service to be stopped\n"); } else { /* prints a debug message */ V_DEBUG("Stopping service\n"); /* stops the service, this call should make the required changes in the service structure so that it's stopped as soon as possible */ return_value = stop_service(service); /* tests the error code for error */ if(IS_ERROR_CODE(return_value)) { /* runs the socket finish so that the proper cleanup operations are performed and then re-raises the error*/ SOCKET_FINISH(); RAISE_AGAIN(return_value); } /* prints a debug message */ V_DEBUG("Finished stopping service\n"); } /* raises no error */ RAISE_NO_ERROR; }
ERROR_CODE run_service() { /* allocates the return value to be used to gather the error result from the service calls */ ERROR_CODE return_value; /* allocates the socket data and then initializes the socket infrastructure (global structures) with it */ SOCKET_DATA socket_data; SOCKET_INITIALIZE(&socket_data); /* starts the service, this call should be able to bootstrap all the required structures and initialize the main loop, this should block the control flow fduring the run of the service */ return_value = start_service(service); /* tests the error code value for error and in case there's one runs the appropriate measures */ if(IS_ERROR_CODE(return_value)) { /* runs the socket finish so that the proper cleanup operations are performed and then re-raises the error*/ SOCKET_FINISH(); RAISE_AGAIN(return_value); } /* runs the socket finish releasing any pending memory information regarding the socket infra-structure */ SOCKET_FINISH(); /* raises no error */ RAISE_NO_ERROR; }
ERROR_CODE init_service(char *program_name, struct hash_map_t *arguments) { /* allocates the return value to be used to gather the error result from the service calls */ ERROR_CODE return_value; /* creates the service and loads the options taking into account the arguments */ create_service( &service, (unsigned char *) VIRIATUM_NAME, (unsigned char *) program_name ); return_value = load_specifications(service); if(IS_ERROR_CODE(return_value)) { RAISE_AGAIN(return_value); } return_value = load_options_service(service, arguments); if(IS_ERROR_CODE(return_value)) { RAISE_AGAIN(return_value); } return_value = calculate_options_service(service); if(IS_ERROR_CODE(return_value)) { RAISE_AGAIN(return_value); } /* updates the registers signals handler so that the service may be able to register the handlers at the proper timing */ service->register_signals = register_signals; /* calculates the locations structure for the service based on the currently loaded configuration, this a complex operation */ calculate_locations_service(service); /* runs the printing operation on the service, this should output the information to the standar output */ print_options_service(service); /* raises no error to the caller method, normal exit operation (should provide no problem) */ RAISE_NO_ERROR; }
ERROR_CODE decode_bencoding_file(char *file_path, struct type_t **type_pointer) { /* allocates space for the general (temporary) variables to be used durring the parsing of the file */ ERROR_CODE return_value; size_t file_size; unsigned char *file_buffer; struct bencoding_engine_t *bencoding_engine; struct bencoding_handler_t *bencoding_handler; /* reads the file contained in the provided file path and then tests the error code for error, in case there is an error prints it to the error stream output */ return_value = read_file(file_path, &file_buffer, &file_size); if(IS_ERROR_CODE(return_value)) { RAISE_ERROR_F( RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Problem reading file %s", file_path ); } /* starts the bencoding engine, starting all of its internal structures and then runs an engine tick parsing the complete file buffer (it's completely available) */ _start_bencoding_engine(&bencoding_engine); _run_bencoding_engine(bencoding_engine, file_buffer, file_size); /* retieves the handler associated with the engine and then uses it to retrieve the top type of the parsed structure */ bencoding_handler = (struct bencoding_handler_t *) bencoding_engine->context; *type_pointer = bencoding_handler->top; /* stops the bencoding engine releasing all of its internal structures, the top type is still defined */ _stop_bencoding_engine(bencoding_engine); /* releases the buffer used durring the parsing of the configuration file */ FREE(file_buffer); /* raises no error */ RAISE_NO_ERROR; }
int execute_arguments(char *program_name, struct hash_map_t *arguments) { /* allocates space for the possible argument to be executed from the arguments map */ void *value; /* allocates the value to be used to verify the exitence of error from the function */ ERROR_CODE return_value; /* sets space for the flag that will control if the service should be run or not, this is used for certain situations (mostyle test) where the service is not meant to be run */ char run_service = TRUE; /* tries to retrieve the help argument from the arguments map in case the value exists prints the help value and then exits the current system */ get_value_string_hash_map(arguments, (unsigned char *) "help", &value); if(value != NULL) { return help(); } /* tries to retrieve the version argument from the arguments map in case the value exists prints the version value and then exits the current system */ get_value_string_hash_map(arguments, (unsigned char *) "version", &value); if(value != NULL) { return version(); } /* retrieves the test argument value from the arguments map and in case it's set starts the test process runing a series of test functions in sequence */ get_value_string_hash_map(arguments, (unsigned char *) "test", &value); if(value != NULL) { return test(); } /* retrieves the speed argument value from the arguments map and in case it's set starts the speed measuring and disables the runnig of the service */ get_value_string_hash_map(arguments, (unsigned char *) "speed", &value); if(value != NULL) { return speed(); } /* tries to retrieve the daemon argument from the arguments map in case the value is set daemonizes the current process so that it remains in background and returns to the caller process immediately, otherwise prints the viriatum information into the standard output "file", the label should be standard */ get_value_string_hash_map(arguments, (unsigned char *) "daemon", &value); if(value != NULL) { daemonize(); } else { print_information(); } /* tries to retrieve the local argument from the arguments map in case the value exists localizes the current service so that any file read is read from the current directory */ get_value_string_hash_map(arguments, (unsigned char *) "local", &value); if(value != NULL) { localize(); } /* in cas the flag that control if the service must be run is unset the control flow must be returned immediately (avoids running service) */ if(run_service == FALSE) { RAISE_NO_ERROR; } /* runs the service, with the given arguments, this call should block the program control flow until an event stop the running of the main loop */ return_value = run_service_s(program_name, arguments); /* tests the error code for error in case it exists prints a message indicating the problem that occurred */ if(IS_ERROR_CODE(return_value)) { V_ERROR_F("Problem running service (%s)\n", (char *) GET_ERROR()); RAISE_AGAIN(return_value); } /* returns the normal result value as no problems has occured during the execution of the command */ RAISE_NO_ERROR; }
lxdream_file_type_t file_load_magic( const gchar *filename, gboolean wrap_exec, ERROR *err ) { gboolean result; /* Try disc types first */ cdrom_disc_t disc = cdrom_disc_open( filename, err ); if( disc != NULL ) { gdrom_mount_disc(disc); return FILE_DISC; } else if( !IS_ERROR_CODE(err,LX_ERR_FILE_UNKNOWN) ) { return FILE_ERROR; } int fd = open( filename, O_RDONLY ); if( fd == -1 ) { SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s' (%s)" ,filename, strerror(errno) ); return FILE_ERROR; } lxdream_file_type_t type = file_identify(filename, fd, err); switch( type ) { case FILE_ERROR: result = FALSE; break; case FILE_ELF: if( wrap_exec ) { disc = cdrom_wrap_elf( CDROM_DISC_XA, filename, fd, err ); result = disc != NULL; if( disc != NULL ) { gdrom_mount_disc(disc); } } else { result = file_load_elf( filename, fd, err ); } break; case FILE_BINARY: if( wrap_exec ) { disc = cdrom_wrap_binary( CDROM_DISC_XA, filename, fd, err ); result = disc != NULL; if( disc != NULL ) { gdrom_mount_disc(disc); } } else { result = file_load_binary( filename, fd, err ); } break; case FILE_SAVE_STATE: result = dreamcast_load_state( filename ); break; case FILE_ZIP: SET_ERROR( err, LX_ERR_FILE_UNSUP, "ZIP/SBI not currently supported" ); result = FALSE; break; case FILE_ISO: SET_ERROR( err, LX_ERR_FILE_UNSUP, "ISO files are not currently supported" ); result = FALSE; break; default: SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' could not be recognized", filename ); result = FALSE; break; } close(fd); if( result ) { CLEAR_ERROR(err); return type; } return FILE_ERROR; }
ERROR_CODE auth_file_http(char *auth_file, char *authorization, unsigned char *result) { /* allocates space for the error return value to be used in error checking for function calls */ ERROR_CODE return_value; /* allocates space for the pointer to the passwd key value structure to be created by parsing the auth file */ struct hash_map_t *passwd; /* allocates space to the various pointer values to be used for the separation and treatment of the auth value */ char *pointer; char *authorization_b64; char *authorization_d; char *password_pointer; /* allocates space for the buffers to be used for the username and password values extracted from the authorization token */ char username[128]; char password[128]; char *password_v; /* allocates the various size relates values for the buffer variables creation */ size_t authorization_size; size_t username_size; size_t password_size; /* tries to find the token that separates the authentication type from the authorization base 64 value in case the value is not found raises an error indicating the problem */ pointer = strchr(authorization, ' '); if(pointer == NULL) { RAISE_ERROR_M( RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Authorization value not valid" ); } authorization_b64 = pointer + 1; /* tries to decode the authorization base 64 value into a plain text value in case the decoding fails, re-raises the error to the upper levels for caller information */ return_value = decode_base64( (unsigned char *) authorization_b64, strlen(authorization_b64), (unsigned char **) &authorization_d, &authorization_size ); if(IS_ERROR_CODE(return_value)) { RAISE_ERROR_M( RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Problem decoding base 64 authorization" ); } /* tries to find the token that separates the username part of the authorization from the password part in case the value is not found raises an error to the upper levels */ pointer = memchr(authorization_d, ':', authorization_size); if(pointer == NULL) { FREE(authorization_d); RAISE_ERROR_M( RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "No password separator found in authorization" ); } password_pointer = pointer + 1; /* calculates the size of both the username and the password from the diference between the various pointers */ username_size = password_pointer - authorization_d - 1; password_size = authorization_d + authorization_size - password_pointer; /* copies both the username and the password values to the apropriate internal buffers (to be used in comparision) */ memcpy(username, authorization_d, username_size); username[username_size] = '\0'; memcpy(password, password_pointer, password_size); password[password_size] = '\0'; /* processes the passwd file using the provided file path for it, this is an expensive io driven operation, and must be used wth care */ process_passwd_file(auth_file, &passwd); /* retrieves the password verification value for the retrieved username and in case it's valid compares it and sets the result value accordingly */ get_value_string_hash_map( passwd, (unsigned char *) username, (void **) &password_v ); if(password_v != NULL && strcmp(password, password_v) == 0) { *result = TRUE; } else { *result = FALSE; } /* releases the memory associated with the complete set of values in the passwd structure and then releases the memory from the hash map structure itself, then releases the memory associated with the authorization decoded string */ delete_values_hash_map(passwd); delete_hash_map(passwd); FREE(authorization_d); /* raises no error, as everything has been done as possible with no problems created in the processing */ RAISE_NO_ERROR; }
ERROR_CODE process_ini_file(char *file_path, struct sort_map_t **configuration_pointer) { /* allocates space for the general (temporary) variables to be used durring the parsing of the file */ ERROR_CODE return_value; size_t index; size_t file_size; unsigned char *file_buffer; unsigned char character; enum ini_state_e state; /* allocates the mark variables used to locate the part of context changing durring the parsing */ unsigned char *pointer = 0; unsigned char *section_end_mark = 0; unsigned char *comment_end_mark = 0; unsigned char *key_end_mark = 0; unsigned char *value_end_mark = 0; /* allocates space for the settings to be used by the engine for the engine instance itself and for the handler to be used to "catch" the events, then retrieves the pointers to these structures*/ struct ini_settings_t ini_settings_s; struct ini_engine_t ini_engine_s; struct ini_handler_t ini_handler_s; struct ini_settings_t *ini_settings = &ini_settings_s; struct ini_engine_t *ini_engine = &ini_engine_s; struct ini_handler_t *ini_handler = &ini_handler_s; /* allocates space for the sort map to be used for the configuration to be created */ struct sort_map_t *configuration; /* creates the sort map that will hold the various arguments, then updates the configuration pointer with the created configuration sort map */ create_sort_map(&configuration, 0); *configuration_pointer = configuration; /* sets the various handlers for the ini settings parsing, they will be used to correctly update the provided configuration sort map */ ini_settings_s.on_section_start = NULL; ini_settings_s.on_section_end = _ini_section_end_callback; ini_settings_s.on_comment_start = NULL; ini_settings_s.on_comment_end = _ini_comment_end_callback; ini_settings_s.on_key_start = NULL; ini_settings_s.on_key_end = _ini_key_end_callback; ini_settings_s.on_value_start = NULL; ini_settings_s.on_value_end = _ini_value_end_callback; /* sets the configuration reference in the ini handler so that it may be updatd and then sets the handler in the ini engine instance to be used for parsing */ ini_handler_s.configuration = configuration; ini_engine_s.context = ini_handler; /* sets the flag that controls if the trailing space characters should be removesd from key and values */ ini_handler_s.remove_spaces = 1; /* reads the file contained in the provided file path and then tests the error code for error, in case there is an error prints it to the error stream output */ return_value = read_file(file_path, &file_buffer, &file_size); if(IS_ERROR_CODE(return_value)) { RAISE_ERROR_F( RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Problem reading file %s", file_path ); } /* sets the initial state for the parsing process this is considered to be the "general loop" state */ state = INI_ENGINE_NORMAL; /* iterates over the byte range of the file, all the bytes should be contained in the buffer "under" iteration */ for(index = 0; index < file_size; index++) { /* retrieves the current character from the file buffer and the retrieves the pointer to its position */ character = file_buffer[index]; pointer = &file_buffer[index]; switch(state) { case INI_ENGINE_NORMAL: if(character == '[') { state = INI_ENGINE_SECTION; INI_MARK_N(section_end, -1); INI_CALLBACK(section_start); } else if(character == ';') { state = INI_ENGINE_COMMENT; INI_MARK_N(comment_end, -1); INI_CALLBACK(comment_start); } else if(character == '\n' || character == '\r') { state = INI_ENGINE_NORMAL; } else { state = INI_ENGINE_KEY; INI_MARK(key_end); INI_CALLBACK(key_start); } break; case INI_ENGINE_SECTION: if(character == ']') { state = INI_ENGINE_NORMAL; INI_CALLBACK_DATA(section_end); } break; case INI_ENGINE_COMMENT: if(character == '\n' || character == '\r') { state = INI_ENGINE_NORMAL; INI_CALLBACK_DATA(comment_end); } break; case INI_ENGINE_KEY: if(character == '=') { state = INI_ENGINE_VALUE; INI_MARK_N(value_end, -1); INI_CALLBACK_DATA(key_end); INI_CALLBACK(value_start); } break; case INI_ENGINE_VALUE: if(character == '\n' || character == '\r') { state = INI_ENGINE_NORMAL; INI_CALLBACK_DATA(value_end); } break; } } /* releases the buffer used durring the parsing of the configuration file (avoids leaks) */ FREE(file_buffer); /* raises no error */ RAISE_NO_ERROR; }