No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / attr_clnt.c
blob8d96dcb14404758f5e6edacaf739dd133112ada1
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* attr_clnt 3
6 /* SUMMARY
7 /* attribute query-reply client
8 /* SYNOPSIS
9 /* #include <attr_clnt.h>
11 /* typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list);
12 /* typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list);
14 /* ATTR_CLNT *attr_clnt_create(server, timeout, max_idle, max_ttl)
15 /* const char *server;
16 /* int timeout;
17 /* int max_idle;
18 /* int max_ttl;
20 /* int attr_clnt_request(client,
21 /* send_flags, send_type, send_name, ..., ATTR_TYPE_END,
22 /* recv_flags, recv_type, recv_name, ..., ATTR_TYPE_END)
23 /* ATTR_CLNT *client;
24 /* int send_flags;
25 /* int send_type;
26 /* const char *send_name;
27 /* int recv_flags;
28 /* int recv_type;
29 /* const char *recv_name;
31 /* void attr_clnt_free(client)
32 /* ATTR_CLNT *client;
34 /* void attr_clnt_control(client, name, value, ... ATTR_CLNT_CTL_END)
35 /* ATTR_CLNT *client;
36 /* int name;
37 /* DESCRIPTION
38 /* This module implements a client for a simple attribute-based
39 /* protocol. The default protocol is described in attr_scan_plain(3).
41 /* attr_clnt_create() creates a client handle. See auto_clnt(3) for
42 /* a description of the arguments.
44 /* attr_clnt_request() sends the specified request attributes and
45 /* receives a reply. The reply argument specifies a name-value table.
46 /* The other arguments are as described in attr_print_plain(3). The
47 /* result is the number of attributes received or -1 in case of trouble.
49 /* attr_clnt_free() destroys a client handle and closes its connection.
51 /* attr_clnt_control() allows the user to fine tune the behavior of
52 /* the specified client. The arguments are a list of (name, value)
53 /* terminated with ATTR_CLNT_CTL_END.
54 /* The following lists the names and the types of the corresponding
55 /* value arguments.
56 /* .IP "ATTR_CLNT_CTL_PROTO(ATTR_CLNT_PRINT_FN, ATTR_CLNT_SCAN_FN)"
57 /* Specifies alternatives for the attr_plain_print() and
58 /* attr_plain_scan() functions.
59 /* DIAGNOSTICS
60 /* Warnings: communication failure.
61 /* SEE ALSO
62 /* auto_clnt(3), client endpoint management
63 /* attr_scan_plain(3), attribute protocol
64 /* attr_print_plain(3), attribute protocol
65 /* LICENSE
66 /* .ad
67 /* .fi
68 /* The Secure Mailer license must be distributed with this software.
69 /* AUTHOR(S)
70 /* Wietse Venema
71 /* IBM T.J. Watson Research
72 /* P.O. Box 704
73 /* Yorktown Heights, NY 10598, USA
74 /*--*/
76 /* System library. */
78 #include <sys_defs.h>
79 #include <unistd.h>
80 #include <errno.h>
82 /* Utility library. */
84 #include <msg.h>
85 #include <mymalloc.h>
86 #include <vstream.h>
87 #include <htable.h>
88 #include <attr.h>
89 #include <iostuff.h>
90 #include <auto_clnt.h>
91 #include <attr_clnt.h>
93 /* Application-specific. */
95 struct ATTR_CLNT {
96 AUTO_CLNT *auto_clnt;
97 ATTR_CLNT_PRINT_FN print;
98 ATTR_CLNT_SCAN_FN scan;
101 /* attr_clnt_free - destroy attribute client */
103 void attr_clnt_free(ATTR_CLNT *client)
105 auto_clnt_free(client->auto_clnt);
106 myfree((char *) client);
109 /* attr_clnt_create - create attribute client */
111 ATTR_CLNT *attr_clnt_create(const char *service, int timeout,
112 int max_idle, int max_ttl)
114 ATTR_CLNT *client;
116 client = (ATTR_CLNT *) mymalloc(sizeof(*client));
117 client->auto_clnt = auto_clnt_create(service, timeout, max_idle, max_ttl);
118 client->scan = attr_vscan_plain;
119 client->print = attr_vprint_plain;
120 return (client);
123 /* attr_clnt_request - send query, receive reply */
125 int attr_clnt_request(ATTR_CLNT *client, int send_flags,...)
127 const char *myname = "attr_clnt_request";
128 VSTREAM *stream;
129 int count = 0;
130 va_list ap;
131 int type;
132 int recv_flags;
133 int err;
134 int ret;
137 * XXX If the stream is readable before we send anything, then assume the
138 * remote end disconnected.
140 * XXX For some reason we can't simply call the scan routine after the print
141 * routine, that messes up the argument list.
143 #define SKIP_ARG(ap, type) { \
144 (void) va_arg(ap, char *); \
145 (void) va_arg(ap, type); \
147 #define SKIP_ARG2(ap, t1, t2) { \
148 SKIP_ARG(ap, t1); \
149 (void) va_arg(ap, t2); \
152 for (;;) {
153 errno = 0;
154 if ((stream = auto_clnt_access(client->auto_clnt)) != 0
155 && readable(vstream_fileno(stream)) == 0) {
156 errno = 0;
157 va_start(ap, send_flags);
158 err = (client->print(stream, send_flags, ap) != 0
159 || vstream_fflush(stream) != 0);
160 va_end(ap);
161 if (err == 0) {
162 va_start(ap, send_flags);
163 while ((type = va_arg(ap, int)) != ATTR_TYPE_END) {
164 switch (type) {
165 case ATTR_TYPE_STR:
166 SKIP_ARG(ap, char *);
167 break;
168 case ATTR_TYPE_DATA:
169 SKIP_ARG2(ap, ssize_t, char *);
170 break;
171 case ATTR_TYPE_INT:
172 SKIP_ARG(ap, int);
173 break;
174 case ATTR_TYPE_LONG:
175 SKIP_ARG(ap, long);
176 break;
177 case ATTR_TYPE_HASH:
178 (void) va_arg(ap, HTABLE *);
179 break;
180 default:
181 msg_panic("%s: unexpected attribute type %d",
182 myname, type);
185 recv_flags = va_arg(ap, int);
186 ret = client->scan(stream, recv_flags, ap);
187 va_end(ap);
188 if (ret > 0)
189 return (ret);
192 if (++count >= 2
193 || msg_verbose
194 || (errno && errno != EPIPE && errno != ENOENT && errno != ECONNRESET))
195 msg_warn("problem talking to server %s: %m",
196 auto_clnt_name(client->auto_clnt));
197 if (count >= 2)
198 return (-1);
199 sleep(1); /* XXX make configurable */
200 auto_clnt_recover(client->auto_clnt);
204 /* attr_clnt_control - fine control */
206 void attr_clnt_control(ATTR_CLNT *client, int name,...)
208 const char *myname = "attr_clnt_control";
209 va_list ap;
211 for (va_start(ap, name); name != ATTR_CLNT_CTL_END; name = va_arg(ap, int)) {
212 switch (name) {
213 case ATTR_CLNT_CTL_PROTO:
214 client->print = va_arg(ap, ATTR_CLNT_PRINT_FN);
215 client->scan = va_arg(ap, ATTR_CLNT_SCAN_FN);
216 break;
217 default:
218 msg_panic("%s: bad name %d", myname, name);
221 va_end(ap);