~benklop/+junk/lcdproc

« back to all changes in this revision

Viewing changes to shared/sockets.c

  • Committer: Bazaar Package Importer
  • Author(s): Jose Luis Tallon
  • Date: 2006-07-23 20:23:48 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060723202348-w65hrbvpwniqn9by
Tags: 0.5.0-1
* New upstream version (Closes: #367945)
  - New maintainer. Thank you for your previous work, Jon!
  - Upstream added suport for 'imon' devices (Closes: #365496)
  - Upstream fixed descriptor leak (Closes: #355460)
  - Upstream fixed placing widgets in frame (Closes: #355458)

* Packaging
  - Depend on debconf-2.0; Allow transition (Closes: #331885)
  - Remove dependency on automake (Closes: #376449)
  - Include missing INSTALL instructions (Closes: #365436)
  - Changed most "by hand" installation steps into debhelper-based ones
  - Updated to 3.7.2 standards version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "config.h"
1
2
#include <unistd.h>
2
3
#include <stddef.h>
3
4
#include <stdio.h>
4
5
#include <string.h>
5
6
#include <errno.h>
6
7
#include <stdlib.h>
 
8
#include <sys/types.h>
 
9
#ifndef WINSOCK2
7
10
#include <sys/socket.h>
8
11
#include <sys/un.h>
9
 
#include <sys/types.h>
10
12
#include <netinet/in.h>
11
13
#include <netdb.h>
12
14
#include <arpa/inet.h>
 
15
#else
 
16
#include <winsock2.h>
 
17
#endif
 
18
#include <stdarg.h>
13
19
#include <fcntl.h>
14
20
 
15
21
#include "report.h"
27
33
typedef struct sockaddr_in sockaddr_in;
28
34
 
29
35
static int
30
 
sock_init_sockaddr (sockaddr_in * name, const char *hostname, unsigned short int port)
 
36
sock_init_sockaddr (sockaddr_in *name, const char *hostname, unsigned short int port)
31
37
{
32
38
        struct hostent *hostinfo;
33
39
 
34
 
        memset (name, 0, sizeof (*name));
 
40
        memset (name, '\0', sizeof (*name));
35
41
        name->sin_family = AF_INET;
36
42
        name->sin_port = htons (port);
37
43
        hostinfo = gethostbyname (hostname);
55
61
 
56
62
        report (RPT_DEBUG, "sock_connect: Creating socket");
57
63
        sock = socket (PF_INET, SOCK_STREAM, 0);
 
64
#ifdef WINSOCK2        
 
65
        if (sock == INVALID_SOCKET) {
 
66
#else
58
67
        if (sock < 0) {
 
68
#endif
59
69
                report (RPT_ERR, "sock_connect: Error creating socket");
60
70
                return sock;
61
71
        }
62
72
        debug (RPT_DEBUG, "sock_connect: Created socket (%i)", sock);
63
73
 
64
 
        sock_init_sockaddr (&servername, host, port);
 
74
        if (sock_init_sockaddr (&servername, host, port) < 0)
 
75
                return -1;
65
76
 
66
77
        err = connect (sock, (struct sockaddr *) &servername, sizeof (servername));
 
78
#ifdef WINSOCK2        
 
79
        if (err == INVALID_SOCKET) {
 
80
#else
67
81
        if (err < 0) {
 
82
#endif
68
83
                report (RPT_ERR, "sock_connect: connect failed");
69
 
                shutdown (sock, 2);
 
84
                shutdown (sock, SHUT_RDWR);
70
85
                return 0;                                         // Normal exit if server doesn't exist...
71
86
        }
72
87
 
 
88
#ifndef WINSOCK2        
73
89
        fcntl (sock, F_SETFL, O_NONBLOCK);
 
90
#else
 
91
        {
 
92
                unsigned long tmp = 1;
 
93
                
 
94
                if (ioctlsocket(sock, FIONBIO, &tmp) == SOCKET_ERROR)
 
95
                        report(RPT_ERR, "sock_connect: Error setting socket to non-blocking");
 
96
        }
 
97
#endif
74
98
 
75
99
        return sock;
76
100
}
80
104
{
81
105
        int err;
82
106
 
83
 
        err = shutdown (fd, 2);
 
107
        err = shutdown (fd, SHUT_RDWR);
84
108
        if (!err)
85
109
                close (fd);
86
110
 
87
111
        return err;
88
112
}
89
113
 
 
114
 
 
115
/**  send printf-like formatted output */
 
116
int
 
117
sock_printf(int fd, const char *format, .../*args*/ )
 
118
{
 
119
        char buf[MAXMSG];
 
120
        va_list ap;
 
121
        int size = 0;
 
122
 
 
123
        va_start(ap, format);
 
124
        size = vsnprintf(buf, sizeof(buf), format, ap);
 
125
        va_end(ap);
 
126
 
 
127
        if (size < 0) {
 
128
                report(RPT_ERR, "sock_printf: vsnprintf failed");
 
129
                return -1;
 
130
        }
 
131
        if (size > sizeof(buf))
 
132
                report(RPT_WARNING, "sock_printf: vsnprintf truncated message");
 
133
        
 
134
        return sock_send_string(fd, buf);
 
135
}
 
136
 
90
137
// Send/receive lines of text
91
138
int
92
139
sock_send_string (int fd, char *string)
93
140
{
94
 
        int len;
95
 
        int offset = 0;
96
 
 
97
 
        if (!string)
98
 
                return -1;
99
 
 
100
 
        len = strlen (string) ;
101
 
        while (offset != len) {
102
 
                // write isn't guaranteed to send the entire string at once,
103
 
                // so we have to sent it in a loop like this
104
 
                int sent = write (fd, string + offset, len - offset);
105
 
                if (sent == -1) {
106
 
                        if (errno != EAGAIN) {
107
 
                                report (RPT_ERR, "sock_send_string: socket write error");
108
 
                                report (RPT_DEBUG, "Message was: %s", string);
109
 
                                //shutdown(fd, 2);
110
 
                                return sent;
111
 
                        }
112
 
                        continue;
113
 
                } else if (sent == 0) {
114
 
                        // when this returns zero, it generally means
115
 
                        // we got disconnected
116
 
                        return sent + offset;
117
 
                }
118
 
 
119
 
                offset += sent;
120
 
        }
121
 
 
122
 
        return offset;
 
141
        return sock_send(fd, string, strlen(string));
123
142
}
124
143
 
125
144
// Recv gives only one line per call...
127
146
sock_recv_string (int fd, char *dest, size_t maxlen)
128
147
{
129
148
        char *ptr = dest;
130
 
        int recv = 0;
 
149
        int recvBytes = 0;
131
150
 
132
151
        if (!dest)
133
152
                return -1;
135
154
                return 0;
136
155
 
137
156
        while (1) {
 
157
#ifndef WINSOCK2
138
158
                int err = read (fd, ptr, 1);
 
159
#else
 
160
                int err = recv(fd, ptr, 1, 0);
 
161
#endif
139
162
                if (err == -1) {
140
163
                        if (errno == EAGAIN) {
141
 
                                if (recv) {
 
164
                                if (recvBytes) {
142
165
                                        // We've begun to read a string, but no bytes are
143
166
                                        // available.  Loop.
144
167
                                        continue;
149
172
                                return err;
150
173
                        }
151
174
                } else if (err == 0) {
152
 
                        return recv;
 
175
                        return recvBytes;
153
176
                }
154
177
 
155
 
                recv++;
 
178
                recvBytes++;
156
179
 
157
 
                if (recv == maxlen || *ptr == 0 || *ptr == 10) {
158
 
                        *ptr = 0;
 
180
                // stop at max. bytes allowed, at NUL or at LF
 
181
                if (recvBytes == maxlen || *ptr == '\0' || *ptr == '\n') {
 
182
                        *ptr = '\0';
159
183
                        break;
160
184
                }
161
185
                ptr++;
162
186
        }
163
187
 
164
 
        if (recv == 1 && dest[0] == 0) {
165
 
                // Don't return a null string
 
188
        // Don't return an empty string
 
189
        if (recvBytes == 1 && dest[0] == '\0')
166
190
                return 0;
167
 
        }
168
 
 
169
 
        if (recv < maxlen - 1) {
170
 
                dest[recv] = 0;
171
 
        }
172
 
 
173
 
        return recv;
 
191
 
 
192
        if (recvBytes < maxlen - 1)
 
193
                dest[recvBytes] = '\0';
 
194
 
 
195
        return recvBytes;
174
196
}
175
197
 
176
198
// Send/receive raw data
185
207
        while (offset != size) {
186
208
                // write isn't guaranteed to send the entire string at once,
187
209
                // so we have to sent it in a loop like this
188
 
                int sent = write (fd, ((char *) src) + offset, size - offset);
 
210
#ifndef WINSOCK2
 
211
                int sent = write (fd, ((char *) src) + offset, size - offset);
 
212
#else
 
213
                int sent = send(fd, ((char *) src) + offset, size - offset, 0);
 
214
#endif
189
215
                if (sent == -1) {
190
216
                        if (errno != EAGAIN) {
191
217
                                report (RPT_ERR, "sock_send: socket write error");
192
 
                                //shutdown(fd, 2);
 
218
                                report (RPT_DEBUG, "Message was: '%.*s'", size-offset, (char *) src);
 
219
                                //shutdown(fd, SHUT_RDWR);
193
220
                                return sent;
194
221
                        }
195
222
                        continue;
215
242
        if (maxlen <= 0)
216
243
                return 0;
217
244
 
 
245
#ifndef WINSOCK2
218
246
        err = read (fd, dest, maxlen);
 
247
#else
 
248
        err = recv(fd, dest, maxlen, 0);
 
249
#endif
219
250
        if (err < 0) {
220
251
                //report (RPT_DEBUG,"sock_recv: socket read error");
221
 
                //shutdown(fd, 2);
 
252
                //shutdown(fd, SHUT_RDWR);
222
253
                return err;
223
254
        }
224
255
        //debug(RPT_DEBUG, "sock_recv: Got message \"%s\"", (char *)dest);
225
256
 
226
257
        return err;
227
258
}
 
259
 
 
260
/*****************************************************************************/
 
261
 
 
262
char*
 
263
sock_geterror(void)
 
264
{
 
265
#ifndef WINSOCK2
 
266
    return strerror(errno);
 
267
#else
 
268
    static char retString[256];
 
269
    long err;
 
270
    char* tmp;
 
271
 
 
272
    err = WSAGetLastError();
 
273
 
 
274
    sprintf(retString, "Error code %ld: ", err);
 
275
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
 
276
                  FORMAT_MESSAGE_FROM_SYSTEM | 
 
277
                  FORMAT_MESSAGE_IGNORE_INSERTS,
 
278
                  NULL,
 
279
                  err,
 
280
                  0, /* Default language */
 
281
                  (LPTSTR) &tmp,
 
282
                  0,
 
283
                  NULL);
 
284
 
 
285
    /* append the message text after the error code and ensure a terminating
 
286
       character ends the string */
 
287
    strncpy(retString + strlen(retString), tmp, 
 
288
            sizeof(retString) - strlen(retString) - 1);
 
289
    retString[sizeof(retString) - 1] = '\0';
 
290
 
 
291
    return retString;
 
292
#endif
 
293
}
 
294
 
 
295
/** prints error to logfile and sends it to the client.
 
296
 * @param fd socket
 
297
 * @param message the message to send (without the "huh? ") */
 
298
int sock_send_error(int fd, char* message)
 
299
{
 
300
        // simple: performance penalty isn't worth more work...
 
301
        return sock_printf_error(fd, message);
 
302
}
 
303
 
 
304
/** prints printf-like formatted output to logfile and sends it to the
 
305
 * client.
 
306
 * @note don't add a the "huh? " to the message. This is done by this
 
307
 *   method
 
308
 * @param fd socket
 
309
 * @param format a printf format */
 
310
int
 
311
sock_printf_error(int fd, const char *format, .../*args*/ )
 
312
{
 
313
        static const char huh[] = "huh? ";
 
314
        char buf[MAXMSG];
 
315
        va_list ap;
 
316
        int size = 0;
 
317
 
 
318
        strncpy(buf, huh, sizeof(huh)); // note: sizeof(huh) < MAXMSG
 
319
        
 
320
        va_start(ap, format);
 
321
        size = vsnprintf(buf + (sizeof(huh)-1), sizeof(buf) - (sizeof(huh)-1), format, ap);
 
322
        buf[sizeof(buf)-1] = '\0';
 
323
        va_end(ap);
 
324
 
 
325
        if (size < 0) {
 
326
                report(RPT_ERR, "sock_printf_error: vsnprintf failed");
 
327
                return -1;
 
328
        }
 
329
        if (size >= sizeof(buf) - (sizeof(huh)-1))
 
330
                report(RPT_WARNING, "sock_printf_error: vsnprintf truncated message");
 
331
 
 
332
        report(RPT_ERR, "error: %s", buf);
 
333
        return sock_send_string(fd, buf);
 
334
}