bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Split strings into fields nondestructively.


From: James Youngman
Subject: [PATCH] Split strings into fields nondestructively.
Date: Mon, 13 Jun 2011 23:55:15 +0100

* lib/splitstring.c: New file; defines splitstring(), which will
non-destructively locate character-separated fields in a string.
* lib/splitstring.h: New file; declares splitstring.
* lib/test_splitstring.c: New file; unit test for splitstring.c.
* lib/nextelem.c: Delete (obsoleted by splitstring.c).
* lib/nextelem.h: Delete (obsoleted by splitstring.h).
* lib/Makefile.am (libfind_a_SOURCES): Add splitstring.c,
splitstring.c.  Remove nextelem.c, nextelem.h.
(check_PROGRAMS): Add test_splitstring.
(TESTS): Add test_splitstring.
(test_splitstring_SOURCES): Sources for the
test_splitstring unit test.
* locate/locate.c: Include splitstring.h rather than nextelem.h.
(dolocate): Use splitstring rather than next_element.  In places
where we need a nul-terminated string, use strndup() to create it.
Convert some space-tab sequences to regular spacing.
* find/parser.c: Include splitstring.h rather than nextelem.h.
(check_path_safety): Use splitstring rather than next_element.
* import-gnulib.config (modules): Depend on the module strndup.
* cfg.mk: Exempt lib/test_splitstring.c from calling
bindtextdomain or set_program_name.
---
 ChangeLog              |   25 ++++++
 cfg.mk                 |    4 +-
 find/parser.c          |   32 +++++---
 import-gnulib.config   |    1 +
 lib/Makefile.am        |   14 ++--
 lib/nextelem.c         |   85 --------------------
 lib/nextelem.h         |   26 ------
 lib/splitstring.c      |   60 ++++++++++++++
 lib/splitstring.h      |   40 ++++++++++
 lib/test_splitstring.c |  201 ++++++++++++++++++++++++++++++++++++++++++++++++
 locate/locate.c        |   61 +++++++++-----
 11 files changed, 396 insertions(+), 153 deletions(-)
 delete mode 100644 lib/nextelem.c
 delete mode 100644 lib/nextelem.h
 create mode 100644 lib/splitstring.c
 create mode 100644 lib/splitstring.h
 create mode 100644 lib/test_splitstring.c

diff --git a/ChangeLog b/ChangeLog
index 827ea60..7b2dd52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
 2011-06-13  James Youngman  <address@hidden>
 
+       Split strings into fields nondestructively.
+       * lib/splitstring.c: New file; defines splitstring(), which will
+       non-destructively locate character-separated fields in a string.
+       * lib/splitstring.h: New file; declares splitstring.
+       * lib/test_splitstring.c: New file; unit test for splitstring.c.
+       * lib/nextelem.c: Delete (obsoleted by splitstring.c).
+       * lib/nextelem.h: Delete (obsoleted by splitstring.h).
+       * lib/Makefile.am (libfind_a_SOURCES): Add splitstring.c,
+       splitstring.c.  Remove nextelem.c, nextelem.h.
+       (check_PROGRAMS): Add test_splitstring.
+       (TESTS): Add test_splitstring.
+       (test_splitstring_SOURCES): Sources for the
+       test_splitstring unit test.
+       * locate/locate.c: Include splitstring.h rather than nextelem.h.
+       (dolocate): Use splitstring rather than next_element.  In places
+       where we need a nul-terminated string, use strndup() to create it.
+       Convert some space-tab sequences to regular spacing.
+       * find/parser.c: Include splitstring.h rather than nextelem.h.
+       (check_path_safety): Use splitstring rather than next_element.
+       * import-gnulib.config (modules): Depend on the module strndup.
+       * cfg.mk: Exempt lib/test_splitstring.c from calling
+       bindtextdomain or set_program_name.
+
+2011-06-13  James Youngman  <address@hidden>
+
        Fix compilation failure in bigram.c by including <locale.h>.
        * locate/bigram.c: Include <locale.h>.
 
diff --git a/cfg.mk b/cfg.mk
index f301884..121c337 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -36,13 +36,15 @@ exclude_file_name_regexp--sc_trailing_blank = \
 exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \
        
