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 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 */ 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 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 */ 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 */ 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