Home | History | Annotate | Download | only in solaris
      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, &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 */
    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