<commit_before>/* wrapper code -- this is the shared code used around the pseduo
 * wrapper functions, which are in pseudo_wrapfuncs.c.
 */
#include <stdlib.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dlfcn.h>

/* used for various specific function arguments */
#include <dirent.h>
#include <fts.h>
#include <ftw.h>
#include <glob.h>
#include <grp.h>
#include <pwd.h>
#include <utime.h>

#include "pseudo.h"
#include "pseudo_wrapfuncs.h"
#include "pseudo_ipc.h"
#include "pseudo_client.h"

static void pseudo_enosys(const char *);
static int pseudo_populate_wrappers(void);
static volatile int antimagic = 0;
static pthread_mutex_t pseudo_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t pseudo_mutex_holder;
static int pseudo_mutex_recursion = 0;
static int pseudo_getlock(void);
static void pseudo_droplock(void);
static size_t pseudo_dechroot(char *, size_t);

extern char *program_invocation_short_name;

/* the generated code goes here */
#include "pseudo_wrapper_table.c"
#include "pseudo_wrapfuncs.c"

static int
pseudo_getlock(void) {
	if (pthread_equal(pseudo_mutex_holder, pthread_self())) {
		++pseudo_mutex_recursion;
		return 0;
	} else {
		if (pthread_mutex_lock(&pseudo_mutex) == 0) {
			pseudo_mutex_recursion = 1;
			pseudo_mutex_holder = pthread_self();
			return 0;
		} else {
			return -1;
		}
	}
}

static void
pseudo_droplock(void) {
	if (--pseudo_mutex_recursion == 0) {
		pseudo_mutex_holder = 0;
		pthread_mutex_unlock(&pseudo_mutex);
	}
}

void
pseudo_antimagic() {
	++antimagic;
}

void
pseudo_magic() {
	if (antimagic > 0)
		--antimagic;
}

static void
pseudo_enosys(const char *func) {
	pseudo_diag("pseudo: ENOSYS for '%s'.\n", func ? func : "<nil>");
	if (getenv("PSEUDO_ENOSYS_ABORT"))
		abort();
}

/* de-chroot a string.
 * note that readlink() yields an unterminated buffer, so
 * must pass in the correct length.  Buffers are null-terminated
 * unconditionally if they are modified -- the modification would
 * shorten the string, so there will be space for the NUL, so
 * this is safe even for stuff like readlink().
 */
static size_t
pseudo_dechroot(char *s, size_t len) {
	if (len == (size_t) -1)
		len = strlen(s);
	if (pseudo_chroot_len && len >= pseudo_chroot_len &&
		!memcmp(s, pseudo_chroot, pseudo_chroot_len)) {
		if (s[pseudo_chroot_len] == '/') {
			memmove(s, s + pseudo_chroot_len, len - pseudo_chroot_len);
			len -= pseudo_chroot_len;
			s[len] = '\0';
		} else if (s[pseudo_chroot_len] == '\0') {
			s[0] = '/';
			len = 1;
			s[len] = '\0';
		}
		/* otherwise, it's not really a match... */
	}
	return len;
}

static int
pseudo_populate_wrappers(void) {
	int i;
	char *debug;
	static int done = 0;
	char *pseudo_path = 0;

	if (done)
		return done;
	pseudo_getlock();
	pseudo_antimagic();
	for (i = 0; pseudo_functions[i].name; ++i) {
		if (*pseudo_functions[i].real == pseudo_functions[i].dummy) {
			int (*f)(void);
			char *e;
			dlerror();
			f = dlsym(RTLD_NEXT, pseudo_functions[i].name);
			if ((e = dlerror()) != NULL) {
				/* leave it pointed to dummy */
				pseudo_diag("No wrapper for %s: %s\n", pseudo_functions[i].name, e);
			} else {
				if (f)
					*pseudo_functions[i].real = f;
			}
		}
	}
	done = 1;
	debug = getenv("PSEUDO_DEBUG");
	if (debug) {
		int level = atoi(debug);
		for (i = 0; i < level; ++i) {
			pseudo_debug_verbose();
		}
	}
	/* must happen after wrappers are set up, because it can call
	 * getcwd(), which needs wrappers, but must happen here so that
	 * any attempt to use a path in a wrapper function will have a
	 * value for cwd.
	 */
	pseudo_client_reset();
	pseudo_path = pseudo_prefix_path(NULL);
	if (pseudo_dir_fd == -1) {
		if (pseudo_path) {
			pseudo_dir_fd = open(pseudo_path, O_RDONLY);
			pseudo_dir_fd = pseudo_fd(pseudo_dir_fd, MOVE_FD);
			free(pseudo_path);
		} else {
			pseudo_diag("No prefix available to to find server.\n");
			exit(1);
		}
		if (pseudo_dir_fd == -1) {
			pseudo_diag("Can't open prefix path (%s) for server.\n",
				strerror(errno));
			exit(1);
		}
	}
	pseudo_debug(2, "(%s) set up wrappers\n", program_invocation_short_name);
	pseudo_magic();
	pseudo_droplock();
	return done;
}

<commit_msg>Allow specification of debug output file.<commit_after>/* wrapper code -- this is the shared code used around the pseduo
 * wrapper functions, which are in pseudo_wrapfuncs.c.
 */
#include <stdlib.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dlfcn.h>

/* used for various specific function arguments */
#include <dirent.h>
#include <fts.h>
#include <ftw.h>
#include <glob.h>
#include <grp.h>
#include <pwd.h>
#include <utime.h>

#include "pseudo.h"
#include "pseudo_wrapfuncs.h"
#include "pseudo_ipc.h"
#include "pseudo_client.h"