^(.*/testsuite/.*\.(xo|xi|xe))|COPYING|doc/regexprops\.texi|m4/order-(bad|good)\.bin$$
 exclude_file_name_regexp--sc_bindtextdomain = \
-       ^lib/regexprops\.c$$
+       ^lib/(regexprops|test_splitstring)\.c$$
 exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \
        ^(build-aux/src-sniff\.py)|ChangeLog$$
 exclude_file_name_regexp--sc_prohibit_test_minus_ao = \
        ^(ChangeLog)|((find|locate|xargs)/testsuite/.*\.exp)$$
 exclude_file_name_regexp--sc_prohibit_doubled_word = \
        ^(xargs/testsuite/xargs\.sysv/iquotes\.xo)|ChangeLog|po/.*\.po$$
+exclude_file_name_regexp--sc_program_name = \
+       ^lib/test_splitstring\.c$$
 
 # sc_texinfo_acronym: perms.texi from coreutils uses @acronym{GNU}.
 exclude_file_name_regexp--sc_texinfo_acronym = doc/perm\.texi
diff --git a/find/parser.c b/find/parser.c
index 7b82ae7..ea676bd 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -34,7 +34,6 @@
 #include "xalloc.h"
 #include "quotearg.h"
 #include "buildcmd.h"
-#include "nextelem.h"
 #include "regextype.h"
 #include "stat-time.h"
 #include "xstrtod.h"
@@ -44,6 +43,7 @@
 #include "findutils-version.h"
 #include "safe-atoi.h"
 #include "fdleak.h"
+#include "splitstring.h"
 
 #include <fcntl.h>
 
@@ -3227,11 +3227,16 @@ make_segment (struct segment **segment,
   return &(*segment)->next;
 }
 
+
+
+
 static void
 check_path_safety (const char *action, char **argv)
 {
-  char *s;
   const char *path = getenv ("PATH");
+  const char *path_separators = ":";
+  size_t pos, len;
+
   if (NULL == path)
     {
       /* $PATH is not set.  Assume the OS default is safe.
@@ -3242,34 +3247,35 @@ check_path_safety (const char *action, char **argv)
       return;
     }
 
-  (void)argv;
-
-  s = next_element (path, 1);
-  while ((s = next_element ((char *) NULL, 1)) != NULL)
+  splitstring (path, path_separators, true, &pos, &len);
+  do
     {
-      if (0 == strcmp (s, "."))
+      if (0 == len || (1 == len && path[pos] == '.'))
        {
+         /* empty field signifies . */
          error (EXIT_FAILURE, 0,
                 _("The current directory is included in the PATH "
                   "environment variable, which is insecure in "
                   "combination with the %s action of find.  "
                   "Please remove the current directory from your "
-                  "$PATH (that is, remove \".\" or leading or trailing "
-                  "colons)"),
+                  "$PATH (that is, remove \".\", doubled colons, "
+                  "or leading or trailing colons)"),
                 action);
        }
-      else if ('/' != s[0])
+      else if (path[pos] != '/')
        {
-         /* Relative paths are also dangerous in $PATH. */
+         char *relpath = strndup (&path[pos], len);
          error (EXIT_FAILURE, 0,
                 _("The relative path %s is included in the PATH "
                   "environment variable, which is insecure in "
                   "combination with the %s action of find.  "
                   "Please remove that entry from $PATH"),
-                safely_quote_err_filename (0, s),
+                safely_quote_err_filename (0, relpath ? relpath : &path[pos]),
                 action);
+         /*NOTREACHED*/
+         free (relpath);
        }
-    }
+    } while (splitstring (path, path_separators, false, &pos, &len));
 }
 
 
diff --git a/import-gnulib.config b/import-gnulib.config
index 5fb46c2..567d66c 100644
--- a/import-gnulib.config
+++ b/import-gnulib.config
@@ -132,6 +132,7 @@ strcasestr
 strdup-posix
 strftime
 string
+strndup
 strtol
 strtoul
 strtoull
diff --git a/lib/Makefile.am b/lib/Makefile.am
index f8ff625..5450e9a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -6,7 +6,7 @@ AM_CFLAGS = $(WARN_CFLAGS)
 
 noinst_LIBRARIES = libfind.a
 
