<commit_before>#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include "watchman.h"
#include <jansson.h>

static void watchman_err(watchman_error_t *error,
			  char *message, ...)
{
	va_list argptr;
	va_start(argptr, message);
	char c;
	int len = vsnprintf(&c, 1, message, argptr);
	va_end(argptr);

	error->message = malloc(len + 1);
	va_start(argptr, message);
	vsnprintf(error->message, len + 1, message, argptr);
	va_end(argptr);
}

watchman_connection_t *watchman_sock_connect(watchman_error_t *error,
					     const char *sockname)
{
	struct sockaddr_un addr = {};

	int fd;
	if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		watchman_err(error, "socket error %d", errno);
		return NULL;
	}

	addr.sun_family = AF_UNIX;
	strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)-1);

	if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
		watchman_err(error, "connect error %d", errno);
		return NULL;
	}

	FILE *sockfp = fdopen(fd, "r+");
	if (!sockfp) {
		watchman_err(error, "Failed to connect to watchman socket %s.",
			      sockname);
		return NULL;
	}
	setlinebuf(sockfp);

	watchman_connection_t *conn = malloc(sizeof(watchman_connection_t));
	conn->fp = sockfp;
	return conn;
}

watchman_connection_t *watchman_connect(watchman_error_t *error)
{
	watchman_connection_t *conn = NULL;
	FILE *fp = popen("watchman get-sockname", "r");
	if (!fp) {
		watchman_err(error,
			     "Could not watchman get-sockname: %d",
			errno);
		return NULL;
	}
	json_error_t jerror;
	json_t *json = json_loadf(fp, 0, &jerror);
	fclose(fp);
	if (!json) {
		watchman_err(error,
			     "Got bad JSON from watchman get-sockname: %s",
			     jerror.text);
		goto done;
	}
	if (!json_is_object(json)) {
		watchman_err(error, "Got bad JSON from watchman get-sockname:"
			       " object expected");
		goto bad_json;
	}
	json_t *sockname_obj = json_object_get(json, "sockname");
	if (!sockname_obj) {
		watchman_err(error, "Got bad JSON from watchman get-sockname:"
			     " socket expected");
		goto bad_json;
	}
	if (!json_is_string(sockname_obj)) {
		watchman_err(error, "Got bad JSON from watchman get-sockname:"
			     " socket is not string");
		goto bad_json;
	}
	const char *sockname = json_string_value(sockname_obj);
	conn = watchman_sock_connect(error, sockname);
bad_json:
	json_decref(json);
done:
	return conn;
}

static int watchman_send_simple_command(watchman_connection_t *conn,
					watchman_error_t *error,
					...)
{

	int result = 0;
	json_t *cmd_array = json_array();
	va_list argptr;
	va_start(argptr, error);
	char *arg;
	while (arg = va_arg(argptr, char*)) {
		json_array_append_new(cmd_array, json_string(arg));
	}
	int json_result = json_dumpf(cmd_array, conn->fp, JSON_COMPACT);
	if (json_result) {
		watchman_err(error, "Failed to send simple watchman command");
		result = 1;
	}<commit_msg>improve error messages<commit_after>#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include "watchman.h"
#include <jansson.h>

static void watchman_err(watchman_error_t *error,
			  char *message, ...)
{
	va_list argptr;
	va_start(argptr, message);
	char c;
	int len = vsnprintf(&c, 1, message, argptr);
	va_end(argptr);

	error->message = malloc(len + 1);
	va_start(argptr, message);
	vsnprintf(error->message, len + 1, message, argptr);
	va_end(argptr);
}

watchman_connection_t *watchman_sock_connect(watchman_error_t *error,
					     const char *sockname)
{
	struct sockaddr_un addr = {};

	int fd;
	if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		watchman_err(error, "Socket error %s", strerror(errno));
		return NULL;
	}

	addr.sun_family = AF_UNIX;
	strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)-1);

	if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
		watchman_err(error, "Connect error %s", strerror(errno));
		return NULL;
	}

	FILE *sockfp = fdopen(fd, "r+");
	if (!sockfp) {
		watchman_err(error,
			     "Failed to connect to watchman socket %s: %s.",
			     sockname, strerror(errno));
		return NULL;
	}
	setlinebuf(sockfp);

	watchman_connection_t *conn = malloc(sizeof(watchman_connection_t));
	conn->fp = sockfp;
	return conn;
}

watchman_connection_t *watchman_connect(watchman_error_t *error)
{
	watchman_connection_t *conn = NULL;
	FILE *fp = popen("watchman get-sockname", "r");
	if (!fp) {
		watchman_err(error,
			     "Could not run watchman get-sockname: %s",
			     strerror(errno));
		return NULL;
	}
	json_error_t jerror;
	json_t *json = json_loadf(fp, 0, &jerror);
	fclose(fp);
	if (!json) {
		watchman_err(error,
			     "Got bad JSON from watchman get-sockname: %s",
			     jerror.text);
		goto done;
	}
	if (!json_is_object(json)) {
		watchman_err(error, "Got bad JSON from watchman get-sockname:"
			       " object expected");
		goto bad_json;
	}
	json_t *sockname_obj = json_object_get(json, "sockname");
	if (!sockname_obj) {
		watchman_err(error, "Got bad JSON from watchman get-sockname:"
			     " sockname element expected");
		goto bad_json;
	}
	if (!json_is_string(sockname_obj)) {
		watchman_err(error, "Got bad JSON from watchman get-sockname:"
			     " sockname is not string");
		goto bad_json;
	}
	const char *sockname = json_string_value(sockname_obj);
	conn = watchman_sock_connect(error, sockname);
bad_json:
	json_decref(json);
done:
	return conn;
}

static int watchman_send_simple_command(watchman_connection_t *conn,
					watchman_error_t *error,
					...)
{

	int result = 0;
	json_t *cmd_array = json_array();
	va_list argptr;
	va_start(argptr, error);
	char *arg;
	while (arg = va_arg(argptr, char*)) {
		json_array_append_new(cmd_array, json_string(arg));
	}
	int json_result = json_dumpf(cmd_array, conn->fp, JSON_COMPACT);
	if (json_result) {
		watchman_err(error, "Failed to send simple watchman command");
		result = 1;
	}
{'fraction_non_alphanumeric': 0.138870320855615, 'fraction_numerical': 0.0033422459893048127, 'mean_word_length': 4.445859872611465, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1909872', 'n_tokens_mistral': 2448, 'n_tokens_neox': 2278, 'n_words': 520}