1 #include "niml_private.h"
2
3 /*************************************************************************/
4 /********************* Functions for NIML I/O ****************************/
5 /*************************************************************************/
6
7 /*! To print a system error message. */
8
9 #undef PERROR
10
11 #ifdef NIML_DEBUG
12 # define PERROR(x) perror(x)
13 #else
14 # define PERROR(x)
15 #endif
16
17 #include <signal.h> /* signal handler stuff */
18 #include <fcntl.h> /* file control stuff */
19
20 /*! For tcp - indicates that SIGPIPE is ignored;
21 will be set the first time tcp_send is called. */
22
23 static int nosigpipe = 0 ;
24
25 /*! For tcp - indicates that the SIGURG handler is installed;
26 will be set the first time a TCP socket is created. */
27
28 static int sigurg = 0 ; /* 02 Jan 2004 */
29
30 /*! How to close a socket, given the descriptor ss. */
31
32 #define CLOSEDOWN(ss) ( shutdown((ss),2) , close((ss)) )
33
34 /*! This is used to set the send/receive buffer size for sockets. */
35
36 #define SOCKET_BUFSIZE (63*1024)
37
38 /*! This macro is used so I can replace recv() with something else if I want. */
39
40 #define tcp_recv recv
41
42 /*! This macro is used so I can replace send() with something else if I want. */
43
44 #define tcp_send send
45
46 #ifndef MIN
47 /*! Duh. */
48 # define MIN(a,b) (((a)>(b)) ? (b) : (a))
49 #endif
50
51 /*! Next delay in milliseconds, given current delay. */
52
53 #undef NEXTDMS
54 #define NEXTDMS(dm) MIN(1.1*(dm)+1.01,66.0)
55
56 /*-------------------------------------------------------------------*/
57 /*! Number of entries on the list of currently open streams.
58
59 This list is needed so we can deal with the SIGURG signal,
60 which we use as a message to shut a socket down. The signal
61 call itself doesn't tell us which socket was the trigger,
62 so we have to search all the open sockets for a match:
63 hence, this list of open streams.
64 ---------------------------------------------------------------------*/
65
66 static int num_open_streams = 0 ;
67
68 /*! The actual array of open NIML streams. */
69
70 static NI_stream_type ** open_streams = NULL ;
71
72 /*! Signal that we are doing atexit() stuff. */
73
74 static volatile int doing_atexit = 0 ; /* 05 May 2005 */
75
76 /*-------------------------------------------------------------------*/
77 /*! Add a stream to the open list. */
78
add_open_stream(NI_stream_type * ns)79 static void add_open_stream( NI_stream_type *ns )
80 {
81 int nn = num_open_streams ;
82
83 if( ns == NULL ) return ; /* bad input */
84
85 open_streams = (NI_stream_type **)realloc( (void *)open_streams ,
86 sizeof(NI_stream_type *)*(nn+1) );
87
88 open_streams[nn] = ns ; num_open_streams++ ; return ;
89 }
90
91 /*-------------------------------------------------------------------*/
92 /*! Remove a stream from the open list. */
93
remove_open_stream(NI_stream_type * ns)94 static void remove_open_stream( NI_stream_type *ns )
95 {
96 int nn = num_open_streams , ii,jj ;
97
98 if( doing_atexit || nn <= 0 || ns == NULL ) return ; /* bad input */
99
100 for( ii=0 ; ii < nn ; ii++ ) /* find input */
101 if( open_streams[ii] == ns ) break ;
102 if( ii == nn ) return ; /* not found!? */
103
104 for( jj=ii+1 ; jj < nn ; jj++ ) /* move those above down */
105 open_streams[jj-1] = open_streams[jj] ;
106
107 open_streams[nn-1] = NULL ; num_open_streams-- ; return ;
108 }
109
110 /*------------------------------------------------------------------*/
111 /*! At program exit, close all open streams. */
112
atexit_open_streams(void)113 static void atexit_open_streams(void) /* 22 Apr 2005 */
114 {
115 int ii ;
116 if( doing_atexit ) return ;
117 doing_atexit = 1 ;
118 for( ii=0 ; ii < num_open_streams ; ii++ ){
119 NI_sleep(2) ;
120 NI_stream_close_keep( open_streams[ii] , 5 ) ;
121 }
122 return ;
123 }
124
125 /*! Variable to indicate that the atexit() call has/hasn't been made */
126
127 static int atexit_is_setup = 0 ;
128
129 /*------------------------------------------------------------------*/
130 /*! Signal handler for SIGURG -- for incoming OOB data on a socket.
131 We just close the NI_stream that the socket is attached to.
132 But first we have to find it!
133 --------------------------------------------------------------------*/
134
tcp_sigurg_handler(int sig)135 static void tcp_sigurg_handler( int sig )
136 {
137 int nn = num_open_streams , ii , sd,sdtop ;
138 NI_stream_type *ns ;
139 fd_set efds ;
140 struct timeval tv ;
141 static volatile int busy=0 ;
142
143 if( sig != SIGURG ||
144 busy ||
145 num_open_streams <= 0 || open_streams == NULL ) return ; /* bad */
146
147 busy = 1 ; /* prevent recursion! */
148
149 /* find largest socket descriptor in list of streams,
150 and make list of all open socket descriptors in streams */
151
152 FD_ZERO(&efds) ; sdtop = -1 ;
153 for( ii=0 ; ii < nn ; ii++ ){
154 if( open_streams[ii] != NULL &&
155 open_streams[ii]->bad != MARKED_FOR_DEATH &&
156 open_streams[ii]->type == NI_TCP_TYPE &&
157 open_streams[ii]->sd >= 0 ){
158
159 FD_SET( open_streams[ii]->sd , &efds ) ;
160 if( open_streams[ii]->sd > sdtop ) sdtop = open_streams[ii]->sd;
161 }
162 }
163 if( sdtop < 0 ){ busy=0 ; return; } /* no sockets found? */
164
165 /* do a select to find which socket has an exceptional condition */
166
167 tv.tv_sec = 0 ;
168 tv.tv_usec = 666 ;
169 ii = select(sdtop+1, NULL, NULL, &efds, &tv) ; /* check it */
170 if( ii <= 0 ){ busy=0 ; return; } /* no sockets found? */
171
172 /* loop over found sockets and close their streams */
173
174 for( ii=0 ; ii < nn ; ii++ ){
175 if( open_streams[ii] != NULL && open_streams[ii]->type == NI_TCP_TYPE ){
176 if( FD_ISSET( open_streams[ii]->sd , &efds ) ){
177 CLOSEDOWN( open_streams[ii]->sd ) ;
178 open_streams[ii]->bad = MARKED_FOR_DEATH ;
179 }
180 }
181 }
182
183 busy=0 ; return ;
184 }
185
186 /********************************************************************
187 Routines to manipulate TCP/IP stream sockets.
188 See http://www.manualy.sk/sock-faq/unix-socket-faq.html for info.
189 *********************************************************************/
190
191 /*-------------------------------------------------------------------*/
192 /*! See if the given socket (file descriptor sd) is ready to read.
193
194 msec is the number of milliseconds to wait:
195 - zero ==> no waiting
196 - < 0 ==> wait until something happens (not recommended)
197
198 Return values are:
199 - -1 = some error occured (socket closed at other end?)
200 - 0 = socket is not ready to read
201 - 1 = socket has data
202 ---------------------------------------------------------------------*/
203
tcp_readcheck(int sd,int msec)204 static int tcp_readcheck( int sd , int msec )
205 {
206 int ii ;
207 fd_set rfds ;
208 struct timeval tv , *tvp ;
209
210 if( sd < 0 ) return -1 ; /* bad socket id */
211
212 FD_ZERO(&rfds) ; FD_SET(sd, &rfds) ; /* check only sd */
213
214 if( msec >= 0 ){ /* set timer */
215 tv.tv_sec = msec/1000 ;
216 tv.tv_usec = (msec%1000)*1000 ;
217 tvp = &tv ;
218 } else {
219 tvp = NULL ; /* forever */
220 }
221
222 ii = select(sd+1, &rfds, NULL, NULL, tvp) ; /* check it */
223 if( ii == -1 ) PERROR( "tcp_readcheck(select)" ) ;
224 return ii ;
225 }
226
227 /*-------------------------------------------------------------------*/
228 /*! See if the given socket (file descriptor sd) is ready to write.
229
230 msec = max amount of time to wait, in milliseconds.
231 - zero ==> no waiting
232 - < 0 ==> wait until something happens (not recommended)
233
234 Return values are
235 - -1 = some error occured (socket closed at other end?)
236 - 0 = socket is not ready to write
237 - 1 = OK to write to socket
238 ---------------------------------------------------------------------*/
239
tcp_writecheck(int sd,int msec)240 static int tcp_writecheck( int sd , int msec )
241 {
242 int ii ;
243 fd_set wfds ;
244 struct timeval tv , *tvp ;
245
246 if( sd < 0 ) return -1 ; /* bad socket id */
247
248 FD_ZERO(&wfds) ; FD_SET(sd, &wfds) ; /* check only sd */
249
250 if( msec >= 0 ){ /* set timer */
251 tv.tv_sec = msec/1000 ;
252 tv.tv_usec = (msec%1000)*1000 ;
253 tvp = &tv ;
254 } else {
255 tvp = NULL ; /* forever */
256 }
257
258 ii = select(sd+1, NULL , &wfds, NULL, tvp); /* check it */
259 if( ii == -1 ) PERROR( "tcp_writecheck(select)" ) ;
260 return ii ;
261 }
262
263 /*------------------------------------------------------------------------*/
264 /*! Set a socket so that it will cutoff quickly when it is closed.
265 See http://www.manualy.sk/sock-faq/unix-socket-faq.html for more
266 information about this stuff.
267 --------------------------------------------------------------------------*/
268
tcp_set_cutoff(int sd)269 static void tcp_set_cutoff( int sd )
270 {
271 if( sd < 0 ) return ; /* bad input */
272
273 #ifdef SO_LINGER
274 /* Turn off "lingering". */
275
276 { struct linger lg ;
277 lg.l_onoff = 1 ;
278 lg.l_linger = 0 ;
279 setsockopt(sd, SOL_SOCKET, SO_LINGER, (void *)&lg, sizeof(struct linger)) ;
280 }
281 #endif
282
283 #ifdef SO_REUSEADDR
284 /* Let the address be reused quickly,
285 in case of another connection from the same host on the same port. */
286
287 { int optval = 1;
288 setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) ;
289 }
290 #endif
291
292 return ;
293 }
294
295 /*-------------------------------------------------------------------*/
296 /*! Check if an already active socket is still alive.
297
298 If it is dead, then readcheck will say we can read, but we
299 won't actually get any bytes when we try (using peek mode).
300 Returns 1 if things are OK, 0 if not.
301 ---------------------------------------------------------------------*/
302
tcp_alivecheck(int sd)303 static int tcp_alivecheck( int sd )
304 {
305 int ii ;
306 char bbb[4] ;
307
308 ii = tcp_readcheck(sd,0) ; /* can I read? */
309 if( ii == 0 ) return 1 ; /* can't read is OK */
310 if( ii < 0 ) return 0 ; /* some error is bad */
311 errno = 0 ;
312 ii = tcp_recv( sd , bbb , 1 , MSG_PEEK ) ; /* try to read one byte */
313 if( ii == 1 ) return 1 ; /* if we get it, good */
314 if( errno ) PERROR("tcp_alivecheck") ;
315 return 0 ; /* no data ==> death! */
316 }
317
318 /*------------------------------------------------------------------------*/
319 /*! Open a socket to the given host, to the given TCP port.
320
321 This function is used to "reach out" to a server that is supposed
322 to be listening on the same port.
323 Returns socket id; if -1, some error occured (e.g., nobody listening).
324 --------------------------------------------------------------------------*/
325
tcp_connect(char * host,int port)326 static int tcp_connect( char *host , int port )
327 {
328 int sd , l , q ; socklen_t qq ;
329 struct sockaddr_in sin ;
330 struct hostent *hostp ;
331
332 if( host == NULL || port < 1 ) return -1 ; /* bad inputs */
333
334 #ifdef NIML_DEBUG
335 NI_dpr("Enter tcp_connect: host=%s port=%d\n",host,port) ;
336 #endif
337
338 /** open a socket **/
339
340 sd = socket( AF_INET , SOCK_STREAM , 0 ) ;
341 if( sd == -1 ){ PERROR("tcp_connect(socket)"); return -1; }
342
343 /** set socket options (no delays, large buffers) **/
344
345 #if 0
346 { char *eee=getenv( "NIML_TCP_NAGLE" ) ;
347 if( eee == NULL || toupper(*eee) != 'Y' ){
348 /** disable the Nagle algorithm **/
349 l = 1;
350 setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *)&l, sizeof(int)) ;
351 }
352 }
353 #endif
354
355 /* but large I/O buffers are good */
356
357 #ifdef SOCKET_BUFSIZE
358 q = 0 ; qq = sizeof(int) ; /* 03 Dec 2002: */
359 getsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&q, &qq ) ; /* only modify */
360 if( q < SOCKET_BUFSIZE ){ /* if current buffer */
361 l = SOCKET_BUFSIZE ; /* is too small */
362 setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&l, sizeof(int)) ;
363 }
364 q = 0 ; qq = sizeof(int) ;
365 getsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&q, &qq ) ;
366 if( q < SOCKET_BUFSIZE ){
367 l = SOCKET_BUFSIZE ;
368 setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&l, sizeof(int)) ;
369 }
370 #endif
371
372 /** set port on remote computer **/
373
374 memset( &sin , 0 , sizeof(sin) ) ;
375 sin.sin_family = AF_INET ;
376 sin.sin_port = htons(port) ;
377
378 /** set remote computer IP address from its name **/
379
380 hostp = gethostbyname(host) ;
381 if( hostp == NULL ){
382 PERROR("tcp_connect(gethostbyname)");
383 #ifdef NIML_DEBUG
384 NI_dpr(" tcp_connect: can't gethostbyname(); errno=%d\n",errno);
385 #endif
386 CLOSEDOWN(sd); return -1;
387 }
388 sin.sin_addr.s_addr = ((struct in_addr *)(hostp->h_addr))->s_addr ;
389
390 errno = 0 ;
391 if( connect(sd,(struct sockaddr *)&sin,sizeof(sin)) != 0 ){
392 if( errno != ECONNREFUSED ) PERROR("tcp_connect(connect)") ;
393 #ifdef NIML_DEBUG
394 NI_dpr(" tcp_connect: can't connect(); errno=%d\n",errno);
395 #endif
396 CLOSEDOWN(sd); return -1;
397 }
398
399 #ifdef NIML_DEBUG
400 NI_dpr(" tcp_connect: connected!\n");
401 #endif
402
403 tcp_set_cutoff( sd ) ;
404 return sd ;
405 }
406
407 /*--------------------------------------------------------------------------*/
408 /*! Set up to listen for a connection on a given port.
409
410 This is intended for use by a server, which will wait for some other
411 program to actively connect to this port. There is no security here -
412 connections will be taken from any IP address.
413
414 This function does not actually form the connection. That must be done
415 separately. Whether someone is trying to connect can be checked for
416 with the routine "tcp_readcheck" and then accepted with "tcp_accept".
417
418 The return value is the descriptor for the listening socket.
419 ----------------------------------------------------------------------------*/
420
421 #ifdef MRILIB_MINI
422 #define get_port_numbered(x) (x)
423 #define get_port_numbered(x) (x)
424
get_user_np()425 int get_user_np(){ return 0; }
426 #endif
427
tcp_listen(int port)428 static int tcp_listen( int port )
429 {
430 int sd , l , q ; socklen_t qq ;
431 struct sockaddr_in sin ;
432 char serr[128]={""};
433
434 if( port < 1 ) return -1 ; /* bad input */
435
436 /** open a socket **/
437
438 sd = socket( AF_INET , SOCK_STREAM , 0 ) ;
439 if( sd == -1 ){
440 sprintf(serr,"tcp_listen(socket): (Name %s, Port %d)",
441 get_port_numbered(port), port);
442 PERROR(serr); return -1;
443 }
444
445 /** set socket options (no delays, large buffers) **/
446
447 #if 0
448 { char *eee=getenv( "NIML_TCP_NAGLE" ) ;
449 if( eee == NULL || toupper(*eee) != 'Y' ){
450 /** disable the Nagle algorithm **/
451 l = 1;
452 setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *)&l, sizeof(int)) ;
453 }
454 }
455 #endif
456
457 /* set socket to have large I/O buffers */
458
459 #ifdef SOCKET_BUFSIZE
460 q = 0 ; qq = sizeof(int) ;
461 getsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&q, &qq ) ;
462 if( q < SOCKET_BUFSIZE ){
463 l = SOCKET_BUFSIZE ;
464 setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&l, sizeof(int)) ;
465 }
466 q = 0 ; qq = sizeof(int) ;
467 getsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&q, &qq ) ;
468 if( q < SOCKET_BUFSIZE ){
469 l = SOCKET_BUFSIZE ;
470 setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&l, sizeof(int)) ;
471 }
472 #endif
473
474 /** set port on remote computer **/
475
476 memset( &sin , 0 , sizeof(sin) ) ;
477 sin.sin_family = AF_INET ;
478 sin.sin_port = htons(port) ;
479 sin.sin_addr.s_addr = INADDR_ANY ; /* reader reads from anybody */
480
481 if( bind(sd , (struct sockaddr *)&sin , sizeof(sin)) == -1 ){
482 sprintf(serr,"tcp_listen(bind) (Name %s, Port %d, sd %d)",
483 get_port_numbered(port), port, sd);
484 PERROR(serr); CLOSEDOWN(sd); return -1;
485 }
486
487 if( listen(sd,1) == -1 ){
488 sprintf(serr,"tcp_listen(listen) (Name %s, Port %d)",
489 get_port_numbered(port), port);
490 PERROR(serr); CLOSEDOWN(sd); return -1;
491 }
492
493 tcp_set_cutoff( sd ) ;
494 return sd ;
495 }
496
497 /*--------------------------------------------------------------------------*/
498 /*! Accept incoming connection on a socket.
499
500 Return value is the attached socket (which is not the original socket!).
501 If -1 is returned, some error occured. If the accept works, then the
502 original socket is still open and listening for further attachments.
503 Under many circumstances, you will want to close the original socket
504 immediately. This can be done with CLOSEDOWN(sd), where sd is the
505 input socket.
506
507 If hostname is not NULL, then the char * it points to will be filled
508 with a pointer to the official name of the host that connected.
509
510 If hostaddr is not NULL, then the char * it points to will be filled
511 with a pointer to the Internet address (in 'dot' form) of the host that
512 connected.
513
514 Both the char * pointers returned are from NI_malloc(), and should be
515 NI_free()-d when no longer needed. If they aren't needed at all, just
516 pass in NULL for these arguments.
517
518 Note that this routine will block until somebody connects. You can
519 use tcp_readcheck(sd,0) to see if anyone is waiting to connect before
520 calling this routine.
521
522 However, if someone connects and the IP address isn't on the
523 trusted list, then the connection will be closed immediately.
524 ---------------------------------------------------------------------------*/
525
tcp_accept(int sd,char ** hostname,char ** hostaddr)526 static int tcp_accept( int sd , char **hostname , char **hostaddr )
527 {
528 struct sockaddr_in pin ;
529 int sd_new ; socklen_t addrlen ;
530 struct hostent *hostp ;
531 char *str ;
532
533 /** accept the connection **/
534
535 addrlen = sizeof(pin) ;
536 sd_new = accept( sd , (struct sockaddr *)&pin , &addrlen ) ;
537 if( sd_new == -1 ){ PERROR("tcp_accept"); return -1; }
538
539 /** get dotted form address of connector **/
540
541 str = inet_ntoa( pin.sin_addr ) ;
542
543 if( !NI_trust_host(str) ){
544 fprintf(stderr,"\n** ILLEGAL attempt to connect from host %s\n",str) ;
545 CLOSEDOWN( sd_new ) ;
546 return -1 ;
547 }
548
549 if( hostaddr != NULL ) *hostaddr = NI_strdup(str) ;
550
551 /** get name of connector **/
552
553 if( hostname != NULL ){
554 hostp = gethostbyaddr( (char *) (&pin.sin_addr) ,
555 sizeof(struct in_addr) , AF_INET ) ;
556
557 if( hostp != NULL ) *hostname = NI_strdup(hostp->h_name) ;
558 else *hostname = NI_strdup("UNKNOWN") ; /* bad lookup */
559 }
560
561 tcp_set_cutoff( sd_new ) ; /* let it die quickly, we hope */
562 return sd_new ;
563 }
564
565 /*******************************************************************/
566 /*** Functions to setup a "trusted host" list for TCP/IP accept. ***/
567 /*******************************************************************/
568
569 static int host_num = 0 ; /*!< Number of trusted hosts. */
570 static char ** host_list = NULL ; /*!< IP addresses in dotted form. */
571
572 static char *init_hosts[] = { /*!< Initial list of OK computers */
573 "127.0.0.1" , /* localhost is always OK */
574 "192.168." , /* private class B networks */
575 "128.231.21" /* SSCC/NIMH/NIH/DHHS/USA */
576 } ;
577 #define INIT_NHO (sizeof(init_hosts)/sizeof(char *))
578 #define HSIZE 32
579
580 /*----------------------------------------------------------------*/
581 /*! Return the Internet address (in 'dot' format, as a string)
582 given the name of the host. If NULL is returned, some
583 error occurrrrred. The string is NI_malloc()-ed, and should
584 be NI_free()-ed when no longer needed.
585 ------------------------------------------------------------------*/
586
NI_hostname_to_inet(char * host)587 char * NI_hostname_to_inet( char *host )
588 {
589 struct hostent *hostp ;
590 char * iname = NULL , *str ;
591 int ll ;
592
593 if( host == NULL || host[0] == '\0' ) return NULL ;
594
595 hostp = gethostbyname(host) ; if( hostp == NULL ) return NULL ;
596
597 str = inet_ntoa(*((struct in_addr *)(hostp->h_addr))) ;
598 if( str == NULL || str[0] == '\0' ) return NULL ;
599
600 iname = NI_strdup(str) ; return iname ;
601 }
602
603 /*----------------------------------------------------------------*/
604 /*! Check if hostname is in dotted form.
605 ------------------------------------------------------------------*/
606
hostname_dotted(char * hnam)607 static int hostname_dotted( char *hnam )
608 {
609 int ii, nh ;
610 if( hnam == NULL ) return 0 ;
611 nh = strlen(hnam) ;
612 for( ii=0 ; ii < nh ; ii++ )
613 if( !isdigit(hnam[ii]) && hnam[ii] != '.' ) return 0 ;
614 return 1 ;
615 }
616
617 /*----------------------------------------------------------------*/
618 /*! Add a host to the trusted list (internal version).
619 ------------------------------------------------------------------*/
620
add_trusted_host(char * hnam)621 static void add_trusted_host( char *hnam )
622 {
623 char *hh=NULL ;
624 int ii ;
625
626 if( hnam == NULL || hnam[0] == '\0' ) return ;
627
628 if( !hostname_dotted(hnam) ){ /* not a dotted number */
629 hh = NI_hostname_to_inet( hnam ) ; /* so do a lookup on it */
630 if( hh == NULL ) return ; /* failed? */
631
632 } else if( strlen(hnam) > HSIZE-1 ){ /* something bad? */
633 return ;
634 } else {
635 hh = hnam ; /* store dotted number */
636 }
637
638 host_list = NI_realloc(host_list, char*,sizeof(char *)*(host_num+1)) ;
639 host_list[host_num] = NI_malloc(char, HSIZE) ;
640 strcpy( host_list[host_num] , hh ) ; host_num++ ;
641
642 if( hh != hnam ) NI_free(hh) ;
643 }
644
645 /*--------------------------------------------------------------------------*/
646 /*! Initialize trusted list from the internal table and the environment.
647 ----------------------------------------------------------------------------*/
648
init_trusted_list(void)649 static void init_trusted_list(void)
650 {
651 int ii ;
652 char ename[HSIZE] , *str ;
653
654 if( host_num == 0 ){ /** only execute this once **/
655 host_num = INIT_NHO ;
656 host_list = NI_malloc(char*, sizeof(char *) * INIT_NHO ) ;
657 for( ii=0 ; ii < INIT_NHO ; ii++ ){
658 host_list[ii] = NI_malloc(char, HSIZE) ;
659 strcpy( host_list[ii] , init_hosts[ii] ) ;
660 }
661
662 for( ii=0 ; ii <= 99 ; ii++ ){
663 sprintf(ename,"NIML_TRUSTHOST_%02d",ii) ; str = getenv(ename) ;
664 if( str == NULL && ii <= 9 ){
665 sprintf(ename,"NIML_TRUSTHOST_%1d",ii) ; str = getenv(ename) ;
666 }
667 if( str == NULL && ii <= 9 ){
668 sprintf(ename,"NIML_TRUSTHOST_O%1d",ii) ; str = getenv(ename) ;
669 }
670 if( str != NULL ) add_trusted_host(str) ;
671 }
672
673 for( ii=0 ; ii <= 99 ; ii++ ){
674 sprintf(ename,"AFNI_TRUSTHOST_%02d",ii) ; str = getenv(ename) ;
675 if( str == NULL && ii <= 9 ){
676 sprintf(ename,"AFNI_TRUSTHOST_%1d",ii) ; str = getenv(ename) ;
677 }
678 if( str == NULL && ii <= 9 ){
679 sprintf(ename,"AFNI_TRUSTHOST_O%1d",ii) ; str = getenv(ename) ;
680 }
681 if( str != NULL ) add_trusted_host(str) ;
682 }
683 }
684 return ;
685 }
686
687 /*--------------------------------------------------------------------------*/
688 /*! Externally callable routine to add a host to the trusted list.
689 If call with NULL, will just initialize the default trusted
690 host list.
691 ----------------------------------------------------------------------------*/
692
NI_add_trusted_host(char * hostname)693 void NI_add_trusted_host( char *hostname )
694 {
695 if( host_num == 0 ) init_trusted_list() ;
696 if( hostname == NULL || hostname[0] == '\0' ) return ;
697 add_trusted_host(hostname) ;
698 }
699
700 /*---------------------------------------------------------------------------*/
701 /*! Return 1 if we like hostid, 0 if we don't.
702 -----------------------------------------------------------------------------*/
703
NI_trust_host(char * hostid)704 int NI_trust_host( char *hostid )
705 {
706 int ii ;
707 char *hh = hostid ;
708
709 /* if the trusted list is empty,
710 see if we want to be completely trusting;
711 if not, then initialize the trusted list and then check */
712
713 if( host_num == 0 ){
714 char *eee = getenv("NIML_COMPLETE_TRUST") ;
715 if( eee != NULL && toupper(*eee) == 'Y' ) return 1 ; /* complete trust */
716 init_trusted_list() ;
717 }
718
719 if( hostid == NULL || hostid[0] == '\0' ) return 0 ;
720
721 if( !hostname_dotted(hostid) ){
722 hh = NI_hostname_to_inet(hostid) ; /* will be NI_malloc()-ed */
723 if( hh == NULL ) return 0 ;
724 }
725
726 /* to be trusted, hostid must start with same
727 string as something in the trusted host_list array */
728
729 for( ii=0 ; ii < host_num ; ii++ ){
730 if( strstr(hh,host_list[ii]) == hh ){
731 if( hh != hostid ) NI_free(hh) ;
732 return 1 ;
733 }
734 }
735
736 if( hh != hostid ) NI_free(hh) ;
737 return 0 ;
738 }
739
740 #ifndef DONT_USE_SHM
741 /****************************************************************
742 Routines to manipulate IPC shared memory segments for I/O
743 [adapted from thd_iochan.c, 31 May 2002 -- RWCox]
744 *****************************************************************/
745
746 /*---------------------------------------------------------------*/
747 /*! Convert a string to a key, for IPC operations.
748 Augment sum by port offset value (-np option)
749 -----------------------------------------------------------------*/
750
SHM_string_to_key(char * key_string)751 static key_t SHM_string_to_key( char *key_string )
752 {
753 int ii , sum = get_user_np() ;
754 key_t kk ;
755
756 sum += 987654321 ;
757 if( key_string == NULL ) return (key_t) sum ;
758
759 for( ii=0 ; key_string[ii] != '\0' ; ii++ )
760 sum += ((int)key_string[ii]) << ((ii%3)*8) ;
761
762 kk = (key_t) sum ;
763 #ifdef IPC_PRIVATE
764 if( kk == IPC_PRIVATE || kk <= 0 ) kk = 666 ;
765 #endif
766 return kk ;
767 }
768
769 /*---------------------------------------------------------------*/
770 /*! Get a pre-existing shmem segment.
771 Returns the shmid >= 0 if successful; returns -1 if failure.
772 -----------------------------------------------------------------*/
773
SHM_accept(char * key_string)774 static int SHM_accept( char *key_string )
775 {
776 key_t key ;
777 int shmid ;
778
779 key = SHM_string_to_key( key_string ) ;
780 shmid = shmget( key , 0 , 0777 ) ;
781 return shmid ;
782 }
783
784 /*---------------------------------------------------------------*/
785 /*! Connect to, or create if needed, a shmem segment.
786 Returns the shmid >= 0 if successful; returns -1 if failure.
787 -----------------------------------------------------------------*/
788
SHM_create(char * key_string,int size)789 static int SHM_create( char *key_string , int size )
790 {
791 key_t key ;
792 int shmid ;
793
794 key = SHM_string_to_key( key_string ) ;
795 shmid = shmget( key , size , 0777 | IPC_CREAT ) ;
796 if( shmid < 0 ) PERROR("SHM_create") ;
797 return shmid ;
798 }
799
800 /*---------------------------------------------------------------*/
801 /*! Actually attach to the shmem segment.
802 Returns the pointer to the segment start.
803 NULL is returned if an error occurs.
804 -----------------------------------------------------------------*/
805
SHM_attach(int shmid)806 static char * SHM_attach( int shmid )
807 {
808 char *adr ;
809 adr = (char *) shmat( shmid , NULL , 0 ) ;
810 if( adr == (char *) -1 ){ adr = NULL ; PERROR("SHM_attach") ; }
811 return adr ;
812 }
813
814 /*---------------------------------------------------------------*/
815 /*! Find the size of a shmem segment.
816 Returns -1 if an error occurs.
817 -----------------------------------------------------------------*/
818
SHM_size(int shmid)819 static int SHM_size( int shmid )
820 {
821 int ii ;
822 struct shmid_ds buf ;
823
824 if( shmid < 0 ) return -1 ;
825 ii = shmctl( shmid , IPC_STAT , &buf ) ;
826 if( ii < 0 ){ PERROR("SHM_size") ; return -1 ; }
827 return buf.shm_segsz ;
828 }
829
830 /*---------------------------------------------------------------*/
831 /*! Find the number of attaches to a shmem segment.
832 Returns -1 if an error occurs.
833 -----------------------------------------------------------------*/
834
SHM_nattach(int shmid)835 static int SHM_nattach( int shmid )
836 {
837 int ii ;
838 static struct shmid_ds buf ;
839 char *eee = getenv( "NIML_DNAME" ) ;
840 static int nid=0;
841
842 if( shmid < 0 ) return -1 ;
843 ii = shmctl( shmid , IPC_STAT , &buf ) ;
844 if( ii < 0 ){
845 if( eee != NULL )
846 fprintf(stderr,
847 "SHM_nattach (%s): (shmid=%d, buf.shm_nattach %d, errno %d), trying again!\n"
848 " EACCES %d, EFAULT %d, EINVAL %d, EPERM %d\n",
849 eee, shmid, (int)buf.shm_nattch, errno, EACCES, EFAULT, EINVAL, EPERM) ;
850 NI_sleep(9) ;
851 ii = shmctl( shmid , IPC_STAT , &buf ) ;
852 }
853 if( ii < 0 ){
854 char *ppp ;
855 if( eee != NULL ){
856 ppp = (char *)calloc(1,strlen(eee)+32) ;
857 strcpy(ppp,"SHM_nattach (") ;
858 strcat(ppp,eee) ; strcat(ppp,")") ;
859 } else {
860 ppp = strdup("SHM_nattach") ;
861 }
862 PERROR(ppp);
863 fprintf(stderr,"%s: called shmctl(%x,%x,%p), got %d\n"
864 " (shmid=%d, buf.shm_nattach %d, errno %d)\n",
865 ppp,(unsigned int)shmid, (unsigned int)IPC_STAT, (void *)&buf,
866 ii,
867 shmid, (int)buf.shm_nattch, errno ) ;
868 nid = 0;
869 free((void *)ppp); return -1;
870 } else if( eee != NULL ){
871 if (!nid) {
872 fprintf(stderr,"SHM_nattach (%s): called shmctl(%x,%x,%p), got %d\n"
873 " Similar messages muted until SHM_nattach fails again.\n",
874 eee,
875 (unsigned int)shmid, (unsigned int)IPC_STAT, (void *)&buf,
876 (int)buf.shm_nattch ) ;
877 }
878 ++nid;
879 }
880 return (int)buf.shm_nattch ;
881 }
882
883 /*---------------------------------------------------------------*/
884 /*! Fill a SHMioc struct that has just been attached as an "r".
885 - ioc->id should be non-negative at this point.
886 - return value is 1 if things are good, -1 if not.
887 -----------------------------------------------------------------*/
888
SHM_fill_accept(SHMioc * ioc)889 static int SHM_fill_accept( SHMioc *ioc )
890 {
891 char *bbb ;
892 int jj ;
893
894 if( ioc == NULL || ioc->id < 0 ) return -1 ; /* bad inputs? */
895
896 NI_sleep(2) ; /* wait a bit */
897 bbb = SHM_attach( ioc->id ) ; /* attach it */
898 if( bbb == NULL ) return -1 ; /* can't? quit */
899
900 if( SHM_nattach(ioc->id) != 2 ){ /* 2 processes? */
901 NI_sleep(10) ; /* wait a bit, */
902 if( SHM_nattach(ioc->id) != 2 ){ /* and try again */
903 shmdt( bbb ) ; /* this is bad! */
904 shmctl( ioc->id , IPC_RMID , NULL ) ;
905 ioc->bad = SHM_IS_DEAD ; return -1 ;
906 }
907 }
908
909 jj = SHM_size(ioc->id) ; /* shmbuf size */
910 if( jj <= SHM_HSIZE ){ /* too small? */
911 shmdt( bbb ) ; /* this is bad! */
912 shmctl( ioc->id , IPC_RMID , NULL ) ;
913 ioc->bad = SHM_IS_DEAD ; return -1 ;
914 }
915
916 ioc->shmbuf = bbb ; /* buffer */
917 ioc->shmhead = (int *) bbb ; /* buffer as int */
918
919 ioc->bufsize1 = ioc->shmhead[SHM_SIZE1] ; /* size of buf 1 */
920 ioc->bstart1 = ioc->shmhead + SHM_BSTART1 ; /* start marker 1*/
921 ioc->bend1 = ioc->shmhead + SHM_BEND1 ; /* end marker 1 */
922 ioc->buf1 = ioc->shmbuf + SHM_HSIZE ; /* buffer 1 */
923
924 ioc->bufsize2 = ioc->shmhead[SHM_SIZE2] ; /* size of buf 2 */
925 ioc->bstart2 = ioc->shmhead + SHM_BSTART2 ; /* start marker 2*/
926 ioc->bend2 = ioc->shmhead + SHM_BEND2 ; /* end marker 2 */
927 ioc->buf2 = ioc->buf1 + ioc->bufsize1 ; /* buffer 2 */
928
929 if( jj < SHM_HSIZE+ioc->bufsize1+ioc->bufsize2 ){ /* too small? */
930 shmdt( bbb ) ; /* this is bad! */
931 shmctl( ioc->id , IPC_RMID , NULL ) ;
932 ioc->bad = SHM_IS_DEAD ; return -1 ;
933 }
934
935 ioc->bad = 0 ; return 1 ; /** DONE **/
936 }
937
938 /*---------------------------------------------------------------*/
939 /*! Create a SHMioc struct for use as a 2-way I/O channel, and
940 return a pointer to it. NULL is returned if an error occurs.
941
942 name = "shm:name:size1+size2" to connect a shared memory
943 segment with buffers of length size1 and size2 bytes.
944 The creator process will write to the size1 buffer
945 and read from the size2 buffer. The acceptor
946 process will reverse this.
947 - The size strings can end in 'K' to multiply by 1024,
948 or end in 'M' to multiply by 1024*1024.
949 - If neither size is given, a default value is used.
950 - If only size1 is given, size2=size1.
951
952 mode = "w" to open a new shared memory channel
953 = "r" to log into a channel created by someone else
954
955 The input "name" is limited to a maximum of 127 bytes.
956 -----------------------------------------------------------------*/
957
SHM_init(char * name,char * mode)958 static SHMioc * SHM_init( char *name , char *mode )
959 {
960 SHMioc *ioc ;
961 int do_create , do_accept ;
962 char key[128] , *kend ;
963 int size1=SHM_DEFAULT_SIZE , ii , jj , size2=SHM_DEFAULT_SIZE ;
964
965 /** check if inputs are reasonable **/
966
967 if( name == NULL ||
968 strlen(name) > 127 ||
969 strncmp(name,"shm:",4) != 0 ||
970 mode == NULL ) return NULL ;
971
972 do_create = (*mode == 'w') ; /* writer */
973 do_accept = (*mode == 'r') ; /* reader */
974
975 if( !do_create && !do_accept ) return NULL ;
976
977 /** get keystring (after "shm:") **/
978
979 for( ii=4 ; name[ii] != ':' && name[ii] != '\0' ; ii++ )
980 key[ii-4] = name[ii] ;
981 key[ii-4] = '\0' ;
982
983 /** get size1 (after "shm:name:"), if we stopped at a ':' **/
984
985 if( do_create && name[ii] == ':' && name[ii+1] != '\0' ){
986
987 size1 = strtol( name+ii+1 , &kend , 10 ) ;
988 if( size1 <= 0 ) size1 = SHM_DEFAULT_SIZE ;
989 else {
990 if( *kend == 'K' || *kend == 'k' ){ size1 *= 1024 ; kend++; }
991 else if( *kend == 'M' || *kend == 'm' ){ size1 *= 1024*1024; kend++; }
992 }
993 size2 = size1 ; /* 23 Aug 2002 */
994
995 /** get size2, if we stopped at a + **/
996
997 if( *kend == '+' ){
998 size2 = strtol( kend+1 , &kend , 10 ) ;
999 if( size2 <= 0 ) size2 = SHM_DEFAULT_SIZE ;
1000 else {
1001 if( *kend == 'K' || *kend == 'k' ){ size2 *= 1024 ; kend++; }
1002 else if( *kend == 'M' || *kend == 'm' ){ size2 *= 1024*1024; kend++; }
1003 }
1004 }
1005 }
1006
1007 /** initialize SHMioc **/
1008
1009 ioc = NI_malloc(SHMioc, sizeof(SHMioc) ) ;
1010
1011 strcpy( ioc->name , key ) ; /* save the key name */
1012
1013 /** attach to existing shmem segment **/
1014
1015 if( do_accept ){
1016 ioc->whoami = SHM_ACCEPTOR ;
1017 for( ii=0 ; ii < 4 ; ii++ ){ /* try to find segment */
1018 ioc->id = SHM_accept( key ) ; /* several times */
1019 if( ioc->id >= 0 ) break ; /* works? break out */
1020 NI_sleep(ii+1) ; /* wait 1 millisecond */
1021 }
1022 if( ioc->id < 0 )
1023 ioc->id = SHM_accept( key ) ; /* 1 last try? */
1024
1025 if( ioc->id < 0 ){ /* failed to find segment? */
1026 ioc->bad = SHM_WAIT_CREATE ; /* mark for waiting */
1027 return ioc ; /* and we are DONE for now */
1028 ioc->goodcheck_time = -99 ; /* 23 Nov 2004 */
1029
1030 } else { /* found it? */
1031
1032 jj = SHM_fill_accept( ioc ) ; /* fill struct */
1033
1034 if( jj < 0 ){ /* this is bad */
1035 NI_free(ioc); return NULL;
1036 }
1037
1038 return ioc ; /** DONE **/
1039 ioc->goodcheck_time = -99 ; /* 23 Nov 2004 */
1040 }
1041 }
1042
1043 /** create a new shmem segment **/
1044
1045 if( do_create ){
1046 char *bbb ;
1047
1048 ioc->whoami = SHM_CREATOR ;
1049 ioc->id = SHM_create( key, size1+size2+SHM_HSIZE+4 ) ; /* create it */
1050 if( ioc->id < 0 ){ /* can't? quit */
1051 NI_free(ioc); return NULL;
1052 }
1053 bbb = SHM_attach( ioc->id ) ; /* attach it */
1054 if( bbb == NULL ){ /* can't? quit */
1055 NI_free(ioc); return NULL;
1056 }
1057
1058 ioc->shmbuf = bbb ; /* buffer */
1059 ioc->shmhead = (int *) bbb ; /* buffer as int */
1060
1061 ioc->bufsize1 = ioc->shmhead[SHM_SIZE1] = size1 ; /* size of buf 1 */
1062 ioc->bstart1 = ioc->shmhead + SHM_BSTART1 ; /* start marker 1*/
1063 ioc->bend1 = ioc->shmhead + SHM_BEND1 ; /* end marker 1 */
1064 ioc->buf1 = ioc->shmbuf + SHM_HSIZE ; /* buffer 1 */
1065
1066 ioc->bufsize2 = ioc->shmhead[SHM_SIZE2] = size2 ; /* size of buf 2 */
1067 ioc->bstart2 = ioc->shmhead + SHM_BSTART2 ; /* start marker 2*/
1068 ioc->bend2 = ioc->shmhead + SHM_BEND2 ; /* end marker 2 */
1069 ioc->buf2 = ioc->buf1 + size1 ; /* buffer 2 */
1070
1071 *(ioc->bstart1) = 0 ; /* init markers 1*/
1072 *(ioc->bend1) = size1-1 ;
1073 *(ioc->bstart2) = 0 ; /* init markers 2*/
1074 *(ioc->bend2) = size2-1 ;
1075
1076 NI_sleep(3) ;
1077 jj = SHM_nattach(ioc->id) ; /* # processes */
1078
1079 if( jj < 2 ){
1080 NI_sleep(3) ; jj = SHM_nattach(ioc->id) ;
1081 }
1082
1083 if( jj > 2 ){ /* should not */
1084 shmdt( bbb ) ; /* happen ever */
1085 shmctl( ioc->id , IPC_RMID , NULL ) ;
1086 NI_free(ioc); return NULL;
1087 }
1088
1089 ioc->bad = (jj < 2) /* ready if both */
1090 ? SHM_WAIT_ACCEPT /* processes are */
1091 : 0 ; /* attached to shm */
1092 ioc->goodcheck_time = -99 ; /* 23 Nov 2004 */
1093 return ioc ;
1094 }
1095
1096 return NULL ; /* should never be reached */
1097 }
1098
1099 /*-------------------------------------------------------------------------*/
1100 /*! Check if the shmem segment is alive (has 2 attached processes).
1101 Returns 0 if not alive, 1 if life is happy.
1102 ---------------------------------------------------------------------------*/
1103
SHM_alivecheck(int shmid)1104 static int SHM_alivecheck( int shmid )
1105 {
1106 if( shmid < 0 ) return 0 ;
1107 return (SHM_nattach(shmid) == 2) ;
1108 }
1109
1110 /*------------------------------------------*/
1111 #ifndef NEXTDMS
1112 #define NEXTDMS(dm) MIN(1.1*(dm)+1.01,99.0) /* expanding wait interval */
1113 #endif
1114 /*------------------------------------------*/
1115
1116 /*-------------------------------------------------------------------------*/
1117 /*! Check if the given SHMioc is ready for I/O. If not, wait up to
1118 msec milliseconds to establish the connection to the other end;
1119 if msec < 0, will wait indefinitely. Returns 1 if ready; 0 if not;
1120 -1 if an error occurs. Possible errors are:
1121 + SHMioc was connected, and now has become disconnected
1122 + SHMioc is passed in as NULL
1123 ---------------------------------------------------------------------------*/
1124
SHM_goodcheck(SHMioc * ioc,int msec)1125 static int SHM_goodcheck( SHMioc *ioc , int msec )
1126 {
1127 int ii , jj , ct ;
1128 char *bbb ;
1129
1130 /** check inputs for OK-osity **/
1131
1132 if( ioc == NULL || ioc->bad == SHM_IS_DEAD ) return -1 ;
1133
1134 /** if it was good before, then check if it is still good **/
1135
1136 if( ioc->bad == 0 ){
1137 ct = NI_clock_time() ;
1138 if( ct - ioc->goodcheck_time > 2 ){ /* 23 Nov 2004 */
1139 ii = SHM_alivecheck(ioc->id) ;
1140 ioc->goodcheck_time = ct ;
1141 } else {
1142 ii = 1 ;
1143 }
1144 if( ii <= 0 ){ /* has died */
1145 #ifdef NIML_DEBUG
1146 NI_dpr("++ Shared memory connection %s has gone bad!\n",
1147 ioc->name ) ;
1148 #endif
1149 shmdt( ioc->shmbuf ) ; ioc->bad = SHM_IS_DEAD ;
1150 shmctl( ioc->id , IPC_RMID , NULL ) ; return -1 ;
1151 }
1152 return 1 ;
1153 }
1154
1155 /** wasn't good before, so check if that condition has changed **/
1156
1157 /** shm "r" process waiting for creation by the "w" process **/
1158
1159 if( ioc->bad == SHM_WAIT_CREATE ){
1160 int dms=0 , ms ;
1161
1162 if( msec < 0 ) msec = 999999999 ; /* a long time (11+ days) */
1163 for( ms=0 ; ms < msec ; ms += dms ){
1164 ioc->id = SHM_accept( ioc->name ) ; /* try to attach to shmem segment */
1165 if( ioc->id >= 0 ) break ; /* works? break out */
1166 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; NI_sleep(dms) ;
1167 }
1168 if( ioc->id < 0 ) /* one last try? */
1169 ioc->id = SHM_accept( ioc->name ) ;
1170
1171 if( ioc->id >= 0 ){ /* found it? */
1172 jj = SHM_fill_accept( ioc ) ; /* fill struct */
1173 if( jj < 0 ) return -1 ; /* this is bad */
1174 ioc->bad = 0 ; /* mark as ready */
1175 return 1 ;
1176 }
1177 return 0 ;
1178 }
1179
1180 /** shmem "w" process waiting for "r" process to attach */
1181
1182 else if( ioc->bad == SHM_WAIT_ACCEPT ){
1183 int dms=0 , ms ;
1184
1185 if( msec < 0 ) msec = 999999999 ; /* a long time (11+ days) */
1186 for( ms=0 ; ms < msec ; ms += dms ){
1187 if( SHM_nattach(ioc->id) > 1 ){ ioc->bad = 0 ; return 1 ; }
1188 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; NI_sleep(dms) ;
1189 }
1190 if( SHM_nattach(ioc->id) > 1 ){ ioc->bad = 0 ; return 1 ; }
1191 return 0 ;
1192 }
1193
1194 return 0 ; /* should never be reached */
1195 }
1196
1197 /*-----------------------------------------------------------------------*/
1198 /*! Close a SHMioc. Note that this will free what ioc points to.
1199 -------------------------------------------------------------------------*/
1200
SHM_close(SHMioc * ioc)1201 static void SHM_close( SHMioc *ioc )
1202 {
1203 if( ioc == NULL ) return ;
1204
1205 if( ioc->id >= 0 && ioc->bad != SHM_IS_DEAD ){
1206 shmdt( ioc->shmbuf ) ; /* detach */
1207 shmctl( ioc->id , IPC_RMID , NULL ) ; /* delete */
1208 ioc->bad = SHM_IS_DEAD ; /* leave for dead */
1209 }
1210
1211 NI_free(ioc) ; return ;
1212 }
1213
1214 /*---------------------------------------------------------------------------*/
1215 /*! Check if the SHMioc is ready to have data read out of it.
1216 If not, the routine will wait up to msec milliseconds for data to be
1217 available. If msec < 0, this routine will wait indefinitely.
1218 For shmem segments, the return value is how many bytes can be
1219 read (0 if none are available).
1220 -1 will be returned if some unrecoverable error is detected.
1221 -----------------------------------------------------------------------------*/
1222
SHM_readcheck(SHMioc * ioc,int msec)1223 static int SHM_readcheck( SHMioc *ioc , int msec )
1224 {
1225 int ii , ct ;
1226 int nread , dms=0 , ms ;
1227 int *bstart, *bend , bsize ; /* for the chosen buffer */
1228
1229 /** check if the SHMioc is good **/
1230
1231 ct = NI_clock_time() ;
1232 if( ct - ioc->goodcheck_time > 2 ){ /* 23 Nov 2004 */
1233 ii = SHM_goodcheck(ioc,0) ;
1234 ioc->goodcheck_time = ct ;
1235 if( ii <= 0 ){ /* not good yet */
1236 ii = SHM_goodcheck(ioc,msec) ; /* so wait for it to get good */
1237 if( ii <= 0 ) return ii ; /* if still not good, exit */
1238 }
1239 } else if( ioc->bad ) return 0 ;
1240
1241 /** choose buffer from which to read **/
1242
1243 switch( ioc->whoami ){
1244
1245 default: return -1 ; /* should never happen */
1246
1247 case SHM_ACCEPTOR:
1248 bstart = ioc->bstart1 ;
1249 bend = ioc->bend1 ;
1250 bsize = ioc->bufsize1 ;
1251 break ;
1252
1253 case SHM_CREATOR:
1254 bstart = ioc->bstart2 ;
1255 bend = ioc->bend2 ;
1256 bsize = ioc->bufsize2 ;
1257 break ;
1258 }
1259
1260 /** must loop and wait **/
1261
1262 if( msec < 0 ) msec = 999999999 ; /* a long time (11+ days) */
1263
1264 /** Compute the number of readable bytes into nread. **/
1265
1266 for( ms=0 ; ms < msec ; ms += dms ){
1267 nread = (*bend - *bstart + bsize + 1) % bsize ;
1268 if( nread > 0 ) return nread ;
1269 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; NI_sleep(dms) ;
1270 ii = SHM_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
1271 }
1272 nread = (*bend - *bstart + bsize + 1) % bsize ;
1273 if( nread > 0 ) return nread ;
1274 return 0 ;
1275 }
1276
1277 /*---------------------------------------------------------------------------*/
1278 /*! Check if the SHMioc is ready to have data written into it.
1279 If not, the routine will wait up to msec milliseconds for writing to
1280 be allowable. If msec < 0, this routine will wait indefinitely.
1281 The return value is the number of bytes that can be sent (0 if none,
1282 positive if some). -1 will be returned if some unrecoverable error is
1283 detected.
1284 -----------------------------------------------------------------------------*/
1285
SHM_writecheck(SHMioc * ioc,int msec)1286 static int SHM_writecheck( SHMioc *ioc , int msec )
1287 {
1288 int ii ;
1289 int nread , dms=0 , ms , nwrite ;
1290 int *bstart, *bend , bsize ; /* for the chosen buffer */
1291
1292 /** check if the SHMioc is good **/
1293
1294 ii = SHM_goodcheck(ioc,0) ;
1295 if( ii == -1 ) return -1 ; /* some error */
1296 if( ii == 0 ){ /* not good yet */
1297 ii = SHM_goodcheck(ioc,msec) ; /* so wait for it to get good */
1298 if( ii <= 0 ) return ii ; /* if still not good, exit */
1299 }
1300
1301 /** choose buffer to which to write **/
1302
1303 switch( ioc->whoami ){
1304
1305 default: return -1 ; /* should never happen */
1306
1307 case SHM_ACCEPTOR:
1308 bstart = ioc->bstart2 ;
1309 bend = ioc->bend2 ;
1310 bsize = ioc->bufsize2 ;
1311 break ;
1312
1313 case SHM_CREATOR:
1314 bstart = ioc->bstart1 ;
1315 bend = ioc->bend1 ;
1316 bsize = ioc->bufsize1 ;
1317 break ;
1318 }
1319
1320 if( msec < 0 ) msec = 999999999 ; /* a long time (11+ days) */
1321
1322 for( ms=0 ; ms < msec ; ms += dms ){
1323 nread = (*bend - *bstart + bsize + 1) % bsize ;
1324 nwrite = bsize - 1 - nread ;
1325 if( nwrite > 0 ) return nwrite ;
1326 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; NI_sleep(dms) ;
1327 ii = SHM_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
1328 }
1329 nread = (*bend - *bstart + bsize + 1) % bsize ;
1330 nwrite = bsize - 1 - nread ;
1331 if( nwrite > 0 ) return nwrite ;
1332 return 0 ;
1333 }
1334
1335 /*----------------------------------------------------------------------------*/
1336 /*! Send nbytes of data from buffer down the SHMioc. Return value is
1337 the number of bytes actually sent, or is -1 if some error occurs.
1338 ------------------------------------------------------------------------------*/
1339
SHM_send(SHMioc * ioc,char * buffer,int nbytes)1340 static int SHM_send( SHMioc *ioc , char *buffer , int nbytes )
1341 {
1342 int ii ;
1343 int nread,nwrite , ebot,etop ;
1344 int *bstart, *bend , bsize ; /* for the chosen buffer */
1345 char *buf ;
1346
1347 /** check for reasonable inputs **/
1348
1349 if( ioc == NULL || ioc->bad ||
1350 buffer == NULL || nbytes < 0 ) return -1 ;
1351
1352 if( nbytes == 0 ) return 0 ; /* stupid user */
1353
1354 ii = SHM_goodcheck(ioc,1) ; /* can't send if it ain't good */
1355 if( ii <= 0 ) return ii ;
1356
1357 ii = SHM_writecheck(ioc,1) ; /* is something is writeable? */
1358 if( ii <= 0 ) return ii ;
1359
1360 /** choose buffer in which to write **/
1361
1362 switch( ioc->whoami ){
1363
1364 default: return -1 ; /* should never happen */
1365
1366 case SHM_ACCEPTOR:
1367 bstart = ioc->bstart2 ;
1368 bend = ioc->bend2 ;
1369 bsize = ioc->bufsize2 ;
1370 buf = ioc->buf2 ;
1371 break ;
1372
1373 case SHM_CREATOR:
1374 bstart = ioc->bstart1 ;
1375 bend = ioc->bend1 ;
1376 bsize = ioc->bufsize1 ;
1377 buf = ioc->buf1 ;
1378 break ;
1379 }
1380
1381 /** write into the circular buffer, past "bend" **/
1382
1383 nread = ( *bend - *bstart + bsize + 1 ) % bsize; /* amount readable */
1384 nwrite = bsize - 1 - nread ; /* amount writeable */
1385 if( nwrite <= 0 ) return 0 ; /* can't write! */
1386
1387 if( nwrite > nbytes ) nwrite = nbytes ; /* how much to write */
1388
1389 ebot = *bend+1 ; if( ebot >= bsize ) ebot = 0 ; /* start at ebot */
1390 etop = ebot+nwrite-1 ; /* end at etop */
1391
1392 if( etop < bsize ){ /* 1 piece to copy */
1393 memcpy( buf + ebot, buffer, nwrite ) ; /* copy data */
1394 *bend = etop ; /* change bend */
1395 } else { /* 2 pieces to copy */
1396 int nn = bsize - ebot ; /* size of piece 1 */
1397 memcpy( buf + ebot, buffer , nn ) ; /* copy piece 1 */
1398 memcpy( buf , buffer+nn, nwrite-nn ) ; /* copy piece 2 */
1399 *bend = nwrite-nn-1 ; /* change bend */
1400 }
1401 return nwrite ;
1402 }
1403
1404 /*----------------------------------------------------------------------------*/
1405 /*! Send (exactly) nbytes of data from the buffer down the SHMioc. The only
1406 difference between this and SHM_send is that this function will not
1407 return until all the data is sent, even if it takes forever.
1408 Under these circumstances, it would be good if the reader process is
1409 still working.
1410 ------------------------------------------------------------------------------*/
1411
SHM_sendall(SHMioc * ioc,char * buffer,int nbytes)1412 static int SHM_sendall( SHMioc *ioc , char *buffer , int nbytes )
1413 {
1414 int ii , ntot=0 , dms=0 ;
1415
1416 /** check for reasonable inputs **/
1417
1418 if( ioc == NULL || ioc->bad ||
1419 buffer == NULL || nbytes < 0 ) return -1 ;
1420
1421 if( nbytes == 0 ) return 0 ;
1422
1423 while(1){
1424 ii = SHM_send( ioc , buffer+ntot , nbytes-ntot ); /* send what's left */
1425 if( ii == -1 ) return -1 ; /* an error!? */
1426
1427 if( ii == 0 ){ /* nothing sent? */
1428 dms = NEXTDMS(dms) ;
1429 } else { /* sent something! */
1430 ntot += ii ; /* total sent so far */
1431 if( ntot >= nbytes ) return nbytes ; /* all done!? */
1432 dms = 1 ;
1433 }
1434
1435 NI_sleep(dms) ; /* wait a bit */
1436 }
1437 return -1 ; /* should never be reached */
1438 }
1439
1440 /*----------------------------------------------------------------------------*/
1441 /*! Read up to nbytes of data from the SHMioc, into buffer. Returns the
1442 number of bytes actually read.
1443 This may be less than nbytes (may even be 0). If an error occurs, -1 is
1444 returned.
1445 ------------------------------------------------------------------------------*/
1446
SHM_recv(SHMioc * ioc,char * buffer,int nbytes)1447 static int SHM_recv( SHMioc *ioc , char *buffer , int nbytes )
1448 {
1449 int *bstart, *bend , bsize ; /* for the chosen buffer */
1450 char *buf ;
1451 int nread, sbot,stop , ii ;
1452
1453 /** check for reasonable inputs **/
1454
1455 if( ioc == NULL || ioc->bad ||
1456 buffer == NULL || nbytes < 0 ) return -1 ;
1457
1458 if( nbytes == 0 ) return 0 ;
1459
1460 ii = SHM_goodcheck(ioc,1) ;
1461 if( ii <= 0 ) return ii ;
1462
1463 /** choose buffer from which to read **/
1464
1465 switch( ioc->whoami ){
1466
1467 default: return -1 ; /* should never happen */
1468
1469 case SHM_ACCEPTOR:
1470 bstart = ioc->bstart1 ;
1471 bend = ioc->bend1 ;
1472 bsize = ioc->bufsize1 ;
1473 buf = ioc->buf1 ;
1474 break ;
1475
1476 case SHM_CREATOR:
1477 bstart = ioc->bstart2 ;
1478 bend = ioc->bend2 ;
1479 bsize = ioc->bufsize2 ;
1480 buf = ioc->buf2 ;
1481 break ;
1482 }
1483
1484 /** read from the circular buffer, starting at bstart **/
1485
1486 nread = ( *bend - *bstart + bsize + 1 ) % bsize ; /* readable amount */
1487 if( nread <= 0 ) return 0 ; /* nothing!? */
1488 if( nread > nbytes ) nread = nbytes ; /* amount to read */
1489
1490 sbot = *bstart ; stop = sbot + nread-1 ; /* from sbot to stop */
1491
1492 if( stop < bsize ){ /* 1 piece to copy */
1493 memcpy( buffer, buf+sbot, nread ) ; /* copy the data */
1494 *bstart = (stop+1) % bsize ; /* move bstart up */
1495 } else { /* 2 pieces to copy */
1496 int nn = bsize - sbot ; /* size of piece 1 */
1497 memcpy( buffer , buf + sbot, nn ) ; /* copy piece 1 */
1498 memcpy( buffer+nn, buf , nread-nn ) ; /* copy piece 2 */
1499 *bstart = nread-nn ; /* move bstart up */
1500 }
1501 return nread ;
1502 }
1503 #endif /* DONT_USE_SHM */
1504
1505 /*******************************************************************/
1506 /*** Functions to read/write from NI_streams (files or sockets). ***/
1507 /*** These functions use the tcp_ and shm_ functions above to do ***/
1508 /*** most of the real work. ***/
1509 /*******************************************************************/
1510
1511 /*-------------------------------------------------------------------------*/
1512 /*! Open a NIML input or output stream, and return a pointer to it.
1513
1514 - NULL is returned if an error occurs.
1515 - Otherwise, you can read and write data using NI_stream_read() and
1516 NI_stream_write().
1517 - Buffered input is also available using NI_stream_readbuf() to read
1518 data from an internal buffer. The advantage of buffered input is
1519 that it will return the number of bytes requested (waiting, if needed),
1520 rather than just the number available at that moment.
1521
1522 Several different types of streams are available. The first two
1523 ("tcp:" and "shm:") are for 2-way interprocess communication.
1524 The later ones ("file:", "str:", "http:", "ftp:", and "fd:") are
1525 for 1-way communication, either to read bytes or to write them.
1526 The formats for the "name" input are described below:
1527
1528 name = "tcp:host:port" to connect a socket to system "host"
1529 on the given port number. One process should open
1530 in "w" mode and one in "r" mode.
1531
1532 name = "shm:keyname:size1+size2" to connect to a shared memory
1533 segment created with "keyname" for the ID and with
1534 I/O buffer sizes of size1 ("w" process to "r" process)
1535 and size2 ("r" process to "w" process).
1536 - Like tcp: streams, one process should open with "w" and the
1537 other with "r".
1538 - The "size" strings can end in 'K' to multiply by 1024,
1539 or end in 'M' to multiply by 1024*1024.
1540 - If neither size is given, a default value is used.
1541 - If only size1 is given, size2=size1 (symmetric stream).
1542 - The total size of the shared memory segment will be
1543 size1+size2+36 bytes. (Some systems put an upper limit
1544 on this size.)
1545 - "keyname" is a string used to identify this shared memory segment
1546 - If you are communicating a lot of data between 2 processes on the
1547 same system, shm: streams are usually much faster than tcp: streams.
1548 - Also see NI_stream_reopen() for a way to open a tcp: stream and then
1549 re-open it to another tcp: port or to be a shm: stream.
1550
1551 name = "file:filename" to open a file for I/O.
1552 - For this type of name ONLY, you can use "a" as the mode string to
1553 indicate that you want to append to the file if it already exists.
1554
1555 name = "str:" to read/write data from/to a string
1556
1557 name = "http://hostname/filename" to read data from a Web server
1558 name = "ftp://hostname/filename" to read data from an FTP server
1559 - The data for these types is transferred all at once from
1560 the remote server and stored in a memory buffer (much like
1561 the str: stream type).
1562 - Data can be read from this buffer using NI_stream_read().
1563 - When the stream is closed, the buffer is NI_free()-ed.
1564
1565 name = "fd:integer" to read or write data from a pre-opened
1566 file descriptor (returned by the open() function).
1567 - For example, "fd:1" is used to write to stdout directly.
1568 - When an "fd:" stream is closed, nothing is actually done;
1569 closing the descriptor is the responsibility of the application.
1570 - Descriptors 0,1,2 use stdin, stdout, and stderr, respectively.
1571 - All other descriptors use fdopen() to open a FILE stream
1572 and then treat the result like file:. This means that if
1573 the descriptor comes from fileno() on a previously opened
1574 FILE stream, you will have trouble if you mix I/O to this
1575 stream with NI_stream_read()/NI_stream_write().
1576 - You can use "stdin:", "stdout:", or "stderr:" as synonyms
1577 for "fd:0", "fd:1", and "fd:2".
1578
1579 The formats for the "mode" input are described below:
1580
1581 mode = "w" to open a stream for writing
1582 - tcp: host must be specified ("w" is for a tcp client).
1583 - shm: keyname determines the ID of the segment to create
1584 (which can be attached to by a shm: "r" process).
1585 - file: filename is opened in write mode (and will be
1586 overwritten if already exists).
1587 - str: data will be written to a buffer in the NI_stream
1588 struct; you can later access this buffer with the
1589 function NI_stream_getbuf(), and clear it with
1590 NI_stream_clearbuf().
1591 - You can't open "fd:0" (stdin) for reading
1592 - You can't open "http:" or "ftp:" streams for writing.
1593 - "a" can be used for "file:" ONLY to append to a file.
1594
1595 mode = "r" to open a stream for reading
1596 - tcp: host is ignored (but must be present);
1597 ("r" is for a tcp server).
1598 - shm: keyname determines the ID of the segment to attach to
1599 (which must be created by a shm: "w" process).
1600 - file: filename is opened in read mode.
1601 - str: characters after the colon are the source of
1602 the input data (will be copied to internal buffer);
1603 OR, you can later set the internal buffer string
1604 later with function NI_stream_setbuf().
1605 - You can't open "fd:1" or "fd:2" (stdout or stderr) for reading.
1606 - ftp:/http: The remote files are fetched and loaded into
1607 memory. After that, these streams operate pretty
1608 much the same as str: streams for reading.
1609
1610 For a file:, fd:, or str: stream, you can either read from or write to
1611 the stream, but not both, depending on how you opened it ("r" or "w").
1612 For a tcp: or shm: stream, once it is connected, you can both read and write.
1613 The asymmetry in tcp: and shm: streams only comes at the opening (one process
1614 must make the call using "w" and one must listen for the call using "r").
1615
1616 The inputs "host" (for tcp:) and "filename" (for file:) are limited to a
1617 maximum of 127 bytes. For str:, there is no limit for the "r" stream
1618 (but clearly you can't have any NUL bytes in there). For shm:, "keyname"
1619 is limited to 127 bytes also.
1620
1621 Since opening a socket or shared memory segment requires sychronizing
1622 two processes, you can't read or write to a tcp: or shm: stream
1623 immediately. Instead you have to check if it is "good" first. This
1624 can be done using the function NI_stream_goodcheck().
1625
1626 After a tcp: "r" stream is good, then the string ns->name
1627 contains the IP address of the connecting host, in "dot" form
1628 (e.g., "201.202.203.204"); here, "ns" is the NI_stream returned
1629 by this routine.
1630 - You can use the NI_add_trusted_host() function
1631 to set a list of IP addresses from which the NIML library will accept
1632 connections.
1633 - Systems not on the trusted list will have their sockets closed
1634 immediately after the connection is accepted. Nothing will be read
1635 from these sockets.
1636
1637 For a file: stream, ns->name contains the filename.
1638 ---------------------------------------------------------------------------*/
1639
NI_stream_open(char * name,char * mode)1640 NI_stream NI_stream_open( char *name , char *mode )
1641 {
1642 NI_stream_type *ns ;
1643 int do_create , do_accept ;
1644 int ni_bufsize = NI_BUFSIZE ; /* 21 Nov 2007 */
1645
1646 /** perhaps initialize debug output **/
1647
1648 #ifdef NIML_DEBUG
1649 if( dfp == NULL ){
1650 char *eee = getenv("NIML_DEBUG") ;
1651 if( eee != NULL ){
1652 dfp = (strcmp(eee,"stderr")==0) ? stderr : fopen(eee,"w") ;
1653 if( dfp == NULL ){ dfp = stderr; eee = "stderr [defaulted]"; }
1654 fprintf(stderr,"NIML: debug output to %s\n",eee) ;
1655 }
1656 }
1657 #endif
1658
1659 #ifdef NIML_DEBUG
1660 NI_malloc_enable_tracking() ;
1661 #endif
1662
1663 /** check if inputs are reasonable **/
1664
1665 if( NI_strlen(name) < 4 ) return NULL ;
1666
1667 if( mode == NULL ) return NULL ;
1668
1669 do_create = (*mode == 'w' || *mode == 'a') ;
1670 do_accept = (*mode == 'r') ;
1671
1672 if( !do_create && !do_accept ) return NULL ;
1673
1674 if( ! atexit_is_setup ){ /* 22 Apr 2005 */
1675 atexit(atexit_open_streams) ; atexit_is_setup = 1 ;
1676 }
1677
1678 /* 21 Nov 2007: alter default buffer size? */
1679
1680 { char *eee ; int bbb ;
1681 eee = getenv( "AFNI_NIML_BUFSIZE" ) ;
1682 if( eee == NULL ) eee = getenv( "NIML_BUFSIZE" ) ;
1683 if( eee == NULL ) eee = getenv( "BUFSIZE") ;
1684 if( eee != NULL ){
1685 bbb = (int)strtod(eee,NULL) ;
1686 if( bbb > ni_bufsize ) ni_bufsize = bbb ;
1687 }
1688 }
1689
1690 /************************************/
1691 /***** deal with TCP/IP sockets *****/
1692
1693 if( strncmp(name,"tcp:",4) == 0 ){
1694 char host[256] , *hend ;
1695 int port=-1 , ii , jj ;
1696
1697 if( NI_strlen(name) > 127 ) return NULL ;
1698
1699 /** find "host" substring **/
1700
1701 hend = strstr( name+4 , ":" ) ;
1702 if( hend == NULL || hend-name > 255 ) return NULL ;
1703
1704 for( ii=4 ; name[ii] != ':' ; ii++ ) host[ii-4] = name[ii] ;
1705 host[ii-4] = '\0' ;
1706
1707 /** get "port" number **/
1708
1709 port = strtol( name+ii+1 , NULL , 10 ) ;
1710 if( port <= 0 ) return NULL ;
1711
1712 /** initialize NI_stream_type output struct **/
1713
1714 ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
1715
1716 ns->type = NI_TCP_TYPE; /* what kind is this? */
1717 ns->port = port ; /* save the port # */
1718 ns->nbuf = 0 ; /* buffer is empty */
1719 ns->npos = 0 ; /* scan starts at 0 */
1720 ns->b64_numleft = 0 ;
1721
1722 ns->buf = NI_malloc(char, ni_bufsize) ;
1723 ns->bufsize = ni_bufsize ;
1724 ns->name[0] = '\0' ;
1725 NI_strncpy(ns->orig_name,name,256) ; /* 23 Aug 2002 */
1726
1727 ns->bin_thresh = -1 ; /* write in text mode */
1728
1729 /* 02 Jan 2004: setup SIGURG handler for OOB data reception. */
1730
1731 if( !sigurg ){ signal(SIGURG,tcp_sigurg_handler); sigurg = 1; }
1732
1733 /** attach to incoming call "r" **/
1734
1735 if( do_accept ){
1736 ns->io_mode = NI_INPUT_MODE ;
1737 ns->sd = tcp_listen( port ) ; /* set up to listen */
1738 if( ns->sd < 0 ){ /* error? must die! */
1739 NI_free(ns->buf); NI_free(ns); return NULL;
1740 }
1741 ns->bad = TCP_WAIT_ACCEPT ; /* not connected yet */
1742 ii = tcp_readcheck(ns->sd,1) ; /* see if ready */
1743 if( ii > 0 ){ /* if socket ready: */
1744 jj = tcp_accept( ns->sd , NULL,&hend ) ; /* accept connection */
1745 if( jj >= 0 ){ /* if accept worked */
1746 CLOSEDOWN( ns->sd ) ; /* close old socket */
1747 NI_strncpy(ns->name,hend,256) ; /* put IP into name */
1748 NI_free(hend); ns->bad = 0; ns->sd = jj ; /* and ready to go! */
1749 fcntl( ns->sd, F_SETOWN, (int)getpid() ) ; /* 02 Jan 2004 */
1750 }
1751 }
1752
1753 add_open_stream(ns) ; /* 02 Jan 2004 */
1754 ns->goodcheck_time = -99 ; /* 23 Nov 2004 */
1755 return ns ;
1756 }
1757
1758 /** place an outgoing call "w" **/
1759
1760 if( do_create ){
1761 struct hostent *hostp ;
1762 ns->io_mode = NI_OUTPUT_MODE ;
1763 hostp = gethostbyname(host) ; /* lookup host on net */
1764 if( hostp == NULL ){ /* fails? must die! */
1765 NI_free(ns->buf); NI_free(ns); return NULL;
1766 }
1767 ns->sd = tcp_connect( host , port ) ; /* connect to host */
1768 ns->bad = (ns->sd < 0) ? TCP_WAIT_CONNECT : 0 ; /* fails? must wait */
1769 NI_strncpy(ns->name,host,256) ; /* save the host name */
1770 if( ns->sd >= 0 )
1771 fcntl( ns->sd, F_SETOWN, (int)getpid() ) ; /* 02 Jan 2004 */
1772
1773 add_open_stream(ns) ; /* 02 Jan 2004 */
1774 ns->goodcheck_time = -99 ; /* 23 Nov 2004 */
1775 return ns ;
1776 }
1777 return NULL ; /* should never be reached */
1778 }
1779
1780 #ifndef DONT_USE_SHM
1781 /*********************************************/
1782 /***** deal with shared memory transport *****/
1783
1784 if( strncmp(name,"shm:",4) == 0 ){
1785 SHMioc *ioc ;
1786
1787 if( *mode == 'a' ) mode = "w" ;
1788 ioc = SHM_init( name , mode ) ; /* open segment */
1789 if( ioc == NULL ) return NULL ; /* this is bad bad bad */
1790
1791 /** initialize NI_stream_type output **/
1792
1793 ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
1794
1795 ns->type = NI_SHM_TYPE; /* what kind is this? */
1796 ns->nbuf = 0 ; /* buffer is empty */
1797 ns->npos = 0 ; /* scan starts at 0 */
1798 ns->io_mode = do_create ? NI_OUTPUT_MODE
1799 : NI_INPUT_MODE ;
1800 ns->bad = 0 ;
1801 ns->shmioc = ioc ;
1802 ns->b64_numleft = 0 ;
1803
1804 ns->buf = NI_malloc(char, ni_bufsize) ;
1805 ns->bufsize = ni_bufsize ;
1806
1807 NI_strncpy( ns->name , name , 256 ) ;
1808
1809 NI_strncpy(ns->orig_name,name,256) ; /* 23 Aug 2002 */
1810
1811 add_open_stream(ns) ; /* 02 Jan 2004 */
1812 ns->goodcheck_time = -99 ; /* 23 Nov 2004 */
1813 return ns ;
1814 }
1815 #endif /* DONT_USE_SHM */
1816
1817 /**********************************/
1818 /***** deal with simple files *****/
1819
1820 if( strncmp(name,"file:",5) == 0 ){
1821
1822 char *fname = name+5 , *fmode ;
1823 FILE *fp ;
1824
1825 if( NI_strlen(name) > 255 || NI_strlen(fname) < 1 ) return NULL ;
1826
1827 if( *mode == 'a' ) fmode = "ab" ;
1828 else fmode = do_create ? (char *)"wb" : (char *)"rb" ;
1829 fp = fopen( fname , fmode ) ;
1830
1831 if( fp == NULL ) return NULL ;
1832
1833 /** initialize NI_stream_type output **/
1834
1835 ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
1836
1837 ns->type = NI_FILE_TYPE; /* what kind is this? */
1838 ns->nbuf = 0 ; /* buffer is empty */
1839 ns->npos = 0 ; /* scan starts at 0 */
1840 ns->fp = fp ;
1841 ns->io_mode = do_create ? NI_OUTPUT_MODE
1842 : NI_INPUT_MODE ;
1843 ns->bad = 0 ;
1844 ns->b64_numleft = 0 ;
1845
1846 ns->bufsize = do_create ? 16 : ni_bufsize ;
1847 ns->buf = NI_malloc(char, ns->bufsize) ;
1848
1849 NI_strncpy( ns->name , fname , 256 ) ;
1850
1851 NI_strncpy(ns->orig_name,name,256) ; /* 23 Aug 2002 */
1852
1853 if( ns->io_mode == NI_INPUT_MODE ) /* save the file size */
1854 ns->fsize = NI_filesize( fname ) ; /* if we are reading */
1855 else
1856 ns->fsize = -1 ;
1857
1858 add_open_stream(ns) ; /* 02 Jan 2004 */
1859 ns->goodcheck_time = -99 ; /* 23 Nov 2004 */
1860 return ns ;
1861 }
1862
1863 /********************************************************************/
1864 /***** fd: very similar to a file, but we don't have to open it *****/
1865
1866 if( strncmp(name,"stdin:" ,6) == 0 ) name = "fd:0" ; /* 25 Mar 2003 */
1867 else if( strncmp(name,"stdout:",7) == 0 ) name = "fd:1" ;
1868 else if( strncmp(name,"stderr:",7) == 0 ) name = "fd:2" ;
1869
1870 if( strncmp(name,"fd:",3) == 0 ){
1871 int fd=-1 ; FILE *fp ;
1872
1873 sscanf(name+3,"%d",&fd) ;
1874 if( fd < 0 ) return NULL ; /* bad integer */
1875
1876 switch( fd ){
1877 default:
1878 fp = fdopen( fd , do_create ? "wb" : "rb" ) ;
1879 if( fp == NULL ) return NULL ;
1880 break ;
1881
1882 case 0:
1883 fp = stdin ;
1884 if( do_create ) return NULL ;
1885 break ;
1886
1887 case 1:
1888 fp = stdout ;
1889 if( !do_create ) return NULL ;
1890 break ;
1891
1892 case 2:
1893 fp = stderr ;
1894 if( !do_create ) return NULL ;
1895 break ;
1896 }
1897
1898 /** initialize NI_stream_type output **/
1899
1900 ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
1901
1902 ns->type = NI_FD_TYPE; /* what kind is this? */
1903 ns->nbuf = 0 ; /* buffer is empty */
1904 ns->npos = 0 ; /* scan starts at 0 */
1905 ns->fp = fp ;
1906 ns->io_mode = do_create ? NI_OUTPUT_MODE
1907 : NI_INPUT_MODE ;
1908 ns->bad = 0 ;
1909 ns->b64_numleft = 0 ;
1910
1911 ns->bufsize = do_create ? 16 : ni_bufsize ;
1912 ns->buf = NI_malloc(char, ns->bufsize) ;
1913
1914 NI_strncpy( ns->name , name , 256 ) ;
1915
1916 NI_strncpy(ns->orig_name,name,256) ; /* 23 Aug 2002 */
1917
1918 ns->fsize = -1 ;
1919
1920 add_open_stream(ns) ; /* 02 Jan 2004 */
1921 ns->goodcheck_time = -99 ; /* 23 Nov 2004 */
1922 return ns ;
1923 }
1924
1925 /*********************************/
1926 /***** str: string array I/O *****/
1927
1928 if( strncmp(name,"str:",4) == 0 ){
1929
1930 int nn = NI_strlen(name+4) ; /* may be 0 */
1931
1932 ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
1933
1934 ns->type = NI_STRING_TYPE; /* what kind is this? */
1935 ns->io_mode = do_create ? NI_OUTPUT_MODE
1936 : NI_INPUT_MODE ;
1937 ns->bad = 0 ;
1938 ns->npos = 0 ; /* scan starts at 0 */
1939 ns->b64_numleft = 0 ;
1940
1941 /* Note that bufsize == nbuf+1 for str:
1942 This is because we don't count the terminal NUL
1943 in nbuf (number of readable bytes),
1944 but do count it in bufsize (size of the buf array) */
1945
1946 if( do_accept ){ /* read from stuff after str: */
1947 ns->nbuf = nn ;
1948 ns->bufsize = nn+1 ;
1949 ns->buf = NI_malloc(char, nn+1) ;
1950 strcpy(ns->buf,name+4) ;
1951 } else { /* write to a string */
1952 ns->nbuf = 0 ;
1953 ns->bufsize = 1 ;
1954 ns->buf = NI_malloc(char, 1) ; /* 1 byte set to zero */
1955 }
1956
1957 strcpy( ns->name , "ElvisHasLeftTheBuilding" ) ;
1958
1959 NI_strncpy(ns->orig_name,name,256) ; /* 23 Aug 2002 */
1960
1961 add_open_stream(ns) ; /* 02 Jan 2004 */
1962 ns->goodcheck_time = -99 ; /* 23 Nov 2004 */
1963 return ns ;
1964 }
1965
1966 /*********************************/
1967 /***** http:// or ftp:// I/O *****/
1968
1969 if( strncmp(name,"http://",7) == 0 || strncmp(name,"ftp://",6) == 0 ){
1970 int nn ;
1971 char *data=NULL ;
1972
1973 if( do_create ) return NULL ; /* bad */
1974
1975 nn = NI_read_URL( name , &data ) ;
1976
1977 if( data == NULL || nn <= 4 ){ /* bad */
1978 NI_free(data); return NULL;
1979 }
1980
1981 ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
1982
1983 ns->type = NI_REMOTE_TYPE; /* what kind is this? */
1984 ns->io_mode = NI_INPUT_MODE ;
1985 ns->bad = 0 ;
1986 ns->npos = 0 ; /* scan starts at 0 */
1987 ns->nbuf = nn ;
1988 ns->bufsize = nn ;
1989 ns->buf = data ;
1990 ns->b64_numleft = 0 ;
1991
1992 NI_strncpy( ns->name , name , 256 ) ;
1993
1994 NI_strncpy(ns->orig_name,name,256) ; /* 23 Aug 2002 */
1995
1996 add_open_stream(ns) ; /* 02 Jan 2004 */
1997 ns->goodcheck_time = -99 ; /* 23 Nov 2004 */
1998 return ns ;
1999 }
2000
2001 return NULL ; /* should never be reached */
2002 }
2003
2004 /*---------------------------------------------------------------------------*/
2005 /*! Re-open a NI_stream on a different channel. This is only possible
2006 if the input original stream (ns) is tcp: type.
2007 - The new stream (nname) can be of the form "tcp::port",
2008 which will reopen the stream to the same host on the new port.
2009 - Or the new stream can be of the form "shm:key:size1+size2",
2010 but only if the existing stream was opened to localhost.
2011 - The main purpose of this function is to let a process connect
2012 to a "standard" port on a server process, then tell the server
2013 to reopen on another port (or to use shm:). In this way, the
2014 standard port can be freed up quickly for reuse.
2015
2016 If necessary, this function will wait until the connection to the
2017 other program is ready. Then it will exchange the information with
2018 the other program about changing things, and will again wait until
2019 the new connection is established. Assuming all goes well, then
2020 when this function returns, the input stream (ns) will be modified
2021 so that it now refers to the new connection.
2022
2023 Return value is 1 if things are OK, 0 if not. Failure can occur
2024 because:
2025 - Input ns or nname was badly formed.
2026 - You tried to open shm: when the input tcp: stream was not to localhost.
2027 - The input tcp: stream can't become connected within 10 seconds.
2028 -----------------------------------------------------------------------------*/
2029
NI_stream_reopen(NI_stream_type * ns,char * nname)2030 int NI_stream_reopen( NI_stream_type *ns , char *nname )
2031 {
2032 NI_stream_type *nsnew ;
2033 int typ_new=0 , port_new=0 , jj,kk ;
2034 char msg[1024] ;
2035
2036 /* check inputs for sanity */
2037
2038 if( ns == NULL || ns->type != NI_TCP_TYPE ) return 0 ; /* bad input stream */
2039 if( ns->bad == MARKED_FOR_DEATH ) return 0 ; /* really bad */
2040 if( nname == NULL || nname[0] == '\0' ) return 0 ; /* bad new name */
2041
2042 if( strncmp(nname,"tcp::",5) == 0 ){ /* new is tcp:? */
2043 typ_new = NI_TCP_TYPE ;
2044 port_new = strtol(nname+5,NULL,10) ;
2045 if( port_new <= 0 ) return 0 ; /* bad new port */
2046 if( port_new == ns->port ) return 1 ; /* same as before? */
2047 #ifndef DONT_USE_SHM
2048 } else if( strncmp(nname,"shm:" ,4) == 0 ){ /* new is shm:? */
2049 char *eee = getenv("AFNI_NOSHM") ; /* 06 Jun 2003 */
2050 if( eee != NULL && toupper(*eee) == 'Y' ){ /* shm: is disabled */
2051 fprintf(stderr,"** NI_stream_reopen: shm is disabled\n");
2052 return 0 ;
2053 }
2054 if( strstr(ns->orig_name,":localhost:") == NULL ){ /* can't do shm: */
2055 fprintf(stderr,"** NI_stream_reopen: shm not localhost!\n"); /* but on localhost */
2056 return 0 ;
2057 }
2058 #endif
2059 } else {
2060 fprintf(stderr,"** NI_stream_reopen: illegal input '%s'\n",nname);
2061 return 0 ; /* bad new name */
2062 }
2063
2064 #ifdef NIML_DEBUG
2065 NI_dpr("NI_stream_reopen: waiting for original connection to be good\n") ;
2066 #endif
2067
2068 /* wait for existing stream to be connected */
2069
2070 for( kk=0 ; kk < 10 ; kk++ ){
2071 jj = NI_stream_goodcheck( ns , 1000 ) ; /* wait 1 sec */
2072 if( jj > 0 ) break; /* good :-) */
2073 if( kk == 0 )
2074 fprintf(stderr,"++ NI_stream_reopen: Waiting for socket connection") ;
2075 else
2076 fprintf(stderr,".") ;
2077 }
2078 if( kk == 10 ){ fprintf(stderr," *Failed*\n"); return 0; }
2079 if( kk > 0 ) fprintf(stderr," *Good*\n") ;
2080
2081 /* open new stream as the writer */
2082
2083 if( strncmp(nname,"tcp::",5) == 0 ){
2084 sprintf(msg,"tcp:%s:%d",ns->name,port_new) ; /* old hostname */
2085 }
2086 #ifndef DONT_USE_SHM
2087 else if( strncmp(nname,"shm:" ,4) == 0 ){
2088 NI_strncpy(msg,nname,1024) ;
2089 }
2090 #endif
2091
2092 #ifdef NIML_DEBUG
2093 NI_dpr("NI_stream_reopen: opening new stream %s\n",msg) ;
2094 #endif
2095
2096 nsnew = NI_stream_open( msg, "w" ) ;
2097 if( nsnew == NULL ) return 0 ; /* bad :-( */
2098
2099 /* send message on old stream to other
2100 program, telling it to open the new stream */
2101
2102 sprintf(msg,"<?ni_do ni_verb='reopen_this' ni_object='%s' ?>\n",nname) ;
2103 kk = strlen(msg) ;
2104
2105 #ifdef NIML_DEBUG
2106 NI_dpr("NI_stream_reopen: sending message %s",msg) ;
2107 #endif
2108
2109 jj = NI_stream_write( ns , msg , kk ) ;
2110 if( jj < kk ){
2111 NI_stream_closenow(nsnew) ; return 0 ; /* bad write! */
2112 }
2113
2114 /* now wait for other program to open the new stream */
2115
2116 #ifdef NIML_DEBUG
2117 NI_dpr("NI_stream_reopen: waiting for new stream to be good\n") ;
2118 #endif
2119
2120 jj = NI_stream_goodcheck( nsnew , 5000 ) ; /* wait up to 5 sec */
2121 if( jj <= 0 ){
2122 NI_stream_closenow(nsnew) ; return 0 ; /* never got good */
2123 }
2124
2125 /* if here, new stream is ready:
2126 close the old stream and replace its
2127 contents with the contents of the new stream */
2128
2129 #ifdef NIML_DEBUG
2130 NI_dpr("NI_stream_reopen: closing old stream\n") ;
2131 #endif
2132
2133 NI_stream_close_keep(ns,0) ; /* will be removed from open streams list */
2134
2135 *ns = *nsnew ;
2136
2137 /* 10 Jun 2005: at this point, nsnew is in the open streams list,
2138 but the pointer nsnew is about to die, and so we
2139 must munge the open streams list around now to
2140 make sure that nsnew is removed and ns is re-added! */
2141
2142 remove_open_stream(nsnew) ; NI_free(nsnew) ; add_open_stream(ns) ;
2143
2144 return 1 ; /* :-) */
2145 }
2146
2147 /*-----------------------------------------------------------------------*/
2148 /*! Seek file: stream to a specific offset location.
2149 - whence is one of SEEK_SET, SEEK_CUR, SEEK_END (cf. "man fseek").
2150 - Also clears the stream buffer.
2151 -------------------------------------------------------------------------*/
2152
NI_stream_seek(NI_stream_type * ns,int64_t offset,int whence)2153 void NI_stream_seek( NI_stream_type *ns , int64_t offset , int whence )
2154 {
2155 if( ns == NULL ||
2156 ns->bad == MARKED_FOR_DEATH ||
2157 ns->type != NI_FILE_TYPE ||
2158 ns->fp == NULL ) return ;
2159
2160 fseeko( ns->fp , offset , whence ) ; /* seek file */
2161 ns->nbuf = ns->npos = 0 ; /* clear buffer */
2162 }
2163
2164 /*-----------------------------------------------------------------------*/
2165 /*! Return 1 if it is legal to read from this stream, 0 if it isn't.
2166 This doesn't say anything about if it is practical to read
2167 at this moment; for that, use NI_stream_readcheck().
2168 -------------------------------------------------------------------------*/
2169
NI_stream_readable(NI_stream_type * ns)2170 int NI_stream_readable( NI_stream_type *ns )
2171 {
2172 if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return 0 ;
2173 if( ns->type == NI_TCP_TYPE || ns->type == NI_SHM_TYPE ) return 1 ;
2174 return (ns->io_mode == NI_INPUT_MODE) ;
2175 }
2176
2177 /*-----------------------------------------------------------------------*/
2178 /*! Return 1 if it is legal to write to this stream, 0 if it isn't.
2179 This doesn't say anything about if it is practical to write
2180 at this moment; for that, use NI_stream_writecheck().
2181 -------------------------------------------------------------------------*/
2182
NI_stream_writeable(NI_stream_type * ns)2183 int NI_stream_writeable( NI_stream_type *ns )
2184 {
2185 if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return 0 ;
2186 if( ns->type == NI_TCP_TYPE || ns->type == NI_SHM_TYPE ) return 1 ;
2187 return (ns->io_mode == NI_OUTPUT_MODE) ;
2188 }
2189
2190 /*-----------------------------------------------------------------------*/
2191 /*! Return the name set in the NI_stream header. (This is the pointer
2192 to the internal string, so don't free it!)
2193 -------------------------------------------------------------------------*/
2194
NI_stream_name(NI_stream_type * ns)2195 char * NI_stream_name( NI_stream_type *ns )
2196 {
2197 if( ns == NULL ) return NULL ;
2198 return ns->name ;
2199 }
2200
2201 /*-----------------------------------------------------------------------*/
2202 /*! Alter the input buffer size for a NI_stream.
2203 - Only works for tcp: & shm: streams, and for "r" file: & fd: streams.
2204 - Return value is 1 if it worked OK, -1 if it didn't.
2205 - NI_realloc() is used, so buffer contents aren't affected (if the
2206 size is increased!).
2207 -------------------------------------------------------------------------*/
2208
NI_stream_setbufsize(NI_stream_type * ns,int bs)2209 int NI_stream_setbufsize( NI_stream_type *ns , int bs ) /* 03 Jan 2003 */
2210 {
2211 char *qbuf ;
2212 if( ns == NULL ||
2213 ns->type == NI_STRING_TYPE ||
2214 ns->bad == MARKED_FOR_DEATH ||
2215 bs < 666 ||
2216 bs < ns->nbuf ) return -1 ; /* bad inputs */
2217
2218 if( !( ns->type == NI_TCP_TYPE || ns->type == NI_SHM_TYPE ||
2219 (ns->type == NI_FILE_TYPE && ns->io_mode == NI_INPUT_MODE) ||
2220 (ns->type == NI_FD_TYPE && ns->io_mode == NI_INPUT_MODE) ) )
2221 return -1 ;
2222
2223 qbuf = NI_realloc( ns->buf , char , bs ) ;
2224 if( qbuf == NULL ) return -1 ; /* this is bad */
2225 ns->buf = qbuf ;
2226 ns->bufsize = bs ;
2227 return 1 ;
2228 }
2229
2230 /*-----------------------------------------------------------------------*/
2231 /*! Get the input buffer size for a NI_stream.
2232 Returns -1 if the stream is bad, or has been sentenced to death.
2233 -------------------------------------------------------------------------*/
2234
NI_stream_getbufsize(NI_stream_type * ns)2235 int NI_stream_getbufsize( NI_stream_type *ns ) /* 03 Jan 2003 */
2236 {
2237 if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return -1 ;
2238 return ns->bufsize ;
2239 }
2240
2241 /*-----------------------------------------------------------------------*/
2242 /*! Return the output string buffer for a NI_stream of str: type.
2243 If the input is not a "w" str: stream, then NULL is returned.
2244 Otherwise a pointer to the internal buffer is returned.
2245 This will be a NUL terminated string.
2246 -------------------------------------------------------------------------*/
2247
NI_stream_getbuf(NI_stream_type * ns)2248 char * NI_stream_getbuf( NI_stream_type *ns )
2249 {
2250 if( ns == NULL ||
2251 ns->type != NI_STRING_TYPE ||
2252 ns->io_mode != NI_OUTPUT_MODE ||
2253 ns->bad == MARKED_FOR_DEATH ) return NULL ; /* bad inputs */
2254
2255 return ns->buf ;
2256 }
2257
2258 /*-----------------------------------------------------------------------*/
2259 /*! Clear the buffer of a str: writing NI_stream. This is intended to
2260 let you write anew without having to close and open again.
2261 -------------------------------------------------------------------------*/
2262
NI_stream_clearbuf(NI_stream_type * ns)2263 void NI_stream_clearbuf( NI_stream_type *ns )
2264 {
2265 if( ns == NULL ||
2266 ns->type != NI_STRING_TYPE ||
2267 ns->io_mode != NI_OUTPUT_MODE ) return ; /* bad inputs */
2268
2269 NI_free(ns->buf) ;
2270 ns->nbuf = 0 ;
2271 ns->bufsize = 1 ;
2272 ns->buf = NI_malloc(char, 1) ; /* 1 byte set to zero */
2273 }
2274
2275 /*-----------------------------------------------------------------------*/
2276 /*! Reset the input string buffer for a NI_stream of str: type.
2277 If the input is not a "r" str: stream, then nothing happens.
2278 Otherwise, the current contents of the buffer are discarded,
2279 and the buffer is replaced with a copy of the input string.
2280 -------------------------------------------------------------------------*/
2281
NI_stream_setbuf(NI_stream_type * ns,char * str)2282 void NI_stream_setbuf( NI_stream_type *ns , char *str )
2283 {
2284 int nn ;
2285
2286 if( ns == NULL ||
2287 ns->type != NI_STRING_TYPE ||
2288 ns->io_mode != NI_INPUT_MODE ||
2289 str == NULL ||
2290 ns->bad == MARKED_FOR_DEATH ) return ; /* bad inputs */
2291
2292 NI_free(ns->buf) ; /* take out the trash */
2293 nn = NI_strlen(str) ; /* size of new buffer string */
2294 ns->nbuf = nn ; /* set num char in new buffer */
2295 ns->npos = 0 ; /* reset scan position */
2296 ns->bufsize = nn+1 ; /* allow space for NUL byte */
2297 ns->buf = NI_malloc(char, nn+1) ; /* and make the buffer */
2298 strcpy(ns->buf,str) ; /* and set its contents */
2299 return ;
2300 }
2301
2302 /*-----------------------------------------------------------------------*/
2303 /*! Check if the given NI_stream is properly opened for I/O.
2304
2305 If not, wait up to msec milliseconds to establish the connection to
2306 the other end; if msec < 0, will wait nearly forever.
2307 Returns 1 if ready; 0 if not (but may become good later);
2308 -1 if an error occurs.
2309 Possible -1 errors are:
2310 - ns was connected to a socket, and now has become disconnected
2311 - ns is passed in as NULL (bad user, bad bad bad)
2312 - ns is reading a file or a string, and we are already at its end
2313 - ns is marked for death
2314 The only cases in which 0 is returned is if the NI_stream is
2315 tcp: or shm: and the stream is waiting for a connection from
2316 the other program. These are also the only cases in which input
2317 parameter msec is actually used.
2318 -------------------------------------------------------------------------*/
2319
NI_stream_goodcheck(NI_stream_type * ns,int msec)2320 int NI_stream_goodcheck( NI_stream_type *ns , int msec )
2321 {
2322 int ii , jj ;
2323 char *bbb ;
2324
2325 /** check inputs for OK-osity **/
2326
2327 if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return -1 ;
2328
2329 switch( ns->type ){
2330
2331 #ifndef DONT_USE_SHM
2332 /** Shared memory **/
2333
2334 case NI_SHM_TYPE:
2335 return SHM_goodcheck( ns->shmioc , msec ) ;
2336 #endif
2337
2338 /** File I/O [there is never any waiting here] **/
2339
2340 case NI_FILE_TYPE:
2341 if( ns->fp == NULL ) return -1 ; /* should never happen */
2342 if( ns->io_mode == NI_INPUT_MODE )
2343 return NI_stream_readcheck(ns,0) ; /* input mode */
2344 else
2345 return 1 ; /* output mode */
2346
2347 case NI_FD_TYPE:
2348 return 1 ; /* no way to check */
2349
2350 /** String I/O **/
2351
2352 case NI_STRING_TYPE:
2353 if( ns->io_mode == NI_INPUT_MODE )
2354 return NI_stream_readcheck(ns,0) ; /* input mode */
2355 else
2356 return 1 ; /* output mode */
2357
2358 /** remote Web input */
2359
2360 case NI_REMOTE_TYPE:
2361 if( ns->io_mode == NI_INPUT_MODE )
2362 return NI_stream_readcheck(ns,0) ; /* input mode */
2363 else
2364 return -1 ; /* output mode */
2365
2366 /** Socket I/O **/
2367
2368 case NI_TCP_TYPE:
2369 if( ns->bad == 0 ){ /** if good before, then check if is still good **/
2370 int ich ;
2371 ich = tcp_alivecheck(ns->sd) ;
2372
2373 #ifdef NIML_DEBUG
2374 if( ich == 0 ) /* 17 Jun 2003 */
2375 NI_dpr("++ Socket %s (port %d) has gone bad!\n",ns->name,ns->port);
2376 #endif
2377
2378 if( ich == 0 ) return -1 ;
2379 return 1 ;
2380 }
2381
2382 /** wasn't good before, so check if that condition has changed **/
2383
2384 /** TCP/IP waiting to accept call from another host **/
2385
2386 if( ns->bad == TCP_WAIT_ACCEPT ){
2387 ii = tcp_readcheck(ns->sd,msec) ; /* see if ready */
2388 if( ii > 0 ){ /* if socket ready: */
2389 jj = tcp_accept( ns->sd , NULL,&bbb ) ; /* accept connection */
2390 if( jj >= 0 ){ /* if accept worked */
2391 CLOSEDOWN( ns->sd ) ; /* close old socket */
2392 NI_strncpy(ns->name,bbb,256) ; /* put IP into name */
2393 NI_free(bbb); ns->bad = 0; ns->sd = jj; /* and ready to go! */
2394 fcntl( ns->sd, F_SETOWN, (int)getpid() ); /* 02 Jan 2004 */
2395 }
2396 }
2397 }
2398
2399 /** TCP/IP waiting to connect call to another host **/
2400
2401 else if( ns->bad == TCP_WAIT_CONNECT ){
2402 int dms=0 , ms ;
2403
2404 if( msec < 0 ) msec = 999999999 ; /* a long time (11+ days) */
2405 for( ms=0 ; ms < msec ; ms += dms ){
2406 ns->sd = tcp_connect( ns->name , ns->port ); /* try to connect */
2407 if( ns->sd >= 0 ) break ; /* worked? get out */
2408 dms = NEXTDMS(dms); dms = MIN(dms,msec-ms); NI_sleep(dms);
2409 }
2410 if( ns->sd < 0 ) /* one last try? */
2411 ns->sd = tcp_connect( ns->name , ns->port ) ;
2412
2413 if( ns->sd >= 0 ) ns->bad = 0 ; /* succeeded? */
2414 if( ns->sd >= 0 )
2415 fcntl( ns->sd, F_SETOWN, (int)getpid() ); /* 02 Jan 2004 */
2416 }
2417
2418 /** see if it turned from bad to good **/
2419
2420 return (ns->bad == 0) ;
2421 }
2422
2423 return -1 ; /* unreachable, I hope */
2424 }
2425
2426 /*---------------------------------------------------------------------------*/
2427 /*! Close a NI_stream, but don't free the insides.
2428 If (flag&1 != 0) send a "close_this" message to the other end.
2429 If (flag&2 != 0) use TCP OOB data to send a SIGURG to the other end.
2430 If (flag&4 != 0) don't remove from open_stream list [only from atexit()]
2431 -----------------------------------------------------------------------------*/
2432
NI_stream_close_keep(NI_stream_type * ns,int flag)2433 void NI_stream_close_keep( NI_stream_type *ns , int flag )
2434 {
2435 if( ns == NULL || !isgraph(ns->orig_name[0]) ) return ;
2436
2437 if( (flag & 4) == 0 ) /* 22 Apr 2005 */
2438 remove_open_stream( ns ) ; /* 02 Jan 2004 */
2439
2440 if( ns->bad == MARKED_FOR_DEATH ){
2441 if( ns->buf != NULL ){ NI_free(ns->buf); ns->buf = NULL;}
2442 return ;
2443 }
2444
2445 /*-- 20 Dec 2002: write a farewell message to the other end? --*/
2446
2447 if( (flag & 1) != 0 &&
2448 (ns->type == NI_TCP_TYPE || ns->type == NI_SHM_TYPE) &&
2449 NI_stream_writecheck(ns,1) > 0 ){
2450
2451 NI_stream_writestring( ns , "<?ni_do ni_verb='close_this' ?>\n" ) ;
2452 NI_sleep(9) ; /* give it an instant to read the message */
2453 }
2454
2455 /*-- mechanics of closing for different stream types --*/
2456
2457 switch( ns->type ){
2458
2459 #ifndef DONT_USE_SHM
2460 case NI_SHM_TYPE:
2461 NI_sleep(9) ; /* 31 Mar 2005 */
2462 SHM_close( ns->shmioc ) ; /* detach shared memory */
2463 break ;
2464 #endif
2465
2466 case NI_FD_TYPE:
2467 if( ns->fp != NULL && ns->io_mode == NI_OUTPUT_MODE ) fflush(ns->fp) ;
2468 break ;
2469
2470 case NI_REMOTE_TYPE:
2471 case NI_STRING_TYPE: /* nothing to do */
2472 break ;
2473
2474 case NI_FILE_TYPE:
2475 if( ns->fp != NULL ) fclose(ns->fp) ; /* close file */
2476 break ;
2477
2478 case NI_TCP_TYPE:
2479 if( ns->sd >= 0 ){
2480 if( (flag & 2) != 0 ){
2481 tcp_send( ns->sd , "X" , 1 , MSG_OOB ) ; /* 02 Jan 2004 */
2482 NI_sleep(9) ;
2483 }
2484 NI_sleep(2) ; /* 31 Mar 2005 */
2485 CLOSEDOWN(ns->sd) ; /* close socket */
2486 }
2487 break ;
2488 }
2489
2490 ns->bad = MARKED_FOR_DEATH ; /* label this as unclean, not to be touched */
2491 if( (flag & 4) == 0 ){ /* only free buf if program is NOT exiting */
2492 NI_free(ns->buf) ; ns->buf = NULL ;
2493 }
2494 return ;
2495 }
2496
2497 /*-----------------------------------------------------------------------*/
2498 /*! Close a NI_stream. Note that this will also free what ns points to.
2499 Don't use this pointer again.
2500 Use the NI_STREAM_CLOSE macro to call this function and then
2501 also set the pointer "ns" to NULL.
2502 -------------------------------------------------------------------------*/
2503
NI_stream_close(NI_stream_type * ns)2504 void NI_stream_close( NI_stream_type *ns )
2505 {
2506 NI_stream_close_keep(ns,1) ; NI_free(ns) ; return ;
2507 }
2508
2509 /*-----------------------------------------------------------------------*/
2510 /*! Close a NI_stream without sending a "close_this"
2511 message to the other end of the stream. */
2512
NI_stream_closenow(NI_stream_type * ns)2513 void NI_stream_closenow( NI_stream_type *ns )
2514 {
2515 NI_stream_close_keep(ns,0) ; NI_free(ns) ; return ;
2516 }
2517
2518 /*-----------------------------------------------------------------------*/
2519 /* Close a NI_stream with a "close_this" message and also using
2520 TCP OOB data (for socket streams, that is) to notify the other end. */
2521
NI_stream_kill(NI_stream_type * ns)2522 void NI_stream_kill( NI_stream_type *ns )
2523 {
2524 NI_stream_close_keep(ns,3) ; NI_free(ns) ; return ;
2525 }
2526
2527 /*---------------------------------------------------------------------------*/
2528 /*! Check if the NI_stream has data read to be read, or has data stored
2529 in its internal buffer.
2530 - Return values are as in NI_stream_readcheck().
2531 - Also see NI_stream_readbuf().
2532 -----------------------------------------------------------------------------*/
2533
NI_stream_hasinput(NI_stream_type * ns,int msec)2534 int NI_stream_hasinput( NI_stream_type *ns , int msec )
2535 {
2536 if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return -1 ;
2537
2538 if( ns->npos < ns->nbuf ) return 1 ; /* check if has data in buffer */
2539 return NI_stream_readcheck( ns , msec ) ; /* see if any data can be read */
2540 }
2541
2542 /*---------------------------------------------------------------------------*/
2543 /*! Check if the NI_stream is ready to have data read out of it.
2544
2545 If not, the routine will wait up to msec milliseconds for data to be
2546 available. If msec < 0, this routine will wait nearly forever.
2547 The return value is 1 if data is ready, 0 if not; -1 will be returned
2548 if some unrecoverable error is detected:
2549 - tcp: the socket connection was dropped
2550 - shm: the other process died or detached the segment
2551 - file: you have reached the end of the file, and are still trying to read.
2552
2553 Also see NI_stream_hasinput() and NI_stream_readbuf().
2554 -----------------------------------------------------------------------------*/
2555
NI_stream_readcheck(NI_stream_type * ns,int msec)2556 int NI_stream_readcheck( NI_stream_type *ns , int msec )
2557 {
2558 int ii ;
2559
2560 if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return -1 ;
2561
2562 switch( ns->type ){
2563
2564 #ifndef DONT_USE_SHM
2565 case NI_SHM_TYPE:
2566 ii = SHM_readcheck( ns->shmioc , msec ) ;
2567 if( ii > 0 ) ii = 1 ;
2568 return ii ;
2569 #endif
2570
2571 /** tcp: ==> uses the Unix "select" mechanism **/
2572
2573 case NI_TCP_TYPE:
2574 ii = NI_stream_goodcheck(ns,0) ; /* check if it is connected */
2575 if( ii == -1 ) return -1 ; /* some error */
2576 if( ii == 0 ){ /* not good yet */
2577 ii = NI_stream_goodcheck(ns,msec) ; /* so wait for it to get good */
2578 if( ii != 1 ) return ii ; /* if still not good, exit */
2579 }
2580 ii = tcp_alivecheck( ns->sd ) ; /* see if it is still open */
2581 if( !ii ) return -1 ; /* if not open, error exit */
2582 ii = tcp_readcheck( ns->sd , msec ) ; /* see if any data is there */
2583 return ii ;
2584
2585 /** fd: ==> use select, as in tcp: **/
2586
2587 case NI_FD_TYPE:
2588 ii = tcp_readcheck( fileno(ns->fp) , msec ) ;
2589 return ii ;
2590
2591 /** file: ==> check current file position and length of file **/
2592
2593 case NI_FILE_TYPE:{
2594 int64_t f_len , f_pos ;
2595
2596 if( ns->fp == NULL ||
2597 ns->io_mode == NI_OUTPUT_MODE ) return -1 ; /* never? */
2598
2599 f_len = ns->fsize ; /* length of file */
2600 if( f_len < 0 ) return -1 ; /* file not found (?) */
2601
2602 f_pos = ftello( ns->fp ) ; /* where are we now? */
2603 if( f_pos < 0 ) return -1 ; /* should never happen */
2604
2605 return (f_pos < f_len) ? 1 : -1 ; /* is good or bad, but */
2606 /* never just neutral */
2607 }
2608
2609 /** str: ==> check current buffer position **/
2610
2611 case NI_REMOTE_TYPE:
2612 case NI_STRING_TYPE:{
2613 if( ns->io_mode == NI_OUTPUT_MODE ) return -1 ; /* never? */
2614
2615 return (ns->npos < ns->nbuf) ? 1 : -1 ; /* is data left? */
2616 }
2617 }
2618
2619 return -1 ; /* should never happen */
2620 }
2621
2622 /*---------------------------------------------------------------------------*/
2623 /*! Check if the NI_stream is ready to have data written into it.
2624
2625 If not, the routine will wait up to msec milliseconds for writing to
2626 be allowable. If msec < 0, this routine will wait nearly forever.
2627 The return value is 1 if data can be sent, 0 if not;
2628 -1 will be returned if some unrecoverable error is detected:
2629 - tcp: the socket closed down at the other end
2630 - file: this should never happen, unless you try to write to
2631 a readonly NI_stream
2632 -----------------------------------------------------------------------------*/
2633
NI_stream_writecheck(NI_stream_type * ns,int msec)2634 int NI_stream_writecheck( NI_stream_type *ns , int msec )
2635 {
2636 int ii ;
2637
2638 if( !NI_stream_writeable(ns) ) return -1 ;
2639
2640 switch( ns->type ){
2641
2642 #ifndef DONT_USE_SHM
2643 case NI_SHM_TYPE:
2644 ii = SHM_writecheck( ns->shmioc , msec ) ;
2645 if( ii > 0 ) ii = 1 ;
2646 return ii ;
2647 #endif
2648
2649 /** tcp: ==> uses the Unix "select" mechanism **/
2650
2651 case NI_TCP_TYPE:
2652 if( ns->bad ){ /* not marked as good */
2653 ii = NI_stream_goodcheck(ns,0) ; /* check if has become good */
2654 if( ii == -1 ) return -1 ; /* some error when checking */
2655 if( ii == 0 ){ /* not good yet, */
2656 ii = NI_stream_goodcheck(ns,msec); /* so wait for it to get good */
2657 if( ii != 1 ) return ii ; /* if still not good, exit */
2658 }
2659 }
2660 /* socket is good, so */
2661 return tcp_writecheck(ns->sd,msec) ; /* check if we can write bytes */
2662
2663 /** fd: ==> use select, as in tcp: **/
2664
2665 case NI_FD_TYPE:
2666 return tcp_writecheck( fileno(ns->fp) , msec ) ;
2667
2668 /** file: ==> if the file was opened in write mode **/
2669
2670 case NI_FILE_TYPE:
2671 return ( (ns->fp != NULL && ns->io_mode == NI_OUTPUT_MODE) ? 1
2672 : -1 ) ;
2673
2674 /** str: ==> if the string was opened in write mode **/
2675
2676 case NI_STRING_TYPE:
2677 return ( (ns->io_mode == NI_OUTPUT_MODE) ? 1
2678 : -1 ) ;
2679 /** http: or ftp: **/
2680
2681 case NI_REMOTE_TYPE: /* can't write to remote files */
2682 return -1 ;
2683 }
2684
2685 return -1 ; /* should never be reached */
2686 }
2687
2688 /*----------------------------------------------------------------------------*/
2689 /*! Send a string (without the NUL byte) down the NI_stream. [15 Oct 2002]
2690 ------------------------------------------------------------------------------*/
2691
NI_stream_writestring(NI_stream_type * ns,char * str)2692 int NI_stream_writestring( NI_stream_type *ns , char *str )
2693 {
2694 if( str == NULL ) return -1 ;
2695 return NI_stream_write( ns , str , strlen(str) ) ;
2696 }
2697
2698 /*----------------------------------------------------------------------------*/
2699 /*! Send nbytes of data from buffer down the NI_stream.
2700
2701 Return value is the number of bytes actually sent, or is -1 if some error
2702 occurs (which means that the NI_stream is bad). If 0 is returned, this
2703 means you tried to write to something that is temporarily unavailable.
2704
2705 - tcp: We use blocking sends, so that all the data should be sent properly
2706 unless the connection to the other end fails for some reason
2707 (e.g., the planet explodes in a fiery cataclysm of annihilation).
2708 - shm: We also block until everything can be written, even if it requires
2709 filling the shared memory buffer many times and waiting for the
2710 reading process to empty it many times.
2711 - file: Everything should be written, unless the filesystem fills up.
2712 If nothing at all gets written, -1 is returned.
2713 - str: Everything will be written, or the program will crash.
2714 Do not include the NUL byte at the end of the string in
2715 the nbytes count.
2716 ------------------------------------------------------------------------------*/
2717
NI_stream_write(NI_stream_type * ns,char * buffer,int nbytes)2718 int NI_stream_write( NI_stream_type *ns , char *buffer , int nbytes )
2719 {
2720 int ii , nsent ;
2721
2722 /** check for reasonable inputs **/
2723
2724 if( ns == NULL || ns->bad ||
2725 buffer == NULL || nbytes < 0 || ns->bad == MARKED_FOR_DEATH ) return -1;
2726
2727 if( nbytes == 0 ) return 0 ; /* that was easy */
2728
2729 #ifdef NIML_DEBUG
2730 NI_dpr("ENTER NI_stream_write\n") ;
2731 #endif
2732
2733 if( ns->type != NI_TCP_TYPE ){
2734 ii = NI_stream_writecheck(ns,66) ; /* check if stream is still OK */
2735 if( ii < 0 ) return ii ; /* if not, vamoose the ranch */
2736 }
2737
2738 switch( ns->type ){
2739
2740 #ifndef DONT_USE_SHM
2741 case NI_SHM_TYPE:
2742 return SHM_sendall( ns->shmioc , buffer , nbytes ) ;
2743 #endif
2744
2745 /** tcp: ==> just use send **/
2746
2747 case NI_TCP_TYPE:
2748
2749 if( ns->bad ) return 0 ; /* socket not ready yet */
2750
2751 /* turn off SIGPIPE signals, which will otherwise be
2752 raised if we send to a socket when the other end has crashed */
2753
2754 if( !nosigpipe ){ signal(SIGPIPE,SIG_IGN); nosigpipe = 1; }
2755
2756 #if 0
2757 /* 03 Mar 2002: wait until we can write fer shur */
2758 do{ ii=tcp_writecheck(ns->sd,1) ; } while(ii==0) ;
2759 if( ii < 0 ) return -1 ;
2760 #endif
2761
2762 errno = 0 ;
2763 nsent = tcp_send( ns->sd , buffer , nbytes , 0 ) ;
2764 if( nsent < nbytes || errno != 0 ) PERROR("NI_stream_write(send)") ;
2765 if( nsent == 0 ){ fprintf(stderr,"tcp send: 0/%d\n",nbytes); nsent=-1; }
2766 return nsent ;
2767
2768 /** file: ==> just fwrite **/
2769
2770 case NI_FD_TYPE:
2771 case NI_FILE_TYPE:
2772 #ifdef NIML_DEBUG
2773 NI_dpr(" file: about to write %d bytes\n",nbytes) ;
2774 #endif
2775 nsent = fwrite( buffer , 1 , nbytes , ns->fp ) ;
2776 if( nsent < nbytes ) PERROR("NI_stream_write(fwrite)") ;
2777 #ifdef NIML_DEBUG
2778 NI_dpr(" file: actually wrote %d bytes\n",nsent) ;
2779 #endif
2780 if( nsent == 0 ) nsent = -1 ;
2781 fflush(ns->fp) ;
2782 return nsent ;
2783
2784 /** str: ==> append to buffer in stream struct **/
2785
2786 case NI_STRING_TYPE:
2787 #ifdef NIML_DEBUG
2788 NI_dpr("NI_stream_write str: input=%s\n",ns->buf) ;
2789 #endif
2790 ns->buf = NI_realloc( ns->buf , char , ns->bufsize+nbytes ) ;
2791 memcpy( ns->buf+ns->nbuf , buffer , nbytes ) ;
2792 ns->nbuf += nbytes ; ns->buf[ns->nbuf] = '\0' ;
2793 ns->bufsize += nbytes ;
2794 #ifdef NIML_DEBUG
2795 NI_dpr("NI_stream_write str: output=%s\n",ns->buf) ;
2796 #endif
2797 return nbytes ;
2798
2799 /** ftp: or http: ==> can't write! */
2800
2801 case NI_REMOTE_TYPE:
2802 return -1 ;
2803 }
2804
2805 return -1 ; /* should not be reached */
2806 }
2807
2808 /*-------------------------------------------------------------------------*/
2809 /*! Read up to nbytes of data from the NI_stream, into buffer.
2810
2811 Returns the number of bytes actually read. For both the case of
2812 sockets and files, this may be less than nbytes (may even be 0).
2813 If an error occurs and no data is read, -1 is returned.
2814
2815 For tcp: streams, if no data is available, this function will
2816 wait until something can be read. If this behavior is undesirable,
2817 then you should use NI_stream_readcheck() before calling this function
2818 in order to see if any data is available.
2819
2820 For shm: streams, will return immediately if no data is available.
2821
2822 For file: streams, this function simply tries to read from the file.
2823 Whether or not it succeeds, it will return immediately. It should
2824 never return -1; if it returns 0, this means end-of-file.
2825 ---------------------------------------------------------------------------*/
2826
NI_stream_read(NI_stream_type * ns,char * buffer,int nbytes)2827 int NI_stream_read( NI_stream_type *ns , char *buffer , int nbytes )
2828 {
2829 int ii ;
2830
2831 /** check for reasonable inputs **/
2832
2833 if( ns == NULL || ns->bad || buffer == NULL || nbytes < 0 ) return -1 ;
2834
2835 if( nbytes == 0 ) return 0 ;
2836
2837 #ifdef NIML_DEBUG
2838 NI_dpr("ENTER NI_stream_read\n") ;
2839 #endif
2840
2841 switch( ns->type ){
2842
2843 #ifndef DONT_USE_SHM
2844 case NI_SHM_TYPE:
2845 return SHM_recv( ns->shmioc , buffer , nbytes ) ;
2846 #endif
2847
2848 /** tcp: just use recv **/
2849
2850 case NI_TCP_TYPE:
2851 ii = NI_stream_goodcheck(ns,1) ; if( ii != 1 ) return ii ;
2852 #if 0
2853 /* wait 'till we can read fer shur */
2854 do{ ii=tcp_readcheck(ns->sd,1); } while( ii==0 ) ;
2855 if( ii < 0 ) return -1 ;
2856 #endif
2857 errno = 0 ;
2858 ii = tcp_recv( ns->sd , buffer , nbytes , 0 ) ;
2859 if( ii == -1 || errno != 0 ) PERROR("NI_stream_read(recv)") ;
2860 #ifdef NIML_DEBUG
2861 NI_dpr(" tcp: got %d/%d bytes ***\n",ii,nbytes) ;
2862 #endif
2863 return ii ;
2864
2865 /** file: just use fread **/
2866
2867 case NI_FD_TYPE:
2868 case NI_FILE_TYPE:
2869 if( ns->fp == NULL || ns->io_mode == NI_OUTPUT_MODE ) return -1 ;
2870 ii = fread( buffer , 1 , nbytes , ns->fp ) ;
2871 return ii ;
2872
2873 /** str: copy bytes out of the buffer string **/
2874
2875 case NI_REMOTE_TYPE:
2876 case NI_STRING_TYPE:
2877 if( ns->io_mode == NI_OUTPUT_MODE ) return -1 ; /* bad stream */
2878 ii = ns->nbuf - ns->npos ; /* how much is left */
2879 if( ii <= 0 ) return -1 ; /* no data left */
2880 if( ii > nbytes ) ii = nbytes ; /* amount to copy */
2881 memcpy( buffer , ns->buf+ns->npos , ii ) ; /* copy it */
2882 ns->npos += ii ; /* advance position */
2883 return ii ;
2884 }
2885
2886 return -1 ; /* should not be reached */
2887 }
2888
2889 /*-----------------------------------------------------------------------*/
2890 /*! Try to fill up the stream's input buffer.
2891 Don't call this function until NI_stream_goodcheck() is 1!
2892
2893 - minread = Minimum number of bytes to read.
2894 Will wait until we get at least this many,
2895 until the stream is bad or the buffer is full.
2896 If minread=0, then may read nothing (but will try).
2897
2898 - msec = Maximum amount of time to wait to satisfy minread,
2899 in milliseconds. If msec<0, will wait nearly forever.
2900 If msec=0, will return after 1st read attempt, even
2901 if nothing was obtained.
2902
2903 Returns number of bytes read (-1 if input stream goes bad before
2904 any data is read). If the input stream goes bad AFTER some data
2905 is read, there is no indication of that (until the next time
2906 you call this, of course).
2907 -------------------------------------------------------------------------*/
2908
NI_stream_fillbuf(NI_stream_type * ns,int minread,int msec)2909 int NI_stream_fillbuf( NI_stream_type *ns, int minread, int msec )
2910 {
2911 int nn , ii=0 , ntot=0 , ngood=0 , mwait=0 ;
2912 int start_msec = NI_clock_time() ;
2913
2914 #ifdef NIML_DEBUG
2915 NI_dpr(" ENTER NI_stream_fillbuf(%s,%d,%d)\n" , ns->orig_name , minread , msec ) ;
2916 NI_dpr(" nbuf = %d bufsize = %d" , ns->nbuf , ns->bufsize ) ;
2917 #endif
2918
2919 if( NI_stream_goodcheck(ns,0) < 0 ){
2920 #ifdef NIML_DEBUG
2921 NI_dpr(" goodcheck fails immediately :(") ;
2922 #endif
2923 return -1 ; /* bad input */
2924 }
2925
2926 if( ns->type == NI_STRING_TYPE ) return -1 ; /* goofy input */
2927 if( ns->type == NI_REMOTE_TYPE ) return -1 ; /* goofy input */
2928
2929 if( ns->nbuf >= ns->bufsize ) return 0 ; /* buffer already full */
2930
2931 if( msec < 0 ) msec = 999999999 ; /* a long time (11+ days) */
2932
2933 /* read loop */
2934
2935 while(1){
2936
2937 ngood = NI_stream_readcheck(ns,mwait); /* check if data can be read */
2938 #ifdef NIML_DEBUG
2939 NI_dpr(" NI_stream_fillbuf gets readcheck = %d",ngood) ;
2940 #endif
2941 if( ngood < 0 ) break ; /* data stream gone bad, so exit */
2942
2943 ii = 0 ;
2944 if( ngood > 0 ){ /* we can read ==> */
2945 /* try to fill buffer completely */
2946 #ifdef NIML_DEBUG
2947 NI_dpr(" NI_stream_fillbuf trying to read data") ;
2948 #endif
2949 ii = NI_stream_read( ns, ns->buf+ns->nbuf, ns->bufsize-ns->nbuf ) ;
2950
2951 if( ii > 0 ){ /* we got data! */
2952 ns->nbuf += ii ; /* buffer is now longer */
2953 ntot += ii ; /* total bytes read here so far */
2954 #ifdef NIML_DEBUG
2955 NI_dpr(" NI_stream_fillbuf got %d bytes") ;
2956 #endif
2957
2958 /* if buffer is full,
2959 or we have all the data that was asked for, then exit */
2960
2961 if( ns->nbuf >= ns->bufsize || ntot >= minread ) break ;
2962
2963 } else if( ii < 0 ){ /* stream suddenly died horribly? */
2964 #ifdef NIML_DEBUG
2965 NI_dpr(" NI_stream_fillbuf stream died horribly") ;
2966 #endif
2967 ngood = -1 ; break ;
2968 }
2969 }
2970
2971 /* if we don't require data, then exit no matter what our status is */
2972
2973 if( minread <= 0 ) break ;
2974
2975 /* if the max time has elapsed, then exit */
2976
2977 if( NI_clock_time()-start_msec >= msec ) break ;
2978
2979 /* otherwise, sleep a little bit before trying again */
2980
2981 if( mwait < 9 && ii < 4096 ) mwait++ ;
2982 }
2983
2984 /* if didn't get any data, and
2985 if the NI_stream was bad, return -1 as a flag of displeasure */
2986
2987 if( ntot == 0 && ngood < 0 ) ntot = -1 ;
2988
2989 return ntot ; /* otherwise, return # of bytes read (may be 0) */
2990 }
2991
2992 /*-----------------------------------------------------------------------*/
2993 /*! Buffered read from a NI_stream. Unlike NI_stream_read(), will try
2994 to read all nbytes of data, waiting if necessary. Also works through
2995 the internal buffer, rather than directly to the stream.
2996
2997 Return value is number of bytes read. May be less than nbytes if
2998 the stream closed (or was used up) before nbytes of data was read.
2999 Will return -1 if something is rotten.
3000 -------------------------------------------------------------------------*/
3001
NI_stream_readbuf(NI_stream_type * ns,char * buffer,int nbytes)3002 int NI_stream_readbuf( NI_stream_type *ns , char *buffer , int nbytes )
3003 {
3004 int ii , jj , bs , nout=0 ;
3005
3006 /** check for reasonable inputs **/
3007
3008 if( nbytes == 0 ) return 0; /* that was real easy */
3009 if( buffer == NULL || nbytes < 0 ) return -1; /* stupid caller */
3010 if( ns->buf == NULL || ns->bufsize == 0 ) return -1; /* shouldn't happen */
3011 if( !NI_stream_readable(ns) ) return -1; /* stupid stream */
3012
3013 /* see how many unused bytes are already in the input buffer */
3014
3015 ii = ns->nbuf - ns->npos ;
3016
3017 if( ii >= nbytes ){ /* have all the data we need already */
3018 memcpy( buffer , ns->buf + ns->npos , nbytes ) ;
3019 ns->npos += nbytes ;
3020 if( ns->npos == ns->nbuf ) ns->nbuf = ns->npos = 0 ; /* buffer used up */
3021 return nbytes ;
3022 }
3023
3024 /* copy what data we already have, if any */
3025
3026 if( ii > 0 ){
3027 memcpy( buffer , ns->buf + ns->npos , ii ) ; nout = ii ;
3028 }
3029 ns->nbuf = ns->npos = 0 ; /* buffer used up */
3030
3031 /* input streams with fixed length buffers ==> can't do no more */
3032
3033 if( ns->type == NI_REMOTE_TYPE || ns->type == NI_STRING_TYPE )
3034 return (nout > 0) ? nout : -1 ;
3035
3036 /* otherwise, fill the buffer and try again */
3037
3038 bs = ns->bufsize ;
3039
3040 while( nout < nbytes ){
3041
3042 jj = MIN( bs , nbytes-nout ) ; /* how much to try to read */
3043 ii = NI_stream_fillbuf( ns,jj,1666 ) ; /* read into stream buffer */
3044
3045 if( ii > 0 ){ /* got something */
3046 ii = ns->nbuf ; /* how much now in buffer */
3047 if( ii > nbytes-nout ) ii = nbytes-nout ;
3048 memcpy( buffer+nout , ns->buf , ii ) ; nout += ii ;
3049 ns->npos += ii ; NI_reset_buffer( ns ) ;
3050 } else { /* got nothing */
3051 break ; /* so quit */
3052 }
3053 }
3054
3055 if( nout == 0 && ii < 0 ) nout = -1 ; /* no data and an I/O error */
3056 return nout ;
3057 }
3058
3059 /*-----------------------------------------------------------------------*/
3060 /*! Buffered read from a NI_stream, like NI_stream_readbuf, but also:
3061 - Converts from Base64 to binary 'on the fly'.
3062 - Will stop at a '<'.
3063
3064 Return value is number of bytes put into the buffer. May be less than
3065 nbytes if the stream closed (or was used up, or hit a '<') before
3066 nbytes of data was read. Will return -1 if something is rotten.
3067 -------------------------------------------------------------------------*/
3068
NI_stream_readbuf64(NI_stream_type * ns,char * buffer,int nbytes)3069 int NI_stream_readbuf64( NI_stream_type *ns , char *buffer , int nbytes )
3070 {
3071 int ii , jj , bs , nout=0 ;
3072 byte a=0,b=0,c=0 , w,x,y,z ;
3073 byte ag,bg,cg ;
3074 int num_reread , bpos ;
3075
3076 /** check for reasonable inputs **/
3077
3078 if( nbytes == 0 ) return 0; /* that was real easy */
3079 if( buffer == NULL || nbytes < 0 ) return -1; /* stupid caller */
3080 if( ns->buf == NULL || ns->bufsize == 0 ) return -1; /* shouldn't happen */
3081 if( !NI_stream_readable(ns) ) return -1; /* stupid stream */
3082
3083 /* are there decoded leftover bytes from a previous call?
3084 if so, use them up first */
3085
3086 if( ns->b64_numleft > 0 ){
3087
3088 if( ns->b64_numleft >= nbytes ){ /* have enough leftovers for all! */
3089 memcpy( buffer , ns->b64_left , nbytes ) ;
3090 ns->b64_numleft -= nbytes ;
3091 if( ns->b64_numleft > 0 ) /* must shift remaining leftovers down */
3092 memmove( ns->b64_left , ns->b64_left + nbytes , ns->b64_numleft ) ;
3093 return nbytes ; /* done done done! */
3094 }
3095
3096 /* if here, have a few bytes leftover, but not enough */
3097
3098 memcpy( buffer , ns->b64_left , ns->b64_numleft ) ;
3099 nout = ns->b64_numleft ; /* how many so far */
3100 ns->b64_numleft = 0 ; /* have none left now */
3101 }
3102
3103 /* now need to decode some bytes from the input stream;
3104 this is done 4 input bytes at a time,
3105 which are decoded to 3 output bytes */
3106
3107 load_decode_table() ; /* prepare for Base64 decoding */
3108
3109 /** loopback point for reading more data from stream into internal buffer **/
3110
3111 num_reread = 0 ;
3112 Base64Reread:
3113 ag = bg = cg = 0 ;
3114 num_reread++ ; if( num_reread > 5 ) goto Base64Done ; /* done waiting! */
3115
3116 /* read more data into buffer, if needed */
3117
3118 if( num_reread > 1 || ns->nbuf - ns->npos < 4 ){
3119 NI_reset_buffer(ns) ; /* discard used up data => ns->npos==0 */
3120 ii = 5 - ns->nbuf ; if( ii <= 1 ) ii = 2 ;
3121 ii = NI_stream_fillbuf( ns , ii , 1666 ) ;
3122 if( ns->nbuf < 4 ) goto Base64Done ; /* can't get no satisfaction! */
3123 }
3124
3125 /*** Copy valid Base64 bytes out of buffer (skipping others),
3126 converting them to binary as we get full quads,
3127 putting the results into buffer.
3128
3129 Exit loop if we hit a '<' character (end of NIML element),
3130 or hit an '=' character (end of Base64 data stream).
3131
3132 Jump back to Base64Reread (above) if we run out of data in the
3133 buffer before we fulfill the caller's demand for nbytes of output. ***/
3134
3135 while( 1 ){
3136 ag = bg = cg = 0 ;
3137 bpos = ns->npos ; /* scan forward in buffer using bpos */
3138
3139 /* get next valid Base64 character into w;
3140 skip whitespaces and other non-Base64 stuff;
3141 if we hit the end token '<' first, quit;
3142 if we hit the end of the buffer first, need more data */
3143
3144 w = ns->buf[bpos++] ;
3145 while( !B64_goodchar(w) && w != '<' && bpos < ns->nbuf )
3146 w = ns->buf[bpos++] ;
3147 ns->npos = bpos-1 ; /** if we have to reread, will start here, at w **/
3148 if( w == '<' ) goto Base64Done;
3149 if( bpos == ns->nbuf ) goto Base64Reread; /* not enuf data yet */
3150
3151 /* repeat to fill x */
3152
3153 x = ns->buf[bpos++] ;
3154 while( !B64_goodchar(x) && x != '<' && bpos < ns->nbuf )
3155 x = ns->buf[bpos++] ;
3156 if( x == '<' ){ ns->npos = bpos-1; goto Base64Done; }
3157 if( bpos == ns->nbuf ) goto Base64Reread;
3158
3159 /* repeat to fill y */
3160
3161 y = ns->buf[bpos++] ;
3162 while( !B64_goodchar(y) && y != '<' && bpos < ns->nbuf )
3163 y = ns->buf[bpos++] ;
3164 if( y == '<' ){ ns->npos = bpos-1; goto Base64Done; }
3165 if( bpos == ns->nbuf ) goto Base64Reread;
3166
3167 /* repeat to fill z */
3168
3169 z = ns->buf[bpos++] ;
3170 while( !B64_goodchar(z) && z != '<' && bpos < ns->nbuf )
3171 z = ns->buf[bpos++] ;
3172 if( z == '<' ){ ns->npos = bpos-1; goto Base64Done; }
3173
3174 /* at this point, have w,x,y,z to decode */
3175
3176 ns->npos = bpos ; /* scan continues at next place in buffer */
3177
3178 B64_decode4(w,x,y,z,a,b,c) ; /* decode 4 bytes into 3 */
3179
3180 if( z == '=' ){ /* got to the end of Base64? */
3181 int nn = B64_decode_count(w,x,y,z) ; /* see how many bytes to save */
3182 ag = (nn > 0) ; /* a byte is good? */
3183 bg = (nn > 1) ; /* b byte is good? */
3184 cg = 0 ; /* c byte is bad!! */
3185
3186 /* save good bytes into output buffer;
3187 if we reach end of the required number of bytes, we're done */
3188
3189 if( ag ){ buffer[nout++]=a; ag=0; if(nout >= nbytes) goto Base64Done; }
3190 if( bg ){ buffer[nout++]=b; bg=0; if(nout >= nbytes) goto Base64Done; }
3191 goto Base64Done ;
3192 }
3193
3194 /* not at the end of Base64 =>
3195 save bytes, and skip out if we fill up the output array */
3196
3197 ag = bg = cg = 1 ; /* all 3 bytes are good */
3198 buffer[nout++]=a; ag=0; if(nout >= nbytes) goto Base64Done;
3199 buffer[nout++]=b; bg=0; if(nout >= nbytes) goto Base64Done;
3200 buffer[nout++]=c; cg=0; if(nout >= nbytes) goto Base64Done;
3201
3202 /* now, loop back to decode the next 4 bytes;
3203 BUT, if we don't have at least 4 bytes in the input buffer,
3204 must do a re-read first! */
3205
3206 num_reread = 1 ; /* finished at least 1 quad ==> reset penalty clock */
3207 if( ns->nbuf - ns->npos < 4 ) goto Base64Reread ;
3208
3209 } /* end of while(1) loop */
3210
3211 /* At this point:
3212 have finished reading and decoding,
3213 have nout bytes in output buffer,
3214 and might have some good bytes left that need to be saved */
3215
3216 Base64Done:
3217 ns->b64_numleft = 0 ;
3218 if( ag ) ns->b64_left[ ns->b64_numleft++ ] = a ;
3219 if( bg ) ns->b64_left[ ns->b64_numleft++ ] = b ;
3220 if( cg ) ns->b64_left[ ns->b64_numleft++ ] = c ;
3221
3222 return nout ;
3223 }
3224