/* Simple door test. */ #include #include #include #include #include #include #include #include #include #include #include #include #include static char door_file[] = "/tmp/vgtest_door_data.XXXXXX"; static volatile int exit_now = 0; static void child_handler(int sig) { if (!exit_now) { fprintf(stderr, "Received premature SIGCHLD.\n"); unlink(door_file); exit(1); } } /* SERVER CODE */ static void server_procedure(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, uint_t n_desc) { char data[] = "Hello from server"; if (!argp) goto out; if (arg_size > INT_MAX) { fprintf(stderr, "Value received from a client is too big.\n"); goto out; } printf("SERVER: %.*s\n", (int)arg_size, argp); fflush(stdout); out: /* Let server_main() know that we should exit. */ *(int*)cookie = 1; door_return(data, strlen(data) + 1, NULL, 0); /* Function door_return() should never return. */ perror("door_return"); exit(1); } static int server_main(void) { int res = 1; int did = -1; int attached = 0; /* Make sure nothing else is attached. */ fdetach(door_file); if ((did = door_create(server_procedure, (void*)&exit_now, 0)) < 0) { perror("door_create"); return 1; } /* Attach to file system. */ if (fattach(did, door_file) < 0) { char str[100]; snprintf(str, sizeof(str), "fattach %s", door_file); perror(str); goto out; } attached = 1; /* Poor man's termination. */ while (!exit_now) sleep(1); res = 0; out: if (attached && unlink(door_file)) { char str[100]; snprintf(str, sizeof(str), "unlink %s", door_file); perror(str); } if (did >= 0 && door_revoke(did)) perror("door_revoke"); return res; } /* CLIENT CODE */ static int client_main(void) { int did; char buf[128]; int tries; door_arg_t params; struct door_info info; tries = 0; while (1) { /* Open the door file. */ if ((did = open(door_file, O_RDWR)) >= 0) if (!door_info(did, &info)) break; close(did); if (tries > 10) { char str[100]; snprintf(str, sizeof(str), "door_info %s", door_file); perror(str); return 1; } tries++; sleep(1); } /* Set call parameters. */ snprintf(buf, sizeof(buf), "Hello from client"); params.data_ptr = buf; params.data_size = strlen(buf) + 1; params.desc_ptr = NULL; params.desc_num = 0; params.rbuf = buf; params.rsize = sizeof(buf); /* Make the call. */ if (door_call(did, ¶ms)) { perror("door_call"); close(did); return 1; } close(did); /* Print a result of the call. */ printf("CLIENT: %.*s\n", (int)params.rsize, params.rbuf); fflush(stdout); /* It's possible that the system allocated a new memory for rbuf. Unmap it if it's the case */ if (params.rbuf != buf) if (munmap(params.rbuf, params.rsize) != 0) { perror("munmap"); return 1; } return 0; } /* MAIN CODE */ int main(void) { struct sigaction sa; pid_t pid; int door_fd; /* Establish handler for client error exit. */ sa.sa_handler = child_handler; sa.sa_flags = SA_NOCLDSTOP; if (sigemptyset(&sa.sa_mask)) { perror("sigemptyset"); return 1; } if (sigaction(SIGCHLD, &sa, NULL)) { perror("sigaction"); return 1; } door_fd = mkstemp(door_file); if (door_fd < 0) { perror("mkstemp"); return 1; } close(door_fd); pid = fork(); if (pid == -1) { perror("fork"); return 1; } if (pid == 0) { return client_main(); } else { int res = server_main(); if (res == 0) { do { if (wait(NULL) == pid) break; if (errno != EINTR) { perror("wait"); res = 1; } } while (errno == EINTR); } return res; } }