http://prdownloads.sourceforge.net/lufs/lufs-0.9.6.tar.gz?download
[lufs.git] / filesystems / cefs / asyncd / socket.c
1 /*
2  * socket.c -- socket library functions
3  *
4  * For license terms, see the file COPYING in this directory.
5  */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif /* HAVE_CONFIG_H */
10 #include <stdio.h>
11 #include <string.h>
12 #ifdef HAVE_MEMORY_H
13 #include <memory.h>
14 #endif /* HAVE_MEMORY_H */
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <netdb.h>
20 #if defined(STDC_HEADERS)
21 #include <stdlib.h>
22 #endif
23 #if defined(HAVE_UNISTD_H)
24 #include <unistd.h>
25 #endif
26 #if defined(HAVE_STDARG_H)
27 #include <stdarg.h>
28 #else
29 #include <varargs.h>
30 #endif
31 #include "socket.h"
32
33 #ifndef INET_ATON
34 #ifndef  INADDR_NONE
35 #ifdef   INADDR_BROADCAST
36 #define  INADDR_NONE    INADDR_BROADCAST
37 #else
38 #define  INADDR_NONE    -1
39 #endif
40 #endif
41 #endif /* INET_ATON */
42
43 int SockOpen(const char *host, int clientPort)
44 {
45     int sock;
46 #ifndef INET_ATON
47     unsigned long inaddr;
48 #endif /* INET_ATON */
49     struct sockaddr_in ad;
50     struct hostent *hp;
51
52     memset(&ad, 0, sizeof(ad));
53     ad.sin_family = AF_INET;
54
55     /* we'll accept a quad address */
56 #ifndef INET_ATON
57     inaddr = inet_addr(host);
58     if (inaddr != INADDR_NONE)
59         memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
60     else
61 #else
62     if (!inet_aton(host, &ad.sin_addr))
63 #endif /* INET_ATON */
64     {
65         hp = gethostbyname(host);
66
67         /*
68          * Add a check to make sure the address has a valid IPv4 or IPv6
69          * length.  This prevents buffer spamming by a broken DNS.
70          */
71         if (hp == NULL || (hp->h_length != 4 && hp->h_length != 8))
72             return -1;
73
74         memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
75     }
76     ad.sin_port = htons(clientPort);
77     
78     sock = socket(AF_INET, SOCK_STREAM, 0);
79     if (sock < 0)
80         return -1;
81     if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) < 0)
82     {
83         close(sock);
84         return -1;
85     }
86
87     return(sock);
88 }
89
90
91 #if defined(HAVE_STDARG_H)
92 int SockPrintf(int sock, char* format, ...)
93 {
94 #else
95 int SockPrintf(sock,format,va_alist)
96 int sock;
97 char *format;
98 va_dcl {
99 #endif
100
101     va_list ap;
102     char buf[8192];
103
104 #if defined(HAVE_STDARG_H)
105     va_start(ap, format) ;
106 #else
107     va_start(ap);
108 #endif
109 #ifdef HAVE_VSNPRINTF
110     vsnprintf(buf, sizeof(buf), format, ap);
111 #else
112     vsprintf(buf, format, ap);
113 #endif
114     va_end(ap);
115     return SockWrite(sock, buf, strlen(buf));
116
117 }
118
119 int SockWrite(int sock, char *buf, int len)
120 {
121     int n, wrlen = 0;
122
123     while (len)
124     {
125         n = write(sock, buf, len);
126         if (n <= 0)
127             return -1;
128         len -= n;
129         wrlen += n;
130         buf += n;
131     }
132     return wrlen;
133 }
134
135 int SockRead(int sock, char *buf, int len)
136 {
137     char *newline, *bp = buf;
138     int n;
139
140     if (--len < 1)
141         return(-1);
142     do {
143         /* 
144          * The reason for these gymnastics is that we want two things:
145          * (1) to read \n-terminated lines,
146          * (2) to return the true length of data read, even if the
147          *     data coming in has embedded NULS.
148          */
149         if ((n = recv(sock, bp, len, MSG_PEEK)) <= 0)
150             return(-1);
151         if ((newline = memchr(bp, '\n', n)) != NULL)
152             n = newline - bp + 1;
153         if ((n = read(sock, bp, n)) == -1)
154             return(-1);
155         bp += n;
156         len -= n;
157     } while 
158             (!newline && len);
159     *bp = '\0';
160     return bp - buf;
161 }
162
163 int SockPeek(int sock)
164 /* peek at the next socket character without actually reading it */
165 {
166     int n;
167     char ch;
168
169     if ((n = recv(sock, &ch, 1, MSG_PEEK)) == -1)
170         return -1;
171     else
172         return(ch);
173 }
174
175 #ifdef MAIN
176 /*
177  * Use the chargen service to test input beuffering directly.
178  * You may have to uncomment the `chargen' service description in your
179  * inetd.conf (and then SIGHUP inetd) for this to work. 
180  */
181 main()
182 {
183     int         sock = SockOpen("localhost", 19);
184     char        buf[80];
185
186     while (SockRead(sock, buf, sizeof(buf)-1))
187         SockWrite(1, buf, strlen(buf));
188 }
189 #endif /* MAIN */
190
191 /* socket.c ends here */