1088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/*
2088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * os-posix.c
3088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner *
4088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Copyright (c) 2003-2008 Fabrice Bellard
5088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Copyright (c) 2010 Red Hat, Inc.
6088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner *
7088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy
8088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal
9088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * in the Software without restriction, including without limitation the rights
10088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is
12088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * furnished to do so, subject to the following conditions:
13088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner *
14088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * The above copyright notice and this permission notice shall be included in
15088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * all copies or substantial portions of the Software.
16088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner *
17088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * THE SOFTWARE.
24088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner */
25088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
26088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <unistd.h>
27088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <fcntl.h>
28088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <signal.h>
29088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <sys/types.h>
30088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <sys/wait.h>
31088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/*needed for MAP_POPULATE before including qemu-options.h */
32088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <sys/mman.h>
33088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <pwd.h>
34088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <libgen.h>
35088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
36088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/* Needed early for CONFIG_BSD etc. */
37088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include "config-host.h"
38088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include "sysemu.h"
39088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include "net.h"
40088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include "qemu-options.h"
41088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
42088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#ifdef CONFIG_LINUX
43088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <sys/prctl.h>
44088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <sys/syscall.h>
45088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif
46088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
47088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#ifdef CONFIG_EVENTFD
48088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include <sys/eventfd.h>
49088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif
50088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
51088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerstatic struct passwd *user_pwd;
52088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerstatic const char *chroot_dir;
53088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerstatic int daemonize;
54088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerstatic int fds[2];
55088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
56088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid os_setup_early_signal_handling(void)
57088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
58088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    struct sigaction act;
59088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    sigfillset(&act.sa_mask);
60088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    act.sa_flags = 0;
61088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    act.sa_handler = SIG_IGN;
62088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    sigaction(SIGPIPE, &act, NULL);
63088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
64088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
65088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerstatic void termsig_handler(int signal)
66088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
67088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    qemu_system_shutdown_request();
68088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
69088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
70088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerstatic void sigchld_handler(int signal)
71088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
72088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    waitpid(-1, NULL, WNOHANG);
73088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
74088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
75088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid os_setup_signal_handling(void)
76088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
77088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    struct sigaction act;
78088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
79088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    memset(&act, 0, sizeof(act));
80088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    act.sa_handler = termsig_handler;
81088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    sigaction(SIGINT,  &act, NULL);
82088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    sigaction(SIGHUP,  &act, NULL);
83088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    sigaction(SIGTERM, &act, NULL);
84088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
85088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    act.sa_handler = sigchld_handler;
86088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    act.sa_flags = SA_NOCLDSTOP;
87088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    sigaction(SIGCHLD, &act, NULL);
88088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
89088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
90088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/* Find a likely location for support files using the location of the binary.
91088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner   For installed binaries this will be "$bindir/../share/qemu".  When
92088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner   running from the build tree this will be "$bindir/../pc-bios".  */
93088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#define SHARE_SUFFIX "/share/qemu"
94088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#define BUILD_SUFFIX "/pc-bios"
95088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerchar *os_find_datadir(const char *argv0)
96088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
97088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    char *dir;
98088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    char *p = NULL;
99088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    char *res;
100088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    char buf[PATH_MAX];
101088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    size_t max_len;
102088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
103088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#if defined(__linux__)
104088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    {
105088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        int len;
106088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
107088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (len > 0) {
108088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            buf[len] = 0;
109088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            p = buf;
110088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
111088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
112088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#elif defined(__FreeBSD__)
113088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    {
114088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
115088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        size_t len = sizeof(buf) - 1;
116088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
117088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        *buf = '\0';
118088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) &&
119088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            *buf) {
120088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            buf[sizeof(buf) - 1] = '\0';
121088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            p = buf;
122088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
123088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
124088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif
125088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    /* If we don't have any way of figuring out the actual executable
126088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner       location then try argv[0].  */
127088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (!p) {
128088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        p = realpath(argv0, buf);
129088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (!p) {
130088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            return NULL;
131088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
132088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
133088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    dir = dirname(p);
134088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    dir = dirname(dir);
135088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
136088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    max_len = strlen(dir) +
137088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
138088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    res = qemu_mallocz(max_len);
139088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
140088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (access(res, R_OK)) {
141088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
142088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (access(res, R_OK)) {
143088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            qemu_free(res);
144088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            res = NULL;
145088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
146088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
147088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
148088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    return res;
149088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
150088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#undef SHARE_SUFFIX
151088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#undef BUILD_SUFFIX
152088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
153088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid os_set_proc_name(const char *s)
154088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
155088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#if defined(PR_SET_NAME)
156088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    char name[16];
157088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (!s)
158088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        return;
159088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    name[sizeof(name) - 1] = 0;
160088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    strncpy(name, s, sizeof(name));
161088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    /* Could rewrite argv[0] too, but that's a bit more complicated.
162088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner       This simple way is enough for `top'. */
163088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (prctl(PR_SET_NAME, name)) {
164088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        perror("unable to change process name");
165088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        exit(1);
166088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
167088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#else
168088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    fprintf(stderr, "Change of process name not supported by your OS\n");
169088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    exit(1);
170088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif
171088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
172088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
173088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/*
174088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Parse OS specific command line options.
175088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * return 0 if option handled, -1 otherwise
176088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner */
177088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid os_parse_cmd_args(int index, const char *optarg)
178088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
179088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    switch (index) {
180088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#ifdef CONFIG_SLIRP
181088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    case QEMU_OPTION_smb:
182088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#if 1
183088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        net_slirp_smb(optarg);
184088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#else
185088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (net_slirp_smb(optarg) < 0)
186088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
187088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif
188088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        break;
189088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif
190088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    case QEMU_OPTION_runas:
191088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        user_pwd = getpwnam(optarg);
192088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (!user_pwd) {
193088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            fprintf(stderr, "User \"%s\" doesn't exist\n", optarg);
194088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
195088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
196088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        break;
197088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    case QEMU_OPTION_chroot:
198088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        chroot_dir = optarg;
199088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        break;
200088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    case QEMU_OPTION_daemonize:
201088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        daemonize = 1;
202088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        break;
203088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
204088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    return;
205088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
206088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
207088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerstatic void change_process_uid(void)
208088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
209088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (user_pwd) {
210088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (setgid(user_pwd->pw_gid) < 0) {
211088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid);
212088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
213088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
214088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (setuid(user_pwd->pw_uid) < 0) {
215088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid);
216088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
217088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
218088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (setuid(0) != -1) {
219088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            fprintf(stderr, "Dropping privileges failed\n");
220088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
221088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
222088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
223088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
224088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
225088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerstatic void change_root(void)
226088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
227088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (chroot_dir) {
228088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (chroot(chroot_dir) < 0) {
229088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            fprintf(stderr, "chroot failed\n");
230088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
231088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
232088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (chdir("/")) {
233088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            perror("not able to chdir to /");
234088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
235088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
236088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
237088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
238088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
239088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
240088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid os_daemonize(void)
241088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
242088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (daemonize) {
243088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	pid_t pid;
244088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
245088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	if (pipe(fds) == -1)
246088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    exit(1);
247088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
248088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	pid = fork();
249088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	if (pid > 0) {
250088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    uint8_t status;
251088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    ssize_t len;
252088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
253088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    close(fds[1]);
254088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
255088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	again:
256088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            len = read(fds[0], &status, 1);
257088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            if (len == -1 && (errno == EINTR))
258088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner                goto again;
259088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
260088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            if (len != 1)
261088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner                exit(1);
262088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            else if (status == 1) {
263088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner                fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
264088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner                exit(1);
265088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            } else
266088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner                exit(0);
267088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	} else if (pid < 0)
268088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
269088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
270088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	close(fds[0]);
271088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	qemu_set_cloexec(fds[1]);
272088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
273088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	setsid();
274088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
275088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	pid = fork();
276088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	if (pid > 0)
277088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    exit(0);
278088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	else if (pid < 0)
279088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    exit(1);
280088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
281088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	umask(027);
282088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
283088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        signal(SIGTSTP, SIG_IGN);
284088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        signal(SIGTTOU, SIG_IGN);
285088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        signal(SIGTTIN, SIG_IGN);
286088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
287088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
288088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
289088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid os_setup_post(void)
290088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
291088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    int fd = 0;
292088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
293088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (daemonize) {
294088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	uint8_t status = 0;
295088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	ssize_t len;
296088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
297088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    again1:
298088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	len = write(fds[1], &status, 1);
299088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	if (len == -1 && (errno == EINTR))
300088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    goto again1;
301088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
302088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	if (len != 1)
303088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    exit(1);
304088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
305088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (chdir("/")) {
306088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            perror("not able to chdir to /");
307088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            exit(1);
308088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
309088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	TFR(fd = qemu_open("/dev/null", O_RDWR));
310088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	if (fd == -1)
311088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner	    exit(1);
312088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
313088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
314088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    change_root();
315088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    change_process_uid();
316088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
317088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (daemonize) {
318088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        dup2(fd, 0);
319088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        dup2(fd, 1);
320088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        dup2(fd, 2);
321088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
322088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        close(fd);
323088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
324088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
325088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
326088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid os_pidfile_error(void)
327088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
328088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (daemonize) {
329088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        uint8_t status = 1;
330088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if (write(fds[1], &status, 1) != 1) {
331088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            perror("daemonize. Writing to pipe\n");
332088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
333088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    } else
334088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
335088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
336088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
337088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid os_set_line_buffering(void)
338088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
339088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    setvbuf(stdout, NULL, _IOLBF, 0);
340088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
341088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
342088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/*
343088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
344088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner */
345088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerint qemu_eventfd(int fds[2])
346088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
347088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#ifdef CONFIG_EVENTFD
348088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    int ret;
349088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
350088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    ret = eventfd(0, 0);
351088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (ret >= 0) {
352088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        fds[0] = ret;
353088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        qemu_set_cloexec(ret);
354088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        if ((fds[1] = dup(ret)) == -1) {
355088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            close(ret);
356088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner            return -1;
357088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        }
358088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        qemu_set_cloexec(fds[1]);
359088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        return 0;
360088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
361088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
362088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (errno != ENOSYS) {
363088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        return -1;
364088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
365088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif
366088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
367088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    return qemu_pipe(fds);
368088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
369088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
370088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerint qemu_create_pidfile(const char *filename)
371088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
372088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    char buffer[128];
373088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    int len;
374088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    int fd;
375088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
376088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
377088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (fd == -1) {
378088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        return -1;
379088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
380088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (lockf(fd, F_TLOCK, 0) == -1) {
381088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        return -1;
382088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
383088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
384088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    if (write(fd, buffer, len) != len) {
385088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner        return -1;
386088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    }
387088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
388088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    return 0;
389088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
390088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner
391088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerint qemu_get_thread_id(void)
392088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{
393088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#if defined (__linux__)
394088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    return syscall(SYS_gettid);
395088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#else
396088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner    return getpid();
397088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif
398088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner}
399