1 |
commit: 43ad7423ae06e9bcad672a21131f14e3ce790204 |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Feb 6 14:20:35 2022 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Feb 6 14:20:35 2022 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=43ad7423 |
7 |
|
8 |
libq/xsystem: cleanup/reuse same codepath, allow passing vector |
9 |
|
10 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
11 |
|
12 |
libq/xsystem.c | 96 ++++++++++++++++++++++++++++++++++++---------------------- |
13 |
libq/xsystem.h | 8 +++-- |
14 |
2 files changed, 65 insertions(+), 39 deletions(-) |
15 |
|
16 |
diff --git a/libq/xsystem.c b/libq/xsystem.c |
17 |
index e2dbc5e..05743ce 100644 |
18 |
--- a/libq/xsystem.c |
19 |
+++ b/libq/xsystem.c |
20 |
@@ -17,49 +17,73 @@ |
21 |
#include "xasprintf.h" |
22 |
#include "xsystem.h" |
23 |
|
24 |
-void xsystem(const char *command) |
25 |
-{ |
26 |
- if (unlikely(system(command))) |
27 |
- errp("system(%s) failed", command); |
28 |
-} |
29 |
- |
30 |
-void xsystembash(const char *command, int cwd) |
31 |
+void xsystembash(const char *command, const char **argv, int cwd) |
32 |
{ |
33 |
pid_t p = fork(); |
34 |
int status; |
35 |
|
36 |
switch (p) { |
37 |
- case 0: /* child */ |
38 |
- if (cwd != AT_FDCWD) |
39 |
- if (fchdir(cwd)) { |
40 |
- /* fchdir works with O_PATH starting w/linux-3.5 */ |
41 |
- if (errno == EBADF) { |
42 |
- char *path; |
43 |
- xasprintf(&path, "/proc/self/fd/%i", cwd); |
44 |
- if (chdir(path)) |
45 |
- errp("chdir(%s) failed", path); |
46 |
- } else |
47 |
- errp("fchdir(%i) failed", cwd); |
48 |
+ case 0: /* child */ |
49 |
+ if (cwd != AT_FDCWD) { |
50 |
+ if (fchdir(cwd)) { |
51 |
+ /* fchdir works with O_PATH starting w/linux-3.5 */ |
52 |
+ if (errno == EBADF) { |
53 |
+ char *path; |
54 |
+ xasprintf(&path, "/proc/self/fd/%i", cwd); |
55 |
+ if (chdir(path)) |
56 |
+ errp("chdir(%s) failed", path); |
57 |
+ } else { |
58 |
+ errp("fchdir(%i) failed", cwd); |
59 |
+ } |
60 |
+ } |
61 |
+ } |
62 |
+ if (argv == NULL) { |
63 |
+ execl(CONFIG_EPREFIX "bin/bash", "bash", |
64 |
+ "--norc", "--noprofile", "-c", command, (char *)NULL); |
65 |
+ /* Hrm, still here ? Maybe no bash ... */ |
66 |
+ _exit(execl("/bin/sh", "sh", "-c", command, (char *)NULL)); |
67 |
+ } else { |
68 |
+ int argc = 0; |
69 |
+ const char *a; |
70 |
+ const char **newargv; |
71 |
+ |
72 |
+ /* count existing args */ |
73 |
+ for (a = argv[0]; a != NULL; a++, argc++) |
74 |
+ ; |
75 |
+ argc += 1 + 1 + 1 + 1; |
76 |
+ newargv = xmalloc(sizeof(newargv[0]) * (argc + 1)); |
77 |
+ argc = 0; |
78 |
+ newargv[argc++] = "bash"; |
79 |
+ newargv[argc++] = "--norc"; |
80 |
+ newargv[argc++] = "--noprofile"; |
81 |
+ newargv[argc++] = "-c"; |
82 |
+ for (a = argv[0]; a != NULL; a++) |
83 |
+ newargv[argc++] = a; |
84 |
+ newargv[argc] = NULL; |
85 |
+ |
86 |
+ execv(CONFIG_EPREFIX "bin/bash", (char *const *)newargv); |
87 |
+ |
88 |
+ /* Hrm, still here ? Maybe no bash ... */ |
89 |
+ newargv = &newargv[2]; /* shift, two args less */ |
90 |
+ argc = 0; |
91 |
+ newargv[argc++] = "sh"; |
92 |
+ _exit(execv("/bin/sh", (char *const *)newargv)); |
93 |
} |
94 |
- execl(CONFIG_EPREFIX "bin/bash", "bash", |
95 |
- "--norc", "--noprofile", "-c", command, (char *)NULL); |
96 |
- /* Hrm, still here ? Maybe no bash ... */ |
97 |
- _exit(execl("/bin/sh", "sh", "-c", command, (char *)NULL)); |
98 |
|
99 |
- default: /* parent */ |
100 |
- waitpid(p, &status, 0); |
101 |
- if (WIFSIGNALED(status)) { |
102 |
- err("phase crashed with signal %i: %s", WTERMSIG(status), |
103 |
- strsignal(WTERMSIG(status))); |
104 |
- } else if (WIFEXITED(status)) { |
105 |
- if (WEXITSTATUS(status) == 0) |
106 |
- return; |
107 |
- else |
108 |
- err("phase exited %i", WEXITSTATUS(status)); |
109 |
- } |
110 |
- /* fall through */ |
111 |
+ default: /* parent */ |
112 |
+ waitpid(p, &status, 0); |
113 |
+ if (WIFSIGNALED(status)) { |
114 |
+ err("phase crashed with signal %i: %s", WTERMSIG(status), |
115 |
+ strsignal(WTERMSIG(status))); |
116 |
+ } else if (WIFEXITED(status)) { |
117 |
+ if (WEXITSTATUS(status) == 0) |
118 |
+ return; |
119 |
+ else |
120 |
+ err("phase exited %i", WEXITSTATUS(status)); |
121 |
+ } |
122 |
+ /* fall through */ |
123 |
|
124 |
- case -1: /* fucked */ |
125 |
- errp("xsystembash(%s) failed", command); |
126 |
+ case -1: /* fucked */ |
127 |
+ errp("xsystembash(%s) failed", command); |
128 |
} |
129 |
} |
130 |
|
131 |
diff --git a/libq/xsystem.h b/libq/xsystem.h |
132 |
index 833840d..d6c4fa4 100644 |
133 |
--- a/libq/xsystem.h |
134 |
+++ b/libq/xsystem.h |
135 |
@@ -1,14 +1,16 @@ |
136 |
/* |
137 |
- * Copyright 2010-2019 Gentoo Foundation |
138 |
+ * Copyright 2010-2022 Gentoo Foundation |
139 |
* Distributed under the terms of the GNU General Public License v2 |
140 |
* |
141 |
* Copyright 2010-2016 Mike Frysinger - <vapier@g.o> |
142 |
+ * Copyright 2022 Fabian Groffen - <grobian@g.o> |
143 |
*/ |
144 |
|
145 |
#ifndef _XSYSTEM_H |
146 |
#define _XSYSTEM_H 1 |
147 |
|
148 |
-void xsystem(const char *command); |
149 |
-void xsystembash(const char *command, int cwd); |
150 |
+void xsystembash(const char *command, const char **argv, int cwd); |
151 |
+#define xsystem(C,F) xsystembash(C, NULL, F) |
152 |
+#define xsystemv(V,F) xsystembash(NULL, V, F) |
153 |
|
154 |
#endif |