]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/zotnet/mts/client.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / zotnet / mts / client.c
1 /* client.c - connect to a server */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: client.c,v 1.22 1995/12/06 22:15:26 jromine Exp shettich $";
4 #endif /* lint */
5
6 #if defined(SYS5) && defined(AUX)
7 #define u_short ushort
8 #define u_long ulong
9 #endif
10
11
12 #if defined(BSD42) || defined(SOCKETS)
13 #include "../h/strings.h"
14 #include <stdio.h>
15 #include "mts.h"
16 #include <errno.h>
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <netdb.h>
21 #ifndef hpux
22 #include <arpa/inet.h>
23 #endif
24
25 #ifdef HESIOD
26 #include <hesiod.h>
27 #endif
28
29 #ifdef KPOP
30 #include <krb.h>
31 #include <ctype.h>
32
33 static CREDENTIALS cred;
34 static MSG_DAT msg_data;
35 static KTEXT ticket = (KTEXT)NULL;
36 static Key_schedule schedule;
37 #endif /* KPOP */
38
39 #define NOTOK (-1)
40 #define OK 0
41 #define DONE 1
42
43 #define TRUE 1
44 #define FALSE 0
45
46 #define OOPS1 (-2)
47 #define OOPS2 (-3)
48
49 #define MAXARGS 1000
50 #define MAXNETS 5
51 #define MAXHOSTS 25
52
53 /* \f */
54
55 extern int errno;
56 #ifndef BSD44
57 extern int sys_nerr;
58 extern char *sys_errlist[];
59 #endif
60
61
62 struct addrent {
63 int a_addrtype; /* assumes AF_INET for inet_netof () */
64
65 union {
66 int un_net;
67 char un_addr[14];
68 } un;
69 #define a_net un.un_net
70 #define a_addr un.un_addr
71 };
72
73 static struct addrent *ne, *nz;
74 static struct addrent nets[MAXNETS];
75
76 static struct addrent *he, *hz;
77 static struct addrent hosts[MAXHOSTS];
78
79 #ifdef KPOP
80 char krb_realm[REALM_SZ];
81 char *PrincipalHostname();
82 static char *kservice; /* "pop" if using kpop */
83 #endif /* KPOP */
84
85 #ifdef __STDC__
86 static int rcaux (struct servent *, struct hostent *, char *);
87 static int getport (int, char *);
88 static int inet (struct hostent *, int);
89 #else
90 static int rcaux (), getport (), inet ();
91 #endif
92
93
94 #if defined(BIND) && !defined(h_addr)
95 #define h_addr h_addr_list[0]
96 #endif
97
98 #define inaddr_copy(hp,sin) \
99 bcopy ((hp) -> h_addr, (char *) &((sin) -> sin_addr), (hp) -> h_length)
100
101
102 struct hostent *gethostbystring ();
103
104
105 static int brkany ();
106 static char *getcpy (), **copyip (), **brkstring ();
107
108 /* \f */
109
110 int client (args, protocol, service, response)
111 char *args,
112 *protocol,
113 *service, /* "pop" or "pop/kpop" */
114 *response;
115 {
116 int sd;
117 register char **ap;
118 char *arguments[MAXARGS];
119 register struct hostent *hp;
120 #ifndef BIND
121 register struct netent *np;
122 #endif
123 register struct servent *sp;
124 #ifdef KPOP
125 char *cp;
126
127 if (cp = index (kservice = service, '/')) { /* "pop/kpop" */
128 *cp++ = '\0'; /* kservice = "pop" */
129 service = cp; /* service = "kpop" */
130 }
131 else
132 kservice = NULL; /* not using KERBEROS */
133 #endif /* KPOP */
134
135
136 if ((sp = getservbyname (service, protocol)) == NULL) {
137 #ifdef HESIOD
138 if ((sp = hes_getservbyname (service, protocol)) == NULL) {
139 (void) sprintf (response, "%s/%s: unknown service",
140 protocol, service);
141 return NOTOK;
142 }
143 #else
144 (void) sprintf (response, "%s/%s: unknown service", protocol, service);
145 return NOTOK;
146 #endif
147 }
148
149 ap = arguments;
150 if (args != NULL && *args != 0)
151 ap = copyip (brkstring (getcpy (args), " ", "\n"), ap);
152 else
153 if (servers != NULL && *servers != 0)
154 ap = copyip (brkstring (getcpy (servers), " ", "\n"), ap);
155 if (ap == arguments) {
156 *ap++ = getcpy ("localhost");
157 *ap = NULL;
158 }
159
160 nz = (ne = nets) + sizeof nets / sizeof nets[0];
161 hz = (he = hosts) + sizeof hosts / sizeof hosts[0];
162
163 for (ap = arguments; *ap; ap++) {
164 if (**ap == '\01') {
165 #ifndef BIND
166 if (np = getnetbyname (*ap + 1)) {
167 sethostent (1);
168 while (hp = gethostent ())
169 if (np -> n_addrtype == hp -> h_addrtype
170 && inet (hp, np -> n_net)) {
171 switch (sd = rcaux (sp, hp, response)) {
172 case NOTOK:
173 continue;
174 case OOPS1:
175 break;
176 case OOPS2:
177 return NOTOK;
178
179 default:
180 return sd;
181 }
182 break;
183 }
184 }
185 #endif
186 continue;
187 }
188
189 if (hp = gethostbystring (*ap)) {
190 switch (sd = rcaux (sp, hp, response)) {
191 case NOTOK:
192 case OOPS1:
193 break;
194 case OOPS2:
195 return NOTOK;
196
197 default:
198 return sd;
199 }
200 continue;
201 }
202 }
203
204 (void) strcpy (response, "no servers available");
205 return NOTOK;
206 }
207
208 /* \f */
209
210 static int rcaux (sp, hp, response)
211 register struct servent *sp;
212 register struct hostent *hp;
213 register char *response;
214 {
215 int sd;
216 struct in_addr in;
217 register struct addrent *ap;
218 struct sockaddr_in in_socket;
219 register struct sockaddr_in *isock = &in_socket;
220 #ifdef KPOP
221 int rem;
222 #endif /* KPOP */
223
224 for (ap = nets; ap < ne; ap++)
225 if (ap -> a_addrtype == hp -> h_addrtype && inet (hp, ap -> a_net))
226 return NOTOK;
227
228 for (ap = hosts; ap < he; ap++)
229 if (ap -> a_addrtype == hp -> h_addrtype
230 && bcmp (ap -> a_addr, hp -> h_addr, hp -> h_length) == 0)
231 return NOTOK;
232
233 if ((sd = getport (hp -> h_addrtype, response)) == NOTOK)
234 return OOPS2;
235
236 bzero ((char *) isock, sizeof *isock);
237 isock -> sin_family = hp -> h_addrtype;
238 inaddr_copy (hp, isock);
239 isock -> sin_port = sp -> s_port;
240
241 if (connect (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK)
242 switch (errno) {
243 case ENETDOWN:
244 case ENETUNREACH:
245 (void) close (sd);
246 if (ne < nz) {
247 ne -> a_addrtype = hp -> h_addrtype;
248 bcopy (hp -> h_addr, (char *) &in, sizeof in);
249 ne -> a_net = inet_netof (in);
250 ne++;
251 }
252 return OOPS1;
253
254 case ETIMEDOUT:
255 case ECONNREFUSED:
256 default:
257 (void) close (sd);
258 if (he < hz) {
259 he -> a_addrtype = hp -> h_addrtype;
260 bcopy (hp -> h_addr, he -> a_addr, hp -> h_length);
261 he++;
262 }
263 return NOTOK;
264 }
265
266 #ifdef KPOP
267 if (kservice) { /* "pop" */
268 ticket = (KTEXT)malloc( sizeof(KTEXT_ST) );
269 rem = krb_sendauth(0L, sd, ticket, kservice, hp->h_name,
270 (char *) krb_realmofhost(hp->h_name),
271 (unsigned long)0, &msg_data, &cred, schedule,
272 (struct sockaddr_in *)NULL,
273 (struct sockaddr_in *)NULL,
274 "KPOPV0.1");
275 if (rem != KSUCCESS) {
276 close(sd);
277 (void) strcpy(response, "Post office refused connection: ");
278 (void) strcat(response, krb_err_txt[rem]);
279 return OOPS2;
280 }
281 }
282 #endif /* KPOP */
283
284 return sd;
285 }
286
287 /* \f */
288
289 static int getport (addrtype, response)
290 int addrtype;
291 register char *response;
292 {
293 int sd,
294 port;
295 struct sockaddr_in in_socket,
296 *isock = &in_socket;
297
298
299 if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) {
300 (void) sprintf (response, "unable to create socket: %s",
301 errno > 0 && errno < sys_nerr ? sys_errlist[errno]
302 : "unknown error");
303 return NOTOK;
304 }
305 #ifdef KPOP
306 if (kservice) /* "pop" */
307 return(sd);
308 #endif /* KPOP */
309 return sd;
310
311 }
312
313 /* \f */
314
315 static int inet (hp, net)
316 register struct hostent *hp;
317 int net;
318 {
319 struct in_addr in;
320
321 bcopy (hp -> h_addr, (char *) &in, sizeof in);
322 return (inet_netof (in) == net);
323 }
324
325 /* \f */
326
327 /* taken from ISODE's compat/internet.c */
328
329 #ifndef OSF1
330 #ifndef DG
331 u_long inet_addr ();
332 #else
333 struct in_addr inet_addr ();
334 #endif
335 #endif
336
337 static char *empty = NULL;
338 #ifdef h_addr
339 static char *addrs[2] = { NULL };
340 #endif
341
342 struct hostent *gethostbystring (s)
343 char *s;
344 {
345 register struct hostent *h;
346 #ifndef DG
347 static u_long iaddr;
348 #else
349 static struct in_addr iaddr;
350 #endif
351 static struct hostent hs;
352
353 iaddr = inet_addr (s);
354 #ifndef DG
355 if ((int)iaddr == NOTOK && strcmp (s, "255.255.255.255"))
356 #else
357 if (iaddr.s_addr == NOTOK && strcmp (s, "255.255.255.255"))
358 #endif
359 return gethostbyname (s);
360
361 h = &hs;
362 h -> h_name = s;
363 h -> h_aliases = &empty;
364 h -> h_addrtype = AF_INET;
365 h -> h_length = sizeof (iaddr);
366 #ifdef h_addr
367 h -> h_addr_list = addrs;
368 bzero ((char *) addrs, sizeof addrs);
369 #endif
370 h -> h_addr = (char *) &iaddr;
371
372 return h;
373 }
374
375 /* \f */
376
377 /* static copies of three MH subroutines... (sigh) */
378
379 static char *broken[MAXARGS + 1];
380
381
382 static char **brkstring (strg, brksep, brkterm)
383 register char *strg;
384 register char *brksep,
385 *brkterm;
386 {
387 register int bi;
388 register char c,
389 *sp;
390
391 sp = strg;
392
393 for (bi = 0; bi < MAXARGS; bi++) {
394 while (brkany (c = *sp, brksep))
395 *sp++ = 0;
396 if (!c || brkany (c, brkterm)) {
397 *sp = 0;
398 broken[bi] = 0;
399 return broken;
400 }
401
402 broken[bi] = sp;
403 while ((c = *++sp) && !brkany (c, brksep) && !brkany (c, brkterm))
404 continue;
405 }
406 broken[MAXARGS] = 0;
407
408 return broken;
409 }
410
411
412 static brkany (chr, strg)
413 register char chr,
414 *strg;
415 {
416 register char *sp;
417
418 if (strg)
419 for (sp = strg; *sp; sp++)
420 if (chr == *sp)
421 return 1;
422 return 0;
423 }
424
425
426 static char **copyip (p, q)
427 register char **p,
428 **q;
429 {
430 while (*p)
431 *q++ = *p++;
432 *q = 0;
433
434 return q;
435 }
436
437
438 static char *getcpy (str)
439 register char *str;
440 {
441 register char *cp;
442
443 if ((cp = malloc ((unsigned) (strlen (str) + 1))) == NULL)
444 return NULL;
445
446 (void) strcpy (cp, str);
447 return cp;
448 }
449 #endif /* BSD42 or SOCKETS */