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