-check_PROGRAMS = regexprops
+check_PROGRAMS = regexprops test_splitstring
 check_SCRIPTS = check-regexprops
 regexprops_SOURCES = regexprops.c regextype.c
 
@@ -15,7 +15,7 @@ if CROSS_COMPILING
 # The regexprops program needs to be a native executable, so we
 # can't build it with a cross-compiler.
 else
-TESTS += check-regexprops
+TESTS += check-regexprops test_splitstring
 endif
 
 libfind_a_SOURCES = findutils-version.c
@@ -32,11 +32,11 @@ MAINTAINERCLEANFILES =
 INCLUDES = -I../gl/lib -I$(top_srcdir)/gl/lib
 LDADD = ../gl/lib/libgnulib.a $(LIBINTL)
 
-libfind_a_SOURCES += nextelem.h printquoted.h listfile.h \
-       regextype.h dircallback.h safe-atoi.h
-libfind_a_SOURCES += listfile.c nextelem.c extendbuf.c buildcmd.c 
savedirinfo.c \
+libfind_a_SOURCES += printquoted.h listfile.h \
+       regextype.h dircallback.h safe-atoi.h splitstring.h
+libfind_a_SOURCES += listfile.c extendbuf.c buildcmd.c savedirinfo.c \
        forcefindlib.c qmark.c printquoted.c regextype.c dircallback.c fdleak.c 
\
-       safe-atoi.c
+       safe-atoi.c splitstring.c
 
 EXTRA_DIST += waitpid.c forcefindlib.c
 TESTS_ENVIRONMENT = REGEXPROPS=regexprops$(EXEEXT)
@@ -46,3 +46,5 @@ libfind_a_DEPENDENCIES = $(FINDLIBOBJS)
 check-regexprops: check-regexprops.sh
        cp  $(srcdir)/check-regexprops.sh check-regexprops
        chmod +x check-regexprops
