1/** \file
2 *  \brief inheritance of file descriptors
3 */
4
5/*
6 * Copyright (c) 2010, 2012, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich,
12 * Attn: Systems Group.
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17
18#include <barrelfish/barrelfish.h>
19#include <barrelfish_kpi/init.h>
20
21#include "testdesc.h"
22
23
24static void print_file_fd(void *handle)
25{
26    vfs_handle_t *vh = *(vfs_handle_t**)handle;
27
28    printf("reading from: %p\n", handle);
29    printf("FILE\n\thandle: %p\n", vh);
30}
31
32static void print_unixsock_fd(void *handle)
33{
34    struct _unix_socket *ush = (struct _unix_socket *)handle;
35
36    printf("reading from: %p\n", handle);
37    printf("UNIX socket\n\ttype: %x protocol: %x\n\tpassive: %d nonblkng: %d\n",
38           ush->type, ush->protocol, ush->passive, ush->nonblocking);
39}
40
41static errval_t get_inherited_fds(void)
42{
43    errval_t err;
44
45    /* Map the FD buffer into our address space.
46     * It stays there since the FD data structures will remain in there and be
47     * referenced from the FD table.
48     */
49    struct capref frame = {
50        .cnode = cnode_task,
51        .slot = TASKCN_SLOT_FDSPAGE,
52    };
53
54    void *fdspg;
55    err = vspace_map_one_frame(&fdspg, FDS_SIZE, frame, NULL, NULL);
56    if (err_is_fail(err)) {
57        return err_push(err, SPAWN_ERR_MAP_FDSPG_TO_SELF);
58    }
59
60    /* Set up to read the table */
61    char *p = fdspg;
62    printf("fds at: %p\n", p);
63
64    int num_fds = *((int*)p);
65    printf("num fds: %d\n", num_fds);
66
67    struct fd_store *fd;
68    p += sizeof(int);
69    fd = (struct fd_store*)p;
70    p += (sizeof(struct fd_store)*num_fds);
71
72    /* Process all the FDs passed in the buffer */
73    int i;
74    for (i = 0; i < num_fds; i++, fd++) {
75
76        /* add each to our fd table - replacing any fds already there */
77        struct fdtab_entry fde;
78        fde.type = fd->type;
79        fde.handle = fd->handle;
80
81        if (fdtab_get(fd->num)->type != FDTAB_TYPE_AVAILABLE) {
82            fdtab_free(fd->num);
83        }
84        fdtab_alloc_from(&fde, fd->num);
85
86        /* print out some info about the FD */
87
88        char *s = "";
89        switch (fd->type) {
90        case FDTAB_TYPE_AVAILABLE:
91            s = "available";
92            break;
93        case FDTAB_TYPE_FILE:
94            s = "file";
95            break;
96        case FDTAB_TYPE_UNIX_SOCKET:
97            s = "unix socket";
98            break;
99        case FDTAB_TYPE_STDIN:
100            s = "stdin";
101            break;
102        case FDTAB_TYPE_STDOUT:
103            s = "stdout";
104            break;
105        case FDTAB_TYPE_STDERR:
106            s = "stderr";
107            break;
108        case FDTAB_TYPE_LWIP_SOCKET:
109            s = "lwip socket";
110            break;
111        case FDTAB_TYPE_EPOLL_INSTANCE:
112            s = "epoll instance";
113            break;
114        case FDTAB_TYPE_PTM:
115            s = "pseudo-terminal master";
116            break;
117        case FDTAB_TYPE_PTS:
118            s = "pseudo-terminal slave";
119            break;
120        }
121        printf("fd_store %d: num: %d, type: %d:%s handle: %p\n",
122               i, fd->num, fd->type, s, fd->handle);
123
124        switch (fd->type) {
125        case FDTAB_TYPE_FILE:
126            print_file_fd((void*)(p + (lpaddr_t)fd->handle));
127            break;
128        case FDTAB_TYPE_UNIX_SOCKET:
129            print_unixsock_fd((void*)(p + (lpaddr_t)fd->handle));
130            break;
131        default:
132            printf("[no handle data]\n");
133            break;
134        }
135
136    }
137
138    return SYS_ERR_OK;
139
140}
141
142int main(int argc, char *argv[])
143{
144    errval_t err;
145
146    printf("Child. will print out file descriptors\n");
147
148    /* Inherit all the FDs sent over */
149    err = get_inherited_fds();
150    if (err_is_fail(err)) {
151        DEBUG_ERR(err, "could not get inherited FDs\n");
152        return EXIT_FAILURE;
153    }
154
155    /* print out all of our FDs */
156    int i;
157    struct fdtab_entry *fde;
158    for (i = MIN_FD; i < MAX_FD; i++) {
159        fde = fdtab_get(i);
160        if (fde->type != FDTAB_TYPE_AVAILABLE) {
161            printf("fd[%d]: type: %d, handle: %p\n", i, fde->type, fde->handle);
162        }
163    }
164
165    return EXIT_SUCCESS;
166}
167