/* Simple door test. */
#include <door.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
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;
}
}