diff options
Diffstat (limited to '')
-rw-r--r-- | src/native_bus.pyx | 160 |
1 files changed, 158 insertions, 2 deletions
diff --git a/src/native_bus.pyx b/src/native_bus.pyx index fdcf341..c3c4039 100644 --- a/src/native_bus.pyx +++ b/src/native_bus.pyx @@ -26,6 +26,7 @@ DEALINGS IN THE SOFTWARE. cimport cython from libc.stdlib cimport malloc, free +from posix.types cimport uid_t, gid_t, mode_t cdef extern int bus_create(const char *, int, char **) @@ -98,6 +99,71 @@ Listen (in a loop, forever) for new message on a bus @return 0 on success, -1 on error ''' +cdef extern int bus_poll_start(long, int) +''' +Announce that the thread is listening on the bus. +This is required so the will does not miss any +messages due to race conditions. Additionally, +not calling this function will cause the bus the +misbehave, is `bus_poll` is written to expect +this function to have been called. + +@param bus Bus information +@param flags `BUS_NOWAIT` if the bus should fail and set `errno` to + `EAGAIN` if there isn't already a message available on + the bus when `bus_poll` is called +@return 0 on success, -1 on error +''' + +cdef extern int bus_poll_stop(long) +''' +Announce that the thread has stopped listening on the bus. +This is required so that the thread does not cause others +to wait indefinitely. + +@param bus Bus information +@return 0 on success, -1 on error +''' + +cdef extern const char *bus_poll(long) +''' +Wait for a message to be broadcasted on the bus. +The caller should make a copy of the received message, +without freeing the original copy, and parse it in a +separate thread. When the new thread has started be +started, the caller of this function should then +either call `bus_poll` again or `bus_poll_stop`. + +@param bus Bus information +@return The received message, `NULL` on error +''' + +cdef extern int bus_chown(const char *, uid_t, gid_t) +''' +Change the ownership of a bus + +`stat(2)` can be used of the bus's associated file to get the bus's ownership + +@param file The pathname of the bus +@param owner The user ID of the bus's new owner +@param group The group ID of the bus's new group +@return 0 on success, -1 on error +''' + +cdef extern int bus_chmod(const char *, mode_t) +''' +Change the permissions for a bus + +`stat(2)` can be used of the bus's associated file to get the bus's permissions + +@param file The pathname of the bus +@param mode The permissions of the bus, any permission for a user implies + full permissions for that user, except only the owner may + edit the bus's associated file +@return 0 on success, -1 on error +''' + + def bus_allocate() -> int: ''' @@ -193,8 +259,8 @@ def bus_write_wrapped(bus : int, message : str, flags : int) -> int: @param bus Bus information @param message The message to write, may not be longer than `BUS_MEMORY_SIZE` including the NUL-termination - @param flags `BUS_NOWAIT` fail if other process is attempting - to write + @param flags `BUS_NOWAIT` fail with errno set to `os.errno.EAGAIN` + if other process is attempting to write @return 0 on success, -1 on error ''' cdef const char* cmessage @@ -234,3 +300,93 @@ def bus_read_wrapped(bus : int, callback : callable, user_data) -> int: user = (callback, user_data) return bus_read(<long>bus, <int (*)(const char *, void *)>&bus_callback_wrapper, <void *>user) + +def bus_poll_start_wrapped(bus : int, flags : int) -> int: + ''' + Announce that the thread is listening on the bus. + This is required so the will does not miss any + messages due to race conditions. Additionally, + not calling this function will cause the bus the + misbehave, is `bus_poll_wrapped` is written to expect + this function to have been called. + + @param bus Bus information + @param flags `BUS_NOWAIT` if the bus should fail and set `errno` to + `os.errno.EAGAIN` if there isn't already a message + available on + the bus when `bus_poll` is called + @return 0 on success, -1 on error + ''' + return bus_poll_start(<long>bus, <int>flags) + + +def bus_poll_stop_wrapped(bus : int) -> int: + ''' + Announce that the thread has stopped listening on the bus. + This is required so that the thread does not cause others + to wait indefinitely. + + @param bus Bus information + @return 0 on success, -1 on error + ''' + return bus_poll_stop(<long>bus) + + +def bus_poll_wrapped(bus : int) -> str: + ''' + Wait for a message to be broadcasted on the bus. + The caller should make a copy of the received message, + without freeing the original copy, and parse it in a + separate thread. When the new thread has started be + started, the caller of this function should then + either call `bus_poll_wrapped` again or + `bus_poll_stop_wrapped`. + + @param bus Bus information + @return The received message, `None` on error + ''' + cdef const char* msg + cdef bytes bs + msg = bus_poll(<long>bus) + if msg is NULL: + return None + bs = msg + return bs.decode('utf-8', 'strict') + + +def bus_chown_wrapped(file : str, owner : int, group : int) -> int: + ''' + Change the ownership of a bus + + `os.stat` can be used of the bus's associated file to get the bus's ownership + + @param file The pathname of the bus + @param owner The user ID of the bus's new owner + @param group The group ID of the bus's new group + @return 0 on success, -1 on error + ''' + cdef const char* cfile + cdef bytes bs + bs = file.encode('utf-8') + bytes([0]) + cfile = bs + return bus_chown(cfile, <uid_t>owner, <gid_t>group) + + +def bus_chmod_wrapped(file : str, mode : int) -> int: + ''' + Change the permissions for a bus + + `os.stat` can be used of the bus's associated file to get the bus's permissions + + @param file The pathname of the bus + @param mode The permissions of the bus, any permission for a user implies + full permissions for that user, except only the owner may + edit the bus's associated file + @return 0 on success, -1 on error + ''' + cdef const char* cfile + cdef bytes bs + bs = file.encode('utf-8') + bytes([0]) + cfile = bs + return bus_chmod(cfile, <mode_t>mode) + |