Next: , Previous: Generalities, Up: Top


6 How to develop an Assuan client

Depending on the type of the server you want to connect you need to use different functions.

For a pipe based server you fork and exec yourself, you use:

— Function: assuan_error_t assuan_pipe_connect (assuan_context_t *ctx,const char *name, const char *const argv[], int *fd_child_list)

A call to this functions forks the current process and executes the program name, passing the arguments given in the NULL-terminated list argv. A list of file descriptors not to be closed may be given using the -1 terminated array fd_child_list.

On success a new assuan context is returned at ctx.

If it is not a simple pipe server but one using full-duplex sockets, the full-fledged variant of the above function should be used:

— Function: assuan_error_t assuan_pipe_connect_ext (assuan_context_t *ctx,const char *name, const char *const argv[], int *fd_child_list, void (*atfork) (void *, int), void *atforkvalue, unsigned int flags)

A call to this functions forks the current process and executes the program name, passing the arguments given in the NULL-terminated list argv. A list of file descriptors not to be closed may be given using the -1 terminated array fd_child_list.

If name as well as argv are given as NULL, only a fork but no exec is done. Thus the child continues to run. However all file descriptors are closed and some special environment variables are set. To let the caller detect whether the child or the parent continues, the child returns with a ctx set to NULL.

If atfork is not NULL, this function is called in the child right after the fork and the value atforkvalue is passed as the first argument. That function should only act if the second argument it received is 0. Such a fork callback is useful to release additional resources not to be used by the child.

flags controls how the function acts: With a value of 0 it expects a simple pipe based server and behaves similar to assuan_pipe_connect. With a value of 1 a sever based on full-duplex pipes is expected. Such pipes are usually created using the socketpair function. It also enables features only available with such servers.

If you are using a long running server listening either on a TCP or a Unix domain socket, the following function is used to connect to the server:

— Function: assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx, const char *name, pid_t server_pid, unsigned int flags)

Make a connection to the Unix domain socket name and return a new Assuan context at ctx. server_pid is currently not used but may become handy in the future; if you don't know the server's pid, pass -1. With flags set to 1, sendmsg and recvmesg are used for input and output and thereby enabling the the use of descriptor passing.

Connecting to a TCP server is not yet implemented. Standard URL schemes are reserved for name specifying a TCP server.

— Function: assuan_error_t assuan_socket_connect (assuan_context_t *ctx, const char *name, pid_t server_pid)

Same as above but no way to specify flags.

Finally, after using the Assuan connection, the resources should be deallocated:

— Function: void assuan_disconnect (assuan_context_t ctx)

Close the connection described by the Assuan context ctx and release all resources. This function also tries to send the BYE command to the server but won't fail on error. It is explicitly allowed to pass NULL for ctx, in which case the function does nothing.

Now that we have a connection to the server, all work may be conveniently done using a couple of callbacks and the transact function:

— Function: assuan_error_t assuan_transact (assuan_context_t ctx, const char *command, int (*data_cb)(void *, const void *, size_t), void *data_cb_arg, int (*inquire_cb)(void*, const char *), void *inquire_cb_arg, int (*status_cb)(void*, const char *), void *status_cb_arg)

Here ctx is the Assuan context opened by one of the connect calls. command is the actual one liner Assuan command. It shall not end with a line feed and its length is limited to ASSUAN_LINELENGTH (~1000 bytes)

data_cb is called by Libassuan for data lines; data_cb_arg is passed to it along with the data and the length. [FIXME: needs more documentation].

inquire_cb is called by Libassuan when the server requests additional information from the client while processing the command. This callback shall check the provided inquiry name and send the data as requested back using the assuan_write_data. The server passed inquiry_cb_arg along with the inquiry name to the callback.

status_cb is called by Libassuan for each status line it receives from the server. status_cb_arg is passed along with the status line to the callback.

The function returns 0 success or an error code. The error code may be the one one returned by the server in error lines or one generated by the callback functions.

Libassuan supports descriptor passing on some platforms. The next two functions are used with this feature:

— Function: assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd)

Send the descriptor fd to the peer using the context ctx. Note, that calling this function with a ctx of NULL and fd of -1 is a valid runtime test to check whether descriptor passing is available on the platform. The descriptor must be sent before the command is issued that makes use of the descriptor.

— Function: assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd)

Receive a descriptor pending for the context ctx from the peer. The descriptor must be pending before this function is called. To accomplish this, the peer needs to use assuan_sendfd before the trigger is sent (e.g. using assuan_write_line ("INPUT FD").