• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Simple door test. */
2 
3 #include <door.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <limits.h>
7 #include <signal.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <sys/mman.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 
17 static char door_file[] = "/tmp/vgtest_door_data.XXXXXX";
18 static volatile int exit_now = 0;
19 
child_handler(int sig)20 static void child_handler(int sig)
21 {
22    if (!exit_now) {
23       fprintf(stderr, "Received premature SIGCHLD.\n");
24       unlink(door_file);
25       exit(1);
26    }
27 }
28 
29 /* SERVER CODE */
server_procedure(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_desc)30 static void server_procedure(void *cookie, char *argp, size_t arg_size,
31                              door_desc_t *dp, uint_t n_desc)
32 {
33    char data[] = "Hello from server";
34 
35    if (!argp)
36       goto out;
37 
38    if (arg_size > INT_MAX) {
39       fprintf(stderr, "Value received from a client is too big.\n");
40       goto out;
41    }
42 
43    printf("SERVER: %.*s\n", (int)arg_size, argp);
44    fflush(stdout);
45 
46 out:
47    /* Let server_main() know that we should exit. */
48    *(int*)cookie = 1;
49 
50    door_return(data, strlen(data) + 1, NULL, 0);
51 
52    /* Function door_return() should never return. */
53    perror("door_return");
54    exit(1);
55 }
56 
server_main(void)57 static int server_main(void)
58 {
59    int res = 1;
60    int did = -1;
61    int attached = 0;
62 
63    /* Make sure nothing else is attached. */
64    fdetach(door_file);
65 
66    if ((did = door_create(server_procedure, (void*)&exit_now, 0)) < 0) {
67       perror("door_create");
68       return 1;
69    }
70 
71    /* Attach to file system. */
72    if (fattach(did, door_file) < 0) {
73       char str[100];
74       snprintf(str, sizeof(str), "fattach %s", door_file);
75       perror(str);
76       goto out;
77    }
78    attached = 1;
79 
80    /* Poor man's termination. */
81    while (!exit_now)
82       sleep(1);
83 
84    res = 0;
85 
86 out:
87    if (attached && unlink(door_file)) {
88       char str[100];
89       snprintf(str, sizeof(str), "unlink %s", door_file);
90       perror(str);
91    }
92    if (did >= 0 && door_revoke(did))
93       perror("door_revoke");
94 
95    return res;
96 }
97 
98 /* CLIENT CODE */
client_main(void)99 static int client_main(void)
100 {
101    int did;
102    char buf[128];
103    int tries;
104    door_arg_t params;
105    struct door_info info;
106 
107    tries = 0;
108    while (1) {
109       /* Open the door file. */
110       if ((did = open(door_file, O_RDWR)) >= 0)
111          if (!door_info(did, &info))
112             break;
113 
114       close(did);
115 
116       if (tries > 10) {
117          char str[100];
118          snprintf(str, sizeof(str), "door_info %s", door_file);
119          perror(str);
120          return 1;
121       }
122 
123       tries++;
124       sleep(1);
125    }
126 
127    /* Set call parameters. */
128    snprintf(buf, sizeof(buf), "Hello from client");
129    params.data_ptr = buf;
130    params.data_size = strlen(buf) + 1;
131    params.desc_ptr = NULL;
132    params.desc_num = 0;
133    params.rbuf = buf;
134    params.rsize = sizeof(buf);
135 
136    /* Make the call. */
137    if (door_call(did, &params)) {
138       perror("door_call");
139       close(did);
140       return 1;
141    }
142 
143    close(did);
144 
145    /* Print a result of the call. */
146    printf("CLIENT: %.*s\n", (int)params.rsize, params.rbuf);
147    fflush(stdout);
148 
149    /* It's possible that the system allocated a new memory for rbuf.  Unmap it
150       if it's the case */
151    if (params.rbuf != buf)
152       if (munmap(params.rbuf, params.rsize) != 0) {
153          perror("munmap");
154          return 1;
155       }
156 
157    return 0;
158 }
159 
160 /* MAIN CODE */
main(void)161 int main(void)
162 {
163    struct sigaction sa;
164    pid_t pid;
165    int door_fd;
166 
167    /* Establish handler for client error exit. */
168    sa.sa_handler = child_handler;
169    sa.sa_flags = SA_NOCLDSTOP;
170    if (sigemptyset(&sa.sa_mask)) {
171       perror("sigemptyset");
172       return 1;
173    }
174    if (sigaction(SIGCHLD, &sa, NULL)) {
175       perror("sigaction");
176       return 1;
177    }
178 
179    door_fd = mkstemp(door_file);
180    if (door_fd < 0) {
181       perror("mkstemp");
182       return 1;
183    }
184    close(door_fd);
185 
186    pid = fork();
187    if (pid == -1) {
188       perror("fork");
189       return 1;
190    }
191 
192    if (pid == 0) {
193       return client_main();
194    } else {
195       int res = server_main();
196       if (res == 0) {
197          do {
198             if (wait(NULL) == pid)
199                break;
200             if (errno != EINTR) {
201                perror("wait");
202                res = 1;
203             }
204          } while (errno == EINTR);
205       }
206       return res;
207    }
208 }
209