source: trunk/instant_messenger/socket/afonso.c @ 151

Revision 151, 18.1 KB checked in by niltonneto, 16 years ago (diff)

Commit da nova versão do módulo, usando agente em C.
Vide Página do módulo do Trac:
http://www.expressolivre.org/dev/wiki/messenger

A versão anterior encontra-se na subpasta bkp (32/64).

Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/socket.h>
5#include <arpa/inet.h>
6#include <netdb.h>
7#include <unistd.h>
8#include <signal.h>
9#include <errno.h>
10#include <sys/wait.h>
11#include <sys/stat.h>
12#include <sys/types.h>
13#include <sys/mman.h>
14#include <stdarg.h>
15#include <syslog.h>
16#include <fcntl.h>
17#include <semaphore.h>
18#include <sys/ipc.h>
19#include <sys/shm.h>
20#include <pthread.h>
21#include <ctype.h>
22
23
24// Buffer size, in bytes, used for copying in the Cat() function.
25const size_t BUF_SIZE = 4096;
26
27// Global variables
28char g_program_name[100];       // Initialised from argv[0] in ParseArgs()
29
30// Typedef for a signal handler function.
31typedef void (* signal_handler_t) (int);
32
33// Prototypes for functions in this file.
34void ParseArgs (int, char **, struct in_addr *, struct in_addr *, struct in_addr *, struct in_addr *);
35void Initialise (void);
36void sig_child (int);
37int CreateServerSocket (int);
38void Daemonise (void);
39void MainLoop (int);//, struct in_addr *, struct in_addr *, struct in_addr *, struct in_addr *);
40void ClearList(void);
41void Proxy (int, int);
42struct accept * AcceptClientConnection (int);
43void VerifyClient(void *);
44struct client * Handshake(int);
45int ConnectToServer (struct in_addr, unsigned short);
46//void Cat (int, int);
47void Cat (void *);
48int NameToAddr (const char *, struct in_addr *);
49int NameToPort (const char *, unsigned short *, const char *);
50#ifdef __GNUC__
51        void quit (const char *, ...) __attribute__ ((format (printf, 1, 2)));
52        void pbomb (const char *, ...) __attribute__ ((format (printf, 1, 2)));
53        void hbomb (const char *, ...) __attribute__ ((format (printf, 1, 2)));
54#else
55        void quit (const char *, ...);
56        void pbomb (const char *, ...);
57        void hbomb (const char *, ...);
58#endif
59void set_signal_handler (int, signal_handler_t);
60
61#define __PORT__ 9000
62#define __MOITA_FOI_SOLICITADA__ "moita"
63#define __OK__ "ok"
64
65struct accept
66{
67        int newfd;
68        struct sockaddr_in sa;
69};
70
71struct main_loop
72{
73        int listen_fd,
74                ra_1,
75                ra_2,
76                ra_3,
77                ra_4;
78};
79
80struct client
81{
82        char * user;
83        int client_fd;
84        int jabber_fd;
85        int keep_alive;
86        time_t last_action;
87        struct client * next;
88        struct client * previous;
89};
90
91struct cat
92{
93        int in_fd,
94                out_fd;
95        int jabber,
96                keep_alive;
97        struct client * client;
98};
99
100struct client * clients = (struct client *)NULL;
101
102pthread_mutex_t mutexsum;
103
104int main (int argc, char ** argv)
105{
106        struct in_addr remote_addr_1,
107                                   remote_addr_2,
108                                   remote_addr_3,
109                                   remote_addr_4;
110        int listen_fd_1,
111                listen_fd_2,
112                listen_fd_3,
113                listen_fd_4,
114                listen_fd_5;
115
116        pthread_t port_9001,
117                          port_9002,
118                          port_9003,
119                          port_9004,
120                          port_9005;
121
122        //ParseArgs (argc, argv, &remote_addr_1, &remote_addr_2, &remote_addr_3, &remote_addr_4);
123
124        // Create server socket before becoming a daemon so
125        // there is still a chance to print an error message.
126        listen_fd_1 = CreateServerSocket (9001);
127        listen_fd_2 = CreateServerSocket (9002);
128        listen_fd_3 = CreateServerSocket (9003);
129        listen_fd_4 = CreateServerSocket (9004);
130        listen_fd_5 = CreateServerSocket (9005);
131
132        if ( listen_fd_1 < 0 )
133                pbomb ("Unable to create server socket #1");
134
135        if ( listen_fd_2 < 0 )
136                pbomb ("Unable to create server socket #2");
137
138        if ( listen_fd_3 < 0 )
139                pbomb ("Unable to create server socket #3");
140
141        if ( listen_fd_4 < 0 )
142                pbomb ("Unable to create server socket #4");
143
144        if ( listen_fd_5 < 0 )
145                pbomb ("Unable to create server socket #5");
146
147        //Daemonise ();
148
149        //pthread_create(&port_900, NULL, (void *) &MainLoop, (void *) accept);
150        MainLoop (listen_fd_1);//, &remote_addr_1, &remote_addr_2, &remote_addr_3, &remote_addr_4); // never returns
151        //MainLoop (listen_fd, &remote_addr_1, &remote_addr_2, &remote_addr_3, &remote_addr_4); // never returns
152        //MainLoop (listen_fd, &remote_addr_1, &remote_addr_2, &remote_addr_3, &remote_addr_4); // never returns
153        //MainLoop (listen_fd, &remote_addr_1, &remote_addr_2, &remote_addr_3, &remote_addr_4); // never returns
154        //MainLoop (listen_fd, &remote_addr_1, &remote_addr_2, &remote_addr_3, &remote_addr_4); // never returns
155
156        syslog (LOG_ERR, "fim MainLoop(): %m");
157        exit (EXIT_SUCCESS);
158}
159
160// ParseArgs()
161// Parse the command line arguments to extract the remote
162// and local adresses and port numbers, ra, rp, la & lp.
163// Exit the program gracefully upon error.
164void ParseArgs (int argc, char ** argv, struct in_addr * ra_1, struct in_addr * ra_2, struct in_addr * ra_3, struct in_addr * ra_4)
165{
166        // argv[0] = program name
167        // argv[1] = remote_addr
168        // argv[2] = remote_port
169        // argv[3] = local_addr (optional)
170        // argv[4] = local_port (optional)
171
172        char * p = strrchr (argv[0], '/');
173
174        strncpy (g_program_name, (p == NULL) ? argv[0] : p + 1, sizeof (g_program_name) - 1);
175
176        if ( (argc < 5) || (argc > 5) )
177        {
178                fprintf (stderr, "usage: %s remote_addr_1 remote_addr_2 remote_addr_3 remote_addr_4\n", argv[0]);
179                exit (EXIT_FAILURE);
180        }
181
182        if ( NameToAddr (argv[1], ra_1) )
183                hbomb ("Unable to resolve \"%s\" to an ip address", argv[1]);
184
185        if ( NameToAddr (argv[2], ra_2) )
186                hbomb ("Unable to resolve \"%s\" to an ip address", argv[2]);
187
188        if ( NameToAddr (argv[3], ra_3) )
189                hbomb ("Unable to resolve \"%s\" to an ip address", argv[3]);
190
191        if ( NameToAddr (argv[4], ra_4) )
192                hbomb ("Unable to resolve \"%s\" to an ip address", argv[4]);
193}
194
195// Initialise()
196// Setup syslog, signal handlers, and other intialisation.
197void Initialise (void)
198{
199        openlog (g_program_name, LOG_PID, LOG_USER);
200        syslog (LOG_INFO, "%s started", g_program_name);
201
202        chdir ("/"); // Change working directory to the root.
203
204        umask (0); // Clear our file mode creation mask
205
206        //set_signal_handler (SIGCHLD, sig_child);
207
208        //signal (SIGPIPE, SIG_IGN);
209}
210
211// CreateServerSocket()
212// Create a socket, bind it to the specified address
213// and port, and set it to listen for client connections.
214// Returns < 0 on failure to bind, bombs on error otherwise,
215// returns the fd of the new socket on success.
216int CreateServerSocket (int port)
217{
218        int err,
219                fd;
220        const int on = 1;
221        struct sockaddr_in sa;
222
223        // Create a socket and get its descriptor.
224        fd = socket (AF_INET, SOCK_STREAM, 0);
225        if ( fd < 0 )
226                syslog (LOG_ERR, "socket(): %m"), exit (EXIT_FAILURE);
227
228        // Set SO_REUSEADDR socket option
229        if ( setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 )
230                syslog (LOG_ERR, "setsockopt(fd%d, SO_REUSEADDR): %m", fd);
231
232        // Load a sa structure with the specified address and port
233        sa.sin_family = AF_INET;
234        sa.sin_addr.s_addr = htonl(INADDR_ANY);
235        sa.sin_port = htons (port);
236        memset (sa.sin_zero, 0, sizeof (sa.sin_zero));
237
238        // Bind our socket to the address and port specified
239        err = bind (fd, (struct sockaddr *) &sa, sizeof (sa));
240        if ( err < 0 )
241        {
242                syslog (LOG_ERR, "bind(): %m");
243                return err;
244        }
245
246        // Tell socket to listen and queue up to 5 incoming connections.
247        if ( listen (fd, 5) < 0 )
248                syslog (LOG_ERR, "listen(): %m"), exit (EXIT_FAILURE);
249
250        return fd;
251}
252
253// MainLoop()
254// Classic concurrent server model.
255// Wait for a client to connect, fork a child process
256// to do the business with the client, parent process
257// continues to wait for the next connection.
258// This function does not return.
259void MainLoop (int listen_fd)
260{
261        struct accept * client;
262        unsigned int addr = 0;
263        char buf[250];
264
265        int bytes_rcvd,
266                bytes_sent,
267                usando_moita = 0,
268                size_of_buffer,
269                i;
270
271        time_t inicio = time(NULL);
272
273        for ( ; ; )
274        {
275                client = AcceptClientConnection (listen_fd);
276                addr = ntohl(client->sa.sin_addr.s_addr);
277
278                sprintf(buf,"%d.%d.%d.%d",
279                                (addr >> 24)  , (addr >> 16) & 0xFF ,
280                                (addr >> 8) & 0xFF ,  addr & 0xFF);
281
282                printf("New connection: %s :: %d\n", buf, ntohs(client->sa.sin_port));
283
284                bzero(buf, 250);
285
286                if ( (bytes_rcvd = recv(client->newfd, buf, 128, 0)) < 1 )
287                        printf("error in recv #1\n");
288                else
289                {
290                        if ( strcmp(buf, __MOITA_FOI_SOLICITADA__) == 0 )
291                                if ( !usando_moita )
292                                {
293                                        bzero(buf, 250);
294                                        sprintf(buf, __OK__);
295                                        size_of_buffer = sizeof(buf);
296                                        for ( i = 0; i < size_of_buffer; i += bytes_sent )
297                                        {
298                                                bytes_sent = send (client->newfd, buf + i, sizeof(buf) - i, 0);
299
300                                                if ( bytes_sent < 0 )
301                                                        break;
302                                        }
303                                }
304                }
305        }
306}
307
308// AcceptClientConnection()
309// waits for a tcp connect to the socket listen_fd, which
310// must already be bound and set to listen on a local port.
311// Bombs on error, returns the fd of the new socket on success.
312struct accept * AcceptClientConnection (int listen_fd)
313{
314        int newfd;
315        struct sockaddr_in sa;
316        socklen_t socklen;
317
318        syslog (LOG_INFO, "AcceptClientConnection(fd%d)", listen_fd);
319
320        // Accept the connection and create a new socket for it.
321        socklen = sizeof (sa);
322        memset (&sa, 0, socklen);
323        do
324        {
325                newfd = accept (listen_fd, (struct sockaddr *) &sa, &socklen);
326        }
327        while ( (newfd < 0) && (errno == EINTR) );
328
329        syslog (LOG_INFO, "Accepted client connection on new socket fd%d", newfd);
330
331        if ( newfd < 0 )
332                syslog (LOG_ERR, "accept(): %m"), pthread_exit(0);
333
334        if ( socklen != sizeof (sa) )
335                syslog (LOG_ERR, "accept() screwed up!"), pthread_exit(0);
336
337        struct accept * new_accept = (struct accept *) malloc(sizeof(struct accept));
338        new_accept->newfd = newfd;
339        new_accept->sa = sa;
340
341        return (new_accept);
342}
343
344void VerifyClient(void * accept)
345{
346        int jabber_fd = (int)NULL;
347        struct accept * client = (struct accept *) accept;
348        struct client * user = (struct client *)NULL;
349        struct cat * info;
350        pthread_t cat_thread;
351
352        unsigned int addr = 0;
353        char buf[250];
354        addr = ntohl(client->sa.sin_addr.s_addr);
355        sprintf(buf,"%d.%d.%d.%d",
356                        (addr >> 24)  , (addr >> 16) & 0xFF ,
357                        (addr >> 8) & 0xFF ,  addr & 0xFF);
358        //printf("New connection: %s\n", buf);
359
360        //if ( strcmp(buf, "10.15.20.42") == 0 )//|| strcmp(buf, "10.15.20.202") == 0 )
361        //{
362        //      user = Handshake(client->newfd);
363        //      jabber_fd = user->jabber_fd;
364        //}
365
366        if ( jabber_fd == (int)NULL )
367        {
368                //jabber_fd = ConnectToServer(client->jabber_addr, client->jabber_port);
369
370                if ( user != (struct client *)NULL )
371                        user->jabber_fd = jabber_fd;
372        }
373
374        info = (struct cat *) malloc(sizeof(struct cat));
375
376        info->out_fd = jabber_fd;
377        info->in_fd = client->newfd;
378        info->jabber = (int)NULL;
379        info->keep_alive = (int)NULL;
380        info->client = user;
381
382        pthread_create(&cat_thread, NULL, (void *) &Cat, (void *)info );
383
384        pthread_exit(0);
385}
386
387struct client * Handshake(int newfd)
388{
389        float is_new_client;// = (float) NULL;
390        int bytes_rcvd,
391                bytes_sent,
392                i;
393
394        unsigned char * const buf = (char *) malloc (sizeof(char) * 5);
395        char * user = (char *) malloc(128 * sizeof(char)),
396                 * pass = (char *) malloc(128 * sizeof(char));
397
398        //struct client * clients = (struct client *)NULL;
399        struct client * new_client = (struct client *)NULL;
400
401        bzero(buf, 5);
402        sprintf(buf, "user");
403        for ( i = 0; i < sizeof(buf); i += bytes_sent )
404        {
405                bytes_sent = send (newfd, buf + i, sizeof(buf) - i, 0);
406
407                if ( bytes_sent < 0 )
408                        break;
409        }
410
411        bzero(user, 128);
412        if ( (bytes_rcvd = recv (newfd, user, 128, 0)) < 1 )
413                pthread_exit(0);
414
415        bzero(buf, 5);
416        sprintf(buf, "pass");
417        for ( i = 0; i < sizeof(buf); i += bytes_sent )
418        {
419                bytes_sent = send (newfd, buf + i, sizeof(buf) - i, 0);
420
421                if ( bytes_sent < 0 )
422                        break;
423        }
424
425        bzero(pass, 128);
426        if ( (bytes_rcvd = recv (newfd, pass, 128, 0)) < 1 )
427                pthread_exit(0);
428
429        pthread_mutex_lock (&mutexsum);
430        if ( clients == (struct client *)NULL )
431        {
432                clients = (struct client *) malloc(sizeof(struct client));
433
434                new_client = clients;
435                new_client->previous = (struct client *)NULL;
436                is_new_client = 1;
437        }
438        else
439        {
440                new_client = clients;
441                while ( ((is_new_client = (float)strcmp(new_client->user, user)) != 0) && (new_client->next != (struct client *)NULL) )
442                        new_client = new_client->next;
443
444                if ( is_new_client != 0 )
445                {
446                        new_client->next = (struct client *) malloc(sizeof(struct client));
447                        new_client->next->previous = new_client;
448                        new_client = new_client->next;
449                }
450        }
451
452        if ( is_new_client != 0 )
453        {
454                new_client->user = user;
455                new_client->jabber_fd = (int)NULL;
456                new_client->keep_alive = 1;
457                new_client->next = (struct client *)NULL;
458        }
459
460        bzero(buf, 5);
461        if ( is_new_client != 0 || new_client->jabber_fd == (int)NULL  )
462                sprintf(buf, "new");
463        else
464                sprintf(buf, "rec");
465
466        send (newfd, buf, 3, 0);
467
468        new_client->client_fd = newfd;
469        new_client->last_action = time(NULL);
470        pthread_mutex_unlock(&mutexsum);
471
472        return new_client;
473}
474
475// ConnectToServer()
476// attempts a tcp connect to the server specified
477// by addr and port.  Bombs on failure to connect,
478// returns the fd of the new socket on success.
479int ConnectToServer (struct in_addr addr, unsigned short port)
480{
481        // TODO: have a timeout for connect() - see Unix socket FAQ 6.2
482
483        int fd, err;
484        struct sockaddr_in sa;
485
486        // Create a socket and get its descriptor.
487        fd = socket (AF_INET, SOCK_STREAM, 0);
488
489        if ( fd < 0 )
490                syslog (LOG_ERR, "socket(): %m"), pthread_exit(0);//exit (EXIT_FAILURE);
491
492        sa.sin_family = AF_INET;
493        sa.sin_port = htons (port);
494        sa.sin_addr = addr;
495        memset (sa.sin_zero, 0, sizeof (sa.sin_zero));
496
497        err = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
498        if (err < 0)
499        {
500                syslog (LOG_ERR, "Unable to connect socket fd%d to server: %m", fd);
501                //exit (EXIT_FAILURE);
502                pthread_exit(0);
503        }
504
505        syslog (LOG_INFO, "Connected socket fd%d to server", fd);
506
507        return fd;
508}
509
510// Cat()
511// read data from in_fd and write it to out_fd until
512// the connection is closed by one of the peers.
513// Data is copied using a dynamically allocated buffer.
514//void Cat (int in_fd, int out_fd)
515//void Cat (int in_fd, int out_fd)
516void Cat (void * info)
517{
518        unsigned char * const buf_in = (char *) malloc (sizeof(char) * BUF_SIZE);
519        unsigned char * const buf_out = (char *) malloc (sizeof(char) * BUF_SIZE);
520        int bytes_rcvd_in = (int) NULL,
521                bytes_sent_in = (int) NULL,
522                bytes_rcvd_out = (int) NULL,
523                bytes_sent_out = (int) NULL,
524                i,
525                in_fd,
526                out_fd;
527        struct cat * user = (struct cat *) info;
528        in_fd = user->in_fd;
529        out_fd = user->out_fd;
530
531        syslog (LOG_INFO, "Cat(fd%d, fd%d)", in_fd, out_fd);
532
533        if ( buf_in == NULL || buf_out == NULL )
534                syslog (LOG_ERR, "malloc(): %m"), pthread_exit(0);
535
536        fcntl(in_fd, F_SETFL, fcntl(in_fd, F_GETFL, 0) | O_NDELAY);
537        fcntl(out_fd, F_SETFL, fcntl(out_fd, F_GETFL, 0) | O_NDELAY);
538
539        bzero(buf_in, BUF_SIZE);
540        bzero(buf_out, BUF_SIZE);
541        do
542        {
543                bzero(buf_in, BUF_SIZE);
544                if ( (bytes_rcvd_in = recv (in_fd, buf_in, BUF_SIZE, 0)) != 0 && strlen(buf_out) > 0 )
545                {
546                        for ( i = 0; i < bytes_rcvd_out; i += bytes_sent_in )
547                        {
548                                bytes_sent_in = send (in_fd, buf_out + i, bytes_rcvd_out - i, 0);
549
550                                if ( bytes_sent_in < 0 )
551                                        break;
552                        }
553                }
554
555                bzero(buf_out, BUF_SIZE);
556                if ( (bytes_rcvd_out = recv (out_fd, buf_out, BUF_SIZE, 0)) != 0 && strlen(buf_in) > 0 )
557                {
558                        //printf("\n%s\n", buf_in);
559                        for ( i = 0; i < bytes_rcvd_in; i += bytes_sent_out )
560                        {
561                                bytes_sent_out = send (out_fd, buf_in + i, bytes_rcvd_in - i, 0);
562
563                                if ( bytes_sent_out < 0 )
564                                        break;
565                        }
566                }
567                usleep(500);
568        }
569        while ( (bytes_rcvd_in != 0) && (bytes_rcvd_out != 0) );
570
571        if ( ((bytes_rcvd_in < 0) || (bytes_rcvd_out < 0)) && (errno != ECONNRESET) )
572                syslog (LOG_ERR, "recv(): %m"), pthread_exit(0);
573
574        if ( ((bytes_sent_in < 0) || (bytes_sent_out < 0)) && (errno != EPIPE) )
575                syslog (LOG_ERR, "send(): %m"), pthread_exit(0);
576
577        if ( user->jabber && !user->keep_alive )
578        {
579                shutdown(user->jabber, SHUT_RDWR);
580                close(user->jabber);
581        }
582        pthread_exit(0);
583        free (buf_in);
584        free (buf_out);
585}
586
587// NameToAddress()
588// Convert name to an ip address.
589// Returns 0 on success, -1 on failure.
590int NameToAddr (const char * name, struct in_addr * p_inaddr)
591{
592        struct hostent * he;
593
594        // First, attempt to convert from string ip format
595        // TODO: use inet_aton() instead
596        p_inaddr->s_addr = inet_addr (name);
597        if ( p_inaddr->s_addr != -1U ) // Success
598                return 0;
599
600        // Next, attempt to read from /etc/hosts or do a DNS lookup
601        he = gethostbyname (name);
602        if ( he != NULL ) // Success
603        {
604                memcpy (p_inaddr, he->h_addr, sizeof (struct in_addr));
605                return 0;
606        }
607
608        return -1; // Failed to resolve name to an ip address
609}
610
611// NameToPort()
612// Convert name to a port number. Name can either be a port name
613// (in which case proto must also be set to either "tcp" or "udp")
614// or name can be the ascii representation of the port number.
615// Returns 0 on success, -1 on failure.
616int NameToPort (const char * name, unsigned short * port, const char * proto)
617{
618        unsigned long lport;
619        char * errpos;
620        struct servent * se;
621
622        // First, attempt to convert string to integer
623        lport = strtoul (name, &errpos, 0);
624        if ( (*errpos == 0) && (lport <= 65535) ) // Success
625        {
626                *port = lport;
627                return 0;
628        }
629
630        // Next, attempt to read the string from /etc/services
631        se = getservbyname (name, proto);
632        if ( se != NULL) // Success
633        {
634                *port = ntohs (se->s_port);
635                return 0;
636        }
637
638        return -1; // Failed to resolve port name to a number
639}
640
641// quit()
642// Print an error message to stderr
643// and syslog, then exit the program.
644void quit (const char * fmt, ...) // quit with msg
645{
646        va_list ap;
647
648        fflush (stdout);
649
650        fprintf (stderr, "%s: ", g_program_name);
651
652        va_start (ap, fmt);
653        vfprintf (stderr, fmt, ap);
654        va_end (ap);
655
656        fputc ('\n', stderr);
657
658        syslog (LOG_ERR, "I quit!");
659
660        exit (EXIT_FAILURE);
661}
662
663// pbomb()
664// Print an error message to stderr
665// and syslog, then exit the program.
666// pbomb() additionally include the
667// string representation of errno.
668void pbomb (const char * fmt, ...) // bomb with perror
669{
670        va_list ap;
671        int errno_save = errno;
672        char buf[100];
673
674        fflush (stdout);
675
676        fprintf (stderr, "%s: ", g_program_name);
677
678        va_start (ap, fmt);
679        vsnprintf (buf, sizeof (buf), fmt, ap);
680        va_end (ap);
681
682        errno = errno_save;
683        perror (buf);
684
685        syslog (LOG_ERR, "Bang!: %s: %m", buf);
686
687        exit (EXIT_FAILURE);
688}
689
690// hbomb()
691// Print an error message to stderr
692// and syslog, then exit the program.
693// hbomb() additionally include the
694// string representation of h_errno.
695void hbomb (const char * fmt, ...) // bomb with herror
696{
697        va_list ap;
698        int h_errno_save = h_errno;
699        char buf[100];
700
701        fflush (stdout);
702
703        fprintf (stderr, "%s: ", g_program_name);
704
705        va_start (ap, fmt);
706        vsnprintf (buf, sizeof (buf), fmt, ap);
707        va_end (ap);
708
709        h_errno = h_errno_save;
710        herror (buf);
711
712        syslog (LOG_ERR, "Bang!: %s: %s", buf, hstrerror (h_errno));
713
714        exit (EXIT_FAILURE);
715}
716
717// set_signal_handler()
718// Sets a signal handler function.
719// Similar to signal() but this method
720// is more portable between platforms.
721void set_signal_handler (int signum, signal_handler_t sa_handler_func)
722{
723        struct sigaction act;
724
725        act.sa_handler = sa_handler_func;
726        sigemptyset (&(act.sa_mask));
727        act.sa_flags = 0;
728
729        if ( sigaction (signum, &act, NULL) < 0 )
730        {
731                syslog (LOG_ERR, "Error setting handler for signal %d: %m", signum);
732                exit (EXIT_FAILURE);
733        }
734}
Note: See TracBrowser for help on using the repository browser.