Mercurial > hg > Applications > mh
diff zotnet/mts/client.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | 442dbbf0ac7d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/zotnet/mts/client.c Mon Apr 18 23:46:02 2005 +0900 @@ -0,0 +1,493 @@ +/* client.c - connect to a server */ +#ifndef lint +static char ident[] = "@(#)$Id$"; +#endif /* lint */ + +#if defined(SYS5) && defined(AUX) +#define u_short ushort +#define u_long ulong +#endif + + +#if defined(BSD42) || defined(SOCKETS) +#include "../h/strings.h" +#include <stdio.h> +#include "mts.h" +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#ifndef hpux +#include <arpa/inet.h> +#endif + +#ifdef HESIOD +#include <hesiod.h> +#endif + +#ifdef KPOP +#include <krb.h> +#include <ctype.h> + +static CREDENTIALS cred; +static MSG_DAT msg_data; +static KTEXT ticket = (KTEXT)NULL; +static Key_schedule schedule; +#endif /* KPOP */ + +#define NOTOK (-1) +#define OK 0 +#define DONE 1 + +#define TRUE 1 +#define FALSE 0 + +#define OOPS1 (-2) +#define OOPS2 (-3) + +#define MAXARGS 1000 +#define MAXNETS 5 +#define MAXHOSTS 25 + +/* */ + +extern int errno; +#if !defined(BSD44) && !defined(__GNU_LIBRARY__) +extern int sys_nerr; +extern char *sys_errlist[]; +#endif + + +struct addrent { + int a_addrtype; /* assumes AF_INET for inet_netof () */ + + union { + int un_net; + char un_addr[14]; + } un; +#define a_net un.un_net +#define a_addr un.un_addr +}; + +static struct addrent *ne, *nz; +static struct addrent nets[MAXNETS]; + +static struct addrent *he, *hz; +static struct addrent hosts[MAXHOSTS]; + +#ifdef KPOP +char krb_realm[REALM_SZ]; +char *PrincipalHostname(); +static char *kservice; /* "pop" if using kpop */ +#endif /* KPOP */ + +#ifdef __STDC__ +static int rcaux (struct servent *, struct hostent *, int, char *); +static int getport (int, int, char *); +static int inet (struct hostent *, int); +#else +static int rcaux (), getport (), inet (); +#endif + + +#if defined(BIND) && !defined(h_addr) +#define h_addr h_addr_list[0] +#endif + +#define inaddr_copy(hp,sin) \ + bcopy ((hp) -> h_addr, (char *) &((sin) -> sin_addr), (hp) -> h_length) + + +struct hostent *gethostbystring (); + + +static int brkany (); +static char *getcpy (), **copyip (), **brkstring (); + +/* */ + +int client (args, protocol, service, rproto, response) +char *args, + *protocol, + *service, /* "pop" or "pop/kpop" */ + *response; +int rproto; +{ + int sd; + register char **ap; + char *arguments[MAXARGS]; + register struct hostent *hp; +#ifndef BIND + register struct netent *np; +#endif + register struct servent *sp; +#ifdef KPOP + char *cp; + + if (cp = index (kservice = service, '/')) { /* "pop/kpop" */ + *cp++ = '\0'; /* kservice = "pop" */ + service = cp; /* service = "kpop" */ + } + else + kservice = NULL; /* not using KERBEROS */ +#endif /* KPOP */ + + + if ((sp = getservbyname (service, protocol)) == NULL) { +#ifdef HESIOD + if ((sp = hes_getservbyname (service, protocol)) == NULL) { + (void) sprintf (response, "%s/%s: unknown service", + protocol, service); + return NOTOK; + } +#else + (void) sprintf (response, "%s/%s: unknown service", protocol, service); + return NOTOK; +#endif + } + + ap = arguments; + if (args != NULL && *args != 0) + ap = copyip (brkstring (getcpy (args), " ", "\n"), ap); + else + if (servers != NULL && *servers != 0) + ap = copyip (brkstring (getcpy (servers), " ", "\n"), ap); + if (ap == arguments) { + *ap++ = getcpy ("localhost"); + *ap = NULL; + } + + nz = (ne = nets) + sizeof nets / sizeof nets[0]; + hz = (he = hosts) + sizeof hosts / sizeof hosts[0]; + + for (ap = arguments; *ap; ap++) { + if (**ap == '\01') { +#if !defined(BIND) && !defined(__CYGWIN32__) + if (np = getnetbyname (*ap + 1)) { + sethostent (1); + while (hp = gethostent ()) + if (np -> n_addrtype == hp -> h_addrtype + && inet (hp, np -> n_net)) { + switch (sd = rcaux (sp, hp, rproto, response)) { + case NOTOK: + continue; + case OOPS1: + break; + case OOPS2: + return NOTOK; + + default: + return sd; + } + break; + } + } +#endif + continue; + } + + if (hp = gethostbystring (*ap)) { + switch (sd = rcaux (sp, hp, rproto, response)) { + case NOTOK: + case OOPS1: + break; + case OOPS2: + return NOTOK; + + default: + return sd; + } + continue; + } + } + + (void) strcpy (response, "no servers available"); + return NOTOK; +} + +/* */ + +static int rcaux (sp, hp, rproto, response) +register struct servent *sp; +register struct hostent *hp; +int rproto; +register char *response; +{ + int sd; + struct in_addr in; + register struct addrent *ap; + struct sockaddr_in in_socket; + register struct sockaddr_in *isock = &in_socket; +#ifdef KPOP + int rem; +#endif /* KPOP */ + + for (ap = nets; ap < ne; ap++) + if (ap -> a_addrtype == hp -> h_addrtype && inet (hp, ap -> a_net)) + return NOTOK; + + for (ap = hosts; ap < he; ap++) + if (ap -> a_addrtype == hp -> h_addrtype + && bcmp (ap -> a_addr, hp -> h_addr, hp -> h_length) == 0) + return NOTOK; + + if ((sd = getport (rproto, hp -> h_addrtype, response)) == NOTOK) + return OOPS2; + + bzero ((char *) isock, sizeof *isock); + isock -> sin_family = hp -> h_addrtype; + inaddr_copy (hp, isock); + isock -> sin_port = sp -> s_port; + + if (connect (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK) + switch (errno) { + case ENETDOWN: + case ENETUNREACH: + (void) close (sd); + if (ne < nz) { + ne -> a_addrtype = hp -> h_addrtype; + bcopy (hp -> h_addr, (char *) &in, sizeof in); + ne -> a_net = inet_netof (in); + ne++; + } + return OOPS1; + + case ETIMEDOUT: + case ECONNREFUSED: + default: + (void) close (sd); + if (he < hz) { + he -> a_addrtype = hp -> h_addrtype; + bcopy (hp -> h_addr, he -> a_addr, hp -> h_length); + he++; + } + return NOTOK; + } + +#ifdef KPOP + if (kservice) { /* "pop" */ + ticket = (KTEXT)malloc( sizeof(KTEXT_ST) ); + rem = krb_sendauth(0L, sd, ticket, kservice, hp->h_name, + (char *) krb_realmofhost(hp->h_name), + (unsigned long)0, &msg_data, &cred, schedule, + (struct sockaddr_in *)NULL, + (struct sockaddr_in *)NULL, + "KPOPV0.1"); + if (rem != KSUCCESS) { + close(sd); + (void) strcpy(response, "Post office refused connection: "); + (void) strcat(response, krb_err_txt[rem]); + return OOPS2; + } + } +#endif /* KPOP */ + + return sd; +} + +/* */ + +static int getport (rproto, addrtype, response) +int rproto, + addrtype; +register char *response; +{ + int sd, + port; + struct sockaddr_in in_socket, + *isock = &in_socket; + + if (rproto && addrtype != AF_INET) { + (void) sprintf (response, "reserved ports not supported for af=%d", + addrtype); + errno = ENOPROTOOPT; + return NOTOK; + } + + if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) { + (void) sprintf (response, "unable to create socket: %s", + errno > 0 && errno < sys_nerr ? sys_errlist[errno] + : "unknown error"); + return NOTOK; + } +#ifdef KPOP + if (kservice) /* "pop" */ + return(sd); +#endif /* KPOP */ + if (!rproto) + return sd; + + bzero ((char *) isock, sizeof *isock); + isock -> sin_family = addrtype; + for (port = IPPORT_RESERVED - 1;;) { + isock -> sin_port = htons ((u_short) port); + if (bind (sd, (struct sockaddr *) isock, sizeof *isock) != NOTOK) + return sd; + + switch (errno) { + case EADDRINUSE: + case EADDRNOTAVAIL: + if (--port <= IPPORT_RESERVED / 2) { + (void) strcpy (response, "ports available"); + return NOTOK; + } + break; + + default: + (void) sprintf (response, "unable to bind socket: %s", + errno > 0 && errno < sys_nerr ? sys_errlist[errno] + : "unknown error"); + return NOTOK; + } + } +} + +/* */ + +static int inet (hp, net) +register struct hostent *hp; +int net; +{ + struct in_addr in; + + bcopy (hp -> h_addr, (char *) &in, sizeof in); + return (inet_netof (in) == net); +} + +/* */ + +/* taken from ISODE's compat/internet.c */ + +#if !defined(SOLARIS) && !defined(linux) && !defined(__bsdi__) && \ + !defined(OSF1) && !defined(__osf__) && !defined(__FreeBSD__) && \ + !defined(__NetBSD__) +#ifndef DG +#ifndef __alpha +u_long inet_addr (); +#else +u_int inet_addr (); +#endif +#else +struct in_addr inet_addr (); +#endif +#endif + +static char *empty = NULL; +#ifdef h_addr +static char *addrs[2] = { NULL }; +#endif +struct hostent *mh_gethostbyname(); + +struct hostent *gethostbystring (s) +char *s; +{ + register struct hostent *h; +#ifndef DG +#ifndef __alpha + static u_long iaddr; +#else + static u_int iaddr; +#endif +#else + static struct in_addr iaddr; +#endif + static struct hostent hs; + + iaddr = inet_addr (s); +#ifndef DG + if ((int)iaddr == NOTOK && strcmp (s, "255.255.255.255")) +#else + if (iaddr.s_addr == NOTOK && strcmp (s, "255.255.255.255")) +#endif + return mh_gethostbyname (s); + + h = &hs; + h -> h_name = s; + h -> h_aliases = ∅ + h -> h_addrtype = AF_INET; + h -> h_length = sizeof (iaddr); +#ifdef h_addr + h -> h_addr_list = addrs; + bzero ((char *) addrs, sizeof addrs); +#endif + h -> h_addr = (char *) &iaddr; + + return h; +} + +/* */ + +/* static copies of three MH subroutines... (sigh) */ + +static char *broken[MAXARGS + 1]; + + +static char **brkstring (strg, brksep, brkterm) +register char *strg; +register char *brksep, + *brkterm; +{ + register int bi; + register char c, + *sp; + + sp = strg; + + for (bi = 0; bi < MAXARGS; bi++) { + while (brkany (c = *sp, brksep)) + *sp++ = 0; + if (!c || brkany (c, brkterm)) { + *sp = 0; + broken[bi] = 0; + return broken; + } + + broken[bi] = sp; + while ((c = *++sp) && !brkany (c, brksep) && !brkany (c, brkterm)) + continue; + } + broken[MAXARGS] = 0; + + return broken; +} + + +static brkany (chr, strg) +register char chr, + *strg; +{ + register char *sp; + + if (strg) + for (sp = strg; *sp; sp++) + if (chr == *sp) + return 1; + return 0; +} + + +static char **copyip (p, q) +register char **p, + **q; +{ + while (*p) + *q++ = *p++; + *q = 0; + + return q; +} + + +static char *getcpy (str) +register char *str; +{ + register char *cp; + + if ((cp = malloc ((unsigned) (strlen (str) + 1))) == NULL) + return NULL; + + (void) strcpy (cp, str); + return cp; +} +#endif /* BSD42 or SOCKETS */