source: trunk/instant_messenger/socket/proxy.c @ 165

Revision 165, 20.5 KB checked in by niltonneto, 16 years ago (diff)

Adição de novos recursos do módulo.

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
21// Buffer size, in bytes, used for copying in the Cat() function.
22const size_t BUF_SIZE = 4096;
23
24// Global variables
25char g_program_name[100];       // Initialised from argv[0] in ParseArgs()
26
27// structs
28struct accept
29{
30        int newfd;
31        struct sockaddr_in sa;
32        struct in_addr jabber_addr;
33        unsigned short jabber_port;
34};
35
36/*struct client
37{
38        unsigned char * user;
39        unsigned char * key;
40        int jabber;
41        int shmid;
42        struct client * next,
43                                  * previous;
44};*/
45struct client
46{
47        char * user;
48        int client_fd;
49        int jabber_fd;
50        int keep_alive;
51        int connectionType; // 0 = read/write; 1 = read; -1 = write;
52        time_t last_action;
53        struct client * next;
54        struct client * previous;
55};
56
57struct cat
58{
59        int in_fd,
60                out_fd;
61        int jabber,
62                keep_alive;
63        struct client * client;
64        int connectionType;
65};
66
67struct client * clients = (struct client *)NULL;
68
69pthread_mutex_t mutexsum;
70
71// Typedef for a signal handler function.
72typedef void (* signal_handler_t) (int);
73
74// Prototypes for functions in this file.
75void ParseArgs (int, char **, struct in_addr *, unsigned short *, struct in_addr *, unsigned short *);
76void Initialise (void);
77void sig_child (int);
78int CreateServerSocket (struct in_addr, unsigned short);
79void Daemonise (void);
80void MainLoop (int, struct in_addr, unsigned short);
81struct accept * AcceptClientConnection (int);
82void VerifyClient(void *);
83struct client * Handshake(int);
84int ConnectToServer (struct in_addr, unsigned short);
85void Reading (void * info);
86void Writing (void * info);
87int NameToAddr (const char *, struct in_addr *);
88int NameToPort (const char *, unsigned short *, const char *);
89#ifdef __GNUC__
90        void quit (const char *, ...) __attribute__ ((format (printf, 1, 2)));
91        void pbomb (const char *, ...) __attribute__ ((format (printf, 1, 2)));
92        void hbomb (const char *, ...) __attribute__ ((format (printf, 1, 2)));
93#else
94        void quit (const char *, ...);
95        void pbomb (const char *, ...);
96        void hbomb (const char *, ...);
97#endif
98void set_signal_handler (int, signal_handler_t);
99
100int main (int argc, char ** argv)
101{
102        struct in_addr remote_addr,
103                                   local_addr;
104        unsigned short remote_port,
105                                   local_port;
106        int listen_fd;
107
108        ParseArgs (argc, argv, &remote_addr, &remote_port, &local_addr, &local_port);
109
110        Initialise ();
111
112        // Create server socket before becoming a daemon so
113        // there is still a chance to print an error message.
114        listen_fd = CreateServerSocket (local_addr, local_port);
115        if ( listen_fd < 0 )
116                pbomb ("Unable to create server socket");
117
118        //Daemonise ();
119
120        MainLoop (listen_fd, remote_addr, remote_port); // never returns
121
122        exit (EXIT_SUCCESS);
123}
124
125// ParseArgs()
126// Parse the command line arguments to extract the remote
127// and local adresses and port numbers, ra, rp, la & lp.
128// Exit the program gracefully upon error.
129void ParseArgs (int argc, char ** argv, struct in_addr * ra, unsigned short * rp, struct in_addr * la, unsigned short * lp)
130{
131        // argv[0] = program name
132        // argv[1] = remote_addr
133        // argv[2] = remote_port
134        // argv[3] = local_addr (optional)
135        // argv[4] = local_port (optional)
136
137        char * p = strrchr (argv[0], '/');
138
139        strncpy (g_program_name, (p == NULL) ? argv[0] : p + 1, sizeof (g_program_name) - 1);
140
141        if ( (argc < 3) || (argc > 5) )
142        {
143                fprintf (stderr, "usage: %s remote_addr remote_port [local_addr] [local_port]\n", argv[0]);
144                exit (EXIT_FAILURE);
145        }
146
147        if ( NameToAddr (argv[1], ra) )
148                hbomb ("Unable to resolve \"%s\" to an ip address", argv[1]);
149
150        if ( NameToPort (argv[2], rp, "tcp") )
151                quit ("Unable to resolve \"%s\" to a port number", argv[2]);
152
153        if ( argc < 4 )
154                la->s_addr = htonl (INADDR_ANY);
155        else
156                if ( NameToAddr (argv[3], la) )
157                        hbomb ("Unable to resolve \"%s\" to an ip address", argv[3]);
158
159        if ( argc < 5 )
160                memcpy (lp, rp, sizeof (*lp));
161        else
162                if ( NameToPort (argv[4], lp, "tcp") )
163                        quit ("Unable to resolve \"%s\" to a port number", argv[4]);
164}
165
166// Initialise()
167// Setup syslog, signal handlers, and other intialisation.
168void Initialise (void)
169{
170        openlog (g_program_name, LOG_PID, LOG_USER);
171        syslog (LOG_INFO, "%s started", g_program_name);
172
173        chdir ("/"); // Change working directory to the root.
174
175        umask (0); // Clear our file mode creation mask
176
177        //set_signal_handler (SIGCHLD, sig_child);
178
179        //signal (SIGPIPE, SIG_IGN);
180}
181
182// sig_child()
183// Handles SIGCHLD from exiting child processes.
184void sig_child (int signo)
185{
186        pid_t pid;
187
188        (void) signo; // suppress compiler warning
189
190        for ( ; ; )
191        {
192                write(1, "SIG\n", sizeof("SIG\n"));
193                pid = waitpid (WAIT_ANY, NULL, WNOHANG);
194
195                if ( pid > 0 )
196                        syslog (LOG_INFO, "Caught SIGCHLD from pid %d", pid);
197                else
198                        break;
199        }
200        write(1, "SIG...\n", sizeof("SIG...\n"));
201
202        if ( (pid < 0) && (errno != ECHILD) )
203                syslog (LOG_ERR, "waitpid(): %m"), exit (EXIT_FAILURE);
204
205        return;
206}
207
208// CreateServerSocket()
209// Create a socket, bind it to the specified address
210// and port, and set it to listen for client connections.
211// Returns < 0 on failure to bind, bombs on error otherwise,
212// returns the fd of the new socket on success.
213int CreateServerSocket (struct in_addr addr, unsigned short port)
214{
215        int err,
216                fd;
217        const int on = 1;
218        struct sockaddr_in sa;
219
220        // Create a socket and get its descriptor.
221        fd = socket (AF_INET, SOCK_STREAM, 0);
222        if ( fd < 0 )
223                syslog (LOG_ERR, "socket(): %m"), exit (EXIT_FAILURE);
224
225        // Set SO_REUSEADDR socket option
226        if ( setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 )
227                syslog (LOG_ERR, "setsockopt(fd%d, SO_REUSEADDR): %m", fd);
228
229        // Load a sa structure with the specified address and port
230        sa.sin_family = AF_INET;
231        sa.sin_port = htons (port);
232        //sa.sin_addr = addr;
233        sa.sin_addr.s_addr = htonl(INADDR_ANY);
234        memset (sa.sin_zero, 0, sizeof (sa.sin_zero));
235
236        // Bind our socket to the address and port specified
237        err = bind (fd, (struct sockaddr *) &sa, sizeof (sa));
238        if ( err < 0 )
239        {
240                syslog (LOG_ERR, "bind(): %m");
241                return err;
242        }
243
244        // Tell socket to listen and queue up to 5 incoming connections.
245        if ( listen (fd, 5) < 0 )
246                syslog (LOG_ERR, "listen(): %m"), exit (EXIT_FAILURE);
247
248        return fd;
249}
250
251// Daemonise()
252// Put the program in the background, set PPID=1, create a
253// new session and process group, without a controlling tty.
254void Daemonise (void)
255{
256        pid_t pid;
257
258        // Close stdin, stdout & stderr
259        // @TODO:
260        //              open /dev/null and dup the fd to stdin, stdout & stderr
261        //              close(STDIN_FILENO);
262        //              close(STDOUT_FILENO);
263        //              close(STDERR_FILENO);
264
265        syslog (LOG_INFO, "%s daemonising", g_program_name);
266
267        // Fork the process to put it in the background.
268
269        pid = fork ();
270        if ( pid == -1 )
271                syslog (LOG_ERR, "fork(): %m"), exit (EXIT_FAILURE);
272
273        // parent terminates here, so shell thinks the command is done.
274        if ( pid )
275                exit (0);
276
277        syslog (LOG_INFO, "%s in background", g_program_name);
278
279        // 1st child continues to run in the background with PPID=1
280
281        // Become leader of a new session and a new process group,
282        // with no controlling tty.
283        setsid ();
284
285        // Fork again to guarantee the process will
286        // not be able to aquire a controlling tty.
287
288        // signal (SIGHUP, SIG_IGN);
289        // required according to Stevens' UNP2 p333
290
291        pid = fork ();
292        if (pid == -1)
293                syslog (LOG_ERR, "fork(): %m"), exit (EXIT_FAILURE);
294
295        if ( pid ) // 1st child terminates
296                exit (0);
297
298        // 2nd child continues, no longer a session or group leader
299
300        syslog (LOG_INFO, "%s daemonised", g_program_name);
301}
302
303// MainLoop()
304// Classic concurrent server model.
305// Wait for a client to connect, fork a child process
306// to do the business with the client, parent process
307// continues to wait for the next connection.
308// This function does not return.
309void MainLoop (int listen_fd, struct in_addr rem_addr, unsigned short rem_port)
310{
311        struct accept * accept;
312        pthread_t accept_thread,
313                          clear_list_thread;
314
315        pthread_mutex_init(&mutexsum, NULL);
316
317        //pthread_create(&clear_list_thread, NULL, (void *) &ClearList, (void *)NULL );
318
319        for ( ; ; )
320        {
321                accept = AcceptClientConnection (listen_fd);
322                accept->jabber_addr = rem_addr;
323                accept->jabber_port = rem_port;
324
325                pthread_create(&accept_thread, NULL, (void *) &VerifyClient, (void *) accept);
326        }
327        pthread_mutex_destroy(&mutexsum);
328        pthread_exit(NULL);
329}
330
331// AcceptClientConnection()
332// waits for a tcp connect to the socket listen_fd, which
333// must already be bound and set to listen on a local port.
334// Bombs on error, returns the fd of the new socket on success.
335//int AcceptClientConnection (int listen_fd)
336struct accept * AcceptClientConnection (int listen_fd)
337{
338        int newfd;
339        struct sockaddr_in sa;
340        socklen_t socklen;
341
342        syslog (LOG_INFO, "AcceptClientConnection(fd%d)", listen_fd);
343
344        // Accept the connection and create a new socket for it.
345        socklen = sizeof (sa);
346        memset (&sa, 0, socklen);
347        do
348        {
349                newfd = accept (listen_fd, (struct sockaddr *) &sa, &socklen);
350        }
351        while ( (newfd < 0) && (errno == EINTR) );
352
353        syslog (LOG_INFO, "Accepted client connection on new socket fd%d", newfd);
354
355        if ( newfd < 0 )
356                syslog (LOG_ERR, "accept(): %m"), exit (EXIT_FAILURE);
357
358        if ( socklen != sizeof (sa) )
359                syslog (LOG_ERR, "accept() screwed up!"), exit (EXIT_FAILURE);
360
361        //return (newfd);
362
363        struct accept * new_accept = (struct accept *) malloc(sizeof(struct accept));
364        new_accept->newfd = newfd;
365        new_accept->sa = sa;
366
367        return (new_accept);
368}
369
370void VerifyClient(void * accept)
371{
372        int jabber_fd = (int)NULL,
373                connectionType = 0;
374        struct accept * client = (struct accept *) accept;
375        struct client * user = (struct client *)NULL;
376        struct cat * info;
377        pthread_t cat_thread;
378
379        /*FILE *file;
380        char line[80];
381        char *ips[20];
382        int cont;
383        int j;*/
384
385        unsigned int addr = 0;
386        char buf[250];
387        addr = ntohl(client->sa.sin_addr.s_addr);
388        sprintf(buf,"%d.%d.%d.%d",
389                        (addr >> 24)  , (addr >> 16) & 0xFF ,
390                        (addr >> 8) & 0xFF ,  addr & 0xFF);
391        printf("\nNew connection: %s\n", buf);
392
393        /*if(!(file = fopen("/etc/socket_im/hosts","r")))
394        {
395                printf("Impossível abrir o arquivo hosts \n");
396                exit(1);
397        }
398
399        fgets(line, 80, file);
400        while(!feof(file))
401        {
402                ips[cont] = malloc(sizeof(char)*17);
403                line[strlen(line) - 1 ] = '\0';
404                strcpy(ips[cont], line);
405                fgets(line, 80, file);
406                cont++;
407        }
408
409        fclose(file);
410
411        for( j = 0; j < cont; j++)
412        {
413                if( strcmp( buf, ips[j] ) == 0)
414                {
415                        user = Handshake(client->newfd);
416                        jabber_fd = user->jabber_fd;
417                        connectionType = user->connectionType;
418                        break;
419                }
420        }*/
421
422        if ( strcmp(buf, "10.15.20.42") == 0 )//|| strcmp(buf, "10.15.20.202") == 0 || strcmp(buf, "10.15.20.145") == 0 )
423        {
424                user = Handshake(client->newfd);
425                jabber_fd = user->jabber_fd;
426                connectionType = user->connectionType;
427        }
428
429        if ( jabber_fd == (int)NULL )
430        {
431                jabber_fd = ConnectToServer(client->jabber_addr, client->jabber_port);
432
433                if ( user != (struct client *)NULL )
434                        user->jabber_fd = jabber_fd;
435        }
436
437        info = (struct cat *) malloc(sizeof(struct cat));
438
439        info->in_fd = jabber_fd;
440        info->out_fd = client->newfd;
441        info->jabber = (int)NULL;
442        info->keep_alive = (int)NULL;
443        info->client = user;
444        info->connectionType = connectionType;
445
446        if ( !connectionType )
447        {
448                pthread_create(&cat_thread, NULL, (void *) &Reading, (void *)info );
449                pthread_create(&cat_thread, NULL, (void *) &Writing, (void *)info );
450        }
451        else
452        {
453                if ( connectionType == 1 )
454                        pthread_create(&cat_thread, NULL, (void *) &Reading, (void *)info );
455                else
456                        pthread_create(&cat_thread, NULL, (void *) &Writing, (void *)info );
457        }
458
459        pthread_exit(0);
460}
461
462struct client * Handshake(int newfd)
463{
464        float is_new_client;// = (float) NULL;
465        int bytes_rcvd,
466                bytes_sent,
467                connectionType,
468                i;
469
470        unsigned char * const buf = (char *) malloc (sizeof(char) * 5);
471        char * user = (char *) malloc(128 * sizeof(char)),
472                 * pass = (char *) malloc(128 * sizeof(char)),
473                 * type = (char *) malloc(128 * sizeof(char));
474
475        //struct client * clients = (struct client *)NULL;
476        struct client * new_client = (struct client *)NULL;
477
478        bzero(buf, 5);
479        sprintf(buf, "user");
480        for ( i = 0; i < sizeof(buf); i += bytes_sent )
481        {
482                bytes_sent = send (newfd, buf + i, sizeof(buf) - i, 0);
483
484                if ( bytes_sent < 0 )
485                        break;
486        }
487
488        bzero(user, 128);
489        if ( (bytes_rcvd = recv (newfd, user, 128, 0)) < 1 )
490        {
491                printf("USER....: %s", user);
492                shutdown(newfd, SHUT_RDWR);
493                close(newfd);
494                pthread_exit(0);
495        }
496
497        bzero(buf, 5);
498        sprintf(buf, "pass");
499        for ( i = 0; i < sizeof(buf); i += bytes_sent )
500        {
501                bytes_sent = send (newfd, buf + i, sizeof(buf) - i, 0);
502
503                if ( bytes_sent < 0 )
504                        break;
505        }
506
507        bzero(pass, 128);
508        if ( (bytes_rcvd = recv (newfd, pass, 128, 0)) < 1 )
509        {
510                printf("PASS....: %s", pass);
511                shutdown(newfd, SHUT_RDWR);
512                close(newfd);
513                pthread_exit(0);
514        }
515
516        bzero(buf, 5);
517        sprintf(buf, "type");
518        for ( i = 0; i < sizeof(buf); i += bytes_sent )
519        {
520                bytes_sent = send (newfd, buf + i, sizeof(buf) - i, 0);
521
522                if ( bytes_sent < 0 )
523                        break;
524        }
525
526        bzero(type, 128);
527        if ( (bytes_rcvd = recv (newfd, type, 128, 0)) < 1 )
528        {
529                printf("TYPE....: %s", type);
530                shutdown(newfd, SHUT_RDWR);
531                close(newfd);
532                pthread_exit(0);
533        }
534
535        pthread_mutex_lock (&mutexsum);
536        if ( clients == (struct client *)NULL )
537        {
538                clients = (struct client *) malloc(sizeof(struct client));
539
540                new_client = clients;
541                new_client->previous = (struct client *)NULL;
542                is_new_client = 1;
543        }
544        else
545        {
546                new_client = clients;
547                while ( ((is_new_client = (float)strcmp(new_client->user, user)) != 0) && (new_client->next != (struct client *)NULL) )
548                        new_client = new_client->next;
549        }
550
551        if ( is_new_client != 0 )
552        {
553                new_client->next = (struct client *) malloc(sizeof(struct client));
554                new_client->next->previous = new_client;
555                new_client = new_client->next;
556                new_client->user = user;
557                new_client->jabber_fd = (int)NULL;
558                new_client->keep_alive = 1;
559                new_client->next = (struct client *)NULL;
560        }
561
562        bzero(buf, 5);
563        if ( is_new_client != 0 || new_client->jabber_fd == (int)NULL  )
564                sprintf(buf, "new");
565        else
566                sprintf(buf, "rec");
567
568        send (newfd, buf, 3, 0);
569
570        new_client->client_fd = newfd;
571        new_client->last_action = time(NULL);
572        new_client->connectionType = 0;
573        pthread_mutex_unlock(&mutexsum);
574
575        if ( strcmp(type, "read") == 0 )
576                new_client->connectionType = 1;
577        else
578                if ( strcmp(type, "write") == 0 )
579                        new_client->connectionType = 2;
580
581        return new_client;
582}
583
584// ConnectToServer()
585// attempts a tcp connect to the server specified
586// by addr and port.  Bombs on failure to connect,
587// returns the fd of the new socket on success.
588int ConnectToServer (struct in_addr addr, unsigned short port)
589{
590        // TODO: have a timeout for connect() - see Unix socket FAQ 6.2
591
592        int fd, err;
593        struct sockaddr_in sa;
594
595        // Create a socket and get its descriptor.
596        fd = socket (AF_INET, SOCK_STREAM, 0);
597
598        if ( fd < 0 )
599                syslog (LOG_ERR, "socket(): %m"), exit (EXIT_FAILURE);
600
601        sa.sin_family = AF_INET;
602        sa.sin_port = htons (port);
603        sa.sin_addr = addr;
604        memset (sa.sin_zero, 0, sizeof (sa.sin_zero));
605
606        err = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
607        if (err < 0)
608        {
609                syslog (LOG_ERR, "Unable to connect socket fd%d to server: %m", fd);
610                exit (EXIT_FAILURE);
611        }
612
613        syslog (LOG_INFO, "Connected socket fd%d to server", fd);
614
615        return fd;
616}
617
618// Cat()
619// read data from in_fd and write it to out_fd until
620// the connection is closed by one of the peers.
621// Data is copied using a dynamically allocated buffer.
622void Reading (void * info)
623{
624        unsigned char * const buf = (char *) malloc (sizeof(char) * BUF_SIZE);
625        int bytes_rcvd,
626                bytes_sent = (int) NULL,
627                i;
628
629        struct cat * user = (struct cat *) info;
630        int in_fd = user->in_fd,
631                out_fd = user->out_fd;
632
633        syslog (LOG_INFO, "Reading(fd%d, fd%d)", in_fd, out_fd);
634
635        // @TODO: verificar alocacao buffer
636        //if ( buf == NULL )
637        //      syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
638
639        do
640        {
641                bzero(buf, BUF_SIZE);
642                bytes_rcvd = recv (in_fd, buf, BUF_SIZE, 0);
643
644                // descomentar para ver oq esta passado de informacao
645                //puts(buf);
646
647                for ( i = 0; i < bytes_rcvd; i += bytes_sent )
648                {
649                        bytes_sent = send (out_fd, buf + i, bytes_rcvd - i, 0);
650
651                        if ( bytes_sent < 0 )
652                                break;
653                }
654        }
655        while ( (bytes_rcvd > 0) && (bytes_sent > 0) );
656
657        //if ( (bytes_rcvd < 0) && (errno != ECONNRESET) )
658        //      syslog (LOG_ERR, "recv(): %m"), exit (EXIT_FAILURE);
659
660        //if ( (bytes_sent < 0) && (errno != EPIPE) )
661        //      syslog (LOG_ERR, "send(): %m"), exit (EXIT_FAILURE);
662
663        free (buf);
664        //shutdown (user->out_fd, SHUT_RDWR);
665        close (user->out_fd);
666        close (user->out_fd);
667        pthread_exit(0);
668}
669
670void Writing (void * info)
671{
672        unsigned char * const buf = (char *) malloc (sizeof(char) * BUF_SIZE);
673        int bytes_rcvd,
674                bytes_sent = (int) NULL,
675                i;
676
677        struct cat * user = (struct cat *) info;
678        int in_fd = user->out_fd,
679                out_fd = user->in_fd;
680
681        syslog (LOG_INFO, "Writing(fd%d, fd%d)", in_fd, out_fd);
682
683        // @TODO: verificar alocacao buffer
684        //if ( buf == NULL )
685        //      syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
686
687        do
688        {
689                bzero(buf, BUF_SIZE);
690                bytes_rcvd = recv (in_fd, buf, BUF_SIZE, 0);
691
692                // descomentar para ver oq esta passado de informacao
693                //puts(buf);
694
695                for ( i = 0; i < bytes_rcvd; i += bytes_sent )
696                {
697                        bytes_sent = send (out_fd, buf + i, bytes_rcvd - i, 0);
698
699                        if ( bytes_sent < 0 )
700                                break;
701                }
702        }
703        while ( (bytes_rcvd > 0) && (bytes_sent > 0) );
704
705        //if ( (bytes_rcvd < 0) && (errno != ECONNRESET) )
706        //      syslog (LOG_ERR, "recv(): %m"), exit (EXIT_FAILURE);
707
708        //if ( (bytes_sent < 0) && (errno != EPIPE) )
709        //      syslog (LOG_ERR, "send(): %m"), exit (EXIT_FAILURE);
710
711        free (buf);
712        //shutdown (user->out_fd, SHUT_RDWR);
713        close (user->out_fd);
714        close (user->out_fd);
715        pthread_exit(0);
716}
717
718// NameToAddress()
719// Convert name to an ip address.
720// Returns 0 on success, -1 on failure.
721int NameToAddr (const char * name, struct in_addr * p_inaddr)
722{
723        struct hostent * he;
724
725        // First, attempt to convert from string ip format
726        // TODO: use inet_aton() instead
727        p_inaddr->s_addr = inet_addr (name);
728        if ( p_inaddr->s_addr != -1U ) // Success
729                return 0;
730
731        // Next, attempt to read from /etc/hosts or do a DNS lookup
732        he = gethostbyname (name);
733        if ( he != NULL ) // Success
734        {
735                memcpy (p_inaddr, he->h_addr, sizeof (struct in_addr));
736                return 0;
737        }
738
739        return -1; // Failed to resolve name to an ip address
740}
741
742// NameToPort()
743// Convert name to a port number. Name can either be a port name
744// (in which case proto must also be set to either "tcp" or "udp")
745// or name can be the ascii representation of the port number.
746// Returns 0 on success, -1 on failure.
747int NameToPort (const char * name, unsigned short * port, const char * proto)
748{
749        unsigned long lport;
750        char * errpos;
751        struct servent * se;
752
753        // First, attempt to convert string to integer
754        lport = strtoul (name, &errpos, 0);
755        if ( (*errpos == 0) && (lport <= 65535) ) // Success
756        {
757                *port = lport;
758                return 0;
759        }
760
761        // Next, attempt to read the string from /etc/services
762        se = getservbyname (name, proto);
763        if ( se != NULL) // Success
764        {
765                *port = ntohs (se->s_port);
766                return 0;
767        }
768
769        return -1; // Failed to resolve port name to a number
770}
771
772// quit()
773// Print an error message to stderr
774// and syslog, then exit the program.
775void quit (const char * fmt, ...) // quit with msg
776{
777        va_list ap;
778
779        fflush (stdout);
780
781        fprintf (stderr, "%s: ", g_program_name);
782
783        va_start (ap, fmt);
784        vfprintf (stderr, fmt, ap);
785        va_end (ap);
786
787        fputc ('\n', stderr);
788
789        syslog (LOG_ERR, "I quit!");
790
791        exit (EXIT_FAILURE);
792}
793
794// pbomb()
795// Print an error message to stderr
796// and syslog, then exit the program.
797// pbomb() additionally include the
798// string representation of errno.
799void pbomb (const char * fmt, ...) // bomb with perror
800{
801        va_list ap;
802        int errno_save = errno;
803        char buf[100];
804
805        fflush (stdout);
806
807        fprintf (stderr, "%s: ", g_program_name);
808
809        va_start (ap, fmt);
810        vsnprintf (buf, sizeof (buf), fmt, ap);
811        va_end (ap);
812
813        errno = errno_save;
814        perror (buf);
815
816        syslog (LOG_ERR, "Bang!: %s: %m", buf);
817
818        exit (EXIT_FAILURE);
819}
820
821// hbomb()
822// Print an error message to stderr
823// and syslog, then exit the program.
824// hbomb() additionally include the
825// string representation of h_errno.
826void hbomb (const char * fmt, ...) // bomb with herror
827{
828        va_list ap;
829        int h_errno_save = h_errno;
830        char buf[100];
831
832        fflush (stdout);
833
834        fprintf (stderr, "%s: ", g_program_name);
835
836        va_start (ap, fmt);
837        vsnprintf (buf, sizeof (buf), fmt, ap);
838        va_end (ap);
839
840        h_errno = h_errno_save;
841        herror (buf);
842
843        syslog (LOG_ERR, "Bang!: %s: %s", buf, hstrerror (h_errno));
844
845        exit (EXIT_FAILURE);
846}
847
848// set_signal_handler()
849// Sets a signal handler function.
850// Similar to signal() but this method
851// is more portable between platforms.
852void set_signal_handler (int signum, signal_handler_t sa_handler_func)
853{
854        struct sigaction act;
855
856        act.sa_handler = sa_handler_func;
857        sigemptyset (&(act.sa_mask));
858        act.sa_flags = 0;
859
860        if ( sigaction (signum, &act, NULL) < 0 )
861        {
862                syslog (LOG_ERR, "Error setting handler for signal %d: %m", signum);
863                exit (EXIT_FAILURE);
864        }
865}
Note: See TracBrowser for help on using the repository browser.