diff options
Diffstat (limited to 'src/driver/amgc_unit_ctx.c')
-rw-r--r-- | src/driver/amgc_unit_ctx.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/src/driver/amgc_unit_ctx.c b/src/driver/amgc_unit_ctx.c index d2268fd..0498a68 100644 --- a/src/driver/amgc_unit_ctx.c +++ b/src/driver/amgc_unit_ctx.c @@ -8,6 +8,8 @@ #include <stddef.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> +#include <errno.h> #include <sys/mman.h> #include <apimagic/apimagic.h> @@ -23,18 +25,84 @@ static int amgc_free_unit_ctx_impl(struct amgc_unit_ctx_impl * ctx, int status) return status; } +static FILE * amgc_stdin_to_tmp(const struct amgc_driver_ctx * dctx) +{ + struct amgc_driver_ctx_impl * ictx; + uintptr_t addr; + int fdtmp; + + FILE * ftmp; + char buf[4096]; + ssize_t nread; + int ret; + + addr = (uintptr_t)dctx - offsetof(struct amgc_driver_ctx_impl,ctx); + ictx = (struct amgc_driver_ctx_impl *)addr; + + if (ictx->fdtmpin >= 0) { + if ((fdtmp = dup(ictx->fdtmpin)) < 0) + return 0; + + if (!(ftmp = fdopen(fdtmp,"r"))) + close(fdtmp); + + return ftmp; + } + + if (!(ftmp = tmpfile())) + return 0; + + if ((ictx->fdtmpin = dup(fileno(ftmp))) < 0) { + fclose(ftmp); + return 0; + } + + nread = read(0,buf,sizeof(buf)-1); + + while (nread) { + if (nread > 0) { + buf[nread] = '\0'; + ret = fputs(buf,ftmp); + } else + ret = (errno == EINTR) ? 0 : -1; + + if (ret < 0) { + fclose(ftmp); + return 0; + } + + nread = read(0,buf,sizeof(buf)-1); + } + + return ftmp; +} + int amgc_get_unit_ctx( const struct amgc_driver_ctx * dctx, const char * path, struct amgc_unit_ctx ** pctx) { struct amgc_unit_ctx_impl * ctx; + FILE * ftmp; + int fd; if (!dctx || !(ctx = calloc(sizeof(*ctx),1))) return -1; - if (amgc_map_input(-1,path,PROT_READ,&ctx->map)) + if (strcmp(path,"-")) + fd = -1; + else if (!(ftmp = amgc_stdin_to_tmp(dctx))) + return amgc_free_unit_ctx_impl(ctx,-1); + else if ((fd = dup(fileno(ftmp))) < 0) return amgc_free_unit_ctx_impl(ctx,-1); + else + fclose(ftmp); + + if (amgc_map_input(fd,path,PROT_READ,&ctx->map)) + return amgc_free_unit_ctx_impl(ctx,-1); + + if (fd > 0) + close(fd); memcpy(&ctx->cctx,dctx->cctx, sizeof(ctx->cctx)); |