~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/lib/dps/csconndi.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * csconndi.c -- low level connection maker for CSDPS
 
3
 * 
 
4
 * (c) Copyright 1990-1994 Adobe Systems Incorporated.
 
5
 * All rights reserved.
 
6
 * 
 
7
 * Permission to use, copy, modify, distribute, and sublicense this software
 
8
 * and its documentation for any purpose and without fee is hereby granted,
 
9
 * provided that the above copyright notices appear in all copies and that
 
10
 * both those copyright notices and this permission notice appear in
 
11
 * supporting documentation and that the name of Adobe Systems Incorporated
 
12
 * not be used in advertising or publicity pertaining to distribution of the
 
13
 * software without specific, written prior permission.  No trademark license
 
14
 * to use the Adobe trademarks is hereby granted.  If the Adobe trademark
 
15
 * "Display PostScript"(tm) is used to describe this software, its
 
16
 * functionality or for any other purpose, such use shall be limited to a
 
17
 * statement that this software works in conjunction with the Display
 
18
 * PostScript system.  Proper trademark attribution to reflect Adobe's
 
19
 * ownership of the trademark shall be given whenever any such reference to
 
20
 * the Display PostScript system is made.
 
21
 * 
 
22
 * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
 
23
 * ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
 
24
 * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
26
 * NON- INFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO EVENT SHALL ADOBE BE LIABLE
 
27
 * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
 
28
 * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
 
29
 * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
 
30
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  ADOBE WILL NOT
 
31
 * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
 
32
 * 
 
33
 * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
 
34
 * Incorporated which may be registered in certain jurisdictions
 
35
 * 
 
36
 * Portions Copyright 1989 Massachusetts Institute of Technology
 
37
 *
 
38
 * Permission to use, copy, modify, distribute, and sell this software and its
 
39
 * documentation for any purpose is hereby granted without fee, provided that
 
40
 * the above copyright notice appear in all copies and that both that
 
41
 * copyright notice and this permission notice appear in supporting
 
42
 * documentation, and that the name of M.I.T. not be used in advertising or
 
43
 * publicity pertaining to distribution of the software without specific,
 
44
 * written prior permission.  M.I.T. makes no representations about the
 
45
 * suitability of this software for any purpose.  It is provided "as is"
 
46
 * without express or implied warranty.
 
47
 *  
 
48
 * Author:  Adobe Systems Incorporated and MIT X Consortium
 
49
 */
 
50
/* $XFree86: xc/lib/dps/csconndi.c,v 1.11 2002/01/07 19:55:04 dawes Exp $ */
 
51
 
 
52
#if defined(sun) && !defined(SVR4)
 
53
#define memmove(t,f,c) bcopy(f,t,c)
 
54
#endif
 
55
 
 
56
#define NEED_EVENTS
 
57
 
 
58
#include <stdio.h>
 
59
#include <stdlib.h>
 
60
#include <X11/Xos.h>
 
61
/* Include this first so that Xasync.h, included from Xlibint.h, can find
 
62
   the definition of NOFILE */
 
63
#include <sys/param.h>
 
64
#include <X11/Xlibint.h>
 
65
#include "Xlibnet.h"            /* New for R5, delete for R4 */
 
66
#include <arpa/inet.h>
 
67
 
 
68
#ifndef hpux    /* HP doesn't include Xauth.h :-( */
 
69
#include <X11/Xauth.h>
 
70
#else
 
71
#define FamilyLocal (256)
 
72
#endif
 
73
 
 
74
#include <ctype.h>
 
75
#ifdef DNETCONN
 
76
#include <netdnet/dn.h>
 
77
#include <netdnet/dnetdb.h>
 
78
#endif
 
79
 
 
80
#include <netdb.h>
 
81
 
 
82
#include "DPSCAPproto.h"
 
83
#include "cslibint.h"
 
84
#include "dpsassert.h"
 
85
 
 
86
#if defined(hpux) || defined(AIXV3)
 
87
#define SELECT_TYPE int *
 
88
#else
 
89
#define SELECT_TYPE fd_set *
 
90
#endif
 
91
 
 
92
#ifndef _XANYSET
 
93
#define _XANYSET N_XANYSET
 
94
#endif /* _XANYSET */
 
95
 
 
96
#ifndef X_CONNECTION_RETRIES            /* number retries on ECONNREFUSED */
 
97
#define X_CONNECTION_RETRIES 5
 
