1 /* SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
13 #include <sys/types.h>
17 int main(int argc
, char *argv
[], char *envp
[])
19 int fd
, fd2
, input
= -1, pipes
[2] = { 0 }, status
;
23 if (argc
> 1 && argv
[argc
- 1][0] != '-') {
24 input
= open(argv
[1], O_RDONLY
);
28 perror("Error: unable to open input file");
31 if (pipe(pipes
) < 0) {
32 perror("Error: unable to open filter pipe");
37 fd
= open(getenv("HOME") ?: getenv("TMPDIR") ?: "/tmp", O_TMPFILE
| O_EXCL
| O_RDWR
, S_IWUSR
| S_IRUSR
);
39 perror("Error: unable to create temporary inode");
42 if (asprintf(&output_path
, "/proc/self/fd/%d", fd
) < 0) {
43 perror("Error: unable to allocate memory for fd string");
47 compiler_pid
= fork();
48 if (compiler_pid
< 0) {
49 perror("Error: unable to fork for compiler");
53 if (compiler_pid
== 0) {
54 const char *cc
= getenv("CC") ?: "gcc";
58 if (dup2(pipes
[0], 0) < 0) {
59 perror("Error: unable to duplicate pipe fd");
64 execlp(cc
, cc
, "-xc", "-o", output_path
, "-", NULL
);
73 len
= read(input
, beginning
, 2);
75 perror("Error: unable to read from input file");
77 } else if (len
== 2 && beginning
[0] == '#' && beginning
[1] == '!')
78 len
= write(pipes
[1], "//", 2);
80 len
= write(pipes
[1], beginning
, len
);
82 perror("Error: unable to write input preamble");
85 if (splice(input
, NULL
, pipes
[1], NULL
, 0x7fffffff, 0) < 0) {
86 perror("Error: unable to splice input to compiler child");
92 if (waitpid(compiler_pid
, &status
, 0) != compiler_pid
|| (!WIFEXITED(status
) || WEXITSTATUS(status
))) {
93 fprintf(stderr
, "Error: compiler process did not complete successfully\n");
97 fd2
= open(output_path
, O_RDONLY
);
99 perror("Error: unable to reopen temporary inode");
104 if (fexecve(fd2
, argv
, envp
) < 0) {
105 perror("Error: could not execute compiled program");