--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/app/dsession/sun-src/dsession.c Mon Oct 13 15:22:07 2014 -0700
@@ -0,0 +1,1812 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files(the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice(including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <sys/stat.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <dirent.h>
+#include <synch.h>
+#include <signal.h>
+#include <libgen.h>
+#include <X11/Xos.h>
+#include "pciaccess.h"
+#include "xorg/xf86Pci.h"
+
+
+#define MAX_DISP_DEV 8
+#define IS_VGA(c) \
+ (((c) & 0x00ffff00) \
+ == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8)))
+#define RETRY_COUNT 30
+#define ALL 255
+#define MAX_EARGC 8
+#define FTOK_FILE "/usr/lib/ConsoleKit/dsession"
+#define FTOK_ID 'H'
+#define SESSION_SIZE 64
+#define TYPE_SIZE 16
+
+typedef struct {
+ char session_id[SESSION_SIZE];
+ Bool open;
+ char busid[64];
+ char dev_path[PATH_MAX];
+ int display;
+ char status[TYPE_SIZE];
+ char usr_session[SESSION_SIZE];
+ pid_t server_pid;
+} dsession_mgr_t;
+
+typedef struct {
+ char session_id[SESSION_SIZE];
+ Bool open;
+ int display;
+ char session_type[TYPE_SIZE];
+ char display_type[TYPE_SIZE];
+} ck_session_t;
+
+typedef struct {
+ dsession_mgr_t dsession_table[MAX_DISP_DEV];
+ mutex_t lock;
+} shared_mem_t;
+
+static struct pci_device_iterator * iter;
+static struct pci_device * dev;
+static struct sol_device_private {
+ struct pci_device base;
+ const char *device_string;
+ };
+#define DEV_PATH(dev) (((struct sol_device_private *) dev)->device_string)
+
+static char *program_name;
+static dsession_mgr_t dsession_mgr_table[MAX_DISP_DEV];
+static int disp_num = 0;
+static ck_session_t ck_sessions[MAX_DISP_DEV * 2];
+static int num_sessions = 0;
+static char device[PATH_MAX];
+static void *shm_addr = NULL;
+static key_t shm_key;
+static int shmid;
+static Bool debug = FALSE;
+
+#define lock (((shared_mem_t *) shm_addr)->lock)
+#define shm_table (((shared_mem_t *) shm_addr)->dsession_table)
+
+
+static Bool
+cmd_exec(char *cmd, char *output, size_t size)
+{
+ pid_t pid;
+ int p_fd[2];
+ char *token;
+ char string[MAX_EARGC + 1][64];
+ char *eargv[MAX_EARGC + 1];
+ int i;
+
+ if (debug)
+ printf("run cmd: %s\n", cmd);
+
+ /* parse cmd */
+ memset(eargv, 0, sizeof (eargv));
+ i = -1;
+
+ token = strtok(cmd, " ");
+
+ /* walk through other tokens */
+ while (token != NULL) {
+ if (++i == MAX_EARGC) {
+ fprintf(stderr, "cmd_exec: arguments exceed limit\n");
+
+ return FALSE;
+ }
+
+ strlcpy(string[i], token, sizeof (string[i]));
+ eargv[i] = string[i];
+
+ token = strtok(NULL, " ");
+ }
+
+ if (i == -1) {
+ fprintf(stderr, "cmd_exec: cmd parsing error\n");
+
+ return FALSE;
+ }
+
+ if (pipe(p_fd) != 0) {
+ fprintf(stderr, "cmd_exec command %s: ", eargv[0]);
+ perror("unable to pipe");
+
+ return FALSE;
+ }
+
+ if ((pid = fork()) == -1) {
+ fprintf(stderr, "cmd_exec command %s: ", eargv[0]);
+ perror("can not fork");
+
+ close(p_fd[0]);
+ close(p_fd[1]);
+
+ return FALSE;
+
+ } else if (pid == 0) {
+ /* child process */
+ close(p_fd[0]);
+
+ if (p_fd[1] != 1) {
+ if (dup2(p_fd[1], 1) < 0) {
+ fprintf(stderr, "cmd_exec command %s: ", eargv[0]);
+ perror("child failed to reopen stdout");
+
+ return FALSE;
+ }
+
+ close(p_fd[1]);
+ }
+
+ execv(eargv[0], eargv);
+
+ fprintf(stderr, "cmd_exec command %s: ", eargv[0]);
+ perror("fail to exec"); /* shouldn't be reached */
+
+ _exit(1);
+
+ } else {
+ /* parent process */
+ FILE *fd;
+ Bool done = FALSE;
+ char *buf;
+ int status;
+ int len;
+
+ close(p_fd[1]);
+ fd = fdopen(p_fd[0], "r");
+
+ if (output && (size > 0)) {
+ buf = malloc(size);
+
+ while (fgets(buf, size, fd) != NULL) {
+ /* only need one line from read */
+ if (!done) {
+ strlcpy(output, buf, size);
+ done = TRUE;
+ }
+ }
+
+ if ((len = strlen(output)) > 0) {
+ if (output[len - 1] == '\n')
+ output[len - 1] = 0;
+
+ else
+ output[len] = 0;
+ }
+
+ } else {
+ buf = malloc(256);
+
+ while (fgets(buf, 256, fd) != NULL);
+ }
+
+ free(buf);
+
+ close(p_fd[0]);
+
+ if (waitpid(pid, &status, 0) != pid) {
+ fprintf(stderr, "cmd_exec command %s: ", eargv[0]);
+ perror("error waiting for child process");
+
+ return FALSE;
+
+ } else if (WIFSIGNALED(status)) {
+ fprintf(stderr, "cmd_exec command %s: ", eargv[0]);
+ fprintf(stderr, "child exited with signal %d\n",
+ WTERMSIG(status));
+
+ return FALSE;
+
+ } else if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)) {
+ return TRUE;
+
+ } else {
+ fprintf(stderr, "cmd_exec command %s: ", eargv[0]);
+ fprintf(stderr, "child exited abnormally\n");
+
+ return FALSE;
+ }
+ }
+}
+
+static void
+get_dsession_mgr_table(void)
+{
+ int i;
+
+ memcpy(dsession_mgr_table, shm_table, sizeof (dsession_mgr_table));
+
+ for (i = 0; i < MAX_DISP_DEV; i++) {
+ if (!dsession_mgr_table[i].dev_path[0])
+ break;
+ }
+
+ if (i == 0)
+ printf("warning: no entry in dsession table\n");
+
+ disp_num = i;
+}
+
+
+static void
+print_mgr_table_entry(int index)
+{
+ printf("%s:\n", dsession_mgr_table[index].session_id);
+
+ if (dsession_mgr_table[index].open)
+ printf("\topen = %s\n", "TRUE");
+
+ else
+ printf("\topen = %s\n", "FALSE");
+
+ if (dsession_mgr_table[index].busid[0])
+ printf("\tbusid = %s\n", dsession_mgr_table[index].busid);
+
+ else
+ printf("\tbusid = %s\n", "NULL");
+
+ if (dsession_mgr_table[index].dev_path[0])
+ printf("\tdev_path = %s\n", dsession_mgr_table[index].dev_path);
+
+ else
+ printf("\tdev_path = %s\n", "NULL");
+
+ if (dsession_mgr_table[index].display == -1)
+ printf("\tdisplay = :\n");
+
+ else
+ printf("\tdisplay = :%d\n", dsession_mgr_table[index].display);
+
+ if (dsession_mgr_table[index].status[0])
+ printf("\tstatus = %s\n", dsession_mgr_table[index].status);
+
+ else
+ printf("\tstatus = %s\n", "UNKNOWN");
+
+ if (dsession_mgr_table[index].usr_session[0])
+ printf("\tuser_session_id = %s\n",
+ dsession_mgr_table[index].usr_session);
+
+ fflush(stdout);
+}
+
+static Bool
+print_mgr_table(Bool all)
+{
+ int i;
+
+ if (all) {
+ for (i = 0; i < disp_num; i++)
+ print_mgr_table_entry(i);
+
+ } else {
+ for (i = 0; i < disp_num; i++) {
+ if (strcmp(dsession_mgr_table[i].dev_path, device) == 0)
+ break;
+ }
+
+ if (i != disp_num)
+ print_mgr_table_entry(i);
+
+ else {
+ fprintf(stderr, "device not in the table\n");
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static int
+get_sessions(char *session)
+{
+ pid_t pid;
+ int p_fd[2];
+
+ if (pipe(p_fd) != 0) {
+ perror("get_sessions: unable to pipe");
+
+ return -1;
+ }
+
+ if ((pid = fork()) == -1) {
+ perror("get_sessions: can not fork");
+
+ close(p_fd[0]);
+ close(p_fd[1]);
+
+ return -1;
+
+ } else if (pid == 0) {
+ /* child process */
+ close(p_fd[0]);
+
+ if (p_fd[1] != 1) {
+ if (dup2(p_fd[1], 1) < 0) {
+ perror("get_sessions: child failed to reopen stdout");
+
+ return -1;
+ }
+
+ close(p_fd[1]);
+ }
+
+ if (strcmp(session, "all") == 0)
+ execl("/usr/bin/ck-list-sessions", "ck-list-sessions", "-a",
+ NULL);
+
+ else
+ execl("/usr/bin/ck-list-sessions", "ck-list-sessions", "-s",
+ session, NULL);
+
+ perror("get_sessions: fail to exec"); /* shouldn't be reached */
+
+ _exit(1);
+
+ } else {
+ /* parent process */
+ FILE *fd;
+ char buf[BUFSIZ];
+ int session_num;
+ int status;
+ Bool discard = FALSE;
+ Bool ret = TRUE;
+
+ close(p_fd[1]);
+ fd = fdopen(p_fd[0], "r");
+ session_num = -1;
+
+ memset(ck_sessions, 0, sizeof (ck_sessions));
+
+ while (fgets(buf, BUFSIZ, fd) != NULL) {
+ size_t bufsize = strlen(buf);
+
+ if (discard)
+ continue;
+
+ if (buf[0] != '\t') {
+ /* session id */
+ if (++session_num > (MAX_DISP_DEV * 2 - 1)) {
+ fprintf(stderr, "max session number exceeded.\n");
+
+ discard = TRUE;
+ ret = FALSE;
+
+ continue;
+ }
+
+ if (bufsize && (buf[bufsize - 1] == '\n')) {
+ buf[bufsize - 1] = 0;
+ bufsize--;
+ }
+
+ if (bufsize && (buf[bufsize - 1] == ':'))
+ buf[bufsize - 1] = 0;
+
+ strlcpy(ck_sessions[session_num].session_id, buf,
+ SESSION_SIZE);
+
+ } else {
+ /* session body */
+ if (bufsize && (buf[bufsize - 1] == '\n'))
+ buf[bufsize - 1] = 0;
+
+ if (strncmp(buf, "\topen = ", sizeof ("\topen = ") - 1) == 0) {
+ if (strncmp(&buf[sizeof ("\topen = ") - 1], "'TRUE'",
+ sizeof ("'TRUE'") - 1) == 0)
+ ck_sessions[session_num].open = TRUE;
+
+ else if (strncmp(&buf[sizeof ("\topen = ") - 1], "'FALSE'",
+ sizeof ("'FALSE'") - 1) == 0)
+ ck_sessions[session_num].open = FALSE;
+
+ } else if (strncmp(buf, "\tx11-display = ",
+ sizeof ("\tx11-display = ") - 1) == 0) {
+ int disp;
+
+ if (strncmp(&buf[sizeof ("\tx11-display = ") - 1], "''",
+ sizeof ("''") - 1) == 0)
+ ck_sessions[session_num].display = -1;
+
+ else {
+ if (sscanf(buf, "\tx11-display = ':%d'",
+ &disp) == 1)
+ ck_sessions[session_num].display = disp;
+ }
+
+ } else if (strncmp(buf, "\tsession-type = ",
+ sizeof ("\tsession-type = ") - 1) == 0) {
+ char type[TYPE_SIZE];
+
+ if (strncmp(&buf[sizeof ("\tsession-type = ") - 1], "''",
+ sizeof ("''") - 1) == 0)
+ ck_sessions[session_num].session_type[0] = 0;
+
+ else {
+ if (sscanf(buf, "\tsession-type = '%16[^']",
+ type) == 1)
+ strlcpy(ck_sessions[session_num].session_type,
+ type, TYPE_SIZE);
+ }
+
+ } else if (strncmp(buf, "\tdisplay-type = ",
+ sizeof ("\tdisplay-type = ") - 1) == 0) {
+ char type[TYPE_SIZE];
+
+ if (strncmp(&buf[sizeof ("\tdisplay-type = ") - 1], "''",
+ sizeof ("''") - 1) == 0)
+ ck_sessions[session_num].display_type[0] = 0;
+
+ else {
+ if (sscanf(buf, "\tdisplay-type = '%16[^']",
+ type) == 1)
+ strlcpy(ck_sessions[session_num].display_type,
+ type, TYPE_SIZE);
+ }
+
+ } else
+ /* ignore */
+ continue;
+ }
+ }
+
+ close(p_fd[0]);
+
+ if (waitpid(pid, &status, 0) != pid) {
+ perror("get_sessions: error waiting for child process");
+
+ return -1;
+
+ } else if (WIFSIGNALED(status)) {
+ fprintf(stderr, "get_sessions: child exited with signal %d\n",
+ WTERMSIG(status));
+
+ return -1;
+
+ } else if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)) {
+ if (ret) {
+ if (debug) {
+ if (strcmp(session, "all") == 0)
+ printf("get_sessions(all): %d sessions found\n",
+ session_num + 1);
+ else
+ printf("get_sessions(single): %d sessions found\n",
+ session_num + 1);
+ }
+
+ return session_num + 1;
+
+ } else
+ return -1;
+
+ } else {
+ fprintf(stderr, "get_sessions: child exited abnormally\n");
+
+ return -1;
+
+ }
+ }
+}
+
+static int
+find_session_in_list(char *session_id)
+{
+ int i;
+
+ if (!session_id)
+ return -1;
+
+ for (i = 0; i < num_sessions; i++) {
+ if (strcmp(ck_sessions[i].session_id, session_id) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+
+static Bool
+probe_and_print_dev(void)
+{
+ if (pci_system_init() != 0) {
+ fprintf(stderr, "can't do pci system init\n");
+
+ return FALSE;
+ }
+
+ iter = pci_slot_match_iterator_create(NULL);
+
+ while ((dev = pci_device_next(iter)) != NULL) {
+ pci_device_probe(dev);
+
+ if (IS_VGA(dev->device_class)) {
+ if (DEV_PATH(dev))
+ printf("/devices%s\n", DEV_PATH(dev));
+
+ }
+ }
+
+ pci_iterator_destroy(iter);
+ pci_system_cleanup();
+
+ return TRUE;
+}
+
+static Bool
+set_server_pid(int i)
+{
+ char output[16];
+ long pid;
+ char display[8];
+
+ if (dsession_mgr_table[i].display != -1)
+ snprintf(display, sizeof (display), ":%d",
+ dsession_mgr_table[i].display);
+
+ else
+ return FALSE;
+
+ setenv("DISPLAY", display, 1);
+
+ memset(output, 0, sizeof (output));
+
+ if (cmd_exec("/usr/lib/ck-get-x11-server-pid", output,
+ sizeof (output)) && output[0]) {
+ if (sscanf(output, "%ld", &pid) == 1) {
+ dsession_mgr_table[i].server_pid = (pid_t) pid;
+
+ if (debug)
+ printf("server pid %ld set for display :%d\n",
+ (long) dsession_mgr_table[i].server_pid,
+ dsession_mgr_table[i].display);
+
+ return TRUE;
+
+ } else
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+verify_and_set(char *type, int index)
+{
+
+ Bool verified = FALSE;
+ int count = 0;
+ Bool allsessions;
+ int i, j;
+ char *session_id;
+
+ if (index == ALL)
+ /* called from init() or fini() */
+ allsessions = TRUE;
+
+ else {
+ allsessions = FALSE;
+ session_id = dsession_mgr_table[index].session_id;
+ }
+
+ if (strcmp(type, "delete") == 0) {
+ while (!verified && (count++ < RETRY_COUNT)) {
+ Bool no_server_pid = FALSE;
+
+ usleep(2000000);
+ if (allsessions) {
+ /* delete all sessions, only when called from fini() */
+ if ((num_sessions = get_sessions("all")) == -1)
+ return FALSE;
+
+ verified = TRUE;
+
+ for (i = 0; i < disp_num; i++) {
+ pid_t server_pid = dsession_mgr_table[i].server_pid;
+
+ if (strcmp(dsession_mgr_table[i].session_id, "Deleted")
+ != 0) {
+ if ((find_session_in_list(
+ dsession_mgr_table[i].session_id)) == -1) {
+ /*
+ * session closed, also need to verify server
+ * termination before exiting
+ */
+ if (server_pid != -1) {
+ if (kill(server_pid, 0)) {
+ if (debug)
+ printf("server %ld terminated\n",
+ (long) server_pid);
+
+ } else
+ verified = FALSE;
+
+ } else
+ no_server_pid = TRUE;
+
+ if (verified) {
+ dsession_mgr_table[i].open = FALSE;
+
+ strlcpy(dsession_mgr_table[i].session_id,
+ "Deleted", SESSION_SIZE);
+ strlcpy(dsession_mgr_table[i].status,
+ "REMOVED", TYPE_SIZE);
+ }
+
+ } else {
+ verified = FALSE;
+
+ if (count == (RETRY_COUNT - 5) &&
+ (server_pid != -1)) {
+
+ errno = 0;
+ if ((kill(server_pid, SIGTERM) == -1) &&
+ (errno != ESRCH))
+ perror("kill server failed");
+
+ else if (debug)
+ printf("server %ld killed\n",
+ (long) server_pid);
+ }
+ }
+ }
+ }
+
+ if (verified && no_server_pid)
+ /*
+ * add a delay if server's termination cannot be
+ * verified
+ */
+ usleep(4000000);
+
+ } else {
+ /* delete single session */
+ pid_t server_pid = dsession_mgr_table[index].server_pid;
+
+ if (get_sessions(session_id) == 0) {
+ /*
+ * session closed, also need to verify server
+ * termination before exiting
+ */
+ if (server_pid != -1) {
+ if (kill(server_pid, 0)) {
+ if (debug)
+ printf("server %ld terminated\n",
+ (long) server_pid);
+
+ verified = TRUE;
+ }
+
+ } else {
+ /*
+ * add a delay if server's termination cannot be
+ * verified
+ */
+ usleep(4000000);
+ verified = TRUE;
+ }
+
+ if (verified) {
+ dsession_mgr_table[index].open = FALSE;
+
+ strlcpy(dsession_mgr_table[index].session_id,
+ "Deleted", SESSION_SIZE);
+ strlcpy(dsession_mgr_table[index].status,
+ "REMOVED", TYPE_SIZE);
+
+ memcpy(&shm_table[index],
+ &dsession_mgr_table[index],
+ sizeof (dsession_mgr_t));
+ }
+
+ } else {
+ if (count == (RETRY_COUNT - 5) &&
+ (server_pid != -1)) {
+
+ errno = 0;
+ if ((kill(server_pid, SIGTERM) == -1) &&
+ (errno != ESRCH))
+ perror("kill server failed");
+
+ else if (debug)
+ printf("server %ld killed\n",
+ (long) server_pid);
+ }
+ }
+ }
+ }
+
+ } else if (strcmp(type, "add") == 0) {
+ while (!verified && (count++ < RETRY_COUNT)) {
+ usleep(2000000);
+
+ if (allsessions) {
+ /* add all sessions, only when called from init() */
+ if ((num_sessions = get_sessions("all")) == -1)
+ return FALSE;
+
+ verified = TRUE;
+
+ for (i = 0; i < disp_num; i++) {
+ if ((j = find_session_in_list(
+ dsession_mgr_table[i].session_id)) != -1) {
+ if ((!ck_sessions[j].open) ||
+ (ck_sessions[j].display == -1))
+ verified = FALSE;
+
+ } else
+ verified = FALSE;
+ }
+
+ } else {
+ /* add single session */
+ i = get_sessions(session_id);
+
+ if ((i == 1) && ck_sessions[0].open &&
+ (ck_sessions[0].display != -1))
+ verified = TRUE;
+ }
+ }
+
+ if (allsessions) {
+ /* add all sessions */
+ for (i = 0; i < disp_num; i++) {
+ if ((j = find_session_in_list(
+ dsession_mgr_table[i].session_id)) != -1) {
+ /* consolekit session was created */
+ dsession_mgr_table[i].open = ck_sessions[j].open;
+
+ if (dsession_mgr_table[i].open) {
+ dsession_mgr_table[i].display = ck_sessions[j].display;
+ strlcpy(dsession_mgr_table[i].status,
+ "UP", TYPE_SIZE);
+
+ if (!set_server_pid(i)) {
+ dsession_mgr_table[i].server_pid = -1;
+ fprintf(stderr, "set server pid failed for :%d\n",
+ dsession_mgr_table[i].display);
+ }
+
+ } else {
+ strlcpy(dsession_mgr_table[i].status,
+ "FAILURE", TYPE_SIZE);
+ fprintf(stderr, "added %s not verified\n",
+ dsession_mgr_table[i].session_id);
+ }
+
+ } else
+ fprintf(stderr, "dsession %s not added\n",
+ dsession_mgr_table[i].session_id);
+ }
+
+ } else {
+ /* Add single session */
+ if ((i == 1) && (strcmp(ck_sessions[0].session_id, session_id)
+ == 0)) {
+ /* consolekit session was created */
+ dsession_mgr_table[index].open = ck_sessions[0].open;
+
+ if (dsession_mgr_table[index].open) {
+ dsession_mgr_table[index].display = ck_sessions[0].display;
+ strlcpy(dsession_mgr_table[index].status,
+ "UP", TYPE_SIZE);
+
+ if (!set_server_pid(index)) {
+ dsession_mgr_table[index].server_pid = -1;
+
+ fprintf(stderr, "set server pid failed for :%d\n",
+ dsession_mgr_table[index].display);
+ }
+
+ } else
+ strlcpy(dsession_mgr_table[index].status,
+ "FAILURE", TYPE_SIZE);
+
+ memcpy(&shm_table[index], &dsession_mgr_table[index],
+ sizeof (dsession_mgr_t));
+ }
+ }
+ }
+
+ return verified;
+
+}
+
+static int
+delete_session(void)
+{
+ int i;
+ char cmd[128];
+
+ for (i = 0; i < disp_num; i++) {
+ if (strcmp(dsession_mgr_table[i].dev_path, device) == 0) {
+ break;
+ }
+ }
+
+ if (i == disp_num) {
+ fprintf(stderr, "invalid device path: %s\n", device);
+ return -1;
+ }
+
+ if ((!dsession_mgr_table[i].session_id[0]) ||
+ (get_sessions(dsession_mgr_table[i].session_id) == 0)) {
+ /*
+ * no valid session id in mgr table, this is abnormal.
+ * try to work around.
+ */
+ if (dsession_mgr_table[i].display != -1) {
+ int j;
+
+ if ((num_sessions = get_sessions("all")) == -1)
+ return -1;
+
+ for (j = 0; j < num_sessions; j++) {
+ if (ck_sessions[j].display == dsession_mgr_table[i].display) {
+ strlcpy(dsession_mgr_table[i].session_id,
+ ck_sessions[j].session_id, SESSION_SIZE);
+
+ break;
+ }
+ }
+ }
+
+ if (strcmp(dsession_mgr_table[i].session_id, "Deleted") == 0) {
+ /* session already deleted */
+ printf("dsession for device %s already deleted\n",
+ basename(device));
+
+ return i;
+ }
+ }
+
+ if (!dsession_mgr_table[i].open &&
+ (strcmp(dsession_mgr_table[i].status, "TRANSFERRED") == 0) &&
+ dsession_mgr_table[i].usr_session[0]) {
+ /* has a user session for it, delete it first */
+ printf("warning: you are deleting a user session\n");
+
+ snprintf(cmd, sizeof (cmd),
+ "/usr/sbin/ck-seat-tool --delete --session-id=%s",
+ dsession_mgr_table[i].usr_session);
+
+ if (cmd_exec(cmd, NULL, 0)) {
+ dsession_mgr_table[i].usr_session[0] = 0;
+
+ printf("user session %s deleted\n",
+ dsession_mgr_table[i].usr_session);
+ }
+ }
+
+ snprintf(cmd, sizeof (cmd),
+ "/usr/sbin/ck-seat-tool --delete --session-id=%s",
+ dsession_mgr_table[i].session_id);
+
+ if (cmd_exec(cmd, NULL, 0)) {
+ printf("%s for device %s deleted\n", dsession_mgr_table[i].session_id,
+ basename(device));
+
+ return i;
+
+ } else {
+ fprintf(stderr, "%s for device %s not deleted\n",
+ dsession_mgr_table[i].session_id, basename(device));
+
+ return -1;
+ }
+}
+
+static int
+add_session(Bool init, int entry)
+{
+ int index;
+ char cmd[256];
+ char output[64];
+ int display;
+
+ if (init) {
+ /* called from init() */
+ index = entry;
+
+ /* avoid using display :0 */
+ display = index + 1;
+
+ } else {
+ Bool found = FALSE;
+
+ for (index = 0; index < disp_num; index++) {
+ if (strcmp(dsession_mgr_table[index].dev_path, device) == 0)
+ break;
+ }
+
+ if (index < disp_num) {
+ /* add session on existing device */
+ if (dsession_mgr_table[index].session_id[0] &&
+ (strcmp(dsession_mgr_table[index].session_id, "Deleted")
+ != 0)) {
+ printf("session for device already running - not added\n");
+
+ return -1;
+ }
+
+ /*
+ * check to see if a ck session already running on
+ * the same display. this could happen when previous
+ * verify_and_set() got interrupted .
+ */
+ if (dsession_mgr_table[index].display != -1) {
+ int i;
+
+ if ((num_sessions = get_sessions("all")) == -1)
+ return -1;
+
+ for (i = 0; i < num_sessions; i++) {
+ if (ck_sessions[i].display ==
+ dsession_mgr_table[index].display) {
+ strlcpy(dsession_mgr_table[index].session_id,
+ ck_sessions[i].session_id, SESSION_SIZE);
+
+ printf("%s for device %s restored in table\n",
+ dsession_mgr_table[index].session_id,
+ basename(dsession_mgr_table[index].dev_path));
+
+ break;
+ }
+ }
+
+ if (i < num_sessions)
+ return index;
+ }
+
+ } else if (disp_num == MAX_DISP_DEV) {
+ /* index == disp_num, and adding a new session */
+ fprintf(stderr, "add session: too many devices\n");
+
+ return -1;
+ }
+
+ /*
+ * unless called from init(), always need a re-probe, as the numbering
+ * of root complex may have changed. So table's busid needs update if
+ * the device already exits in the table.
+ */
+ if (pci_system_init() != 0) {
+ fprintf(stderr, "can't do pci system init\n");
+
+ return -1;
+ }
+
+ iter = pci_slot_match_iterator_create(NULL);
+
+ while ((dev = pci_device_next(iter)) != NULL) {
+ char dev_path[PATH_MAX];
+
+ if (IS_VGA(dev->device_class)) {
+ pci_device_probe(dev);
+
+ if (DEV_PATH(dev))
+ snprintf(dev_path, PATH_MAX,
+ "/devices%s", DEV_PATH(dev));
+ else
+ continue;
+
+ if (strcmp(device, dev_path) == 0) {
+ snprintf(dsession_mgr_table[index].busid,
+ sizeof (dsession_mgr_table[index].busid),
+ "PCI:%d:%d:%d", dev->domain << 8 | dev->bus,
+ dev->dev, dev->func);
+
+ if (index < disp_num) {
+ if ((display = dsession_mgr_table[index].display)
+ == -1)
+ display = index + 1;
+
+ } else {
+ /* add a session for new device */
+ strlcpy(dsession_mgr_table[index].dev_path, dev_path,
+ PATH_MAX);
+
+ dsession_mgr_table[index].display = -1;
+ dsession_mgr_table[index].server_pid = -1;
+
+ disp_num++;
+ display = index + 1;
+ }
+
+ found = TRUE;
+
+ break;
+ }
+
+ }
+ }
+
+ pci_iterator_destroy(iter);
+ pci_system_cleanup();
+
+ if (!found) {
+ fprintf(stderr, "cannot find device %s in probe\n", device);
+
+ return -1;
+ }
+ }
+
+ /* prepare command */
+ snprintf(cmd, sizeof (cmd),
+ "/usr/sbin/ck-seat-tool -a --session-type=LoginWindow"
+ " --display-type=HotPlug --seat-id=StaticSeat1"
+ " display=:%d busid=%s",
+ display, dsession_mgr_table[index].busid);
+
+ memset(output, 0, sizeof (output));
+
+ /* run command */
+ if (cmd_exec(cmd, output, sizeof (output)) && output[0]) {
+ printf("%s for device %s added\n", output,
+ basename(dsession_mgr_table[index].dev_path));
+
+ strlcpy(dsession_mgr_table[index].session_id, output,
+ SESSION_SIZE);
+
+ return index;
+
+ } else {
+ fprintf(stderr, "dsession for device %s not added\n",
+ basename(dsession_mgr_table[index].dev_path));
+
+ return -1;
+ }
+}
+
+static Bool
+restart_session(void)
+{
+ int i;
+
+ if ((i = delete_session()) == -1) {
+ fprintf(stderr, "failed to delete dsession for %s\n",
+ basename(device));
+
+ return FALSE;
+
+ } else {
+ if (!verify_and_set("delete", i)) {
+ fprintf(stderr, "deleted dsession can't be verified,"
+ "restart failed\n");
+
+ return FALSE;
+
+ } else {
+ printf("deleted dsession verified\n");
+
+ if ((i = add_session(FALSE, 0)) == -1) {
+ fprintf(stderr, "failed to add dsession for %s\n",
+ basename(device));
+
+ return FALSE;
+
+ } else {
+ if (!verify_and_set("add", i)) {
+ fprintf(stderr, "added dsession can't be verified\n");
+
+ return FALSE;
+
+ } else {
+ printf("added dsession %s verified\n",
+ dsession_mgr_table[i].session_id);
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static Bool
+sync_sessions(void)
+{
+ int i, j, k;
+ Bool ret = TRUE;
+ Bool ck_session_changed = FALSE;
+
+ if ((num_sessions = get_sessions("all")) == -1)
+ return FALSE;
+
+ for (j = 0; j < num_sessions; j++) {
+ if ((strncmp(ck_sessions[j].session_type, "LoginWindow",
+ sizeof ("LoginWindow") - 1) == 0) &&
+ (strncmp(ck_sessions[j].display_type, "HotPlug",
+ sizeof ("HotPlug") - 1) == 0) &&
+ ck_sessions[j].open == FALSE) {
+ /* handle closed sessions */
+ int display = -1;
+
+ for (i = 0; i < disp_num; i++) {
+ if (strcmp(dsession_mgr_table[i].session_id,
+ ck_sessions[j].session_id) == 0) {
+ display = dsession_mgr_table[i].display;
+
+ break;
+ }
+ }
+
+ if (display != -1) {
+ /* found a session in mgr table with valid display */
+ for (k = 0; k < num_sessions; k++) {
+ if ((strncmp(ck_sessions[k].session_type, "LoginWindow",
+ sizeof ("LoginWindow") - 1) != 0) &&
+ (display == ck_sessions[k].display)) {
+ /*
+ * found user session (type is not "LoginWindow")
+ * with same display. update mgr table
+ */
+ if (strncmp(dsession_mgr_table[i].status, "TRANSFERRED",
+ sizeof ("TRANSFERRED") - 1) != 0) {
+ strlcpy(dsession_mgr_table[i].status,
+ "TRANSFERRED", TYPE_SIZE);
+ dsession_mgr_table[i].open = FALSE;
+
+ strlcpy(dsession_mgr_table[i].usr_session,
+ ck_sessions[k].session_id,
+ SESSION_SIZE);
+
+ memcpy(&shm_table[i], &dsession_mgr_table[i],
+ sizeof (dsession_mgr_t));
+
+ if (debug)
+ printf("session %s updated in sync\n",
+ dsession_mgr_table[i].session_id);
+ }
+
+ break;
+ }
+ }
+
+ } else {
+ /* not a transferred session, delete it as it's closed */
+ char cmd[128];
+
+ snprintf(cmd, sizeof (cmd),
+ "/usr/sbin/ck-seat-tool --delete --session-id=%s",
+ ck_sessions[j].session_id);
+
+ if (cmd_exec(cmd, NULL, 0)) {
+ if (debug)
+ printf("session %s deleted in sync\n",
+ ck_sessions[j].session_id);
+
+ ck_session_changed = TRUE;
+
+ } else
+ ret = FALSE;
+
+ if (i < disp_num) {
+ /* session in mgr table, need to update entry */
+ strlcpy(dsession_mgr_table[i].session_id,
+ "Deleted", SESSION_SIZE);
+ strlcpy(dsession_mgr_table[i].status,
+ "REMOVED", TYPE_SIZE);
+
+ memcpy(&shm_table[i], &dsession_mgr_table[i],
+ sizeof (dsession_mgr_t));
+ }
+ }
+ }
+ }
+
+ if ((ck_session_changed) && ((num_sessions = get_sessions("all")) == -1))
+ ret = FALSE;
+
+ for (i = 0; i < disp_num; i++) {
+ if (strcmp(dsession_mgr_table[i].status, "TRANSFERRED") == 0) {
+ for (j = 0; j < num_sessions; j++) {
+ if ((strcmp(dsession_mgr_table[i].session_id,
+ ck_sessions[j].session_id) == 0) &&
+ ck_sessions[j].open &&
+ find_session_in_list(dsession_mgr_table[i].usr_session)
+ == -1) {
+ /*
+ * corresponding session in ck table becomes open and
+ * the user session does not exist any more
+ */
+ strlcpy(dsession_mgr_table[i].status, "UP",
+ TYPE_SIZE);
+
+ dsession_mgr_table[i].open = TRUE;
+ dsession_mgr_table[i].usr_session[0] = 0;
+
+ memcpy(&shm_table[i], &dsession_mgr_table[i],
+ sizeof (dsession_mgr_t));
+
+ if (debug)
+ printf("session %s updated in sync\n",
+ dsession_mgr_table[i].session_id);
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (ret && debug)
+ printf("sync sessions done\n");
+
+ return ret;
+}
+
+static Bool
+fini(void)
+{
+ int i;
+
+ if ((shmid = shmget(shm_key, sizeof (shared_mem_t),
+ IPC_ALLOC)) == -1) {
+ perror("shared memory get error");
+
+ return FALSE;
+ }
+
+ if ((shm_addr = (char *) shmat(shmid,
+ (void *) NULL, 0)) == (void *) -1) {
+ perror("shared memory attach error");
+
+ return FALSE;
+ }
+
+ mutex_lock(&lock);
+
+ get_dsession_mgr_table();
+
+ for (i = 0; i < disp_num; i++) {
+ if (dsession_mgr_table[i].dev_path[0]) {
+ strlcpy(device, dsession_mgr_table[i].dev_path, PATH_MAX);
+
+ if (delete_session() == -1)
+ fprintf(stderr, "failed to delete dsession for %s\n",
+ basename(device));
+ }
+ }
+
+ /* verify sessions just deleted */
+ if (debug)
+ printf("verifying the deleted dsessions ...\n");
+
+ if (verify_and_set("delete", ALL))
+ printf("deleted dsessions all verified\n");
+
+ else
+ fprintf(stderr, "deleted dsessions not verified\n");
+
+ memcpy(shm_table, dsession_mgr_table, sizeof (dsession_mgr_table));
+
+ mutex_unlock(&lock);
+
+ if (shmdt(shm_addr) == -1) {
+ perror("shared memory detach error");
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+clean(void)
+{
+ if (!fini())
+ fprintf(stderr, "failed to fini\n");
+
+ if ((shmid = shmget(shm_key, sizeof (shared_mem_t),
+ IPC_ALLOC)) == -1) {
+ perror("shared memory get error");
+
+ return FALSE;
+ }
+
+ if ((shm_addr = (char *) shmat(shmid,
+ (void *) NULL, 0)) == (void *) -1) {
+ perror("shared memory attach error");
+
+ return FALSE;
+ }
+
+ mutex_destroy(&lock);
+
+ if (shmdt(shm_addr) == -1) {
+ perror("shared memory detach error");
+
+ return FALSE;
+ }
+
+ /* destroy the shared memory area */
+ if (shmctl(shmid, IPC_RMID, NULL) == -1) {
+ perror("shared memory remove error");
+
+ return FALSE;
+ }
+
+ printf("shared memory removed\n");
+
+ return TRUE;
+}
+
+static Bool
+init(void)
+{
+ int i;
+ Bool shm_created = FALSE;
+
+ if ((shmid = shmget(shm_key, sizeof (shared_mem_t),
+ IPC_ALLOC)) != -1) {
+ /* shared memory already exists */
+ if ((shm_addr = (char *) shmat(shmid,
+ (void *) NULL, 0)) == (void *) -1) {
+ perror("shared memory attach error");
+
+ return FALSE;
+ }
+
+ mutex_lock(&lock);
+
+ get_dsession_mgr_table();
+
+ for (i = 0; i < disp_num; i++) {
+ if (dsession_mgr_table[i].session_id[0] &&
+ (strcmp(dsession_mgr_table[i].session_id,
+ "Deleted") != 0)) {
+ fprintf(stderr, "need to delete all sessions "
+ "before running \"dsession -i/--init\"\n");
+
+ mutex_unlock(&lock);
+
+ if (shmdt(shm_addr) == -1)
+ perror("shared memory detach error");
+
+ return FALSE;
+ }
+ }
+
+ shm_created = TRUE;
+ }
+
+ /* initialize mgr table */
+ if (pci_system_init() != 0) {
+ fprintf(stderr, "can't do pci system init\n");
+
+ if (shm_created) {
+ mutex_unlock(&lock);
+
+ if (shmdt(shm_addr) == -1)
+ perror("shared memory detach error");
+ }
+
+ return FALSE;
+ }
+
+ memset(dsession_mgr_table, 0, sizeof (dsession_mgr_table));
+
+ disp_num = 0;
+
+ iter = pci_slot_match_iterator_create(NULL);
+
+ while ((dev = pci_device_next(iter)) != NULL) {
+ if (IS_VGA(dev->device_class)) {
+ if (disp_num == MAX_DISP_DEV) {
+ fprintf(stderr, "init: too many display devices\n");
+
+ if (shm_created) {
+ mutex_unlock(&lock);
+
+ if (shmdt(shm_addr) == -1)
+ perror("shared memory detach error");
+ }
+
+ pci_iterator_destroy(iter);
+ pci_system_cleanup();
+
+ return FALSE;
+ }
+
+ pci_device_probe(dev);
+
+ snprintf(dsession_mgr_table[disp_num].busid,
+ sizeof (dsession_mgr_table[disp_num].busid),
+ "PCI:%d:%d:%d", dev->domain << 8 | dev->bus,
+ dev->dev, dev->func);
+
+ if (DEV_PATH(dev)) {
+ snprintf(dsession_mgr_table[disp_num].dev_path,
+ PATH_MAX,
+ "/devices%s", DEV_PATH(dev));
+
+ dsession_mgr_table[disp_num].display = -1;
+ dsession_mgr_table[disp_num].server_pid = -1;
+
+ disp_num++;
+ }
+ }
+ }
+
+ pci_iterator_destroy(iter);
+ pci_system_cleanup();
+
+ if (!shm_created) {
+ /* shared memory has never been created */
+ if ((shmid = shmget(shm_key, sizeof (shared_mem_t),
+ IPC_CREAT|IPC_EXCL|0600)) == -1) {
+ perror("shared memory get error during create");
+
+ return FALSE;
+ }
+
+ printf("shared memory create successful\n");
+
+ if ((shm_addr = (char *) shmat(shmid,
+ (void *) NULL, 0)) == (void *) -1) {
+ perror("shared memory attach error");
+
+ return FALSE;
+ }
+
+ mutex_init(&lock, USYNC_PROCESS, NULL);
+
+ mutex_lock(&lock);
+ }
+
+ /* dynamically add sessions, one for each device */
+ for (i = 0; i < disp_num; i++) {
+ if (dsession_mgr_table[i].dev_path[0] &&
+ add_session(TRUE, i) == -1)
+ fprintf(stderr, "failed to add dsession for %s\n",
+ basename(device));
+ }
+
+ /* verify sessions just added */
+ if (debug)
+ printf("verifying the added dsessions ...\n");
+
+ if (verify_and_set("add", ALL))
+ printf("%d added dsessions all verified\n", disp_num);
+
+ else
+ fprintf(stderr, "added dsessions not verified\n");
+
+ memcpy(shm_table, dsession_mgr_table, sizeof (dsession_mgr_table));
+
+ mutex_unlock(&lock);
+
+ if (shmdt(shm_addr) == -1) {
+ perror("shared memory detach error");
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*ARGSUSED*/
+static void
+sig_handler(int sig)
+{
+ int status;
+
+ if (debug)
+ printf("signal %d caught\n", sig);
+
+ if (!(status = mutex_trylock(&lock)))
+ mutex_unlock(&lock);
+
+ else if (status == EBUSY)
+ mutex_unlock(&lock);
+
+ if ((shm_addr) && (shmdt(shm_addr) == -1))
+ perror("shared memory detach error");
+
+ (void) sigset(sig, SIG_DFL);
+
+ (void) kill(getpid(), sig);
+
+ exit(1);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "\nUsage:\n");
+
+ fprintf(stderr,
+ "%s -h|--help\n%s", program_name,
+ " Print help messages\n\n");
+
+ fprintf(stderr,
+ "%s [debug-option] sub-command\n%s", program_name,
+ " Run sub-command, where\n\n"
+ " debug-option:\n"
+ " -v or --verb\t\tPrint debug messages\n\n"
+ " sub-command:\t\t(<dev> is path of display device)\n"
+ " -a or --add <dev>\t\tAdd a dsession to run on <dev>\n"
+ " -d or --delete <dev>\tDelete a dsession running on <dev>\n"
+ " -r or --restart <dev>\tRestart a dsession running on <dev>\n"
+ " -l or --list all\t\tList all dsessions\n"
+ " -l or --list dev\t\tProbe and list devs\n"
+ " -l or --list <dev>\t\tList dsession running on <dev>\n"
+ " -i or --init\t\tInitialize: create shared memory\n"
+ " \t\tand mutex, add all dsessions\n"
+ " -f or --fini\t\tFinish: delete all dsessions\n"
+ " -c or --clean\t\tDelete all dsessions,\n"
+ " \t\tdestroy mutex and shared memory\n");
+}
+
+static Bool
+get_shm_key() {
+ struct stat statbuf;
+
+ if (stat(FTOK_FILE, &statbuf) != 0) {
+ fprintf(stderr, "need to install dsession at %s before run\n",
+ FTOK_FILE);
+
+ return FALSE;
+ }
+
+ if ((shm_key = ftok(FTOK_FILE, FTOK_ID)) == -1) {
+ perror("IPC error: ftok");
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int
+main(int argc, char **argv)
+{
+
+ program_name = argv[0];
+ Bool add = FALSE;
+ Bool delete = FALSE;
+ Bool list_all = FALSE;
+ Bool list_dev = FALSE;
+ Bool list_probe_dev = FALSE;
+ Bool restart = FALSE;
+ int ret = 0;
+ int signals[] = {SIGHUP, SIGTERM, SIGINT, SIGQUIT, SIGSEGV, SIGBUS,
+ SIGPIPE};
+ int i;
+
+ if ((argc == 2) && ((strcmp("-h", argv[1]) == 0) ||
+ (strcmp("--help", argv[1]) == 0))) {
+ usage();
+
+ exit(0);
+ }
+
+ if ((argc > 1) && ((strcmp("-v", argv[1]) == 0) ||
+ (strcmp("--verb", argv[1]) == 0))) {
+ debug = TRUE;
+
+ argc--;
+ argv++;
+ }
+
+ if ((argc < 2) || (argc > 3)) {
+ usage();
+
+ exit(1);
+ }
+
+ for (i = 0; i < sizeof (signals)/sizeof (signals[0]); i++) {
+ if (sigset(signals[i], SIG_IGN) == SIG_DFL)
+ (void) sigset(signals[i], sig_handler);
+ }
+
+ if ((strcmp("-a", argv[1]) == 0) ||
+ (strcmp("--add", argv[1]) == 0))
+ add = TRUE;
+
+ else if ((strcmp("-d", argv[1]) == 0) ||
+ (strcmp("--delete", argv[1]) == 0))
+ delete = TRUE;
+
+ else if ((strcmp("-r", argv[1]) == 0) ||
+ (strcmp("--restart", argv[1]) == 0))
+ restart = TRUE;
+
+ else if (((strcmp("-l", argv[1]) == 0) ||
+ (strcmp("--list", argv[1]) == 0)) &&
+ (argc == 3)) {
+ if (strcmp("all", argv[2]) == 0)
+ list_all = TRUE;
+
+ else if (strcmp("dev", argv[2]) == 0)
+ list_probe_dev = TRUE;
+
+ else
+ list_dev = TRUE;
+ }
+
+ if ((argc == 3) && (add || delete || restart || list_all || list_dev)) {
+ if (add || delete || restart || list_dev) {
+ char *path;
+
+ if (path = realpath(argv[2], NULL)) {
+ strlcpy(device, path, PATH_MAX);
+ free(path);
+
+ } else {
+ fprintf(stderr, "invalid device path: %s\n", argv[2]);
+
+ exit(1);
+ }
+ }
+
+ if (!get_shm_key()) {
+ fprintf(stderr, "get_shm_key failed\n");
+
+ exit(1);
+ }
+
+ if ((shmid = shmget(shm_key, sizeof (shared_mem_t),
+ IPC_ALLOC)) == -1) {
+ perror("shared memory get error");
+
+ exit(1);
+ }
+
+ if ((shm_addr = (char *) shmat(shmid,
+ (void *) NULL, 0)) == (void *) -1) {
+ perror("shared memory attach error");
+
+ exit(1);
+ }
+
+ mutex_lock(&lock);
+
+ get_dsession_mgr_table();
+
+ if (!sync_sessions())
+ fprintf(stderr, "warning: sync sessions partially failed\n");
+
+ if (add) {
+ if ((i = add_session(FALSE, 0)) == -1) {
+ fprintf(stderr, "failed to add dsession for %s\n",
+ basename(device));
+ ret = 1;
+
+ } else {
+ if (verify_and_set("add", i))
+ printf("added dsession %s verified\n",
+ dsession_mgr_table[i].session_id);
+
+ else {
+ fprintf(stderr, "added dsession can't be verified\n");
+ ret = 1;
+ }
+ }
+
+ } else if (delete) {
+ if ((i = delete_session()) == -1) {
+ fprintf(stderr, "failed to delete dsession for %s\n",
+ basename(device));
+ ret = 1;
+
+ } else {
+ if (verify_and_set("delete", i))
+ printf("deleted dsession verified\n");
+
+ else {
+ fprintf(stderr, "deleted dsession can't be verified\n");
+ ret = 1;
+ }
+ }
+
+ } else if (restart) {
+ if (restart_session())
+ printf("restart dsession on dev %s succeeded\n",
+ basename(device));
+
+ else {
+ fprintf(stderr, "failed to restart dsession for %s\n",
+ basename(device));
+ ret = 1;
+ }
+
+ } else if (list_all) {
+ if (!print_mgr_table(TRUE))
+ fprintf(stderr, "failed to print table\n");
+
+ } else if (list_dev) {
+ if (!print_mgr_table(FALSE)) {
+ fprintf(stderr, "failed to print table for %s\n", device);
+ ret = 1;
+ }
+ }
+
+ mutex_unlock(&lock);
+
+ if (shmdt(shm_addr) == -1) {
+ perror("shared memory detach error");
+
+ exit(1);
+ }
+
+ } else if (argc == 2) {
+ if (!get_shm_key()) {
+ fprintf(stderr, "get_shm_key failed\n");
+
+ exit(1);
+ }
+
+ if ((strcmp("-i", argv[1]) == 0) ||
+ (strcmp("--init", argv[1]) == 0)) {
+ if (!init()) {
+ fprintf(stderr, "failed to init\n");
+
+ exit(1);
+ }
+
+ } else if ((strcmp("-f", argv[1]) == 0) ||
+ (strcmp("--fini", argv[1]) == 0)) {
+ if (!fini()) {
+ fprintf(stderr, "failed to fini\n");
+
+ exit(1);
+ }
+
+ } else if ((strcmp("-c", argv[1]) == 0) ||
+ (strcmp("--clean", argv[1]) == 0)) {
+ if (!clean()) {
+ fprintf(stderr, "failed to clean\n");
+
+ exit(1);
+ }
+
+ } else {
+ usage();
+
+ exit(1);
+ }
+
+ } else if (list_probe_dev) {
+ if (!probe_and_print_dev())
+ ret = 1;
+
+ } else {
+ usage();
+
+ exit(1);
+ }
+
+ exit(ret);
+ /*NOTREACHED*/
+
+}