00001
00002
00003
00004
00005
00006
00007 #include "thd_iochan.h"
00008 #include "Amalloc.h"
00009 #include <errno.h>
00010
00011 static char *error_string=NULL ;
00012
00013 char *iochan_error_string(void){ return error_string; }
00014
00015 #ifndef DONT_USE_SHM
00016 static int shm_RMID_delay = 0 ;
00017 #endif
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 static int pron = 1 ;
00065 void iochan_enable_perror( int q ){ pron = q; }
00066
00067 #undef DEBUG
00068 #ifdef DEBUG
00069 # define PERROR(x) perror(x)
00070 # define STATUS(x) fprintf(stderr,"%s\n",x)
00071 #else
00072 # define PERROR(x) do{ if(pron) perror(x); } while(0)
00073 # define STATUS(x)
00074 #endif
00075
00076
00077 #include <signal.h>
00078 static int nosigpipe = 0 ;
00079
00080 #define USE_SHUTDOWN
00081 #ifdef USE_SHUTDOWN
00082 # define CLOSEDOWN(ss) ( shutdown((ss),2) , close((ss)) )
00083 #else
00084 # define CLOSEDOWN(ss) close((ss))
00085 #endif
00086
00087
00088
00089 #define SOCKET_BUFSIZE (31*1024)
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 int tcp_readcheck( int sd , int msec )
00108 {
00109 int ii ;
00110 fd_set rfds ;
00111 struct timeval tv , * tvp ;
00112
00113 if( sd < 0 ){ STATUS("tcp_readcheck: illegal sd") ; return -1 ; }
00114
00115 FD_ZERO(&rfds) ; FD_SET(sd, &rfds) ;
00116
00117 if( msec >= 0 ){
00118 tv.tv_sec = msec/1000 ;
00119 tv.tv_usec = (msec%1000)*1000 ;
00120 tvp = &tv ;
00121 } else {
00122 tvp = NULL ;
00123 }
00124
00125
00126
00127 ii = select(sd+1, &rfds, NULL, NULL, tvp) ;
00128 if( ii == -1 ) PERROR( "Socket gone bad? tcp_readcheck[select]" ) ;
00129 return ii ;
00130 }
00131
00132 int tcp_writecheck( int sd , int msec )
00133 {
00134 int ii ;
00135 fd_set wfds ;
00136 struct timeval tv , * tvp ;
00137
00138 if( sd < 0 ){ STATUS("tcp_writecheck: illegal sd") ; return -1 ; }
00139
00140 FD_ZERO(&wfds) ; FD_SET(sd, &wfds) ;
00141
00142 if( msec >= 0 ){
00143 tv.tv_sec = msec/1000 ;
00144 tv.tv_usec = (msec%1000)*1000 ;
00145 tvp = &tv ;
00146 } else {
00147 tvp = NULL ;
00148 }
00149
00150
00151
00152 ii = select(sd+1, NULL , &wfds, NULL, tvp) ;
00153 if( ii == -1 ) PERROR( "Socket gone bad? tcp_writecheck[select]" ) ;
00154 return ii ;
00155 }
00156
00157
00158
00159
00160
00161 #ifdef USE_TCP_RECV
00162 int tcp_recv( int s , void * buf , int len , unsigned int flags )
00163 {
00164 int ii ;
00165
00166 while(1){
00167 ii = recv( s , buf , len , flags ) ;
00168 if( ii >= 0 ) return ii ;
00169 if( errno != EINTR ) return ii ;
00170 }
00171 return 0 ;
00172 }
00173 #endif
00174
00175
00176
00177
00178
00179 void tcp_set_cutoff( int sd )
00180 {
00181 #ifdef SO_LINGER
00182 { struct linger lg ;
00183 lg.l_onoff = 1 ;
00184 lg.l_linger = 0 ;
00185 setsockopt(sd, SOL_SOCKET, SO_LINGER, (void *)&lg, sizeof(struct linger)) ;
00186 }
00187 #endif
00188 #ifdef SO_REUSEADDR
00189 { int optval = 1;
00190 setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) ;
00191 }
00192 #endif
00193 return ;
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203 int tcp_alivecheck( int sd )
00204 {
00205 int ii ;
00206 char bbb[4] ;
00207
00208 ii = tcp_readcheck(sd,0) ;
00209 if( ii == 0 ) return 1 ;
00210 if( ii < 0 ) return 0 ;
00211 errno = 0 ;
00212 ii = tcp_recv( sd , bbb , 1 , MSG_PEEK ) ;
00213 if( ii == 1 ) return 1 ;
00214 if( errno ) PERROR("Socket gone bad? tcp_alivecheck") ;
00215 return 0 ;
00216 }
00217
00218
00219
00220
00221
00222
00223 int tcp_connect( char * host , int port )
00224 {
00225 int sd , l ;
00226 struct sockaddr_in sin ;
00227 struct hostent * hostp ;
00228
00229 if( host == NULL || port < 1 ){ STATUS("tcp_connect: illegal inputs") ; return -1 ; }
00230
00231
00232
00233 sd = socket( AF_INET , SOCK_STREAM , 0 ) ;
00234 if( sd == -1 ){ PERROR("Can't create? tcp_connect[socket]"); return -1; }
00235
00236
00237
00238 #if 0
00239 l = 1;
00240 setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *)&l, sizeof(int)) ;
00241 #endif
00242 l = SOCKET_BUFSIZE ;
00243 setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&l, sizeof(int)) ;
00244 setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&l, sizeof(int)) ;
00245
00246
00247
00248 memset( &sin , 0 , sizeof(sin) ) ;
00249 sin.sin_family = AF_INET ;
00250 sin.sin_port = htons(port) ;
00251
00252
00253
00254 hostp = gethostbyname(host) ;
00255 if( hostp == NULL ){
00256 PERROR("Can't lookup? tcp_connect[gethostbyname]"); CLOSEDOWN(sd); return -1;
00257 }
00258 sin.sin_addr.s_addr = ((struct in_addr *)(hostp->h_addr))->s_addr ;
00259
00260 if( connect(sd , (struct sockaddr *)&sin , sizeof(sin)) == -1 ){
00261 PERROR("Can't connect? tcp_connect[connect]") ; CLOSEDOWN(sd); return -1;
00262 }
00263
00264 return sd ;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 int tcp_listen( int port )
00277 {
00278 int sd , l ;
00279 struct sockaddr_in sin ;
00280
00281 if( port < 1 ){ STATUS("tcp_listen: illegal port") ; return -1 ; }
00282
00283
00284
00285 sd = socket( AF_INET , SOCK_STREAM , 0 ) ;
00286 if( sd == -1 ){ PERROR("Can't create? tcp_listen[socket]"); return -1; }
00287
00288
00289
00290 #if 0
00291 l = 1;
00292 setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *)&l, sizeof(int)) ;
00293 #endif
00294 l = SOCKET_BUFSIZE ;
00295 setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&l, sizeof(int)) ;
00296 setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&l, sizeof(int)) ;
00297
00298
00299
00300 memset( &sin , 0 , sizeof(sin) ) ;
00301 sin.sin_family = AF_INET ;
00302 sin.sin_port = htons(port) ;
00303 sin.sin_addr.s_addr = INADDR_ANY ;
00304
00305 if( bind(sd , (struct sockaddr *)&sin , sizeof(sin)) == -1 ){
00306 PERROR("Can't bind? tcp_listen[bind]"); CLOSEDOWN(sd); return -1;
00307 }
00308
00309 if( listen(sd,1) == -1 ){
00310 PERROR("Can't listen? tcp_listen[listen]"); CLOSEDOWN(sd); return -1;
00311 }
00312
00313 return sd ;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 int tcp_accept( int sd , char ** hostname , char ** hostaddr )
00339 {
00340 struct sockaddr_in pin ;
00341 int addrlen , sd_new ;
00342 struct hostent * hostp ;
00343 char * sout , * str ;
00344
00345
00346
00347
00348
00349 addrlen = sizeof(pin) ;
00350 sd_new = accept( sd , (struct sockaddr *)&pin , &addrlen ) ;
00351 if( sd_new == -1 ){ PERROR("Can't accept? tcp_accept"); return -1; }
00352
00353
00354
00355 if( hostname != NULL ){
00356 hostp = gethostbyaddr( (char *) (&pin.sin_addr) ,
00357 sizeof(struct in_addr) , AF_INET ) ;
00358 if( hostp != NULL ){
00359 sout = (char *) malloc( strlen(hostp->h_name)+1 ) ;
00360 strcpy(sout,hostp->h_name) ;
00361 } else {
00362 sout = (char *) malloc( strlen("UNKNOWN")+1 ) ;
00363 strcpy(sout,"UNKNOWN") ;
00364 }
00365 *hostname = sout ;
00366 }
00367
00368
00369
00370 if( hostaddr != NULL ){
00371 str = inet_ntoa( pin.sin_addr ) ;
00372 sout = (char *) malloc( strlen(str)+1 ) ;
00373 strcpy(sout,str) ;
00374 *hostaddr = sout ;
00375 }
00376
00377 return sd_new ;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 key_t string_to_key( char * key_string )
00389 {
00390 int ii , sum ;
00391
00392 sum = 666 ;
00393 if( key_string == NULL ) return (key_t) sum ;
00394
00395 for( ii=0 ; key_string[ii] != '\0' ; ii++ )
00396 sum += ((int)key_string[ii]) << ((ii%3)*8) ;
00397
00398 if( sum < 0 ) sum = -sum ;
00399 else if( sum == 0 ) sum = 314159265 ;
00400
00401 return (key_t) sum ;
00402 }
00403
00404 #ifndef DONT_USE_SHM
00405
00406
00407
00408
00409
00410 int shm_accept( char * key_string )
00411 {
00412 key_t key ;
00413 int shmid ;
00414
00415 key = string_to_key( key_string ) ;
00416 shmid = shmget( key , 0 , 0777 ) ;
00417 return shmid ;
00418 }
00419
00420
00421
00422
00423
00424
00425 int shm_create( char * key_string , int size )
00426 {
00427 key_t key ;
00428 int shmid ;
00429
00430 key = string_to_key( key_string ) ;
00431 shmid = shmget( key , size , 0777 | IPC_CREAT ) ;
00432 if( shmid < 0 ){
00433 PERROR("Can't create? shm_create") ;
00434 if( pron ) fprintf(stderr,"key_string=%s key=%d size=%d\n",
00435 key_string , (int)key , size ) ;
00436 }
00437 return shmid ;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446 char * shm_attach( int shmid )
00447 {
00448 char * adr ;
00449 adr = (char *) shmat( shmid , NULL , 0 ) ;
00450 if( adr == (char *) -1 ){
00451 adr = NULL ; PERROR("Can't attach? shm_attach") ;
00452 }
00453 return adr ;
00454 }
00455
00456
00457
00458
00459
00460
00461 int shm_size( int shmid )
00462 {
00463 int ii ;
00464 struct shmid_ds buf ;
00465
00466 if( shmid < 0 ) return -1 ;
00467 ii = shmctl( shmid , IPC_STAT , &buf ) ;
00468 if( ii < 0 ){ PERROR("Can't check? shm_size"); return -1; }
00469 return buf.shm_segsz ;
00470 }
00471
00472
00473
00474
00475
00476
00477 int shm_nattach( int shmid )
00478 {
00479 int ii ;
00480 struct shmid_ds buf ;
00481
00482 if( shmid < 0 ){ STATUS("shm_nattach: illegal shmid") ; return -1 ; }
00483 errno = 0 ;
00484 ii = shmctl( shmid , IPC_STAT , &buf ) ;
00485 if( ii < 0 ){
00486 PERROR("Has shared memory buffer gone bad? shm_nattach") ;
00487 return -1 ;
00488 }
00489 return buf.shm_nattch ;
00490 }
00491
00492 #else
00493
00494 int shm_nattach( int shmid ) { return -1 ; }
00495 int shm_size ( int shmid ) { return -1 ; }
00496 char * shm_attach ( int shmid ) { return NULL;}
00497 int shm_create ( char * key_string , int size ){ return -1 ; }
00498 int shm_accept ( char * key_string ) { return -1 ; }
00499
00500 #endif
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 IOCHAN * iochan_init( char * name , char * mode )
00547 {
00548 IOCHAN * ioc ;
00549 int do_create , do_accept ;
00550
00551
00552
00553 #ifndef DONT_USE_SHM
00554 { static int first=1 ;
00555 if( first ){
00556 char *eee = getenv("IOCHAN_DELAY_RMID") ;
00557 shm_RMID_delay = ( eee != NULL && (*eee=='Y' || *eee=='y') ) ;
00558 first = 0 ;
00559 }
00560 }
00561 #endif
00562
00563
00564
00565 error_string = NULL ;
00566
00567 if( name == NULL || strlen(name) < 6 || strlen(name) > 127 ){
00568 error_string = "iochan_init: bad name" ; return NULL ;
00569 }
00570
00571 if( mode == NULL ){
00572 error_string = "iochan_init: bad mode" ; return NULL ;
00573 }
00574
00575 do_create = (strcmp(mode,"create") == 0 || strcmp(mode,"w") == 0) ;
00576 do_accept = (strcmp(mode,"accept") == 0 || strcmp(mode,"r") == 0) ;
00577
00578 if( !do_create && !do_accept ){
00579 error_string = "iochan_init: bad mode" ; return NULL ;
00580 }
00581
00582 #ifdef DEBUG
00583 fprintf(stderr,"iochan_init: name=%s mode=%s\n",name,mode) ;
00584 #endif
00585
00586
00587
00588 if( strncmp(name,"tcp:",4) == 0 ){
00589 char host[128] , * hend ;
00590 int port=-1 , ii , jj ;
00591
00592
00593
00594 hend = strstr( name+4 , ":" ) ;
00595 if( hend == NULL || hend-name > 128 ){
00596 error_string = "iochan_init: bad name" ; return NULL ;
00597 }
00598 for( ii=4 ; name[ii] != ':' ; ii++ ) host[ii-4] = name[ii] ;
00599 host[ii-4] = '\0' ;
00600
00601
00602
00603 port = strtol( name+ii+1 , NULL , 10 ) ;
00604 if( port <= 0 ){
00605 error_string = "iochan_init: bad port" ; return NULL ;
00606 }
00607
00608
00609
00610 ioc = (IOCHAN *) malloc( sizeof(IOCHAN) ) ;
00611
00612 ioc->type = TCP_IOCHAN ;
00613 ioc->port = port ;
00614 ioc->bufsize = 0 ;
00615 ioc->buf = NULL ;
00616 ioc->sendsize = 0 ;
00617 ioc->ioc2 = NULL ;
00618
00619
00620
00621 if( do_accept ){
00622 ioc->whoami = ACCEPTOR ;
00623 ioc->id = tcp_listen( port ) ;
00624 if( ioc->id < 0 ){
00625 error_string = "iochan_init: tcp_listen fails" ;
00626 free(ioc) ; return NULL ;
00627 }
00628 ioc->bad = TCP_WAIT_ACCEPT ;
00629 ii = tcp_readcheck(ioc->id,1) ;
00630 if( ii > 0 ){
00631 jj = tcp_accept( ioc->id , NULL,&hend ) ;
00632 if( jj >= 0 ){
00633 CLOSEDOWN( ioc->id ) ;
00634 strcpy( ioc->name , hend ) ;
00635 free(hend) ; ioc->bad = 0 ; ioc->id = jj ;
00636 }
00637 }
00638 return ioc ;
00639 }
00640
00641
00642
00643 if( do_create ){
00644 struct hostent * hostp ;
00645 ioc->whoami = CREATOR ;
00646 hostp = gethostbyname(host) ;
00647 if( hostp == NULL ){
00648 error_string = "iochan_init: gethostbyname fails" ;
00649 free(ioc) ; return NULL ;
00650 }
00651 ioc->id = tcp_connect( host , port ) ;
00652 ioc->bad = (ioc->id < 0) ? TCP_WAIT_CONNECT : 0 ;
00653 strcpy( ioc->name , host ) ;
00654 return ioc ;
00655 }
00656 return NULL ;
00657 }
00658
00659
00660
00661 if( strncmp(name,"shm:",4) == 0 ){
00662 char key[128] , * kend , shm2[256] ;
00663 int size=-1 , ii , jj , size2=-1 ;
00664
00665 #ifdef DONT_USE_SHM
00666 return NULL ;
00667 #endif
00668
00669
00670
00671 kend = strstr( name+4 , ":" ) ;
00672 if( kend == NULL || kend-name > 128 ){
00673 error_string = "iochan_init: bad name" ; return NULL ;
00674 }
00675 for( ii=4 ; name[ii] != ':' ; ii++ ) key[ii-4] = name[ii] ;
00676 key[ii-4] = '\0' ;
00677
00678
00679
00680 size = strtol( name+ii+1 , &kend , 10 ) ;
00681 if( size < 0 || (size == 0 && do_create) ){
00682 error_string = "iochan_init: bad size" ; return NULL ;
00683 }
00684 if( *kend == 'K' || *kend == 'k' ){ size *= 1024 ; kend++ ; }
00685 else if( *kend == 'M' || *kend == 'm' ){ size *= 1024*1024 ; kend++ ; }
00686
00687
00688
00689 if( *kend == '+' ){
00690 size2 = strtol( kend+1 , &kend , 10 ) ;
00691 if( size2 < 0 || (size2 == 0 && do_create) ){
00692 error_string = "iochan_init: bad size2" ; return NULL ;
00693 }
00694 if( *kend == 'K' || *kend == 'k' ){ size2 *= 1024 ; kend++ ; }
00695 else if( *kend == 'M' || *kend == 'm' ){ size2 *= 1024*1024 ; kend++ ; }
00696
00697 sprintf(shm2,"shm:%s++:%d",key,size2) ;
00698 } else {
00699 shm2[0] = '\0' ;
00700 }
00701
00702
00703
00704 ioc = (IOCHAN *) malloc( sizeof(IOCHAN) ) ;
00705
00706 ioc->type = SHM_IOCHAN ;
00707 strcpy( ioc->name , key ) ;
00708 ioc->ioc2 = NULL ;
00709
00710
00711
00712 if( shm2[0] != '\0' ){
00713 ioc->ioc2 = iochan_init( shm2 , mode ) ;
00714 if( ioc->ioc2 == NULL ){
00715 error_string = "iochan_init: can't open shm2" ;
00716 free(ioc) ; return NULL ;
00717 }
00718 #ifdef DEBUG
00719 fprintf(stderr,"iochan_init: input=%s shm2=%s\n",name,shm2) ;
00720 #endif
00721 }
00722
00723
00724
00725 if( do_accept ){
00726 ioc->whoami = ACCEPTOR ;
00727 for( ii=0 ; ii < 2 ; ii++ ){
00728 ioc->id = shm_accept( key ) ;
00729 if( ioc->id >= 0 ) break ;
00730 iochan_sleep(1) ;
00731 }
00732 if( ioc->id < 0 ) ioc->id = shm_accept( key ) ;
00733
00734 if( ioc->id < 0 ){
00735 ioc->bad = SHM_WAIT_CREATE ;
00736
00737 } else {
00738 char * bbb ;
00739 bbb = shm_attach( ioc->id ) ;
00740 if( bbb == NULL ){
00741 error_string = "iochan_init: shm_attach fails" ;
00742 iochan_close(ioc) ; return NULL ;
00743 }
00744 ioc->bstart = (int *) bbb ;
00745 ioc->bend = (int *) (bbb + sizeof(int)) ;
00746 ioc->buf = bbb + 2*sizeof(int) ;
00747 ioc->bufsize = shm_size(ioc->id) - 2*sizeof(int) ;
00748 if( ioc->bufsize <= 0 ){
00749 error_string = "iochan_init: bufsize < 0" ;
00750 iochan_close(ioc) ; return NULL ;
00751 }
00752 ioc->bad = 0 ;
00753 }
00754 return ioc ;
00755 }
00756
00757
00758
00759 if( do_create ){
00760 char * bbb ;
00761 ioc->whoami = CREATOR ;
00762 size = size + 1 ;
00763 ioc->id = shm_create( key , size+2*sizeof(int) ) ;
00764 if( ioc->id < 0 ){
00765 error_string = "iochan_init: shm_create fails" ;
00766 iochan_close(ioc->ioc2) ; free(ioc) ; return NULL ;
00767 }
00768 bbb = shm_attach( ioc->id ) ;
00769 if( bbb == NULL ){
00770 error_string = "iochan_init: shm_attach fails" ;
00771 iochan_close(ioc) ; free(ioc) ; return NULL ;
00772 }
00773 ioc->bstart = (int *) bbb ;
00774 ioc->bend = (int *) (bbb + sizeof(int)) ;
00775 *(ioc->bstart) = 0 ;
00776 *(ioc->bend) = size-1 ;
00777 ioc->buf = bbb + 2*sizeof(int) ;
00778 ioc->bufsize = size ;
00779 ioc->bad = (shm_nattach(ioc->id) < 2)
00780 ? SHM_WAIT_ACCEPT
00781 : 0 ;
00782 return ioc ;
00783 }
00784 return NULL ;
00785 }
00786
00787 return NULL ;
00788 }
00789
00790
00791
00792
00793
00794
00795 int shm_alivecheck( int shmid )
00796 {
00797 if( shmid < 0 ) return 0 ;
00798 return (shm_nattach(shmid) >= 2) ;
00799 }
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810 int iochan_goodcheck( IOCHAN * ioc , int msec )
00811 {
00812 int ii , jj ;
00813 char * bbb ;
00814
00815
00816
00817 error_string = NULL ;
00818
00819 if( ioc == NULL ){
00820 error_string = "iochan_goodcheck: bad input" ; return -1 ;
00821 }
00822
00823
00824
00825 if( IOC_BAD(ioc) == 0 ){
00826 int ich = 1 ;
00827
00828 if( ioc->type == TCP_IOCHAN ){
00829 ich = tcp_alivecheck(ioc->id) ;
00830 } else if( ioc->type == SHM_IOCHAN ){
00831 ich = shm_alivecheck(ioc->id) ;
00832 if( ich && ioc->ioc2 != NULL )
00833 ich = shm_alivecheck(ioc->ioc2->id) ;
00834 }
00835
00836 if( ich == 0 ){
00837 error_string = "iochan_goodcheck: no longer alive" ; return -1 ;
00838 }
00839 else
00840 return 1 ;
00841 }
00842
00843
00844
00845
00846
00847 if( ioc->bad == TCP_WAIT_ACCEPT ){
00848 ii = tcp_readcheck(ioc->id,msec) ;
00849 if( ii > 0 ){
00850 STATUS("iochan_goodcheck: try to accept tcp");
00851 jj = tcp_accept( ioc->id , NULL,&bbb ) ;
00852 if( jj >= 0 ){
00853 STATUS("iochan_goodcheck: accept worked!") ;
00854 CLOSEDOWN( ioc->id ) ;
00855 strcpy( ioc->name , bbb ) ;
00856 free(bbb) ; ioc->bad = 0 ; ioc->id = jj ;
00857 } else {
00858 STATUS("iochan_goodcheck: accept failed!") ;
00859 }
00860 }
00861 }
00862
00863
00864
00865 else if( ioc->bad == TCP_WAIT_CONNECT ){
00866 int dms=0 , ms ;
00867
00868 if( msec < 0 ) msec = 999999999 ;
00869 for( ms=0 ; ms < msec ; ms += dms ){
00870 ioc->id = tcp_connect( ioc->name , ioc->port ) ;
00871 if( ioc->id >= 0 ) break ;
00872 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
00873 }
00874 if( ioc->id < 0 )
00875 ioc->id = tcp_connect( ioc->name , ioc->port ) ;
00876
00877 if( ioc->id >= 0 ) ioc->bad = 0 ;
00878 }
00879
00880
00881
00882 else if( ioc->bad == SHM_WAIT_CREATE ){
00883 int dms=0 , ms ;
00884
00885 if( msec < 0 ) msec = 999999999 ;
00886 for( ms=0 ; ms < msec ; ms += dms ){
00887 ioc->id = shm_accept( ioc->name ) ;
00888 if( ioc->id >= 0 ) break ;
00889 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
00890 }
00891 if( ioc->id < 0 )
00892 ioc->id = shm_accept( ioc->name ) ;
00893
00894 if( ioc->id >= 0 ){
00895 char * bbb ;
00896 bbb = shm_attach( ioc->id ) ;
00897 ioc->bstart = (int *) bbb ;
00898 ioc->bend = (int *) (bbb + sizeof(int)) ;
00899 ioc->buf = bbb + 2*sizeof(int) ;
00900 ioc->bufsize = shm_size(ioc->id) - 2*sizeof(int) ;
00901 ioc->bad = 0 ;
00902 }
00903 }
00904
00905
00906
00907 else if( ioc->bad == SHM_WAIT_ACCEPT ){
00908 int dms=0 , ms ;
00909
00910 if( msec < 0 ) msec = 999999999 ;
00911 for( ms=0 ; ms < msec ; ms += dms ){
00912 if( shm_nattach(ioc->id) > 1 ){ ioc->bad = 0 ; break ; }
00913 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
00914 }
00915 if( ioc->bad && shm_nattach(ioc->id) > 1 ) ioc->bad = 0 ;
00916 }
00917
00918
00919
00920 if( ioc->ioc2 != NULL && ioc->ioc2->bad != 0 )
00921 iochan_goodcheck( ioc->ioc2 , msec ) ;
00922
00923 return ( IOC_BAD(ioc) == 0 ) ;
00924 }
00925
00926
00927
00928
00929
00930
00931 void iochan_close( IOCHAN * ioc )
00932 {
00933 if( ioc == NULL ) return ;
00934
00935 if( ioc->ioc2 != NULL ) iochan_close(ioc->ioc2) ;
00936
00937 if( ioc->type == TCP_IOCHAN ){
00938 if( ioc->id >= 0 ) CLOSEDOWN(ioc->id) ;
00939 }
00940
00941 else if( ioc->type == SHM_IOCHAN ){
00942 #ifndef DONT_USE_SHM
00943 if( ioc->id >= 0 ){
00944 shmdt( (char *) ioc->bstart ) ;
00945
00946 if( !shm_RMID_delay || shm_nattach(ioc->id) < 1 )
00947 shmctl( ioc->id , IPC_RMID , NULL ) ;
00948 }
00949 #endif
00950 }
00951
00952 free( ioc ) ; return ;
00953 }
00954
00955 void iochan_set_cutoff( IOCHAN * ioc )
00956 {
00957 if( ioc == NULL ) return ;
00958
00959 if( ioc->type == TCP_IOCHAN && ioc->id >= 0 ) tcp_set_cutoff( ioc->id ) ;
00960 return ;
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974 int iochan_readcheck( IOCHAN * ioc , int msec )
00975 {
00976 int ii ;
00977
00978
00979
00980 error_string = NULL ;
00981
00982 ii = iochan_goodcheck(ioc,0) ;
00983 if( ii == -1 ) return -1 ;
00984 if( ii == 0 ){
00985 ii = iochan_goodcheck(ioc,msec) ;
00986 if( ii != 1 ) return 0 ;
00987 }
00988
00989
00990
00991 if( ioc->type == TCP_IOCHAN ){
00992 ii = tcp_alivecheck( ioc->id ) ; if( !ii ) return -1 ;
00993 ii = tcp_readcheck( ioc->id , msec ) ;
00994 if( ii < 0 ) error_string = "iochan_readcheck: socket is bad" ;
00995 return ii ;
00996 }
00997
00998
00999
01000 if( ioc->type == SHM_IOCHAN ){
01001 int nread , dms=0 , ms ;
01002
01003 if( msec < 0 ) msec = 999999999 ;
01004
01005
01006
01007
01008
01009 ioc = SHMIOC_READ(ioc) ;
01010
01011 for( ms=0 ; ms < msec ; ms += dms ){
01012 nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01013 if( nread > 0 ) return nread ;
01014 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
01015 ii = iochan_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
01016 }
01017 nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01018 if( nread > 0 ) return nread ;
01019 return 0 ;
01020 }
01021
01022 return -1 ;
01023 }
01024
01025
01026
01027
01028
01029
01030
01031 #define QBUF 1024
01032
01033 int iochan_force_clear( IOCHAN * ioc )
01034 {
01035 int ii , ntot = 0 ;
01036 char qbuf[QBUF] ;
01037
01038 do{
01039 ii = iochan_readcheck(ioc,0) ;
01040 if( ii == -1 ) return -1 ;
01041 if( ii == 0 ) return ntot ;
01042
01043 ii = iochan_recv( ioc , qbuf , QBUF ) ;
01044 if( ii == -1 ) return -1 ;
01045 ntot += ii ;
01046
01047 } while( 1 ) ;
01048
01049 return -1 ;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 int iochan_clearcheck( IOCHAN * ioc , int msec )
01062 {
01063 int ii ;
01064
01065
01066
01067 error_string = NULL ;
01068
01069 ii = iochan_goodcheck(ioc,0) ;
01070 if( ii == -1 ) return -1 ;
01071 if( ii == 0 ) return 1 ;
01072
01073
01074
01075 if( ioc->type == TCP_IOCHAN ) return ( tcp_readcheck(ioc->id,msec) == 0 ) ;
01076
01077
01078
01079 if( ioc->type == SHM_IOCHAN ){
01080 int nread , dms=0 , ms ;
01081
01082 if( msec < 0 ) msec = 999999999 ;
01083
01084 ioc = SHMIOC_WRITE(ioc) ;
01085
01086 for( ms=0 ; ms < msec ; ms += dms ){
01087 nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01088 if( nread == 0 ) return 1 ;
01089 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
01090 ii = iochan_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
01091 }
01092 nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01093 return (nread == 0) ;
01094 }
01095
01096 return -1 ;
01097 }
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110 int iochan_writecheck( IOCHAN * ioc , int msec )
01111 {
01112 int ii ;
01113
01114
01115
01116 error_string = NULL ;
01117
01118 ii = iochan_goodcheck(ioc,0) ;
01119 if( ii == -1 ) return -1 ;
01120 if( ii == 0 ){
01121 ii = iochan_goodcheck(ioc,msec) ;
01122 if( ii != 1 ) return ii ;
01123 }
01124
01125
01126
01127 if( ioc->type == TCP_IOCHAN ){
01128 ii = tcp_writecheck( ioc->id , msec ) ;
01129 if( ii == -1 ) error_string = "iochan_writecheck: socket not ready" ;
01130 return ii ;
01131 }
01132
01133
01134
01135 if( ioc->type == SHM_IOCHAN ){
01136 int nread , dms=0 , ms , nwrite ;
01137
01138 if( msec < 0 ) msec = 999999999 ;
01139
01140 ioc = SHMIOC_WRITE(ioc) ;
01141
01142
01143
01144
01145 for( ms=0 ; ms < msec ; ms += dms ){
01146 nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01147 nwrite = ioc->bufsize - 1 - nread ;
01148 if( nwrite > 0 ) return nwrite ;
01149 dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
01150 ii = iochan_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
01151 }
01152 nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01153 nwrite = ioc->bufsize - 1 - nread ;
01154 if( nwrite > 0 ) return nwrite ;
01155 return 0 ;
01156 }
01157
01158 return -1 ;
01159 }
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 int iochan_send( IOCHAN * ioc , char * buffer , int nbytes )
01177 {
01178 int ii ;
01179
01180
01181
01182 error_string = NULL ;
01183
01184 if( ioc == NULL || IOC_BAD(ioc) != 0 ||
01185 buffer == NULL || nbytes < 0 ){
01186
01187 error_string = "iochan_send: bad inputs" ; return -1 ;
01188 }
01189
01190 if( nbytes == 0 ) return 0 ;
01191
01192 ii = iochan_goodcheck(ioc,0) ;
01193 if( ii != 1 ){
01194 if( error_string == NULL )
01195 error_string = "iochan_send: iochan_goodcheck fails" ;
01196 return ii ;
01197 }
01198
01199 ii = iochan_writecheck(ioc,1) ;
01200 if( ii <= 0 ){
01201 if( error_string == NULL )
01202 error_string = "iochan_send: iochan_writecheck fails" ;
01203 return ii ;
01204 }
01205
01206
01207
01208 if( ioc->type == TCP_IOCHAN ){
01209 if( !nosigpipe ){ signal( SIGPIPE , SIG_IGN ) ; nosigpipe = 1 ; }
01210
01211 if( ioc->sendsize <= 0 || nbytes <= ioc->sendsize ){
01212 int nsent = send( ioc->id , buffer , nbytes , 0 ) ;
01213 if( nsent == -1 ) PERROR("Can't use socket? tcp[send]") ;
01214 if( nsent < 0 ) error_string = "iochan_send: tcp send fails" ;
01215 return nsent ;
01216 } else {
01217 int nsent , ntosend , ntot = 0 ;
01218 do{
01219 while( tcp_writecheck(ioc->id,1) == 0 ) ;
01220 ntosend = MIN( ioc->sendsize , nbytes-ntot ) ;
01221 nsent = send( ioc->id , buffer+ntot , ntosend , 0 ) ;
01222 if( nsent == -1 ) PERROR("Can't use socket? tcp[send]") ;
01223 if( nsent <= 0 ){
01224 error_string = "iochan_send: tcp send fails" ;
01225 return ((ntot>0) ? ntot : nsent) ;
01226 }
01227 ntot += nsent ;
01228 } while( ntot < nbytes ) ;
01229 return ntot ;
01230 }
01231 }
01232
01233
01234
01235 if( ioc->type == SHM_IOCHAN ){
01236 int nread,nwrite , bend,bstart , ebot,etop , size ;
01237
01238 ioc = SHMIOC_WRITE(ioc) ;
01239
01240 bend = *(ioc->bend) ; bstart = *(ioc->bstart) ; size = ioc->bufsize ;
01241 nread = ( bend - bstart + size + 1 ) % size ;
01242 nwrite = size - 1 - nread ;
01243 if( nwrite <= 0 ) return 0 ;
01244
01245 if( nwrite > nbytes ) nwrite = nbytes ;
01246
01247 ebot = bend+1 ; if( ebot >= size ) ebot = 0 ;
01248 etop = ebot+nwrite-1 ;
01249
01250 if( etop < size ){
01251 BCOPY( ioc->buf + ebot, buffer, nwrite ) ;
01252 *(ioc->bend) = etop ;
01253 #ifdef DEBUG
01254 fprintf(stderr,"iochan_send: shm 1 piece: %d to %d\n",ebot,etop) ;
01255 #endif
01256
01257 } else {
01258 int nn = size - ebot ;
01259 BCOPY( ioc->buf + ebot, buffer , nn ) ;
01260 BCOPY( ioc->buf , buffer+nn, nwrite-nn ) ;
01261 *(ioc->bend) = nwrite-nn-1 ;
01262 #ifdef DEBUG
01263 fprintf(stderr,"iochan_send: shm 2 pieces: %d to %d AND %d to %d\n",
01264 ebot,ebot+nn-1,0,nwrite-nn-1) ;
01265 #endif
01266
01267 }
01268 return nwrite ;
01269 }
01270
01271 return -1 ;
01272 }
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282 int iochan_sendall( IOCHAN * ioc , char * buffer , int nbytes )
01283 {
01284 int ii , ntot=0 , dms=0 ;
01285
01286 error_string = NULL ;
01287
01288
01289
01290 if( ioc == NULL || IOC_BAD(ioc) != 0 ||
01291 buffer == NULL || nbytes < 0 ){
01292
01293 error_string = "iochan_sendall: bad inputs" ; return -1 ;
01294 }
01295
01296 if( nbytes == 0 ) return 0 ;
01297
01298 while(1){
01299 ii = iochan_send( ioc , buffer+ntot , nbytes-ntot );
01300 if( ii == -1 ){
01301 if( error_string == NULL )
01302 error_string = "iochan_sendall: iochan_send fails" ;
01303 return -1 ;
01304 }
01305 ntot += ii ;
01306 if( ntot == nbytes ) return nbytes ;
01307 dms = NEXTDMS(dms) ; iochan_sleep(dms) ;
01308 }
01309 return -1 ;
01310 }
01311
01312
01313
01314
01315
01316
01317
01318
01319 int iochan_recv( IOCHAN * ioc , char * buffer , int nbytes )
01320 {
01321
01322
01323 error_string = NULL ;
01324
01325 if( ioc == NULL || IOC_BAD(ioc) != 0 ||
01326 buffer == NULL || nbytes < 0 ){
01327
01328 error_string = "iochan_recv: bad inputs" ; return -1 ;
01329 }
01330
01331 if( nbytes == 0 ) return 0 ;
01332 if( iochan_goodcheck(ioc,0) != 1 ) return -1 ;
01333
01334
01335
01336 if( ioc->type == TCP_IOCHAN ){
01337 int ii = tcp_recv( ioc->id , buffer , nbytes , 0 ) ;
01338 if( ii == -1 ){
01339 PERROR("Can't read from socket? tcp[recv]") ;
01340 error_string = "iochan_recv: tcp recv fails" ;
01341 }
01342 return ii ;
01343 }
01344
01345
01346
01347 if( ioc->type == SHM_IOCHAN ){
01348 int nread, bend,bstart , size , sbot,stop ;
01349
01350 ioc = SHMIOC_READ(ioc) ;
01351
01352 bend = *(ioc->bend) ; bstart = *(ioc->bstart) ; size = ioc->bufsize ;
01353 nread = ( bend - bstart + size + 1 ) % size ;
01354 if( nread <= 0 ) return 0 ;
01355 if( nread > nbytes ) nread = nbytes ;
01356
01357 sbot = bstart ; stop = sbot + nread-1 ;
01358
01359 if( stop < size ){
01360 BCOPY( buffer, ioc->buf + sbot, nread ) ;
01361 *(ioc->bstart) = (stop+1) % size ;
01362 #ifdef DEBUG
01363 fprintf(stderr,"iochan_recv: get 1 piece: %d to %d\n",sbot,stop) ;
01364 #endif
01365
01366 } else {
01367 int nn = size - sbot ;
01368 BCOPY( buffer , ioc->buf + sbot, nn ) ;
01369 BCOPY( buffer+nn, ioc->buf , nread-nn ) ;
01370 *(ioc->bstart) = nread-nn ;
01371 #ifdef DEBUG
01372 fprintf(stderr,"iochan_recv: get 2 pieces: %d to %d AND %d to %d\n",
01373 sbot,sbot+nn-1,0,nread-nn-1) ;
01374 #endif
01375
01376 }
01377 return nread ;
01378 }
01379
01380 return -1 ;
01381 }
01382
01383
01384
01385
01386
01387
01388 int iochan_recvloop( IOCHAN * ioc , char * buffer , int nbytes )
01389 {
01390 int jj , nbuf=0 ;
01391
01392 error_string = NULL ;
01393
01394
01395
01396 if( ioc == NULL || IOC_BAD(ioc) != 0 ||
01397 buffer == NULL || nbytes < 0 ){
01398
01399 error_string = "iochan_recvloop: bad inputs" ; return -1 ;
01400 }
01401
01402 if( iochan_goodcheck(ioc,0) != 1 ) return -1 ;
01403
01404 if( nbytes == 0 ) return 0 ;
01405
01406 while(1){
01407 jj = iochan_recv( ioc , buffer+nbuf , nbytes-nbuf ) ;
01408 if( jj < 1 ) break ;
01409 nbuf += jj ;
01410 if( nbuf >= nbytes ) break ;
01411 iochan_sleep(1) ;
01412 }
01413
01414 return nbuf ;
01415 }
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 int iochan_recvall( IOCHAN * ioc , char * buffer , int nbytes )
01426 {
01427 int ii , ntot=0 , dms=0 ;
01428
01429
01430
01431 error_string = NULL ;
01432
01433 if( ioc == NULL || IOC_BAD(ioc) != 0 ||
01434 buffer == NULL || nbytes < 0 ){
01435
01436 error_string = "iochan_recvall: bad inputs" ; return -1 ;
01437 }
01438
01439 if( nbytes == 0 ) return 0 ;
01440
01441 while(1){
01442 ii = iochan_recv( ioc , buffer+ntot , nbytes-ntot ) ;
01443 if( ii == -1 ) return -1 ;
01444 ntot += ii ;
01445 if( ntot == nbytes ) return nbytes ;
01446 dms = NEXTDMS(dms) ; iochan_sleep(dms) ;
01447 }
01448 return -1 ;
01449 }
01450
01451
01452
01453
01454
01455 void iochan_sleep( int msec )
01456 {
01457 struct timeval tv ;
01458 if( msec <= 0 ) return ;
01459 tv.tv_sec = msec/1000 ;
01460 tv.tv_usec = (msec%1000)*1000 ;
01461 select( 1 , NULL,NULL,NULL , &tv ) ;
01462 return ;
01463 }
01464
01465
01466
01467
01468
01469
01470 int iochan_ctl( IOCHAN * ioc , int cmd , int arg )
01471 {
01472 if( ioc == NULL ) return -1 ;
01473
01474 switch( cmd ){
01475
01476 case IOC_TCP_SENDSIZE:
01477 if( arg >= 0 ){ ioc->sendsize = arg ; return 0 ; }
01478 else return -1 ;
01479 break ;
01480
01481 }
01482 return -1 ;
01483 }
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543 static IOCHAN *ioc_kill_1 = NULL ;
01544 static IOCHAN *ioc_kill_2 = NULL ;
01545
01546 static void iochan_fork_sigfunc(int sig)
01547 {
01548 switch( sig ){
01549 case SIGTERM:
01550 if( ioc_kill_1 != NULL ) iochan_close(ioc_kill_1) ;
01551 if( ioc_kill_2 != NULL ) iochan_close(ioc_kill_2) ;
01552 fprintf(stderr,"\n*** iochan_fork received SIGTERM signal\n");
01553 fflush(stderr) ;
01554 _exit(1) ;
01555 case SIGSEGV:
01556 if( ioc_kill_1 != NULL ) iochan_close(ioc_kill_1) ;
01557 if( ioc_kill_2 != NULL ) iochan_close(ioc_kill_2) ;
01558 fprintf(stderr,"\n*** iochan_fork received SIGSEGV signal\n");
01559 fflush(stderr) ;
01560 _exit(1) ;
01561 }
01562 }
01563
01564
01565
01566 pid_t iochan_fork_relay( char * name_in , char * name_out )
01567 {
01568 pid_t ppid = (pid_t)(-1) ;
01569 int jj , kk , nbuf ;
01570 #define MBUF 1048576
01571 char * buf , *sss ;
01572 IOCHAN *ioc_in, *ioc_out ;
01573
01574 if( name_in == NULL || name_out == NULL ) return ppid ;
01575
01576
01577
01578 ppid = fork() ;
01579 if( ppid == (pid_t)(-1) ){
01580 perror("iochan_fork failed") ;
01581 return ppid ;
01582 }
01583
01584 if( ppid != 0 ){
01585 pid_t qpid ;
01586 iochan_sleep(5) ;
01587 qpid = waitpid( ppid , NULL , WNOHANG ) ;
01588 if( qpid == ppid ) ppid = (pid_t)(-1) ;
01589 return ppid ;
01590 }
01591
01592
01593
01594 ioc_in = iochan_init( name_in , "accept" ) ;
01595 if( ioc_in == NULL ) _exit(1) ;
01596
01597 ioc_out = iochan_init( name_out , "create" ) ;
01598 if( ioc_out == NULL ){
01599 iochan_close(ioc_in) ; _exit(1) ;
01600 }
01601
01602
01603
01604 ioc_kill_1 = ioc_in ;
01605 ioc_kill_2 = ioc_out ;
01606 signal( SIGTERM , iochan_fork_sigfunc ) ;
01607 signal( SIGSEGV , iochan_fork_sigfunc ) ;
01608
01609 fprintf(stderr,"forked process for shm->tcp started\n") ;
01610
01611 do{
01612
01613 jj = iochan_goodcheck(ioc_in ,1) ;
01614 kk = iochan_goodcheck(ioc_out,1) ;
01615 if( jj < 0 || kk < 0 ){
01616 iochan_close(ioc_in) ; iochan_close(ioc_out) ; _exit(1) ;
01617 }
01618
01619 } while( jj == 0 || kk == 0 ) ;
01620
01621 fprintf(stderr,"forked process fully connected\n") ;
01622
01623 buf = AFMALL(char, MBUF) ;
01624 if( buf == NULL ){
01625 fprintf(stderr,"forked process can't malloc I/O buffer") ;
01626 iochan_close(ioc_in) ; iochan_close(ioc_out) ; _exit(1) ;
01627 }
01628
01629 while(1){
01630
01631 errno = 0 ;
01632 jj = iochan_readcheck( ioc_in , 20 ) ;
01633 if( jj < 0 ){
01634 if( errno ) perror( "forked readcheck" ) ;
01635 else fprintf(stderr,"forked readcheck abort: jj=%d!\n",jj) ;
01636 sss = iochan_error_string() ;
01637 if( sss != NULL ) fprintf(stderr," ** %s\n",sss) ;
01638 break ;
01639 }
01640 if( jj == 0 ) continue ;
01641
01642 nbuf = iochan_recvloop( ioc_in , buf , MBUF ) ;
01643 if( nbuf <= 0 ) continue ;
01644
01645 #if 0
01646 fprintf(stderr,"forked process read %d bytes\n",nbuf) ;
01647 #endif
01648
01649 errno = 0 ;
01650 kk = iochan_writecheck( ioc_out , 1 ) ;
01651 if( kk == 0 ){
01652 int qq ;
01653 fprintf(stderr,"forked writecheck repeat:") ;
01654 for( qq=0 ; qq < 1000 ; qq++ ){
01655 if( qq%50 == 0 ) fprintf(stderr," %d",qq+1) ;
01656 kk = iochan_writecheck( ioc_out , 2 ) ;
01657 if( kk != 0 ) break ;
01658 }
01659 fprintf(stderr,"\n") ;
01660 }
01661 if( kk <= 0 ){
01662 if( errno ) perror( "forked writecheck" ) ;
01663 else fprintf(stderr,"forked writecheck abort: kk=%d!\n",kk) ;
01664 sss = iochan_error_string() ;
01665 if( sss != NULL ) fprintf(stderr," ** %s\n",sss) ;
01666 break ;
01667 }
01668 kk = iochan_sendall( ioc_out , buf , nbuf ) ;
01669 if( kk < 0 ){
01670 if( errno ) perror( "forked sendall" ) ;
01671 else fprintf(stderr,"forked sendall abort: kk=%d!\n",kk) ;
01672 sss = iochan_error_string() ;
01673 if( sss != NULL ) fprintf(stderr," ** %s\n",sss) ;
01674 break ;
01675 }
01676
01677 #if 0
01678 fprintf(stderr,"forked process wrote %d bytes\n",nbuf) ;
01679 #endif
01680 }
01681
01682
01683
01684 fprintf(stderr,"forked process fails!\n") ;
01685
01686 iochan_close(ioc_in) ; iochan_close(ioc_out) ; _exit(1) ;
01687 }
01688
01689
01690
01691
01692
01693 #include <time.h>
01694
01695 double COX_clock_time(void)
01696 {
01697 struct timeval new_tval ;
01698 struct timezone tzone ;
01699 static struct timeval old_tval ;
01700 static int first = 1 ;
01701
01702 gettimeofday( &new_tval , &tzone ) ;
01703
01704 if( first ){
01705 old_tval = new_tval ;
01706 first = 0 ;
01707 return 0.0 ;
01708 }
01709
01710 if( old_tval.tv_usec > new_tval.tv_usec ){
01711 new_tval.tv_usec += 1000000 ;
01712 new_tval.tv_sec -- ;
01713 }
01714
01715 return (double)( (new_tval.tv_sec - old_tval.tv_sec )
01716 +(new_tval.tv_usec - old_tval.tv_usec)*1.0e-6 ) ;
01717 }
01718
01719
01720
01721
01722
01723 double COX_cpu_time(void)
01724 #ifdef CLK_TCK
01725 {
01726 struct tms ttt ;
01727
01728 (void) times( &ttt ) ;
01729 return ( (double) (ttt.tms_utime )
01730 / (double) CLK_TCK ) ;
01731 }
01732 #else
01733 { return 0.0 ; }
01734 #endif