1// Copyright 2016 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <launchpad/launchpad.h>
6#include <launchpad/vmo.h>
7
8#include <zircon/process.h>
9#include <zircon/processargs.h>
10#include <zircon/syscalls.h>
11#include <lib/fdio/io.h>
12#include <lib/fdio/namespace.h>
13#include <lib/fdio/util.h>
14
15#include <stdlib.h>
16#include <unistd.h>
17
18static zx_status_t add_fdio(launchpad_t* lp,
19                            zx_handle_t handles[FDIO_MAX_HANDLES],
20                            uint32_t types[FDIO_MAX_HANDLES],
21                            zx_status_t status) {
22    if (status == ZX_ERR_BAD_HANDLE)
23        return ZX_OK;
24    if (status == ZX_ERR_NOT_SUPPORTED)
25        return ZX_OK;
26    if (status > 0) {
27        return launchpad_add_handles(lp, status, handles, types);
28    } else {
29        launchpad_abort(lp, status, "add_fdio: failed");
30        return status;
31    }
32}
33
34zx_status_t launchpad_clone(launchpad_t* lp, uint32_t what) {
35    zx_handle_t handles[FDIO_MAX_HANDLES];
36    uint32_t types[FDIO_MAX_HANDLES];
37    zx_status_t status;
38
39    if (what & LP_CLONE_FDIO_NAMESPACE) {
40        fdio_flat_namespace_t* flat;
41        status = fdio_ns_export_root(&flat);
42        if (status == ZX_OK) {
43            launchpad_set_nametable(lp, flat->count, flat->path);
44            launchpad_add_handles(lp, flat->count, flat->handle, flat->type);
45            free(flat);
46        } else if (status != ZX_ERR_NOT_FOUND) {
47            launchpad_abort(lp, status, "clone: error cloning namespace");
48            return status;
49        }
50    }
51    if (what & LP_CLONE_FDIO_STDIO) {
52        for (int fd = 0; fd < 3; fd++) {
53            add_fdio(lp, handles, types, fdio_clone_fd(fd, fd, handles, types));
54        }
55    }
56    if (what & LP_CLONE_ENVIRON) {
57        launchpad_set_environ(lp, (const char* const*)environ);
58    }
59    if (what & LP_CLONE_DEFAULT_JOB) {
60        zx_handle_t job;
61        if (zx_handle_duplicate(zx_job_default(), ZX_RIGHT_SAME_RIGHTS, &job) == ZX_OK) {
62            launchpad_add_handle(lp, job, PA_HND(PA_JOB_DEFAULT, 0));
63        }
64    }
65    return launchpad_get_status(lp);
66}
67
68zx_status_t launchpad_clone_fd(launchpad_t* lp, int fd, int target_fd) {
69    zx_handle_t handles[FDIO_MAX_HANDLES];
70    uint32_t types[FDIO_MAX_HANDLES];
71    return add_fdio(lp, handles, types,
72                    fdio_clone_fd(fd, target_fd, handles, types));
73}
74
75zx_status_t launchpad_transfer_fd(launchpad_t* lp, int fd, int target_fd) {
76    zx_handle_t handles[FDIO_MAX_HANDLES];
77    uint32_t types[FDIO_MAX_HANDLES];
78    return add_fdio(lp, handles, types,
79                    fdio_transfer_fd(fd, target_fd, handles, types));
80}
81