Exemple #1
0
tree_ptr tree_new_binary(fun_ptr fun, tree_ptr x, tree_ptr y) {
	tree_ptr t = tree_new_funcall();
	tree_append(t, x);
	tree_append(t, y);
	tree_set_fun(t, tree_new_fun(fun));
	return t;
}
Exemple #2
0
static void
url_add (char *urltext, int len)
{
	char *data;
	int size;

	if (!prefs.url_grabber)
		return;

	data = malloc (len + 1);
	if (!data)
		return;
	memcpy (data, urltext, len);
	data[len] = 0;

	if (data[len - 1] == '.')	/* chop trailing dot */
	{
		len--;
		data[len] = 0;
	}
	if (data[len - 1] == ')')	/* chop trailing ) */
		data[len - 1] = 0;

	if (url_find (data))
	{
		free (data);
		return;
	}

	if (!url_tree)
		url_tree = tree_new ((tree_cmp_func *)g_ascii_strcasecmp, NULL);

	size = tree_size (url_tree);
	/* 0 is unlimited */
	if (prefs.url_grabber_limit > 0 && size >= prefs.url_grabber_limit)
	{
		/* the loop is necessary to handle having the limit lowered while
		   xchat is running */
		size -= prefs.url_grabber_limit;
		for(; size > 0; size--)
			tree_remove_at_pos (url_tree, 0);
	}

	tree_append (url_tree, data);
	fe_url_add (data);
}
Exemple #3
0
/*
 * Open a directory tree for traversal.
 */
struct tree *
tree_open(const char *path)
{
	struct tree *t;

	t = malloc(sizeof(*t));
	memset(t, 0, sizeof(*t));
	tree_append(t, path, strlen(path));
	t->initialDirFd = open(".", O_RDONLY);
	/*
	 * During most of the traversal, items are set up and then
	 * returned immediately from tree_next().  That doesn't work
	 * for the very first entry, so we set a flag for this special
	 * case.
	 */
	t->flags = needsReturn;
	return (t);
}
Exemple #4
0
/*
 * Open a directory tree for traversal.
 */
struct tree *
tree_open(const char *path)
{
	struct tree *t;

	t = malloc(sizeof(*t));
	if (t == NULL)
		abort();
	memset(t, 0, sizeof(*t));
	tree_append(t, path, strlen(path));
#ifdef HAVE_FCHDIR
	t->initialDirFd = open(".", O_RDONLY);
#elif defined(_WIN32) && !defined(__CYGWIN__)
	t->initialDir = getcwd(NULL, 0);
#endif
	/*
	 * During most of the traversal, items are set up and then
	 * returned immediately from tree_next().  That doesn't work
	 * for the very first entry, so we set a flag for this special
	 * case.
	 */
	t->flags = needsReturn;
	return (t);
}
Exemple #5
0
static void
url_add (char *urltext, int len)
{
	char *data;
	int size;

	/* we don't need any URLs if we have neither URL grabbing nor URL logging enabled */
	if (!prefs.hex_url_grabber && !prefs.hex_url_logging)
	{
		return;
	}

	data = malloc (len + 1);
	if (!data)
	{
		return;
	}
	memcpy (data, urltext, len);
	data[len] = 0;

	if (data[len - 1] == '.')	/* chop trailing dot */
	{
		len--;
		data[len] = 0;
	}
	/* chop trailing ) but only if there's no counterpart */
	if (data[len - 1] == ')' && strchr (data, '(') == NULL)
	{
		data[len - 1] = 0;
	}

	if (prefs.hex_url_logging)
	{
		url_save_node (data);
	}

	/* the URL is saved already, only continue if we need the URL grabber too */
	if (!prefs.hex_url_grabber)
	{
		free (data);
		return;
	}

	if (!url_tree)
	{
		url_tree = tree_new ((tree_cmp_func *)strcasecmp, NULL);
		url_btree = g_tree_new ((GCompareFunc)strcasecmp);
	}

	if (url_find (data))
	{
		free (data);
		return;
	}

	size = tree_size (url_tree);
	/* 0 is unlimited */
	if (prefs.hex_url_grabber_limit > 0 && size >= prefs.hex_url_grabber_limit)
	{
		/* the loop is necessary to handle having the limit lowered while
		   HexChat is running */
		size -= prefs.hex_url_grabber_limit;
		for(; size > 0; size--)
		{
			char *pos;

			pos = tree_remove_at_pos (url_tree, 0);
			g_tree_remove (url_btree, pos);
			free (pos);
		}
	}

	tree_append (url_tree, data);
	g_tree_insert (url_btree, data, GINT_TO_POINTER (tree_size (url_tree) - 1));
	fe_url_add (data);
}
Exemple #6
0
/*
 * Get the next item in the tree traversal.
 */
