remote.c revision 2bc08f26
1/* $Xorg: remote.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $ */
2/******************************************************************************
3
4Copyright 1993, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25******************************************************************************/
26/* $XFree86: xc/programs/xsm/remote.c,v 1.4 2001/01/17 23:46:30 dawes Exp $ */
27
28/*
29 * We use the rstart protocol to restart clients on remote machines.
30 */
31
32#include "xsm.h"
33#include "log.h"
34
35static char 		*format_rstart_env(char *str);
36
37
38void
39remote_start(const char *restart_protocol, const char *restart_machine,
40	     const char *program, char **args, const char *cwd,
41	     char **env, const char *non_local_display_env,
42	     const char *non_local_session_env)
43{
44    FILE *fp;
45    int	 pipefd[2];
46    char msg[256];
47    int  i;
48
49    if (strcmp (restart_protocol, "rstart-rsh") != 0)
50    {
51	if (verbose)
52	    printf ("Only rstart-rsh remote execution protocol supported.\n");
53	return;
54    }
55
56    if (!restart_machine)
57    {
58	if (verbose)
59	    printf ("Bad remote machine specified for remote execute.\n");
60	return;
61    }
62
63    if (verbose)
64	printf ("Attempting to restart remote client on %s\n",
65	    restart_machine);
66
67    if (pipe (pipefd) < 0)
68    {
69	snprintf (msg, sizeof(msg),
70		  "%s: pipe() error during remote start of %s",
71		  Argv[0], program);
72	add_log_text (msg);
73	perror (msg);
74    }
75    else
76    {
77	switch(fork())
78	{
79	case -1:
80
81	    snprintf (msg, sizeof(msg),
82		      "%s: fork() error during remote start of %s",
83		      Argv[0], program);
84	    add_log_text (msg);
85	    perror (msg);
86	    break;
87
88	case 0:		/* kid */
89
90	    close (pipefd[1]);
91	    close (0);
92	    dup (pipefd[0]);
93	    close (pipefd[0]);
94
95	    execlp (RSHCMD, restart_machine, "rstartd", (char *) 0);
96
97	    snprintf (msg, sizeof(msg),
98		      "%s: execlp() of rstartd failed for remote start of %s",
99		      Argv[0], program);
100	    perror (msg);
101	    /*
102	     * TODO : We would like to send this log information to the
103	     * log window in the parent.  This would require using the
104	     * pipe between the parent and child.  The child would
105	     * set close-on-exec.  If the exec succeeds, the pipe will
106	     * be closed.  If it fails, the child can write a message
107	     * to the parent.
108	     */
109	    _exit(255);
110
111	default:		/* parent */
112
113	    close (pipefd[0]);
114	    fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
115	    fp = fdopen (pipefd[1], "w");
116
117	    fprintf (fp, "CONTEXT X\n");
118	    fprintf (fp, "DIR %s\n", cwd);
119	    fprintf (fp, "DETACH\n");
120
121	    if (env)
122	    {
123		/*
124		 * The application saved its environment.
125		 */
126
127		for (i = 0; env[i]; i++)
128		{
129		    /*
130		     * rstart requires that any spaces, backslashes, or
131		     * non-printable characters inside of a string be
132		     * represented by octal escape sequences.
133		     */
134
135		    char *temp = format_rstart_env (env[i]);
136		    fprintf (fp, "MISC X %s\n", temp);
137		    if (temp != env[i])
138			XtFree (temp);
139		}
140	    }
141	    else
142	    {
143		/*
144		 * The application did not save its environment.
145		 * The default PATH set up by rstart may not contain
146		 * the program we want to restart.  We play it safe
147		 * and pass xsm's PATH.  This will most likely contain
148		 * the path we need.
149		 */
150
151		char *path = (char *) getenv ("PATH");
152
153		if (path)
154		    fprintf (fp, "MISC X PATH=%s\n", path);
155	    }
156
157	    fprintf (fp, "MISC X %s\n", non_local_display_env);
158	    fprintf (fp, "MISC X %s\n", non_local_session_env);
159
160	    /*
161	     * Pass the authentication data.
162	     * Each transport has auth data for ICE and XSMP.
163	     * Don't pass local auth data.
164	     */
165
166	    for (i = 0; i < numTransports * 2; i++)
167	    {
168		if (Strstr (authDataEntries[i].network_id, "local/"))
169		    continue;
170
171		fprintf (fp, "AUTH ICE %s \"\" %s %s ",
172		    authDataEntries[i].protocol_name,
173		    authDataEntries[i].network_id,
174		    authDataEntries[i].auth_name);
175
176		fprintfhex (fp,
177		    authDataEntries[i].auth_data_length,
178		    authDataEntries[i].auth_data);
179
180		fprintf (fp, "\n");
181	    }
182
183	    /*
184	     * And execute the program
185	     */
186
187	    fprintf (fp, "EXEC %s %s", program, program);
188	    for (i = 1; args[i]; i++)
189		fprintf (fp, " %s", args[i]);
190	    fprintf (fp, "\n\n");
191	    fclose (fp);
192	    break;
193	}
194    }
195}
196
197
198
199/*
200 * rstart requires that any spaces/backslashes/non-printable characters
201 * inside of a string be represented by octal escape sequences.
202 */
203
204static char *
205format_rstart_env(char *str)
206{
207    int escape_count = 0, i;
208    char *temp = str;
209
210    while (*temp != '\0')
211    {
212	if (!isgraph (*temp) || *temp == '\\')
213	    escape_count++;
214	temp++;
215    }
216
217    if (escape_count == 0)
218	return (str);
219    else
220    {
221	int len = strlen (str) + 1 + (escape_count * 3);
222	char *ret = (char *) XtMalloc (len);
223	char *ptr = ret;
224
225	temp = str;
226	while (*temp != '\0')
227	{
228	    if (!isgraph (*temp) || *temp == '\\')
229	    {
230		char octal[4];
231		snprintf (octal, sizeof(octal), "%o", *temp);
232		*(ptr++) = '\\';
233		for (i = 0; i < (3 - (int) strlen (octal)); i++)
234		    *(ptr++) = '0';
235		strcpy (ptr, octal);
236		ptr += strlen (octal);
237	    }
238	    else
239		*(ptr++) = *temp;
240
241	    temp++;
242	}
243
244	*ptr = '\0';
245	return (ret);
246    }
247}
248