+
+test_splitstring_SOURCES = test_splitstring.c splitstring.c
diff --git a/lib/nextelem.c b/lib/nextelem.c
deleted file mode 100644
index 3e9246c..0000000
--- a/lib/nextelem.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Return the next element of a path.
-   Copyright (C) 1992, 2005, 2010, 2011 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program 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.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/* Written by David MacKenzie <address@hidden>,
-   inspired by John P. Rouillard <address@hidden>.  */
-
-#include <config.h>
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-
-#include "nextelem.h"
-
-
-/* Return the next element of a colon-separated path.
-   A null entry in the path is equivalent to "." (the current directory).
-
-   If NEW_PATH is non-NULL, set the path and return NULL.
-   If NEW_PATH is NULL, return the next item in the string, or
-   return NULL if there are no more elements.  */
-
-char *
-next_element (const char *new_path, int curdir_ok)
-{
-  static char *path = NULL;    /* Freshly allocated copy of NEW_PATH.  */
-  static char *end;            /* Start of next element to return.  */
-  static int final_colon;      /* If zero, path didn't end with a colon.  */
-  char *start;                 /* Start of path element to return.  */
-
-  if (new_path)
-    {
-      free (path);
-      end = path = strdup (new_path);
-      final_colon = 0;
-      return NULL;
-    }
-
-  if (*end == '\0')
-    {
-      if (final_colon)
-       {
-         final_colon = 0;
-         return curdir_ok ? "." : "";
-       }
-      return NULL;
-    }
-
-  start = end;
-  final_colon = 1;             /* Maybe there will be one.  */
-
-  end = strchr (start, ':');
-  if (end == start)
-    {
-      /* An empty path element.  */
-      *end++ = '\0';
-      return curdir_ok ? "." : "";
-    }
-  else if (end == NULL)
-    {
-      /* The last path element.  */
-      end = strchr (start, '\0');
-      final_colon = 0;
-    }
-  else
-    *end++ = '\0';
-
-  return start;
-}
diff --git a/lib/nextelem.h b/lib/nextelem.h
deleted file mode 100644
index 00ffcfe..0000000
--- a/lib/nextelem.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Return the next element of a path.
-   Copyright (C) 1992, 2010, 2011 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program 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.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/* Written by David MacKenzie <address@hidden>,
-   inspired by John P. Rouillard <address@hidden>.  */
-
-#ifndef INC_NEXTELEM_H
-#define INC_NEXTELEM_H 1
-
-char *next_element (const char *path, int curdir_ok);
-
-#endif
diff --git a/lib/splitstring.c b/lib/splitstring.c
new file mode 100644
index 0000000..e706d9c
--- /dev/null
+++ b/lib/splitstring.c
@@ -0,0 +1,60 @@
+/* splitstring.c -- split a const string into fields.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/*
+ * Written by James Youngman.
+ */
+
+#include <config.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "splitstring.h"
+
+static size_t
+field_length (const char *str, const char *separators)
+{
+  /* if there are no separators, the whole input is one field. */
+  if (*separators)
+    {
+      const char *end = strpbrk (str, separators);
+      if (end)
+       return end - str;
+    }
+  return strlen (str);
+}
+
+
+bool
+splitstring(const char *s, const char *separators, bool first,
+           size_t *pos, size_t *len)
+{
+  if (first)
+    {
+      *pos = 0u;
+      *len = 0u;
+    }
+  else
+    {
+      *pos += *len;            /* advance to the next field. */
+      if (s[*pos])
+       ++*pos;                 /* skip the separator */
+      else
+       return false;           /* we reached the end. */
+    }
+  *len = field_length (&s[*pos], separators);
+  return true;
+}
diff --git a/lib/splitstring.h b/lib/splitstring.h
new file mode 100644
index 0000000..c91f7e7
--- /dev/null
+++ b/lib/splitstring.h
@@ -0,0 +1,40 @@
+/* splitstring.h -- split a const string into fields.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/*
+ * Written by James Youngman.
+ */
+
+/* Split a string into fields.   The string is never modified.
+ *
+ * A false return value indicates that there are no more fields.
+ * Otherwise the next field is at the poisition indicated by *POS and
+ * has length *LEN.
+ *
+ * Set FIRST to true only on the first call for any given value of s.
+ * *POS and *LEN do not need to be initialised in this case.
+ * On subsequent calls, these values should be left at the values
+ * set by the last call.
+ *
+ * Any character in SEPARATORS is taken to be a field separator.
+ * Consecutive field separators are taken to indicate the presence of
+ * an empty field.
+ */
+#include <stdbool.h>
+#include <stddef.h>
+
+bool splitstring(const char *s, const char *separators,
+                bool first, size_t *pos, size_t *len);
diff --git a/lib/test_splitstring.c b/lib/test_splitstring.c
new file mode 100644
index 0000000..9dedb7c
--- /dev/null
+++ b/lib/test_splitstring.c
@@ -0,0 +1,201 @@
+/* test_splitstring.c -- unit test for splitstring()
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "splitstring.h"
+
+static void
+assertEqualFunc(const char *file, int line, const char *label,
+               size_t expected, size_t got)
+{
+  if (expected != got)
+    fprintf(stderr, "%s line %d: %s: expected %lu, got %lu\n",
+           file, line, label, (unsigned long)expected, (unsigned long)got);
+}
+#define ASSERT_EQUAL(expected,got) \
+  do{ \
+    assertEqualFunc(__FILE__,__LINE__,"ASSERT_EQUAL",expected,got); \
+    assert (expected == got); \
+  } while (0);
+
+
+static void
+test_empty (void)
+{
+  size_t len, pos;
+  bool result;
+  const char *empty = "";
+
+  result = splitstring (empty, ":", true, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (0, pos);
+  ASSERT_EQUAL (0, len);
+  result = splitstring (empty, ":", false, &pos, &len);
+  assert (!result);
+}
+
+static void test_onefield (void)
+{
+  size_t len, pos;
+  bool result;
+  const char *input = "aaa";
+
+  result = splitstring (input, ":", true, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (0, pos);
+  ASSERT_EQUAL (3, len);
+  result = splitstring (input, ":", false, &pos, &len);
+  assert (!result);
+}
+
+static void test_not_colon (void)
+{
+  size_t len, pos;
+  bool result;
+  const char *separators = "!";
+  const char *input = "aa!b";
+
+  result = splitstring (input, separators, true, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (0, pos);
+  ASSERT_EQUAL (2, len);
+
+  result = splitstring (input, separators, false, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (3, pos);
+  ASSERT_EQUAL (1, len);
+
+  result = splitstring (input, separators, false, &pos, &len);
+  assert (!result);
+}
+
+static void test_empty_back (void)
+{
+  size_t len, pos;
+  bool result;
+  const char *input = "aa:";
+
+  result = splitstring (input, ":", true, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (0, pos);
+  ASSERT_EQUAL (2, len);
+  result = splitstring (input, ":", false, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (3, pos);
+  ASSERT_EQUAL (0, len);
+  result = splitstring (input, ":", false, &pos, &len);
+  assert (!result);
+}
+
+static void test_empty_front (void)
+{
+  size_t len, pos;
+  bool result;
+  const char *input = ":aaa";
+
+  result = splitstring (input, ":", true, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (0, pos);
+  ASSERT_EQUAL (0, len);
+  result = splitstring (input, ":", false, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (1, pos);
+  ASSERT_EQUAL (3, len);
+  result = splitstring (input, ":", false, &pos, &len);
+  assert (!result);
+}
+
+static void test_twofields (void)
+{
+  size_t len, pos;
+  bool result;
+  const char *input = "aaa:bb";
+
+  result = splitstring (input, ":", true, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (0, pos);
+  ASSERT_EQUAL (3, len);
+  result = splitstring (input, ":", false, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (4, pos);
+  ASSERT_EQUAL (2, len);
+  result = splitstring (input, ":", false, &pos, &len);
+  assert (!result);
+}
+
+static void test_twoseparators (void)
+{
+  size_t len, pos;
+  bool result;
+  const char *input = "a:bb!c";
+
+  result = splitstring (input, ":!", true, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (0, pos);
+  ASSERT_EQUAL (1, len);
+  result = splitstring (input, ":!", false, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (2,  pos);
+  ASSERT_EQUAL (2, len);
+  result = splitstring (input, ":!", false, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (5, pos);
+  ASSERT_EQUAL (1, len);
+  result = splitstring (input, ":!", false, &pos, &len);
+  assert (!result);
+}
+
+static void test_consecutive_empty (void)
+{
+  size_t len, pos;
+  bool result;
+  const char *input = "a::b";
+  const char *separators = ":";
+
+  result = splitstring (input, separators, true, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (0, pos);
+  ASSERT_EQUAL (1, len);
+
+  result = splitstring (input, separators, false, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (2, pos);
+  ASSERT_EQUAL (0, len);
+
+  result = splitstring (input, separators, false, &pos, &len);
+  assert (result);
+  ASSERT_EQUAL (3, pos);
+  ASSERT_EQUAL (1, len);
+
+  result = splitstring (input, separators, false, &pos, &len);
+  assert (!result);
+}
+
+int main (int argc, char *argv[])
+{
+  test_empty ();
+  test_onefield ();
+  test_not_colon ();
+  test_empty_back ();
+  test_empty_front ();
+  test_twofields ();
+  test_twoseparators ();
+  test_consecutive_empty ();
+  return 0;
+}
diff --git a/locate/locate.c b/locate/locate.c
index ad7b56a..42089ee 100644
--- a/locate/locate.c
+++ b/locate/locate.c
@@ -123,11 +123,11 @@
 #include "human.h"
 #include "dirname.h"
 #include "closeout.h"
-#include "nextelem.h"
 #include "regex.h"
 #include "quotearg.h"
 #include "printquoted.h"
 #include "regextype.h"
+#include "splitstring.h"
 #include "findutils-version.h"
 
 /* Note that this evaluates Ch many times.  */
