diff options
author | midipix <writeonce@midipix.org> | 2016-03-08 14:30:50 -0500 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2016-03-10 08:32:39 -0500 |
commit | 528799aa1ab548dc649befeb9fa81f0d83f14a50 (patch) | |
tree | 64ea8f8d65152aff251c68bdb56c5ac115db174c | |
parent | a288c4f46e5e7d9c3e643a13572cda4c601d76dd (diff) | |
download | slibtool-528799aa1ab548dc649befeb9fa81f0d83f14a50.tar.bz2 slibtool-528799aa1ab548dc649befeb9fa81f0d83f14a50.tar.xz |
slbt_get_exec_ctx(), slbt_free_exec_ctx(): initial implementation.
-rw-r--r-- | include/slibtool/slibtool.h | 13 | ||||
-rw-r--r-- | project/common.mk | 1 | ||||
-rw-r--r-- | src/logic/slbt_exec_ctx.c | 164 |
3 files changed, 178 insertions, 0 deletions
diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h index 312c7cd..97f3b49 100644 --- a/include/slibtool/slibtool.h +++ b/include/slibtool/slibtool.h @@ -2,7 +2,9 @@ #define SOFORT_H #include <stdint.h> +#include <stddef.h> #include <stdio.h> +#include <unistd.h> #include "slibtool_api.h" @@ -76,6 +78,14 @@ struct slbt_input { size_t size; }; +struct slbt_exec_ctx { + char * program; + char ** argv; + char ** envp; + pid_t pid; + int exitcode; +}; + struct slbt_common_ctx { uint64_t drvflags; uint64_t actflags; @@ -115,6 +125,9 @@ slbt_api void slbt_free_driver_ctx (struct slbt_driver_ctx *); slbt_api int slbt_get_unit_ctx (const struct slbt_driver_ctx *, const char * path, struct slbt_unit_ctx **); slbt_api void slbt_free_unit_ctx (struct slbt_unit_ctx *); +slbt_api int slbt_get_exec_ctx (const struct slbt_driver_ctx *, struct slbt_exec_ctx **); +slbt_api void slbt_free_exec_ctx (struct slbt_exec_ctx *); + slbt_api int slbt_map_input (int fd, const char * path, int prot, struct slbt_input *); slbt_api int slbt_unmap_input (struct slbt_input *); diff --git a/project/common.mk b/project/common.mk index 45a3d8f..0dcdcd6 100644 --- a/project/common.mk +++ b/project/common.mk @@ -1,6 +1,7 @@ COMMON_SRCS = \ src/driver/slbt_driver_ctx.c \ src/driver/slbt_unit_ctx.c \ + src/logic/slbt_exec_ctx.c \ src/logic/slbt_map_input.c \ src/skin/slbt_skin_default.c \ diff --git a/src/logic/slbt_exec_ctx.c b/src/logic/slbt_exec_ctx.c new file mode 100644 index 0000000..87d8412 --- /dev/null +++ b/src/logic/slbt_exec_ctx.c @@ -0,0 +1,164 @@ +/*******************************************************************/ +/* slibtool: a skinny libtool implementation, written in C */ +/* Copyright (C) 2016 Z. Gilboa */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#include <stdint.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#include <slibtool/slibtool.h> + +#define SLBT_ARGV_SPARE_PTRS 16 + +struct slbt_exec_ctx_impl { + int argc; + char * args; + struct slbt_exec_ctx ctx; + char * buffer[]; +}; + + +static size_t slbt_parse_comma_separated_flags( + const char * str, + int * argc) +{ + const char * ch; + + for (ch=str; *ch; ch++) + if (*ch == ',') + (*argc)++; + + return ch - str; +} + + +static struct slbt_exec_ctx_impl * slbt_exec_ctx_alloc( + const struct slbt_driver_ctx * dctx) +{ + struct slbt_exec_ctx_impl * ictx; + size_t size; + int argc; + char * args; + char ** parg; + + size = argc = 0; + + /* buffer size (cargv, -Wc) */ + for (parg=dctx->cctx->cargv; *parg; parg++, argc++) + if (!(strncmp("-Wc,",*parg,4))) + size += sizeof('\0') + slbt_parse_comma_separated_flags( + parg[4],&argc); + else + size += sizeof('\0') + strlen(*parg); + + /* alloc */ + if (!(args = malloc(size + strlen(".libs/") + + strlen(".lo") + + strlen(dctx->cctx->output)))) + return 0; + + size = sizeof(*ictx) + (argc+SLBT_ARGV_SPARE_PTRS)*sizeof(char *); + + if (!(ictx = calloc(1,size))) { + free(args); + return 0; + } + + ictx->args = args; + ictx->argc = argc; + + return ictx; +} + + +int slbt_get_exec_ctx( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx ** ectx) +{ + struct slbt_exec_ctx_impl * ictx; + char ** parg; + char * ch; + char * slash; + int i; + + /* alloc */ + if (!(ictx = slbt_exec_ctx_alloc(dctx))) + return -1; + + /* init with guard for later .lo check */ + ch = ictx->args + strlen(".lo"); + ictx->ctx.argv = ictx->buffer; + + /* <compiler> */ + ictx->ctx.program = dctx->cctx->cargv[0]; + + /* cargv, -Wc */ + for (i=0, parg=dctx->cctx->cargv; *parg; parg++, ch++) { + if (!(strncmp("-Wc,",*parg,4))) { + strcpy(ch,parg[4]); + ictx->ctx.argv[i++] = ch; + + for (; *ch; ch++) + if (*ch == ',') { + *ch = '\0'; + ictx->ctx.argv[i++] = ch+1; + } + } else { + ictx->ctx.argv[i++] = ch; + ch += sprintf(ch,"%s",*parg); + } + } + + if (dctx->cctx->mode == SLBT_MODE_COMPILE) { + if (dctx->cctx->drvflags & SLBT_DRIVER_SHARED) { + ictx->ctx.argv[i++] = "-DPIC"; + ictx->ctx.argv[i++] = "-fPIC"; + } + + ictx->ctx.argv[i++] = "-c"; + ictx->ctx.argv[i++] = "-o"; + ictx->ctx.argv[i++] = ch; + + if ((slash = strrchr(dctx->cctx->output,'/'))) { + sprintf(ch,"%s",dctx->cctx->output); + ch += slash - dctx->cctx->output; + ch += sprintf(ch,"/.libs%s",slash); + } else + ch += sprintf(ch,".libs/%s",dctx->cctx->output); + + if ((ch[-3] == '.') && (ch[-2] == 'l') && (ch[-1] == 'o')) { + ch[-2] = 'o'; + ch[-1] = '\0'; + ch--; + } + } + + *ectx = &ictx->ctx; + return 0; +} + + +static int slbt_free_exec_ctx_impl( + struct slbt_exec_ctx_impl * ictx, + int status) +{ + free(ictx->args); + free (ictx); + return status; +} + + +void slbt_free_exec_ctx(struct slbt_exec_ctx * ctx) +{ + struct slbt_exec_ctx_impl * ictx; + uintptr_t addr; + + if (ctx) { + addr = (uintptr_t)ctx - offsetof(struct slbt_exec_ctx_impl,ctx); + ictx = (struct slbt_exec_ctx_impl *)addr; + slbt_free_exec_ctx_impl(ictx,0); + } +} |