root / os-posix.c @ 904ebffe
History | View | Annotate | Download (8.5 kB)
1 | 86b645e7 | Jes Sorensen | /*
|
---|---|---|---|
2 | 86b645e7 | Jes Sorensen | * os-posix.c
|
3 | 86b645e7 | Jes Sorensen | *
|
4 | 86b645e7 | Jes Sorensen | * Copyright (c) 2003-2008 Fabrice Bellard
|
5 | 86b645e7 | Jes Sorensen | * Copyright (c) 2010 Red Hat, Inc.
|
6 | 86b645e7 | Jes Sorensen | *
|
7 | 86b645e7 | Jes Sorensen | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 | 86b645e7 | Jes Sorensen | * of this software and associated documentation files (the "Software"), to deal
|
9 | 86b645e7 | Jes Sorensen | * in the Software without restriction, including without limitation the rights
|
10 | 86b645e7 | Jes Sorensen | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 | 86b645e7 | Jes Sorensen | * copies of the Software, and to permit persons to whom the Software is
|
12 | 86b645e7 | Jes Sorensen | * furnished to do so, subject to the following conditions:
|
13 | 86b645e7 | Jes Sorensen | *
|
14 | 86b645e7 | Jes Sorensen | * The above copyright notice and this permission notice shall be included in
|
15 | 86b645e7 | Jes Sorensen | * all copies or substantial portions of the Software.
|
16 | 86b645e7 | Jes Sorensen | *
|
17 | 86b645e7 | Jes Sorensen | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 | 86b645e7 | Jes Sorensen | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 | 86b645e7 | Jes Sorensen | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
20 | 86b645e7 | Jes Sorensen | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 | 86b645e7 | Jes Sorensen | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 | 86b645e7 | Jes Sorensen | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 | 86b645e7 | Jes Sorensen | * THE SOFTWARE.
|
24 | 86b645e7 | Jes Sorensen | */
|
25 | 86b645e7 | Jes Sorensen | |
26 | 86b645e7 | Jes Sorensen | #include <unistd.h> |
27 | 86b645e7 | Jes Sorensen | #include <fcntl.h> |
28 | 86b645e7 | Jes Sorensen | #include <signal.h> |
29 | 8d963e6a | Jes Sorensen | #include <sys/types.h> |
30 | 8d963e6a | Jes Sorensen | #include <sys/wait.h> |
31 | 69e8b162 | Jes Sorensen | /*needed for MAP_POPULATE before including qemu-options.h */
|
32 | 69e8b162 | Jes Sorensen | #include <sys/mman.h> |
33 | 8847cfe8 | Jes Sorensen | #include <pwd.h> |
34 | 6170540b | Jes Sorensen | #include <libgen.h> |
35 | 86b645e7 | Jes Sorensen | |
36 | 86b645e7 | Jes Sorensen | /* Needed early for CONFIG_BSD etc. */
|
37 | 86b645e7 | Jes Sorensen | #include "config-host.h" |
38 | 86b645e7 | Jes Sorensen | #include "sysemu.h" |
39 | 59a5264b | Jes Sorensen | #include "net/slirp.h" |
40 | 59a5264b | Jes Sorensen | #include "qemu-options.h" |
41 | 86b645e7 | Jes Sorensen | |
42 | ce798cf2 | Jes Sorensen | #ifdef CONFIG_LINUX
|
43 | ce798cf2 | Jes Sorensen | #include <sys/prctl.h> |
44 | ce798cf2 | Jes Sorensen | #endif
|
45 | ce798cf2 | Jes Sorensen | |
46 | 949d31e6 | Jes Sorensen | #ifdef CONFIG_EVENTFD
|
47 | 949d31e6 | Jes Sorensen | #include <sys/eventfd.h> |
48 | 949d31e6 | Jes Sorensen | #endif
|
49 | 949d31e6 | Jes Sorensen | |
50 | 8847cfe8 | Jes Sorensen | static struct passwd *user_pwd; |
51 | 0766379d | Jes Sorensen | static const char *chroot_dir; |
52 | eb505be1 | Jes Sorensen | static int daemonize; |
53 | eb505be1 | Jes Sorensen | static int fds[2]; |
54 | 8847cfe8 | Jes Sorensen | |
55 | fe98ac14 | Jes Sorensen | void os_setup_early_signal_handling(void) |
56 | 86b645e7 | Jes Sorensen | { |
57 | 86b645e7 | Jes Sorensen | struct sigaction act;
|
58 | 86b645e7 | Jes Sorensen | sigfillset(&act.sa_mask); |
59 | 86b645e7 | Jes Sorensen | act.sa_flags = 0;
|
60 | 86b645e7 | Jes Sorensen | act.sa_handler = SIG_IGN; |
61 | 86b645e7 | Jes Sorensen | sigaction(SIGPIPE, &act, NULL);
|
62 | 86b645e7 | Jes Sorensen | } |
63 | 8d963e6a | Jes Sorensen | |
64 | 8d963e6a | Jes Sorensen | static void termsig_handler(int signal) |
65 | 8d963e6a | Jes Sorensen | { |
66 | 8d963e6a | Jes Sorensen | qemu_system_shutdown_request(); |
67 | 8d963e6a | Jes Sorensen | } |
68 | 8d963e6a | Jes Sorensen | |
69 | 8d963e6a | Jes Sorensen | static void sigchld_handler(int signal) |
70 | 8d963e6a | Jes Sorensen | { |
71 | 8d963e6a | Jes Sorensen | waitpid(-1, NULL, WNOHANG); |
72 | 8d963e6a | Jes Sorensen | } |
73 | 8d963e6a | Jes Sorensen | |
74 | 8d963e6a | Jes Sorensen | void os_setup_signal_handling(void) |
75 | 8d963e6a | Jes Sorensen | { |
76 | 8d963e6a | Jes Sorensen | struct sigaction act;
|
77 | 8d963e6a | Jes Sorensen | |
78 | 8d963e6a | Jes Sorensen | memset(&act, 0, sizeof(act)); |
79 | 8d963e6a | Jes Sorensen | act.sa_handler = termsig_handler; |
80 | 8d963e6a | Jes Sorensen | sigaction(SIGINT, &act, NULL);
|
81 | 8d963e6a | Jes Sorensen | sigaction(SIGHUP, &act, NULL);
|
82 | 8d963e6a | Jes Sorensen | sigaction(SIGTERM, &act, NULL);
|
83 | 8d963e6a | Jes Sorensen | |
84 | 8d963e6a | Jes Sorensen | act.sa_handler = sigchld_handler; |
85 | 8d963e6a | Jes Sorensen | act.sa_flags = SA_NOCLDSTOP; |
86 | 8d963e6a | Jes Sorensen | sigaction(SIGCHLD, &act, NULL);
|
87 | 8d963e6a | Jes Sorensen | } |
88 | 6170540b | Jes Sorensen | |
89 | 6170540b | Jes Sorensen | /* Find a likely location for support files using the location of the binary.
|
90 | 6170540b | Jes Sorensen | For installed binaries this will be "$bindir/../share/qemu". When
|
91 | 6170540b | Jes Sorensen | running from the build tree this will be "$bindir/../pc-bios". */
|
92 | 6170540b | Jes Sorensen | #define SHARE_SUFFIX "/share/qemu" |
93 | 6170540b | Jes Sorensen | #define BUILD_SUFFIX "/pc-bios" |
94 | 6170540b | Jes Sorensen | char *os_find_datadir(const char *argv0) |
95 | 6170540b | Jes Sorensen | { |
96 | 6170540b | Jes Sorensen | char *dir;
|
97 | 6170540b | Jes Sorensen | char *p = NULL; |
98 | 6170540b | Jes Sorensen | char *res;
|
99 | 6170540b | Jes Sorensen | char buf[PATH_MAX];
|
100 | 6170540b | Jes Sorensen | size_t max_len; |
101 | 6170540b | Jes Sorensen | |
102 | 6170540b | Jes Sorensen | #if defined(__linux__)
|
103 | 6170540b | Jes Sorensen | { |
104 | 6170540b | Jes Sorensen | int len;
|
105 | 6170540b | Jes Sorensen | len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); |
106 | 6170540b | Jes Sorensen | if (len > 0) { |
107 | 6170540b | Jes Sorensen | buf[len] = 0;
|
108 | 6170540b | Jes Sorensen | p = buf; |
109 | 6170540b | Jes Sorensen | } |
110 | 6170540b | Jes Sorensen | } |
111 | 6170540b | Jes Sorensen | #elif defined(__FreeBSD__)
|
112 | 6170540b | Jes Sorensen | { |
113 | 6170540b | Jes Sorensen | static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; |
114 | 6170540b | Jes Sorensen | size_t len = sizeof(buf) - 1; |
115 | 6170540b | Jes Sorensen | |
116 | 6170540b | Jes Sorensen | *buf = '\0';
|
117 | 66fe09ee | Blue Swirl | if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) && |
118 | 6170540b | Jes Sorensen | *buf) { |
119 | 6170540b | Jes Sorensen | buf[sizeof(buf) - 1] = '\0'; |
120 | 6170540b | Jes Sorensen | p = buf; |
121 | 6170540b | Jes Sorensen | } |
122 | 6170540b | Jes Sorensen | } |
123 | 6170540b | Jes Sorensen | #endif
|
124 | 6170540b | Jes Sorensen | /* If we don't have any way of figuring out the actual executable
|
125 | 6170540b | Jes Sorensen | location then try argv[0]. */
|
126 | 6170540b | Jes Sorensen | if (!p) {
|
127 | 6170540b | Jes Sorensen | p = realpath(argv0, buf); |
128 | 6170540b | Jes Sorensen | if (!p) {
|
129 | 6170540b | Jes Sorensen | return NULL; |
130 | 6170540b | Jes Sorensen | } |
131 | 6170540b | Jes Sorensen | } |
132 | 6170540b | Jes Sorensen | dir = dirname(p); |
133 | 6170540b | Jes Sorensen | dir = dirname(dir); |
134 | 6170540b | Jes Sorensen | |
135 | 6170540b | Jes Sorensen | max_len = strlen(dir) + |
136 | 6170540b | Jes Sorensen | MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
|
137 | 6170540b | Jes Sorensen | res = qemu_mallocz(max_len); |
138 | 6170540b | Jes Sorensen | snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
|
139 | 6170540b | Jes Sorensen | if (access(res, R_OK)) {
|
140 | 6170540b | Jes Sorensen | snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
|
141 | 6170540b | Jes Sorensen | if (access(res, R_OK)) {
|
142 | 6170540b | Jes Sorensen | qemu_free(res); |
143 | 6170540b | Jes Sorensen | res = NULL;
|
144 | 6170540b | Jes Sorensen | } |
145 | 6170540b | Jes Sorensen | } |
146 | 6170540b | Jes Sorensen | |
147 | 6170540b | Jes Sorensen | return res;
|
148 | 6170540b | Jes Sorensen | } |
149 | 6170540b | Jes Sorensen | #undef SHARE_SUFFIX
|
150 | 6170540b | Jes Sorensen | #undef BUILD_SUFFIX
|
151 | 59a5264b | Jes Sorensen | |
152 | ce798cf2 | Jes Sorensen | void os_set_proc_name(const char *s) |
153 | ce798cf2 | Jes Sorensen | { |
154 | ce798cf2 | Jes Sorensen | #if defined(PR_SET_NAME)
|
155 | ce798cf2 | Jes Sorensen | char name[16]; |
156 | ce798cf2 | Jes Sorensen | if (!s)
|
157 | ce798cf2 | Jes Sorensen | return;
|
158 | ce798cf2 | Jes Sorensen | name[sizeof(name) - 1] = 0; |
159 | ce798cf2 | Jes Sorensen | strncpy(name, s, sizeof(name));
|
160 | ce798cf2 | Jes Sorensen | /* Could rewrite argv[0] too, but that's a bit more complicated.
|
161 | ce798cf2 | Jes Sorensen | This simple way is enough for `top'. */
|
162 | ce798cf2 | Jes Sorensen | if (prctl(PR_SET_NAME, name)) {
|
163 | ce798cf2 | Jes Sorensen | perror("unable to change process name");
|
164 | ce798cf2 | Jes Sorensen | exit(1);
|
165 | ce798cf2 | Jes Sorensen | } |
166 | ce798cf2 | Jes Sorensen | #else
|
167 | ce798cf2 | Jes Sorensen | fprintf(stderr, "Change of process name not supported by your OS\n");
|
168 | ce798cf2 | Jes Sorensen | exit(1);
|
169 | ce798cf2 | Jes Sorensen | #endif
|
170 | ce798cf2 | Jes Sorensen | } |
171 | ce798cf2 | Jes Sorensen | |
172 | 59a5264b | Jes Sorensen | /*
|
173 | 59a5264b | Jes Sorensen | * Parse OS specific command line options.
|
174 | 59a5264b | Jes Sorensen | * return 0 if option handled, -1 otherwise
|
175 | 59a5264b | Jes Sorensen | */
|
176 | 59a5264b | Jes Sorensen | void os_parse_cmd_args(int index, const char *optarg) |
177 | 59a5264b | Jes Sorensen | { |
178 | 59a5264b | Jes Sorensen | switch (index) {
|
179 | 59a5264b | Jes Sorensen | #ifdef CONFIG_SLIRP
|
180 | 59a5264b | Jes Sorensen | case QEMU_OPTION_smb:
|
181 | 59a5264b | Jes Sorensen | if (net_slirp_smb(optarg) < 0) |
182 | 59a5264b | Jes Sorensen | exit(1);
|
183 | 59a5264b | Jes Sorensen | break;
|
184 | 59a5264b | Jes Sorensen | #endif
|
185 | 8847cfe8 | Jes Sorensen | case QEMU_OPTION_runas:
|
186 | 8847cfe8 | Jes Sorensen | user_pwd = getpwnam(optarg); |
187 | 8847cfe8 | Jes Sorensen | if (!user_pwd) {
|
188 | 8847cfe8 | Jes Sorensen | fprintf(stderr, "User \"%s\" doesn't exist\n", optarg);
|
189 | 8847cfe8 | Jes Sorensen | exit(1);
|
190 | 8847cfe8 | Jes Sorensen | } |
191 | 8847cfe8 | Jes Sorensen | break;
|
192 | 0766379d | Jes Sorensen | case QEMU_OPTION_chroot:
|
193 | 0766379d | Jes Sorensen | chroot_dir = optarg; |
194 | 0766379d | Jes Sorensen | break;
|
195 | eb505be1 | Jes Sorensen | case QEMU_OPTION_daemonize:
|
196 | eb505be1 | Jes Sorensen | daemonize = 1;
|
197 | eb505be1 | Jes Sorensen | break;
|
198 | 59a5264b | Jes Sorensen | } |
199 | 59a5264b | Jes Sorensen | return;
|
200 | 59a5264b | Jes Sorensen | } |
201 | 8847cfe8 | Jes Sorensen | |
202 | e06eb601 | Jes Sorensen | static void change_process_uid(void) |
203 | 8847cfe8 | Jes Sorensen | { |
204 | 8847cfe8 | Jes Sorensen | if (user_pwd) {
|
205 | 8847cfe8 | Jes Sorensen | if (setgid(user_pwd->pw_gid) < 0) { |
206 | 8847cfe8 | Jes Sorensen | fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid);
|
207 | 8847cfe8 | Jes Sorensen | exit(1);
|
208 | 8847cfe8 | Jes Sorensen | } |
209 | 8847cfe8 | Jes Sorensen | if (setuid(user_pwd->pw_uid) < 0) { |
210 | 8847cfe8 | Jes Sorensen | fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid);
|
211 | 8847cfe8 | Jes Sorensen | exit(1);
|
212 | 8847cfe8 | Jes Sorensen | } |
213 | 8847cfe8 | Jes Sorensen | if (setuid(0) != -1) { |
214 | 8847cfe8 | Jes Sorensen | fprintf(stderr, "Dropping privileges failed\n");
|
215 | 8847cfe8 | Jes Sorensen | exit(1);
|
216 | 8847cfe8 | Jes Sorensen | } |
217 | 8847cfe8 | Jes Sorensen | } |
218 | 8847cfe8 | Jes Sorensen | } |
219 | 0766379d | Jes Sorensen | |
220 | e06eb601 | Jes Sorensen | static void change_root(void) |
221 | 0766379d | Jes Sorensen | { |
222 | 0766379d | Jes Sorensen | if (chroot_dir) {
|
223 | 0766379d | Jes Sorensen | if (chroot(chroot_dir) < 0) { |
224 | 0766379d | Jes Sorensen | fprintf(stderr, "chroot failed\n");
|
225 | 0766379d | Jes Sorensen | exit(1);
|
226 | 0766379d | Jes Sorensen | } |
227 | 0766379d | Jes Sorensen | if (chdir("/")) { |
228 | 0766379d | Jes Sorensen | perror("not able to chdir to /");
|
229 | 0766379d | Jes Sorensen | exit(1);
|
230 | 0766379d | Jes Sorensen | } |
231 | 0766379d | Jes Sorensen | } |
232 | 0766379d | Jes Sorensen | |
233 | 0766379d | Jes Sorensen | } |
234 | eb505be1 | Jes Sorensen | |
235 | eb505be1 | Jes Sorensen | void os_daemonize(void) |
236 | eb505be1 | Jes Sorensen | { |
237 | eb505be1 | Jes Sorensen | if (daemonize) {
|
238 | eb505be1 | Jes Sorensen | pid_t pid; |
239 | eb505be1 | Jes Sorensen | |
240 | eb505be1 | Jes Sorensen | if (pipe(fds) == -1) |
241 | eb505be1 | Jes Sorensen | exit(1);
|
242 | eb505be1 | Jes Sorensen | |
243 | eb505be1 | Jes Sorensen | pid = fork(); |
244 | eb505be1 | Jes Sorensen | if (pid > 0) { |
245 | eb505be1 | Jes Sorensen | uint8_t status; |
246 | eb505be1 | Jes Sorensen | ssize_t len; |
247 | eb505be1 | Jes Sorensen | |
248 | eb505be1 | Jes Sorensen | close(fds[1]);
|
249 | eb505be1 | Jes Sorensen | |
250 | eb505be1 | Jes Sorensen | again:
|
251 | eb505be1 | Jes Sorensen | len = read(fds[0], &status, 1); |
252 | eb505be1 | Jes Sorensen | if (len == -1 && (errno == EINTR)) |
253 | eb505be1 | Jes Sorensen | goto again;
|
254 | eb505be1 | Jes Sorensen | |
255 | eb505be1 | Jes Sorensen | if (len != 1) |
256 | eb505be1 | Jes Sorensen | exit(1);
|
257 | eb505be1 | Jes Sorensen | else if (status == 1) { |
258 | eb505be1 | Jes Sorensen | fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
|
259 | eb505be1 | Jes Sorensen | exit(1);
|
260 | eb505be1 | Jes Sorensen | } else
|
261 | eb505be1 | Jes Sorensen | exit(0);
|
262 | eb505be1 | Jes Sorensen | } else if (pid < 0) |
263 | eb505be1 | Jes Sorensen | exit(1);
|
264 | eb505be1 | Jes Sorensen | |
265 | eb505be1 | Jes Sorensen | close(fds[0]);
|
266 | eb505be1 | Jes Sorensen | qemu_set_cloexec(fds[1]);
|
267 | eb505be1 | Jes Sorensen | |
268 | eb505be1 | Jes Sorensen | setsid(); |
269 | eb505be1 | Jes Sorensen | |
270 | eb505be1 | Jes Sorensen | pid = fork(); |
271 | eb505be1 | Jes Sorensen | if (pid > 0) |
272 | eb505be1 | Jes Sorensen | exit(0);
|
273 | eb505be1 | Jes Sorensen | else if (pid < 0) |
274 | eb505be1 | Jes Sorensen | exit(1);
|
275 | eb505be1 | Jes Sorensen | |
276 | eb505be1 | Jes Sorensen | umask(027);
|
277 | eb505be1 | Jes Sorensen | |
278 | eb505be1 | Jes Sorensen | signal(SIGTSTP, SIG_IGN); |
279 | eb505be1 | Jes Sorensen | signal(SIGTTOU, SIG_IGN); |
280 | eb505be1 | Jes Sorensen | signal(SIGTTIN, SIG_IGN); |
281 | eb505be1 | Jes Sorensen | } |
282 | eb505be1 | Jes Sorensen | } |
283 | eb505be1 | Jes Sorensen | |
284 | eb505be1 | Jes Sorensen | void os_setup_post(void) |
285 | eb505be1 | Jes Sorensen | { |
286 | eb505be1 | Jes Sorensen | int fd = 0; |
287 | eb505be1 | Jes Sorensen | |
288 | eb505be1 | Jes Sorensen | if (daemonize) {
|
289 | eb505be1 | Jes Sorensen | uint8_t status = 0;
|
290 | eb505be1 | Jes Sorensen | ssize_t len; |
291 | eb505be1 | Jes Sorensen | |
292 | eb505be1 | Jes Sorensen | again1:
|
293 | eb505be1 | Jes Sorensen | len = write(fds[1], &status, 1); |
294 | eb505be1 | Jes Sorensen | if (len == -1 && (errno == EINTR)) |
295 | eb505be1 | Jes Sorensen | goto again1;
|
296 | eb505be1 | Jes Sorensen | |
297 | eb505be1 | Jes Sorensen | if (len != 1) |
298 | eb505be1 | Jes Sorensen | exit(1);
|
299 | eb505be1 | Jes Sorensen | |
300 | eb505be1 | Jes Sorensen | if (chdir("/")) { |
301 | eb505be1 | Jes Sorensen | perror("not able to chdir to /");
|
302 | eb505be1 | Jes Sorensen | exit(1);
|
303 | eb505be1 | Jes Sorensen | } |
304 | eb505be1 | Jes Sorensen | TFR(fd = qemu_open("/dev/null", O_RDWR));
|
305 | eb505be1 | Jes Sorensen | if (fd == -1) |
306 | eb505be1 | Jes Sorensen | exit(1);
|
307 | eb505be1 | Jes Sorensen | } |
308 | eb505be1 | Jes Sorensen | |
309 | e06eb601 | Jes Sorensen | change_root(); |
310 | e06eb601 | Jes Sorensen | change_process_uid(); |
311 | eb505be1 | Jes Sorensen | |
312 | eb505be1 | Jes Sorensen | if (daemonize) {
|
313 | eb505be1 | Jes Sorensen | dup2(fd, 0);
|
314 | eb505be1 | Jes Sorensen | dup2(fd, 1);
|
315 | eb505be1 | Jes Sorensen | dup2(fd, 2);
|
316 | eb505be1 | Jes Sorensen | |
317 | eb505be1 | Jes Sorensen | close(fd); |
318 | eb505be1 | Jes Sorensen | } |
319 | eb505be1 | Jes Sorensen | } |
320 | eb505be1 | Jes Sorensen | |
321 | eb505be1 | Jes Sorensen | void os_pidfile_error(void) |
322 | eb505be1 | Jes Sorensen | { |
323 | eb505be1 | Jes Sorensen | if (daemonize) {
|
324 | eb505be1 | Jes Sorensen | uint8_t status = 1;
|
325 | eb505be1 | Jes Sorensen | if (write(fds[1], &status, 1) != 1) { |
326 | eb505be1 | Jes Sorensen | perror("daemonize. Writing to pipe\n");
|
327 | eb505be1 | Jes Sorensen | } |
328 | eb505be1 | Jes Sorensen | } else
|
329 | eb505be1 | Jes Sorensen | fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
|
330 | eb505be1 | Jes Sorensen | } |
331 | 9156d763 | Jes Sorensen | |
332 | 9156d763 | Jes Sorensen | void os_set_line_buffering(void) |
333 | 9156d763 | Jes Sorensen | { |
334 | 9156d763 | Jes Sorensen | setvbuf(stdout, NULL, _IOLBF, 0); |
335 | 9156d763 | Jes Sorensen | } |
336 | 949d31e6 | Jes Sorensen | |
337 | 949d31e6 | Jes Sorensen | /*
|
338 | 949d31e6 | Jes Sorensen | * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
|
339 | 949d31e6 | Jes Sorensen | */
|
340 | 949d31e6 | Jes Sorensen | int qemu_eventfd(int fds[2]) |
341 | 949d31e6 | Jes Sorensen | { |
342 | 949d31e6 | Jes Sorensen | #ifdef CONFIG_EVENTFD
|
343 | 949d31e6 | Jes Sorensen | int ret;
|
344 | 949d31e6 | Jes Sorensen | |
345 | 949d31e6 | Jes Sorensen | ret = eventfd(0, 0); |
346 | 949d31e6 | Jes Sorensen | if (ret >= 0) { |
347 | 949d31e6 | Jes Sorensen | fds[0] = ret;
|
348 | 949d31e6 | Jes Sorensen | qemu_set_cloexec(ret); |
349 | 949d31e6 | Jes Sorensen | if ((fds[1] = dup(ret)) == -1) { |
350 | 949d31e6 | Jes Sorensen | close(ret); |
351 | 949d31e6 | Jes Sorensen | return -1; |
352 | 949d31e6 | Jes Sorensen | } |
353 | 949d31e6 | Jes Sorensen | qemu_set_cloexec(fds[1]);
|
354 | 949d31e6 | Jes Sorensen | return 0; |
355 | 949d31e6 | Jes Sorensen | } |
356 | 949d31e6 | Jes Sorensen | |
357 | 949d31e6 | Jes Sorensen | if (errno != ENOSYS) {
|
358 | 949d31e6 | Jes Sorensen | return -1; |
359 | 949d31e6 | Jes Sorensen | } |
360 | 949d31e6 | Jes Sorensen | #endif
|
361 | 949d31e6 | Jes Sorensen | |
362 | 949d31e6 | Jes Sorensen | return qemu_pipe(fds);
|
363 | 949d31e6 | Jes Sorensen | } |
364 | bc4a957c | Jes Sorensen | |
365 | bc4a957c | Jes Sorensen | int qemu_create_pidfile(const char *filename) |
366 | bc4a957c | Jes Sorensen | { |
367 | bc4a957c | Jes Sorensen | char buffer[128]; |
368 | bc4a957c | Jes Sorensen | int len;
|
369 | bc4a957c | Jes Sorensen | int fd;
|
370 | bc4a957c | Jes Sorensen | |
371 | bc4a957c | Jes Sorensen | fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
|
372 | bc4a957c | Jes Sorensen | if (fd == -1) { |
373 | bc4a957c | Jes Sorensen | return -1; |
374 | bc4a957c | Jes Sorensen | } |
375 | bc4a957c | Jes Sorensen | if (lockf(fd, F_TLOCK, 0) == -1) { |
376 | bc4a957c | Jes Sorensen | return -1; |
377 | bc4a957c | Jes Sorensen | } |
378 | bc4a957c | Jes Sorensen | len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); |
379 | bc4a957c | Jes Sorensen | if (write(fd, buffer, len) != len) {
|
380 | bc4a957c | Jes Sorensen | return -1; |
381 | bc4a957c | Jes Sorensen | } |
382 | bc4a957c | Jes Sorensen | |
383 | bc4a957c | Jes Sorensen | return 0; |
384 | bc4a957c | Jes Sorensen | } |