98
#endif
 
99
 
 
100
#define CONN_PARAMS char *, int , int , int *, int *, char **
 
101
 
 
102
#ifdef DNETCONN
 
103
static int MakeDECnetConnection(CONN_PARAMS);
 
104
#endif
 
105
#ifdef UNIXCONN
 
106
static int MakeUNIXSocketConnection(CONN_PARAMS);
 
107
#endif
 
108
#ifdef TCPCONN
 
109
static int MakeTCPConnection(CONN_PARAMS);
 
110
#endif
 
111
#ifdef STREAMSCONN
 
112
extern int _XMakeStreamsConnection(CONN_PARAMS);
 
113
#endif
 
114
 
 
115
/* This global controls the size of the output socket buffer.  Zero
 
116
   means to use the system default size. */
 
117
int gNXSndBufSize = 0;
 
118
 
 
119
static char *copystring (char *src, int len)
 
120
{
 
121
    char *dst = Xmalloc (len + 1);
 
122
 
 
123
    if (dst) {
 
124
        strncpy (dst, src, len);
 
125
        dst[len] = '\0';
 
126
    }
 
127
 
 
128
    return dst;
 
129
}
 
130
 
 
131
 
 
132
/* 
 
133
 * Attempts to connect to agent, given name. Returns file descriptor
 
134
 * (network socket) or -1 if connection fails.  Names may be of the
 
135
 * following format:
 
136
 *
 
137
 *     [hostname] : [:] agentnumber
 
138
 *
 
139
 * The second colon indicates a DECnet style name.  No hostname is interpretted
 
140
 * as the most efficient local connection to a server on the same machine.  
 
141
 * This is usually:
 
142
 *
 
143
 *     o  shared memory
 
144
 *     o  local stream
 
145
 *     o  UNIX domain socket
 
146
 *     o  TCP to local host
 
147
 */
 
148
 
 
149
int 
 
150
DPSCAPConnect(
 
151
    char *display_name,
 
152
    char **fullnamep,                   /* RETURN */
 
153
    int *dpynump,                       /* RETURN */
 
154
    int *familyp,                       /* RETURN */
 
155
    int *saddrlenp,                     /* RETURN */
 
156
    char **saddrp)                      /* RETURN, freed by caller */
 
