+/*
+ * Having verboselog() and errorlog() is necessary when using libi3.
+ *
+ */
+void verboselog(char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+}
+
+void errorlog(char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
+
+static char *last_key = NULL;
+
+typedef struct reply_t {
+ bool success;
+ char *error;
+ char *input;
+ char *errorposition;
+} reply_t;
+
+static reply_t last_reply;
+
+static int reply_boolean_cb(void *params, int val) {
+ if (strcmp(last_key, "success") == 0)
+ last_reply.success = val;
+ return 1;
+}
+
+#if YAJL_MAJOR >= 2
+static int reply_string_cb(void *params, const unsigned char *val, size_t len) {
+#else
+static int reply_string_cb(void *params, const unsigned char *val, unsigned int len) {
+#endif
+ char *str = scalloc(len + 1);
+ strncpy(str, (const char*)val, len);
+ if (strcmp(last_key, "error") == 0)
+ last_reply.error = str;
+ else if (strcmp(last_key, "input") == 0)
+ last_reply.input = str;
+ else if (strcmp(last_key, "errorposition") == 0)
+ last_reply.errorposition = str;
+ else free(str);
+ return 1;
+}
+
+static int reply_start_map_cb(void *params) {
+ return 1;
+}
+
+static int reply_end_map_cb(void *params) {
+ if (!last_reply.success) {
+ fprintf(stderr, "ERROR: Your command: %s\n", last_reply.input);
+ fprintf(stderr, "ERROR: %s\n", last_reply.errorposition);
+ fprintf(stderr, "ERROR: %s\n", last_reply.error);
+ }
+ return 1;
+}
+
+
+#if YAJL_MAJOR >= 2
+static int reply_map_key_cb(void *params, const unsigned char *keyVal, size_t keyLen) {
+#else
+static int reply_map_key_cb(void *params, const unsigned char *keyVal, unsigned keyLen) {
+#endif
+ free(last_key);
+ last_key = scalloc(keyLen + 1);
+ strncpy(last_key, (const char*)keyVal, keyLen);
+ return 1;
+}
+
+yajl_callbacks reply_callbacks = {
+ NULL,
+ &reply_boolean_cb,
+ NULL,
+ NULL,
+ NULL,
+ &reply_string_cb,
+ &reply_start_map_cb,
+ &reply_map_key_cb,
+ &reply_end_map_cb,
+ NULL,
+ NULL
+};
+