#include "xsm.h"
#include "log.h"
#include "restart.h"
#include "saveutil.h"
Bool
CheckIsManager(char *program)
{
return (strcmp (program, "twm") == 0);
}
void
GetRestartInfo(char *restart_service_prop, char *client_host_name,
Bool *run_local, char **restart_protocol, char **restart_machine)
{
char hostnamebuf[80];
char *temp;
*run_local = False;
*restart_protocol = NULL;
*restart_machine = NULL;
if (restart_service_prop)
{
gethostname (hostnamebuf, sizeof hostnamebuf);
if ((temp = (char *) strchr (
restart_service_prop, '/')) == NULL)
{
*restart_protocol = (char *) XtNewString ("rstart-rsh");
*restart_machine = (char *) XtNewString (restart_service_prop);
}
else
{
*restart_protocol = (char *) XtNewString (restart_service_prop);
(*restart_protocol)[temp - restart_service_prop] = '\0';
*restart_machine = (char *) XtNewString (temp + 1);
}
if (strcmp (*restart_machine, hostnamebuf) == 0 ||
strcmp (*restart_protocol, "local") == 0)
{
*run_local = True;
}
}
else
{
if (strncmp (client_host_name, "tcp/", 4) != 0 &&
strncmp (client_host_name, "decnet/", 7) != 0)
{
*run_local = True;
}
else
{
*restart_protocol = (char *) XtNewString ("rstart-rsh");
if ((temp = (char *) strchr (
client_host_name, '/')) == NULL)
{
*restart_machine = (char *) XtNewString (client_host_name);
}
else
{
*restart_machine = (char *) XtNewString (temp + 1);
}
}
}
}
Status
Restart(int flag)
{
List *cl, *pl, *vl;
PendingClient *c;
Prop *prop;
char *cwd;
char *program;
char **args;
char **env;
char **pp;
int cnt;
char *p;
char *restart_service_prop;
char *restart_protocol;
char *restart_machine;
Bool run_local;
Bool is_manager;
Bool ran_manager = 0;
for(cl = ListFirst(PendingList); cl; cl = ListNext(cl)) {
c = (PendingClient *)cl->thing;
if (verbose) {
printf("Restarting id '%s'...\n", c->clientId);
printf("Host = %s\n", c->clientHostname);
}
cwd = ".";
env = NULL;
program=NULL;
args=NULL;
restart_service_prop=NULL;
is_manager = 0;
for(pl = ListFirst(c->props); pl; pl = ListNext(pl)) {
prop = (Prop *)pl->thing;
if(!strcmp(prop->name, SmProgram)) {
vl = ListFirst(prop->values);
if(vl) program = ((PropValue *)vl->thing)->value;
if (CheckIsManager (program))
is_manager = 1;
} else if(!strcmp(prop->name, SmCurrentDirectory)) {
vl = ListFirst(prop->values);
if(vl) cwd = ((PropValue *)vl->thing)->value;
} else if(!strcmp(prop->name, "_XC_RestartService")) {
vl = ListFirst(prop->values);
if(vl) restart_service_prop =
((PropValue *)vl->thing)->value;
} else if(!strcmp(prop->name, SmRestartCommand)) {
cnt = ListCount(prop->values);
args = (char **)XtMalloc((cnt+1) * sizeof(char *));
pp = args;
for(vl = ListFirst(prop->values); vl; vl = ListNext(vl)) {
*pp++ = ((PropValue *)vl->thing)->value;
}
*pp = NULL;
} else if(!strcmp(prop->name, SmEnvironment)) {
cnt = ListCount(prop->values);
env = (char **)XtMalloc((cnt+3+1) * sizeof(char *));
pp = env;
for(vl = ListFirst(prop->values); vl; vl = ListNext(vl)) {
p = ((PropValue *)vl->thing)->value;
if((display_env && strbw(p, "DISPLAY="))
|| (session_env && strbw(p, "SESSION_MANAGER="))
|| (audio_env && strbw(p, "AUDIOSERVER="))
) continue;
*pp++ = p;
}
if(display_env) *pp++ = display_env;
if(session_env) *pp++ = session_env;
if(audio_env) *pp++ = audio_env;
*pp = NULL;
}
}
if(program && args) {
char logtext[256];
if ((flag == RESTART_MANAGERS && !is_manager) ||
(flag == RESTART_REST_OF_CLIENTS && is_manager))
{
if(args) XtFree((char *)args);
if(env) XtFree((char *)env);
continue;
}
if (flag == RESTART_MANAGERS && is_manager)
ran_manager = 1;
if (verbose) {
printf("\t%s\n", program);
printf("\t");
for(pp = args; *pp; pp++) printf("%s ", *pp);
printf("\n");
}
GetRestartInfo (restart_service_prop, c->clientHostname,
&run_local, &restart_protocol, &restart_machine);
if (run_local)
{
snprintf (logtext, sizeof(logtext), "Restarting locally : ");
for (pp = args; *pp; pp++)
{
strcat (logtext, *pp);
strcat (logtext, " ");
}
strcat (logtext, "\n");
add_log_text (logtext);
switch(fork()) {
case -1:
snprintf (logtext, sizeof(logtext),
"%s: Can't fork() %s", Argv[0], program);
add_log_text (logtext);
perror (logtext);
break;
case 0:
chdir(cwd);
if(env) environ = env;
execvp(program, args);
snprintf (logtext, sizeof(logtext),
"%s: Can't execvp() %s", Argv[0], program);
perror (logtext);
_exit(255);
default:
break;
}
}
else if (!remote_allowed)
{
fprintf(stderr,
"Can't remote start client ID '%s': only local supported\n",
c->clientId);
}
else
{
snprintf (logtext, sizeof(logtext),
"Restarting remotely on %s : ", restart_machine);
for (pp = args; *pp; pp++)
{
strcat (logtext, *pp);
strcat (logtext, " ");
}
strcat (logtext, "\n");
add_log_text (logtext);
remote_start (restart_protocol, restart_machine,
program, args, cwd, env,
non_local_display_env, non_local_session_env);
}
if (restart_protocol)
XtFree (restart_protocol);
if (restart_machine)
XtFree (restart_machine);
} else {
fprintf(stderr, "Can't restart ID '%s': no program or no args\n",
c->clientId);
}
if(args) XtFree((char *)args);
if(env) XtFree((char *)env);
}
if (flag == RESTART_MANAGERS && !ran_manager)
return (0);
else
return (1);
}
void
Clone(ClientRec *client, Bool useSavedState)
{
char *cwd;
char *program;
char **args;
char **env;
char **pp;
char *p;
char *restart_service_prop;
char *restart_protocol;
char *restart_machine;
Bool run_local;
List *pl, *pj;
if (verbose)
{
printf ("Cloning id '%s', useSavedState = %d...\n",
client->clientId, useSavedState);
printf ("Host = %s\n", client->clientHostname);
}
cwd = ".";
env = NULL;
program = NULL;
args = NULL;
restart_service_prop = NULL;
for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
{
Prop *pprop = (Prop *) pl->thing;
List *vl = ListFirst (pprop->values);
PropValue *pval = (PropValue *) vl->thing;
if (strcmp (pprop->name, SmProgram) == 0)
program = (char *) pval->value;
else if (strcmp (pprop->name, SmCurrentDirectory) == 0)
cwd = (char *) pval->value;
else if (strcmp (pprop->name, "_XC_RestartService") == 0)
restart_service_prop = (char *) pval->value;
else if (
(!useSavedState && strcmp (pprop->name, SmCloneCommand) == 0) ||
(useSavedState && strcmp (pprop->name, SmRestartCommand) == 0))
{
args = (char **) XtMalloc (
(ListCount (pprop->values) + 1) * sizeof (char *));
pp = args;
for (pj = ListFirst (pprop->values); pj; pj = ListNext (pj))
{
pval = (PropValue *) pj->thing;
*pp++ = (char *) pval->value;
}
*pp = NULL;
}
else if (strcmp (pprop->name, SmEnvironment) == 0)
{
env = (char **) XtMalloc (
(ListCount (pprop->values) + 3 + 1) * sizeof (char *));
pp = env;
for (pj = ListFirst (pprop->values); pj; pj = ListNext (pj))
{
pval = (PropValue *) pj->thing;
p = (char *) pval->value;
if ((display_env && strbw (p, "DISPLAY="))
|| (session_env && strbw (p, "SESSION_MANAGER="))
|| (audio_env && strbw (p, "AUDIOSERVER=")))
continue;
*pp++ = p;
}
if (display_env)
*pp++ = display_env;
if (session_env)
*pp++ = session_env;
if (audio_env)
*pp++ = audio_env;
*pp = NULL;
}
}
if (program && args)
{
if (verbose)
{
printf("\t%s\n", program);
printf("\t");
for (pp = args; *pp; pp++)
printf ("%s ", *pp);
printf("\n");
}
GetRestartInfo (restart_service_prop, client->clientHostname,
&run_local, &restart_protocol, &restart_machine);
if (run_local)
{
char msg[256];
switch(fork()) {
case -1:
snprintf (msg, sizeof(msg),
"%s: Can't fork() %s", Argv[0], program);
add_log_text (msg);
perror (msg);
break;
case 0:
chdir(cwd);
if(env) environ = env;
execvp(program, args);
snprintf (msg, sizeof(msg),
"%s: Can't execvp() %s", Argv[0], program);
perror (msg);
_exit(255);
default:
break;
}
}
else if (!remote_allowed)
{
fprintf(stderr,
"Can't remote clone client ID '%s': only local supported\n",
client->clientId);
}
else
{
remote_start (restart_protocol, restart_machine,
program, args, cwd, env,
non_local_display_env, non_local_session_env);
}
if (restart_protocol)
XtFree (restart_protocol);
if (restart_machine)
XtFree (restart_machine);
}
else
{
#ifdef XKB
XkbStdBell(XtDisplay(topLevel),XtWindow(topLevel),0,XkbBI_Failure);
#else
XBell (XtDisplay (topLevel), 0);
#endif
fprintf(stderr, "Can't restart ID '%s': no program or no args\n",
client->clientId);
}
if (args)
XtFree ((char *)args);
if (env)
XtFree ((char *)env);
}
void
StartDefaultApps (void)
{
FILE *f;
char *buf, *p, *home, filename[128];
int buflen, len;
home = (char *) getenv ("HOME");
if (!home)
home = ".";
snprintf (filename, sizeof(filename), "%s/.xsmstartup", home);
f = fopen (filename, "r");
if (!f)
{
f = fopen (SYSTEM_INIT_FILE, "r");
if (!f)
{
printf ("Could not find default apps file. Make sure you did\n");
printf ("a 'make install' in the xsm build directory.\n");
exit (1);
}
}
buf = NULL;
buflen = 0;
while (getnextline(&buf, &buflen, f))
{
char logtext[256];
if (buf[0] == '!')
continue;
if ((p = strchr (buf, '\n')))
*p = '\0';
snprintf (logtext, sizeof(logtext), "Starting locally : %s\n", buf);
add_log_text (logtext);
len = strlen (buf);
buf[len] = '&';
buf[len+1] = '\0';
execute_system_command (buf);
}
if (buf)
free (buf);
}
void
StartNonSessionAwareApps(void)
{
char logtext[256];
int i;
for (i = 0; i < non_session_aware_count; i++)
{
snprintf (logtext, sizeof(logtext), "Restarting locally : %s\n",
non_session_aware_clients[i]);
add_log_text (logtext);
strcat (non_session_aware_clients[i], "&");
execute_system_command (non_session_aware_clients[i]);
free ((char *) non_session_aware_clients[i]);
}
if (non_session_aware_clients)
{
free ((char *) non_session_aware_clients);
non_session_aware_clients = NULL;
}
}