Esempio n. 1
0
/**
 * Search executable within the user's PATH.
 *
 * @return full path if found, NULL otherwise.
 * The returned string is allocated with halloc().
 */
char *
file_locate_from_path(const char *argv0)
{
	static bool already_done;
	char *path;
	char *tok;
	char filepath[MAX_PATH_LEN + 1];
	char *result = NULL;
	char *ext = "";

	if (is_running_on_mingw() && !is_strsuffix(argv0, (size_t) -1, ".exe")) {
		ext = ".exe";
	}

	if (filepath_basename(argv0) != argv0) {
		if (!already_done) {
			s_warning("can't locate \"%s\" in PATH: name contains '%c' already",
				argv0,
				strchr(argv0, G_DIR_SEPARATOR) != NULL ? G_DIR_SEPARATOR : '/');
		}
		goto done;
	}

	path = getenv("PATH");
	if (NULL == path) {
		if (!already_done) {
			s_warning("can't locate \"%s\" in PATH: "
				"no such environment variable", argv0);
		}
		goto done;
	}

	path = h_strdup(path);

	tok = strtok(path, G_SEARCHPATH_SEPARATOR_S);
	while (NULL != tok) {
		const char *dir = tok;
		filestat_t buf;

		if ('\0' == *dir)
			dir = ".";
		concat_strings(filepath, sizeof filepath,
			dir, G_DIR_SEPARATOR_S, argv0, ext, NULL);

		if (-1 != stat(filepath, &buf)) {
			if (S_ISREG(buf.st_mode) && -1 != access(filepath, X_OK)) {
				result = h_strdup(filepath);
				break;
			}
		}
		tok = strtok(NULL, G_SEARCHPATH_SEPARATOR_S);
	}

	hfree(path);

done:
	already_done = TRUE;	/* No warning on subsequent invocation */
	return result;
}
Esempio n. 2
0
/**
 * Get the full program path.
 *
 * @return a newly allocated string (through halloc()) that points to the
 * path of the program being run, NULL if we can't compute a suitable path.
 */
char *
file_program_path(const char *argv0)
{
	filestat_t buf;
	char *file = deconstify_char(argv0);
	char filepath[MAX_PATH_LEN + 1];

	if (is_running_on_mingw() && !is_strsuffix(argv0, (size_t) -1, ".exe")) {
		concat_strings(filepath, sizeof filepath, argv0, ".exe", NULL_PTR);
	} else {
		clamp_strcpy(filepath, sizeof filepath, argv0);
	}

	if (-1 == stat(filepath, &buf)) {
		int saved_errno = errno;
		file = file_locate_from_path(argv0);
		if (NULL == file) {
			errno = saved_errno;
			s_warning("%s(): could not stat() \"%s\": %m", G_STRFUNC, filepath);
			return NULL;
		}
	}

	if (file != NULL && file != argv0)
		return file;		/* Allocated by file_locate_from_path() */

	return h_strdup(filepath);
}
Esempio n. 3
0
G_GNUC_COLD void
statusbar_gui_init(void)
{
    GtkStatusbar *sb;

    sb = statusbar_get();
	statusbar_set_shadow_type(GTK_STATUSBAR(sb), GTK_SHADOW_ETCHED_IN);

	scid_bottom = gtk_statusbar_get_context_id(sb, "default");
	scid_hostsfile = gtk_statusbar_get_context_id(sb, "reading hosts file");
	scid_queue_freezed = gtk_statusbar_get_context_id(sb, "queue freezed");
   	scid_info = gtk_statusbar_get_context_id(sb, "information");
    scid_ip_changed = gtk_statusbar_get_context_id(sb, "ip changed");
    scid_warn = gtk_statusbar_get_context_id(sb, "warning");

   	/*
	 * This message lies at the bottom of the statusbar, and is never removed,
	 * but to be replaced by an updated message.
	 *
	 * The current string held at the bottom is stored in `statbar_botstr'.
	 * If a new string is pending replacement in `statbar_botstr_new', then
	 * it will replace the current one when the last timeout for pushed
	 * messages expires, at which time we'll know the bottom message is shown.
	 *		--RAM, 27/06/2002
	 */

	statbar_botstr = h_strdup(product_get_website());
	statusbar_gui_push(SB_MESSAGE, scid_bottom, 0, "%s", statbar_botstr);

	main_gui_add_timer(statusbar_gui_clear_timeouts);
}
Esempio n. 4
0
static SmProp *make_string_list_propv_full(int num_vals, const char *name,
        char const * const *values, const char *prop_type)
{
    int n;
    SmProp *prop = malloc(sizeof(SmProp));

    prop->name = h_strdup(name);
    prop->type = h_strdup(prop_type);
    prop->num_vals = num_vals;
    prop->vals = malloc(sizeof(SmPropValue) * num_vals);
    for (n = 0; n < num_vals; ++n)
    {
        fill_in_prop_val(prop->vals + n, values[n]);
    }
    return prop;
}
Esempio n. 5
0
/**
 * @return NULL on error, a newly allocated string via halloc() otherwise.
 */
