~ubuntu-branches/debian/stretch/alpine/stretch

« back to all changes in this revision

Viewing changes to imap/src/osdep/os2/tcp_os2.c

  • Committer: Bazaar Package Importer
  • Author(s): Asheesh Laroia
  • Date: 2007-02-17 13:17:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070217131742-99x5c6cpg1pbkdhw
Tags: upstream-0.82+dfsg
ImportĀ upstreamĀ versionĀ 0.82+dfsg

Show diffs side-by-side

added added

removed removed

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