157
{
 
158
    char *lastp, *p;                    /* char pointers */
 
159
    char *phostname = NULL;             /* start of host of display */
 
160
    char *pdpynum = NULL;               /* start of dpynum of display */
 
161
    char *pscrnum = NULL;               /* start of screen of display */
 
162
    Bool dnet = False;                  /* if true, then DECnet format */
 
163
    int iagent;                         /* required display number */
 
164
    int (*connfunc)(CONN_PARAMS);       /* method to create connection */
 
165
    int fd = -1;                        /* file descriptor to return */
 
166
    int len;                            /* length tmp variable */
 
167
 
 
168
    p = display_name;
 
169
 
 
170
    *saddrlenp = 0;                     /* set so that we can clear later */
 
171
    *saddrp = NULL;
 
172
 
 
173
    /*
 
174
     * Step 1, find the hostname.  This is delimited by the required 
 
175
     * first colon.
 
176
     */
 
177
    for (lastp = p; *p && *p != ':'; p++) ;
 
178
    if (!*p) return -1;         /* must have a colon */
 
179
 
 
180
    if (p != lastp) {           /* no hostname given */
 
181
        phostname = copystring (lastp, p - lastp);
 
182
        if (!phostname) goto bad;       /* no memory */
 
183
    }
 
184
 
 
185
 
 
186
    /*
 
187
     * Step 2, see if this is a DECnet address by looking for the optional
 
188
     * second colon.
 
189
     */
 
190
    if (p[1] == ':') {                  /* then DECnet format */
 
191
        dnet = True;
 
192
        p++;
 
193
    }
 
194
 
 
195
    /*
 
196
     * see if we're allowed to have a DECnet address
 
197
     */
 
198
#ifndef DNETCONN
 
199
    if (dnet) goto bad;
 
200
#endif
 
201
 
 
202
    
 
203
    /*
 
204
     * Step 3, find the port number.  This field is required.
 
205
     * Zero is acceptable as a port number, meaning use the default.
 
206
     */
 
207
 
 
208
    for (lastp = ++p; *p && isascii(*p) && isdigit(*p); p++) ;
 
209
    if ((p == lastp) ||                 /* required field */
 
210
        (*p != '\0' && *p != '.') ||    /* invalid non-digit terminator */
 
211
        !(pdpynum = copystring (lastp, p - lastp)))  /* no memory */
 
212
      goto bad;
 
213
    iagent = atoi (pdpynum);
 
214
 
 
215
 
 
216
    /*
 
217
     * At this point, we know the following information:
 
218
     *
 
219
     *     phostname                hostname string or NULL
 
220
     *     iagent                   agent port number
 
221
     *     dnet                     DECnet boolean
 
222
     * 
 
223
     * We can now decide which transport to use based on the ConnectionFlags
 
224
     * build parameter the hostname string.  If phostname is NULL or equals
 
225
     * the string "local", then choose the best transport.  If phostname
 
226
     * is "unix", then choose BSD UNIX domain sockets (if configured).
 
227
     *
 
228
     * First, choose default transports:  DECnet else (TCP or STREAMS)
 
229
     */
 
230
 
 
231
 
 
232
#ifdef DNETCONN
 
233
    if (dnet)
 
234
      connfunc = MakeDECnetConnection;
 
235
    else
 
236
#endif
 
237
#ifdef TCPCONN
 
238
      connfunc = MakeTCPConnection;
 
239
#else
 
240
#ifdef STREAMSCONN
 
241
      connfunc = _XMakeStreamsConnection;
 
242
#else
 
243
      connfunc = NULL;
 
244
#endif
 
245
#endif
 
246
 
 
247
#ifdef UNIXCONN
 
248
    /*
 
249
     * Now that the defaults have been established, see if we have any 
 
250
     * special names that we have to override:
 
251
     *
 
252
     *     :N         =>     if UNIXCONN then unix-domain-socket
 
253
     *     ::N        =>     if UNIXCONN then unix-domain-socket
 
254
     *     unix:N     =>     if UNIXCONN then unix-domain-socket
 
255
     *
 
256
     * Note that if UNIXCONN isn't defined, then we can use the default
 
257
     * transport connection function set above.
 
258
     */
 
259
    if (!phostname) {
 
260
        connfunc = MakeUNIXSocketConnection;
 
261
    }
 
262
    else if (strcmp (phostname, "unix") == 0) {
 
263
        connfunc = MakeUNIXSocketConnection;
 
264
    }
 
265
#endif
 
266
    if (!connfunc)
 
267
        goto bad;
 
268
 
 
269
 
 
270
#ifdef UNIXCONN
 
271
#define LOCALCONNECTION (!phostname || connfunc == MakeUNIXSocketConnection)
 
272
#else
 
273
#define LOCALCONNECTION (!phostname)
 
274
#endif
 
275
 
 
276
    if (LOCALCONNECTION) {
 
277
        /*
 
278
         * Get the auth info for local hosts so that it doesn't have to be
 
279
         * repeated everywhere; the particular values in these fields are
 
280
         * not part of the protocol.
 
281
         */
 
282
        char hostnamebuf[256];
 
283
        int len = N_XGetHostname (hostnamebuf, sizeof hostnamebuf);
 
284
 
 
285
        *familyp = FamilyLocal;
 
286
        if (len > 0) {
 
287
            *saddrp = Xmalloc (len + 1);
 
288
            if (*saddrp) {
 
289
                strcpy (*saddrp, hostnamebuf);
 
290
                *saddrlenp = len;
 
291
            } else {
 
292
                *saddrlenp = 0;
 
293
            }
 
294
        }
 
295
    }
 
296
#undef LOCALCONNECTION
 
297
 
 
298
#ifndef ultrix
 
299
    /* Ultrix has a nasty bug in getservbyname(); if the name passed to
 
300
       it is not in the services list it seg faults!  *sigh*  So, we
 
301
       don't ever look in the services info for ultrix... */
 
302
    if (iagent == 0) {          /* find service default, if one's defined */
 
303
      struct servent *serventInfo;
 
304
      
 
305
      if ((serventInfo = getservbyname(DPS_NX_SERV_NAME,
 
306
                                       (char *) NULL)) != NULL) {
 
307
        if (strcmp("tcp", serventInfo->s_proto) != 0) {
 
308
          DPSWarnProc(NULL, "Services database specifies a protocol other than tcp.  Using default port.\n");
 
309
        } else                  /* extract the port number */
 
310
          iagent = ntohs(serventInfo->s_port);
 
311
      }
 
312
    }
 
313
#endif /* ultrix */    
 
314
    /*
 
315
     * Make the connection, also need to get the auth address info for
 
316
     * non-local connections.  Do retries in case server host has hit its
 
317
     * backlog (which, unfortunately, isn't distinguishable from there not
 
318
     * being a server listening at all, which is why we have to not retry
 
319
     * too many times).
 
320
     */
 
321
    if ((fd = (*connfunc) (phostname, iagent, X_CONNECTION_RETRIES,
 
322
                           familyp, saddrlenp, saddrp)) < 0)
 
323
      goto bad;
 
324
 
 
325
 
 
326
    /*
 
327
     * Set the connection non-blocking since we use select() to block; also
 
328
     * set close-on-exec so that programs that fork() doesn't get confused.
 
329
     */
 
330
#ifdef FIOSNBIO
 
331
    {
 
332
        int arg = 1;
 
333
        ioctl (fd, FIOSNBIO, &arg);
 
334
    }
 
335
#else
 
336
#if defined(O_NONBLOCK)
 
337
    (void) fcntl (fd, F_SETFL, O_NONBLOCK);
 
338
#elif defined(FNDELAY)
 
339
    (void) fcntl (fd, F_SETFL, FNDELAY);
 
340
#else
 
341
    (void) fcntl (fd, F_SETFL, O_NDELAY);
 
342
#endif /* O_NONBLOCK/FNDELAY */
 
343
#endif /* FIOSNBIO */
 
344
 
 
345
    (void) fcntl (fd, F_SETFD, 1);
 
346
 
 
347
 
 
348
    /*
 
349
     * Build the expanded display name:
 
350
     *
 
351
     *     [host] : [:] agent \0
 
352
     */
 
353
    len = ((phostname ? strlen(phostname) : 0) + 1 + (dnet ? 1 : 0) +
 
354
           strlen(pdpynum) + 1);
 
355
    *fullnamep = (char *) Xmalloc (len);
 
356
    if (!*fullnamep) goto bad;
 
357
 
 
358
    sprintf (*fullnamep, "%s%s%d",
 
359
             (phostname ? phostname : ""), (dnet ? "::" : ":"),
 
360
             iagent);
 
361
 
 
362
    *dpynump = iagent;
 
363
    if (phostname) Xfree (phostname);
 
364
    if (pdpynum) Xfree (pdpynum);
 
365
    if (pscrnum) Xfree (pscrnum);
 
366
    return fd;
 
367
 
 
368
 
 
369
    /*
 
370
     * error return; make sure everything is cleaned up.
 
371
     */
 
372
  bad:
 
373
    if (fd >= 0) (void) close (fd);
 
374
    if (*saddrp) {
 
375
        Xfree (*saddrp);
 
376
        *saddrp = NULL;
 
377
    }
 
378
    *saddrlenp = 0;
 
379
    if (phostname) Xfree (phostname);
 
380
    if (pdpynum) Xfree (pdpynum);
 
381
    return -1;
 
382
 
 
383
}
 