static void pseudo_enosys(const char *);
static int pseudo_populate_wrappers(void);
static volatile int antimagic = 0;
static pthread_mutex_t pseudo_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t pseudo_mutex_holder;
static int pseudo_mutex_recursion = 0;
static int pseudo_getlock(void);
static void pseudo_droplock(void);
static size_t pseudo_dechroot(char *, size_t);

extern char *program_invocation_short_name;

/* the generated code goes here */
#include "pseudo_wrapper_table.c"
#include "pseudo_wrapfuncs.c"

static int
pseudo_getlock(void) {
	if (pthread_equal(pseudo_mutex_holder, pthread_self())) {
		++pseudo_mutex_recursion;
		return 0;
	} else {
		if (pthread_mutex_lock(&pseudo_mutex) == 0) {
			pseudo_mutex_recursion = 1;
			pseudo_mutex_holder = pthread_self();
			return 0;
		} else {
			return -1;
		}
	}
}

static void
pseudo_droplock(void) {
	if (--pseudo_mutex_recursion == 0) {
		pseudo_mutex_holder = 0;
		pthread_mutex_unlock(&pseudo_mutex);
	}
}

void
pseudo_antimagic() {
	++antimagic;
}

void
pseudo_magic() {
	if (antimagic > 0)
		--antimagic;
}

static void
pseudo_enosys(const char *func) {
	pseudo_diag("pseudo: ENOSYS for '%s'.\n", func ? func : "<nil>");
	if (getenv("PSEUDO_ENOSYS_ABORT"))
		abort();
}

/* de-chroot a string.
 * note that readlink() yields an unterminated buffer, so
 * must pass in the correct length.  Buffers are null-terminated
 * unconditionally if they are modified -- the modification would
 * shorten the string, so there will be space for the NUL, so
 * this is safe even for stuff like readlink().
 */
static size_t
pseudo_dechroot(char *s, size_t len) {
	if (len == (size_t) -1)
		len = strlen(s);
	if (pseudo_chroot_len && len >= pseudo_chroot_len &&
		!memcmp(s, pseudo_chroot, pseudo_chroot_len)) {
		if (s[pseudo_chroot_len] == '/') {
			memmove(s, s + pseudo_chroot_len, len - pseudo_chroot_len);
			len -= pseudo_chroot_len;
			s[len] = '\0';
		} else if (s[pseudo_chroot_len] == '\0') {
			s[0] = '/';
			len = 1;
			s[len] = '\0';
		}
		/* otherwise, it's not really a match... */
	}
	return len;
}

static int
pseudo_populate_wrappers(void) {
	int i;
	char *debug;
	static int done = 0;
	char *pseudo_path = 0;
	int fd;

	if (done)
		return done;
	pseudo_getlock();
	pseudo_antimagic();
	for (i = 0; pseudo_functions[i].name; ++i) {
		if (*pseudo_functions[i].real == pseudo_functions[i].dummy) {
			int (*f)(void);
			char *e;
			dlerror();
			f = dlsym(RTLD_NEXT, pseudo_functions[i].name);
			if ((e = dlerror()) != NULL) {
				/* leave it pointed to dummy */
				pseudo_diag("No wrapper for %s: %s\n", pseudo_functions[i].name, e);
			} else {
				if (f)
					*pseudo_functions[i].real = f;
			}
		}
	}
	done = 1;
	debug = getenv("PSEUDO_DEBUG");
	if (debug) {
		int level = atoi(debug);
		for (i = 0; i < level; ++i) {
			pseudo_debug_verbose();
		}
	}
	if (getenv("PSEUDO_DEBUG_FILE")) {
		char filebuf[pseudo_path_max()], *fmt = getenv("PSEUDO_DEBUG_FILE");
		char *name, *pid;
		name = strstr(fmt, "%s");
		pid = strstr(fmt, "%d");
		if (name && pid) {
			if (name > pid) {
				snprintf(filebuf, pseudo_path_max(), fmt, getpid(), program_invocation_short_name);
			} else {
				snprintf(filebuf, pseudo_path_max(), fmt, program_invocation_short_name, getpid());
			}
		} else if (name) {
			snprintf(filebuf, pseudo_path_max(), fmt, program_invocation_short_name);
		} else if (pid) {
			snprintf(filebuf, pseudo_path_max(), fmt, getpid());
		} else {
			snprintf(filebuf, pseudo_path_max(), "%s", fmt);
		}
		fd = open(filebuf, O_WRONLY | O_APPEND | O_CREAT, 0644);
		if (fd >= 0) {
			pseudo_util_debug_fd = fd;
		}
	}
	/* must happen after wrappers are set up, because it can call
	 * getcwd(), which needs wrappers, but must happen here so that
	 * any attempt to use a path in a wrapper function will have a
	 * value for cwd.
	 */
	pseudo_client_reset();
	pseudo_path = pseudo_prefix_path(NULL);
	if (pseudo_dir_fd == -1) {
		if (pseudo_path) {
			pseudo_dir_fd = open(pseudo_path, O_RDONLY);
			pseudo_dir_fd = pseudo_fd(pseudo_dir_fd, MOVE_FD);
			free(pseudo_path);
		} else {
			pseudo_diag("No prefix available to to find server.\n");
			exit(1);
		}
		if (pseudo_dir_fd == -1) {
			pseudo_diag("Can't open prefix path (%s) for server.\n",
				strerror(errno));
			exit(1);
		}
	}
	pseudo_debug(2, "(%s) set up wrappers\n", program_invocation_short_name);
	pseudo_magic();
	pseudo_droplock();
	return done;
}


{'fraction_non_alphanumeric': 0.1432198011423736, 'fraction_numerical': 0.0060291939919610744, 'mean_word_length': 4.130222463374932, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 51, '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': '1828099', 'n_tokens_mistral': 3953, 'n_tokens_neox': 3660, 'n_words': 915}