summary refs log tree commit diff stats
path: root/libotr/libgpg-error-1.42/src/stringutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'libotr/libgpg-error-1.42/src/stringutils.c')
-rw-r--r--libotr/libgpg-error-1.42/src/stringutils.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/libotr/libgpg-error-1.42/src/stringutils.c b/libotr/libgpg-error-1.42/src/stringutils.c
new file mode 100644
index 0000000..0be8769
--- /dev/null
+++ b/libotr/libgpg-error-1.42/src/stringutils.c
@@ -0,0 +1,224 @@
+/* stringutils.c - String helper functions.
+ * Copyright (C) 1997, 2014 Werner Koch
+ * Copyright (C) 2020 g10 Code GmbH
+ *
+ * This file is part of libgpg-error.
+ *
+ * libgpg-error is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * libgpg-error 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#ifdef HAVE_STAT
+# include <sys/stat.h>
+#endif
+#include <sys/types.h>
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+#include "gpgrt-int.h"
+
+
+/* Helper for _gpgrt_fnameconcat.  The additional flag WANT_ABS tells
+ * whether an absolute file name is requested.  */
+char *
+_gpgrt_vfnameconcat (int want_abs, const char *first_part, va_list arg_ptr)
+{
+  const char *argv[32];
+  int argc;
+  size_t n;
+  int skip = 1;  /* Characters to skip from FIRST_PART.  */
+  char *home_buffer = NULL;
+  char *name, *home, *p;
+
+  /* Put all args into an array because we need to scan them twice.  */
+  n = strlen (first_part) + 1;
+  argc = 0;
+  while ((argv[argc] = va_arg (arg_ptr, const char *)))
+    {
+      n += strlen (argv[argc]) + 1;
+      if (argc >= DIM (argv)-1)
+        {
+          _gpg_err_set_errno (EINVAL);
+          return NULL;
+        }
+      argc++;
+    }
+  n++;
+
+  home = NULL;
+  if (*first_part == '~')
+    {
+      if (first_part[1] == '/' || !first_part[1])
+        {
+          /* This is the "~/" or "~" case.  */
+          home_buffer = _gpgrt_getenv ("HOME");
+          if (!home_buffer)
+            home_buffer = _gpgrt_getpwdir (NULL);
+          home = home_buffer;
+          if (home && *home)
+            n += strlen (home);
+        }
+      else
+        {
+          /* This is the "~username/" or "~username" case.  */
+          char *user;
+
+          user = _gpgrt_strdup (first_part+1);
+          if (!user)
+            return NULL;
+
+          p = strchr (user, '/');
+          if (p)
+            *p = 0;
+          skip = 1 + strlen (user);
+
+          home = home_buffer = _gpgrt_getpwdir (user);
+          xfree (user);
+          if (home)
+            n += strlen (home);
+          else
+            skip = 1;
+        }
+    }
+
+  name = xtrymalloc (n);
+  if (!name)
+    {
+      _gpgrt_free (home_buffer);
+      return NULL;
+    }
+
+  if (home)
+    p = stpcpy (stpcpy (name, home), first_part + skip);
+  else
+    p = stpcpy (name, first_part);
+
+  xfree (home_buffer);
+  home_buffer = NULL;
+
+  for (argc=0; argv[argc]; 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)
+    {
+#ifdef HAVE_W32_SYSTEM
+      p = strchr (name, ':');
+      if (p)
+        p++;
+      else
+        p = name;
+#else
+      p = name;
+#endif
+      if (*p != '/'
+#ifdef HAVE_W32_SYSTEM
+          && *p != '\\'
+#endif
+          )
+        {
+          home = _gpgrt_getcwd ();
+          if (!home)
+            {
+              xfree (name);
+              return NULL;
+            }
+
+          n = strlen (home) + 1 + strlen (name) + 1;
+          home_buffer = xtrymalloc (n);
+          if (!home_buffer)
+            {
+              xfree (home);
+              xfree (name);
+              return NULL;
+            }
+
+          if (p == name)
+            p = home_buffer;
+          else /* Windows case.  */
+            {
+              memcpy (home_buffer, p, p - name + 1);
+              p = home_buffer + (p - name + 1);
+            }
+
+          /* 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 (home);
+          xfree (name);
+          name = home_buffer;
+          /* Let's do a simple compression to catch the common case of
+           * a trailing "/.".  */
+          n = strlen (name);
+          if (n > 2 && name[n-2] == '/' && name[n-1] == '.')
+            name[n-2] = 0;
+        }
+    }
+
+#ifdef HAVE_W32_SYSTEM
+  for (p=name; *p; p++)
+    if (*p == '\\')
+      *p = '/';
+#endif
+  return name;
+}
+
+
+/* Construct a filename from the NULL terminated list of parts.  Tilde
+ * expansion is done for the first argument.  The caller must release
+ * the result using gpgrt_free; on error ERRNO is set and NULL
+ * returned.  */
+char *
+_gpgrt_fnameconcat (const char *first_part, ... )
+{
+  va_list arg_ptr;
+  char *result;
+
+  va_start (arg_ptr, first_part);
+  result = _gpgrt_vfnameconcat (0, first_part, arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
+
+
+/* Construct a filename from the NULL terminated list of parts.  Tilde
+ * expansion is done for the first argument.  The caller must release
+ * the result using gpgrt_free; on error ERRNO is set and NULL
+ * returned.  This version returns an absolute filename. */
+char *
+_gpgrt_absfnameconcat (const char *first_part, ... )
+{
+  va_list arg_ptr;
+  char *result;
+
+  va_start (arg_ptr, first_part);
+  result = _gpgrt_vfnameconcat (1, first_part, arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}