fix up errno references
[project/librpc-uclibc.git] / clnt_generic.c
1 /*
2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part. Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
8 *
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12 *
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
16 *
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
20 *
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
24 *
25 * Sun Microsystems, Inc.
26 * 2550 Garcia Avenue
27 * Mountain View, California 94043
28 */
29 /*
30 * Copyright (C) 1987, Sun Microsystems, Inc.
31 */
32
33 #define __FORCE_GLIBC
34 #include <features.h>
35
36 #include <alloca.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <rpc/rpc.h>
40 #include <sys/socket.h>
41 #include <netdb.h>
42
43
44 /*
45 * Generic client creation: takes (hostname, program-number, protocol) and
46 * returns client handle. Default options are set, which the user can
47 * change using the rpc equivalent of ioctl()'s.
48 */
49 CLIENT *
50 clnt_create (const char *hostname, u_long prog, u_long vers,
51 const char *proto)
52 {
53 struct hostent hostbuf, *h;
54 size_t hstbuflen;
55 char *hsttmpbuf;
56 struct protoent protobuf, *p;
57 size_t prtbuflen;
58 char *prttmpbuf;
59 struct sockaddr_in sin;
60 struct sockaddr_un sun;
61 int sock;
62 struct timeval tv;
63 CLIENT *client;
64 int herr;
65
66 if (strcmp (proto, "unix") == 0)
67 {
68 memset ((char *)&sun, 0, sizeof (sun));
69 sun.sun_family = AF_UNIX;
70 strcpy (sun.sun_path, hostname);
71 sock = RPC_ANYSOCK;
72 client = clntunix_create (&sun, prog, vers, &sock, 0, 0);
73 if (client == NULL)
74 return NULL;
75 #if 0
76 /* This is not wanted. This would disable the user from having
77 a timeout in the clnt_call() call. Only a call to cnlt_control()
78 by the user should set the timeout value. */
79 tv.tv_sec = 25;
80 tv.tv_usec = 0;
81 clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
82 #endif
83 return client;
84 }
85
86 hstbuflen = 1024;
87 hsttmpbuf = alloca (hstbuflen);
88 while (gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen,
89 &h, &herr) != 0
90 || h == NULL)
91 if (herr != NETDB_INTERNAL || errno != ERANGE)
92 {
93 get_rpc_createerr().cf_stat = RPC_UNKNOWNHOST;
94 return NULL;
95 }
96 else
97 {
98 /* Enlarge the buffer. */
99 hstbuflen *= 2;
100 hsttmpbuf = alloca (hstbuflen);
101 }
102
103 if (h->h_addrtype != AF_INET)
104 {
105 /*
106 * Only support INET for now
107 */
108 struct rpc_createerr *ce = &get_rpc_createerr ();
109 ce->cf_stat = RPC_SYSTEMERROR;
110 ce->cf_error.re_errno = EAFNOSUPPORT;
111 return NULL;
112 }
113 sin.sin_family = h->h_addrtype;
114 sin.sin_port = 0;
115 memset (sin.sin_zero, 0, sizeof (sin.sin_zero));
116 memcpy ((char *) &sin.sin_addr, h->h_addr, h->h_length);
117
118 prtbuflen = 1024;
119 prttmpbuf = alloca (prtbuflen);
120 while (getprotobyname_r (proto, &protobuf, prttmpbuf, prtbuflen, &p) != 0
121 || p == NULL)
122 if (errno != ERANGE)
123 {
124 struct rpc_createerr *ce = &get_rpc_createerr ();
125 ce->cf_stat = RPC_UNKNOWNPROTO;
126 ce->cf_error.re_errno = EPFNOSUPPORT;
127 return NULL;
128 }
129 else
130 {
131 /* Enlarge the buffer. */
132 prtbuflen *= 2;
133 prttmpbuf = alloca (prtbuflen);
134 }
135
136 sock = RPC_ANYSOCK;
137 switch (p->p_proto)
138 {
139 case IPPROTO_UDP:
140 tv.tv_sec = 5;
141 tv.tv_usec = 0;
142 client = clntudp_create (&sin, prog, vers, tv, &sock);
143 if (client == NULL)
144 {
145 return NULL;
146 }
147 #if 0
148 /* This is not wanted. This would disable the user from having
149 a timeout in the clnt_call() call. Only a call to cnlt_control()
150 by the user should set the timeout value. */
151 tv.tv_sec = 25;
152 clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
153 #endif
154 break;
155 case IPPROTO_TCP:
156 client = clnttcp_create (&sin, prog, vers, &sock, 0, 0);
157 if (client == NULL)
158 {
159 return NULL;
160 }
161 #if 0
162 /* This is not wanted. This would disable the user from having
163 a timeout in the clnt_call() call. Only a call to cnlt_control()
164 by the user should set the timeout value. */
165 tv.tv_sec = 25;
166 tv.tv_usec = 0;
167 clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
168 #endif
169 break;
170 default:
171 {
172 struct rpc_createerr *ce = &get_rpc_createerr ();
173 ce->cf_stat = RPC_SYSTEMERROR;
174 ce->cf_error.re_errno = EPFNOSUPPORT;
175 }
176 return (NULL);
177 }
178 return client;
179 }