imapext-2007
diff src/osdep/vms/tcp_vmsl.c @ 0:ada5e610ab86
imap-2007e
author | yuuji@gentei.org |
---|---|
date | Mon, 14 Sep 2009 15:17:45 +0900 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/osdep/vms/tcp_vmsl.c Mon Sep 14 15:17:45 2009 +0900 1.3 @@ -0,0 +1,378 @@ 1.4 +/* ======================================================================== 1.5 + * Copyright 1988-2008 University of Washington 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * 1.14 + * ======================================================================== 1.15 + */ 1.16 + 1.17 +/* 1.18 + * Program: VMS TCP/IP routines for Netlib. 1.19 + * 1.20 + * Author: Mark Crispin 1.21 + * Networks and Distributed Computing 1.22 + * Computing & Communications 1.23 + * University of Washington 1.24 + * Administration Building, AG-44 1.25 + * Seattle, WA 98195 1.26 + * Internet: MRC@CAC.Washington.EDU 1.27 + * 1.28 + * Date: 2 August 1994 1.29 + * Last Edited: 13 January 2008 1.30 + */ 1.31 + 1.32 +/* Thanks to Yehavi Bourvine at The Hebrew University of Jerusalem who 1.33 + contributed the original VMS code */ 1.34 + 1.35 +#include <descrip.h> 1.36 + 1.37 +static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size, 1.38 + long *contd); 1.39 + 1.40 +/* TCP/IP manipulate parameters 1.41 + * Accepts: function code 1.42 + * function-dependent value 1.43 + * Returns: function-dependent return value 1.44 + */ 1.45 + 1.46 +void *tcp_parameters (long function,void *value) 1.47 +{ 1.48 + return NIL; 1.49 +} 1.50 + 1.51 + 1.52 +/* TCP/IP open 1.53 + * Accepts: host name 1.54 + * contact service name 1.55 + * contact port number 1.56 + * Returns: TCP/IP stream if success else NIL 1.57 + */ 1.58 + 1.59 +TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) 1.60 +{ 1.61 + TCPSTREAM *stream = NIL; 1.62 + unsigned long sock; 1.63 + int status; 1.64 + char tmp[MAILTMPLEN]; 1.65 + /* hostname to connect to */ 1.66 + struct dsc$descriptor HostDesc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; 1.67 + port &= 0xffff; /* erase flags */ 1.68 + /* assign a local socket */ 1.69 + if (!((status = net_assign (&sock)) & 0x1)) { 1.70 + sprintf (tmp,"Unable to assign to net, status=%d",status); 1.71 + mm_log (tmp,ERROR); 1.72 + return NIL; 1.73 + } 1.74 + if (!((status = net_bind (&sock,1)) & 0x1)) { 1.75 + sprintf (tmp,"Unable to create local socket, status=%d",status); 1.76 + mm_log (tmp,ERROR); 1.77 + return NIL; 1.78 + } 1.79 + /* open connection */ 1.80 + HostDesc.dsc$w_length = strlen (host); 1.81 + HostDesc.dsc$a_pointer = host; 1.82 + if (!((status = tcp_connect (&sock,&HostDesc,port)) & 0x1)) { 1.83 + sprintf (tmp,"Can't connect to %.80s,%lu: %s",host,port,strerror (errno)); 1.84 + mm_log (tmp,ERROR); 1.85 + return NIL; 1.86 + } 1.87 + /* create TCP/IP stream */ 1.88 + stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM)); 1.89 + stream->host = cpystr (host); /* copy official host name */ 1.90 + /* copy local host name */ 1.91 + stream->localhost = cpystr (mylocalhost ()); 1.92 + stream->port = port; /* copy port number */ 1.93 + /* init sockets */ 1.94 + stream->tcpsi = stream->tcpso = sock; 1.95 + stream->ictr = 0; /* init input counter */ 1.96 + return stream; /* return success */ 1.97 +} 1.98 + 1.99 +/* TCP/IP authenticated open 1.100 + * Accepts: NETMBX specifier 1.101 + * service name 1.102 + * returned user name buffer 1.103 + * Returns: TCP/IP stream if success else NIL 1.104 + */ 1.105 + 1.106 +TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf) 1.107 +{ 1.108 + return NIL; 1.109 +} 1.110 + 1.111 +/* TCP receive line 1.112 + * Accepts: TCP stream 1.113 + * Returns: text line string or NIL if failure 1.114 + */ 1.115 + 1.116 +char *tcp_getline (TCPSTREAM *stream) 1.117 +{ 1.118 + unsigned long n,contd; 1.119 + char *ret = tcp_getline_work (stream,&n,&contd); 1.120 + if (ret && contd) { /* got a line needing continuation? */ 1.121 + STRINGLIST *stl = mail_newstringlist (); 1.122 + STRINGLIST *stc = stl; 1.123 + do { /* collect additional lines */ 1.124 + stc->text.data = (unsigned char *) ret; 1.125 + stc->text.size = n; 1.126 + stc = stc->next = mail_newstringlist (); 1.127 + ret = tcp_getline_work (stream,&n,&contd); 1.128 + } while (ret && contd); 1.129 + if (ret) { /* stash final part of line on list */ 1.130 + stc->text.data = (unsigned char *) ret; 1.131 + stc->text.size = n; 1.132 + /* determine how large a buffer we need */ 1.133 + for (n = 0, stc = stl; stc; stc = stc->next) n += stc->text.size; 1.134 + ret = fs_get (n + 1); /* copy parts into buffer */ 1.135 + for (n = 0, stc = stl; stc; n += stc->text.size, stc = stc->next) 1.136 + memcpy (ret + n,stc->text.data,stc->text.size); 1.137 + ret[n] = '\0'; 1.138 + } 1.139 + mail_free_stringlist (&stl);/* either way, done with list */ 1.140 + } 1.141 + return ret; 1.142 +} 1.143 + 1.144 +/* TCP receive line or partial line 1.145 + * Accepts: TCP stream 1.146 + * pointer to return size 1.147 + * pointer to return continuation flag 1.148 + * Returns: text line string, size and continuation flag, or NIL if failure 1.149 + */ 1.150 + 1.151 +static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size, 1.152 + long *contd) 1.153 +{ 1.154 + unsigned long n; 1.155 + char *s,*ret,c,d; 1.156 + *contd = NIL; /* assume no continuation */ 1.157 + /* make sure have data */ 1.158 + if (!tcp_getdata (stream)) return NIL; 1.159 + for (s = stream->iptr, n = 0, c = '\0'; stream->ictr--; n++, c = d) { 1.160 + d = *stream->iptr++; /* slurp another character */ 1.161 + if ((c == '\015') && (d == '\012')) { 1.162 + ret = (char *) fs_get (n--); 1.163 + memcpy (ret,s,*size = n); /* copy into a free storage string */ 1.164 + ret[n] = '\0'; /* tie off string with null */ 1.165 + return ret; 1.166 + } 1.167 + } 1.168 + /* copy partial string from buffer */ 1.169 + memcpy ((ret = (char *) fs_get (n)),s,*size = n); 1.170 + /* get more data from the net */ 1.171 + if (!tcp_getdata (stream)) fs_give ((void **) &ret); 1.172 + /* special case of newline broken by buffer */ 1.173 + else if ((c == '\015') && (*stream->iptr == '\012')) { 1.174 + stream->iptr++; /* eat the line feed */ 1.175 + stream->ictr--; 1.176 + ret[*size = --n] = '\0'; /* tie off string with null */ 1.177 + } 1.178 + else *contd = LONGT; /* continuation needed */ 1.179 + return ret; 1.180 +} 1.181 + 1.182 +/* TCP/IP receive buffer 1.183 + * Accepts: TCP/IP stream 1.184 + * size in bytes 1.185 + * buffer to read into 1.186 + * Returns: T if success, NIL otherwise 1.187 + */ 1.188 + 1.189 +long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer) 1.190 +{ 1.191 + unsigned long n; 1.192 + char *bufptr = buffer; 1.193 + while (size > 0) { /* until request satisfied */ 1.194 + if (!tcp_getdata (stream)) return NIL; 1.195 + n = min (size,stream->ictr);/* number of bytes to transfer */ 1.196 + /* do the copy */ 1.197 + memcpy (bufptr,stream->iptr,n); 1.198 + bufptr += n; /* update pointer */ 1.199 + stream->iptr +=n; 1.200 + size -= n; /* update # of bytes to do */ 1.201 + stream->ictr -=n; 1.202 + } 1.203 + bufptr[0] = '\0'; /* tie off string */ 1.204 + return T; 1.205 +} 1.206 + 1.207 + 1.208 +/* TCP/IP receive data 1.209 + * Accepts: TCP/IP stream 1.210 + * Returns: T if success, NIL otherwise 1.211 + */ 1.212 + 1.213 +long tcp_getdata (TCPSTREAM *stream) 1.214 +{ 1.215 + char tmp[MAILTMPLEN]; 1.216 + int i,status; 1.217 + /* Note: the doc says we need here dynamic descriptor, but we need static 1.218 + * one... */ 1.219 + struct dsc$descriptor BufDesc = {BUFLEN,DSC$K_DTYPE_T,DSC$K_CLASS_S, 1.220 + stream->ibuf}; 1.221 + static short iosb[4]; 1.222 + if (stream->tcpsi < 0) return NIL; 1.223 + while (stream->ictr < 1) { /* if nothing in the buffer */ 1.224 + if (!((status = tcp_receive(&(stream->tcpsi), &BufDesc, iosb)) & 0x1)) { 1.225 + sprintf (tmp,"Error reading from TcpIp/NETLIB, status=%d",status); 1.226 + mm_log (tmp,ERROR); 1.227 + return tcp_abort (stream); 1.228 + } 1.229 + if (iosb[1] > BUFLEN) i = BUFLEN; 1.230 + else i = iosb[1]; 1.231 + if (i < 1) return tcp_abort (stream); 1.232 + stream->ictr = i; /* set new byte count */ 1.233 + stream->iptr = stream->ibuf;/* point at TCP buffer */ 1.234 + } 1.235 + return T; 1.236 +} 1.237 + 1.238 +/* TCP/IP send string as record 1.239 + * Accepts: TCP/IP stream 1.240 + * string pointer 1.241 + * Returns: T if success else NIL 1.242 + */ 1.243 + 1.244 +long tcp_soutr (TCPSTREAM *stream,char *string) 1.245 +{ 1.246 + return tcp_sout (stream,string,(unsigned long) strlen (string)); 1.247 +} 1.248 + 1.249 + 1.250 +/* TCP/IP send string 1.251 + * Accepts: TCP/IP stream 1.252 + * string pointer 1.253 + * byte count 1.254 + * Returns: T if success else NIL 1.255 + */ 1.256 + 1.257 +long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size) 1.258 +{ 1.259 + int status; 1.260 + struct dsc$descriptor_s BufDesc = {strlen(string),DSC$K_DTYPE_T, 1.261 + DSC$K_CLASS_S,string }; 1.262 + /* 2 = Do not add \r\n */ 1.263 + return ((status = tcp_send (&(stream->tcpso),&BufDesc,2)) & 0x1) ? T : 1.264 + tcp_abort (stream); 1.265 +} 1.266 + 1.267 +/* TCP/IP close 1.268 + * Accepts: TCP/IP stream 1.269 + */ 1.270 + 1.271 +void tcp_close (TCPSTREAM *stream) 1.272 +{ 1.273 + tcp_abort (stream); /* nuke the stream */ 1.274 + /* flush host names */ 1.275 + fs_give ((void **) &stream->host); 1.276 + fs_give ((void **) &stream->localhost); 1.277 + fs_give ((void **) &stream); /* flush the stream */ 1.278 +} 1.279 + 1.280 + 1.281 +/* TCP/IP abort stream 1.282 + * Accepts: TCP/IP stream 1.283 + * Returns: NIL always 1.284 + */ 1.285 + 1.286 +long tcp_abort (TCPSTREAM *stream) 1.287 +{ 1.288 + if (stream->tcpsi >= 0) { /* no-op if no socket */ 1.289 + /* nuke the socket */ 1.290 + tcp_disconnect (&(stream->tcpsi)); 1.291 + stream->tcpsi = stream->tcpso = -1; 1.292 + } 1.293 + return NIL; 1.294 +} 1.295 + 1.296 +/* TCP/IP get host name 1.297 + * Accepts: TCP/IP stream 1.298 + * Returns: host name for this stream 1.299 + */ 1.300 + 1.301 +char *tcp_host (TCPSTREAM *stream) 1.302 +{ 1.303 + return stream->host; /* return host name */ 1.304 +} 1.305 + 1.306 + 1.307 +/* TCP/IP get remote host name 1.308 + * Accepts: TCP/IP stream 1.309 + * Returns: host name for this stream 1.310 + */ 1.311 + 1.312 +char *tcp_remotehost (TCPSTREAM *stream) 1.313 +{ 1.314 + return stream->host; /* return host name */ 1.315 +} 1.316 + 1.317 + 1.318 +/* TCP/IP return port for this stream 1.319 + * Accepts: TCP/IP stream 1.320 + * Returns: port number for this stream 1.321 + */ 1.322 + 1.323 +unsigned long tcp_port (TCPSTREAM *stream) 1.324 +{ 1.325 + return stream->port; /* return port number */ 1.326 +} 1.327 + 1.328 + 1.329 +/* TCP/IP get local host name 1.330 + * Accepts: TCP/IP stream 1.331 + * Returns: local host name 1.332 + */ 1.333 + 1.334 +char *tcp_localhost (TCPSTREAM *stream) 1.335 +{ 1.336 + return stream->localhost; /* return local host name */ 1.337 +} 1.338 + 1.339 +/* Return my local host name 1.340 + * Returns: my local host name 1.341 + */ 1.342 + 1.343 +char *mylocalhost () 1.344 +{ 1.345 + int status; 1.346 + char tmp[MAILTMPLEN]; 1.347 + if (!myLocalHost) { /* have local host yet? */ 1.348 + /* receives local host name */ 1.349 + struct dsc$descriptor LocalhostDesc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,NULL}; 1.350 + if (!((status = net_get_hostname (&LocalhostDesc)) & 0x1)) { 1.351 + sprintf (tmp,"Can't get local hostname, status=%d",status); 1.352 + mm_log (tmp,ERROR); 1.353 + return "UNKNOWN"; 1.354 + } 1.355 + strncpy (tmp,LocalhostDesc.dsc$a_pointer,LocalhostDesc.dsc$w_length); 1.356 + tmp[LocalhostDesc.dsc$w_length] = '\0'; 1.357 + str$free1_dx (&LocalhostDesc); 1.358 + myLocalHost = cpystr (tmp); 1.359 + } 1.360 + return myLocalHost; 1.361 +} 1.362 + 1.363 +/* TCP/IP return canonical form of host name 1.364 + * Accepts: host name 1.365 + * Returns: canonical form of host name 1.366 + */ 1.367 + 1.368 +char *tcp_canonical (char *name) 1.369 +{ 1.370 + return name; 1.371 +} 1.372 + 1.373 + 1.374 +/* TCP/IP get client host name (server calls only) 1.375 + * Returns: client host name 1.376 + */ 1.377 + 1.378 +char *tcp_clienthost () 1.379 +{ 1.380 + return "UNKNOWN"; 1.381 +}