@@ -1555,7 +1555,11 @@ opendb (const char *name)
 int
 dolocate (int argc, char **argv, int secure_db_fd)
 {
-  char *dbpath;
+  char *path_element;
+  size_t path_element_pos, path_element_len;
+  const char *locate_path;
+  const char *db_name;
+  const char *path_separators = ":";
   unsigned long int found = 0uL;
   int ignore_case = 0;
   int print = 0;
@@ -1593,11 +1597,9 @@ dolocate (int argc, char **argv, int secure_db_fd)
    * setuid-access-controlled database,, since that could cause a leak
    * of private data.
    */
-  dbpath = getenv ("LOCATE_PATH");
-  if (dbpath)
-    {
+  locate_path = getenv ("LOCATE_PATH");
+  if (locate_path)
       they_chose_db = 1;
-    }
 
   check_existence = ACCEPT_EITHER;
 
@@ -1629,7 +1631,7 @@ dolocate (int argc, char **argv, int secure_db_fd)
          break;
 
        case 'd':
-         dbpath = optarg;
+          locate_path = optarg;
          they_chose_db = 1;
          break;
 
@@ -1753,7 +1755,8 @@ dolocate (int argc, char **argv, int secure_db_fd)
     stdout_is_a_tty = false;
 
   if (they_chose_db)
-    next_element (dbpath, 0);  /* Initialize.  */
+    splitstring (locate_path, path_separators, true,
+                 &path_element_pos, &path_element_len);
 
   /* Bail out early if limit already reached. */
   while (!use_limit || limits.limit > limits.items_accepted)
@@ -1772,11 +1775,7 @@ dolocate (int argc, char **argv, int secure_db_fd)
       if (they_chose_db)
        {
          /* Take the next element from the list of databases */
-         e = next_element ((char *) NULL, 0);
-         if (NULL == e)
-           break;
-
-         if (0 == strcmp (e, "-"))
+          if (1 == path_element_len && '-' == locate_path[path_element_pos])
            {
              if (did_stdin)
                {
@@ -1793,17 +1792,25 @@ dolocate (int argc, char **argv, int secure_db_fd)
            }
          else
            {
-             if (0 == strlen (e) || 0 == strcmp (e, "."))
+              if (0 == path_element_len
+                  || (1 == path_element_len
+                      && '.' == locate_path[path_element_pos]))
+                {
+                  db_name = LOCATE_DB;
+                }
+              else
                {
-                 e = LOCATE_DB;
+                  path_element = strndup (&locate_path[path_element_pos],
+                                          path_element_len);
+                  db_name = path_element;
                }
 
              /* open the database */
-             fd = opendb (e);
+              fd = opendb (db_name);
              if (fd < 0)
                {
                  error (0, errno, "%s",
-                        quotearg_n_style (0, locale_quoting_style, e));
+                         quotearg_n_style (0, locale_quoting_style, db_name));
                  return 0;
                }
            }
@@ -1817,7 +1824,7 @@ dolocate (int argc, char **argv, int secure_db_fd)
            }
          else
            {
-             e = selected_secure_db;
+              db_name = selected_secure_db;
              fd = secure_db_fd;
              secure_db_fd = -1;
            }
@@ -1827,7 +1834,7 @@ dolocate (int argc, char **argv, int secure_db_fd)
       if (fstat (fd, &st))
        {
          error (0, errno, "%s",
-                quotearg_n_style (0, locale_quoting_style, e));
+                 quotearg_n_style (0, locale_quoting_style, db_name));
          /* continue anyway */
          filesize = (off_t)0;
        }
