xfindproxy.c revision b8f75c19
1/* $Xorg: xfindproxy.c,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $ */ 2 3/* 4Copyright 1996, 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 13in all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of The Open Group shall 24not be used in advertising or otherwise to promote the sale, use or 25other dealings in this Software without prior written authorization 26from The Open Group. 27*/ 28/* $XFree86: xc/programs/xfindproxy/xfindproxy.c,v 1.8tsi Exp $ */ 29 30 31#include <stdio.h> 32#include <X11/Xos.h> 33#include <X11/Xfuncs.h> 34#include <X11/Xmd.h> 35#include <X11/StringDefs.h> 36#include <X11/Intrinsic.h> 37#include <X11/ICE/ICElib.h> 38#include <X11/ICE/ICEmsg.h> 39#include <X11/ICE/ICEproto.h> 40#include <X11/PM/PM.h> 41#include <X11/PM/PMproto.h> 42#include "xfindproxy.h" 43 44#include <stdlib.h> 45#include <ctype.h> 46 47static void PMprocessMessages(IceConn iceConn, IcePointer clientData, 48 int opcode, unsigned long length, Bool swap, 49 IceReplyWaitInfo *replyWait, 50 Bool *replyReadyRet); 51static void _XtProcessIceMsgProc(XtPointer client_data, int *source, 52 XtInputId *id); 53static void _XtIceWatchProc(IceConn ice_conn, IcePointer client_data, 54 Bool opening, IcePointer *watch_data); 55static Status InitWatchProcs(XtAppContext appContext); 56 57int PMopcode; 58 59int PMversionCount = 1; 60IcePoVersionRec PMversions[] = 61 {{PM_MAJOR_VERSION, PM_MINOR_VERSION, PMprocessMessages}}; 62 63XtAppContext appContext; 64 65typedef struct { 66 int status; 67 char *addr; 68 char *error; 69} GetProxyAddrReply; 70 71 72static int 73cvthexkey(char *hexstr, char **ptrp) /* turn hex key string into octets */ 74{ 75 int i; 76 int len = 0; 77 char *retval, *s; 78 unsigned char *us; 79 char c; 80 char savec = '\0'; 81 82 /* count */ 83 for (s = hexstr; *s; s++) { 84 if (!isascii(*s)) return -1; 85 if (isspace(*s)) continue; 86 if (!isxdigit(*s)) return -1; 87 len++; 88 } 89 90 /* if odd then there was an error */ 91 if ((len & 1) == 1) return -1; 92 93 94 /* now we know that the input is good */ 95 len >>= 1; 96 retval = (char *) malloc (len); 97 if (!retval) 98 return -1; 99 100 for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) { 101 c = *hexstr; 102 if (isspace(c)) continue; /* already know it is ascii */ 103 if (isupper(c)) 104 c = tolower(c); 105 if (savec) { 106#define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10))) 107 *us = (unsigned char)((atoh(savec) << 4) + atoh(c)); 108#undef atoh 109 savec = 0; /* ready for next character */ 110 us++; 111 i--; 112 } else { 113 savec = c; 114 } 115 } 116 *ptrp = retval; 117 return len; 118} 119 120int 121main(int argc, char *argv[]) 122{ 123 IceConn iceConn; 124 IceProtocolSetupStatus setupstat; 125 char *vendor = NULL; 126 char *release = NULL; 127 pmGetProxyAddrMsg *pMsg; 128 char *pData; 129 int len, i; 130 IceReplyWaitInfo replyWait; 131 GetProxyAddrReply reply; 132 int majorVersion, minorVersion; 133 Bool gotReply, ioErrorOccured; 134 char errorString[255]; 135 char *serviceName = NULL, *serverAddress = NULL; 136 char *hostAddress = NULL, *startOptions = NULL; 137 char *managerAddress = NULL; 138 Bool haveAuth = 0; 139 char authName[40]; 140 char authData[128]; 141 char *authDataBinary = NULL; 142 int authLen = 0; 143 144 for (i = 1; i < argc; i++) 145 { 146 if (argv[i][0] == '-') 147 { 148 switch (argv[i][1]) 149 { 150 case 'a': /* -auth */ 151 haveAuth = 1; 152 continue; 153 154 case 'm': /* -manager */ 155 if (++i >= argc) goto usage; 156 managerAddress = (char *) XtNewString (argv[i]); 157 continue; 158 159 case 's': /* -server */ 160 if (++i >= argc) goto usage; 161 serverAddress = (char *) XtNewString (argv[i]); 162 continue; 163 164 case 'n': /* -name */ 165 if (++i >= argc) goto usage; 166 serviceName = XtNewString (argv[i]); 167 continue; 168 169 case 'h': /* -host */ 170 if (++i >= argc) goto usage; 171 hostAddress = XtNewString (argv[i]); 172 continue; 173 174 case 'o': /* -options */ 175 if (++i >= argc) goto usage; 176 startOptions = XtNewString (argv[i]); 177 continue; 178 } 179 } 180 181 usage: 182 fprintf (stderr, 183 "usage: xfindproxy -server serverAddr -name serviceName [-manager managerAddr] [-auth] [-host hostAddr] [-options opts]\n-manager can be omitted only if PROXY_MANAGER is in the environment\n"); 184 exit (1); 185 } 186 187 if (serviceName == NULL || serverAddress == NULL) 188 goto usage; 189 190 if (managerAddress == NULL) { 191 managerAddress = getenv("PROXY_MANAGER"); 192 if (managerAddress == NULL) { 193 fprintf (stderr, "Error: -manager option must be specified when PROXY_MANAGER is not in the environment\n"); 194 exit (1); 195 } 196 } 197 198 /* 199 * Register support for PROXY_MANAGEMENT. 200 */ 201 202 if ((PMopcode = IceRegisterForProtocolSetup ( 203 PM_PROTOCOL_NAME, 204 "XC", "1.0", 205 PMversionCount, PMversions, 206 0, /* authcount */ 207 NULL, /* authnames */ 208 NULL, /* authprocs */ 209 NULL /* IceIOErrorProc */ )) < 0) 210 { 211 fprintf (stderr, 212 "Could not register PROXY_MANAGEMENT protocol with ICE"); 213 exit (1); 214 } 215 216 217 appContext = XtCreateApplicationContext (); 218 219 InitWatchProcs (appContext); 220 221 if ((iceConn = IceOpenConnection ( 222 managerAddress, NULL, 0, 0, 256, errorString)) == NULL) 223 { 224 fprintf (stderr, 225 "Could not open ICE connection to proxy manager: %s", errorString); 226 exit (1); 227 } 228 229 setupstat = IceProtocolSetup (iceConn, PMopcode, NULL, 230 False /* mustAuthenticate */, 231 &majorVersion, &minorVersion, 232 &vendor, &release, 256, errorString); 233 234 if (setupstat != IceProtocolSetupSuccess) 235 { 236 IceCloseConnection (iceConn); 237 fprintf (stderr, 238 "Could not initialize proxy management protocol: %s\n", 239 errorString); 240 exit (1); 241 } 242 243 244 /* 245 * If auth data is supplied, read it from stdin. 246 */ 247 248 if (haveAuth) 249 { 250 fgets (authName, sizeof (authName), stdin); 251 fgets (authData, sizeof (authData), stdin); 252 253 for (i = 0; i < strlen (authName); i++) 254 if (authName[i] == '\n') 255 { 256 authName[i] = '\0'; 257 break; 258 } 259 for (i = 0; i < strlen (authData); i++) 260 if (authData[i] == '\n') 261 { 262 authData[i] = '\0'; 263 break; 264 } 265 266 /* 267 * Convert the hex auth data to binary. 268 */ 269 270 authLen = cvthexkey (authData, &authDataBinary); 271 272 if (authLen == -1) 273 { 274 fprintf (stderr, "Could not convert hex auth data to binary\n"); 275 exit (1); 276 } 277 } 278 279 280 /* 281 * Now send the GetProxyAddr request. 282 */ 283 284 len = STRING_BYTES (serviceName) + 285 STRING_BYTES (serverAddress) + 286 STRING_BYTES (hostAddress) + 287 STRING_BYTES (startOptions) + 288 (authLen > 0 ? (STRING_BYTES (authName) + authLen) : 0); 289 290 IceGetHeaderExtra (iceConn, PMopcode, PM_GetProxyAddr, 291 SIZEOF (pmGetProxyAddrMsg), WORD64COUNT (len), 292 pmGetProxyAddrMsg, pMsg, pData); 293 294 pMsg->authLen = authLen; 295 296 STORE_STRING (pData, serviceName); 297 STORE_STRING (pData, serverAddress); 298 STORE_STRING (pData, hostAddress); 299 STORE_STRING (pData, startOptions); 300 if (authLen > 0) 301 { 302 STORE_STRING (pData, authName); 303 memcpy (pData, authDataBinary, authLen); 304 } 305 306 IceFlush (iceConn); 307 308 replyWait.sequence_of_request = IceLastSentSequenceNumber (iceConn); 309 replyWait.major_opcode_of_request = PMopcode; 310 replyWait.minor_opcode_of_request = PM_GetProxyAddr; 311 replyWait.reply = (IcePointer) &reply; 312 313 gotReply = False; 314 ioErrorOccured = False; 315 316 while (!gotReply && !ioErrorOccured) 317 { 318 ioErrorOccured = (IceProcessMessages ( 319 iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); 320 321 if (ioErrorOccured) 322 { 323 fprintf (stderr, "IO error occured\n"); 324 exit (1); 325 } 326 else if (gotReply) 327 { 328 if (reply.status == PM_Success) 329 { 330 fprintf (stdout, "%s\n", reply.addr); 331 exit (0); 332 } 333 else 334 { 335 fprintf (stderr, "Error from proxy manager: %s\n", 336 reply.error); 337 exit (1); 338 } 339 } 340 } 341 /*NOTREACHED*/ 342 exit(0); 343} 344 345 346 347static void 348PMprocessMessages(IceConn iceConn, IcePointer clientData, int opcode, 349 unsigned long length, Bool swap, 350 IceReplyWaitInfo *replyWait, Bool *replyReadyRet) 351{ 352 if (replyWait) 353 *replyReadyRet = False; 354 355 switch (opcode) 356 { 357 case PM_GetProxyAddrReply: 358 359 if (!replyWait || 360 replyWait->minor_opcode_of_request != PM_GetProxyAddr) 361 { 362 _IceReadSkip (iceConn, length << 3); 363 364 _IceErrorBadState (iceConn, PMopcode, 365 PM_GetProxyAddrReply, IceFatalToProtocol); 366 } 367 else 368 { 369 pmGetProxyAddrReplyMsg *pMsg; 370 char *pData, *pStart; 371 GetProxyAddrReply *reply = 372 (GetProxyAddrReply *) (replyWait->reply); 373 374#if 0 /* No-op */ 375 CHECK_AT_LEAST_SIZE (iceConn, PMopcode, opcode, 376 length, SIZEOF (pmGetProxyAddrReplyMsg), IceFatalToProtocol); 377#endif 378 379 IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrReplyMsg), 380 pmGetProxyAddrReplyMsg, pMsg, pStart); 381 382 if (!IceValidIO (iceConn)) 383 { 384 IceDisposeCompleteMessage (iceConn, pStart); 385 return; 386 } 387 388 pData = pStart; 389 390 SKIP_STRING (pData, swap); /* proxy-address */ 391 SKIP_STRING (pData, swap); /* failure-reason */ 392 393 CHECK_COMPLETE_SIZE (iceConn, PMopcode, opcode, 394 length, pData - pStart + SIZEOF (pmGetProxyAddrReplyMsg), 395 pStart, IceFatalToProtocol); 396 397 pData = pStart; 398 399 EXTRACT_STRING (pData, swap, reply->addr); 400 EXTRACT_STRING (pData, swap, reply->error); 401 402 reply->status = pMsg->status; 403 *replyReadyRet = True; 404 405 IceDisposeCompleteMessage (iceConn, pStart); 406 } 407 break; 408 409 default: 410 { 411 _IceErrorBadMinor (iceConn, PMopcode, opcode, IceCanContinue); 412 _IceReadSkip (iceConn, length << 3); 413 break; 414 } 415 } 416} 417 418 419static void 420_XtProcessIceMsgProc(XtPointer client_data, int *source, XtInputId *id) 421{ 422 IceConn ice_conn = (IceConn) client_data; 423 IceProcessMessagesStatus status; 424 425 status = IceProcessMessages (ice_conn, NULL, NULL); 426 427 if (status == IceProcessMessagesIOError) 428 { 429 fprintf (stderr, "IO error occured\n"); 430 exit (1); 431 } 432} 433 434 435static void 436_XtIceWatchProc(IceConn ice_conn, IcePointer client_data, 437 Bool opening, IcePointer *watch_data) 438{ 439 if (opening) 440 { 441 XtAppContext appContext = (XtAppContext) client_data; 442 443 *watch_data = (IcePointer) XtAppAddInput ( 444 appContext, 445 IceConnectionNumber (ice_conn), 446 (XtPointer) XtInputReadMask, 447 _XtProcessIceMsgProc, 448 (XtPointer) ice_conn); 449 } 450 else 451 { 452 XtRemoveInput ((XtInputId) *watch_data); 453 } 454} 455 456 457static Status 458InitWatchProcs(XtAppContext appContext) 459{ 460 return (IceAddConnectionWatch (_XtIceWatchProc, (IcePointer) appContext)); 461} 462