~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to o/nsocket.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* the following file compiles under win95 using cygwinb19 */ 
 
2
#include <stdlib.h>
 
3
#include "include.h"
 
4
#include <string.h>
 
5
 
 
6
#ifdef DODEBUG
 
7
#define dprintf(s,arg) \
 
8
  do {fprintf(stderr,s,arg); \
 
9
    fflush(stderr); }\
 
10
    while(0)
 
11
#else 
 
12
#define dprintf(s,arg)
 
13
#endif     
 
14
 
 
15
#ifdef HAVE_NSOCKET
 
16
 
 
17
 
 
18
 
 
19
#include <sys/time.h>
 
20
#include <sys/types.h>
 
21
#include <unistd.h>
 
22
 
 
23
#include <errno.h>
 
24
#include <fcntl.h>
 
25
#include <stdio.h>
 
26
 
 
27
 
 
28
 
 
29
/************* for the sockets ******************/ 
 
30
#include <sys/socket.h>         /* struct sockaddr, SOCK_STREAM, ... */
 
31
#ifndef NO_UNAME
 
32
#   include <sys/utsname.h>     /* uname system call. */
 
33
#endif
 
34
#include <netinet/in.h>         /* struct in_addr, struct sockaddr_in */
 
35
#include <arpa/inet.h>          /* inet_ntoa() */
 
36
#include <netdb.h>              /* gethostbyname() */
 
37
 
 
38
/****************end for sockets *******************/
 
39
 
 
40
 
 
41
 
 
42
/*
 
43
 * These bits may be ORed together into the "flags" field of a TcpState
 
44
 * structure.
 
45
 */
 
46
 
 
47
 
 
48
#define TCP_ASYNC_SOCKET        (1<<0)  /* Asynchronous socket. */
 
49
#define TCP_ASYNC_CONNECT       (1<<1)  /* Async connect in progress. */
 
50
 
 
51
/*
 
52
 * The following defines the maximum length of the listen queue. This is
 
53
 * the number of outstanding yet-to-be-serviced requests for a connection
 
54
 * on a server socket, more than this number of outstanding requests and
 
55
 * the connection request will fail.
 
56
 */
 
57
 
 
58
#ifndef SOMAXCONN
 
59
#define SOMAXCONN       100
 
60
#endif
 
61
 
 
62
#if     (SOMAXCONN < 100)
 
63
#undef  SOMAXCONN
 
64
#define SOMAXCONN       100
 
65
#endif
 
66
 
 
67
#define VOID void
 
68
#define ERROR_MESSAGE(msg)     do{ fprintf(stderr,msg); exit(1) ; } while(0)    
 
69
 
 
70
#ifdef STAND
 
71
 
 
72
main(argc,argv)
 
73
     char *argv[];
 
74
     int argc;
 
75
{
 
76
  char buf[1000];
 
77
  char out[1000];
 
78
  char op[10];
 
79
  int n,fd;
 
80
  int x,y,ans,errno;
 
81
  char *bp;
 
82
  fd_set readfds;
 
83
  struct timeval timeout;
 
84
  
 
85
  
 
86
  bp = buf;
 
87
  fd = doConnect(argv[1],atoi(argv[2]));
 
88
  if (fd < 0) {
 
89
    perror("cant connect");
 
90
    exit(1);
 
91
  }
 
92
 
 
93
  while (1) { int high;
 
94
    timeout.tv_sec = 20;
 
95
    timeout.tv_usec = 0;
 
96
    FD_ZERO(&readfds);
 
97
    FD_SET(fd,&readfds);
 
98
    
 
99
    high = select(fd+1,&readfds,NULL,NULL,&timeout);
 
100
    if (high > 0)
 
101
      {
 
102
        int n;
 
103
        n = read(fd,buf,sizeof(buf));
 
104
        if (3 == sscanf(buf,"%d %s %d",&x,op,&y)) {
 
105
          switch (op[0]) {
 
106
            
 
107
          case '+':       sprintf(out,"%d\n",x+y);
 
108
            break;
 
109
          case '*':  sprintf(out,"%d\n",x*y);
 
110
            break;
 
111
          default:
 
112
            sprintf(out,"bad operation\n");
 
113
          }
 
114
          write(fd,out,strlen(out));
 
115
        }
 
116
      }
 
117
  }
 
118
}
 
119
 
 
120
#endif
 
