123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 |
- /* $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);
- }
- }
- 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;
- }
- }
|