7 /* attribute query-reply client
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;
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)
26 /* const char *send_name;
29 /* const char *recv_name;
31 /* void attr_clnt_free(client)
34 /* void attr_clnt_control(client, name, value, ... ATTR_CLNT_CTL_END)
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
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.
60 /* Warnings: communication failure.
62 /* auto_clnt(3), client endpoint management
63 /* attr_scan_plain(3), attribute protocol
64 /* attr_print_plain(3), attribute protocol
68 /* The Secure Mailer license must be distributed with this software.
71 /* IBM T.J. Watson Research
73 /* Yorktown Heights, NY 10598, USA
82 /* Utility library. */
90 #include <auto_clnt.h>
91 #include <attr_clnt.h>
93 /* Application-specific. */
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
)
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
;
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";
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) { \
149 (void) va_arg(ap, t2); \
154 if ((stream
= auto_clnt_access(client
->auto_clnt
)) != 0
155 && readable(vstream_fileno(stream
)) == 0) {
157 va_start(ap
, send_flags
);
158 err
= (client
->print(stream
, send_flags
, ap
) != 0
159 || vstream_fflush(stream
) != 0);
162 va_start(ap
, send_flags
);
163 while ((type
= va_arg(ap
, int)) != ATTR_TYPE_END
) {
166 SKIP_ARG(ap
, char *);
169 SKIP_ARG2(ap
, ssize_t
, char *);
178 (void) va_arg(ap
, HTABLE
*);
181 msg_panic("%s: unexpected attribute type %d",
185 recv_flags
= va_arg(ap
, int);
186 ret
= client
->scan(stream
, recv_flags
, ap
);
194 || (errno
&& errno
!= EPIPE
&& errno
!= ENOENT
&& errno
!= ECONNRESET
))
195 msg_warn("problem talking to server %s: %m",
196 auto_clnt_name(client
->auto_clnt
));
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";
211 for (va_start(ap
, name
); name
!= ATTR_CLNT_CTL_END
; name
= va_arg(ap
, int)) {
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
);
218 msg_panic("%s: bad name %d", myname
, name
);