384
 
 
385
 
 
386
/*****************************************************************************
 
387
 *                                                                           *
 
388
 *                         Make Connection Routines                          *
 
389
 *                                                                           *
 
390
 *****************************************************************************/
 
391
 
 
392
#ifdef DNETCONN                         /* stupid makedepend */
 
393
#define NEED_BSDISH
 
394
#endif
 
395
#ifdef UNIXCONN
 
396
#define NEED_BSDISH
 
397
#endif
 
398
#ifdef TCPCONN
 
399
#define NEED_BSDISH
 
400
#endif
 
401
 
 
402
#ifdef NEED_BSDISH                      /* makedepend can't handle #if */
 
403
/*
 
404
 * 4.2bsd-based systems
 
405
 */
 
406
#include <sys/socket.h>
 
407
 
 
408
#ifndef hpux
 
409
#ifdef apollo                   /* nest if(n)defs because makedepend is broken */
 
410
#ifndef NO_TCP_H
 
411
#include <netinet/tcp.h>
 
412
#endif /* NO_TCP_H */
 
413
#else  /* apollo */
 
414
#include <netinet/tcp.h>
 
415
#endif /* apollo */
 
416
#endif
 
417
#endif /* NEED_BSDISH */
 
418
 
 
419
 
 
420
#ifdef DNETCONN
 
