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