configstring: rename variables to dts
[riscv-isa-sim.git] / spike_main / xspike.cc
1 // See LICENSE for license details.
2
3 // xspike forks an xterm for spike's target machine console,
4 // preserving the current terminal for debugging.
5
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <signal.h>
9 #include <sys/wait.h>
10 #include <cstdio>
11 #include <climits>
12 #include <cstring>
13 #include <stdexcept>
14
15 static pid_t fork_spike(int tty_fd, int argc, char** argv);
16 static pid_t fork_xterm(int* tty_fd);
17
18 int main(int argc, char** argv)
19 {
20 int tty_fd, wait_status, ret = -1;
21 pid_t xterm, spike;
22
23 static bool signal_exit = false;
24 auto handle_signal = [](int) { signal_exit = true; };
25
26 if ((xterm = fork_xterm(&tty_fd)) < 0)
27 {
28 fprintf(stderr, "could not open xterm\n");
29 goto out;
30 }
31
32 signal(SIGINT, handle_signal);
33
34 if ((spike = fork_spike(tty_fd, argc, argv)) < 0)
35 {
36 fprintf(stderr, "could not open spike\n");
37 goto close_xterm;
38 }
39
40 while ((ret = waitpid(spike, &wait_status, 0)) < 0)
41 if (signal_exit)
42 break;
43
44 if (ret < 0) // signal_exit
45 kill(spike, SIGTERM);
46 else
47 ret = WIFEXITED(wait_status) ? WEXITSTATUS(wait_status) : -1;
48
49 close_xterm:
50 kill(-xterm, SIGTERM);
51 out:
52 return ret;
53 }
54
55 static pid_t fork_spike(int tty_fd, int argc, char** argv)
56 {
57 pid_t pid = fork();
58 if (pid < 0)
59 return -1;
60
61 if (pid == 0)
62 {
63 if (dup2(tty_fd, STDIN_FILENO) < 0 || dup2(tty_fd, STDOUT_FILENO) < 0)
64 return -1;
65 execvp("spike", argv);
66 return -1;
67 }
68
69 return pid;
70 }
71
72 static pid_t fork_xterm(int* tty_fd)
73 {
74 static const char cmd[] = "3>&1 xterm -title xspike -e sh -c 'tty 1>&3; termios-xspike'";
75
76 int fds[2];
77 if (pipe(fds) < 0)
78 return -1;
79
80 pid_t pid = fork();
81 if (pid < 0)
82 return -1;
83
84 if (pid == 0)
85 {
86 setpgid(0, 0);
87 if (dup2(fds[1], STDOUT_FILENO) < 0)
88 return -1;
89 execl("/bin/sh", "sh", "-c", cmd, NULL);
90 return -1;
91 }
92
93 char tty[PATH_MAX];
94 ssize_t ttylen = read(fds[0], tty, sizeof(tty));
95 if (ttylen <= 1 || tty[ttylen-1] != '\n')
96 return -1;
97 tty[ttylen-1] = '\0';
98 if ((*tty_fd = open(tty, O_RDWR)) < 0)
99 return -1;
100
101 return pid;
102 }