421
static int MakeDECnetConnection (phostname, iagent, retries,
 
422
                                 familyp, saddrlenp, saddrp)
 
423
    char *phostname;
 
424
    int iagent;
 
425
    int retries;
 
426
    int *familyp;                       /* RETURN */
 
427
    int *saddrlenp;                     /* RETURN */
 
428
    char **saddrp;                      /* RETURN */
 
429
{
 
430
    int fd;
 
431
    char objname[20];
 
432
    extern int dnet_conn();
 
433
    struct dn_naddr *dnaddrp, dnaddr;
 
434
    struct nodeent *np;
 
435
 
 
436
    if (!phostname) phostname = "0";
 
437
 
 
438
    /*
 
439
     * build the target object name.
 
440
     */
 
441
    sprintf (objname, "DPS$EXECUTIVE_%d", iagent);
 
442
 
 
443
    /*
 
444
     * Attempt to open the DECnet connection, return -1 if fails; ought to
 
445
     * do some retries here....
 
446
     */
 
447
    if ((fd = dnet_conn (phostname, objname, SOCK_STREAM, 0, 0, 0, 0)) < 0) {
 
448
        return -1;
 
449
    }
 
450
 
 
451
    *familyp = FamilyDECnet;
 
452
    if (dnaddrp = dnet_addr (phostname)) {  /* stolen from xhost */
 
453
        dnaddr = *dnaddrp;
 
454
    } else {
 
455
        if ((np = getnodebyname (phostname)) == NULL) {
 
456
            (void) close (fd);
 
457
            return -1;
 
458
        }
 
459
        dnaddr.a_len = np->n_length;
 
460
        memmove(dnaddr.a_addr, np->n_addr, np->n_length);
 
461
    }
 
462
 
 
463
    *saddrlenp = sizeof (struct dn_naddr);
 
464
    *saddrp = Xmalloc (*saddrlenp);
 
465
    if (!*saddrp) {
 
466
        (void) close (fd);
 
467
        return -1;
 
468
    }
 
469
    memmove (*saddrp, (char *)&dnaddr, *saddrlenp);
 
470
    return fd;
 
471
}
 
472
#endif /* DNETCONN */
 
473
 
 
474
 
 
475
#ifdef UNIXCONN
 
476
 
 
477
#ifndef X_NO_SYS_UN
 
478
#include <sys/un.h>
 
479
#endif
 
480
 
 
481
#ifndef CSDPS_UNIX_PATH
 
482
#ifdef hpux
 
483
#define CSDPS_UNIX_DIR      "/usr/spool/sockets/DPSNX"
 
484
#define CSDPS_UNIX_PATH     "/usr/spool/sockets/DPSNX/"
 
485
#else
 
486
#define CSDPS_UNIX_DIR      "/tmp/.DPSNX-unix"
 
487
#define CSDPS_UNIX_PATH     "/tmp/.DPSNX-unix/AGENT"
 
488
#endif
 
489
#endif
 
490
 
 
491
static int MakeUNIXSocketConnection (
 
492
    char *phostname,
 
493
    int iagent,
 
494
    int retries,
 
495
    int *familyp,                       /* RETURN */
 
496
    int *saddrlenp,                     /* RETURN */
 
497
    char **saddrp)                      /* RETURN */
 
498
{
 
499
    struct sockaddr_un unaddr;          /* UNIX socket data block */
 
500
    struct sockaddr *addr;              /* generic socket pointer */
 
501
    int addrlen;                        /* length of addr */
 
502
    int fd;                             /* socket file descriptor */
 
503
    int port = (iagent == 0) ? CSDPSPORT : iagent;
 
504
    int ret;
 
505
 
 
506
    unaddr.sun_family = AF_UNIX;
 
507
    sprintf (unaddr.sun_path, "%s_%d", CSDPS_UNIX_PATH, port);
 
508
 
 
509
    addr = (struct sockaddr *) &unaddr;
 
510
    addrlen = strlen(unaddr.sun_path) + sizeof(unaddr.sun_family);
 
511
 
 
512
    /*
 
513
     * Open the network connection.
 
514
     */
 
515
    do {
 
516
        if ((fd = socket ((int) addr->sa_family, SOCK_STREAM, 0)) < 0) {
 
517
            return -1;
 
518
        }
 
519
 
 
520
        if (gNXSndBufSize > 0)
 
521
            ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &gNXSndBufSize, sizeof(gNXSndBufSize));
 
522
 
 
523
        if (connect (fd, addr, addrlen) < 0) {
 
524
            int olderrno = errno;
 
525
            (void) close (fd);
 
526
            if (olderrno != ENOENT || retries <= 0) {
 
527
                errno = olderrno;
 
528
                return -1;
 
529
            }
 
530
            sleep (1);
 
531
        } else {
 
532
            break;
 
533
        }
 
534
    } while (retries-- > 0);
 
