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