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]);
1142bc08f26Swiz	    fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
1152bc08f26Swiz	    fp = fdopen (pipefd[1], "w");
1168108eb18Smrg
1178108eb18Smrg	    fprintf (fp, "CONTEXT X\n");
1188108eb18Smrg	    fprintf (fp, "DIR %s\n", cwd);
1198108eb18Smrg	    fprintf (fp, "DETACH\n");
1208108eb18Smrg
1218108eb18Smrg	    if (env)
1228108eb18Smrg	    {
1238108eb18Smrg		/*
1248108eb18Smrg		 * The application saved its environment.
1258108eb18Smrg		 */
1268108eb18Smrg
1278108eb18Smrg		for (i = 0; env[i]; i++)
1288108eb18Smrg		{
1298108eb18Smrg		    /*
1308108eb18Smrg		     * rstart requires that any spaces, backslashes, or
1318108eb18Smrg		     * non-printable characters inside of a string be
1328108eb18Smrg		     * represented by octal escape sequences.
1338108eb18Smrg		     */
1348108eb18Smrg
1358108eb18Smrg		    char *temp = format_rstart_env (env[i]);
1368108eb18Smrg		    fprintf (fp, "MISC X %s\n", temp);
1378108eb18Smrg		    if (temp != env[i])
1388108eb18Smrg			XtFree (temp);
1398108eb18Smrg		}
1408108eb18Smrg	    }
1418108eb18Smrg	    else
1428108eb18Smrg	    {
1438108eb18Smrg		/*
1448108eb18Smrg		 * The application did not save its environment.
1458108eb18Smrg		 * The default PATH set up by rstart may not contain
1468108eb18Smrg		 * the program we want to restart.  We play it safe
1478108eb18Smrg		 * and pass xsm's PATH.  This will most likely contain
1488108eb18Smrg		 * the path we need.
1498108eb18Smrg		 */
1508108eb18Smrg
1518108eb18Smrg		char *path = (char *) getenv ("PATH");
1528108eb18Smrg
1538108eb18Smrg		if (path)
1548108eb18Smrg		    fprintf (fp, "MISC X PATH=%s\n", path);
1558108eb18Smrg	    }
1568108eb18Smrg
1578108eb18Smrg	    fprintf (fp, "MISC X %s\n", non_local_display_env);
1588108eb18Smrg	    fprintf (fp, "MISC X %s\n", non_local_session_env);
1598108eb18Smrg
1608108eb18Smrg	    /*
1618108eb18Smrg	     * Pass the authentication data.
1628108eb18Smrg	     * Each transport has auth data for ICE and XSMP.
1638108eb18Smrg	     * Don't pass local auth data.
1648108eb18Smrg	     */
1658108eb18Smrg
1668108eb18Smrg	    for (i = 0; i < numTransports * 2; i++)
1678108eb18Smrg	    {
1688108eb18Smrg		if (Strstr (authDataEntries[i].network_id, "local/"))
1698108eb18Smrg		    continue;
1708108eb18Smrg
1718108eb18Smrg		fprintf (fp, "AUTH ICE %s \"\" %s %s ",
1728108eb18Smrg		    authDataEntries[i].protocol_name,
1738108eb18Smrg		    authDataEntries[i].network_id,
1748108eb18Smrg		    authDataEntries[i].auth_name);
1758108eb18Smrg
1768108eb18Smrg		fprintfhex (fp,
1778108eb18Smrg		    authDataEntries[i].auth_data_length,
1788108eb18Smrg		    authDataEntries[i].auth_data);
1798108eb18Smrg
1808108eb18Smrg		fprintf (fp, "\n");
1818108eb18Smrg	    }
1828108eb18Smrg
1838108eb18Smrg	    /*
1848108eb18Smrg	     * And execute the program
1858108eb18Smrg	     */
1868108eb18Smrg
1878108eb18Smrg	    fprintf (fp, "EXEC %s %s", program, program);
1888108eb18Smrg	    for (i = 1; args[i]; i++)
1898108eb18Smrg		fprintf (fp, " %s", args[i]);
1908108eb18Smrg	    fprintf (fp, "\n\n");
1918108eb18Smrg	    fclose (fp);
1928108eb18Smrg	    break;
1938108eb18Smrg	}
1948108eb18Smrg    }
1958108eb18Smrg}
1968108eb18Smrg
1978108eb18Smrg
1988108eb18Smrg
1998108eb18Smrg/*
2008108eb18Smrg * rstart requires that any spaces/backslashes/non-printable characters
2018108eb18Smrg * inside of a string be represented by octal escape sequences.
2028108eb18Smrg */
2038108eb18Smrg
2048108eb18Smrgstatic char *
2058108eb18Smrgformat_rstart_env(char *str)
2068108eb18Smrg{
2078108eb18Smrg    int escape_count = 0, i;
2088108eb18Smrg    char *temp = str;
2098108eb18Smrg
2108108eb18Smrg    while (*temp != '\0')
2118108eb18Smrg    {
2128108eb18Smrg	if (!isgraph (*temp) || *temp == '\\')
2138108eb18Smrg	    escape_count++;
2148108eb18Smrg	temp++;
2158108eb18Smrg    }
2168108eb18Smrg
2178108eb18Smrg    if (escape_count == 0)
2188108eb18Smrg	return (str);
2198108eb18Smrg    else
2208108eb18Smrg    {
2218108eb18Smrg	int len = strlen (str) + 1 + (escape_count * 3);
2228108eb18Smrg	char *ret = (char *) XtMalloc (len);
2238108eb18Smrg	char *ptr = ret;
2248108eb18Smrg
2258108eb18Smrg	temp = str;
2268108eb18Smrg	while (*temp != '\0')
2278108eb18Smrg	{
2288108eb18Smrg	    if (!isgraph (*temp) || *temp == '\\')
2298108eb18Smrg	    {
2301a650d1eSmrg		char octal[4];
2311a650d1eSmrg		snprintf (octal, sizeof(octal), "%o", *temp);
2328108eb18Smrg		*(ptr++) = '\\';
2338108eb18Smrg		for (i = 0; i < (3 - (int) strlen (octal)); i++)
2348108eb18Smrg		    *(ptr++) = '0';
2358108eb18Smrg		strcpy (ptr, octal);
2368108eb18Smrg		ptr += strlen (octal);
2378108eb18Smrg	    }
2388108eb18Smrg	    else
2398108eb18Smrg		*(ptr++) = *temp;
2408108eb18Smrg
2418108eb18Smrg	    temp++;
2428108eb18Smrg	}
2438108eb18Smrg
2448108eb18Smrg	*ptr = '\0';
2458108eb18Smrg	return (ret);
2468108eb18Smrg    }
2478108eb18Smrg}
248