X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=afs.c;h=c726f35f6a3524fa56a8934ae660d62472c8bf45;hp=364eb7f311c2322fa4dcb2228d77ff896c9c3ed3;hb=aea0aba712b2170e2d39ffa1c8f8cb55fc0881bf;hpb=8211954fc3390c0fa19cca788b03336a37aa9dc0 diff --git a/afs.c b/afs.c index 364eb7f3..c726f35f 100644 --- a/afs.c +++ b/afs.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1997-2007 Andre Noll + * Copyright (C) 2007 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -23,31 +23,7 @@ #include "signal.h" #include "fd.h" -extern uint32_t afs_socket_cookie; - -/** - * Compare two osl objects of string type. - * - * \param obj1 Pointer to the first object. - * \param obj2 Pointer to the second object. - * - * In any case, only \p MIN(obj1->size, obj2->size) characters of each string - * are taken into account. - * - * \return It returns an integer less than, equal to, or greater than zero if - * \a obj1 is found, respectively, to be less than, to match, or be greater than - * obj2. - * - * \sa strcmp(3), strncmp(3), osl_compare_func. - */ -int string_compare(const struct osl_object *obj1, const struct osl_object *obj2) -{ - const char *str1 = (const char *)obj1->data; - const char *str2 = (const char *)obj2->data; - return strncmp(str1, str2, PARA_MIN(obj1->size, obj2->size)); -} - -/** The osl tables used by afs. \sa blob.c */ +/** The osl tables used by afs. \sa blob.c. */ enum afs_table_num { /** Contains audio file information. See aft.c. */ TBLNUM_AUDIO_FILES, @@ -89,69 +65,40 @@ struct command_task { struct task task; }; - /** - * A wrapper for strtol(3). + * A random number used to "authenticate" the connection. * - * \param str The string to be converted to a long integer. - * \param result The converted value is stored here. - * - * \return Positive on success, -E_ATOL on errors. - * - * \sa strtol(3), atoi(3). + * para_server picks this number by random before forking the afs process. The + * command handlers write this number together with the id of the shared memory + * area containing the query. This way, a malicious local user has to know this + * number to be able to cause the afs process to crash by sending fake queries. */ -int para_atol(const char *str, long *result) -{ - char *endptr; - long val; - int ret, base = 10; - - errno = 0; /* To distinguish success/failure after call */ - val = strtol(str, &endptr, base); - ret = -E_ATOL; - if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) - goto out; /* overflow */ - if (errno != 0 && val == 0) - goto out; /* other error */ - if (endptr == str) - goto out; /* No digits were found */ - if (*endptr != '\0') - goto out; /* Further characters after number */ - *result = val; - ret = 1; -out: - return ret; -} +extern uint32_t afs_socket_cookie; /** - * Struct to let para_server call a function specified from child context. + * Struct to let command handlers execute a callback in afs context. + * + * Commands that need to change the state of afs can't change the relevant data + * structures directly because commands are executed in a child process, i.e. + * they get their own virtual address space. * - * Commands that need to change the state of para_server can't - * change the relevant data structures directly because commands - * are executed in a child process, i.e. they get their own - * virtual address space. This structure must be used to let - * para_server (i.e. the parent process) call a function specified - * by the child (the command handler). + * This structure is used by \p send_callback_request() (executed from handler + * context) in order to let the afs process call the specified function. An + * instance of that structure is written to a shared memory area together with + * the arguments to the callback function. The identifier of the shared memory + * area is written to the command socket. * - * \sa fork(2), ipc.c. + * The afs process accepts connections on the command socket and reads the + * shared memory id, attaches the corresponing area, calls the given handler to + * perform the desired action and to optionally compute a result. + * + * The result and a \p callback_result structure is then written to another + * shared memory area. The identifier for that area is written to the handler's + * command socket, so that the handler process can read the id, attach the + * shared memory area and use the result. + * + * \sa struct callback_result. */ -struct callback_data { - /** The function to be called. */ - callback_function *handler; - /** The sma for the parameters of the callback function. */ - int query_shmid; - /** The size of the query sma. */ - size_t query_size; - /** If the callback produced a result, it is stored in this sma. */ - int result_shmid; - /** The size of the result sma. */ - size_t result_size; - /** The return value of the callback function. */ - int callback_ret; - /** The return value of the callback() procedure. */ - int sma_ret; -}; - struct callback_query { /** The function to be called. */ callback_function *handler; @@ -159,16 +106,20 @@ struct callback_query { size_t query_size; }; +/** + * Structure embedded in the result of a callback. + * + * If the callback produced a result, an instance of that structure is embeeded + * into the shared memory area holding the result, mainly to let the command + * handler know the size of the result. + * + * \sa struct callback_query. + */ struct callback_result { /** The number of bytes of the result. */ size_t result_size; }; -static struct callback_data *shm_callback_data; -static int callback_mutex; -static int child_mutex; -static int result_mutex; - /** * Ask the parent process to call a given function. * @@ -328,6 +279,62 @@ int send_standard_callback_request(int argc, const char **argv, return send_option_arg_callback_request(NULL, argc, argv, f, result); } +/** + * Compare two osl objects of string type. + * + * \param obj1 Pointer to the first object. + * \param obj2 Pointer to the second object. + * + * In any case, only \p MIN(obj1->size, obj2->size) characters of each string + * are taken into account. + * + * \return It returns an integer less than, equal to, or greater than zero if + * \a obj1 is found, respectively, to be less than, to match, or be greater than + * obj2. + * + * \sa strcmp(3), strncmp(3), osl_compare_func. + */ +int string_compare(const struct osl_object *obj1, const struct osl_object *obj2) +{ + const char *str1 = (const char *)obj1->data; + const char *str2 = (const char *)obj2->data; + return strncmp(str1, str2, PARA_MIN(obj1->size, obj2->size)); +} + +/** + * A wrapper for strtol(3). + * + * \param str The string to be converted to a long integer. + * \param result The converted value is stored here. + * + * \return Positive on success, -E_ATOL on errors. + * + * \sa strtol(3), atoi(3). + */ +int para_atol(const char *str, long *result) +{ + char *endptr; + long val; + int ret, base = 10; + + errno = 0; /* To distinguish success/failure after call */ + val = strtol(str, &endptr, base); + ret = -E_ATOL; + if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) + goto out; /* overflow */ + if (errno != 0 && val == 0) + goto out; /* other error */ + if (endptr == str) + goto out; /* No digits were found */ + if (*endptr != '\0') + goto out; /* Further characters after number */ + *result = val; + ret = 1; +out: + return ret; +} + + /* * write input from fd to dynamically allocated char array, * but maximal max_size byte. Return size. @@ -719,7 +726,6 @@ void register_tasks(uint32_t cookie) __noreturn int afs_init(uint32_t cookie, int socket_fd) { int ret; -// void *shm_area; enum play_mode current_play_mode; struct sched s; @@ -755,29 +761,6 @@ __noreturn int afs_init(uint32_t cookie, int socket_fd) s.default_timeout.tv_usec = 99 * 1000; sched(&s); -#if 0 - ret = shm_new(sizeof(struct callback_data)); - if (ret < 0) - return ret; - shmid = ret; - ret = shm_attach(shmid, ATTACH_RW, &shm_area); - if (ret < 0) - return ret; - shm_callback_data = shm_area; - ret = mutex_new(); - if (ret < 0) - return ret; - callback_mutex = ret; - ret = mutex_new(); - if (ret < 0) - return ret; - child_mutex = ret; - ret = mutex_new(); - if (ret < 0) - return ret; - result_mutex = ret; - mutex_lock(result_mutex); -#endif aft_init_error: score_shutdown(OSL_MARK_CLEAN); score_init_error: