diff --git a/libXmd/build.sh b/libXmd/build.sh index 0d821af..f23c380 100755 --- a/libXmd/build.sh +++ b/libXmd/build.sh @@ -1,9 +1,17 @@ #!/bin/sh . ../scripts/flags.sh +BUILDFLAGS="$CFLAGS -Iinclude" +LINTCHECKS="-checks=-*,clang-analyzer-*,bugprone-*,portability-*,cert-*" +SOURCE="src/*.c" function build() { - cc $CFLAGS -Iinclude -shared -o "lib/libXmd.so" src/*.c || \ + cc $SOURCE -o "lib/libXmd.so" -shared $BUILDFLAGS || \ + echo "XXX FAIL!" +} + +function lint() { + clang-tidy $SOURCE $LINTCHECKS -- $BUILDFLAGS || \ echo "XXX FAIL!" } @@ -21,6 +29,9 @@ install) clean) clean ;; +lint) + lint + ;; *) build esac diff --git a/libXmd/include/Xmd/Buffer.h b/libXmd/include/Xmd/Buffer.h index ce0f2db..a89f7c3 100644 --- a/libXmd/include/Xmd/Buffer.h +++ b/libXmd/include/Xmd/Buffer.h @@ -13,18 +13,20 @@ typedef struct _XmdBuffer XmdBuffer; #define XmdBufferNew(type) _XmdBufferNew(sizeof(type)); XmdBuffer *_XmdBufferNew (Cardinal size); -/* XmdBufferPush adds a new element to the buffer. */ +/* XmdBufferPush adds a new element to the buffer. If element is NULL, the new + element in the buffer is set to all zeros. */ void XmdBufferPush (XmdBuffer *buffer, void *element); /* XmdBufferPop copies the last element into element, and removes it from the - buffer. */ + buffer. If element is NULL, it removes the element without copying it. */ void XmdBufferPop (XmdBuffer *buffer, void *element); -/* XmdBufferPoke sets a single element of the buffer. */ +/* XmdBufferPoke sets a single element of the buffer. If element is NULL, the + element in the buffer is instead set to all zeros. */ void XmdBufferPoke (XmdBuffer *buffer, Cardinal index, void *element); /* XmdBufferPeek copies the value of a single element of the buffer into - element. */ + element. If element is NULL, this function does nothing. */ void XmdBufferPeek (XmdBuffer *buffer, Cardinal index, void *element); /* XmdBufferBreak frees the buffer without freeing its data. Its data is diff --git a/libXmd/include/Xmd/Exec.h b/libXmd/include/Xmd/Exec.h new file mode 100644 index 0000000..4c50ecf --- /dev/null +++ b/libXmd/include/Xmd/Exec.h @@ -0,0 +1,12 @@ +#ifndef _XmdExec_h +#define _XmdExec_h + +#include +#include +#include + +FILE *XmdVaPipedExecPath (const String file, pid_t *child, String mode, ...); + +FILE *XmdPipedExecPath (const String file, pid_t *child, String mode, String const argv[]); + +#endif diff --git a/libXmd/src/Buffer.c b/libXmd/src/Buffer.c index ac02b3a..a7078d6 100644 --- a/libXmd/src/Buffer.c +++ b/libXmd/src/Buffer.c @@ -40,17 +40,21 @@ void XmdBufferResize (XmdBuffer *buffer, Cardinal length) { void XmdBufferFit (XmdBuffer *buffer) { if (buffer->length > buffer->capacity) { - puts("fitting"); buffer->capacity *= XmdBUFFER_GROWTH_FACTOR; - buffer->data = XtReallocArray ( + void *data = XtReallocArray ( buffer->data, buffer->capacity, buffer->size); + if (data == NULL) { + /* TODO return error */ + } + buffer->data = data; } } void *XmdBufferOffset (XmdBuffer *buffer, Cardinal index) { - return buffer->data + (index * buffer->size); + char *data = buffer->data; + return (void *)(data + ((size_t)(index) * buffer->size)); } void XmdBufferPush (XmdBuffer *buffer, void *element) { @@ -67,14 +71,19 @@ void XmdBufferPop (XmdBuffer *buffer, void *element) { void XmdBufferPoke (XmdBuffer *buffer, Cardinal index, void *element) { if (index > buffer->length) return; - memcpy ( - XmdBufferOffset(buffer, index), - element, - buffer->size); + char *destination = XmdBufferOffset(buffer, index); + char *source = element; + + if (source == NULL) { + memset(destination, 0, buffer->size); + } else { + memcpy(destination, source, buffer->size); + } } void XmdBufferPeek (XmdBuffer *buffer, Cardinal index, void *element) { if (index > buffer->length) return; + if (element == NULL) return; memcpy ( element, XmdBufferOffset(buffer, index), diff --git a/libXmd/src/Exec.c b/libXmd/src/Exec.c new file mode 100644 index 0000000..bfb1a73 --- /dev/null +++ b/libXmd/src/Exec.c @@ -0,0 +1,49 @@ +#define _POSIX_C_SOURCE 200112L + +#include +#include + +#include +#include +#include +#include + +FILE *XmdVaPipedExecPath (const String file, pid_t *child, String mode, ...) { + XmdBuffer *buffer = XmdBufferNew(String); + va_list argList; + va_start(argList, mode); + + while (1) { + String arg = va_arg(argList, String); + if (arg == NULL) break; + XmdBufferPush(buffer, &arg); + } + + va_end(argList); + String *args = XmdBufferBreak(buffer); + FILE* pipe = XmdPipedExecPath(file, child, mode, args); + XtFree((char *)(args)); + return pipe; +} + +FILE *XmdPipedExecPath (const String file, pid_t *child, String mode, String const argv[]) { + int pipes[2]; + pipe(pipes); + + pid_t pid = fork(); + switch (pid) { + case -1: /* fail */ + return NULL; + case 0: /* child */ + dup2(pipes[1], STDOUT_FILENO); + close(pipes[0]); + close(pipes[1]); + execvp(file, argv); + exit(EXIT_FAILURE); + return NULL; + default: /* parent */ + close(pipes[1]); + *child = pid; + return fdopen(pipes[0], mode); + } +}