static char *
ghc_get_next(void)
{
	struct ghc *ghc;
	char *url;
	time_t now;

	g_return_val_if_fail(ghc_list, NULL);

	now = tm_time();
	ghc = list_head(ghc_list);
	if (NULL == ghc)
		return NULL;

	/*
	 * Wait GHC_RETRY_AFTER secs before contacting the GHC again.
	 */

	if (ghc->stamp && delta_time(now, ghc->stamp) < GHC_RETRY_AFTER)
		return NULL;

	ghc->stamp = now;
	url = h_strdup(ghc->url);

	if (ghc->used < GHC_MAX_ATTEMPTS) {
		ghc->used++;
		list_moveto_tail(ghc_list, ghc);
	} else {
		list_remove(ghc_list, ghc);
		ghc_free_null(&ghc);
	}

	return url;
}
Esempio n. 6
0
/**
 * Creates a copy with the given pathname with the basename cut off. A slash
 * is always considered a separator but G_DIR_SEPARATOR is considered as
 * well. Thus "/whatever/blah\\yadda" returns "/whatever/blah" if G_DIR_SEPARATOR
 * is a backslash, otherwise "/whatever" is returned.
 *
 * @return	A newly allocated string holding the given pathname with the
 *			basename cut off. If the string contained no directory separator,
 *			NULL is returned.  The string must be freed via hfree().
 */
char *
filepath_directory(const char *pathname)
{
	const char *sep;
	char *dir;

	sep = filepath_directory_end(pathname, '/');
	if (G_DIR_SEPARATOR != '/') {
		const char *alt;

		alt = filepath_directory_end(pathname, G_DIR_SEPARATOR);
		if (sep && alt) {
			sep = (sep - pathname > alt - pathname) ? sep : alt;
		} else if (alt) {
			sep = alt;
		}
	}
	if (sep == pathname) {
		dir = h_strdup(G_DIR_SEPARATOR_S);
	} else if (sep) {
		dir = h_strndup(pathname, sep - pathname);
	} else {
		dir = NULL;
	}
	return dir;
}
Esempio n. 7
0
/**
 * Add header line to the `headers' hash for specified field name.
 * A private copy of the `field' name and of the `text' data is made.
 */
static void
add_header(header_t *o, const char *field, const char *text)
{
	htable_t *ht;
	str_t *v;

	header_check(o);

	ht = header_get_table(o);
	v = htable_lookup(ht, field);
	if (v) {
		/*
		 * Header already exists, according to RFC2616 we need to append
		 * the value, comma-separated.
		 */

		STR_CAT(v, ", ");
		str_cat(v, text);

	} else {
		char *key;

		/*
		 * Create a new header entry in the hash table.
		 */

		key = h_strdup(field);
		v = str_new_from(text);
		htable_insert(ht, key, v);
	}
}
Esempio n. 8
0
/**
 * Allocate a new descriptor for managing large keys and values.
 */
DBMBIG *
big_alloc(const char *datname, int flags, int mode)
{
	DBMBIG *dbg;
	struct datfile *file;

	WALLOC0(dbg);
	dbg->fd = -1;
	dbg->bitbno = -1;

	WALLOC(file);
	file->datname = h_strdup(datname);
	file->flags = flags;
	file->mode = mode;
	dbg->file = file;

	/*
	 * If the .dat file exists and O_TRUNC was given in the flags and the
	 * database is opened for writing, then the database is re-initialized:
	 * unlink the .dat file, which will be re-created on-demand.
	 */

	if ((flags & (O_RDWR | O_WRONLY)) && (flags & O_TRUNC)) {
		unlink(datname);
	}

	return dbg;
}
Esempio n. 9
0
/**
 * Create the string representation of the push-proxies, for inclusion
 * in the push:// URL.
 *
 * @return An empty string (""), if the list is empty or the address NULL;
 * otherwise a colon-separated list of IP:port, beginning with a colon. The
 * string is newly allocated via halloc().
 */
char *
magnet_proxies_to_string(const sequence_t *proxies)
{
	if (NULL == proxies)
		return h_strdup("");
	
	return proxy_sequence_to_string(proxies);
}
Esempio n. 10
0
/**
 * Append line of text to given header field.
 * A private copy of the data is made.
 */
static void
hfield_append(header_field_t *h, const char *text)
{
	header_field_check(h);

	if (!h->lines) {
		h->lines = slist_new();
	}
	slist_append(h->lines, h_strdup(text));
}
Esempio n. 11
0
static inline void
tls_log_function(int level, const char *text)
{
    if (GNET_PROPERTY(tls_debug) > UNSIGNED(level)) {
        char *str = h_strdup(text);
        strchomp(str, 0);
        g_debug("TLS(%d): %s", level, str);
        hfree(str);
    }
}
Esempio n. 12
0
void
statusbar_gui_set_default(const char *format, ...)
{
    static gchar buf[1024];
    va_list args;

    va_start(args, format);

    HFREE_NULL(statbar_botstr_new);

    if (format != NULL) {
        str_vbprintf(buf, sizeof(buf), format, args);
        statbar_botstr_new = h_strdup(buf);
    } else {
        statbar_botstr_new = h_strdup(product_get_website());
    }

    va_end(args);
}
Esempio n. 13
0
/**
 * Create a new empty header field, whose name is `name'.
 * A private copy of `name' is done.
 */
