summaryrefslogtreecommitdiff
path: root/emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c
blob: 78c80e43a3a135497e82183ae2b49533a08bc010 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
--- a/bsd-user/freebsd/os-proc.c
--- b/bsd-user/freebsd/os-proc.c
@@ -83,7 +83,7 @@ out:
 }
 
 static int
-is_target_shell_script(int fd, char *interp, size_t size)
+is_target_shell_script(int fd, char *interp, size_t size, char **interp_args)
 {
     char buf[2], *p, *b;
     ssize_t n;
@@ -120,7 +120,21 @@ is_target_shell_script(int fd, char *int
             return 0;
         }
         if ((p = memchr(b, '\n', size)) != NULL) {
+            int hasargs = 0;
             *p = 0;
+
+            *interp_args = NULL;
+            p = interp;
+            while (*p) {
+                if ((*p == ' ') || (*p == '\t')) {
+                    hasargs = 1;
+                    *p = 0;
+                } else if (hasargs) {
+                    *interp_args = p;
+                    break;
+                }
+                ++p;
+            }
             return 1;
         }
         b += n;
@@ -136,7 +150,7 @@ is_target_shell_script(int fd, char *int
 abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
         abi_ulong guest_envp, int do_fexec)
 {
-    char **argp, **envp, **qargp, **qarg1, **qarg0;
+    char **argp, **envp, **qargp, **qarg1, **qarg0, **qargend;
     int argc, envc;
     abi_ulong gp;
     abi_ulong addr;
@@ -166,7 +180,7 @@ abi_long freebsd_exec_common(abi_ulong p
         envc++;
     }
 
-    qarg0 = argp =  alloca((argc + 4) * sizeof(void *));
+    qarg0 = argp =  alloca((argc + 5) * sizeof(void *));
     /* save the first agrument for the emulator */
     *argp++ = (char *)getprogname();
     qargp = argp;
@@ -188,7 +202,8 @@ abi_long freebsd_exec_common(abi_ulong p
         }
         total_size += strlen(*q) + 1;
     }
-    *q = NULL;
+    *q++ = NULL;
+    qargend = q;
 
     for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
         if (get_user_ual(addr, gp)) {
@@ -217,7 +232,7 @@ abi_long freebsd_exec_common(abi_ulong p
     }
 
     if (do_fexec) {
-        char execpath[PATH_MAX];
+        char execpath[PATH_MAX], *scriptargs;
 
         if (((int)path_or_fd > 0 &&
             is_target_elf_binary((int)path_or_fd)) == 1) {
@@ -238,7 +253,7 @@ abi_long freebsd_exec_common(abi_ulong p
                 goto execve_end;
             }
         } else if (is_target_shell_script((int)path_or_fd, execpath,
-                    sizeof(execpath)) != 0) {
+                    sizeof(execpath), &scriptargs) != 0) {
             char scriptpath[PATH_MAX];
 
             /* execve() as a target script using emulator. */
@@ -246,6 +261,10 @@ abi_long freebsd_exec_common(abi_ulong p
                         sizeof(scriptpath)) != NULL) {
                 *qargp = execpath;
                 *qarg1 = scriptpath;
+                if (scriptargs) {
+                    memmove(qarg1 + 1, qarg1, (qargend-qarg1) * sizeof(*qarg1));
+                    *qarg1 = scriptargs;
+                }
                 ret = get_errno(execve(qemu_proc_pathname, qarg0, envp));
             } else {
                 ret = -TARGET_EBADF;
@@ -256,7 +275,7 @@ abi_long freebsd_exec_common(abi_ulong p
         }
     } else {
         int fd;
-        char execpath[PATH_MAX];
+        char execpath[PATH_MAX], *scriptargs;
 
         p = lock_user_string(path_or_fd);
         if (p == NULL) {
@@ -275,11 +294,15 @@ abi_long freebsd_exec_common(abi_ulong p
             *qarg1 = (char *)p;
             ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
         } else if (is_target_shell_script(fd, execpath,
-                    sizeof(execpath)) != 0) {
+                    sizeof(execpath), &scriptargs) != 0) {
             close(fd);
             /* execve() as a target script using emulator. */
             *qargp = execpath;
             *qarg1 = (char *)p;
+            if (scriptargs) {
+                memmove(qarg1 + 1, qarg1, (qargend-qarg1) * sizeof(*qarg1));
+                *qarg1 = scriptargs;
+            }
             ret = get_errno(execve(qemu_proc_pathname, qarg0, envp));
         } else {
             close(fd);