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.3 $
   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 void SK_close(int socket) {
     /* [<][>][^][v][top][bottom][index][help] */
 114   ER_dbg_va(FAC_SK, ASP_SK_GEN, "Closing socket... %d", socket);
 115 
 116   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 } /* SK_cd_puts() */
 559 
 560 /* SK_cd_gets() */
 561 /*++++++++++++++++++++++++++++++++++++++
 562 
 563    Wrapper around SK_gets.
 564 
 565    int SK_cd_gets  The total_count of bytes read, 
 566                    or errors (represented as negative numbers)
 567 
 568    sk_conn_st *condat connection data
 569 
 570    char   *str       The buffer to be written from the socket.
 571 
 572   More:
 573        if the connection structure has bad status for this connection
 574        from previous calls, no write will be attempted.
 575 
 576   +html+ <PRE>
 577   Authors:
 578         marek
 579         
 580   Side Effects:
 581        broken connections get registered
 582        in the connection structure within the query environment 
 583        
 584   +html+ </PRE>
 585 
 586   ++++++++++++++++++++++++++++++++++++++*/
 587 int SK_cd_gets(sk_conn_st *condat, char *str, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 588   int res;
 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 } /* SK_cd_gets() */
 624 
 625 
 626 int SK_cd_close(sk_conn_st *condat) {
     /* [<][>][^][v][top][bottom][index][help] */
 627   SK_close(condat->sock);
 628 } /* SK_cd_close() */
 629 
 630 
 631 /* print to condat like printf
 632 
 633    by marek
 634 */
 635 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 636 {
 637 #define SKBUFLEN 2047
 638   va_list   ap;
 639   char      buffer[SKBUFLEN+1];
 640   int       len;
 641   char      *newbuf = NULL;
 642   char      *finalbuf = buffer; /* points to where the text REALLY is */
 643  
 644   /* vsnprintf returns the number of character it WOULD write if it could.
 645      So we assume the buffer to be of adequate size for most cases,
 646      and if it isn't, then we allocate to newbuf and call v*printf again 
 647   */
 648   va_start(ap, txt);
 649   len = vsnprintf(buffer, SKBUFLEN, txt, ap);
 650   va_end(ap);
 651   
 652   if( len > SKBUFLEN ) {
 653     dieif(!NOERR(wr_malloc( (void **)& newbuf, len+1)));
 654     
 655     va_start(ap, txt);
 656     vsnprintf(newbuf, len, txt, ap);
 657     va_end(ap);   
 658     
 659     finalbuf = newbuf;
 660   }  
 661   /* terminate */
 662   finalbuf[len] = 0;
 663 
 664   /* reuse len */
 665   len = SK_cd_puts(condat, finalbuf);
 666 
 667   if(newbuf != NULL) {
 668     wr_free(newbuf);
 669   }
 670 
 671   return len;
 672 }
 673 
 674 
 675 /* sk_watchdog - started as a separate thread.
 676 
 677    selects on the given socket; discards all input.
 678    whenever it sees end of file (socket closed), it
 679    * sets a corresponding flag in the condat structure, 
 680    * kills a thread designated to be killed (by SK_watchkill)
 681 
 682    by marek;
 683 */
 684 static
 685 void *sk_watchdog(void *arg)
     /* [<][>][^][v][top][bottom][index][help] */
 686 {
 687   sk_conn_st *condat = (sk_conn_st *) arg;
 688   int nready;
 689   int n;
 690   fd_set rset;
 691   char buff[STR_S];
 692   int socket = condat->sock;
 693   sigset_t sset;
 694   struct sigaction act;
 695 
 696   FD_ZERO(&rset);
 697   FD_SET(socket, &rset);
 698 
 699   sigemptyset(&sset);
 700   sigaddset(&sset, SIGUSR1);
 701   
 702   act.sa_handler = func_sigusr;
 703   act.sa_flags = 0;
 704   dieif(sigaction(SIGUSR1, &act, NULL) != 0);
 705 
 706   dieif(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) != 0);
 707   
 708   pthread_mutex_unlock( & condat->watchmutex ); /* now ready for signal */
 709 
 710   while ((nready=select(socket+1, &rset, NULL, NULL, NULL))!=-1) {
 711    
 712     /* don't even try to read if we have been killed */
 713     if( errno == EINTR ) {
 714       break;
 715     }
 716 
 717    /* There was some input or client half of connection was closed */
 718    /* Check for the latter */
 719    if (( n=read(socket, buff, sizeof(buff))) == 0) {
 720    /* Connection was closed by client */
 721    /* Now send a cancellation request to the whois thread. */
 722    /* mysql thread will be terminated by thread cleanup routine */
 723    
 724      /* set the reason-to-close flag on this connection */
 725      condat->rtc |= SK_INTERRUPT;
 726 
 727      /* cancel the thread to be cancelled if defined */
 728      if( condat->killthis != 0 ) {
 729        pthread_cancel(condat->killthis);
 730        /* The only possible error is ESRCH, so we do not care about it*/
 731      }
 732 
 733      /* call the function to be called if defined */
 734      if( condat->execthis != NULL ) {
 735        condat->execthis(condat->execargs);
 736      }
 737 
 738      /* quit */
 739      break;
 740    }
 741    /* Otherwise dump input and continue */
 742 
 743   }
 744 
 745   /* Exit the watchdog thread, passing NULL as we don't expect a join */
 746   pthread_exit(NULL);
 747 }
 748 
 749 /* SK_watchstart
 750 
 751    starts sk_watchdog thread unless already started,
 752    and registers its threadid in the condat structure
 753 
 754    dies if watchdog already running
 755 */
 756 er_ret_t
 757 SK_watchstart(sk_conn_st *condat)
     /* [<][>][^][v][top][bottom][index][help] */
 758 {
 759   dieif( condat->watchdog != 0 );
 760   
 761   /* init the mutex in locked state, watchdog will unlock it when 
 762      it's ready for signal */
 763   pthread_mutex_init( & condat->watchmutex, NULL );
 764   pthread_mutex_lock( & condat->watchmutex ); 
 765 
 766   pthread_create(&condat->watchdog, NULL, sk_watchdog, (void *) condat );
 767   
 768   return SK_OK;
 769 }
 770 
 771 
 772 /* SK_watchstop 
 773 
 774    stops sk_watchdog thread if it is registered in the connection struct
 775 */
 776 er_ret_t
 777 SK_watchstop(sk_conn_st *condat)
     /* [<][>][^][v][top][bottom][index][help] */
 778 {
 779   void *res;
 780 
 781   if(condat->watchdog > 0) {
 782     int ret;
 783 
 784     /* wait until the watchdog is ready for signal */
 785     pthread_mutex_lock( & condat->watchmutex ); 
 786 
 787     ret = pthread_kill(condat->watchdog, SIGUSR1);
 788     
 789     ret = pthread_join(condat->watchdog, &res);
 790     
 791     pthread_mutex_destroy( & condat->watchmutex ); 
 792     condat->watchdog = 0;
 793   }
 794   return SK_OK;
 795 }
 796 
 797 /* SK_watchkill
 798 
 799    sets the threadid of the thread to be killed by watchdog
 800    0 means dont kill anything
 801 */
 802 void
 803 SK_watchkill(sk_conn_st *condat, pthread_t killthis)
     /* [<][>][^][v][top][bottom][index][help] */
 804 {
 805   condat->killthis = killthis;
 806 }
 807 
 808 void
 809 SK_watchexec( sk_conn_st *condat, void *(*function)(void *) , void *args)
     /* [<][>][^][v][top][bottom][index][help] */
 810 {
 811   condat->execthis = function;
 812   condat->execargs = args;
 813 }
 814 
 815 void 
 816 SK_watchclear(sk_conn_st *condat) 
     /* [<][>][^][v][top][bottom][index][help] */
 817 {
 818   condat->execthis = NULL;
 819   condat->execargs = NULL;
 820   condat->killthis = 0;
 821 }

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