sync code with last improvements from OpenBSD
This commit is contained in:
commit
88965415ff
26235 changed files with 29195616 additions and 0 deletions
608
app/xsm/restart.c
Normal file
608
app/xsm/restart.c
Normal file
|
@ -0,0 +1,608 @@
|
|||
/* $Xorg: restart.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $ */
|
||||
/******************************************************************************
|
||||
|
||||
Copyright 1993, 1998 The Open Group
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
The above copyright notice and this permission notice 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
|
||||
OPEN GROUP 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.
|
||||
|
||||
Except as contained in this notice, the name of The Open Group shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from The Open Group.
|
||||
******************************************************************************/
|
||||
/* $XFree86: xc/programs/xsm/restart.c,v 1.5 2001/01/17 23:46:30 dawes Exp $ */
|
||||
|
||||
#include "xsm.h"
|
||||
#include "log.h"
|
||||
#include "restart.h"
|
||||
#include "saveutil.h"
|
||||
|
||||
|
||||
/*
|
||||
* Until XSMP provides a better way to know which clients are "managers",
|
||||
* we have to hard code the list.
|
||||
*/
|
||||
|
||||
Bool
|
||||
CheckIsManager(char *program)
|
||||
{
|
||||
return (strcmp (program, "twm") == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* GetRestartInfo() will determine which method should be used to
|
||||
* restart a client.
|
||||
*
|
||||
* 'restart_service_prop' is a property set by the client, or NULL.
|
||||
* The format is "remote_start_protocol/remote_start_data". An
|
||||
* example is "rstart-rsh/hostname". This is a non-standard property,
|
||||
* which is the whole reason we need this function in order to determine
|
||||
* the restart method. The proxy uses this property to over-ride the
|
||||
* 'client_host_name' from the ICE connection (the proxy is connected to
|
||||
* the SM via a local connection, but the proxy may be acting as a proxy
|
||||
* for a remote client).
|
||||
*
|
||||
* 'client_host_name' is the connection info obtained from the ICE
|
||||
* connection. It's format is "transport/host_info". An example
|
||||
* is "tcp/machine:port".
|
||||
*
|
||||
* If 'restart_service_prop' is NULL, we use 'client_host_name' to
|
||||
* determine the restart method. If the transport is "local", we
|
||||
* do a local restart. Otherwise, we use the default "rstart-rsh" method.
|
||||
*
|
||||
* If 'restart_service_prop' is non-NULL, we check the remote_start_protocol
|
||||
* field. "local" means a local restart. Currently, the only remote
|
||||
* protocol we recognize is "rstart-rsh". If the remote protocol is
|
||||
* "rstart-rsh" but the hostname in the 'restart_service_prop' matches
|
||||
* 'client_host_name', we do a local restart.
|
||||
*
|
||||
* On return, set the run_local flag, restart_protocol and restart_machine.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Restart clients. The flag indicates RESTART_MANAGERS or
|
||||
* RESTART_REST_OF_CLIENTS.
|
||||
*/
|
||||
|
||||
Status
|
||||
Restart(int flag)
|
||||
{
|
||||
List *cl, *pl, *vl;
|
||||
PendingClient *c;
|
||||
Prop *prop;
|
||||
const 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)
|
||||
{
|
||||
/*
|
||||
* The client is being restarted on the local machine.
|
||||
*/
|
||||
|
||||
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: /* kid */
|
||||
chdir(cwd);
|
||||
if(env) environ = env;
|
||||
execvp(program, args);
|
||||
snprintf (logtext, sizeof(logtext),
|
||||
"%s: Can't execvp() %s", Argv[0], program);
|
||||
perror (logtext);
|
||||
/*
|
||||
* TODO : We would like to send this log information to the
|
||||
* log window in the parent. This would require opening
|
||||
* a pipe between the parent and child. The child would
|
||||
* set close-on-exec. If the exec succeeds, the pipe will
|
||||
* be closed. If it fails, the child can write a message
|
||||
* to the parent.
|
||||
*/
|
||||
_exit(255);
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!remote_allowed)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Can't remote start client ID '%s': only local supported\n",
|
||||
c->clientId);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The client is being restarted on a remote machine.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Clone a client
|
||||
*/
|
||||
|
||||
void
|
||||
Clone(ClientRec *client, Bool useSavedState)
|
||||
{
|
||||
const 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)
|
||||
{
|
||||
/*
|
||||
* The client is being cloned on the local machine.
|
||||
*/
|
||||
|
||||
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: /* kid */
|
||||
chdir(cwd);
|
||||
if(env) environ = env;
|
||||
execvp(program, args);
|
||||
snprintf (msg, sizeof(msg),
|
||||
"%s: Can't execvp() %s", Argv[0], program);
|
||||
perror (msg);
|
||||
/*
|
||||
* TODO : We would like to send this log information to the
|
||||
* log window in the parent. This would require opening
|
||||
* a pipe between the parent and child. The child would
|
||||
* set close-on-exec. If the exec succeeds, the pipe will
|
||||
* be closed. If it fails, the child can write a message
|
||||
* to the parent.
|
||||
*/
|
||||
_exit(255);
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!remote_allowed)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Can't remote clone client ID '%s': only local supported\n",
|
||||
client->clientId);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The client is being cloned on a remote machine.
|
||||
*/
|
||||
|
||||
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, filename[128];
|
||||
const char *home;
|
||||
int buflen, len;
|
||||
|
||||
/*
|
||||
* First try ~/.xsmstartup, then system.xsm
|
||||
*/
|
||||
|
||||
home = 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);
|
||||
}
|
||||
}
|
||||
fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
|
||||
|
||||
buf = NULL;
|
||||
buflen = 0;
|
||||
|
||||
while (getnextline(&buf, &buflen, f))
|
||||
{
|
||||
char logtext[256];
|
||||
|
||||
if (buf[0] == '!')
|
||||
continue; /* a comment */
|
||||
|
||||
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';
|
||||
|
||||
/* let the shell parse the stupid args */
|
||||
|
||||
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++)
|
||||
{
|
||||
/*
|
||||
* Let the shell parse the stupid args. We need to add an "&"
|
||||
* at the end of the command. We previously allocated an extra
|
||||
* byte for this.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue