remote.c revision 8108eb18
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
358108eb18Smrg#include <X11/ICE/ICEutil.h>
368108eb18Smrg
378108eb18Smrgstatic char 		*format_rstart_env(char *str);
388108eb18Smrg
398108eb18Smrgextern IceAuthDataEntry	*authDataEntries;
408108eb18Smrgextern int		numTransports;
418108eb18Smrg
428108eb18Smrg
438108eb18Smrgvoid
448108eb18Smrgremote_start(char *restart_protocol, char *restart_machine, char *program,
458108eb18Smrg	     char **args, char *cwd, char **env,
468108eb18Smrg	     char *non_local_display_env, char *non_local_session_env)
478108eb18Smrg{
488108eb18Smrg    FILE *fp;
498108eb18Smrg    int	 pipefd[2];
508108eb18Smrg    char msg[256];
518108eb18Smrg    int  i;
528108eb18Smrg
538108eb18Smrg    if (strcmp (restart_protocol, "rstart-rsh") != 0)
548108eb18Smrg    {
558108eb18Smrg	if (verbose)
568108eb18Smrg	    printf ("Only rstart-rsh remote execution protocol supported.\n");
578108eb18Smrg	return;
588108eb18Smrg    }
598108eb18Smrg
608108eb18Smrg    if (!restart_machine)
618108eb18Smrg    {
628108eb18Smrg	if (verbose)
638108eb18Smrg	    printf ("Bad remote machine specified for remote execute.\n");
648108eb18Smrg	return;
658108eb18Smrg    }
668108eb18Smrg
678108eb18Smrg    if (verbose)
688108eb18Smrg	printf ("Attempting to restart remote client on %s\n",
698108eb18Smrg	    restart_machine);
708108eb18Smrg
718108eb18Smrg    if (pipe (pipefd) < 0)
728108eb18Smrg    {
738108eb18Smrg	sprintf (msg, "%s: pipe() error during remote start of %s",
748108eb18Smrg	    Argv[0], program);
758108eb18Smrg	add_log_text (msg);
768108eb18Smrg	perror (msg);
778108eb18Smrg    }
788108eb18Smrg    else
798108eb18Smrg    {
808108eb18Smrg	switch(fork())
818108eb18Smrg	{
828108eb18Smrg	case -1:
838108eb18Smrg
848108eb18Smrg	    sprintf (msg, "%s: fork() error during remote start of %s",
858108eb18Smrg		Argv[0], program);
868108eb18Smrg	    add_log_text (msg);
878108eb18Smrg	    perror (msg);
888108eb18Smrg	    break;
898108eb18Smrg
908108eb18Smrg	case 0:		/* kid */
918108eb18Smrg
928108eb18Smrg	    close (pipefd[1]);
938108eb18Smrg	    close (0);
948108eb18Smrg	    dup (pipefd[0]);
958108eb18Smrg	    close (pipefd[0]);
968108eb18Smrg
978108eb18Smrg	    execlp (RSHCMD, restart_machine, "rstartd", (char *) 0);
988108eb18Smrg
998108eb18Smrg	    sprintf (msg,
1008108eb18Smrg	        "%s: execlp() of rstartd failed for remote start of %s",
1018108eb18Smrg		Argv[0], program);
1028108eb18Smrg	    perror (msg);
1038108eb18Smrg	    /*
1048108eb18Smrg	     * TODO : We would like to send this log information to the
1058108eb18Smrg	     * log window in the parent.  This would require using the
1068108eb18Smrg	     * pipe between the parent and child.  The child would
1078108eb18Smrg	     * set close-on-exec.  If the exec succeeds, the pipe will
1088108eb18Smrg	     * be closed.  If it fails, the child can write a message
1098108eb18Smrg	     * to the parent.
1108108eb18Smrg	     */
1118108eb18Smrg	    _exit(255);
1128108eb18Smrg
1138108eb18Smrg	default:		/* parent */
1148108eb18Smrg
1158108eb18Smrg	    close (pipefd[0]);
1168108eb18Smrg	    fp = (FILE *) fdopen (pipefd[1], "w");
1178108eb18Smrg
1188108eb18Smrg	    fprintf (fp, "CONTEXT X\n");
1198108eb18Smrg	    fprintf (fp, "DIR %s\n", cwd);
1208108eb18Smrg	    fprintf (fp, "DETACH\n");
1218108eb18Smrg
1228108eb18Smrg	    if (env)
1238108eb18Smrg	    {
1248108eb18Smrg		/*
1258108eb18Smrg		 * The application saved its environment.
1268108eb18Smrg		 */
1278108eb18Smrg
1288108eb18Smrg		for (i = 0; env[i]; i++)
1298108eb18Smrg		{
1308108eb18Smrg		    /*
1318108eb18Smrg		     * rstart requires that any spaces, backslashes, or
1328108eb18Smrg		     * non-printable characters inside of a string be
1338108eb18Smrg		     * represented by octal escape sequences.
1348108eb18Smrg		     */
1358108eb18Smrg
1368108eb18Smrg		    char *temp = format_rstart_env (env[i]);
1378108eb18Smrg		    fprintf (fp, "MISC X %s\n", temp);
1388108eb18Smrg		    if (temp != env[i])
1398108eb18Smrg			XtFree (temp);
1408108eb18Smrg		}
1418108eb18Smrg	    }
1428108eb18Smrg	    else
1438108eb18Smrg	    {
1448108eb18Smrg		/*
1458108eb18Smrg		 * The application did not save its environment.
1468108eb18Smrg		 * The default PATH set up by rstart may not contain
1478108eb18Smrg		 * the program we want to restart.  We play it safe
1488108eb18Smrg		 * and pass xsm's PATH.  This will most likely contain
1498108eb18Smrg		 * the path we need.
1508108eb18Smrg		 */
1518108eb18Smrg
1528108eb18Smrg		char *path = (char *) getenv ("PATH");
1538108eb18Smrg
1548108eb18Smrg		if (path)
1558108eb18Smrg		    fprintf (fp, "MISC X PATH=%s\n", path);
1568108eb18Smrg	    }
1578108eb18Smrg
1588108eb18Smrg	    fprintf (fp, "MISC X %s\n", non_local_display_env);
1598108eb18Smrg	    fprintf (fp, "MISC X %s\n", non_local_session_env);
1608108eb18Smrg
1618108eb18Smrg	    /*
1628108eb18Smrg	     * Pass the authentication data.
1638108eb18Smrg	     * Each transport has auth data for ICE and XSMP.
1648108eb18Smrg	     * Don't pass local auth data.
1658108eb18Smrg	     */
1668108eb18Smrg
1678108eb18Smrg	    for (i = 0; i < numTransports * 2; i++)
1688108eb18Smrg	    {
1698108eb18Smrg		if (Strstr (authDataEntries[i].network_id, "local/"))
1708108eb18Smrg		    continue;
1718108eb18Smrg
1728108eb18Smrg		fprintf (fp, "AUTH ICE %s \"\" %s %s ",
1738108eb18Smrg		    authDataEntries[i].protocol_name,
1748108eb18Smrg		    authDataEntries[i].network_id,
1758108eb18Smrg		    authDataEntries[i].auth_name);
1768108eb18Smrg
1778108eb18Smrg		fprintfhex (fp,
1788108eb18Smrg		    authDataEntries[i].auth_data_length,
1798108eb18Smrg		    authDataEntries[i].auth_data);
1808108eb18Smrg
1818108eb18Smrg		fprintf (fp, "\n");
1828108eb18Smrg	    }
1838108eb18Smrg
1848108eb18Smrg	    /*
1858108eb18Smrg	     * And execute the program
1868108eb18Smrg	     */
1878108eb18Smrg
1888108eb18Smrg	    fprintf (fp, "EXEC %s %s", program, program);
1898108eb18Smrg	    for (i = 1; args[i]; i++)
1908108eb18Smrg		fprintf (fp, " %s", args[i]);
1918108eb18Smrg	    fprintf (fp, "\n\n");
1928108eb18Smrg	    fclose (fp);
1938108eb18Smrg	    break;
1948108eb18Smrg	}
1958108eb18Smrg    }
1968108eb18Smrg}
1978108eb18Smrg
1988108eb18Smrg
1998108eb18Smrg
2008108eb18Smrg/*
2018108eb18Smrg * rstart requires that any spaces/backslashes/non-printable characters
2028108eb18Smrg * inside of a string be represented by octal escape sequences.
2038108eb18Smrg */
2048108eb18Smrg
2058108eb18Smrgstatic char *
2068108eb18Smrgformat_rstart_env(char *str)
2078108eb18Smrg{
2088108eb18Smrg    int escape_count = 0, i;
2098108eb18Smrg    char *temp = str;
2108108eb18Smrg
2118108eb18Smrg    while (*temp != '\0')
2128108eb18Smrg    {
2138108eb18Smrg	if (!isgraph (*temp) || *temp == '\\')
2148108eb18Smrg	    escape_count++;
2158108eb18Smrg	temp++;
2168108eb18Smrg    }
2178108eb18Smrg
2188108eb18Smrg    if (escape_count == 0)
2198108eb18Smrg	return (str);
2208108eb18Smrg    else
2218108eb18Smrg    {
2228108eb18Smrg	int len = strlen (str) + 1 + (escape_count * 3);
2238108eb18Smrg	char *ret = (char *) XtMalloc (len);
2248108eb18Smrg	char *ptr = ret;
2258108eb18Smrg
2268108eb18Smrg	temp = str;
2278108eb18Smrg	while (*temp != '\0')
2288108eb18Smrg	{
2298108eb18Smrg	    if (!isgraph (*temp) || *temp == '\\')
2308108eb18Smrg	    {
2318108eb18Smrg		char octal[3];
2328108eb18Smrg		sprintf (octal, "%o", *temp);
2338108eb18Smrg		*(ptr++) = '\\';
2348108eb18Smrg		for (i = 0; i < (3 - (int) strlen (octal)); i++)
2358108eb18Smrg		    *(ptr++) = '0';
2368108eb18Smrg		strcpy (ptr, octal);
2378108eb18Smrg		ptr += strlen (octal);
2388108eb18Smrg	    }
2398108eb18Smrg	    else
2408108eb18Smrg		*(ptr++) = *temp;
2418108eb18Smrg
2428108eb18Smrg	    temp++;
2438108eb18Smrg	}
2448108eb18Smrg
2458108eb18Smrg	*ptr = '\0';
2468108eb18Smrg	return (ret);
2478108eb18Smrg    }
2488108eb18Smrg}
249