modules/sk/sk_socket.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SK_atoport
  2. func_sigusr
  3. SK_close
  4. SK_getsock
  5. SK_accept_connection
  6. SK_read
  7. SK_write
  8. SK_gets
  9. SK_puts
  10. SK_putc
  11. SK_getc
  12. SK_getpeername
  13. SK_getpeerip
  14. SK_cd_puts
  15. SK_cd_gets
  16. SK_cd_close
  17. SK_cd_printf
  18. sk_watchdog
  19. SK_watchstart
  20. SK_watchstop
  21. SK_watchkill
  22. SK_watchexec
  23. SK_watchclear

   1 /***************************************
   2   $Revision: 1.4 $
   3 
   4   Example code: A socket module.
   5 
   6   Status: NOT REVUED, NOT TESTED
   7 
   8   +html+ <DL COMPACT>
   9   +html+ <DT>Online References:
  10   +html+ <DD><UL>
  11   +html+   <LI>Adapted from <A HREF="http://www.ibrado.com/sock-faq/sfaq.html#faq65">sample source code</A>.
  12   +html+ </UL>
  13   +html+ </DL>
  14   +html+ <PRE>
  15   +html+ </PRE>
  16  
  17   ******************/ /******************
  18   Modification History:
  19         ottrey (08/03/1999) Created from sockhelp.c.
  20         ottrey (08/03/1998) Heavily butchered.
  21         joao   (22/06/1999) Modified socket creation and accepts.
  22   ******************/ /******************
  23  REMINDER: PUT THE PROPER COPYRIGHT NOTICE HERE
  24   ***************************************/
  25 #include <arpa/inet.h>
  26 #include "socket.h"
  27 #include "constants.h"
  28 #include "stubs.h"
  29 
  30 #include "iproutines.h"
  31 #include "memwrap.h"
  32 
  33 #include <pthread.h>
  34 
  35 extern int h_errno;
  36 
  37 
  38 /*+ String sizes +*/
  39 #define STR_S   63
  40 #define STR_M   255
  41 #define STR_L   1023
  42 #define STR_XL  4095
  43 #define STR_XXL 16383
  44 
  45 /* SK_atoport() */
  46 /*++++++++++++++++++++++++++++++++++++++
  47    Take a service name, and a service type, and return a port number.  If the
  48    service name is not found, it tries it as a decimal number.  The number
  49    returned is byte ordered for the network.
  50 
  51   char *service   Service name (or port number).
  52 
  53   char *proto     Protocol (eg "tcp").
  54 
  55   More:
  56   +html+ <PRE>
  57   Authors:
  58         ottrey
  59 
  60   +html+ </PRE><DL COMPACT>
  61   +html+ <DT>Online References:
  62   +html+ <DD><UL>
  63   +html+ </UL></DL>
  64 
  65   ++++++++++++++++++++++++++++++++++++++*/
  66 int SK_atoport(const char *service, const char *proto) {
     /* [<][>][^][v][top][bottom][index][help] */
  67   int port;
  68   long int lport;
  69   struct servent *serv;
  70   char *errpos;
  71   struct servent result;
  72   char buffer[STR_XXL];
  73 
  74   /* First try to read it from /etc/services */
  75 
  76   /*  serv = getservbyname(service, proto); */
  77   serv = getservbyname_r(service, proto, &result, buffer, sizeof(buffer));
  78   if (serv != NULL)
  79     port = serv->s_port;
  80   else { /* Not in services, maybe a number? */
  81     lport = strtol(service,&errpos,0);
  82     if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) )
  83       return -1; /* Invalid port address */
  84     port = htons(lport);
  85   }
  86   return port;
  87 } /* SK_atoport() */
  88 
  89 
  90 /* SK_close_listening_socket() */
  91 /*++++++++++++++++++++++++++++++++++++++
  92   XXX Note: Not sure how long this function will last.  Shouldn't _really_ need it.
  93 
  94   More:
  95   +html+ <PRE>
  96   Authors:
  97         ottrey
  98 
  99   +html+ </PRE><DL COMPACT>
 100   +html+ <DT>Online References:
 101   +html+ <DD><UL>
 102   +html+ </UL></DL>
 103 
 104   ++++++++++++++++++++++++++++++++++++++*/
 105 /*void SK_close_listening_socket() {
 106   close(listening_socket);         
 107 } */ /* SK_close_listening_socket */
 108 
 109 static void func_sigusr(int n) {
     /* [<][>][^][v][top][bottom][index][help] */
 110   ER_dbg_va(FAC_SK, ASP_SK_GEN,"func_sigusr(%d) called", n);
 111 }
 112 
 113 int SK_close(int socket) {
     /* [<][>][^][v][top][bottom][index][help] */
 114   ER_dbg_va(FAC_SK, ASP_SK_GEN, "Closing socket... %d", socket);
 115 
 116   return close(socket);
 117 }
 118 
 119 /* SK_getsock() */
 120 /*++++++++++++++++++++++++++++++++++++++
 121 
 122    This function creates a socket and binds to it
 123 
 124    int      SK_getsock       The new socket
 125 
 126    int      socket_type      SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets)
 127 
 128    u_short  port             The port to listen on.  Remember that ports < 1024 are
 129                              reserved for the root user.  Must be passed in network byte
 130                              order (see "man htons").
 131 
 132    uint32_t bind_address     Address to bind to, in network order.
 133   More:
 134   +html+ <PRE>
 135   Authors:
 136         ottrey
 137         joao
 138 
 139   +html+ </PRE><DL COMPACT>
 140   +html+ <DT>Online References:
 141   +html+ <DD><UL>
 142   +html+ </UL></DL>
 143 
 144   ++++++++++++++++++++++++++++++++++++++*/
 145 int SK_getsock(int socket_type, u_short port, uint32_t bind_address) {
     /* [<][>][^][v][top][bottom][index][help] */
 146   struct sockaddr_in address;
 147   int listening_socket;
 148   int reuse_addr = 1;
 149 
 150   /* Setup internet address information.  
 151      This is used with the bind() call */
 152   memset((char *) &address, 0, sizeof(address));
 153   address.sin_family = AF_INET;
 154   address.sin_port = port;
 155   address.sin_addr.s_addr = bind_address;
 156 
 157   /* Map all of the signals and exit routine */
 158 
 159   listening_socket = socket(AF_INET, socket_type, 0);
 160   if (listening_socket < 0) {
 161     perror("socket");
 162     exit(EXIT_FAILURE);
 163   }
 164 
 165   setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse_addr, sizeof(reuse_addr));
 166 
 167   if (bind(listening_socket, (struct sockaddr *) &address, sizeof(address)) < 0) {
 168     perror("bind");
 169     close(listening_socket);
 170     exit(EXIT_FAILURE);
 171   }
 172 
 173 
 174   if (socket_type == SOCK_STREAM) {
 175     listen(listening_socket, 5); /* Queue up to five connections before
 176                                   having them automatically rejected. */
 177   }
 178 
 179   return listening_socket;
 180 } /* SK_getsock() */
 181 
 182 /*++++++++++++++++++++++++++++++++++++++
 183 
 184    Wait for an incoming connection on the specified socket
 185 
 186    int  SK_accept_connection The socket for communicating to the client
 187 
 188    int  listening_socket     The socket that the server is bound to
 189 
 190   More:
 191   +html+ <PRE>
 192   Authors:
 193         joao
 194   +html+ </PRE>
 195   ++++++++++++++++++++++++++++++++++++++*/
 196 int SK_accept_connection(int listening_socket) {
     /* [<][>][^][v][top][bottom][index][help] */
 197   int connected_socket = -1;
 198 
 199   while(connected_socket < 0) {
 200     
 201     ER_dbg_va(FAC_SK, ASP_SK_GEN, 
 202               "Going to accept connections on socket : %d",listening_socket);
 203 
 204 /* XXX joao - ? - why is this here?
 205 fflush(NULL);
 206 */
 207 
 208     connected_socket = accept(listening_socket, NULL, NULL);
 209     if (connected_socket < 0) {
 210       /* Either a real error occured, or blocking was interrupted for
 211          some reason.  Only abort execution if a real error occured. */
 212       if (errno != EINTR) {
 213         perror("accept");
 214         close(listening_socket);
 215         return(-1);
 216      /* no exit, just return with error */
 217       } else {
 218         continue;    /* don't return - do the accept again */
 219       }
 220     }
 221   }
 222 
 223   ER_dbg_va(FAC_SK, ASP_SK_GEN, "client connected on socket %d", 
 224             connected_socket
 225             );
 226 
 227   return connected_socket;
 228 }
 229 
 230 /* SK_read() */
 231 /*++++++++++++++++++++++++++++++++++++++
 232 
 233    This is just like the read() system call, except that it will make
 234    sure that all your data goes through the socket.
 235 
 236    int    SK_read  The number of bytes read.
 237 
 238    int    sockfd    The socket file descriptor.
 239 
 240    char   *buf      The buffer to be read from the socket.
 241 
 242    size_t count     The number of bytes in the buffer.
 243 
 244   More:
 245   +html+ <PRE>
 246   Authors:
 247         ottrey
 248   +html+ </PRE>
 249   ++++++++++++++++++++++++++++++++++++++*/
 250 int SK_read(int sockfd, char *buf, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 251   size_t bytes_read = 0;
 252   int this_read;
 253 
 254   while (bytes_read < count) {
 255     do
 256       this_read = read(sockfd, buf, count - bytes_read);
 257     while ( (this_read < 0) && (errno == EINTR) );
 258     if (this_read < 0)
 259       return this_read;
 260     else if (this_read == 0)
 261       return bytes_read;
 262     bytes_read += this_read;
 263     buf += this_read;
 264   }
 265 
 266   return count;
 267 
 268 } /* SK_read() */
 269 
 270 
 271 /* SK_write() */
 272 /*++++++++++++++++++++++++++++++++++++++
 273 
 274    This is just like the write() system call, accept that it will
 275    make sure that all data is transmitted.
 276 
 277    int    sockfd  The socket file descriptor.
 278 
 279    char   *buf    The buffer to be written to the socket.
 280 
 281    size_t count   The number of bytes in the buffer.
 282 
 283   More:
 284   +html+ <PRE>
 285   Authors:
 286         ottrey
 287 
 288   +html+ </PRE><DL COMPACT>
 289   +html+ <DT>Online References:
 290   +html+ <DD><UL>
 291   +html+ </UL></DL>
 292 
 293   ++++++++++++++++++++++++++++++++++++++*/
 294 int SK_write(int sockfd, const char *buf, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 295   size_t  bytes_sent = 0;
 296   int     this_write;
 297 
 298   
 299   ER_dbg_va(FAC_SK, ASP_SK_WRIT,
 300             "SK_write = { sockfd=[%d], buf=[%s], count=[%d]", 
 301             sockfd, buf, count);
 302 
 303   while (bytes_sent < count) {
 304     do
 305       this_write = write(sockfd, buf, count - bytes_sent);
 306     while ( (this_write < 0) && (errno == EINTR) );
 307     if (this_write <= 0)
 308       return this_write;
 309     bytes_sent += this_write;
 310     buf += this_write;
 311   }
 312   return count;
 313 } /* SK_write() */
 314 
 315 
 316 /* SK_gets() */
 317 /*++++++++++++++++++++++++++++++++++++++
 318 
 319    This function reads from a socket, until it recieves a linefeed
 320    character.  It fills the buffer "str" up to the maximum size "count".
 321 
 322    int SK_gets  The total_count of bytes read.
 323 
 324    int    sockfd    The socket file descriptor.
 325 
 326    char   *str      The buffer to be written from the socket.
 327 
 328    size_t count     The number of bytes in the buffer.
 329 
 330   More:
 331   +html+ <PRE>
 332   Authors:
 333         ottrey
 334 
 335   Side Effects:
 336         This function will return -1 if the socket is closed during the read operation.
 337 
 338         Note that if a single line exceeds the length of count, the extra data
 339         will be read and discarded!  You have been warned.
 340 
 341   To Do:
 342         Capture the control-c properly!
 343 
 344   +html+ </PRE>
 345 
 346   ++++++++++++++++++++++++++++++++++++++*/
 347 int SK_gets(int sockfd, char *str, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 348   int bytes_read;
 349   int total_count = 0;
 350   char *current_position;
 351   char last_read = 0;
 352 
 353   int control_c = 0;
 354 
 355   current_position = str;
 356   while (last_read != 10) {
 357 
 358     
 359 
 360     bytes_read = read(sockfd, &last_read, 1);
 361     if (bytes_read <= 0) {
 362       /* The other side may have closed unexpectedly */
 363       return SK_DISCONNECT; 
 364       /* Is this effective on other platforms than linux? */
 365     }
 366     if ( (total_count < count) && (last_read != 10) && (last_read !=13) ) {
 367       *current_position = last_read;
 368       current_position++;
 369       total_count++;
 370     }
 371 
 372     if (last_read == -1) {
 373       bytes_read = read(sockfd, &last_read, 1);
 374       if (last_read == -12) {
 375         ER_dbg_va(FAC_SK, ASP_SK_GEN,"Client pressed Control-c");
 376         control_c = 1;
 377         ER_dbg_va(FAC_SK, ASP_SK_GEN,"returning SK_INTERRUPT");
 378         return SK_INTERRUPT;
 379       }
 380     }
 381   }
 382   if (count > 0) {
 383     *current_position = 0;
 384   }
 385 
 386   return total_count;
 387 
 388 } /* SK_gets() */
 389 
 390 
 391 /* SK_puts() */
 392 /*++++++++++++++++++++++++++++++++++++++
 393 
 394    This function writes a character string out to a socket.
 395 
 396    int SK_puts  The total_count of bytes written, 
 397                 or errors (represented as negative numbers)
 398 
 399    int    sockfd    The socket file descriptor.
 400 
 401    char   *str      The buffer to be written from the socket.
 402 
 403   More:
 404   +html+ <PRE>
 405   Authors:
 406         ottrey
 407 
 408   Side Effects:
 409         This function will return -1 if the socket is closed during the write operation.
 410 
 411         Note that if a single line exceeds the length of count, the extra data
 412         will be read and discarded!  You have been warned.
 413 
 414   +html+ </PRE>
 415 
 416   ++++++++++++++++++++++++++++++++++++++*/
 417 int SK_puts(int sockfd, const char *str) {
     /* [<][>][^][v][top][bottom][index][help] */
 418 
 419   return SK_write(sockfd, str, strlen(str));
 420 
 421 } /* SK_puts() */
 422 
 423 /* SK_putc() */
 424 /*++++++++++++++++++++++++++++++++++++++
 425 
 426    int SK_putc This function writes a single character out to a socket.
 427 
 428    int sockfd        socket
 429    char ch           character
 430 
 431    return number of chars written 
 432 
 433   ++++++++++++++++++++++++++++++++++++++*/
 434 int SK_putc(int sockfd, char ch) {
     /* [<][>][^][v][top][bottom][index][help] */
 435   return SK_write(sockfd, &ch, 1);
 436 }/* SK_putc() */
 437 
 438 /*++++++++++++++++++++++++++++++++++++++
 439 
 440    This function reads a single character from a socket.
 441 
 442    returns EOF when no character can be read. 
 443 
 444   ++++++++++++++++++++++++++++++++++++++*/
 445 int SK_getc(int sockfd) {
     /* [<][>][^][v][top][bottom][index][help] */
 446   char ch;
 447 
 448   if( read(sockfd, &ch, 1) <= 0 ) {
 449     return EOF;
 450   }
 451   else {
 452     return ch;
 453   }
 454 }/* SK_getc() */
 455 
 456 /* SK_getpeername() */
 457 /*++++++++++++++++++++++++++++++++++++++
 458 
 459    This function will tell you who is at the other end of a connected stream socket.
 460    XXX It's not working.
 461    XXX ? MB it is...
 462 
 463    int    sockfd    The socket file descriptor.
 464 
 465   More:
 466   +html+ <PRE>
 467   Authors:
 468         ottrey
 469   +html+ </PRE>
 470 
 471   ++++++++++++++++++++++++++++++++++++++*/
 472 char *SK_getpeername(int sockfd) 
     /* [<][>][^][v][top][bottom][index][help] */
 473 {
 474   char *hostaddress=NULL;
 475   struct sockaddr_in addr_in;
 476   int namelen=sizeof(addr_in);
 477  
 478   if (getpeername(sockfd, (struct sockaddr *)&addr_in, &namelen) != -1) {
 479 
 480     dieif( wr_malloc((void **)&hostaddress, 16) != UT_OK); 
 481     
 482     strcpy(hostaddress, inet_ntoa(addr_in.sin_addr));  /* XXX MT-UNSAFE */
 483   }
 484 
 485   return hostaddress;
 486   
 487 } /* SK_getpeername() */
 488 
 489 /* SK_getpeerip */
 490 int SK_getpeerip(int sockfd, ip_addr_t *ip) {
     /* [<][>][^][v][top][bottom][index][help] */
 491   struct sockaddr_in addr_in;
 492   int namelen=sizeof(addr_in);
 493   int ret=-1;
 494 
 495   memset(& addr_in, 0, sizeof(struct sockaddr_in));
 496 
 497   if (getpeername(sockfd, (struct sockaddr *)(& addr_in), &namelen) != -1) {
 498     ret=0;
 499     IP_addr_s2b(ip, &addr_in, namelen);
 500   }
 501   
 502   return ret;
 503 }
 504 
 505 /*-------------------------------------------------------------------
 506  *   CD varieties of the functions: broken connections get registered
 507  *   in the connection structure within the query environment 
 508  *   as side effects.
 509  * -----------------------------------------------------------------*/
 510 
 511 /* SK_cd_puts() */
 512 /*++++++++++++++++++++++++++++++++++++++
 513 
 514    This function writes a character string out to a socket.
 515 
 516    int SK_qe_puts  The total_count of bytes written, 
 517                 or errors (represented as negative numbers)
 518 
 519    sk_conn_st *condat connection data
 520 
 521    char   *str       The buffer to be written from the socket.
 522 
 523   More:
 524        if the connection structure has bad status for this connection
 525        from previous calls, no write will be attempted.
 526 
 527   +html+ <PRE>
 528   Authors:
 529         marek
 530 
 531   Side Effects:
 532        broken connections get registered
 533        in the connection structure within the query environment 
 534         
 535   +html+ </PRE>
 536 
 537   ++++++++++++++++++++++++++++++++++++++*/
 538 int SK_cd_puts(sk_conn_st *condat, const char *str) {
     /* [<][>][^][v][top][bottom][index][help] */
 539   int res=SK_puts(condat->sock, str);
 540 
 541   if( res < 0 ){
 542     /* set the corresponding rtc flag */
 543     condat->rtc |= (-res);
 544 
 545     switch( - res ) {
 546       /* dont know what to do and how to log */
 547     case SK_DISCONNECT:
 548     case SK_INTERRUPT:
 549       /*("Thread received a control-c\n");*/
 550     case SK_TIMEOUT:
 551       /*("Reading timed out\n");*/
 552       break;
 553     default:
 554       /* unexpected error code. bail out */
 555       die;
 556     }
 557   }
 558   return res;
 559 } /* SK_cd_puts() */
 560 
 561 /* SK_cd_gets() */
 562 /*++++++++++++++++++++++++++++++++++++++
 563 
 564    Wrapper around SK_gets.
 565 
 566    int SK_cd_gets  The total_count of bytes read, 
 567                    or errors (represented as negative numbers)
 568 
 569    sk_conn_st *condat connection data
 570 
 571    char   *str       The buffer to be written from the socket.
 572 
 573   More:
 574        if the connection structure has bad status for this connection
 575        from previous calls, no write will be attempted.
 576 
 577   +html+ <PRE>
 578   Authors:
 579         marek
 580         
 581   Side Effects:
 582        broken connections get registered
 583        in the connection structure within the query environment 
 584        
 585   +html+ </PRE>
 586 
 587   ++++++++++++++++++++++++++++++++++++++*/
 588 int SK_cd_gets(sk_conn_st *condat, char *str, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 589   fd_set rset;
 590   struct timeval *ptm = & condat->rd_timeout;
 591   int readcount = 0;
 592   
 593   memset( str, 0, count);
 594   FD_ZERO( &rset );
 595   FD_SET( condat->sock, &rset );
 596 
 597   if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined, 
 598                                                   do blocking I/O */
 599     ptm = NULL;
 600   }
 601 
 602   do {
 603     char buf[2];
 604     int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);    
 605 
 606     dieif(sel < 0); /* we don't expect problems */
 607       
 608     if( sel == 0 ) {      
 609       condat->rtc |= SK_TIMEOUT;
 610       break;
 611     }
 612 
 613     else { 
 614       read( condat->sock, buf, 1 );
 615       str[readcount] = buf[0];
 616       readcount++;
 617       if( buf[0] == '\n' ) {
 618         break;
 619       }
 620     } 
 621   } while( readcount < count );
 622          
 623   return readcount;
 624 
 625 } /* SK_cd_gets() */
 626 
 627 
 628 int SK_cd_close(sk_conn_st *condat) {
     /* [<][>][^][v][top][bottom][index][help] */
 629   return SK_close(condat->sock);
 630 } /* SK_cd_close() */
 631 
 632 
 633 /* print to condat like printf
 634 
 635    by marek
 636 */
 637 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 638 {
 639 #define SKBUFLEN 2047
 640   va_list   ap;
 641   char      buffer[SKBUFLEN+1];
 642   int       len;
 643   char      *newbuf = NULL;
 644   char      *finalbuf = buffer; /* points to where the text REALLY is */
 645  
 646   /* vsnprintf returns the number of character it WOULD write if it could.
 647      So we assume the buffer to be of adequate size for most cases,
 648      and if it isn't, then we allocate to newbuf and call v*printf again 
 649   */
 650   va_start(ap, txt);
 651   len = vsnprintf(buffer, SKBUFLEN, txt, ap);
 652   va_end(ap);
 653   
 654   if( len > SKBUFLEN ) {
 655     dieif(!NOERR(wr_malloc( (void **)& newbuf, len+1)));
 656     
 657     va_start(ap, txt);
 658     vsnprintf(newbuf, len, txt, ap);
 659     va_end(ap);   
 660     
 661     finalbuf = newbuf;
 662   }  
 663   /* terminate */
 664   finalbuf[len] = 0;
 665 
 666   /* reuse len */
 667   len = SK_cd_puts(condat, finalbuf);
 668 
 669   if(newbuf != NULL) {
 670     wr_free(newbuf);
 671   }
 672 
 673   return len;
 674 }
 675 
 676 
 677 /* sk_watchdog - started as a separate thread.
 678 
 679    selects on the given socket; discards all input.
 680    whenever it sees end of file (socket closed), it
 681    * sets a corresponding flag in the condat structure, 
 682    * kills a thread designated to be killed (by SK_watchkill)
 683 
 684    by marek;
 685 */
 686 static
 687 void *sk_watchdog(void *arg)
     /* [<][>][^][v][top][bottom][index][help] */
 688 {
 689   sk_conn_st *condat = (sk_conn_st *) arg;
 690   int nready;
 691   int n;
 692   fd_set rset;
 693   char buff[STR_S];
 694   int socket = condat->sock;
 695   sigset_t sset;
 696   struct sigaction act;
 697 
 698   FD_ZERO(&rset);
 699   FD_SET(socket, &rset);
 700 
 701   sigemptyset(&sset);
 702   sigaddset(&sset, SIGUSR1);
 703   
 704   act.sa_handler = func_sigusr;
 705   act.sa_flags = 0;
 706   dieif(sigaction(SIGUSR1, &act, NULL) != 0);
 707 
 708   dieif(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) != 0);
 709   
 710   pthread_mutex_unlock( & condat->watchmutex ); /* now ready for signal */
 711 
 712   while ((nready=select(socket+1, &rset, NULL, NULL, NULL))!=-1) {
 713    
 714     /* don't even try to read if we have been killed */
 715     if( errno == EINTR ) {
 716       break;
 717     }
 718 
 719    /* There was some input or client half of connection was closed */
 720    /* Check for the latter */
 721    if (( n=read(socket, buff, sizeof(buff))) == 0) {
 722    /* Connection was closed by client */
 723    /* Now send a cancellation request to the whois thread. */
 724    /* mysql thread will be terminated by thread cleanup routine */
 725    
 726      /* set the reason-to-close flag on this connection */
 727      condat->rtc |= SK_INTERRUPT;
 728 
 729      /* cancel the thread to be cancelled if defined */
 730      if( condat->killthis != 0 ) {
 731        pthread_cancel(condat->killthis);
 732        /* The only possible error is ESRCH, so we do not care about it*/
 733      }
 734 
 735      /* call the function to be called if defined */
 736      if( condat->execthis != NULL ) {
 737        condat->execthis(condat->execargs);
 738      }
 739 
 740      /* quit */
 741      break;
 742    }
 743    /* Otherwise dump input and continue */
 744 
 745   }
 746 
 747   /* Exit the watchdog thread, passing NULL as we don't expect a join */
 748   pthread_exit(NULL);
 749 
 750   /* oh yes. Shouldn't compilers _analyze_ library functions ? */
 751   return NULL;
 752 }
 753 
 754 /* SK_watchstart
 755 
 756    starts sk_watchdog thread unless already started,
 757    and registers its threadid in the condat structure
 758 
 759    dies if watchdog already running
 760 */
 761 er_ret_t
 762 SK_watchstart(sk_conn_st *condat)
     /* [<][>][^][v][top][bottom][index][help] */
 763 {
 764   dieif( condat->watchdog != 0 );
 765   
 766   /* init the mutex in locked state, watchdog will unlock it when 
 767      it's ready for signal */
 768   pthread_mutex_init( & condat->watchmutex, NULL );
 769   pthread_mutex_lock( & condat->watchmutex ); 
 770 
 771   pthread_create(&condat->watchdog, NULL, sk_watchdog, (void *) condat );
 772   
 773   return SK_OK;
 774 }
 775 
 776 
 777 /* SK_watchstop 
 778 
 779    stops sk_watchdog thread if it is registered in the connection struct
 780 */
 781 er_ret_t
 782 SK_watchstop(sk_conn_st *condat)
     /* [<][>][^][v][top][bottom][index][help] */
 783 {
 784   void *res;
 785 
 786   if(condat->watchdog > 0) {
 787     int ret;
 788 
 789     /* wait until the watchdog is ready for signal */
 790     pthread_mutex_lock( & condat->watchmutex ); 
 791 
 792     ret = pthread_kill(condat->watchdog, SIGUSR1);
 793     
 794     ret = pthread_join(condat->watchdog, &res);
 795     
 796     pthread_mutex_destroy( & condat->watchmutex ); 
 797     condat->watchdog = 0;
 798   }
 799   return SK_OK;
 800 }
 801 
 802 /* SK_watchkill
 803 
 804    sets the threadid of the thread to be killed by watchdog
 805    0 means dont kill anything
 806 */
 807 void
 808 SK_watchkill(sk_conn_st *condat, pthread_t killthis)
     /* [<][>][^][v][top][bottom][index][help] */
 809 {
 810   condat->killthis = killthis;
 811 }
 812 
 813 void
 814 SK_watchexec( sk_conn_st *condat, void *(*function)(void *) , void *args)
     /* [<][>][^][v][top][bottom][index][help] */
 815 {
 816   condat->execthis = function;
 817   condat->execargs = args;
 818 }
 819 
 820 void 
 821 SK_watchclear(sk_conn_st *condat) 
     /* [<][>][^][v][top][bottom][index][help] */
 822 {
 823   condat->execthis = NULL;
 824   condat->execargs = NULL;
 825   condat->killthis = 0;
 826 }

/* [<][>][^][v][top][bottom][index][help] */