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