int
tree_next(struct tree *t)
{
	struct dirent *de = NULL;
	int r;

	/* If we're called again after a fatal error, that's an API
	 * violation.  Just crash now. */
	if (t->visit_type == TREE_ERROR_FATAL) {
		const char *msg = "Unable to continue traversing"
		    " directory hierarchy after a fatal error.\n";
		errmsg(msg);
		*(volatile int *)0 = 1; /* Deliberate SEGV; NULL pointer dereference. */
		exit(1); /* In case the SEGV didn't work. */
	}

	/* Handle the startup case by returning the initial entry. */
	if (t->flags & needsReturn) {
		t->flags &= ~needsReturn;
		return (t->visit_type = TREE_REGULAR);
	}

	while (t->stack != NULL) {
		/* If there's an open dir, get the next entry from there. */
		while (t->d != NULL) {
			errno = 0;
			de = readdir(t->d);
			if (de == NULL) {
				if (errno) {
					/* If readdir fails, we're screwed. */
					closedir(t->d);
					t->d = NULL;
					t->visit_type = TREE_ERROR_FATAL;
					return (t->visit_type);
				}
				/* Reached end of directory. */
				closedir(t->d);
				t->d = NULL;
			} else if (de->d_name[0] == '.'
			    && de->d_name[1] == '\0') {
				/* Skip '.' */
			} else if (de->d_name[0] == '.'
			    && de->d_name[1] == '.'
			    && de->d_name[2] == '\0') {
				/* Skip '..' */
			} else {
				/*
				 * Append the path to the current path
				 * and return it.
				 */
				tree_append(t, de->d_name, D_NAMELEN(de));
				t->flags &= ~hasLstat;
				t->flags &= ~hasStat;
				return (t->visit_type = TREE_REGULAR);
			}
		}

		/* If the current dir needs to be visited, set it up. */
		if (t->stack->flags & needsPreVisit) {
			t->current = t->stack;
			tree_append(t, t->stack->name, strlen(t->stack->name));
			t->stack->flags &= ~needsPreVisit;
			/* If it is a link, set up fd for the ascent. */
			if (t->stack->flags & isDirLink) {
#ifdef HAVE_FCHDIR
				t->stack->fd = open(".", O_RDONLY);
#elif defined(_WIN32) && !defined(__CYGWIN__)
				t->stack->fullpath = getcwd(NULL, 0);
#endif
				t->openCount++;
				if (t->openCount > t->maxOpenCount)
					t->maxOpenCount = t->openCount;
			}
			t->dirname_length = t->path_length;
			if (chdir(t->stack->name) != 0) {
				/* chdir() failed; return error */
				tree_pop(t);
				t->tree_errno = errno;
				return (t->visit_type = TREE_ERROR_DIR);
			}
			t->depth++;
			t->d = opendir(".");
			if (t->d == NULL) {
				r = tree_ascend(t); /* Undo "chdir" */
				tree_pop(t);
				t->tree_errno = errno;
				t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
				return (t->visit_type);
			}
			t->flags &= ~hasLstat;
			t->flags &= ~hasStat;
			t->basename = ".";

			/* Figure out where we are. */
			if (getcwd(t->realpath, PATH_MAX) != NULL) {
				t->realpath_dirname_length =
				    strlen(t->realpath);
				if (t->realpath[0] == '/' &&
				    t->realpath[1] == '\0')
					t->realpath_dirname_length = 0;
				t->realpath_valid = 1;
			} else {
				t->realpath_valid = 0;
			}

			return (t->visit_type = TREE_POSTDESCENT);
		}

		/* We've done everything necessary for the top stack entry. */
		if (t->stack->flags & needsPostVisit) {
			r = tree_ascend(t);
			tree_pop(t);
			t->flags &= ~hasLstat;
			t->flags &= ~hasStat;
			t->visit_type = r != 0 ? r : TREE_POSTASCENT;
			return (t->visit_type);
		}
	}
	return (t->visit_type = 0);
}
Exemple #7
0
static tree_ptr tree_new_unary(fun_ptr fun, tree_ptr x) {
	tree_ptr t = tree_new_funcall();
	tree_append(t, x);
	tree_set_fun(t, tree_new_fun(fun));
	return t;
}
Exemple #8
0
/*
 * Get the next item in the tree traversal.
 */