static header_field_t *
hfield_make(const char *name)
{
	header_field_t *h;

	WALLOC0(h);
	h->magic = HEADER_FIELD_MAGIC;
	h->name = h_strdup(name);

	return h;
}
Esempio n. 14
0
/**
 * Allocate a new attribute key/value.
 *
 * @param uri		the namespace URI (may be NULL)
 * @param local		the local name
 * @param value		the attribute value (copied)
 *
 * @return a new attribute key/value.
 */
static struct xattr *
xattr_alloc(const char *uri, const char *local, const char *value)
{
	struct xattr *xa;

	WALLOC(xa);
	xa->uri = (NULL == uri) ? NULL : atom_str_get(uri);
	xa->local = atom_str_get(local);
	xa->value = h_strdup(value);

	return xa;
}
Esempio n. 15
0
/**
 * @return NULL on error, a newly allocated string via halloc() otherwise.
 */
static char *
uhc_get_next(void)
{
	struct uhc *uhc;
	char *host;
	time_t now;
	size_t n;

	g_return_val_if_fail(uhc_list, NULL);

	now = tm_time();

	n = hash_list_count(uhc_list);
	if (0 == n)
		return NULL;

	/*
	 * Wait UHC_RETRY_AFTER secs before contacting the UHC again.
	 * Can't be too long because the UDP reply may get lost if the
	 * requesting host already has a saturated b/w.
	 * If we come here, it's because we're lacking hosts for establishing
	 * a Gnutella connection, after we exhausted our caches.
	 */

	while (n-- != 0) {
		uhc = hash_list_head(uhc_list);

		g_assert(uhc != NULL);	/* We computed count on entry */

		if (delta_time(now, uhc->stamp) >= UHC_RETRY_AFTER)
			goto found;

		hash_list_moveto_tail(uhc_list, uhc);
	}

	return NULL;

found:
	uhc->stamp = now;
	host = h_strdup(uhc->host);

	if (uhc->used < UHC_MAX_ATTEMPTS) {
		uhc->used++;
		hash_list_moveto_tail(uhc_list, uhc);
	} else {
		hash_list_remove(uhc_list, uhc);
		uhc_free(&uhc);
	}

	return host;
}
Esempio n. 16
0
/**
 * Create a new comment node, inserted under parent node as the last child.
 *
 * @param parent		the parent node (NULL creates a standalone node
 * @param text			the comment text, copied ("--" will be emitted as "- -")
 */
xnode_t *
xnode_new_comment(xnode_t *parent, const char *text)
{
	xnode_t *xn;

	g_assert(text != NULL);

	xn = xnode_new(XNODE_T_COMMENT);
	xn->u.c.text = h_strdup(text);

	if (parent != NULL)
		xnode_add_child(parent, xn);

	return xn;
}
Esempio n. 17
0
/**
 * Parse options.
 * @return halloc()-ed option string, or NULL on error.
 */
static char *
ctl_parse_options(struct ctl_string *s)
{
	struct ctl_tok *tok = ctl_next_token(s);
	char *opt = NULL;

	if (CTL_TOK_ID != tok->type) {
		ctl_error(s, tok, "country options");
	} else {
		opt = h_strdup(tok->val.s);
	}

	ctl_token_free_null(&tok);
	return opt;
}
Esempio n. 18
0
/**
 * Create an absolute path.
 * The resulting string must be freed with hfree().
 */
char *
absolute_pathname(const char *file)
{
	g_assert(file != NULL);
	
	if (is_absolute_path(file)) {
		return h_strdup(file);
	} else if ('\0' == file[0]) {
		return NULL;
	} else {
		char buf[4096], *ret;

		ret = getcwd(buf, sizeof buf);
		return ret ? make_pathname(ret, file) : NULL;
	}
}
Esempio n. 19
0
/**
 * Create a new text node, inserted under parent node as the last child..
 *
 * When created as verbatim, any '&' character is left as-is, otherwise they
 * are escaped.  All '<' and '>' are escaped regardless.
 *
 * @param parent		the parent node (NULL creates a standalone node
 * @param text			the text
 * @param verbatim		whether text is to be emitted verbatim or escaped
 */
