remote.c revision 5977a007
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	    fp = (FILE *) fdopen (pipefd[1], "w");
115
116	    fprintf (fp, "CONTEXT X\n");
117	    fprintf (fp, "DIR %s\n", cwd);
118	    fprintf (fp, "DETACH\n");
119
120	    if (env)
121	    {
122		/*
123		 * The application saved its environment.
124		 */
125
126		for (i = 0; env[i]; i++)
127		{
128		    /*
129		     * rstart requires that any spaces, backslashes, or
130		     * non-printable characters inside of a string be
131		     * represented by octal escape sequences.
132		     */
133
134		    char *temp = format_rstart_env (env[i]);
135		    fprintf (fp, "MISC X %s\n", temp);
136		    if (temp != env[i])
137			XtFree (temp);
138		}
139	    }
140	    else
141	    {
142		/*
143		 * The application did not save its environment.
144		 * The default PATH set up by rstart may not contain
145		 * the program we want to restart.  We play it safe
146		 * and pass xsm's PATH.  This will most likely contain
147		 * the path we need.
148		 */
149
150		char *path = (char *) getenv ("PATH");
151
152		if (path)
153		    fprintf (fp, "MISC X PATH=%s\n", path);
154	    }
155
156	    fprintf (fp, "MISC X %s\n", non_local_display_env);
157	    fprintf (fp, "MISC X %s\n", non_local_session_env);
158
159	    /*
160	     * Pass the authentication data.
161	     * Each transport has auth data for ICE and XSMP.
162	     * Don't pass local auth data.
163	     */
164
165	    for (i = 0; i < numTransports * 2; i++)
166	    {
167		if (Strstr (authDataEntries[i].network_id, "local/"))
168		    continue;
169
170		fprintf (fp, "AUTH ICE %s \"\" %s %s ",
171		    authDataEntries[i].protocol_name,
172		    authDataEntries[i].network_id,
173		    authDataEntries[i].auth_name);
174
175		fprintfhex (fp,
176		    authDataEntries[i].auth_data_length,
177		    authDataEntries[i].auth_data);
178
179		fprintf (fp, "\n");
180	    }
181
182	    /*
183	     * And execute the program
184	     */
185
186	    fprintf (fp, "EXEC %s %s", program, program);
187	    for (i = 1; args[i]; i++)
188		fprintf (fp, " %s", args[i]);
189	    fprintf (fp, "\n\n");
190	    fclose (fp);
191	    break;
192	}
193    }
194}
195
196
197
198/*
199 * rstart requires that any spaces/backslashes/non-printable characters
200 * inside of a string be represented by octal escape sequences.
201 */
202
203static char *
204format_rstart_env(char *str)
205{
206    int escape_count = 0, i;
207    char *temp = str;
208
209    while (*temp != '\0')
210    {
211	if (!isgraph (*temp) || *temp == '\\')
212	    escape_count++;
213	temp++;
214    }
215
216    if (escape_count == 0)
217	return (str);
218    else
219    {
220	int len = strlen (str) + 1 + (escape_count * 3);
221	char *ret = (char *) XtMalloc (len);
222	char *ptr = ret;
223
224	temp = str;
225	while (*temp != '\0')
226	{
227	    if (!isgraph (*temp) || *temp == '\\')
228	    {
229		char octal[4];
230		snprintf (octal, sizeof(octal), "%o", *temp);
231		*(ptr++) = '\\';
232		for (i = 0; i < (3 - (int) strlen (octal)); i++)
233		    *(ptr++) = '0';
234		strcpy (ptr, octal);
235		ptr += strlen (octal);
236	    }
237	    else
238		*(ptr++) = *temp;
239
240	    temp++;
241	}
242
243	*ptr = '\0';
244	return (ret);
245    }
246}
247