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