535
 
 
536
    /*
 
537
     * Don't need to get auth info since we're local
 
538
     */
 
539
    return fd;
 
540
}
 
541
#endif /* UNIXCONN */
 
542
 
 
543
 
 
544
#ifdef TCPCONN
 
545
static int MakeTCPConnection (
 
546
    char *phostname,
 
547
    int iagent,
 
548
    int retries,
 
549
    int *familyp,                       /* RETURN */
 
550
    int *saddrlenp,                     /* RETURN */
 
551
    char **saddrp)                      /* RETURN */
 
552
{
 
553
    char hostnamebuf[256];              /* tmp space */
 
554
    unsigned long hostinetaddr;         /* result of inet_addr of arpa addr */
 
555
    struct sockaddr_in inaddr;          /* IP socket */
 
556
    struct sockaddr *addr;              /* generic socket pointer */
 
557
    int addrlen;                        /* length of addr */
 
558
    struct hostent *hp;                 /* entry in hosts table */
 
559
    char *cp;                           /* character pointer iterator */
 
560
    int fd;                             /* file descriptor to return */
 
561
    int len;                            /* length tmp variable */
 
562
 
 
563
#define INVALID_INETADDR ((unsigned long) -1)
 
564
 
 
565
    if (!phostname) {
 
566
        hostnamebuf[0] = '\0';
 
567
        (void) N_XGetHostname (hostnamebuf, sizeof hostnamebuf);
 
568
        phostname = hostnamebuf;
 
569
    }
 
570
 
 
571
    /*
 
572
     * if numeric host name then try to parse it as such; do the number
 
573
     * first because some systems return garbage instead of INVALID_INETADDR
 
574
     */
 
575
    if (isascii(phostname[0]) && isdigit(phostname[0])) {
 
576
        hostinetaddr = inet_addr (phostname);
 
577
    } else {
 
578
        hostinetaddr = INVALID_INETADDR;
 
579
    }
 
580
 
 
581
    /*
 
582
     * try numeric
 
583
     */
 
584
    if (hostinetaddr == INVALID_INETADDR) {
 
585
        if ((hp = gethostbyname(phostname)) == NULL) {
 
586
            /* No such host! */
 
587
            return -1;
 
588
        }
 
589
        if (hp->h_addrtype != AF_INET) {  /* is IP host? */
 
590
            /* Not an Internet host! */
 
591
            return -1;
 
592
        }
 
593
 
 
594
        /* Set up the socket data. */
 
595
        inaddr.sin_family = hp->h_addrtype;
 
596
#if defined(CRAY) && defined(OLDTCP)
 
597
        /* Only Cray UNICOS3 and UNICOS4 will define this */
 
598
        {
 
599
            long t;
 
600
            memmove ((char *)&t, (char *)hp->h_addr, sizeof(t));
 
601
            inaddr.sin_addr = t;
 
602
        }
 
603
#else
 
604
        memmove ((char *)&inaddr.sin_addr, (char *)hp->h_addr, 
 
605
               sizeof(inaddr.sin_addr));
 
606
#endif /* CRAY and OLDTCP */
 
607
    } else {
 
608
#if defined(CRAY) && defined(OLDTCP)
 
609
        /* Only Cray UNICOS3 and UNICOS4 will define this */
 
610
        inaddr.sin_addr = hostinetaddr;
 
611
#else
 
612
        inaddr.sin_addr.s_addr = hostinetaddr;
 
613
#endif /* CRAY and OLDTCP */
 
614
        inaddr.sin_family = AF_INET;
 
615
    }
 
616
 
 
617
    addr = (struct sockaddr *) &inaddr;
 
618
    addrlen = sizeof (struct sockaddr_in);
 
619
    inaddr.sin_port = (iagent == 0) ? CSDPSPORT : iagent;
 
620
    inaddr.sin_port = htons (inaddr.sin_port);  /* may be funky macro */
 
621
 
 
622
 
 
623
    /*
 
624
     * Open the network connection.
 
625
     */
 
626
    do {
 
627
        if ((fd = socket ((int) addr->sa_family, SOCK_STREAM, 0)) < 0) {
 
628
            return -1;
 
629
        }
 
630
 
 
631
        /*
 
632
         * turn off TCP coalescence
 
633
         */
 
634
#ifdef TCP_NODELAY
 
635
        {
 
636
            int tmp = 1;
 
637
            setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof (int));
 
638
        }
 
639
#endif
 
640
        if (gNXSndBufSize > 0)
 
641
            len = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &gNXSndBufSize, sizeof(gNXSndBufSize));
 
