> At this point I'm mainly interested in feedback about the API, if it looks sane and future proof.
The example code provided gives users a great start. I'm wondering if some of the example code could be pulled into the library itself? My guess is that many people who use the library will basically copy/paste portions into their own code. What do you think of something like the following: int main() { chrony_session *csess; chrony_socket *csock = chrony_socket_open(); int r = chrony_session_init(&csess, csock); if(r == CHRONY_OK) { print_all_reports(csess); chrony_session_deinit(csess); } else { chrony_error(r); } chrony_socket_close(&csock); return r; } The following line would try both UNIX and INET sockets automatically using the default path: chrony_socket *csock = chrony_socket_open(); Under the hood, perhaps chrony_socket_open makes use of: chrony_socket_open_unix(); chrony_socket_open_inet(); This also allows for: chrony_socket *csock = chrony_socket_open("/var/run/chrony/custom.sock"); It would mean that chrony_error would be responsible for invoking perror, or perhaps users would have to switch on the result from chrony_session_init to handle any errors: switch(r) { case CRHONY_ERROR_SOCKET_UNIX: perror("socket unix"); break; case CRHONY_ERROR_SOCKET_BIND: perror("bind unix"); break; case CRHONY_ERROR_SOCKET_INET: perror("socket inet"); break; } Would that be useful and likely lead to more reuse of library code?