* All OS-level includes are now included from webcit.h instead of from
[citadel.git] / webcit / tcp_sockets.c
1 /*
2  * $Id$
3  * 
4  * TCP client socket module for WebCit
5  *
6  */
7
8 /*
9  * Uncomment this to log all communications with the Citadel server
10 #define SERV_TRACE 1
11  */
12
13 #include "webcit.h"
14 #include "webserver.h"
15
16 #ifndef INADDR_NONE
17 #define INADDR_NONE 0xffffffff
18 #endif
19
20 RETSIGTYPE timeout(int signum)
21 {
22         lprintf(1, "Connection timed out.\n");
23         exit(3);
24 }
25
26
27
28 /*
29  * Connect a unix domain socket
30  */
31 int uds_connectsock(char *sockpath)
32 {
33         struct sockaddr_un addr;
34         int s;
35
36         memset(&addr, 0, sizeof(addr));
37         addr.sun_family = AF_UNIX;
38         strncpy(addr.sun_path, sockpath, sizeof addr.sun_path);
39
40         s = socket(AF_UNIX, SOCK_STREAM, 0);
41         if (s < 0) {
42                 lprintf(1, "Can't create socket: %s\n",
43                         strerror(errno));
44                 return(-1);
45         }
46
47         if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
48                 lprintf(1, "Can't connect: %s\n",
49                         strerror(errno));
50                 close(s);
51                 return(-1);
52         }
53
54         return s;
55 }
56
57
58 /*
59  * Connect a TCP/IP socket
60  */
61 int tcp_connectsock(char *host, char *service)
62 {
63         struct hostent *phe;
64         struct servent *pse;
65         struct protoent *ppe;
66         struct sockaddr_in sin;
67         int s;
68
69         memset(&sin, 0, sizeof(sin));
70         sin.sin_family = AF_INET;
71
72         pse = getservbyname(service, "tcp");
73         if (pse) {
74                 sin.sin_port = pse->s_port;
75         } else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) {
76                 lprintf(1, "Can't get %s service entry\n", service);
77                 return (-1);
78         }
79         phe = gethostbyname(host);
80         if (phe) {
81                 memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
82         } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
83                 lprintf(1, "Can't get %s host entry: %s\n",
84                         host, strerror(errno));
85                 return (-1);
86         }
87         if ((ppe = getprotobyname("tcp")) == 0) {
88                 lprintf(1, "Can't get TCP protocol entry: %s\n",
89                         strerror(errno));
90                 return (-1);
91         }
92
93         s = socket(PF_INET, SOCK_STREAM, ppe->p_proto);
94         if (s < 0) {
95                 lprintf(1, "Can't create socket: %s\n", strerror(errno));
96                 return (-1);
97         }
98         signal(SIGALRM, timeout);
99         alarm(30);
100
101         if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
102                 lprintf(1, "Can't connect to %s.%s: %s\n",
103                         host, service, strerror(errno));
104                 close(s);
105                 return (-1);
106         }
107         alarm(0);
108         signal(SIGALRM, SIG_IGN);
109
110         return (s);
111 }
112
113
114
115
116 /*
117  * Input binary data from socket
118  */
119 void serv_read(char *buf, int bytes)
120 {
121         int len, rlen;
122
123         len = 0;
124         while (len < bytes) {
125                 rlen = read(WC->serv_sock, &buf[len], bytes - len);
126                 if (rlen < 1) {
127                         lprintf(1, "Server connection broken: %s\n",
128                                 strerror(errno));
129                         close(WC->serv_sock);
130                         WC->serv_sock = (-1);
131                         WC->connected = 0;
132                         WC->logged_in = 0;
133                         memset(buf, 0, bytes);
134                         return;
135                 }
136                 len = len + rlen;
137         }
138 }
139
140
141 /*
142  * input string from pipe
143  */
144 void serv_getln(char *strbuf, int bufsize)
145 {
146         int ch, len;
147         char buf[2];
148
149         len = 0;
150         strbuf[0] = 0;
151         do {
152                 serv_read(&buf[0], 1);
153                 ch = buf[0];
154                 strbuf[len++] = ch;
155         } while ((ch != 10) && (ch != 0) && (len < (bufsize-1)));
156         if (strbuf[len-1] == 10) strbuf[--len] = 0;
157         if (strbuf[len-1] == 13) strbuf[--len] = 0;
158 #ifdef SERV_TRACE
159         lprintf(9, "%3d>%s\n", WC->serv_sock, strbuf);
160 #endif
161 }
162
163
164
165 /*
166  * send binary to server
167  */
168 void serv_write(char *buf, int nbytes)
169 {
170         int bytes_written = 0;
171         int retval;
172         while (bytes_written < nbytes) {
173                 retval = write(WC->serv_sock, &buf[bytes_written],
174                                nbytes - bytes_written);
175                 if (retval < 1) {
176                         lprintf(1, "Server connection broken: %s\n",
177                                 strerror(errno));
178                         close(WC->serv_sock);
179                         WC->serv_sock = (-1);
180                         WC->connected = 0;
181                         WC->logged_in = 0;
182                         return;
183                 }
184                 bytes_written = bytes_written + retval;
185         }
186 }
187
188
189 /*
190  * send line to server
191  */
192 void serv_puts(char *string)
193 {
194         char buf[SIZ];
195
196 #ifdef SERV_TRACE
197         lprintf(9, "%3d<%s\n", WC->serv_sock, string);
198 #endif
199         sprintf(buf, "%s\n", string);
200         serv_write(buf, strlen(buf));
201 }
202
203
204 /*
205  * convenience function to send stuff to the server
206  */
207 void serv_printf(const char *format,...)
208 {
209         va_list arg_ptr;
210         char buf[SIZ];
211
212         va_start(arg_ptr, format);
213         vsnprintf(buf, sizeof buf, format, arg_ptr);
214         va_end(arg_ptr);
215
216         strcat(buf, "\n");
217         serv_write(buf, strlen(buf));
218 #ifdef SERV_TRACE
219         lprintf(9, "<%s", buf);
220 #endif
221 }