642
 
 
643
        /*
 
644
         * connect to the socket; if there is no X server or if the backlog has
 
645
         * been reached, then ECONNREFUSED will be returned.
 
646
         */
 
647
        if (connect (fd, addr, addrlen) < 0) {
 
648
            int olderrno = errno;
 
649
            (void) close (fd);
 
650
            if (olderrno != ECONNREFUSED || retries <= 0) {
 
651
                errno = olderrno;
 
652
                return -1;
 
653
            }
 
654
            sleep (1);
 
655
        } else {
 
656
            break;
 
657
        }
 
658
    } while (retries-- > 0);
 
659
 
 
660
 
 
661
    /*
 
662
     * Success!  So, save the auth information
 
663
     */
 
664
#ifdef CRAY
 
665
#ifdef OLDTCP
 
666
    len = sizeof(inaddr.sin_addr);
 
667
#else
 
668
    len = SIZEOF_in_addr;
 
669
#endif /* OLDTCP */
 
670
    cp = (char *) &inaddr.sin_addr;
 
671
#else /* else not CRAY */
 
672
    len = sizeof(inaddr.sin_addr.s_addr);
 
673
    cp = (char *) &inaddr.sin_addr.s_addr;
 
674
#endif /* CRAY */
 
675
 
 
676
    /*
 
677
     * We are special casing the BSD hack localhost address
 
678
     * 127.0.0.1, since this address shouldn't be copied to
 
679
     * other machines.  So, we simply omit generating the auth info
 
680
     * since we set it to the local machine before calling this routine!
 
681
     */
 
682
    if (!((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
 
683
          (cp[2] == 0) && (cp[3] == 1))) {
 
684
        *saddrp = Xmalloc (len);
 
685
        if (*saddrp) {
 
686
            *saddrlenp = len;
 
687
            memmove (*saddrp, cp, len);
 
688
            *familyp = FamilyInternet;
 
689
        } else {
 
690
            *saddrlenp = 0;
 
691
        }
 
692
    }
 
693
 
 
694
    return fd;
 
695
}
 
696
#undef INVALID_INETADDR
 
697
#endif /* TCPCONN */
 
698
 
 
699
 
 
700
/*****************************************************************************
 
701
 *                                                                           *
 
702
 *                        Connection Utility Routines                        *
 
703
 *                                                                           *
 
704
 *****************************************************************************/
 
705
 
 
706
/* 
 
707
 * Disconnect from server.
 
708
 */
 
709
 
 
710
int N_XDisconnectDisplay (int server)
 
711
{
 
712
    (void) close(server);
 
713
    return 0;
 
714
}
 
715
 
 
716
 
 
717
#include <stddef.h>
 
718
/*
 
719
 * This is an OS dependent routine which:
 
720
 * 1) returns as soon as the connection can be written on....
 
721
 * 2) if the connection can be read, must enqueue events and handle errors,
 
722
 * until the connection is writable.
 
723
 */
 
724
void N_XWaitForWritable(Display *dpy)
 
