source: trunk/instant_messenger/socket/BKP_20071105/BKP_20071026/BKP_20071019/BKP_20071018/BKP_20071009/BKP_20071008/BKP/BOOK/unp.h @ 151

Revision 151, 12.9 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 "config.h"
2
3#include <sys/types.h>          /* basic system data type */
4#include <sys/socket.h>         /* basic socket definitions */
5#include <sys/time.h>           /* timeval{} for select() */
6#include <time.h>                       /* timespec{} for pselect() */
7#include <netinet/in.h>         /* sockaddr_in{} and other Internet defns */
8#include <arpa/inet.h>          /* inet(3) functions */
9#include <errno.h>
10#include <fcntl.h>                      /* for nonblocking */
11#include <netdb.h>
12#include <signal.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/stat.h>           /* for S_xxx file mode constants */
17#include <sys/uio.h>            /* for iovec{} and readv/writev */
18#include <unistd.h>
19#include <sys/wait.h>
20#include <sys/un.h>                     /* for Unix domain sockets */
21
22#ifdef  HAVE_SYS_SELECT_H
23        #include <sys/select.h> /* for convenience */
24#endif
25
26#ifdef  HAVE_POLL_H
27        #include <poll.h>       /* for convenience */
28#endif
29
30#ifdef  HAVE_STRINGS_H
31        #include <strings.h>    /* for convenience */
32#endif
33
34/* Three headers are normally needed for socket/file ioctl's:
35 * <sys/ioctl.h>, <sys/filio.h> and <sys/sockio.h>.
36 */
37#ifdef HAVE_SYS_IOCTL_H
38        #include <sys/ioctl.h>
39#endif
40
41#ifdef HAVE_SYS_FILIO_H
42        #include <sys/filio.h>
43#endif
44
45#ifdef HAVE_SYS_SOCKIO_H
46        #include <sys/sockio.h>
47#endif
48
49#ifdef HAVE_PTHREAD_H
50        #include <pthread.h>
51#endif
52
53/* OSF/1 actually disable recv() and send() in <sys/socket.h> */
54#ifdef __osf__
55        #undef recv
56        #undef send
57        #define recv(a,b,c,d)   recvfrom(a,b,c,d,0,0)
58        #define send(a,b,c,d)   sendto(a,b,c,d,0,0)
59#endif
60
61#ifndef INADDR_NOME
62        #define INADDR_NOME 0xffffffff  /* should have been in <netinet/in.h> */
63#endif
64
65#ifndef SHUT_RD                         /* these three Posix.1g names are quite now */
66        #define SHUT_RD         0       /* shutdown for reading */
67        #define SHUT_WR         1       /* shutdown for writing */
68        #define SHUT_RDWR       2       /* shutdown for reading and writing */
69#endif
70
71#ifndef INET_ADDRSTRLEN
72        #define INETADDRSTRLEN 16       /* "ddd.ddd.ddd.ddd\0" 1234567890123456 */
73#endif
74
75/* Define following even if IPv6 not supported, so we can always allocate
76 * an adequately-sized buffer, without #ifdefs in the code.
77 */
78#ifndef INET6_ADDRSTRLEN
79        #define INET6_ADDRSTRLEN 46     /* max size of IPv6 address string:
80                                                                 * "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" or
81                                                                 * "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd\0"
82                                                                 * 1234567890123456789012345678901234567890123456
83                                                                 */
84#endif
85
86/* Define bzero() as a macro if it's not standard C libary. */
87#ifndef HAVE_BZERO
88        #define bzero(ptr,n)    memset(ptr,0,n)
89#endif
90
91/* Older resolvers do not have gethostbyname2() */
92#ifndef HAVE_GETHOSTBYNAME2
93        #define gethostbyname2(host,family)             gethostbyname((host))
94#endif
95
96/* The structure returned by recvfrom_frags() */
97//struct in_pktinfo
98//{
99//      struct in_addr ipi_addr;        /* dst IPv4 address */
100//      int ipi_ifindex;                        /* received interface index */
101//}
102
103/* We need the newer CMSG_LEN() and CMSG_SPACE() macros, but few
104 * implementions support them today. These two macros really need
105 * an ALIGN() macro, but each implementation does this differently. */
106#ifndef CMSG_LEN
107        #define CMSG_LEN(size)          (sizeof(struct cmsghdr) + (size))
108#endif
109#ifndef CMSG_SPACE
110        #define CMSG_SPACE(size)        (sizeof(struct cmsghdr) + (size))
111#endif
112
113/* Posix.1g requires the SUN_LEN() macro but not all implementations
114 * define it (yet). Note that this 4.4BSD macro works regardless
115 * whether there is a length field or not
116 */
117#ifndef SUN_LEN
118        #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
119#endif
120
121/* Posix.1g remanes "Unix domain" as "local IPC". But
122 * not all systems define AF_LOCAL and PF_LOCAL (yet).
123 */
124#ifndef AF_LOCAL
125        #define AF_LOCAL        AF_UNIX
126#endif
127#ifndef PF_LOCAL
128        #define PF_LOCAL        PF_UNIX
129#endif
130
131/* Posix.1g require that an include of <poll.h> define INFTIM, but
132 * many systems still define it in <sys/stropts.h>. We don't want
133 * to include all the streams stuff if it's not needed, so we just
134 * define INFTIM here. This is the standard value, but there's no
135 * guarantee it is -1.
136 */
137#ifndef INFTIM
138        #define INFTIM (-1)                     /* infinite poll timeout */
139        #ifdef HAVE_POLL_H
140                #define INFTIM_UNPH             /* tell unpxti.h we defined it */
141        #endif
142#endif
143
144/* Following could be derived from SOMAXCONN in <sys/socket.h>, but many
145 * kernels still #define it as 5, while actually supporting many more
146 */
147#define LISTENQ         1024    /* 2nd argument to listen() */
148
149/* Miscellaneous constants */
150#define MAXLINE         4096    /* max text line length */
151#define MAXSOCKADDR     128             /* max socket address struct size */
152#define BUFFSIZE        8192    /* buffer size for reads and writes */
153
154/* Define some port number that can be used for client-servers */
155#define SERV_PORT               9877                    /* TCP and UDP client-servers */
156#define SERV_PORT_STR   "9877"                  /* TCP and UDP client-servers */
157#define UNIXSTR_PATH    "/tmp/unix.str" /* Unix domain stream cli-serv */
158#define UNIXDG_PATH     "/tmp/unix.dg"  /* Unix domain datagram cli-serv */
159
160/* Following shortens all the type casts of point arguments */
161#define SA struct sockaddr
162#define FILE_MODE       (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)         /* default file access permissions for new files */
163#define DIR_MODE        (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)       /* default permissions for new directories */
164
165typedef void Sigfunc(int);      /* for signal handlers */
166
167#define min(a,b)        ((a) < (b) ? (a) : (b))
168#define max(a,b)        ((a) > (b) ? (a) : (b))
169
170#include <stdarg.h>             /* ANSI C hearder file */
171#include <syslog.h>             /* for syslog() */
172
173int daemon_proc;
174
175static void err_doit(int, int, const char *, va_list);
176
177void err_ret(const char * fmt, ...)
178{
179        va_list ap;
180        va_start(ap, fmt);
181        err_doit(1, LOG_INFO, fmt, ap);
182        va_end(ap);
183        return;
184}
185
186int err_sys(const char * fmt, ...)
187{
188        va_list ap;
189        va_start(ap, fmt);
190        err_doit(1, LOG_INFO, fmt, ap);
191        va_end(ap);
192        exit(1);
193}
194
195void err_dump(const char * fmt, ...)
196{
197        va_list ap;
198        va_start(ap, fmt);
199        err_doit(1, LOG_INFO, fmt, ap);
200        va_end(ap);
201        abort();
202        exit(1);
203}
204
205void err_msg(const char * fmt, ...)
206{
207        va_list ap;
208        va_start(ap, fmt);
209        err_doit(1, LOG_INFO, fmt, ap);
210        va_end(ap);
211        return;
212}
213
214void err_quit(const char * fmt, ...)
215{
216        va_list ap;
217        va_start(ap, fmt);
218        err_doit(1, LOG_INFO, fmt, ap);
219        va_end(ap);
220        exit(1);
221}
222
223static void err_doit(int errnoflag, int level, const char * fmt, va_list ap)
224{
225        int errno_save,
226                n;
227        char buf[MAXLINE + 1];
228
229        errno_save = errno;
230        #ifdef HAVE_VSNPRINTF
231                vsnprintf(buf, MAXLINE, fmt, ap);
232        #else
233                vsprintf(buf, fmt, ap);
234        #endif
235        n = strlen(buf);
236        if ( errnoflag )
237                snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
238        else
239        {
240                fflush(stdout);
241                fputs(buf, stderr);
242                fflush(stderr);
243        }
244        return;
245}
246
247int Socket(int family, int type, int protocol)
248{
249        int n;
250        if ( (n = socket(family, type, protocol)) < 0 )
251                err_sys("socket error");
252        return(n);
253}
254
255void Listen(int fd, int backlog)
256{
257        char * ptr;
258        /* can override 2nd argument with environment variable */
259        if ( (ptr = getenv("LISTENQ")) != NULL )
260                backlog = atoi(ptr);
261        if ( listen(fd, backlog) < 0 )
262                err_sys("listen error");
263}
264
265/* Read 'n' bytes from a descriptor. */
266ssize_t readn(int fd, void * vptr, size_t n)
267{
268        size_t  nleft;
269        ssize_t nread;
270        char    * ptr;
271
272        ptr = vptr;
273        nleft = n;
274        while ( nleft > 0 )
275        {
276                if ( (nleft = read(fd, ptr, nleft)) < 0 )
277                {
278                        if ( errno == EINTR )
279                                nread = 0; /* and call read() again */
280                        else
281                                return (-1);
282                }
283                else if ( nread == 0 )
284                        break; /* EOF */
285
286                nleft -= nread;
287                ptr += nread;
288        }
289        return (n - nleft); /* return >= 0 */
290}
291
292/* Write 'n' bytes to a descriptor. */
293ssize_t writen(int fd, const void *(vptr), size_t n)
294{
295        size_t  nleft;
296        ssize_t nwritten;
297        const char * ptr;
298
299        ptr = vptr;
300        nleft = n;
301        while ( nleft > 0 )
302        {
303                if ( (nwritten = write(fd, ptr, nleft)) <= 0 )
304                {
305                        if ( errno == EINTR )
306                                nwritten = 0; /*and call write() again */
307                        else
308                                return (-1); /* error */
309                }
310
311                nleft -= nwritten;
312                ptr += nwritten;
313        }
314        return (n);
315}
316
317ssize_t readline(int fd, void *(vptr), size_t maxlen)
318{
319        size_t  n,
320                        rc;
321        char c,
322                 * ptr;
323
324        ptr = vptr;
325        for ( n = 1; n < maxlen; n++ )
326        {
327                again:
328                        if ( (rc = read(fd, &(c), 1)) == 1 )
329                        {
330                                *(ptr)++ = c;
331                                if ( c == '\n' )
332                                        break; /* newline is stored, like fgets() */
333                        }
334                        else if ( rc == 0 )
335                        {
336                                if ( n == 1 )
337                                        return(0); /* EOF, no data read */
338                                else
339                                        break; /* EOF, some data read */
340                        }
341                        else
342                        {
343                                if ( errno == EINTR )
344                                        goto again;
345                                return(-1); /* error, errno set by read() */
346                        }
347        }
348
349        *(ptr) = 0; /* null terminate like fgets() */
350        return(n);
351}
352
353char * gf_time(void)
354{
355        struct timeval tv;
356        static char str[30];
357        char * ptr;
358
359        if ( gettimeofday(&tv, NULL) < 0 )
360                err_sys("gettimeofday error");
361
362        ptr = ctime(&tv.tv_sec);
363        strcpy(str, &ptr[11]);
364        snprintf(str + 8, sizeof(str) - 8, ".%06d", tv.tv_usec);
365        return(str);
366}
367
368void str_echo(int sockfd)
369{
370        long arg1,
371                 arg2;
372        ssize_t n;
373        char line[MAXLINE];
374
375        for ( ; ; )
376        {
377                if ( (n = readline(sockfd, line, MAXLINE)) == 0 )
378                        return; /* connection closed by other end */
379
380                /*if ( sscanf(line, "%ld%ld", &(arg1), &(arg2)) == 2 )
381                        snprintf(line, sizeof(line), "%ld\n", arg1 + arg2);
382                else
383                        snprintf(line, sizeof(line), "input error\n");
384
385                n = strlen(line);*/
386                writen(sockfd, line, n);
387        }
388}
389
390void str_cli(FILE * fp, int sockfd)
391{
392        int maxfdp1, stdineof, val;
393        ssize_t n, nwritten;
394        fd_set rset, wset;
395        char sendline[MAXLINE],
396                 recvline[MAXLINE];
397        char to[MAXLINE],
398                 fr[MAXLINE];
399        char * toiptr,
400                 * tooptr,
401                 * friptr,
402                 * froptr;
403
404        val = fcntl(sockfd, F_GETFL, 0);
405        fcntl(sockfd, F_SETFL, val| O_NONBLOCK);
406
407        val = fcntl(STDIN_FILENO, F_GETFL, 0);
408        fcntl(STDIN_FILENO, F_SETFL, val| O_NONBLOCK);
409
410        val = fcntl(STDOUT_FILENO, F_GETFL, 0);
411        fcntl(STDOUT_FILENO, F_SETFL, val| O_NONBLOCK);
412
413        toiptr = tooptr = to;
414        friptr = froptr = fr;
415        stdineof = 0;
416
417        maxfdp1 = max(max(STDIN_FILENO, STDOUT_FILENO), sockfd) + 1;
418        for ( ; ; )
419        {
420                FD_ZERO(&(rset));
421                FD_ZERO(&(wset));
422                if ( stdineof == 0 && toiptr < &to[MAXLINE] )
423                        FD_SET(STDIN_FILENO, &(rset));  /* read from stdin */
424                if ( friptr < &fr[MAXLINE] )
425                        FD_SET(sockfd, &(rset));                /* read from socket */
426                if ( tooptr != toiptr )
427                        FD_SET(sockfd, &(wset));                /* data to wrtite to socket */
428                if ( froptr != friptr )
429                        FD_SET(STDOUT_FILENO, &(wset)); /* data to wrtite to stdout */
430
431                select(maxfdp1, &(rset), &(wset), NULL, NULL);
432
433                if ( FD_ISSET(STDIN_FILENO, &(rset)) )
434                {
435                        if ( (n = readline(STDIN_FILENO, toiptr, &to[MAXLINE] - toiptr)) < 0 )
436                        {
437                                if ( errno != EWOULDBLOCK )
438                                        err_sys("read error on stdin");
439                        }
440                        else if ( n == 0 )
441                        {
442                                fprintf(stderr, "%s: EOF on stdin\n", gf_time());
443                                stdineof = 1;   /* all done with stdin */
444                                if ( tooptr == toiptr )
445                                        shutdown(sockfd, SHUT_WR);      /* send FIN */
446                        }
447                        else
448                        {
449                                fprintf(stderr, "%s: read %d bytes from socket\n", gf_time(), n);
450                                toiptr += n;    /* # just read */
451                                FD_SET(sockfd, &(wset));        /* try and write below */
452                        }
453                }
454
455                if ( FD_ISSET(sockfd, &(rset)) )
456                {
457                        if ( (n = readline(sockfd, friptr, &fr[MAXLINE] - friptr)) < 0 )
458                        {
459                                if ( errno != EWOULDBLOCK )
460                                        err_sys("read error on socket");
461                        }
462                        else if ( n == 0 )
463                        {
464                                fprintf(stderr, "%s: EOF on socket\n", gf_time());
465                                if ( stdineof )
466                                        return; /* normal termination */
467                                else
468                                        err_quit("server terminated prematurely");
469                        }
470                        else
471                        {
472                                fprintf(stderr, "%s: read %d bytes from socket\n", gf_time(), n);
473                                friptr += n;    /* # just read */
474                                FD_SET(STDOUT_FILENO, &(wset)); /* try and write below */
475                        }
476                }
477
478                if ( FD_ISSET(STDOUT_FILENO, &(wset)) && ((n = friptr - froptr) < 0) )
479                {
480                        if ( (nwritten = write(STDOUT_FILENO, froptr, n)) < 0 )
481                        {
482                                if ( errno != EWOULDBLOCK )
483                                        err_sys("write error to stdout");
484                        }
485                        else
486                        {
487                                fprintf(stderr, "%s: wrote %d bytes to stdout\n", gf_time(), nwritten);
488                                froptr += nwritten;     /* # just written */
489                                if ( froptr == friptr )
490                                        froptr = friptr = fr;   /* back to beginning of buffer */
491                        }
492                }
493
494                if ( FD_ISSET(sockfd, &(wset)) && ((n = toiptr - tooptr) < 0) )
495                {
496                        if ( (nwritten = write(sockfd, tooptr, n)) < 0 )
497                        {
498                                if ( errno != EWOULDBLOCK )
499                                        err_sys("write error to socket");
500                        }
501                        else
502                        {
503                                fprintf(stderr, "%s: wrote %d bytes to socket\n", gf_time(), nwritten);
504                                tooptr += nwritten;     /* # just written */
505                                if ( tooptr == toiptr )
506                                {
507                                        tooptr = toiptr = to;   /* back to beginning of buffer */
508                                        if ( stdineof )
509                                                shutdown(sockfd, SHUT_WR);      /* send FIN */
510                                }
511                        }
512                }
513
514
515
516
517
518                /*
519                if ( FD_ISSET(fileno(fp), &(rset)) ) // input is readable
520                {
521                        if ( fgets(sendline, MAXLINE, fp) == NULL )
522                        {
523                                stdineof == 1;
524                                shutdown(sockfd, SHUT_WR); // send FIN
525                                FD_CLR(fileno(fp), &(rset));
526                                continue;
527                        }
528                        writen(sockfd, sendline, strlen(sendline));
529                }
530                */
531        }
532}
533
534Sigfunc * signal(int signo, Sigfunc * func)
535{
536        struct sigaction act,
537                                         oact;
538
539        act.sa_handler = func;
540        sigemptyset(&(act.sa_mask));
541        act.sa_flags = 0;
542        if ( signo == SIGALRM )
543        {
544                #ifdef SA_INTERRUPT
545                        act.sa_flags |= SA_INTERRUPT;   /* SunOS 4.x */
546                #endif
547        }
548        else
549        {
550                #ifdef SA_RESTART
551                        act.sa_flags |= SA_RESTART;             /* SVR4, 4.4BSD */
552                #endif
553        }
554        if ( sigaction(signo, &(act), &(oact)) < 0 )
555                return SIG_ERR;
556        return oact.sa_handler;
557}
558
559void sig_chld(int signo)
560{
561        pid_t pid;
562        int stat;
563
564        while ( (pid = waitpid(-1, &(stat), WNOHANG)) > 0 )
565                printf("child %d terminated\n", pid);
566        return;
567}
Note: See TracBrowser for help on using the repository browser.