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