121
 
 
122
 
 
123
/*
 
124
 *----------------------------------------------------------------------
 
125
 *
 
126
 * CreateSocketAddress --
 
127
 *
 
128
 *      This function initializes a sockaddr structure for a host and port.
 
129
 *
 
130
 * Results:
 
131
 *      1 if the host was valid, 0 if the host could not be converted to
 
132
 *      an IP address.
 
133
 *
 
134
 * Side effects:
 
135
 *      Fills in the *sockaddrPtr structure.
 
136
 *
 
137
 *----------------------------------------------------------------------
 
138
 */
 
139
 
 
140
static int
 
141
CreateSocketAddress(struct sockaddr_in *sockaddrPtr, char *host, int port)
 
142
                                        /* Socket address */
 
143
                                        /* Host.  NULL implies INADDR_ANY */
 
144
                                        /* Port number */
 
145
{
 
146
    struct hostent *hostent;            /* Host database entry */
 
147
    struct in_addr addr;                /* For 64/32 bit madness */
 
148
 
 
149
    (void) memset((VOID *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
 
150
    sockaddrPtr->sin_family = AF_INET;
 
151
    sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
 
152
    if (host == NULL) {
 
153
        addr.s_addr = INADDR_ANY;
 
154
    } else {
 
155
        addr.s_addr = inet_addr(host);
 
156
        if (addr.s_addr == -1) {
 
157
            hostent = gethostbyname(host);
 
158
            if (hostent != NULL) {
 
159
                memcpy((VOID *) &addr,
 
160
                        (VOID *) hostent->h_addr_list[0],
 
161
                        (size_t) hostent->h_length);
 
162
            } else {
 
163
#ifdef  EHOSTUNREACH
 
164
                errno = EHOSTUNREACH;
 
165
#else
 
166
#ifdef ENXIO
 
167
                errno = ENXIO;
 
168
#endif
 
169
#endif
 
170
                return 0;       /* error */
 
171
            }
 
172
        }
 
173
    }
 
174
        
 
175
    /*
 
176
     * NOTE: On 64 bit machines the assignment below is rumored to not
 
177
     * do the right thing. Please report errors related to this if you
 
178
     * observe incorrect behavior on 64 bit machines such as DEC Alphas.
 
179
     * Should we modify this code to do an explicit memcpy?
 
180
     */
 
181
 
 
182
    sockaddrPtr->sin_addr.s_addr = addr.s_addr;
 
183
    return 1;   /* Success. */
 
184
}
 
185
 
 
186
 
 
187
 
 
188
/* return -1 on failure, or else an fd */
 
189
int 
 
190
CreateSocket(int port, char *host, int server, char *myaddr, int myport, int async)
 
191
                                /* Port number to open. */
 
192
                                /* Name of host on which to open port.
 
193
                                 * NULL implies INADDR_ANY */
 
194
                                /* 1 if socket should be a server socket,
 
195
                                 * else 0 for a client socket. */
 
196
                                /* Optional client-side address */
 
197
                                /* Optional client-side port */
 
198
                                /* If nonzero and creating a client socket,
 
199
                                 * attempt to do an async connect. Otherwise
 
200
                                 * do a synchronous connect or bind. */
 
201
{
 
202
    int status, sock, asyncConnect, curState, origState;
 
203
    struct sockaddr_in sockaddr;        /* socket address */
 
204
    struct sockaddr_in mysockaddr;      /* Socket address for client */
 
205
 
 
206
    sock = -1;
 
207
    origState = 0;
 
208
    if (! CreateSocketAddress(&sockaddr, host, port)) {
 
209
        goto addressError;
 
210
    }
 
211
    if ((myaddr != NULL || myport != 0) &&
 
212
            ! CreateSocketAddress(&mysockaddr, myaddr, myport)) {
 
213
        goto addressError;
 
214
    }
 
215
 
 
216
    sock = socket(AF_INET, SOCK_STREAM, 0);
 
217
    if (sock < 0) {
 
218
        goto addressError;
 
219
    }
 
220
 
 
221
    /*
 
222
     * Set the close-on-exec flag so that the socket will not get
 
223
     * inherited by child processes.
 
224
     */
 
225
 
 
226
    fcntl(sock, F_SETFD, FD_CLOEXEC);
 
227
    
 
228
    asyncConnect = 0;
 
229
    status = 0;
 
230
    if (server) {
 
231
 
 
232
        /*
 
233
         * Set up to reuse server addresses automatically and bind to the
 
234
         * specified port.
 
235
         */
 
236
    
 
237
        status = 1;
 
238
        (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &status,
 
239
                sizeof(status));
 
240
        status = bind(sock, (struct sockaddr *) &sockaddr,
 
241
                sizeof(struct sockaddr));
 
242
        if (status != -1) {
 
243
            status = listen(sock, SOMAXCONN);
 
244
        } 
 
245
    } else {
 
246
        if (myaddr != NULL || myport != 0) { 
 
247
            curState = 1;
 
248
            (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
 
249
                    (char *) &curState, sizeof(curState));
 
250
            status = bind(sock, (struct sockaddr *) &mysockaddr,
 
251
                    sizeof(struct sockaddr));
 
252
            if (status < 0) {
 
253
                goto bindError;
 
254
            }
 
255
        }
 
256
 
 
257
        /*
 
258
         * Attempt to connect. The connect may fail at present with an
 
259
         * EINPROGRESS but at a later time it will complete. The caller
 
260
         * will set up a file handler on the socket if she is interested in
 
261
         * being informed when the connect completes.
 
262
         */
 
263
 
 
264
        if (async) {
 
265
#ifndef USE_FIONBIO
 
266
            origState = fcntl(sock, F_GETFL);
 
267
            curState = origState | O_NONBLOCK;
 
268
            status = fcntl(sock, F_SETFL, curState);
 
269
#endif
 
270
 
 
271
#ifdef  USE_FIONBIO
 
272
            curState = 1;
 
273
            status = ioctl(sock, FIONBIO, &curState);
 
274
#endif            
 
275
        } else {
 
276
            status = 0;
 
277
        }
 
278
        if (status > -1) {
 
279
            status = connect(sock, (struct sockaddr *) &sockaddr,
 
280
                    sizeof(sockaddr));
 
281
            if (status < 0) {
 
282
                if (errno == EINPROGRESS) {
 
283
                    asyncConnect = 1;
 
284
                    status = 0;
 
285
                }
 
286
            }
 
287
        }
 
288
    }
 
289
 
 
290
bindError:
 
291
    if (status < 0) {
 
292
 
 
293
            ERROR_MESSAGE("couldn't open socket:");
 
294
 
 
295
        if (sock != -1) {
 
296
            close(sock);
 
297
        }
 
298
        return -1;
 
299
    }
 
300
 
 
301
      return sock;
 
302
 
 
303
addressError:
 
304
    if (sock != -1) {
 
305
        close(sock);
 
306
    }
 
307
 
 
308
      ERROR_MESSAGE("couldn't open socket:");
 
309
 
 
310
    return -1;
 
311
}
 
312
 
 
313
 
 
314
#ifdef STAND
 
315
int
 
316
doConnect(host,port)
 
317
          char *host;          /*name of host we are trying to connect to */
 
318
          int port;            /* port number to use */
 
319
{
 
320
    return CreateSocket(port, host, 0 , NULL , 0 , 0);    
 
321
}
 
322
#endif
 
323
 
 
324
 
 
325
 
 
326
#define SOCKET_FD(strm) ((strm)->sm.sm_fp ? fileno((strm)->sm.sm_fp) : -1)
 
327
 
 
328
DEFUN_NEW("GETPEERNAME",object,fSgetpeername,SI,1,1,NONE,OO,OO,OO,OO,(object sock),
 
329
 "Return a list of three elements: the address, the hostname and the port for the other end of the socket.  If hostname is not available it will be equal to the address.  Invalid on server sockets. Return NIL on failure.")
 
330
{
 
331
 struct sockaddr_in peername;
 
332
 int size = sizeof(struct sockaddr_in);
 
333
 struct hostent *hostEntPtr;
 
334
 object address,host;
 
335
 check_socket(sock);
 
336
 if (getpeername(SOCKET_FD(sock), (struct sockaddr *) &peername, &size)
 
337
                >= 0) {
 
338
           address=make_simple_string(inet_ntoa(peername.sin_addr));
 
339
           hostEntPtr = gethostbyaddr((char *) &(peername.sin_addr),
 
340
                    sizeof(peername.sin_addr), AF_INET);
 
341
            if (hostEntPtr != (struct hostent *) NULL) 
 
342
               host = make_simple_string(hostEntPtr->h_name);
 
343
            else host = address;
 
344
            return list(3,address,host,make_fixnum(ntohs(peername.sin_port)));
 
345
 } else {
 
346
   return Cnil;
 
347
 }
 
348
}
 
349
            
 
350
 
 
351
DEFUN_NEW("GETSOCKNAME",object,fSgetsockname,SI,1,1,NONE,OO,OO,OO,OO,(object sock),
 
352
 "Return a list of three elements: the address, the hostname and the port for the socket.  If hostname is not available it will be equal to the address. Return NIL on failure. ")
 
353
{ struct sockaddr_in sockname;
 
354
 int size = sizeof(struct sockaddr_in);
 
355
 struct hostent *hostEntPtr;
 
356
 object address,host;
 
357
 
 
358
 check_socket(sock);
 
359
 if (getsockname(SOCKET_FD(sock), (struct sockaddr *) &sockname, &size)
 
360
                >= 0) {
 
361
  address= make_simple_string(inet_ntoa(sockname.sin_addr));
 
362
  hostEntPtr = gethostbyaddr((char *) &(sockname.sin_addr),
 
363
                             sizeof(sockname.sin_addr), AF_INET);
 
364
  if (hostEntPtr != (struct hostent *) NULL)
 
365
   host = make_simple_string(hostEntPtr->h_name);
 
366
  else host=address;
 
367
  return list(3,address,host,make_fixnum(ntohs(sockname.sin_port)));
 
368
 } else {
 
369
   return Cnil;
 
370
 }
 
371
}
 
372
 
 
373
/*
 
374
  TcpBlocking --
 
375
    Use on a tcp socket to alter the blocking or non blocking.
 
376
  Results 0 if succeeds and errno if fails.
 
377
 
 
378
  Side effects:
 
379
     the channel is setto blocking or nonblocking mode. 
 
380
*/  
 
381
 
 
382
DEFUN_NEW("SET-BLOCKING",object,fSset_blocking,SI,2,2,NONE,OO,OO,OO,OO,(object sock,object setBlocking),
 
383
      "Set blocking on if MODE is T otherwise off.  Return 0 if succeeds. Otherwise the error number.")
 
384
{
 
385
      int setting;
 
386
      int fd ;
 
387
   AGAIN:
 
388
      check_stream(sock);
 
389
      /* set our idea of whether blocking on or off 
 
390
        setBlocking==Cnil <==> blocking turned off.  */
 
391
     SET_STREAM_FLAG(sock,gcl_sm_tcp_async,setBlocking==Cnil);
 
392
      if (sock->sm.sm_mode == smm_two_way) {
 
393
        /* check for case they are sock streams and so
 
394
           share the same fd */
 
395
        if (STREAM_INPUT_STREAM(sock)->sm.sm_fp != NULL
 
396
            &&STREAM_OUTPUT_STREAM(sock)->sm.sm_fp != NULL
 
397
            && (SOCKET_FD(STREAM_INPUT_STREAM(sock))==
 
398
                SOCKET_FD(STREAM_OUTPUT_STREAM(sock))))
 
399
          {
 
400
            SET_STREAM_FLAG(STREAM_OUTPUT_STREAM(sock),
 
401
                            gcl_sm_tcp_async,setBlocking==Cnil);
 
402
            sock = STREAM_INPUT_STREAM(sock);
 
403
            /* they share an 'fd' and so only do one. */
 
404
            goto AGAIN;
 
405
          }
 
406
        else
 
407
        {
 
408
          int x1 = fix(FFN(fSset_blocking)(STREAM_INPUT_STREAM(sock),setBlocking));
 
409
          int x2 = fix(FFN(fSset_blocking)(STREAM_OUTPUT_STREAM(sock),setBlocking));
 
410
          /* if either is negative result return negative. (ie fail)
 
411
             If either is positive return positive (ie fail)
 
412
             Zero result means both ok.  (ie succeed)
 
413
             */       
 
414
          
 
415
          return make_fixnum((x1 < 0 || x2 < 0 ? -2 : x1 > 0  ? x1 : x2));
 
416
        }
 
417
      }
 
418
        
 
419
      if (sock->sm.sm_fp == NULL)
 
420
        return make_fixnum(-2);
 
421
      fd = SOCKET_FD(sock);
 
422
 
 
423
 
 
424
#ifndef USE_FIONBIO
 
425
    setting = fcntl(fd, F_GETFL);
 
426
    if (setBlocking != Cnil) {
 
427
      setting &= (~(O_NONBLOCK));
 
428
    } else {
 
429
      setting |= O_NONBLOCK;
 
430
    }
 
431
    if (fcntl(fd, F_SETFL, setting) < 0) {
 
432
        return make_fixnum(errno);
 
433
    }
 
434
#endif
 
435
 
 
436
#ifdef  USE_FIONBIO
 
437
    if (setBlocking != Cnil) {
 
438
        setting = 0;
 
439
        if (ioctl(fd, (int) FIONBIO, &setting) == -1) {
 
440
            return make_fixnum(errno);
 
441
        }
 
442
    } else {
 
443
        setting = 1;
 
444
        if (ioctl(fd, (int) FIONBIO, &setting) == -1) {
 
445
            return make_fixnum(errno);
 
446
        }
 
447
    }
 
448
#endif
 
449
  return make_fixnum(0);
 
450
}
 
451
 
 
452
/* with 2 args return the function if any.
 
453
*/
 
454
 
 
455
/*setHandler(stream,readable,function)
 
456
     object stream;     stream to watch 
 
457
     object readable;   keyword readable,writable 
 
458
     object function;   the handler function to be invoked with arg stream 
 
459
{
 
460
  
 
461
}
 
462
*/
 
463
/* goes through the streams does a select with 0 timeout, and invokes
 
464
   any handlers */
 
465
/*
 
466
update ()
 
467
{
 
468
 
 
469
}
 
470
*/
 
471
 
 
472
static int
 
473
joe(int x) { return x; }
 
474
 
 
475
/*
 
476
  get a character from FP but block, if it would return
 
477
  the EOF, but the stream is not closed.
 
478
*/   
 
479
int
 
480
getOneChar(FILE *fp)
 
481
{
 
482
  fd_set readfds;
 
483
  struct timeval timeout;
 
484
  int fd= fileno(fp);
 
485
  int high;
 
486
  /*  fprintf(stderr,"<socket 0x%x>",fp);
 
487
  fflush(stderr); */
 
488
  fprintf(stderr,"in getOneChar, fd=%d,fp=%p",fd,fp);
 
489
  fflush(stderr);
 
490
  if (fd == 0)
 
491
   { joe(fd);
 
492
   return -1;
 
493
   }
 
494
 
 
495
  while (1) {
 
496
  timeout.tv_sec = 0;
 
497
  timeout.tv_usec = 200000;
 
498
  FD_ZERO(&readfds);
 
499
  FD_SET(fd,&readfds);
 
500
  CHECK_INTERRUPT;       
 
501
  high = select(fd+1,&readfds,NULL,NULL,&timeout);
 
502
  if (high > 0)
 
503
    {
 
504
      int ch ;
 
505
      fprintf(stderr,"in getOneChar, fd=%d,fp=%p",fd,fp);
 
506
      fflush(stderr);
 
507
      ch = getc(fp);
 
508
      if ( ch != EOF || feof(fp) ) {
 
509
        /*      fprintf(stderr,"< 0x%x returning %d,%c>\n",fp,ch,ch);
 
510
      fflush(stderr);
 
511
      */
 
512
      }
 
513
      fprintf(stderr,"in getOneChar, ch= %c,%d\n",ch,ch);
 
514
      fflush(stderr);
 
515
      CHECK_INTERRUPT;   
 
516
      if (ch != EOF) return ch;
 
517
      if (feof(fp)) return EOF;
 
518
    }
 
519
     
 
520
  }
 
521
}
 
522
 
 
523
#ifdef DODEBUG
 
524
#define dprintf(s,arg) \
 
525
  do {fprintf(stderr,s,arg); \
 
526
    fflush(stderr); }\
 
527
    while(0)
 
528
#else 
 
529
#define dprintf(s,arg)
 
530
#endif     
 
531
     
 
532
void
 
533
ungetCharGclSocket(int c, object strm)
 
534
                  /* the character to unget */
 
535
                  /* stream */
 
536
{  object bufp = SOCKET_STREAM_BUFFER(strm);
 
537
  if (c == EOF) return;
 
538
  dprintf("pushing back %c\n",c);
 
539
  if (bufp->ust.ust_fillp < bufp->ust.ust_dim) {
 
540
    bufp->ust.ust_self[(bufp->ust.ust_fillp)++]=c;
 
541
  } else {
 
542
    FEerror("Tried to unget too many chars",0);
 
543
  }
 
544
}
 
545
 
 
546
 
 
547
/*
 
548
 *----------------------------------------------------------------------
 
549
 *
 
550
 * TcpOutputProc --
 
551
 *
 
552
 *      This procedure is invoked by the generic IO level to write output
 
553
 *      to a TCP socket based channel.
 
554
 *
 
555
 *      NOTE: We cannot share code with FilePipeOutputProc because here
 
556
 *      we must use send, not write, to get reliable error reporting.
 
557
 *
 
558
 * Results:
 
559
 *      The number of bytes written is returned. An output argument is
 
560
 *      set to a POSIX error code if an error occurred, or zero.
 
561
 *
 
562
 * Side effects:
 
563
 *      Writes output on the output device of the channel.
 
564
 *
 
565
 *----------------------------------------------------------------------
 
566
 */
 
567
 
 
568
int
 
569
TcpOutputProc(int fd, char *buf, int toWrite, int *errorCodePtr)
 
570
                        /* Socket state. */
 
571
                                        /* The data buffer. */
 
572
                                        /* How many bytes to write? */
 
573
                                        /* Where to store error code. */
 
574
{
 
575
    int written;
 
576
 
 
577
    *errorCodePtr = 0;
 
578
    written = send(fd, buf, (size_t) toWrite, 0);
 
579
    if (written > -1) {
 
580
        return written;
 
581
    }
 
582
    *errorCodePtr = errno;
 
583
    return -1;
 
584
}
 
585
 
 
586
void
 
587
tcpCloseSocket(int fd)
 
588
{
 
589
  close(fd);
 
590
 
 
591
}
 
592
 
 
593
static void
 
594
doReverse(char *s, int n)
 
595
{ char *p=&s[n-1];
 
596
  int m = n/2;
 
597
  while (--m>=0) {
 
598
    int tem = *s;
 
599
    *s = *p;
 
600
    *p = tem;
 
601
    s++; p--;
 
602
  }
 
603
}
 
604
 
 
605
 
 
606
 
 
607
/*
 
608
  getCharGclSocket(strm,block) -- get one character from a socket
 
609
  stream.
 
610
  Results: a character or EOF if at end of file
 
611
  Side Effects:  The buffer may be filled, and the fill pointer
 
612
  of the buffer may be changed.
 
613
 */
 
614
int
 
615
getCharGclSocket(object strm, object block)
 
616
{
 
617
  object bufp = SOCKET_STREAM_BUFFER(strm);
 
618
  if (bufp->ust.ust_fillp > 0) {
 
619
    dprintf("getchar returns (%c)\n",bufp->ust.ust_self[-1+(bufp->ust.ust_fillp)]);
 
620
    return bufp->ust.ust_self[--(bufp->ust.ust_fillp)];
 
621
  }
 
622
  else {
 
623
    fd_set readfds;
 
624
    struct timeval timeout;
 
625
    int fd = SOCKET_STREAM_FD(strm);
 
626
    if (1)
 
627
      { int high;
 
628
      AGAIN:      
 
629
      /* under cygwin a too large timout like (1<<30) does not work */
 
630
      timeout.tv_sec = (block != Ct ?  0 : 0);
 
631
      timeout.tv_usec = 10000;
 
632
      FD_ZERO(&readfds);
 
633
      FD_SET(fd,&readfds);
 
634
      high = select(fd+1,&readfds,NULL,NULL,&timeout);
 
635
      if (high > 0)
 
636
        { object bufp = SOCKET_STREAM_BUFFER(strm);
 
637
        int n;
 
638
        n = SAFE_READ(fd,bufp->ust.ust_self ,bufp->ust.ust_dim);
 
639
        doReverse(bufp->ust.ust_self,n);
 
640
        bufp->ust.ust_fillp=n;
 
641
        if (n > 0)
 
642
          {
 
643
            dprintf("getchar returns (%c)\n",bufp->ust.ust_self[-1+(bufp->ust.ust_fillp)]);
 
644
            return bufp->ust.ust_self[--(bufp->ust.ust_fillp)];
 
645
          }
 
646
        else
 
647
          {
 
648
           return EOF;
 
649
          FEerror("select said there was stuff there but there was not",0);
 
650
          }
 
651
        }
 
652
      /* probably a signal interrupted us.. */
 
653
      if (block == Ct)
 
654
        goto AGAIN;
 
655
      return EOF;
 
656
      }
 
657
  }
 
658
}
 
659
 
 
660
#else
 
661
int
 
662
getOneChar(fp)
 
663
     FILE *fp;
 
664
{
 
665
  return getc(fp);
 
666
}
 
667
 
 
668
#endif
 
669
 
 
670
 
 
671