xnode_t *
xnode_new_text(xnode_t *parent, const char *text, bool verbatim)
{
	xnode_t *xn;

	g_assert(text != NULL);

	xn = xnode_new(XNODE_T_TEXT);
	xn->u.t.text = h_strdup(text);
	xn->u.t.asis = booleanize(verbatim);

	if (parent != NULL)
		xnode_add_child(parent, xn);

	return xn;
}
Esempio n. 20
0
static gboolean
search_by_regex(GtkTreeModel *model, gint column, const gchar *key,
	GtkTreeIter *iter, gpointer unused_data)
{
	static const gboolean found = FALSE;
	static gchar *last_key;	/* This will be "leaked" on exit */
	static regex_t re;		/* The last regex will be "leaked" on exit */
	gint ret;

	g_return_val_if_fail(model, !found);
	g_return_val_if_fail(column >= 0, !found);
	g_return_val_if_fail((guint) column < SEARCH_RESULTS_VISIBLE_COLUMNS,
		!found);
	g_return_val_if_fail(key, !found);
	g_return_val_if_fail(iter, !found);
	(void) unused_data;

	if (!last_key || 0 != strcmp(last_key, key)) {
		if (last_key) {
			regfree(&re);
			HFREE_NULL(last_key);
		}

		ret = regcomp(&re, key, REG_EXTENDED | REG_NOSUB | REG_ICASE);
		g_return_val_if_fail(0 == ret, !found);

		last_key = h_strdup(key);
	}

	{
		const struct result_data *rd;
		
		rd = get_result_data(model, iter);
		g_return_val_if_fail(NULL != rd, !found);
		g_return_val_if_fail(NULL != rd->record->utf8_name, !found);

		ret = regexec(&re, rd->record->utf8_name, 0, NULL, 0);
	}

	return 0 == ret ? found : !found;
}
Esempio n. 21
0
char *
bitzi_gui_get_metadata(const bitzi_data_t *data)
{
	g_assert(data != NULL);

	/*
	 * Build string
	 */

	if (
		data->judgment == BITZI_FJ_FAILURE ||
		data->judgment == BITZI_FJ_WRONG_FILESIZE
	) {
		return h_strdup(bitzi_fj_to_string(data->judgment));
	} else if (data->mime_type) {
		if (data->mime_desc) {
			return h_strdup_printf("%s (%1.1f): %s (%s)%s%s",
					bitzi_fj_to_string(data->judgment),
					data->goodness,
					data->mime_type,
					data->mime_desc,
					data->duration != 0 ? "; " : "",
					data->duration != 0 ? short_time(data->duration) : "");
		} else {
			return h_strdup_printf("%s (%1.1f): %s%s%s",
					bitzi_fj_to_string(data->judgment),
					data->goodness,
					data->mime_type,
					data->duration != 0 ? "; " : "",
					data->duration != 0 ? short_time(data->duration) : "");
		}
	} else if (data->judgment != BITZI_FJ_UNKNOWN) {
		return h_strdup_printf("%s (%1.1f): %s",
				bitzi_fj_to_string(data->judgment),
				data->goodness,
				_("No other data"));
	}

	return NULL;
}
Esempio n. 22
0
/**
 * Retrieve more hosts from web cache, asynchronously.
 */
void
gwc_get_hosts(void)
{
    void *handle;
    char *url;
    const char *msg;
    static time_t last_called = 0;
    time_t now = tm_time();

    /*
     * Make sure we don't probe more than one webcache at a time.
     * Ancient versions should rely on their hostcache to be connected.
     */

    if (gwc_get_running || GNET_PROPERTY(ancient_version))
        return;

    /*
     * This routine is called each time we run out of hosts to try in our
     * cache, so we have absolutely no guarantee about the frequency at which
     * it will be called.
     *
     * Force picking up a new cache (well, randomly) if we were called less
     * than an hour ago.  Note that we don't remember whether it was THIS
     * particular current cache that was accessed last time we were called.
     * We only care about the calling frequency, and bet on the high number
     * of available web caches and the random selection process to behave.
     * properly.
     *		--RAM, 24/11/2003
     */

    if (delta_time(now, last_called) < REUSE_PERIOD)
        gwc_clear_current_url(FALSE);

    last_called = now;

    if (!gwc_check_current_url())
        return;

    /*
     * Give some GUI feedback.
     */

    msg = str_smsg(_("Connecting to web cache %s"), gwc_current_url);
    gcu_statusbar_message(msg);

    if (GNET_PROPERTY(bootstrap_debug))
        g_message("BOOT connecting to web cache %s", gwc_current_url);

    /*
     * Launch the asynchronous request and attach parsing information.
     */

    msg = str_smsg("%s?get=1&net=gnutella2&%s", gwc_current_url, CLIENT_INFO);
    url = h_strdup(msg);

    if (GNET_PROPERTY(bootstrap_debug) > 2)
        g_message("GWC host request: %s", url);

    handle = http_async_get(url, NULL, gwc_host_data_ind, gwc_host_error_ind);

    if (NULL == handle) {
        g_warning("could not launch a \"GET %s\" request: %s",
                  url, http_async_strerror(http_async_errno));
        gwc_clear_current_url(TRUE);
    } else {
        http_async_set_op_gotreply(handle, gwc_got_reply);
        gwc_parse_context_set(handle, MAX_IP_LINES);
        gwc_get_running = TRUE;
    }

    hfree(url);
}
Esempio n. 23
0
/**
 * Load spam database from the supplied FILE.
 *
 * The current file format is as follows:
 *
 * # Comment
 * SHA1 <SHA-1>
 * ADDED <date>
 * END
 *
 * @returns the amount of entries loaded or -1 on failure.
 */
