You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
3.7 KiB

#include "entrance.h"
#include <sys/wait.h>
#include <unistd.h>
typedef struct Entrance_Xserver_
{
const char *dname;
Entrance_X_Cb start;
} Entrance_Xserver;
Entrance_Xserver *_xserver;
Ecore_Event_Handler *_handler_start;
/*
* man Xserver
* SIGUSR1 This signal is used quite differently from either of the
* above. When the server starts, it checks to see if it has inherite
* SIGUSR1 as SIG_IGN instead of the usual SIG_DFL. In this case, the server
* sends a SIGUSR1 to its parent process after it has set up the various
* connection schemes. Xdm uses this feature to recognize when connecting to
* the server is possible.
* */
static void
_env_set(const char *dname)
{
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "DISPLAY=%s", dname);
putenv(strdup(buf));
}
static int
9 years ago
_xserver_start(void)
{
char *buf = NULL;
char **args = NULL;
pid_t pid;
PT("Launching xserver\n");
pid = fork();
if (!pid)
{
char *token;
int num_token = 0;
entrance_close_log();
signal(SIGTTIN, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGUSR1, SIG_IGN);
if (!(buf = strdup(entrance_config->command.xinit_args)))
goto xserver_error;
token = strtok(buf, " ");
while(token)
{
++num_token;
token = strtok(NULL, " ");
}
if (buf) free(buf);
if (num_token)
{
int i;
if (!(buf = strdup(entrance_config->command.xinit_args)))
goto xserver_error;
if (!(args = calloc(num_token + 2, sizeof(char *))))
{
if (buf) free(buf);
goto xserver_error;
}
args[0] = (char *)entrance_config->command.xinit_path;
token = strtok(buf, " ");
++num_token;
for(i = 1; i < num_token; ++i)
{
if (token)
args[i] = token;
token = strtok(NULL, " ");
}
args[num_token] = NULL;
}
else
{
if (!(args = calloc(2, sizeof(char*))))
goto xserver_error;
args[0] = (char *)entrance_config->command.xinit_path;
args[1] = NULL;
}
execv(args[0], args);
if (buf) free(buf);
if (args) free(args);
PT("Couldn't launch Xserver ...\n");
}
return pid;
xserver_error:
_exit(EXIT_FAILURE);
}
static Eina_Bool
_xserver_started(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
{
PT("xserver started\n");
_env_set(_xserver->dname);
_xserver->start(_xserver->dname);
return ECORE_CALLBACK_PASS_ON;
}
int
entrance_xserver_init(Entrance_X_Cb start, const char *dname)
{
int pid;
char buf[64];
sigset_t newset;
sigemptyset(&newset);
_xserver = calloc(1, sizeof(Entrance_Xserver));
_xserver->dname = eina_stringshare_add(dname);
_xserver->start = start;
pid = _xserver_start();
snprintf(buf, sizeof(buf), "ENTRANCE_XPID=%d", pid);
putenv(strdup(buf));
PT("xserver adding signal user handler\n");
_handler_start = ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
_xserver_started,
NULL);
return pid;
}
void
9 years ago
entrance_xserver_end(void)
{
const char *xpid;
PT("xserver end\n");
xpid = getenv("ENTRANCE_XPID");
if (xpid)
kill(atoi(xpid), SIGTERM);
unsetenv("ENTRANCE_XPID");
while (waitpid(-1, NULL, WNOHANG) > 0);
}
void
9 years ago
entrance_xserver_shutdown(void)
{
eina_stringshare_del(_xserver->dname);
free(_xserver);
ecore_event_handler_del(_handler_start);
}