return -1;
}
+int
+interruptible_accept(
+ int sock,
+ struct sockaddr *addr,
+ socklen_t *addrlen,
+ gboolean (*prolong)(gpointer data),
+ gpointer prolong_data)
+{
+ SELECT_ARG_TYPE readset;
+ struct timeval tv;
+ int nfound;
+
+ if (sock < 0 || sock >= FD_SETSIZE) {
+ g_debug("interruptible_accept: bad socket %d", sock);
+ return EBADF;
+ }
+
+ memset(&readset, 0, SIZEOF(readset));
+
+ while (1) {
+ if (!prolong(prolong_data)) {
+ errno = 0;
+ return -1;
+ }
+
+ FD_ZERO(&readset);
+ FD_SET(sock, &readset);
+
+ /* try accepting for 1s */
+ memset(&tv, 0, SIZEOF(tv));
+ tv.tv_sec = 1;
+
+ nfound = select(sock+1, &readset, NULL, NULL, &tv);
+ if (nfound < 0) {
+ return -1;
+ } else if (nfound == 0) {
+ continue;
+ } else if (!FD_ISSET(sock, &readset)) {
+ g_debug("interruptible_accept: select malfunction");
+ errno = EBADF;
+ return -1;
+ } else {
+ int rv = accept(sock, addr, addrlen);
+ if (rv < 0 && errno == EAGAIN)
+ continue;
+ return rv;
+ }
+ }
+}
+
/*
* Writes out the entire iovec
*/
result = g_new0(char *, strs->len + 1);
memmove(result, strs->pdata, sizeof(char *) * strs->len);
- g_ptr_array_free(strs, FALSE); /* FALSE => don't free strings */
+ g_ptr_array_free(strs, TRUE); /* TRUE => free pdata, strings are not freed */
g_free(local);
return result;
return ret;
}
+/* Helper for parse_braced_component; this will turn a single element array
+ * matching /^\d+\.\.\d+$/ into a sequence of numbered array elements. */
+static GPtrArray *
+expand_braced_sequence(GPtrArray *arr)
+{
+ char *elt, *p;
+ char *l, *r;
+ int ldigits, rdigits, ndigits;
+ guint64 start, end;
+ gboolean leading_zero;
+
+ /* check whether the element matches the pattern */
+ /* expand last element of the array only */
+ elt = g_ptr_array_index(arr, arr->len-1);
+ ldigits = 0;
+ for (l = p = elt; *p && g_ascii_isdigit(*p); p++)
+ ldigits++;
+ if (ldigits == 0)
+ return arr;
+ if (*(p++) != '.')
+ return arr;
+ if (*(p++) != '.')
+ return arr;
+ rdigits = 0;
+ for (r = p; *p && g_ascii_isdigit(*p); p++)
+ rdigits++;
+ if (rdigits == 0)
+ return arr;
+ if (*p)
+ return arr;
+
+ /* we have a match, so extract start and end */
+ start = g_ascii_strtoull(l, NULL, 10);
+ end = g_ascii_strtoull(r, NULL, 10);
+ leading_zero = *l == '0';
+ ndigits = MAX(ldigits, rdigits);
+ if (start > end)
+ return arr;
+
+ /* sanity check.. */
+ if (end - start > 100000)
+ return arr;
+
+ /* remove last from the array */
+ g_ptr_array_remove_index(arr, arr->len - 1);
+
+ /* Add new elements */
+ while (start <= end) {
+ if (leading_zero) {
+ g_ptr_array_add(arr, g_strdup_printf("%0*ju",
+ ndigits, (uintmax_t)start));
+ } else {
+ g_ptr_array_add(arr, g_strdup_printf("%ju", (uintmax_t)start));
+ }
+ start++;
+ }
+
+ return arr;
+}
+
/* Helper for expand_braced_alternates; returns a list of un-escaped strings
* for the first "component" of str, where a component is a plain string or a
* brace-enclosed set of alternatives. str is pointing to the first character
if (*p == '}' || *p == ',') {
*c = '\0';
g_ptr_array_add(result, g_strdup(current));
+ result = expand_braced_sequence(result);
current = ++c;
if (*p == '}')
}
-/* A GHFunc (callback for g_hash_table_foreach) */
-void count_proplist(
- gpointer key_p G_GNUC_UNUSED,
- gpointer value_p,
- gpointer user_data_p)
-{
- property_t *value_s = value_p;
- int *nb = user_data_p;
- GSList *value;
-
- for(value=value_s->values; value != NULL; value = value->next) {
- (*nb)++;
- }
-}
-
-/* A GHFunc (callback for g_hash_table_foreach) */
-void proplist_add_to_argv(
+/* A GHFunc (callback for g_hash_table_foreach),
+ * Store a property and it's value in an ARGV.
+ *
+ * @param key_p: (char *) property name.
+ * @param value_p: (GSList *) property values list.
+ * @param user_data_p: (char ***) pointer to ARGV.
+ */
+static void
+proplist_add_to_argv(
gpointer key_p,
gpointer value_p,
gpointer user_data_p)
amfree(qprop);
}
+void
+property_add_to_argv(
+ GPtrArray *argv_ptr,
+ GHashTable *proplist)
+{
+ g_hash_table_foreach(proplist, &proplist_add_to_argv, argv_ptr);
+}
+
/*
* Process parameters