int
tree_next(struct tree *t)
{
	struct dirent *de = NULL;

	/* Handle the startup case by returning the initial entry. */
	if (t->flags & needsReturn) {
		t->flags &= ~needsReturn;
		return (1);
	}

	while (t->stack != NULL) {
		/* If there's an open dir, get the next entry from there. */
		while (t->d != NULL) {
			de = readdir(t->d);
			if (de == NULL) {
				closedir(t->d);
				t->d = NULL;
			} else if (de->d_name[0] == '.'
			    && de->d_name[1] == '\0') {
				/* Skip '.' */
			} else if (de->d_name[0] == '.'
			    && de->d_name[1] == '.'
			    && de->d_name[2] == '\0') {
				/* Skip '..' */
			} else {
				/*
				 * Append the path to the current path
				 * and return it.
				 */
				tree_append(t, de->d_name, D_NAMELEN(de));
				t->flags &= ~hasLstat;
				t->flags &= ~hasStat;
				return (1);
			}
		}

		/* If the current dir needs to be traversed, set it up. */
		if (t->stack->flags & needsTraversal) {
			tree_append(t, t->stack->name, strlen(t->stack->name));
			t->stack->flags &= ~needsTraversal;
			/* If it is a link, set up fd for the ascent. */
			if (t->stack->flags & isDirLink) {
				t->stack->fd = open(".", O_RDONLY);
				t->openCount++;
				if (t->openCount > t->maxOpenCount)
					t->maxOpenCount = t->openCount;
			}
			if (chdir(t->stack->name) == 0) {
				t->depth++;
				t->dirname_length = t->path_length;
				t->d = opendir(".");
			} else
				tree_pop(t);
			continue;
		}

		/* We've done everything necessary for the top stack entry. */
		tree_ascend(t);
		tree_pop(t);
	}
	return (0);
}
Exemple #9
0
/*
 * Get the next item in the tree traversal.
 */
int
tree_next(struct tree *t)
{
	struct dirent *de = NULL;

	/* Handle the startup case by returning the initial entry. */
	if (t->flags & needsReturn) {
		t->flags &= ~needsReturn;
		return (t->visit_type = TREE_REGULAR);
	}

	while (t->stack != NULL) {
		/* If there's an open dir, get the next entry from there. */
		while (t->d != NULL) {
			de = readdir(t->d);
			if (de == NULL) {
				closedir(t->d);
				t->d = NULL;
			} else if (de->d_name[0] == '.'
			    && de->d_name[1] == '\0') {
				/* Skip '.' */
			} else if (de->d_name[0] == '.'
			    && de->d_name[1] == '.'
			    && de->d_name[2] == '\0') {
				/* Skip '..' */
			} else {
				/*
				 * Append the path to the current path
				 * and return it.
				 */
				tree_append(t, de->d_name, D_NAMELEN(de));
				t->flags &= ~hasLstat;
				t->flags &= ~hasStat;
				return (t->visit_type = TREE_REGULAR);
			}
		}

		/* If the current dir needs to be visited, set it up. */
		if (t->stack->flags & needsPreVisit) {
			t->current = t->stack;
			tree_append(t, t->stack->name, strlen(t->stack->name));
			t->stack->flags &= ~needsPreVisit;
			/* If it is a link, set up fd for the ascent. */
			if (t->stack->flags & isDirLink) {
				t->stack->fd = open(".", O_RDONLY);
				t->openCount++;
				if (t->openCount > t->maxOpenCount)
					t->maxOpenCount = t->openCount;
			}
			t->dirname_length = t->path_length;
			if (chdir(t->stack->name) != 0) {
				/* chdir() failed; return error */
				tree_pop(t);
				t->tree_errno = errno;
				return (t->visit_type = TREE_ERROR_DIR);
			}
			t->depth++;
			t->d = opendir(".");
			if (t->d == NULL) {
				tree_ascend(t); /* Undo "chdir" */
				tree_pop(t);
				t->tree_errno = errno;
				return (t->visit_type = TREE_ERROR_DIR);
			}
			t->flags &= ~hasLstat;
			t->flags &= ~hasStat;
			t->basename = ".";
			return (t->visit_type = TREE_POSTDESCENT);
		}

		/* We've done everything necessary for the top stack entry. */
		if (t->stack->flags & needsPostVisit) {
			tree_ascend(t);
			tree_pop(t);
			t->flags &= ~hasLstat;
			t->flags &= ~hasStat;
			return (t->visit_type = TREE_POSTASCENT);
		}
	}
	return (t->visit_type = 0);
}