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) {
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) {
110 | ER_dbg_va(FAC_SK, ASP_SK_GEN,"func_sigusr(%d) called", n);
111 | }
112 |
113 | int SK_close(int socket) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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)
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) {
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) {
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) {
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) {
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, ...)
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)
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)
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)
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)
809 | {
810 | condat->killthis = killthis;
811 | }
812 |
813 | void
814 | SK_watchexec( sk_conn_st *condat, void *(*function)(void *) , void *args)
815 | {
816 | condat->execthis = function;
817 | condat->execargs = args;
818 | }
819 |
820 | void
821 | SK_watchclear(sk_conn_st *condat)
822 | {
823 | condat->execthis = NULL;
824 | condat->execargs = NULL;
825 | condat->killthis = 0;
826 | }