/*++ /* NAME /* mail_command_client 3 /* SUMMARY /* single-command client /* SYNOPSIS /* #include /* /* int mail_command_client(class, name, proto, type, attr, ...) /* const char *class; /* const char *name; /* const char *proto; /* int type; /* const char *attr; /* DESCRIPTION /* This module implements a client interface for single-command /* clients: a client that sends a single command and expects /* a single completion status code. /* /* Arguments: /* .IP class /* Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE /* .IP name /* Service name (master.cf). /* .IP proto /* The expected protocol name in the server announcement. /* .IP "type, attr, ..." /* Attribute information as defined in attr_print(3). /* DIAGNOSTICS /* The result is -1 if the request could not be sent, otherwise /* the result is the status reported by the server. /* Warnings: problems connecting to the requested service. /* Fatal: out of memory. /* SEE ALSO /* attr_print(3), send attributes over byte stream /* mail_command_server(3), server interface /* mail_proto(3h), client-server protocol /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* /* Wietse Venema /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA /*--*/ /* System library. */ #include #include /* 44BSD stdarg.h uses abort() */ #include /* Utility library. */ #include #include /* Global library. */ #include /* mail_command_client - single-command transaction with completion status */ int mail_command_client(const char *class, const char *name, const char *proto,...) { va_list ap; VSTREAM *stream; int status; /* * Talk a little protocol with the specified service. * * This function is used for non-critical services where it is OK to back * off after the first error. Log what communication stage failed, to * facilitate trouble analysis. */ if ((stream = mail_connect(class, name, BLOCKING)) == 0) { msg_warn("connect to %s/%s: %m", class, name); return (-1); } if (attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_STREQ(MAIL_ATTR_PROTO, proto), ATTR_TYPE_END) != 0) { msg_warn("read %s: %m", VSTREAM_PATH(stream)); status = -1; } else if (va_start(ap, proto), (status = attr_vprint(stream, ATTR_FLAG_NONE, ap)), va_end(ap), (status != 0)) { msg_warn("write %s: %m", VSTREAM_PATH(stream)); status = -1; } else if (attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), ATTR_TYPE_END) != 1) { msg_warn("write/read %s: %m", VSTREAM_PATH(stream)); status = -1; } (void) vstream_fclose(stream); return (status); }