common/iobuf.c: Combine iobuf_open, iobuf_create and iobuf_openrw.
[gnupg.git] / common / stringhelp.c
index 96710bf..576c2ea 100644 (file)
@@ -4,9 +4,9 @@
  * Copyright (C) 2014 Werner Koch
  * Copyright (C) 2015  g10 Code GmbH
  *
  * Copyright (C) 2014 Werner Koch
  * Copyright (C) 2015  g10 Code GmbH
  *
- * This file is part of JNLIB, which is a subsystem of GnuPG.
+ * This file is part of GnuPG.
  *
  *
- * JNLIB is free software; you can redistribute it and/or modify it
+ * GnuPG is free software; you can redistribute it and/or modify it
  * under the terms of either
  *
  *   - the GNU Lesser General Public License as published by the Free
  * under the terms of either
  *
  *   - the GNU Lesser General Public License as published by the Free
@@ -21,7 +21,7 @@
  *
  * or both in parallel, as here.
  *
  *
  * or both in parallel, as here.
  *
- * JNLIB is distributed in the hope that it will be useful, but
+ * GnuPG is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
@@ -48,6 +48,7 @@
 # endif
 # include <windows.h>
 #endif
 # endif
 # include <windows.h>
 #endif
+#include <assert.h>
 
 #include "util.h"
 #include "common-defs.h"
 
 #include "util.h"
 #include "common-defs.h"
@@ -492,7 +493,13 @@ do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
 
   xfree (home_buffer);
   for (argc=0; argv[argc]; argc++)
 
   xfree (home_buffer);
   for (argc=0; argv[argc]; argc++)
-    p = stpcpy (stpcpy (p, "/"), argv[argc]);
+    {
+      /* Avoid a leading double slash if the first part was "/".  */
+      if (!argc && name[0] == '/' && !name[1])
+        p = stpcpy (p, argv[argc]);
+      else
+        p = stpcpy (stpcpy (p, "/"), argv[argc]);
+    }
 
   if (want_abs)
     {
 
   if (want_abs)
     {
@@ -542,7 +549,13 @@ do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
               memcpy (home_buffer, p, p - name + 1);
               p = home_buffer + (p - name + 1);
             }
               memcpy (home_buffer, p, p - name + 1);
               p = home_buffer + (p - name + 1);
             }
-          strcpy (stpcpy (stpcpy (p, home), "/"), name);
+
+          /* Avoid a leading double slash if the cwd is "/".  */
+          if (home[0] == '/' && !home[1])
+            strcpy (stpcpy (p, "/"), name);
+          else
+            strcpy (stpcpy (stpcpy (p, home), "/"), name);
+
           xfree (name);
           name = home_buffer;
           /* Let's do a simple compression to catch the most common
           xfree (name);
           name = home_buffer;
           /* Let's do a simple compression to catch the most common
@@ -1234,3 +1247,69 @@ strsplit (char *string, char delim, char replacement, int *count)
 
   return result;
 }
 
   return result;
 }
+
+
+/* Tokenize STRING using the set of delimiters in DELIM.  Leading
+ * spaces and tabs are removed from all tokens.  The caller must xfree
+ * the result.
+ *
+ * Returns: A malloced and NULL delimited array with the tokens.  On
+ *          memory error NULL is returned and ERRNO is set.
+ */
+char **
+strtokenize (const char *string, const char *delim)
+{
+  const char *s;
+  size_t fields;
+  size_t bytes, n;
+  char *buffer;
+  char *p, *px, *pend;
+  char **result;
+
+  /* Count the number of fields.  */
+  for (fields = 1, s = strpbrk (string, delim); s; s = strpbrk (s + 1, delim))
+    fields++;
+  fields++; /* Add one for the terminating NULL.  */
+
+  /* Allocate an array for all fields, a terminating NULL, and space
+     for a copy of the string.  */
+  bytes = fields * sizeof *result;
+  if (bytes / sizeof *result != fields)
+    {
+      gpg_err_set_errno (ENOMEM);
+      return NULL;
+    }
+  n = strlen (string) + 1;
+  bytes += n;
+  if (bytes < n)
+    {
+      gpg_err_set_errno (ENOMEM);
+      return NULL;
+    }
+  result = xtrymalloc (bytes);
+  if (!result)
+    return NULL;
+  buffer = (char*)(result + fields);
+
+  /* Copy and parse the string.  */
+  strcpy (buffer, string);
+  for (n = 0, p = buffer; (pend = strpbrk (p, delim)); p = pend + 1)
+    {
+      *pend = 0;
+      while (spacep (p))
+        p++;
+      for (px = pend - 1; px >= p && spacep (px); px--)
+        *px = 0;
+      result[n++] = p;
+    }
+  while (spacep (p))
+    p++;
+  for (px = p + strlen (p) - 1; px >= p && spacep (px); px--)
+    *px = 0;
+  result[n++] = p;
+  result[n] = NULL;
+
+  assert ((char*)(result + n + 1) == buffer);
+
+  return result;
+}