Annotation of libwww/Library/src/HTTCP.c, revision 2.7
1.1 timbl 1: /* Generic Communication Code HTTCP.c
2: ** ==========================
3: **
4: ** This code is in common between client and server sides.
5: **
6: ** 16 Jan 92 TBL Fix strtol() undefined on CMU Mach.
7: ** 25 Jun 92 JFG Added DECNET option through TCP socket emulation.
2.7 ! duns 8: ** 13 Sep 93 MD Added correct return of vmserrorno for HTInetStatus.
! 9: ** Added decoding of vms error message for MULTINET.
1.1 timbl 10: */
11:
12:
13: #include "HTUtils.h"
14: #include "tcp.h" /* Defines SHORT_NAMES if necessary */
15: #ifdef SHORT_NAMES
16: #define HTInetStatus HTInStat
17: #define HTInetString HTInStri
18: #define HTParseInet HTPaInet
19: #endif
20:
21: /* Module-Wide variables
22: */
23:
24: PRIVATE char *hostname=0; /* The name of this host */
25:
26:
27: /* PUBLIC VARIABLES
28: */
29:
30: /* PUBLIC SockA HTHostAddress; */ /* The internet address of the host */
31: /* Valid after call to HTHostName() */
32:
33: /* Encode INET status (as in sys/errno.h) inet_status()
34: ** ------------------
35: **
36: ** On entry,
37: ** where gives a description of what caused the error
38: ** global errno gives the error number in the unix way.
39: **
40: ** On return,
41: ** returns a negative status in the unix way.
42: */
43: #ifndef PCNFS
2.7 ! duns 44: #ifdef VMS
1.1 timbl 45: extern int uerrno; /* Deposit of error info (as per errno.h) */
2.7 ! duns 46: extern volatile noshare int socket_errno; /* socket VMS error info
! 47: (used for translation of vmserrno) */
1.1 timbl 48: extern volatile noshare int vmserrno; /* Deposit of VMS error info */
49: extern volatile noshare int errno; /* noshare to avoid PSECT conflict */
2.7 ! duns 50: #else /* VMS */
1.1 timbl 51: #ifndef errno
52: extern int errno;
53: #endif /* errno */
2.7 ! duns 54: #endif /* VMS */
1.1 timbl 55:
56: #ifndef VM
2.7 ! duns 57: #ifndef VMS
1.1 timbl 58: #ifndef NeXT
59: #ifndef THINK_C
60: extern char *sys_errlist[]; /* see man perror on cernvax */
61: extern int sys_nerr;
62: #endif /* think c */
63: #endif /* NeXT */
2.7 ! duns 64: #endif /* VMS */
1.1 timbl 65: #endif /* VM */
66:
67: #endif /* PCNFS */
68:
69: /* Report Internet Error
70: ** ---------------------
71: */
72: #ifdef __STDC__
73: PUBLIC int HTInetStatus(char *where)
74: #else
75: PUBLIC int HTInetStatus(where)
76: char *where;
77: #endif
78: {
2.7 ! duns 79: #ifdef VMS
! 80: #ifdef MULTINET
! 81: socket_errno = vmserrno;
! 82: #endif
! 83: #endif
! 84:
1.1 timbl 85: CTRACE(tfp, "TCP: Error %d in `errno' after call to %s() failed.\n\t%s\n",
86: errno, where,
2.7 ! duns 87:
1.1 timbl 88: #ifdef VM
89: "(Error number not translated)"); /* What Is the VM equiv? */
90: #define ER_NO_TRANS_DONE
91: #endif
2.7 ! duns 92: #ifdef VMS
! 93: #ifdef MULTINET
! 94: vms_errno_string());
! 95: #else
1.1 timbl 96: "(Error number not translated)");
2.7 ! duns 97: #endif
1.1 timbl 98: #define ER_NO_TRANS_DONE
99: #endif
100: #ifdef NeXT
101: strerror(errno));
102: #define ER_NO_TRANS_DONE
103: #endif
104: #ifdef THINK_C
105: strerror(errno));
106: #define ER_NO_TRANS_DONE
107: #endif
108:
109: #ifndef ER_NO_TRANS_DONE
110: errno < sys_nerr ? sys_errlist[errno] : "Unknown error" );
111: #endif
112:
2.7 ! duns 113: #ifdef VMS
! 114: #ifndef MULTINET
1.1 timbl 115: CTRACE(tfp, " Unix error number (uerrno) = %ld dec\n", uerrno);
116: CTRACE(tfp, " VMS error (vmserrno) = %lx hex\n", vmserrno);
117: #endif
2.7 ! duns 118: #endif
! 119:
! 120: #ifdef VMS
! 121: /* uerrno and errno happen to be zero if vmserrno <> 0 */
! 122: return -vmserrno;
! 123: #else
1.1 timbl 124: return -errno;
2.7 ! duns 125: #endif
1.1 timbl 126: }
127:
128:
129: /* Parse a cardinal value parse_cardinal()
130: ** ----------------------
131: **
132: ** On entry,
133: ** *pp points to first character to be interpreted, terminated by
134: ** non 0:9 character.
135: ** *pstatus points to status already valid
136: ** maxvalue gives the largest allowable value.
137: **
138: ** On exit,
139: ** *pp points to first unread character
140: ** *pstatus points to status updated iff bad
141: */
142:
143: PUBLIC unsigned int HTCardinal ARGS3
144: (int *, pstatus,
145: char **, pp,
146: unsigned int, max_value)
147: {
148: int n;
149: if ( (**pp<'0') || (**pp>'9')) { /* Null string is error */
150: *pstatus = -3; /* No number where one expeceted */
151: return 0;
152: }
153:
154: n=0;
155: while ((**pp>='0') && (**pp<='9')) n = n*10 + *((*pp)++) - '0';
156:
157: if (n>max_value) {
158: *pstatus = -4; /* Cardinal outside range */
159: return 0;
160: }
161:
162: return n;
163: }
164:
165:
166: #ifndef DECNET /* Function only used below for a trace message */
167:
168: /* Produce a string for an Internet address
169: ** ----------------------------------------
170: **
171: ** On exit,
172: ** returns a pointer to a static string which must be copied if
173: ** it is to be kept.
174: */
175:
176: PUBLIC CONST char * HTInetString ARGS1(SockA*,sin)
177: {
178: static char string[16];
179: sprintf(string, "%d.%d.%d.%d",
180: (int)*((unsigned char *)(&sin->sin_addr)+0),
181: (int)*((unsigned char *)(&sin->sin_addr)+1),
182: (int)*((unsigned char *)(&sin->sin_addr)+2),
183: (int)*((unsigned char *)(&sin->sin_addr)+3));
184: return string;
185: }
186: #endif /* Decnet */
187:
188:
189: /* Parse a network node address and port
190: ** -------------------------------------
191: **
192: ** On entry,
193: ** str points to a string with a node name or number,
194: ** with optional trailing colon and port number.
195: ** sin points to the binary internet or decnet address field.
196: **
197: ** On exit,
198: ** *sin is filled in. If no port is specified in str, that
199: ** field is left unchanged in *sin.
200: */
201: PUBLIC int HTParseInet ARGS2(SockA *,sin, CONST char *,str)
202: {
203: char *port;
204: char host[256];
205: struct hostent *phost; /* Pointer to host - See netdb.h */
206: strcpy(host, str); /* Take a copy we can mutilate */
207:
208:
209:
210: /* Parse port number if present
211: */
212: if (port=strchr(host, ':')) {
213: *port++ = 0; /* Chop off port */
214: if (port[0]>='0' && port[0]<='9') {
215:
216: #ifdef unix
217: sin->sin_port = htons(atol(port));
218: #else /* VMS */
219: #ifdef DECNET
220: sin->sdn_objnum = (unsigned char) (strtol(port, (char**)0 , 10));
221: #else
222: sin->sin_port = htons(strtol(port, (char**)0 , 10));
223: #endif /* Decnet */
224: #endif /* Unix vs. VMS */
225:
226: } else {
227:
228: #ifdef SUPPRESS /* 1. crashes!?!. 2. Not recommended */
229: struct servent * serv = getservbyname(port, (char*)0);
230: if (serv) sin->sin_port = serv->s_port;
231: else if (TRACE) fprintf(stderr, "TCP: Unknown service %s\n", port);
232: #endif
233: }
234: }
235:
236: #ifdef DECNET
237: /* read Decnet node name. @@ Should know about DECnet addresses, but it's
238: probably worth waiting until the Phase transition from IV to V. */
239:
240: sin->sdn_nam.n_len = min(DN_MAXNAML, strlen(host)); /* <=6 in phase 4 */
241: strncpy (sin->sdn_nam.n_name, host, sin->sdn_nam.n_len + 1);
242:
243: if (TRACE) fprintf(stderr,
244: "DECnet: Parsed address as object number %d on host %.6s...\n",
245: sin->sdn_objnum, host);
246:
247: #else /* parse Internet host */
248:
249: /* Parse host number if present.
250: */
251: if (*host>='0' && *host<='9') { /* Numeric node address: */
252: sin->sin_addr.s_addr = inet_addr(host); /* See arpa/inet.h */
253:
254: } else { /* Alphanumeric node name: */
255: #ifdef MVS /* Oustanding problem with crash in MVS gethostbyname */
2.6 timbl 256: if(TRACE)fprintf(stderr, "HTTCP: Calling gethostbyname(%s)\n", host);
1.1 timbl 257: #endif
258: phost=gethostbyname(host); /* See netdb.h */
259: #ifdef MVS
2.6 timbl 260: if(TRACE)fprintf(stderr, "HTTCP: gethostbyname() returned %d\n", phost);
1.1 timbl 261: #endif
262: if (!phost) {
263: if (TRACE) fprintf(stderr,
264: "HTTPAccess: Can't find internet node name `%s'.\n",host);
265: return -1; /* Fail? */
266: }
267: memcpy(&sin->sin_addr, phost->h_addr, phost->h_length);
268: }
269:
270: if (TRACE) fprintf(stderr,
271: "TCP: Parsed address as port %d, IP address %d.%d.%d.%d\n",
2.5 timbl 272: (int)ntohs(sin->sin_port),
1.1 timbl 273: (int)*((unsigned char *)(&sin->sin_addr)+0),
274: (int)*((unsigned char *)(&sin->sin_addr)+1),
275: (int)*((unsigned char *)(&sin->sin_addr)+2),
276: (int)*((unsigned char *)(&sin->sin_addr)+3));
277:
278: #endif /* Internet vs. Decnet */
279:
280: return 0; /* OK */
281: }
282:
283:
284: /* Derive the name of the host on which we are
285: ** -------------------------------------------
286: **
287: */
288: #ifdef __STDC__
289: PRIVATE void get_host_details(void)
290: #else
291: PRIVATE void get_host_details()
292: #endif
293:
294: #ifndef MAXHOSTNAMELEN
295: #define MAXHOSTNAMELEN 64 /* Arbitrary limit */
296: #endif
297:
298: {
299: char name[MAXHOSTNAMELEN+1]; /* The name of this host */
300: #ifdef NEED_HOST_ADDRESS /* no -- needs name server! */
301: struct hostent * phost; /* Pointer to host -- See netdb.h */
302: #endif
303: int namelength = sizeof(name);
304:
305: if (hostname) return; /* Already done */
306: gethostname(name, namelength); /* Without domain */
307: CTRACE(tfp, "TCP: Local host name is %s\n", name);
308: StrAllocCopy(hostname, name);
309:
310: #ifndef DECNET /* Decnet ain't got no damn name server 8#OO */
311: #ifdef NEED_HOST_ADDRESS /* no -- needs name server! */
312: phost=gethostbyname(name); /* See netdb.h */
313: if (!phost) {
314: if (TRACE) fprintf(stderr,
315: "TCP: Can't find my own internet node address for `%s'!!\n",
316: name);
317: return; /* Fail! */
318: }
319: StrAllocCopy(hostname, phost->h_name);
320: memcpy(&HTHostAddress, &phost->h_addr, phost->h_length);
321: if (TRACE) fprintf(stderr, " Name server says that I am `%s' = %s\n",
322: hostname, HTInetString(&HTHostAddress));
323: #endif
324:
325: #endif /* not Decnet */
326: }
327:
328: #ifdef __STDC__
329: PUBLIC const char * HTHostName(void)
330: #else
331: PUBLIC char * HTHostName()
332: #endif
333: {
334: get_host_details();
335: return hostname;
336: }
337:
Webmaster