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