static G_GNUC_COLD gulong
spam_load(FILE *f)
{
	static const struct spam_item zero_item;
	struct spam_item item;
	char line[1024];
	guint line_no = 0;
	bit_array_t tag_used[BIT_ARRAY_SIZE(NUM_SPAM_TAGS)];
	gulong item_count = 0;

	g_assert(f);

	/* Reset state */
	item = zero_item;
	bit_array_init(tag_used, NUM_SPAM_TAGS);

	while (fgets(line, sizeof line, f)) {
		const char *tag_name, *value;
		char *sp, *nl;
		spam_tag_t tag;

		line_no++;

		nl = strchr(line, '\n');
		if (!nl) {
			/*
			 * If the line is too long or unterminated the file is either
			 * corrupt or was manually edited without respecting the
			 * exact format. If we continued, we would read from the
			 * middle of a line which could be the filename or ID.
			 */
			g_warning("spam_load(): "
				"line too long or missing newline in line %u",
				line_no);
			break;
		}
		*nl = '\0';

		/* Skip comments and empty lines */
		if (*line == '#' || *line == '\0')
			continue;

		sp = strchr(line, ' ');
		if (sp) {
			*sp = '\0';
			value = &sp[1];
		} else {
			value = strchr(line, '\0');
		}
		tag_name = line;

		tag = spam_string_to_tag(tag_name);
		g_assert(UNSIGNED(tag) < UNSIGNED(NUM_SPAM_TAGS));

		if (SPAM_TAG_UNKNOWN != tag && !bit_array_flip(tag_used, tag)) {
			g_warning("spam_load(): duplicate tag \"%s\" in entry in line %u",
				tag_name, line_no);
			continue;
		}
		
		switch (tag) {
		case SPAM_TAG_ADDED:
			{
				time_t t;
				
				t = date2time(value, tm_time());
				if ((time_t) -1 == t) {
					item.damaged = TRUE;
				}
			}
			break;
			
		case SPAM_TAG_SHA1:
			{
				if (strlen(value) != SHA1_BASE32_SIZE) {
					item.damaged = TRUE;
					g_warning("spam_load(): SHA-1 has wrong length.");
				} else {
					const struct sha1 *raw;

					raw = base32_sha1(value);
					if (raw)
						item.sha1 = *raw;
					else
						item.damaged = TRUE;
				}
			}
			break;

		case SPAM_TAG_NAME:
			{
				if ('\0' == value[0]) {
					item.damaged = TRUE;
					g_warning("spam_load(): Missing filename pattern.");
				} else if (!utf8_is_valid_string(value)) {
					item.damaged = TRUE;
					g_warning("spam_load(): Filename pattern is not UTF-8.");
				} else {
					item.name = h_strdup(value);
				}
			}
			break;

		case SPAM_TAG_SIZE:
			{
				const char *endptr;
				guint64 u;
				int error;
					
				u = parse_uint64(value, &endptr, 10, &error);
				if (error) {
					item.damaged = TRUE;
					g_warning("spam_load(): Cannot parse SIZE: %s", value);
				} else {
					item.min_size = u;
					item.max_size = u;

					if ('-' == endptr[0]) {
						u = parse_uint64(&endptr[1], &endptr, 10, &error);
						if (error) {
							item.damaged = TRUE;
							g_warning("spam_load(): Cannot parse SIZE: %s",
								value);
						}
						if (u < item.min_size) {
							item.damaged = TRUE;
							g_warning("spam_load(): "
								"Maximum size below minimum size");
						} else {
							item.max_size = u;
						}
					}
				}
			}
			break;

		case SPAM_TAG_END:
			if (
				!bit_array_get(tag_used, SPAM_TAG_SHA1) &&
				!bit_array_get(tag_used, SPAM_TAG_NAME)
			) {
				g_warning("spam_load(): missing SHA1 or NAME tag");
				item.damaged = TRUE;
			}
			if (!bit_array_get(tag_used, SPAM_TAG_ADDED)) {
				g_warning("spam_load(): missing ADDED tag");
				item.damaged = TRUE;
			}
			item.done = TRUE;
			break;

		case SPAM_TAG_UNKNOWN:
			/* Ignore */
			break;
			
		case NUM_SPAM_TAGS:
			g_assert_not_reached();
			break;
		}

		if (item.done && !item.damaged) {
			if (bit_array_get(tag_used, SPAM_TAG_SHA1)) {
				spam_sha1_add(&item.sha1);
				item_count++;
			}
			if (bit_array_get(tag_used, SPAM_TAG_NAME)) {
				if (!bit_array_get(tag_used, SPAM_TAG_SIZE)) {
					item.min_size = 0;
					item.max_size = MAX_INT_VAL(filesize_t);
				}
				if (
					spam_add_name_and_size(item.name,
						item.min_size, item.max_size)
				) {
					item.damaged = TRUE;	
				} else {
					item_count++;
				}
			}
		}

		if (item.damaged) {
			g_warning("Damaged spam entry in line %u: "
				"tag_name=\"%s\", value=\"%s\"",
				line_no, tag_name, value);
		}

		if (item.done) {
			/* Reset state */
			HFREE_NULL(item.name);
			item = zero_item;
			bit_array_clear_range(tag_used, 0, NUM_SPAM_TAGS - 1U);
		}
	}

	spam_sha1_sync();

	return item_count;
}
Esempio n. 24
0
/**
 * Search executable within the user's PATH.
 *
 * @return full path if found, NULL otherwise.
 * The returned string is allocated with halloc().
 */