@@ -1855,7 +1862,7 @@ dolocate (int argc, char **argv, int secure_db_fd)
                     warning: database `fred' is more than 8 days old (actual 
age is 10 days)*/
                  error (0, 0,
                         _("warning: database %s is more than %d %s old (actual 
age is %.1f %s)"),
-                        quotearg_n_style (0,  locale_quoting_style, e),
+                         quotearg_n_style (0,  locale_quoting_style, db_name),
                         warn_number_units,              _(warn_name_units),
                         (age/(double)SECONDS_PER_UNIT), _(warn_name_units));
                }
@@ -1866,7 +1873,7 @@ dolocate (int argc, char **argv, int secure_db_fd)
       if (NULL == fp)
        {
          error (0, errno, "%s",
-                quotearg_n_style (0, locale_quoting_style, e));
+                 quotearg_n_style (0, locale_quoting_style, db_name));
          return 0;
        }
 
@@ -1881,9 +1888,19 @@ dolocate (int argc, char **argv, int secure_db_fd)
       if (fclose (fp) == EOF)
        {
          error (0, errno, "%s",
-                quotearg_n_style (0, locale_quoting_style, e));
+                 quotearg_n_style (0, locale_quoting_style, db_name));
          return 0;
        }
+       if (path_element)
+        {
+          free (path_element);
+          path_element = NULL;
+        }
+      if (!splitstring (locate_path, path_separators, false,
+                        &path_element_pos, &path_element_len))
+        {
+          break;
+        }
     }
 
   if (just_count)
-- 
1.7.2.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]