remote.c revision 5977a007
18108eb18Smrg/* $Xorg: remote.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $ */
28108eb18Smrg/******************************************************************************
38108eb18Smrg
48108eb18SmrgCopyright 1993, 1998  The Open Group
58108eb18Smrg
68108eb18SmrgPermission to use, copy, modify, distribute, and sell this software and its
78108eb18Smrgdocumentation for any purpose is hereby granted without fee, provided that
88108eb18Smrgthe above copyright notice appear in all copies and that both that
98108eb18Smrgcopyright notice and this permission notice appear in supporting
108108eb18Smrgdocumentation.
118108eb18Smrg
128108eb18SmrgThe above copyright notice and this permission notice shall be included in
138108eb18Smrgall copies or substantial portions of the Software.
148108eb18Smrg
158108eb18SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168108eb18SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178108eb18SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
188108eb18SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
198108eb18SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
208108eb18SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
218108eb18Smrg
228108eb18SmrgExcept as contained in this notice, the name of The Open Group shall not be
238108eb18Smrgused in advertising or otherwise to promote the sale, use or other dealings
248108eb18Smrgin this Software without prior written authorization from The Open Group.
258108eb18Smrg******************************************************************************/
268108eb18Smrg/* $XFree86: xc/programs/xsm/remote.c,v 1.4 2001/01/17 23:46:30 dawes Exp $ */
278108eb18Smrg
288108eb18Smrg/*
298108eb18Smrg * We use the rstart protocol to restart clients on remote machines.
308108eb18Smrg */
318108eb18Smrg
328108eb18Smrg#include "xsm.h"
338108eb18Smrg#include "log.h"
348108eb18Smrg
358108eb18Smrgstatic char 		*format_rstart_env(char *str);
368108eb18Smrg
378108eb18Smrg
388108eb18Smrgvoid
395977a007Smrgremote_start(const char *restart_protocol, const char *restart_machine,
405977a007Smrg	     const char *program, char **args, const char *cwd,
415977a007Smrg	     char **env, const char *non_local_display_env,
425977a007Smrg	     const char *non_local_session_env)
438108eb18Smrg{
448108eb18Smrg    FILE *fp;
458108eb18Smrg    int	 pipefd[2];
468108eb18Smrg    char msg[256];
478108eb18Smrg    int  i;
488108eb18Smrg
498108eb18Smrg    if (strcmp (restart_protocol, "rstart-rsh") != 0)
508108eb18Smrg    {
518108eb18Smrg	if (verbose)
528108eb18Smrg	    printf ("Only rstart-rsh remote execution protocol supported.\n");
538108eb18Smrg	return;
548108eb18Smrg    }
558108eb18Smrg
568108eb18Smrg    if (!restart_machine)
578108eb18Smrg    {
588108eb18Smrg	if (verbose)
598108eb18Smrg	    printf ("Bad remote machine specified for remote execute.\n");
608108eb18Smrg	return;
618108eb18Smrg    }
628108eb18Smrg
638108eb18Smrg    if (verbose)
648108eb18Smrg	printf ("Attempting to restart remote client on %s\n",
658108eb18Smrg	    restart_machine);
668108eb18Smrg
678108eb18Smrg    if (pipe (pipefd) < 0)
688108eb18Smrg    {
691a650d1eSmrg	snprintf (msg, sizeof(msg),
701a650d1eSmrg		  "%s: pipe() error during remote start of %s",
711a650d1eSmrg		  Argv[0], program);
728108eb18Smrg	add_log_text (msg);
738108eb18Smrg	perror (msg);
748108eb18Smrg    }
758108eb18Smrg    else
768108eb18Smrg    {
778108eb18Smrg	switch(fork())
788108eb18Smrg	{
798108eb18Smrg	case -1:
808108eb18Smrg
811a650d1eSmrg	    snprintf (msg, sizeof(msg),
821a650d1eSmrg		      "%s: fork() error during remote start of %s",
831a650d1eSmrg		      Argv[0], program);
848108eb18Smrg	    add_log_text (msg);
858108eb18Smrg	    perror (msg);
868108eb18Smrg	    break;
878108eb18Smrg
888108eb18Smrg	case 0:		/* kid */
898108eb18Smrg
908108eb18Smrg	    close (pipefd[1]);
918108eb18Smrg	    close (0);
928108eb18Smrg	    dup (pipefd[0]);
938108eb18Smrg	    close (pipefd[0]);
948108eb18Smrg
958108eb18Smrg	    execlp (RSHCMD, restart_machine, "rstartd", (char *) 0);
968108eb18Smrg
971a650d1eSmrg	    snprintf (msg, sizeof(msg),
981a650d1eSmrg		      "%s: execlp() of rstartd failed for remote start of %s",
991a650d1eSmrg		      Argv[0], program);
1008108eb18Smrg	    perror (msg);
1018108eb18Smrg	    /*
1028108eb18Smrg	     * TODO : We would like to send this log information to the
1038108eb18Smrg	     * log window in the parent.  This would require using the
1048108eb18Smrg	     * pipe between the parent and child.  The child would
1058108eb18Smrg	     * set close-on-exec.  If the exec succeeds, the pipe will
1068108eb18Smrg	     * be closed.  If it fails, the child can write a message
1078108eb18Smrg	     * to the parent.
1088108eb18Smrg	     */
1098108eb18Smrg	    _exit(255);
1108108eb18Smrg
1118108eb18Smrg	default:		/* parent */
1128108eb18Smrg
1138108eb18Smrg	    close (pipefd[0]);
1148108eb18Smrg	    fp = (FILE *) fdopen (pipefd[1], "w");
1158108eb18Smrg
1168108eb18Smrg	    fprintf (fp, "CONTEXT X\n");
1178108eb18Smrg	    fprintf (fp, "DIR %s\n", cwd);
1188108eb18Smrg	    fprintf (fp, "DETACH\n");
1198108eb18Smrg
1208108eb18Smrg	    if (env)
1218108eb18Smrg	    {
1228108eb18Smrg		/*
1238108eb18Smrg		 * The application saved its environment.
1248108eb18Smrg		 */
1258108eb18Smrg
1268108eb18Smrg		for (i = 0; env[i]; i++)
1278108eb18Smrg		{
1288108eb18Smrg		    /*
1298108eb18Smrg		     * rstart requires that any spaces, backslashes, or
1308108eb18Smrg		     * non-printable characters inside of a string be
1318108eb18Smrg		     * represented by octal escape sequences.
1328108eb18Smrg		     */
1338108eb18Smrg
1348108eb18Smrg		    char *temp = format_rstart_env (env[i]);
1358108eb18Smrg		    fprintf (fp, "MISC X %s\n", temp);
1368108eb18Smrg		    if (temp != env[i])
1378108eb18Smrg			XtFree (temp);
1388108eb18Smrg		}
1398108eb18Smrg	    }
1408108eb18Smrg	    else
1418108eb18Smrg	    {
1428108eb18Smrg		/*
1438108eb18Smrg		 * The application did not save its environment.
1448108eb18Smrg		 * The default PATH set up by rstart may not contain
1458108eb18Smrg		 * the program we want to restart.  We play it safe
1468108eb18Smrg		 * and pass xsm's PATH.  This will most likely contain
1478108eb18Smrg		 * the path we need.
1488108eb18Smrg		 */
1498108eb18Smrg
1508108eb18Smrg		char *path = (char *) getenv ("PATH");
1518108eb18Smrg
1528108eb18Smrg		if (path)
1538108eb18Smrg		    fprintf (fp, "MISC X PATH=%s\n", path);
1548108eb18Smrg	    }
1558108eb18Smrg
1568108eb18Smrg	    fprintf (fp, "MISC X %s\n", non_local_display_env);
1578108eb18Smrg	    fprintf (fp, "MISC X %s\n", non_local_session_env);
1588108eb18Smrg
1598108eb18Smrg	    /*
1608108eb18Smrg	     * Pass the authentication data.
1618108eb18Smrg	     * Each transport has auth data for ICE and XSMP.
1628108eb18Smrg	     * Don't pass local auth data.
1638108eb18Smrg	     */
1648108eb18Smrg
1658108eb18Smrg	    for (i = 0; i < numTransports * 2; i++)
1668108eb18Smrg	    {
1678108eb18Smrg		if (Strstr (authDataEntries[i].network_id, "local/"))
1688108eb18Smrg		    continue;
1698108eb18Smrg
1708108eb18Smrg		fprintf (fp, "AUTH ICE %s \"\" %s %s ",
1718108eb18Smrg		    authDataEntries[i].protocol_name,
1728108eb18Smrg		    authDataEntries[i].network_id,
1738108eb18Smrg		    authDataEntries[i].auth_name);
1748108eb18Smrg
1758108eb18Smrg		fprintfhex (fp,
1768108eb18Smrg		    authDataEntries[i].auth_data_length,
1778108eb18Smrg		    authDataEntries[i].auth_data);
1788108eb18Smrg
1798108eb18Smrg		fprintf (fp, "\n");
1808108eb18Smrg	    }
1818108eb18Smrg
1828108eb18Smrg	    /*
1838108eb18Smrg	     * And execute the program
1848108eb18Smrg	     */
1858108eb18Smrg
1868108eb18Smrg	    fprintf (fp, "EXEC %s %s", program, program);
1878108eb18Smrg	    for (i = 1; args[i]; i++)
1888108eb18Smrg		fprintf (fp, " %s", args[i]);
1898108eb18Smrg	    fprintf (fp, "\n\n");
1908108eb18Smrg	    fclose (fp);
1918108eb18Smrg	    break;
1928108eb18Smrg	}
1938108eb18Smrg    }
1948108eb18Smrg}
1958108eb18Smrg
1968108eb18Smrg
1978108eb18Smrg
1988108eb18Smrg/*
1998108eb18Smrg * rstart requires that any spaces/backslashes/non-printable characters
2008108eb18Smrg * inside of a string be represented by octal escape sequences.
2018108eb18Smrg */
2028108eb18Smrg
2038108eb18Smrgstatic char *
2048108eb18Smrgformat_rstart_env(char *str)
2058108eb18Smrg{
2068108eb18Smrg    int escape_count = 0, i;
2078108eb18Smrg    char *temp = str;
2088108eb18Smrg
2098108eb18Smrg    while (*temp != '\0')
2108108eb18Smrg    {
2118108eb18Smrg	if (!isgraph (*temp) || *temp == '\\')
2128108eb18Smrg	    escape_count++;
2138108eb18Smrg	temp++;
2148108eb18Smrg    }
2158108eb18Smrg
2168108eb18Smrg    if (escape_count == 0)
2178108eb18Smrg	return (str);
2188108eb18Smrg    else
2198108eb18Smrg    {
2208108eb18Smrg	int len = strlen (str) + 1 + (escape_count * 3);
2218108eb18Smrg	char *ret = (char *) XtMalloc (len);
2228108eb18Smrg	char *ptr = ret;
2238108eb18Smrg
2248108eb18Smrg	temp = str;
2258108eb18Smrg	while (*temp != '\0')
2268108eb18Smrg	{
2278108eb18Smrg	    if (!isgraph (*temp) || *temp == '\\')
2288108eb18Smrg	    {
2291a650d1eSmrg		char octal[4];
2301a650d1eSmrg		snprintf (octal, sizeof(octal), "%o", *temp);
2318108eb18Smrg		*(ptr++) = '\\';
2328108eb18Smrg		for (i = 0; i < (3 - (int) strlen (octal)); i++)
2338108eb18Smrg		    *(ptr++) = '0';
2348108eb18Smrg		strcpy (ptr, octal);
2358108eb18Smrg		ptr += strlen (octal);
2368108eb18Smrg	    }
2378108eb18Smrg	    else
2388108eb18Smrg		*(ptr++) = *temp;
2398108eb18Smrg
2408108eb18Smrg	    temp++;
2418108eb18Smrg	}
2428108eb18Smrg
2438108eb18Smrg	*ptr = '\0';
2448108eb18Smrg	return (ret);
2458108eb18Smrg    }
2468108eb18Smrg}
247