char *
file_locate_from_path(const char *argv0)
{
	static bool already_done;
	char *path;
	char *tok;
	char filepath[MAX_PATH_LEN + 1];
	char *result = NULL;
	char *ext = "";

	if (is_running_on_mingw() && !is_strsuffix(argv0, (size_t) -1, ".exe")) {
		ext = ".exe";
	}

	if (filepath_basename(argv0) != argv0) {
		if (!already_done) {
			s_warning("can't locate \"%s\" in PATH: name contains '%c' already",
				argv0,
				strchr(argv0, G_DIR_SEPARATOR) != NULL ? G_DIR_SEPARATOR : '/');
		}
		result = h_strdup(argv0);
		goto done;
	}

	path = getenv("PATH");
	if (NULL == path) {
		if (!already_done) {
			s_warning("can't locate \"%s\" in PATH: "
				"no such environment variable", argv0);
		}
		goto done;
	}

	/*
	 * On Windows, we need to implicitly add "." to the path if not already
	 * present -- this is done by appending a separator and a dot, not by
	 * checking whether "." is already part of the path.
	 *
	 * The reason is that "." is implied, and also because one may omit the
	 * ".exe" extension when launching a program.  This means checks done
	 * in crash_init() for instance to see whether the file listed in
	 * argv[0] exists and which do not account for a missing ".exe" will
	 * attempt to locate the program in the PATH to get a full name and will
	 * fail if we do not add ".".
	 *
	 * On UNIX this cannot happen because there is no hidden extension and
	 * the "." is never made part of the PATH implictly.
	 *
	 *		--RAM, 2015-12-06
	 */

	if (is_running_on_mingw())
		path = h_strdup_printf("%s%c.", path, *G_SEARCHPATH_SEPARATOR_S);
	else
		path = h_strdup(path);

	path = h_strdup(path);

	/* FIXME: strtok() is not thread-safe --RAM, 2015-12-06 */

	tok = strtok(path, G_SEARCHPATH_SEPARATOR_S);
	while (NULL != tok) {
		const char *dir = tok;
		filestat_t buf;

		if ('\0' == *dir)
			dir = ".";
		concat_strings(filepath, sizeof filepath,
			dir, G_DIR_SEPARATOR_S, argv0, ext, NULL_PTR);

		if (-1 != stat(filepath, &buf)) {
			if (S_ISREG(buf.st_mode) && -1 != access(filepath, X_OK)) {
				result = h_strdup(filepath);
				break;
			}
		}
		tok = strtok(NULL, G_SEARCHPATH_SEPARATOR_S);
	}

	hfree(path);

done:
	already_done = TRUE;	/* No warning on subsequent invocation */
	return result;
}
int
csm_update_service(csm_service_list *services, csm_service *s, csm_ctx *ctx, int validate)
{
  if (validate)
    CHECK(csm_validate_fields(ctx, s), "Service doesn't validate");
//   assert(s->lifetime);
  long lifetime = s->lifetime;
  
  // check if service is attached to service_list
  CHECK(co_list_contains(services->services, (co_obj_t*)container_of(s, co_service_t, service)),
	"Cannot update service not in service list");
  
  // detach s->fields from s and attach to services->service_fields
  if (!co_list_contains(services->service_fields, s->fields)) {
    co_obj_t *fields = s->fields;
    hattach(fields, NULL);
    CHECK(co_list_append(services->service_fields, fields),
	  "Failed to add service fields to service list");
  }
  
  /* Create or verify signature */
  if (s->signature)
    CHECK(csm_verify_signature(s),"Invalid signature");
  else
    CHECK(csm_create_signature(s),"Failed to create signature");
  
  /* Set expiration timer on the service */
#ifdef USE_UCI
  long def_lifetime = default_lifetime();
  if (lifetime == 0 || (def_lifetime < lifetime && def_lifetime > 0))
    lifetime = def_lifetime;
#endif
  if (lifetime > 0) {
    struct timeval tv;
    avahi_elapse_time(&tv, 1000*lifetime, 0);
    time_t current_time = time(NULL);
    // create expiration event for service
    s->timeout = avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll),
								       &tv,
								       _csm_expire_service,
								       s);
    /* Convert lifetime period into timestamp */
    if (current_time != ((time_t)-1)) {
      struct tm *timestr = localtime(&current_time);
      timestr->tm_sec += lifetime;
      current_time = mktime(timestr);
      char *c_time_string = ctime(&current_time);
      if (c_time_string) {
	c_time_string[strlen(c_time_string)-1] = '\0'; /* ctime adds \n to end of time string; remove it */
	s->expiration = h_strdup(c_time_string);
	CHECK_MEM(s->expiration);
	service_attach(s->expiration, s);
      }
    }
  }
  
  // finalize service by running update handlers
  csm_services_commit(services);
  
  return 1;
error:
  return 0;
}
Esempio n. 26
0
/**
 * Analyze the data we have received, and give each line to the supplied
 * dispatcher callback `cb', after having chomped it.  On EOF, call `eof'
 * to finalize parsing.
 */
