249 lines
6.0 KiB
C
249 lines
6.0 KiB
C
|
/* $Xorg: remote.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/remote.c,v 1.4 2001/01/17 23:46:30 dawes Exp $ */
|
|||
|
|
|||
|
/*
|
|||
|
* We use the rstart protocol to restart clients on remote machines.
|
|||
|
*/
|
|||
|
|
|||
|
#include "xsm.h"
|
|||
|
#include "log.h"
|
|||
|
|
|||
|
#include <X11/ICE/ICEutil.h>
|
|||
|
|
|||
|
static char *format_rstart_env(char *str);
|
|||
|
|
|||
|
extern IceAuthDataEntry *authDataEntries;
|
|||
|
extern int numTransports;
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
remote_start(char *restart_protocol, char *restart_machine, char *program,
|
|||
|
char **args, char *cwd, char **env,
|
|||
|
char *non_local_display_env, char *non_local_session_env)
|
|||
|
{
|
|||
|
FILE *fp;
|
|||
|
int pipefd[2];
|
|||
|
char msg[256];
|
|||
|
int i;
|
|||
|
|
|||
|
if (strcmp (restart_protocol, "rstart-rsh") != 0)
|
|||
|
{
|
|||
|
if (verbose)
|
|||
|
printf ("Only rstart-rsh remote execution protocol supported.\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (!restart_machine)
|
|||
|
{
|
|||
|
if (verbose)
|
|||
|
printf ("Bad remote machine specified for remote execute.\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (verbose)
|
|||
|
printf ("Attempting to restart remote client on %s\n",
|
|||
|
restart_machine);
|
|||
|
|
|||
|
if (pipe (pipefd) < 0)
|
|||
|
{
|
|||
|
sprintf (msg, "%s: pipe() error during remote start of %s",
|
|||
|
Argv[0], program);
|
|||
|
add_log_text (msg);
|
|||
|
perror (msg);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
switch(fork())
|
|||
|
{
|
|||
|
case -1:
|
|||
|
|
|||
|
sprintf (msg, "%s: fork() error during remote start of %s",
|
|||
|
Argv[0], program);
|
|||
|
add_log_text (msg);
|
|||
|
perror (msg);
|
|||
|
break;
|
|||
|
|
|||
|
case 0: /* kid */
|
|||
|
|
|||
|
close (pipefd[1]);
|
|||
|
close (0);
|
|||
|
dup (pipefd[0]);
|
|||
|
close (pipefd[0]);
|
|||
|
|
|||
|
execlp (RSHCMD, restart_machine, "rstartd", (char *) 0);
|
|||
|
|
|||
|
sprintf (msg,
|
|||
|
"%s: execlp() of rstartd failed for remote start of %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 using the
|
|||
|
* 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 */
|
|||
|
|
|||
|
close (pipefd[0]);
|
|||
|
fp = (FILE *) fdopen (pipefd[1], "w");
|
|||
|
|
|||
|
fprintf (fp, "CONTEXT X\n");
|
|||
|
fprintf (fp, "DIR %s\n", cwd);
|
|||
|
fprintf (fp, "DETACH\n");
|
|||
|
|
|||
|
if (env)
|
|||
|
{
|
|||
|
/*
|
|||
|
* The application saved its environment.
|
|||
|
*/
|
|||
|
|
|||
|
for (i = 0; env[i]; i++)
|
|||
|
{
|
|||
|
/*
|
|||
|
* rstart requires that any spaces, backslashes, or
|
|||
|
* non-printable characters inside of a string be
|
|||
|
* represented by octal escape sequences.
|
|||
|
*/
|
|||
|
|
|||
|
char *temp = format_rstart_env (env[i]);
|
|||
|
fprintf (fp, "MISC X %s\n", temp);
|
|||
|
if (temp != env[i])
|
|||
|
XtFree (temp);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/*
|
|||
|
* The application did not save its environment.
|
|||
|
* The default PATH set up by rstart may not contain
|
|||
|
* the program we want to restart. We play it safe
|
|||
|
* and pass xsm's PATH. This will most likely contain
|
|||
|
* the path we need.
|
|||
|
*/
|
|||
|
|
|||
|
char *path = (char *) getenv ("PATH");
|
|||
|
|
|||
|
if (path)
|
|||
|
fprintf (fp, "MISC X PATH=%s\n", path);
|
|||
|
}
|
|||
|
|
|||
|
fprintf (fp, "MISC X %s\n", non_local_display_env);
|
|||
|
fprintf (fp, "MISC X %s\n", non_local_session_env);
|
|||
|
|
|||
|
/*
|
|||
|
* Pass the authentication data.
|
|||
|
* Each transport has auth data for ICE and XSMP.
|
|||
|
* Don't pass local auth data.
|
|||
|
*/
|
|||
|
|
|||
|
for (i = 0; i < numTransports * 2; i++)
|
|||
|
{
|
|||
|
if (Strstr (authDataEntries[i].network_id, "local/"))
|
|||
|
continue;
|
|||
|
|
|||
|
fprintf (fp, "AUTH ICE %s \"\" %s %s ",
|
|||
|
authDataEntries[i].protocol_name,
|
|||
|
authDataEntries[i].network_id,
|
|||
|
authDataEntries[i].auth_name);
|
|||
|
|
|||
|
fprintfhex (fp,
|
|||
|
authDataEntries[i].auth_data_length,
|
|||
|
authDataEntries[i].auth_data);
|
|||
|
|
|||
|
fprintf (fp, "\n");
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* And execute the program
|
|||
|
*/
|
|||
|
|
|||
|
fprintf (fp, "EXEC %s %s", program, program);
|
|||
|
for (i = 1; args[i]; i++)
|
|||
|
fprintf (fp, " %s", args[i]);
|
|||
|
fprintf (fp, "\n\n");
|
|||
|
fclose (fp);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* rstart requires that any spaces/backslashes/non-printable characters
|
|||
|
* inside of a string be represented by octal escape sequences.
|
|||
|
*/
|
|||
|
|
|||
|
static char *
|
|||
|
format_rstart_env(char *str)
|
|||
|
{
|
|||
|
int escape_count = 0, i;
|
|||
|
char *temp = str;
|
|||
|
|
|||
|
while (*temp != '\0')
|
|||
|
{
|
|||
|
if (!isgraph (*temp) || *temp == '\\')
|
|||
|
escape_count++;
|
|||
|
temp++;
|
|||
|
}
|
|||
|
|
|||
|
if (escape_count == 0)
|
|||
|
return (str);
|
|||
|
else
|
|||
|
{
|
|||
|
int len = strlen (str) + 1 + (escape_count * 3);
|
|||
|
char *ret = (char *) XtMalloc (len);
|
|||
|
char *ptr = ret;
|
|||
|
|
|||
|
temp = str;
|
|||
|
while (*temp != '\0')
|
|||
|
{
|
|||
|
if (!isgraph (*temp) || *temp == '\\')
|
|||
|
{
|
|||
|
char octal[3];
|
|||
|
sprintf (octal, "%o", *temp);
|
|||
|
*(ptr++) = '\\';
|
|||
|
for (i = 0; i < (3 - (int) strlen (octal)); i++)
|
|||
|
*(ptr++) = '0';
|
|||
|
strcpy (ptr, octal);
|
|||
|
ptr += strlen (octal);
|
|||
|
}
|
|||
|
else
|
|||
|
*(ptr++) = *temp;
|
|||
|
|
|||
|
temp++;
|
|||
|
}
|
|||
|
|
|||
|
*ptr = '\0';
|
|||
|
return (ret);
|
|||
|
}
|
|||
|
}
|