]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - afs.c
Change the type of the argv argument of all commands.
[paraslash.git] / afs.c
diff --git a/afs.c b/afs.c
index 364eb7f311c2322fa4dcb2228d77ff896c9c3ed3..806d0fbd70d199bdd8f515e4511f6224ddfaf856 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2007 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 #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.
  *
@@ -284,7 +235,7 @@ out:
  * \sa send_standard_callback_request(), send_callback_request().
  */
 int send_option_arg_callback_request(struct osl_object *options,
-               int argc, const char **argv, callback_function *f,
+               int argc,  char * const * const argv, callback_function *f,
                struct osl_object *result)
 {
        char *p;
@@ -322,12 +273,68 @@ int send_option_arg_callback_request(struct osl_object *options,
  * \return The return value of the underlying call to
  * send_option_arg_callback_request().
  */
-int send_standard_callback_request(int argc, const char **argv,
+int send_standard_callback_request(int argc,  char * const * const argv,
                callback_function *f, struct osl_object *result)
 {
        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.
@@ -667,7 +674,7 @@ static void command_post_select(struct sched *s, struct task *t)
                goto out;
        }
        if (t->ret != sizeof(buf)) {
-               PARA_NOTICE_LOG("short read (%d bytes, expected %d)\n",
+               PARA_NOTICE_LOG("short read (%d bytes, expected %lu)\n",
                        t->ret, sizeof(buf));
                t->ret = 1;
                goto out;
@@ -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:
@@ -811,7 +794,7 @@ static int create_all_tables(void)
 }
 
 /* TODO load tables after init */
-int com_init(__a_unused int fd, int argc, const char **argv)
+int com_init(__a_unused int fd, int argc, char * const * const argv)
 {
        int i, j, ret;
        if (argc == 1)