static void
parse_dispatch_lines(void *handle, const char *buf, size_t len,
		parse_dispatch_t cb, parse_eof_t eofile)
{
	struct parse_context *ctx;
	const char *p = buf;
	size_t remain = len;

	/*
	 * Retrieve parsing context, stored as an opaque attribute in the
	 * asynchronous HTTP request handle.
	 */

	ctx = http_async_get_opaque(handle);

	g_assert(ctx->handle == handle);	/* Make sure it's the right context */

	if (len == 0) {						/* Nothing to parse, got EOF */
		if (eofile != NULL)
			(*eofile)(ctx);
		return;
	}

	/*
	 * Read a line at a time.
	 */

	for (;;) {
		char *line;
		bool error;
		size_t line_len;
		size_t parsed;

		switch (getline_read(ctx->getline, p, remain, &parsed)) {
		case READ_OVERFLOW:
			http_async_cancel(handle);
			ghc_connecting = FALSE;
			return;
		case READ_DONE:
			p += parsed;
			remain -= parsed;
			break;
		case READ_MORE:			/* ok, but needs more data */
			g_assert(parsed == remain);
			return;
		}

		/*
		 * We come here everytime we get a full line.
		 */

		line = h_strdup(getline_str(ctx->getline));
		line_len = getline_length(ctx->getline);
		line_len = strchomp(line, line_len);

		error = !(*cb)(ctx, line, line_len); /* An ERROR was reported */
		HFREE_NULL(line);

		if (error) {
			ghc_ctx.ha = NULL;
			ghc_connecting = FALSE;
			return;
		}

		/*
		 * Make sure we don't process lines ad infinitum.
		 */

		ctx->lines++;
		if (ctx->lines >= ctx->maxlines) {
			const char *req;
			const char *url = http_async_info(handle, &req, NULL, NULL, NULL);
			if (GNET_PROPERTY(bootstrap_debug))
				g_warning("BOOT GHC got %u+ lines from \"%s %s\", stopping",
					ctx->lines, req, url);
			http_async_close(handle);
			ghc_connecting = FALSE;
			return;
		}

		getline_reset(ctx->getline);
	}
}
Esempio n. 27
0
inline static void fill_in_prop_val(SmPropValue *val, const char *s)
{
    val->length = strlen(s);
    val->value = (SmPointer) h_strdup(s);
}
Esempio n. 28
0
/**
 * Creates a valid and sanitized filename from the supplied string. For most
 * Unix-like platforms anything goes but for security reasons, shell meta
 * characters are replaced by harmless characters.
 *
 * @param filename the suggested filename.
 * @param no_spaces if TRUE, spaces are replaced with underscores.
 * @param no_evil if TRUE, "evil" characters are replaced with underscores.
 *
 * @returns a newly allocated string using halloc() or ``filename''
 *			if it was a valid filename already.
 */
char *
filename_sanitize(const char *filename, bool no_spaces, bool no_evil)
{
	const char *p;
	const char *s;
	char *q;

	g_assert(filename);

	/* Almost all evil characters are forbidden on Windows, anyway */
	no_evil |= is_running_on_mingw();

	/* Leading spaces are just confusing */
	p = skip_ascii_spaces(filename);

	/* Make sure the filename isn't too long */
	if (strlen(p) >= FILENAME_MAXBYTES) {
		q = halloc(FILENAME_MAXBYTES);
		filename_shrink(p, q, FILENAME_MAXBYTES);
		s = q;
	} else {
		s = p;
		q = NULL;
	}

	/*
	 * Replace shell meta characters and likely problematic characters.
	 *
	 * Although parentheses are not evil per se, they make it a pain to
	 * copy-n-paste filenames without going through the shell's auto-
	 * completion (which normally does the necessary escaping).
	 *
	 * To keep things "readable", we replace parentheses with brackets.
	 * Although brackets are meaningful for the shells, they are only
	 * interpreted in the presence of "*" or "?", two characters that we
	 * strip already.
	 *		--RAM, 2013-11-03
	 */
	{
		size_t i;
		uchar c;

		for (i = 0; '\0' != (c = s[i]); i++) {
			if (
				c < 32
				|| is_ascii_cntrl(c)
				|| G_DIR_SEPARATOR == c
				|| '/' == c
				|| (0 == i && ('.' == c || '-' == c))
				|| (no_spaces && is_ascii_space(c))
				|| (no_evil && filename_is_evil_char(c))
			) {
				if (!q)
					q = h_strdup(s);
				q[i] = '_';	/* replace undesired char with underscore */
			} else if ('(' == c) {
				if (!q)
					q = h_strdup(s);
				q[i] = '[';
			} else if (')' == c) {
				if (!q)
					q = h_strdup(s);
				q[i] = ']';
			}
		}

		/**
		 * Windows does not like filenames ending with a space or period.
		 */
		while (i-- > 0 && (is_ascii_space(s[i]) || '.' == s[i])) {
			if (!q)
				q = h_strdup(s);
			q[i] = '\0';	/* truncate string */
		}
	}

	if (filename_is_reserved(q ? q : s)) {
		HFREE_NULL(q);
		q = h_strdup("noname");
	}

	if (NULL == q && s != filename)
		q = h_strdup(s);		/* Trimmed leading white space, must copy */

	return q ? q : deconstify_gchar(s);
}
Esempio n. 29
0
/**
 * Make filename prettier, by removing leading "_", making sure the filename
 * does not start with "-" or ".", and stripping consecutive "_" or "_" that
 * surround a punctuation character.
 *
 * Finally, ensure the filename is not completely empty, as this is
 * awkward to manipulate from a shell.
 *
 * @param filename	the filename to beautify
 *
 * @returns a newly allocated string holding the beautified filename, even if
 * it is a mere copy of the original.
 */
