rev |
line source |
yuuji@0
|
1 /* ========================================================================
|
yuuji@0
|
2 * Copyright 1988-2008 University of Washington
|
yuuji@0
|
3 *
|
yuuji@0
|
4 * Licensed under the Apache License, Version 2.0 (the "License");
|
yuuji@0
|
5 * you may not use this file except in compliance with the License.
|
yuuji@0
|
6 * You may obtain a copy of the License at
|
yuuji@0
|
7 *
|
yuuji@0
|
8 * http://www.apache.org/licenses/LICENSE-2.0
|
yuuji@0
|
9 *
|
yuuji@0
|
10 *
|
yuuji@0
|
11 * ========================================================================
|
yuuji@0
|
12 */
|
yuuji@0
|
13
|
yuuji@0
|
14 /*
|
yuuji@0
|
15 * Program: MS-DOS TCP/IP routines
|
yuuji@0
|
16 *
|
yuuji@0
|
17 * Author: Mark Crispin
|
yuuji@0
|
18 * Networks and Distributed Computing
|
yuuji@0
|
19 * Computing & Communications
|
yuuji@0
|
20 * University of Washington
|
yuuji@0
|
21 * Administration Building, AG-44
|
yuuji@0
|
22 * Seattle, WA 98195
|
yuuji@0
|
23 * Internet: MRC@CAC.Washington.EDU
|
yuuji@0
|
24 *
|
yuuji@0
|
25 * Date: 11 April 1989
|
yuuji@0
|
26 * Last Edited: 13 January 2008
|
yuuji@0
|
27 */
|
yuuji@0
|
28
|
yuuji@0
|
29 static tcptimeout_t tmoh = NIL; /* TCP timeout handler routine */
|
yuuji@0
|
30 static long ttmo_read = 0; /* TCP timeouts, in seconds */
|
yuuji@0
|
31 static long ttmo_write = 0;
|
yuuji@0
|
32
|
yuuji@0
|
33 static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size,
|
yuuji@0
|
34 long *contd);
|
yuuji@0
|
35
|
yuuji@0
|
36 /* TCP/IP manipulate parameters
|
yuuji@0
|
37 * Accepts: function code
|
yuuji@0
|
38 * function-dependent value
|
yuuji@0
|
39 * Returns: function-dependent return value
|
yuuji@0
|
40 */
|
yuuji@0
|
41
|
yuuji@0
|
42 void *tcp_parameters (long function,void *value)
|
yuuji@0
|
43 {
|
yuuji@0
|
44 void *ret = NIL;
|
yuuji@0
|
45 switch ((int) function) {
|
yuuji@0
|
46 case SET_TIMEOUT:
|
yuuji@0
|
47 tmoh = (tcptimeout_t) value;
|
yuuji@0
|
48 case GET_TIMEOUT:
|
yuuji@0
|
49 ret = (void *) tmoh;
|
yuuji@0
|
50 break;
|
yuuji@0
|
51 case SET_READTIMEOUT:
|
yuuji@0
|
52 ttmo_read = (long) value;
|
yuuji@0
|
53 case GET_READTIMEOUT:
|
yuuji@0
|
54 ret = (void *) ttmo_read;
|
yuuji@0
|
55 break;
|
yuuji@0
|
56 case SET_WRITETIMEOUT:
|
yuuji@0
|
57 ttmo_write = (long) value;
|
yuuji@0
|
58 case GET_WRITETIMEOUT:
|
yuuji@0
|
59 ret = (void *) ttmo_write;
|
yuuji@0
|
60 break;
|
yuuji@0
|
61 }
|
yuuji@0
|
62 return ret;
|
yuuji@0
|
63 }
|
yuuji@0
|
64
|
yuuji@0
|
65 /* TCP/IP open
|
yuuji@0
|
66 * Accepts: host name
|
yuuji@0
|
67 * contact service name
|
yuuji@0
|
68 * contact port number
|
yuuji@0
|
69 * Returns: TCP/IP stream if success else NIL
|
yuuji@0
|
70 */
|
yuuji@0
|
71
|
yuuji@0
|
72 TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
|
yuuji@0
|
73 {
|
yuuji@0
|
74 TCPSTREAM *stream = NIL;
|
yuuji@0
|
75 struct sockaddr_in sin;
|
yuuji@0
|
76 int sock;
|
yuuji@0
|
77 char *s,tmp[MAILTMPLEN];
|
yuuji@0
|
78 port &= 0xffff; /* erase flags */
|
yuuji@0
|
79 /* The domain literal form is used (rather than simply the dotted decimal
|
yuuji@0
|
80 as with other Unix programs) because it has to be a valid "host name"
|
yuuji@0
|
81 in mailsystem terminology. */
|
yuuji@0
|
82 sin.sin_family = AF_INET; /* family is always Internet */
|
yuuji@0
|
83 /* look like domain literal? */
|
yuuji@0
|
84 if (host[0] == '[' && host[(strlen (host))-1] == ']') {
|
yuuji@0
|
85 strcpy (tmp,host+1); /* yes, copy number part */
|
yuuji@0
|
86 tmp[strlen (tmp)-1] = '\0';
|
yuuji@0
|
87 if ((sin.sin_addr.s_addr = inet_addr (tmp)) == -1) {
|
yuuji@0
|
88 sprintf (tmp,"Bad format domain-literal: %.80s",host);
|
yuuji@0
|
89 mm_log (tmp,ERROR);
|
yuuji@0
|
90 return NIL;
|
yuuji@0
|
91 }
|
yuuji@0
|
92 }
|
yuuji@0
|
93 /* look up host name */
|
yuuji@0
|
94 else if (!lookuphost (&host,&sin)) {
|
yuuji@0
|
95 sprintf (tmp,"Host not found: %s",host);
|
yuuji@0
|
96 mm_log (tmp,ERROR);
|
yuuji@0
|
97 return NIL;
|
yuuji@0
|
98 }
|
yuuji@0
|
99
|
yuuji@0
|
100 /* copy port number in network format */
|
yuuji@0
|
101 if (!(sin.sin_port = htons (port))) fatal ("Bad port argument to tcp_open");
|
yuuji@0
|
102 /* get a TCP stream */
|
yuuji@0
|
103 if ((sock = socket (sin.sin_family,SOCK_STREAM,0)) < 0) {
|
yuuji@0
|
104 sprintf (tmp,"Unable to create TCP socket (%d)",errno);
|
yuuji@0
|
105 mm_log (tmp,ERROR);
|
yuuji@0
|
106 fs_give ((void **) &host);
|
yuuji@0
|
107 return NIL;
|
yuuji@0
|
108 }
|
yuuji@0
|
109 #if 0
|
yuuji@0
|
110 /* needed? */
|
yuuji@0
|
111 else if (sock >= FD_SETSIZE) {/* unselectable sockets are useless */
|
yuuji@0
|
112 sprintf (tmp,"Unable to create selectable TCP socket (%d >= %d)",
|
yuuji@0
|
113 sock,FD_SETSIZE);
|
yuuji@0
|
114 close (sock);
|
yuuji@0
|
115 errno = ENOBUFS; /* just in case */
|
yuuji@0
|
116 return NIL;
|
yuuji@0
|
117 }
|
yuuji@0
|
118 #endif
|
yuuji@0
|
119 /* open connection */
|
yuuji@0
|
120 if (connect (sock,(struct sockaddr *) &sin,sizeof (sin)) < 0) {
|
yuuji@0
|
121 switch (errno) { /* analyze error */
|
yuuji@0
|
122 case ECONNREFUSED:
|
yuuji@0
|
123 s = "Refused";
|
yuuji@0
|
124 break;
|
yuuji@0
|
125 case ENOBUFS:
|
yuuji@0
|
126 s = "Insufficient system resources";
|
yuuji@0
|
127 break;
|
yuuji@0
|
128 case ETIMEDOUT:
|
yuuji@0
|
129 s = "Timed out";
|
yuuji@0
|
130 break;
|
yuuji@0
|
131 default:
|
yuuji@0
|
132 s = "Unknown error";
|
yuuji@0
|
133 break;
|
yuuji@0
|
134 }
|
yuuji@0
|
135 sprintf (tmp,"Can't connect to %.80s,%ld: %s (%d)",host,port,s,errno);
|
yuuji@0
|
136 mm_log (tmp,ERROR);
|
yuuji@0
|
137 close (sock);
|
yuuji@0
|
138 fs_give ((void **) &host);
|
yuuji@0
|
139 return NIL;
|
yuuji@0
|
140 }
|
yuuji@0
|
141 /* create TCP/IP stream */
|
yuuji@0
|
142 stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM));
|
yuuji@0
|
143 stream->host = host; /* official host name */
|
yuuji@0
|
144 stream->localhost = cpystr (mylocalhost ());
|
yuuji@0
|
145 stream->port = port; /* port number */
|
yuuji@0
|
146 stream->tcps = sock; /* init socket */
|
yuuji@0
|
147 stream->ictr = 0; /* init input counter */
|
yuuji@0
|
148 return stream; /* return success */
|
yuuji@0
|
149 }
|
yuuji@0
|
150
|
yuuji@0
|
151 /* TCP/IP authenticated open
|
yuuji@0
|
152 * Accepts: NETMBX specifier
|
yuuji@0
|
153 * service name
|
yuuji@0
|
154 * returned user name buffer
|
yuuji@0
|
155 * Returns: TCP/IP stream if success else NIL
|
yuuji@0
|
156 */
|
yuuji@0
|
157
|
yuuji@0
|
158 TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf)
|
yuuji@0
|
159 {
|
yuuji@0
|
160 return NIL; /* always NIL on DOS */
|
yuuji@0
|
161 }
|
yuuji@0
|
162
|
yuuji@0
|
163 /* TCP receive line
|
yuuji@0
|
164 * Accepts: TCP stream
|
yuuji@0
|
165 * Returns: text line string or NIL if failure
|
yuuji@0
|
166 */
|
yuuji@0
|
167
|
yuuji@0
|
168 char *tcp_getline (TCPSTREAM *stream)
|
yuuji@0
|
169 {
|
yuuji@0
|
170 unsigned long n,contd;
|
yuuji@0
|
171 char *ret = tcp_getline_work (stream,&n,&contd);
|
yuuji@0
|
172 if (ret && contd) { /* got a line needing continuation? */
|
yuuji@0
|
173 STRINGLIST *stl = mail_newstringlist ();
|
yuuji@0
|
174 STRINGLIST *stc = stl;
|
yuuji@0
|
175 do { /* collect additional lines */
|
yuuji@0
|
176 stc->text.data = (unsigned char *) ret;
|
yuuji@0
|
177 stc->text.size = n;
|
yuuji@0
|
178 stc = stc->next = mail_newstringlist ();
|
yuuji@0
|
179 ret = tcp_getline_work (stream,&n,&contd);
|
yuuji@0
|
180 } while (ret && contd);
|
yuuji@0
|
181 if (ret) { /* stash final part of line on list */
|
yuuji@0
|
182 stc->text.data = (unsigned char *) ret;
|
yuuji@0
|
183 stc->text.size = n;
|
yuuji@0
|
184 /* determine how large a buffer we need */
|
yuuji@0
|
185 for (n = 0, stc = stl; stc; stc = stc->next) n += stc->text.size;
|
yuuji@0
|
186 ret = fs_get (n + 1); /* copy parts into buffer */
|
yuuji@0
|
187 for (n = 0, stc = stl; stc; n += stc->text.size, stc = stc->next)
|
yuuji@0
|
188 memcpy (ret + n,stc->text.data,stc->text.size);
|
yuuji@0
|
189 ret[n] = '\0';
|
yuuji@0
|
190 }
|
yuuji@0
|
191 mail_free_stringlist (&stl);/* either way, done with list */
|
yuuji@0
|
192 }
|
yuuji@0
|
193 return ret;
|
yuuji@0
|
194 }
|
yuuji@0
|
195
|
yuuji@0
|
196 /* TCP receive line or partial line
|
yuuji@0
|
197 * Accepts: TCP stream
|
yuuji@0
|
198 * pointer to return size
|
yuuji@0
|
199 * pointer to return continuation flag
|
yuuji@0
|
200 * Returns: text line string, size and continuation flag, or NIL if failure
|
yuuji@0
|
201 */
|
yuuji@0
|
202
|
yuuji@0
|
203 static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size,
|
yuuji@0
|
204 long *contd)
|
yuuji@0
|
205 {
|
yuuji@0
|
206 unsigned long n;
|
yuuji@0
|
207 char *s,*ret,c,d;
|
yuuji@0
|
208 *contd = NIL; /* assume no continuation */
|
yuuji@0
|
209 /* make sure have data */
|
yuuji@0
|
210 if (!tcp_getdata (stream)) return NIL;
|
yuuji@0
|
211 for (s = stream->iptr, n = 0, c = '\0'; stream->ictr--; n++, c = d) {
|
yuuji@0
|
212 d = *stream->iptr++; /* slurp another character */
|
yuuji@0
|
213 if ((c == '\015') && (d == '\012')) {
|
yuuji@0
|
214 ret = (char *) fs_get (n--);
|
yuuji@0
|
215 memcpy (ret,s,*size = n); /* copy into a free storage string */
|
yuuji@0
|
216 ret[n] = '\0'; /* tie off string with null */
|
yuuji@0
|
217 return ret;
|
yuuji@0
|
218 }
|
yuuji@0
|
219 }
|
yuuji@0
|
220 /* copy partial string from buffer */
|
yuuji@0
|
221 memcpy ((ret = (char *) fs_get (n)),s,*size = n);
|
yuuji@0
|
222 /* get more data from the net */
|
yuuji@0
|
223 if (!tcp_getdata (stream)) fs_give ((void **) &ret);
|
yuuji@0
|
224 /* special case of newline broken by buffer */
|
yuuji@0
|
225 else if ((c == '\015') && (*stream->iptr == '\012')) {
|
yuuji@0
|
226 stream->iptr++; /* eat the line feed */
|
yuuji@0
|
227 stream->ictr--;
|
yuuji@0
|
228 ret[*size = --n] = '\0'; /* tie off string with null */
|
yuuji@0
|
229 }
|
yuuji@0
|
230 else *contd = LONGT; /* continuation needed */
|
yuuji@0
|
231 return ret;
|
yuuji@0
|
232 }
|
yuuji@0
|
233
|
yuuji@0
|
234 /* TCP/IP receive buffer
|
yuuji@0
|
235 * Accepts: TCP/IP stream
|
yuuji@0
|
236 * size in bytes
|
yuuji@0
|
237 * buffer to read into
|
yuuji@0
|
238 * Returns: T if success, NIL otherwise
|
yuuji@0
|
239 */
|
yuuji@0
|
240
|
yuuji@0
|
241 long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer)
|
yuuji@0
|
242 {
|
yuuji@0
|
243 unsigned long n;
|
yuuji@0
|
244 char *bufptr = buffer;
|
yuuji@0
|
245 while (size > 0) { /* until request satisfied */
|
yuuji@0
|
246 if (!tcp_getdata (stream)) return NIL;
|
yuuji@0
|
247 n = min (size,stream->ictr);/* number of bytes to transfer */
|
yuuji@0
|
248 /* do the copy */
|
yuuji@0
|
249 memcpy (bufptr,stream->iptr,n);
|
yuuji@0
|
250 bufptr += n; /* update pointer */
|
yuuji@0
|
251 stream->iptr +=n;
|
yuuji@0
|
252 size -= n; /* update # of bytes to do */
|
yuuji@0
|
253 stream->ictr -=n;
|
yuuji@0
|
254 }
|
yuuji@0
|
255 bufptr[0] = '\0'; /* tie off string */
|
yuuji@0
|
256 return T;
|
yuuji@0
|
257 }
|
yuuji@0
|
258
|
yuuji@0
|
259 /* TCP/IP receive data
|
yuuji@0
|
260 * Accepts: TCP/IP stream
|
yuuji@0
|
261 * Returns: T if success, NIL otherwise
|
yuuji@0
|
262 */
|
yuuji@0
|
263
|
yuuji@0
|
264 long tcp_getdata (TCPSTREAM *stream)
|
yuuji@0
|
265 {
|
yuuji@0
|
266 int i;
|
yuuji@0
|
267 fd_set fds,efds;
|
yuuji@0
|
268 struct timeval tmo;
|
yuuji@0
|
269 time_t t = time (0);
|
yuuji@0
|
270 if (stream->tcps < 0) return NIL;
|
yuuji@0
|
271 while (stream->ictr < 1) { /* if nothing in the buffer */
|
yuuji@0
|
272 time_t tl = time (0); /* start of request */
|
yuuji@0
|
273 tmo.tv_sec = ttmo_read; /* read timeout */
|
yuuji@0
|
274 tmo.tv_usec = 0;
|
yuuji@0
|
275 FD_ZERO (&fds); /* initialize selection vector */
|
yuuji@0
|
276 FD_ZERO (&efds); /* handle errors too */
|
yuuji@0
|
277 FD_SET (stream->tcps,&fds);/* set bit in selection vector */
|
yuuji@0
|
278 FD_SET(stream->tcps,&efds);/* set bit in error selection vector */
|
yuuji@0
|
279 errno = NIL; /* block and read */
|
yuuji@0
|
280 while (((i = select (stream->tcps+1,&fds,0,&efds,ttmo_read ? &tmo : 0))<0)
|
yuuji@0
|
281 && (errno == EINTR));
|
yuuji@0
|
282 if (!i) { /* timeout? */
|
yuuji@0
|
283 time_t tc = time (0);
|
yuuji@0
|
284 if (tmoh && ((*tmoh) (tc - t,tc - tl))) continue;
|
yuuji@0
|
285 else return tcp_abort (stream);
|
yuuji@0
|
286 }
|
yuuji@0
|
287 else if (i < 0) return tcp_abort (stream);
|
yuuji@0
|
288 while (((i = read (stream->tcps,stream->ibuf,BUFLEN)) < 0) &&
|
yuuji@0
|
289 (errno == EINTR));
|
yuuji@0
|
290 if (i < 1) return tcp_abort (stream);
|
yuuji@0
|
291 stream->iptr = stream->ibuf;/* point at TCP buffer */
|
yuuji@0
|
292 stream->ictr = i; /* set new byte count */
|
yuuji@0
|
293 }
|
yuuji@0
|
294 return T;
|
yuuji@0
|
295 }
|
yuuji@0
|
296
|
yuuji@0
|
297 /* TCP/IP send string as record
|
yuuji@0
|
298 * Accepts: TCP/IP stream
|
yuuji@0
|
299 * string pointer
|
yuuji@0
|
300 * Returns: T if success else NIL
|
yuuji@0
|
301 */
|
yuuji@0
|
302
|
yuuji@0
|
303 long tcp_soutr (TCPSTREAM *stream,char *string)
|
yuuji@0
|
304 {
|
yuuji@0
|
305 return tcp_sout (stream,string,(unsigned long) strlen (string));
|
yuuji@0
|
306 }
|
yuuji@0
|
307
|
yuuji@0
|
308
|
yuuji@0
|
309 /* TCP/IP send string
|
yuuji@0
|
310 * Accepts: TCP/IP stream
|
yuuji@0
|
311 * string pointer
|
yuuji@0
|
312 * byte count
|
yuuji@0
|
313 * Returns: T if success else NIL
|
yuuji@0
|
314 */
|
yuuji@0
|
315
|
yuuji@0
|
316 long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size)
|
yuuji@0
|
317 {
|
yuuji@0
|
318 int i;
|
yuuji@0
|
319 fd_set fds;
|
yuuji@0
|
320 struct timeval tmo;
|
yuuji@0
|
321 time_t t = time (0);
|
yuuji@0
|
322 if (stream->tcps < 0) return NIL;
|
yuuji@0
|
323 while (size > 0) { /* until request satisfied */
|
yuuji@0
|
324 time_t tl = time (0); /* start of request */
|
yuuji@0
|
325 tmo.tv_sec = ttmo_write; /* write timeout */
|
yuuji@0
|
326 tmo.tv_usec = 0;
|
yuuji@0
|
327 FD_ZERO (&fds); /* initialize selection vector */
|
yuuji@0
|
328 FD_SET (stream->tcps,&fds);/* set bit in selection vector */
|
yuuji@0
|
329 errno = NIL; /* block and write */
|
yuuji@0
|
330 while (((i = select (stream->tcps+1,0,&fds,0,ttmo_write ? &tmo : 0)) < 0)
|
yuuji@0
|
331 && (errno == EINTR));
|
yuuji@0
|
332 if (!i) { /* timeout? */
|
yuuji@0
|
333 time_t tc = time (0);
|
yuuji@0
|
334 if (tmoh && ((*tmoh) (tc - t,tc - tl))) continue;
|
yuuji@0
|
335 else return tcp_abort (stream);
|
yuuji@0
|
336 }
|
yuuji@0
|
337 else if (i < 0) return tcp_abort (stream);
|
yuuji@0
|
338 while (((i = write (stream->tcps,string,size)) < 0) && (errno == EINTR));
|
yuuji@0
|
339 if (i < 0) return tcp_abort (stream);
|
yuuji@0
|
340 size -= i; /* how much we sent */
|
yuuji@0
|
341 string += i;
|
yuuji@0
|
342 }
|
yuuji@0
|
343 return T; /* all done */
|
yuuji@0
|
344 }
|
yuuji@0
|
345
|
yuuji@0
|
346 /* TCP/IP close
|
yuuji@0
|
347 * Accepts: TCP/IP stream
|
yuuji@0
|
348 */
|
yuuji@0
|
349
|
yuuji@0
|
350 void tcp_close (TCPSTREAM *stream)
|
yuuji@0
|
351 {
|
yuuji@0
|
352 tcp_abort (stream); /* nuke the socket */
|
yuuji@0
|
353 /* flush host names */
|
yuuji@0
|
354 fs_give ((void **) &stream->host);
|
yuuji@0
|
355 fs_give ((void **) &stream->localhost);
|
yuuji@0
|
356 fs_give ((void **) &stream); /* flush the stream */
|
yuuji@0
|
357 }
|
yuuji@0
|
358
|
yuuji@0
|
359
|
yuuji@0
|
360 /* TCP/IP abort stream
|
yuuji@0
|
361 * Accepts: TCP/IP stream
|
yuuji@0
|
362 * Returns: NIL always
|
yuuji@0
|
363 */
|
yuuji@0
|
364
|
yuuji@0
|
365 long tcp_abort (TCPSTREAM *stream)
|
yuuji@0
|
366 {
|
yuuji@0
|
367 if (stream->tcps >= 0) close (stream->tcps);
|
yuuji@0
|
368 stream->tcps = -1;
|
yuuji@0
|
369 return NIL;
|
yuuji@0
|
370 }
|
yuuji@0
|
371
|
yuuji@0
|
372 /* TCP/IP get host name
|
yuuji@0
|
373 * Accepts: TCP/IP stream
|
yuuji@0
|
374 * Returns: host name for this stream
|
yuuji@0
|
375 */
|
yuuji@0
|
376
|
yuuji@0
|
377 char *tcp_host (TCPSTREAM *stream)
|
yuuji@0
|
378 {
|
yuuji@0
|
379 return stream->host; /* return host name */
|
yuuji@0
|
380 }
|
yuuji@0
|
381
|
yuuji@0
|
382
|
yuuji@0
|
383 /* TCP/IP get remote host name
|
yuuji@0
|
384 * Accepts: TCP/IP stream
|
yuuji@0
|
385 * Returns: host name for this stream
|
yuuji@0
|
386 */
|
yuuji@0
|
387
|
yuuji@0
|
388 char *tcp_remotehost (TCPSTREAM *stream)
|
yuuji@0
|
389 {
|
yuuji@0
|
390 return stream->host; /* all we can do for now */
|
yuuji@0
|
391 }
|
yuuji@0
|
392
|
yuuji@0
|
393
|
yuuji@0
|
394 /* TCP/IP return port for this stream
|
yuuji@0
|
395 * Accepts: TCP/IP stream
|
yuuji@0
|
396 * Returns: port number for this stream
|
yuuji@0
|
397 */
|
yuuji@0
|
398
|
yuuji@0
|
399 unsigned long tcp_port (TCPSTREAM *stream)
|
yuuji@0
|
400 {
|
yuuji@0
|
401 return stream->port; /* return port number */
|
yuuji@0
|
402 }
|
yuuji@0
|
403
|
yuuji@0
|
404
|
yuuji@0
|
405 /* TCP/IP get local host name
|
yuuji@0
|
406 * Accepts: TCP/IP stream
|
yuuji@0
|
407 * Returns: local host name
|
yuuji@0
|
408 */
|
yuuji@0
|
409
|
yuuji@0
|
410 char *tcp_localhost (TCPSTREAM *stream)
|
yuuji@0
|
411 {
|
yuuji@0
|
412 return stream->localhost; /* return local host name */
|
yuuji@0
|
413 }
|
yuuji@0
|
414
|
yuuji@0
|
415
|
yuuji@0
|
416 /* TCP/IP return canonical form of host name
|
yuuji@0
|
417 * Accepts: host name
|
yuuji@0
|
418 * Returns: canonical form of host name
|
yuuji@0
|
419 */
|
yuuji@0
|
420
|
yuuji@0
|
421 char *tcp_canonical (char *name)
|
yuuji@0
|
422 {
|
yuuji@0
|
423 return name;
|
yuuji@0
|
424 }
|
yuuji@0
|
425
|
yuuji@0
|
426
|
yuuji@0
|
427 /* TCP/IP get client host name (server calls only)
|
yuuji@0
|
428 * Returns: client host name
|
yuuji@0
|
429 */
|
yuuji@0
|
430
|
yuuji@0
|
431 char *tcp_clienthost ()
|
yuuji@0
|
432 {
|
yuuji@0
|
433 return "UNKNOWN";
|
yuuji@0
|
434 }
|