summaryrefslogtreecommitdiffhomepage
path: root/src/helper
diff options
context:
space:
mode:
Diffstat (limited to 'src/helper')
-rw-r--r--src/helper/slbt_dump_machine.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/helper/slbt_dump_machine.c b/src/helper/slbt_dump_machine.c
new file mode 100644
index 0000000..0ef13d5
--- /dev/null
+++ b/src/helper/slbt_dump_machine.c
@@ -0,0 +1,113 @@
+/*******************************************************************/
+/* slibtool: a skinny libtool implementation, written in C */
+/* Copyright (C) 2016 Z. Gilboa */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <stdio.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/wait.h>
+
+#include <slibtool/slibtool.h>
+#include "slibtool_spawn_impl.h"
+
+static int slbt_dump_machine_child(
+ char * program,
+ int fd[2])
+{
+ char * compiler;
+ char * argv[3];
+
+ if ((compiler = strchr(program,'/')))
+ compiler++;
+ else
+ compiler = program;
+
+ argv[0] = compiler;
+ argv[1] = "-dumpmachine";
+ argv[2] = 0;
+
+ close(fd[0]);
+ close(0);
+ close(1);
+
+ if ((fd[0] = open("/dev/null",O_RDONLY)))
+ exit(EXIT_FAILURE);
+
+ if (dup(fd[1]) == 1)
+ execvp(program,argv);
+
+ exit(EXIT_FAILURE);
+ return -1;
+}
+
+int slbt_dump_machine(
+ const char * compiler,
+ char * machine,
+ size_t bufsize)
+{
+ pid_t pid;
+ pid_t rpid;
+ int code;
+ int fd[2];
+ FILE * fmachine;
+ char * newline;
+ char check[2];
+ char program[PATH_MAX];
+
+ if (!machine || !bufsize)
+ return -1;
+
+ if ((size_t)snprintf(program,sizeof(program),"%s",
+ compiler) >= sizeof(program))
+ return -1;
+
+ if (pipe(fd))
+ return -1;
+
+ if ((pid = fork()) < 0) {
+ close(fd[0]);
+ close(fd[1]);
+ return -1;
+ }
+
+ if (pid == 0)
+ return slbt_dump_machine_child(
+ program,
+ fd);
+
+ rpid = waitpid(
+ pid,
+ &code,
+ 0);
+
+ if ((rpid != pid) || code) {
+ close(fd[0]);
+ close(fd[1]);
+ return -1;
+ }
+
+ if ((fmachine = fdopen(fd[0],"r"))) {
+ close(fd[1]);
+ newline = 0;
+
+ if (fgets(machine,bufsize,fmachine) == machine)
+ if (!fgets(check,sizeof(check),fmachine))
+ if (feof(fmachine))
+ if ((newline = strrchr(machine,'\n')))
+ *newline = 0;
+
+ fclose(fmachine);
+ } else {
+ newline = 0;
+ close(fd[0]);
+ close(fd[1]);
+ }
+
+ return newline ? 0 : -1;
+}