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, ¶ms)) {
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