Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 423 lines (375 sloc) 11.294 kb
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
1 /* osos2/osnet.c */
2
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
3 /*
4 * This is basically identical to the win32 version, adapted for OS/2 by
5 * Herbert
6 *
7 * $Log: osnet.c,v $
2fe6e17 Martin Dietze Import Elvis 2.2_1 (written by Steve Kirkendall)
authored
8 * Revision 1.6 2003/10/23 23:35:45 steve
9 * Herbert's latest changes.
10 *
11 * Revision 1.5 2003/10/17 17:41:23 steve
12 * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with
13 * types defined other headers.
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
14 *
15 * Revision 1.4 2003/10/12 18:36:18 steve
16 * Changed elvis' ctype macro names to start with "elv"
17 *
18 * Revision 1.3 2001/10/22 17:51:47 steve
19 * Added RCS Id strings to some files which lacked them.
20 *
21 * Revision 1.2 2001/04/20 00:00:37 steve
22 * Some bug fixes, and uglification of the source code.
23 *
24 * Revision 1.2 2000/06/04 10:26:54 HERBERT
25 * Some formatting and CVS Logging.
26 *
27 *
28 */
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
29
30 /* This function contains functions for accessing the internet. These are
31 * all protocol-independent, but (to some degree) OS-dependent. Specifically,
32 * the following functions are defined:
33 *
34 * sockbuf_t *netconnect(char *site_port, unsigned int defport);
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
35 * Open a socket connection to a specific port on a specific site.
36 * site_port is a host name or numbers-and-dots address, optionally
37 * followed by a port number. defport is the port number to use if
38 * site_port contains no port number.
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
39 *
40 * void netdisconnect(sockbuf_t *sb);
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
41 * Close a socket connection which was created via netconnect()
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
42 *
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
43 * ELVBOOL netread(sockbuf_t *sb);
44 * Read bytes from sb's socket. Returns ElvTrue if successful (even if
45 * no data has been read, at the end of input), or ElvFalse if error or
46 * user-abort (after giving an error message).
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
47 *
48 * char *netgetline(sockbuf_t *sb);
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
49 * Fetch the next line of text from a socket, and return it.
50 * Returns NULL if error or user-abort.
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
51 *
52 * char *netbuffer(sockbuf_t *sb);
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
53 * Return a pointer to the next byte in sb's read-buffer.
54 * (This is actually a macro, defined in osnet.h.)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
55 *
56 * int netbytes(sockbuf_t *sb);
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
57 * Return the number of bytes in sb's read-buffer.
58 * (This is actually a macro, defined in osnet.h.)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
59 *
60 * void netconsume(sockbuf_t *sb, int len);
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
61 * Consume len bytes from sb's read-buffer.
62 * (This is actually a macro, defined in osnet.h)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
63 *
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
64 * ELVBOOL netwrite(sockbuf_t *sb, char *text, int bytes);
65 * Write data to sb's socket. Returns ElvTrue iff successful.
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
66 *
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
67 * ELVBOOL netputline(sockbuf_t *sb, char *text);
68 * Write a line to sb's socket. text is a NUL-terminated line;
69 * netlinewrite() adds a CR-LF pair itself.
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
70 *
71 * char *netself(void)
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
72 * Return the name of the local system.
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
73 */
74
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
75 char id_osnet[] = "$Id";
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
76 #include "elvis.h"
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
77
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
78 #if defined(PROTOCOL_HTTP) || defined(PROTOCOL_FTP)
79 # ifdef __IBMC__
80 # define BSD_SELECT
81 # include <types.h>
82 # endif
2fe6e17 Martin Dietze Import Elvis 2.2_1 (written by Steve Kirkendall)
authored
83 # ifdef __WATCOMC__
84 # define BSD_SELECT
85 typedef long off_t;
86 #include <sys/time.h>
87 #include <utils.h>
88 # endif
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
89 # ifdef __EMX__
90 # include <sys/types.h>
91 # include <sys/time.h>
92 # endif
93 # include <sys/socket.h>
94 # include <netdb.h>
95 # ifdef __EMX__
96 # include <io.h>
97 # include <netinet/in.h>
98 # endif
99 # include <sys/select.h>
100 # ifdef __IBMC__
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
101 # define close(s) soclose(s)
102 # define read(s,p,n) recv(s, p, n, 0)
103 # define write(s,p,n) send(s, p, n, 0)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
104 # endif
105
106 # if USE_PROTOTYPES
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
107 static ELVBOOL site2addr (char *site, struct in_addr *address);
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
108 # endif
109
110
97d8998 Martin Dietze Import Elvis 2.1_4 (written by Steve Kirkendall)
authored
111 #ifndef __EMX__
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
112 static ELVBOOL initialized;
97d8998 Martin Dietze Import Elvis 2.1_4 (written by Steve Kirkendall)
authored
113 #endif
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
114
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
115 static int
116 inet_aton (char *site, struct in_addr *addr)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
117 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
118 int a0,a1,a2,a3;
119
120 if (sscanf (site, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
121 {
122 return 0;
123 }
124 ((char *)&addr->s_addr)[0] = a0;
125 ((char *)&addr->s_addr)[1] = a1;
126 ((char *)&addr->s_addr)[2] = a2;
127 ((char *)&addr->s_addr)[3] = a3;
128 return 1;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
129 }
130
131 /* Find the address of a site. The site can be given as either a domain name,
132 * or a "numbers and dots" name. If successful, the address is stuffed into
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
133 * address struct, and ElvTrue is returned; otherwise ElvFalse is returned.
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
134 */
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
135 static ELVBOOL
136 site2addr(char *site, struct in_addr *address)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
137 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
138 struct hostent *siteinfo;
139 static char prevsite[100];
140 static struct in_addr prevaddr;
141
142
143 /* if the site name starts with a digit, then assume it is in the
144 * "numbers and dots" format.
145 */
146 if (elvdigit(site[0]))
147 {
148 /* convert to binary address */
149 if (!inet_aton(site, address))
150 {
151 goto Error;
152 }
153 }
154 else
155 {
156 /* if same name as last time, then just use the same address */
157 if (strlen(site) < QTY(prevsite) && !strcmp(prevsite, site))
158 {
159 *address = prevaddr;
160 return ElvTrue;
161 }
162
163 /* look up the name */
164 msg(MSG_STATUS, "[s]looking up site $1", site); /* !!!*/
165 siteinfo = gethostbyname(site);
166 if (!siteinfo)
167 {
168 goto Error;
169 }
170
171 /* use the primary address */
172 memcpy(address, siteinfo->h_addr_list[0], siteinfo->h_length);
173
174 /* save the info about this site */
175 strncpy(prevsite, site, sizeof prevsite);
176 prevaddr = *address;
177 }
178
179 return ElvTrue;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
180
181 Error:
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
182 msg(MSG_ERROR, "[s]unknown site $1", site);
183 return ElvFalse;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
184 }
185
186 /* Open a connection to a given site and port.
187 * Returns a sockbuf_t pointer if successful, or NULL for errors (in which
188 * case it also gives an error message).
189 */
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
190 sockbuf_t * /* name of remote system, with optional port number */
191 netconnect (char *site_port, unsigned int defport)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
192 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
193 struct in_addr serverAddress;
194 struct sockaddr_in destPort;
195 char *tmp;
196 char buf[150];
197 sockbuf_t *sb;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
198
97d8998 Martin Dietze Import Elvis 2.1_4 (written by Steve Kirkendall)
authored
199 #ifndef __EMX__
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
200 /* If first time, then initialize OS/2 sockets */
201 if (!initialized)
202 {
203 (void)sock_init ();
204 initialized = ElvTrue;
205 }
97d8998 Martin Dietze Import Elvis 2.1_4 (written by Steve Kirkendall)
authored
206 #endif
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
207
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
208 /* if site_port contains a port number, then separate it from the site
209 * name, and use the given port instead of the default port.
210 */
211 strcpy (buf, site_port);
212 tmp = strchr (buf, ':');
213 if (tmp)
214 {
215 *tmp++ = '\0';
216 defport = atoi (tmp);
217 }
218
219 /* look up the address of the server */
220 if (!site2addr (buf, &serverAddress))
221 {
222 return NULL;
223 }
224
225 /* The remainder of this function connects to the server */
226 msg (MSG_STATUS, "[s]connecting to $1", buf);
227
228 /* create a socket, and a sockbuf_t to buffer it */
229 sb = safealloc(1, sizeof(sockbuf_t));
230 sb->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
231 if (sb->fd < 0)
232 {
233 safefree(sb);
234 return NULL;
235 }
236
237 /* connect the socket to the remote machine */
238 destPort.sin_family = AF_INET;
239 destPort.sin_port = htons((unsigned short)defport);
240 destPort.sin_addr = serverAddress;
241 if (connect(sb->fd, (struct sockaddr *)&destPort, sizeof(destPort)))
242 {
243 netdisconnect(sb);
244 return NULL;
245 }
246
247 return sb;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
248 }
249
250
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
251 void
252 netdisconnect (sockbuf_t *sb) /* buffered socket to be freed */
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
253 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
254 close(sb->fd);
255 safefree(sb);
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
256 }
257
258
259 /* Read as much data as possible from a socket, with a timeout. Returns True
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
260 * if successful, or ElvFalse if there was an error or the user aborted; in the
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
261 * latter cases, an error message is given.
262 */
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
263 ELVBOOL
264 netread (sockbuf_t *sb)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
265 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
266 int i;
267 int gotfds;
268 fd_set rfds;
269 struct timeval timeout;
270
271 /* Wait for data, checking periodically for a user abort. */
272 do
273 {
274 /* try to read for up to 2 seconds */
275 FD_ZERO (&rfds);
276 FD_SET (sb->fd, &rfds);
277 timeout.tv_sec = 2;
278 timeout.tv_usec = 0;
279 gotfds = select (sb->fd + 1, &rfds, NULL, NULL, &timeout);
280 if (gotfds < 0 || guipoll(ElvFalse))
281 {
282 return ElvFalse;
283 }
284 }
285 while (gotfds == 0);
286
287 /* remove any consumed text from the buffer */
288 if (sb->left > 0 && sb->right > sb->left)
289 {
290 /* regions may overlap -- it is guaranteed to work */
291 memmove(sb->buf, &sb->buf[sb->left], sb->right - sb->left);
292 }
293 sb->right -= sb->left;
294 sb->left = 0;
295
296 /* Read as much data as is available */
297 i = read(sb->fd, &sb->buf[sb->right], sizeof sb->buf - sb->right);
298 if (i < 0)
299 {
300 i = read(sb->fd, &sb->buf[sb->right], sizeof sb->buf - sb->right);
301 }
302 if (i < 0)
303 {
304 msg(MSG_ERROR, "error reading from socket");
305 return ElvFalse;
306 }
307 sb->right += i;
308
309 /* return the number of bytes available */
310 return ElvTrue;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
311 }
312
313
314 /* Read a line from a socket. Return the line if successful, NULL if error. */
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
315 char *
316 netgetline(sockbuf_t *sb)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
317 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
318 int i;
319 char *ret;
320
321 /* loop until something interesting happens */
322 for (;;)
323 {
324 /* see if we have a whole line now */
325 for (ret = netbuffer(sb), i = sb->left; i < sb->right; i++)
326 {
327 if (sb->buf[i] == '\n')
328 {
329 /* found end-of-line! Mark it & return. */
330 sb->buf[i] = '\0';
331 if (i >= 1 && sb->buf[i - 1] == '\r')
332 {
333 sb->buf[i - 1] = '\0';
334 }
335 sb->left = i + 1;
336 return ret;
337 }
338 }
339
340 /* read some more data */
341 i = netbytes(sb);
342 if (!netread(sb) || i == netbytes(sb))
343 {
344 return NULL;
345 }
346 }
347 /*NOTREACHED*/
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
348 }
349
350
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
351 /* Send data bytes through a socket. Returns ElvTrue if successful, or ElvFalse if
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
352 * error (after giving an error message).
353 */
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
354 ELVBOOL
355 netwrite(sockbuf_t *sb, char *data, int len)
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
356 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
357 if (write(sb->fd, data, len) == len)
358 {
359 return ElvTrue;
360 }
361 msg(MSG_ERROR, "transmission failed");
362 return ElvFalse;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
363 }
364
97d8998 Martin Dietze Import Elvis 2.1_4 (written by Steve Kirkendall)
authored
365
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
366 /* Send a line through a socket. This intended to be used for sending commands
367 * to an FTP or HTTP server. The line should be a normal NUL-terminated string
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
368 * with no newline; this function appends a CRLF. Returns ElvTrue if successful,
369 * or ElvFalse if error (after giving an error message).
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
370 */
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
371 ELVBOOL
372 netputline(sockbuf_t *sb, /* stream to write to */
373 char *command, /* command name */
374 char *arg1, char *arg2)/* arguments, may be NULL if not used */
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
375 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
376 int len;
377 char *buf;
378
379 /* combine the command and arg into one string */
380 if (arg2)
381 {
382 len = strlen(command) + strlen(arg1) + strlen(arg2) + 5;
383 buf = safealloc(len, sizeof(char));
384 sprintf(buf, "%s %s %s\r\n", command, arg1, arg2);
385 }
386 else if (arg1)
387 {
388 len = strlen(command) + strlen(arg1) + 4;
389 buf = safealloc(len, sizeof(char));
390 sprintf(buf, "%s %s\r\n", command, arg1);
391 }
392 else
393 {
394 len = strlen(command) + 3;
395 buf = safealloc(len, sizeof(char));
396 sprintf(buf, "%s\r\n", command);
397 }
398 len--; /* <-- so the NUL terminator isn't sent */
399
400 /* send the command to the server */
401 if (write(sb->fd, buf, len) != len && *command)
402 {
403 msg(MSG_ERROR, "could not send request to server");
404 safefree(buf);
405 return ElvFalse;
406 }
407 safefree(buf);
408 return ElvTrue;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
409 }
410
97d8998 Martin Dietze Import Elvis 2.1_4 (written by Steve Kirkendall)
authored
411
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
412 char *
413 netself P_((void))
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
414 {
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
415 static char name[50];
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
416
9f1c6f0 Martin Dietze Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
417 if (gethostname(name, sizeof(name)))
418 strcpy(name, "graceland");
419 return name;
8d1ac0c Martin Dietze Import Elvis 2.1 (written by Steve Kirkendall)
authored
420 }
421
422 #endif /* PROTOCOL_HTTP || PROTOCOL_FTP */
Something went wrong with that request. Please try again.