725
{
 
726
    unsigned long r_mask[MSKCNT];
 
727
    unsigned long w_mask[MSKCNT];
 
728
    int nfound;
 
729
 
 
730
    CLEARBITS(r_mask);
 
731
    CLEARBITS(w_mask);
 
732
 
 
733
    while (1) {
 
734
        BITSET(r_mask, dpy->fd);
 
735
        BITSET(w_mask, dpy->fd);
 
736
 
 
737
        do {
 
738
            nfound = select (dpy->fd + 1, (SELECT_TYPE) r_mask,
 
739
                             (SELECT_TYPE) w_mask, (SELECT_TYPE) NULL,
 
740
                             (struct timeval *) NULL);
 
741
            if (nfound < 0 && errno != EINTR)
 
742
                _XIOError(dpy);
 
743
        } while (nfound <= 0);
 
744
 
 
745
        if (_XANYSET(r_mask)) {
 
746
            char buf[BUFSIZE];
 
747
            long pend_not_register;
 
748
            register long pend;
 
749
            register xEvent *ev;
 
750
 
 
751
            /* find out how much data can be read */
 
752
            if (BytesReadable(dpy->fd, (char *) &pend_not_register) < 0)
 
753
                _XIOError(dpy);
 
754
            pend = pend_not_register;
 
755
 
 
756
            /* must read at least one xEvent; if none is pending, then
 
757
               we'll just block waiting for it */
 
758
            if (pend < SIZEOF(xEvent)) pend = SIZEOF(xEvent);
 
759
                
 
760
            /* but we won't read more than the max buffer size */
 
761
            if (pend > BUFSIZE) pend = BUFSIZE;
 
762
 
 
763
            /* round down to an integral number of XReps */
 
764
            pend = (pend / SIZEOF(xEvent)) * SIZEOF(xEvent);
 
765
 
 
766
            N_XRead (dpy, buf, pend);
 
767
 
 
768
            /* no space between comma and type or else macro will die */
 
769
            STARTITERATE (ev,xEvent, buf, (pend > 0),
 
770
                          (pend -= SIZEOF(xEvent))) {
 
771
                if (ev->u.u.type == X_Error)
 
772
                    _XError (dpy, (xError *) ev);
 
773
                else            /* it's an event packet; die */
 
774
                    DPSFatalProc((DPSContext)0, "N_XWaitForWritable read bogus X event");
 
775
            }
 
776
            ENDITERATE
 
777
        }
 
778
        if (_XANYSET(w_mask))
 
779
            return;
 
780
    }
 
781
}
 
782
 
 
783
 
 
784
void N_XWaitForReadable(Display *dpy)
 
785
{
 
786
    unsigned long r_mask[MSKCNT];
 
787
    int result;
 
788
        
 
789
    CLEARBITS(r_mask);
 
790
    do {
 
791
        BITSET(r_mask, dpy->fd);
 
792
        result = select(dpy->fd + 1, (SELECT_TYPE) r_mask, (SELECT_TYPE) NULL,
 
793
                        (SELECT_TYPE) NULL, (struct timeval *) NULL);
 
794
        if (result == -1 && errno != EINTR) _XIOError(dpy);
 
795
    } while (result <= 0);
 
796
}
 
797
 
 
798
#ifdef XXX
 
799
 
 
800
static int padlength[4] = {0, 3, 2, 1};  /* make sure auth is multiple of 4 */
 
801
 
 
802
_XSendClientPrefix (
 
803
     Display *dpy,
 
804
     xConnClientPrefix *client,         /* contains count for auth_* */
 
805
     char *auth_proto,                  /* NOT null-terminated */
 
806
     char char *auth_string)            /* NOT null-terminated */
 
807
{
 
808
    int auth_length = client->nbytesAuthProto;
 
809
    int auth_strlen = client->nbytesAuthString;
 
810
    char padbuf[3];                     /* for padding to 4x bytes */
 
811
    int pad;
 
812
    struct iovec iovarray[5], *iov = iovarray;
 
813
    int niov = 0;
 
814
 
 
815
#define add_to_iov(b,l) \
 
816
          { iov->iov_base = (b); iov->iov_len = (l); iov++, niov++; }
 
817
 
 
818
    add_to_iov ((caddr_t) client, SIZEOF(xConnClientPrefix));
 
819
 
 
820
    /*
 
821
     * write authorization protocol name and data
 
822
     */
 
823
    if (auth_length > 0) {
 
824
        add_to_iov (auth_proto, auth_length);
 
825
        pad = padlength [auth_length & 3];
 
826
        if (pad) add_to_iov (padbuf, pad);
 
827
    }
 
828
    if (auth_strlen > 0) {
 
829
        add_to_iov (auth_string, auth_strlen);
 
830
        pad = padlength [auth_strlen & 3];
 
831
        if (pad) add_to_iov (padbuf, pad);
 
832
    }
 
833
 
 
834
#undef add_to_iov
 
835
 
 
836
    (void) WritevToServer (dpy->fd, iovarray, niov);
 
837
    return;
 
838
}
 
839
 
 
840
#endif /* XXX */