char *
filename_beautify(const char *filename)
{
	const char *s;
	char *q;
	uchar c;
	size_t len;
	size_t j = 0;
	static const char punct[] = "_-+=.,<>{}[]";	/* 1st MUST be '_' */
	static const char strip[] = "_-.";
	static const char empty[] = "{empty}";

	g_assert(filename);

	s = filename;
	len = strlen(filename);
	q = halloc(len + 1);		/* Trailing NUL */

	while ((c = *s++)) {
		uchar d;

		/* Beautified filename cannot start with stripped characters */
		if (j == 0) {
			if (NULL == strchr(strip, c))
				q[j++] = c;
			continue;
		}

		g_assert(j > 0);

		d = q[j - 1];		/* Last char we've kept in beautified name */

		/* A "_" followed by a punctuation character, strip the "_" */
		if (d == '_' && NULL != strchr(punct, c)) {
			q[j - 1] = c;
			continue;
		}

		/* A punctuation character followed by "_", ignore that "_" */
		if (NULL != strchr(&punct[1], d) && c == '_')
			continue;

		q[j++] = c;
	}

	g_assert(j <= len);
	q[j] = '\0';

	/* Ensure we have no empty name */
	if (j == 0) {
		HFREE_NULL(q);
		return h_strdup(empty);
	}

	/*
	 * If there was an extension following stripped chars (e.g. "_.ext"),
	 * then the filename kept will become "ext" (we assume a valid extension
	 * cannot contain "escaped" chars).  In which case we will prepend the
	 * string "{empty}." to it.
	 */

	if (NULL == strchr(q, '.') && j < len && '.' == filename[len - j]) {
		char *r = h_strconcat(empty, ".", q, NULL_PTR);
		HFREE_NULL(q);

		return r;
	}

	return q;
}
Esempio n. 30
0
static char *
thex_download_handle_xml(struct thex_download *ctx,
	const char *data, size_t size)
{
	xnode_t *hashtree = NULL, *node;
	char *hashtree_id = NULL;
	bool success = FALSE;
	vxml_parser_t *vp;
	vxml_error_t e;

	if (size <= 0) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH XML record has no data");
		}
		goto finish;
	}

	/*
	 * Parse the XML record.
	 */

	vp = vxml_parser_make("THEX record", VXML_O_STRIP_BLANKS);
	vxml_parser_add_data(vp, data, size);
	e = vxml_parse_tree(vp, &hashtree);
	vxml_parser_free(vp);

	if (VXML_E_OK != e) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_warning("TTH cannot parse XML record: %s", vxml_strerror(e));
			dump_hex(stderr, "XML record", data, size);
		}
		goto finish;
	}

	if (0 != strcmp("hashtree", xnode_element_name(hashtree))) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH couldn't find root hashtree element");
		}
		goto finish;
	}
	
	node = find_element_by_name(hashtree, "file");
	if (node) {
		if (!verify_element(node, "size", filesize_to_string(ctx->filesize)))
			goto finish;
		if (!verify_element(node, "segmentsize", THEX_SEGMENT_SIZE))
			goto finish;
	} else {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH couldn't find hashtree/file element");
		}
		goto finish;
	}

	node = find_element_by_name(hashtree, "digest");
	if (node) {
		if (!verify_element(node, "algorithm", THEX_HASH_ALGO))
			goto finish;
		if (!verify_element(node, "outputsize", THEX_HASH_SIZE))
			goto finish;
	} else {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH couldn't find hashtree/digest element");
		}
    	goto finish;
	}
  
	node = find_element_by_name(hashtree, "serializedtree");
	if (node) {
		const char *value;
		int error;
		
		if (!verify_element(node, "type", THEX_TREE_TYPE))
    		goto finish;

		value = xnode_prop_get(node, "uri");
		if (NULL == value) {
			if (GNET_PROPERTY(tigertree_debug)) {
				g_debug("TTH couldn't find property \"uri\" of node \"%s\"",
					xnode_element_name(node));
			}
			goto finish;
		}
		hashtree_id = h_strdup(value);

		value = xnode_prop_get(node, "depth");
		if (NULL == value) {
			if (GNET_PROPERTY(tigertree_debug)) {
				g_debug("TTH couldn't find property \"depth\" of node \"%s\"",
					xnode_element_name(node));
			}
			goto finish;
		}
		
		ctx->depth = parse_uint16(value, NULL, 10, &error);
		error |= ctx->depth > tt_full_depth(ctx->filesize);
		if (error) {
			ctx->depth = 0;
			g_warning("TTH bad value for \"depth\" of node \"%s\": \"%s\"",
				xnode_element_name(node), value);
		}
		if (error)
			goto finish;
	} else {
		if (GNET_PROPERTY(tigertree_debug))
			g_debug("TTH couldn't find hashtree/serializedtree element");
		goto finish;
	}

	success = TRUE;

finish:
	if (!success)
		HFREE_NULL(hashtree_id);
	xnode_tree_free_null(&hashtree);

	return hashtree_id;
}