diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.in | 5 | ||||
-rw-r--r-- | src/accessdb.c | 3 | ||||
-rw-r--r-- | src/catman.c | 31 | ||||
-rw-r--r-- | src/check_mandirs.c | 160 | ||||
-rw-r--r-- | src/descriptions.c | 75 | ||||
-rw-r--r-- | src/descriptions.h | 15 | ||||
-rw-r--r-- | src/descriptions_store.c | 46 | ||||
-rw-r--r-- | src/globbing.c | 166 | ||||
-rw-r--r-- | src/globbing.h | 8 | ||||
-rw-r--r-- | src/globbing_test.c | 29 | ||||
-rw-r--r-- | src/lexgrog_test.c | 41 | ||||
-rw-r--r-- | src/man.c | 558 | ||||
-rw-r--r-- | src/manconv_main.c | 5 | ||||
-rw-r--r-- | src/mandb.c | 111 | ||||
-rw-r--r-- | src/manp.c | 632 | ||||
-rw-r--r-- | src/manp.h | 14 | ||||
-rw-r--r-- | src/manpath.c | 11 | ||||
-rw-r--r-- | src/straycats.c | 57 | ||||
-rw-r--r-- | src/tests/Makefile.in | 5 | ||||
-rw-r--r-- | src/ult_src.c | 52 | ||||
-rw-r--r-- | src/ult_src.h | 20 | ||||
-rw-r--r-- | src/whatis.c | 234 | ||||
-rw-r--r-- | src/zsoelim.c | 129 | ||||
-rw-r--r-- | src/zsoelim.h | 8 | ||||
-rw-r--r-- | src/zsoelim.l | 67 | ||||
-rw-r--r-- | src/zsoelim_main.c | 9 |
26 files changed, 1192 insertions, 1299 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index c2f4385a..413cae19 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -103,6 +103,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \ $(top_srcdir)/m4/man-arg-db.m4 \ $(top_srcdir)/m4/man-arg-device.m4 \ $(top_srcdir)/m4/man-arg-mandirs.m4 \ + $(top_srcdir)/m4/man-arg-manual.m4 \ $(top_srcdir)/m4/man-arg-override-dir.m4 \ $(top_srcdir)/m4/man-arg-sections.m4 \ $(top_srcdir)/m4/man-arg-setuid.m4 \ @@ -125,7 +126,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \ $(top_srcdir)/gl/m4/btowc.m4 \ $(top_srcdir)/gl/m4/builtin-expect.m4 \ $(top_srcdir)/gl/m4/canonicalize.m4 \ - $(top_srcdir)/gl/m4/chdir-long.m4 \ + $(top_srcdir)/gl/m4/chdir-long.m4 $(top_srcdir)/gl/m4/chown.m4 \ $(top_srcdir)/gl/m4/clock_time.m4 $(top_srcdir)/gl/m4/close.m4 \ $(top_srcdir)/gl/m4/closedir.m4 $(top_srcdir)/gl/m4/codeset.m4 \ $(top_srcdir)/gl/m4/d-ino.m4 $(top_srcdir)/gl/m4/d-type.m4 \ @@ -169,7 +170,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \ $(top_srcdir)/gl/m4/intmax_t.m4 \ $(top_srcdir)/gl/m4/inttypes_h.m4 $(top_srcdir)/gl/m4/ioctl.m4 \ $(top_srcdir)/gl/m4/langinfo_h.m4 \ - $(top_srcdir)/gl/m4/largefile.m4 \ + $(top_srcdir)/gl/m4/largefile.m4 $(top_srcdir)/gl/m4/lchown.m4 \ $(top_srcdir)/gl/m4/lib-ignore.m4 \ $(top_srcdir)/gl/m4/lib-ld.m4 $(top_srcdir)/gl/m4/lib-link.m4 \ $(top_srcdir)/gl/m4/lib-prefix.m4 \ diff --git a/src/accessdb.c b/src/accessdb.c index 21f18cb8..ff3fef5e 100644 --- a/src/accessdb.c +++ b/src/accessdb.c @@ -27,6 +27,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdio.h> #include <errno.h> #include <string.h> @@ -70,7 +71,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { case 'd': - debug_level = 1; + debug_level = true; return 0; case 'h': argp_state_help (state, state->out_stream, diff --git a/src/catman.c b/src/catman.c index 489b33ca..c58ef6c0 100644 --- a/src/catman.c +++ b/src/catman.c @@ -31,6 +31,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdio.h> #include <assert.h> #include <sys/types.h> @@ -61,6 +62,7 @@ #endif /* !ARG_MAX */ #include "argp.h" +#include "gl_list.h" #include "progname.h" #include "gettext.h" @@ -72,6 +74,7 @@ #include "cleanup.h" #include "error.h" +#include "glcontainers.h" #include "pipeline.h" #include "sandbox.h" @@ -110,7 +113,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) switch (key) { case 'd': - debug_level = 1; + debug_level = true; return 0; case 'M': manp = arg; @@ -164,7 +167,7 @@ static struct argp argp = { options, parse_opt, args_doc }; static char *locale; -static char *manpathlist[MAXDIRS]; +static gl_list_t manpathlist; static void post_fork (void) { @@ -353,7 +356,7 @@ static int check_access (const char *directory) int main (int argc, char *argv[]) { char *sys_manp; - char **mp; + char *mp; const char **sp; set_program_name (argv[0]); @@ -388,14 +391,14 @@ int main (int argc, char *argv[]) debug ("manpath=%s\n", manp); - /* get the manpath as an array of pointers */ - create_pathlist (manp, manpathlist); - - for (mp = manpathlist; *mp; mp++) { + /* get the manpath as a list of pointers */ + manpathlist = create_pathlist (manp); + + GL_LIST_FOREACH_START (manpathlist, mp) { char *catpath; size_t len; - catpath = get_catpath (*mp, SYSTEM_CAT | USER_CAT); + catpath = get_catpath (mp, SYSTEM_CAT | USER_CAT); if (catpath) { if (is_directory (catpath) != 1) { @@ -404,10 +407,10 @@ int main (int argc, char *argv[]) } database = mkdbname (catpath); } else { - if (is_directory (*mp) != 1) + if (is_directory (mp) != 1) continue; - database = mkdbname (*mp); - catpath = xstrdup (*mp); + database = mkdbname (mp); + catpath = xstrdup (mp); } len = strlen (catpath); @@ -419,14 +422,14 @@ int main (int argc, char *argv[]) continue; if (check_access (catpath)) continue; - if (parse_for_sec (*mp, *sp)) { - error (0, 0, _("unable to update %s"), *mp); + if (parse_for_sec (mp, *sp)) { + error (0, 0, _("unable to update %s"), mp); break; } } free (catpath); - } + } GL_LIST_FOREACH_END (manpathlist); free_pathlist (manpathlist); free (locale); diff --git a/src/check_mandirs.c b/src/check_mandirs.c index c8c33dce..5aba37cb 100644 --- a/src/check_mandirs.c +++ b/src/check_mandirs.c @@ -31,6 +31,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -43,6 +44,10 @@ #include <unistd.h> #include "dirname.h" +#include "gl_array_list.h" +#include "gl_hash_map.h" +#include "gl_xlist.h" +#include "gl_xmap.h" #include "stat-time.h" #include "timespec.h" #include "xvasprintf.h" @@ -53,10 +58,9 @@ #include "manconfig.h" #include "error.h" -#include "hashtable.h" +#include "glcontainers.h" #include "orderfiles.h" #include "security.h" -#include "xchown.h" #include "mydbm.h" #include "db_storage.h" @@ -68,24 +72,24 @@ #include "ult_src.h" #include "check_mandirs.h" -int opt_test; /* don't update db */ +bool opt_test; /* don't update db */ int pages; -int force_rescan = 0; +bool force_rescan = false; -static struct hashtable *whatis_hash = NULL; +gl_map_t whatis_map = NULL; -struct whatis_hashent { +struct whatis { char *whatis; - struct ult_trace trace; + gl_list_t trace; }; -static void whatis_hashtable_free (void *defn) +static void whatis_free (const void *value) { - struct whatis_hashent *hashent = defn; + struct whatis *whatis = (struct whatis *) value; - free (hashent->whatis); - free_ult_trace (&hashent->trace); - free (hashent); + free (whatis->whatis); + gl_list_free (whatis->trace); + free (whatis); } static void gripe_multi_extensions (const char *path, const char *sec, @@ -127,12 +131,11 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path) struct mandata info, *exists; struct stat buf; size_t len; - struct ult_trace ult_trace; - struct whatis_hashent *whatis; + gl_list_t ult_trace = NULL; + const struct whatis *whatis; memset (&lg, 0, sizeof (struct lexgrog)); memset (&info, 0, sizeof (struct mandata)); - memset (&ult_trace, 0, sizeof (struct ult_trace)); manpage = filename_info (file, &info, NULL); if (!manpage) @@ -158,7 +161,7 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path) * save both an ult_src() and a find_name(), amongst other wastes of * time. */ - exists = dblookup_exact (dbf, manpage_base, info.ext, 1); + exists = dblookup_exact (dbf, manpage_base, info.ext, true); /* Ensure we really have the actual page. Gzip keeps the mtime the * same when it compresses, so we have to compare compression @@ -202,8 +205,8 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path) */ { /* Avoid too much noise in debug output */ - int save_debug = debug_level; - debug_level = 0; + bool save_debug = debug_level; + debug_level = false; ult = ult_src (file, path, &buf, SOFT_LINK | HARD_LINK, NULL); debug_level = save_debug; } @@ -215,10 +218,10 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path) return; } - if (!whatis_hash) - whatis_hash = hashtable_create (&whatis_hashtable_free); + if (!whatis_map) + whatis_map = new_string_map (GL_HASH_MAP, whatis_free); - whatis = hashtable_lookup (whatis_hash, ult, strlen (ult)); + whatis = gl_map_get (whatis_map, ult); if (!whatis) { if (!STRNEQ (ult, file, len)) debug ("\ntest_manfile(): link not in cache:\n" @@ -228,8 +231,9 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path) * looking for whatis info in files containing only '.so * manx/foo.x', which will give us an unobtainable whatis * for the entry. */ + ult_trace = new_string_list (GL_ARRAY_LIST, true); ult = ult_src (file, path, &buf, - SO_LINK | SOFT_LINK | HARD_LINK, &ult_trace); + SO_LINK | SOFT_LINK | HARD_LINK, ult_trace); } if (!ult) { @@ -261,6 +265,7 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path) else { /* Cache miss; go and get the whatis info in its raw state. */ char *file_base = base_name (file); + struct whatis *new_whatis; lg.type = MANPAGE; drop_effective_privs (); @@ -268,11 +273,12 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path) free (file_base); regain_effective_privs (); - whatis = XMALLOC (struct whatis_hashent); - whatis->whatis = lg.whatis ? xstrdup (lg.whatis) : NULL; + new_whatis = XMALLOC (struct whatis); + new_whatis->whatis = lg.whatis ? xstrdup (lg.whatis) : NULL; /* We filled out ult_trace above. */ - memcpy (&whatis->trace, &ult_trace, sizeof (ult_trace)); - hashtable_install (whatis_hash, ult, strlen (ult), whatis); + new_whatis->trace = ult_trace; + gl_map_put (whatis_map, xstrdup (ult), new_whatis); + whatis = new_whatis; } debug ("\"%s\"\n", lg.whatis); @@ -281,15 +287,11 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path) info.pointer = NULL; /* direct page, so far */ info.filter = lg.filters; if (lg.whatis) { - struct page_description *descs = - parse_descriptions (manpage_base, lg.whatis); - if (descs) { - if (!opt_test) - store_descriptions (dbf, descs, &info, - path, manpage_base, - &whatis->trace); - free_descriptions (descs); - } + gl_list_t descs = parse_descriptions (manpage_base, lg.whatis); + if (!opt_test) + store_descriptions (dbf, descs, &info, path, + manpage_base, whatis->trace); + gl_list_free (descs); } else if (quiet < 2) { (void) stat (ult, &buf); if (buf.st_size == 0) @@ -311,8 +313,8 @@ static void add_dir_entries (MYDBM_FILE dbf, const char *path, char *infile) int len; struct dirent *newdir; DIR *dir; - char **names; - size_t names_len, names_max, i; + gl_list_t names; + const char *name; manpage = xasprintf ("%s/%s/", path, infile); len = strlen (manpage); @@ -329,9 +331,7 @@ static void add_dir_entries (MYDBM_FILE dbf, const char *path, char *infile) return; } - names_len = 0; - names_max = 1024; - names = XNMALLOC (names_max, char *); + names = new_string_list (GL_ARRAY_LIST, false); /* strlen(newdir->d_name) could be replaced by newdir->d_reclen */ @@ -339,24 +339,19 @@ static void add_dir_entries (MYDBM_FILE dbf, const char *path, char *infile) if (*newdir->d_name == '.' && strlen (newdir->d_name) < (size_t) 3) continue; - if (names_len >= names_max) { - names_max *= 2; - names = xnrealloc (names, names_max, sizeof (char *)); - } - names[names_len++] = xstrdup (newdir->d_name); + gl_list_add_last (names, xstrdup (newdir->d_name)); } closedir (dir); - order_files (infile, names, names_len); + order_files (infile, &names); - for (i = 0; i < names_len; ++i) { - manpage = appendstr (manpage, names[i], (void *) 0); + GL_LIST_FOREACH_START (names, name) { + manpage = appendstr (manpage, name, (void *) 0); test_manfile (dbf, manpage, path); *(manpage + len) = '\0'; - free (names[i]); - } + } GL_LIST_FOREACH_END (names); - free (names); + gl_list_free (names); free (manpage); } @@ -379,11 +374,8 @@ void chown_if_possible (const char *path) (st.st_uid != man_owner->pw_uid || st.st_gid != man_owner->pw_gid)) { debug ("fixing ownership of %s\n", path); -#ifdef HAVE_LCHOWN - xlchown (path, man_owner->pw_uid, man_owner->pw_gid); -#else - xchown (path, man_owner->pw_uid, man_owner->pw_gid); -#endif + if (lchown (path, man_owner->pw_uid, man_owner->pw_gid) < 0) + error (FATAL, 0, _("can't chown %s"), path); } } #else /* !MAN_OWNER */ @@ -652,12 +644,12 @@ int create_db (const char *manpath, const char *catpath) } /* Make sure an existing database is essentially sane. */ -static int sanity_check_db (MYDBM_FILE dbf) +static bool sanity_check_db (MYDBM_FILE dbf) { datum key; if (dbver_rd (dbf)) - return 0; + return false; key = MYDBM_FIRSTKEY (dbf); while (MYDBM_DPTR (key) != NULL) { @@ -668,7 +660,7 @@ static int sanity_check_db (MYDBM_FILE dbf) debug ("warning: %s has a key with no content (%s); " "rebuilding\n", database, MYDBM_DPTR (key)); MYDBM_FREE_DPTR (key); - return 0; + return false; } MYDBM_FREE_DPTR (content); nextkey = MYDBM_NEXTKEY (dbf, key); @@ -676,7 +668,7 @@ static int sanity_check_db (MYDBM_FILE dbf) key = nextkey; } - return 1; + return true; } /* routine to update the db, ensure that it is consistent with the @@ -771,38 +763,38 @@ pointers_next: * out that this is better handled in look_for_file() itself. */ static int count_glob_matches (const char *name, const char *ext, - char **source, struct timespec db_mtime) + gl_list_t source, struct timespec db_mtime) { - char **walk; + const char *walk; int count = 0; - for (walk = source; walk && *walk; ++walk) { + GL_LIST_FOREACH_START (source, walk) { struct mandata info; struct stat statbuf; char *buf; memset (&info, 0, sizeof (struct mandata)); - if (stat (*walk, &statbuf) == -1) { + if (stat (walk, &statbuf) == -1) { debug ("count_glob_matches: excluding %s " - "because stat failed\n", *walk); + "because stat failed\n", walk); continue; } if (db_mtime.tv_sec != (time_t) -1 && timespec_cmp (get_stat_mtime (&statbuf), db_mtime) <= 0) { debug ("count_glob_matches: excluding %s, " - "no newer than database\n", *walk); + "no newer than database\n", walk); continue; } - buf = filename_info (*walk, &info, name); + buf = filename_info (walk, &info, name); if (buf) { if (STREQ (ext, info.ext)) ++count; free (info.name); free (buf); } - } + } GL_LIST_FOREACH_END (source); return count; } @@ -811,7 +803,7 @@ static int count_glob_matches (const char *name, const char *ext, * page. */ static int purge_normal (MYDBM_FILE dbf, const char *name, - struct mandata *info, char **found) + struct mandata *info, gl_list_t found) { struct timespec t; @@ -834,8 +826,8 @@ static int purge_normal (MYDBM_FILE dbf, const char *name, /* Decide whether to purge a reference to a WHATIS_MAN or WHATIS_CAT page. */ static int purge_whatis (MYDBM_FILE dbf, const char *path, int cat, - const char *name, struct mandata *info, char **found, - struct timespec db_mtime) + const char *name, struct mandata *info, + gl_list_t found, struct timespec db_mtime) { /* TODO: On some systems, the cat page extension differs from the * man page extension, so this may be too strict. @@ -852,7 +844,7 @@ static int purge_whatis (MYDBM_FILE dbf, const char *path, int cat, debug ("%s(%s): whatis replaced by real page; " "forcing a rescan just in case\n", name, info->ext); - force_rescan = 1; + force_rescan = true; return 0; } else if (STREQ (info->pointer, "-")) { /* This is broken; a WHATIS_MAN should never have an empty @@ -870,23 +862,26 @@ static int purge_whatis (MYDBM_FILE dbf, const char *path, int cat, debug ("%s(%s): whatis had empty pointer; " "forcing a rescan just in case\n", name, info->ext); - force_rescan = 1; + force_rescan = true; return 1; } else { /* Does the real page still exist? */ - char **real_found; - int save_debug = debug_level; + gl_list_t real_found; + bool save_debug = debug_level; struct timespec t; + int count; - debug_level = 0; + debug_level = false; real_found = look_for_file (path, info->ext, info->pointer, cat, LFF_MATCHCASE); debug_level = save_debug; t.tv_sec = -1; t.tv_nsec = -1; - if (count_glob_matches (info->pointer, info->ext, real_found, - t)) + count = count_glob_matches (info->pointer, info->ext, + real_found, t); + gl_list_free (real_found); + if (count) return 0; if (!opt_test) @@ -923,7 +918,7 @@ static int check_multi_key (const char *name, const char *content) if (!valid) { debug ("%s: broken multi key \"%s\", " "forcing a rescan\n", name, content); - force_rescan = 1; + force_rescan = true; return 1; } @@ -985,8 +980,8 @@ int purge_missing (const char *manpath, const char *catpath, datum content, nextkey; struct mandata entry; char *nicekey, *tab; - int save_debug; - char **found; + bool save_debug; + gl_list_t found; /* Ignore db identifier keys. */ if (*MYDBM_DPTR (key) == '$') { @@ -1025,7 +1020,7 @@ int purge_missing (const char *manpath, const char *catpath, split_content (MYDBM_DPTR (content), &entry); save_debug = debug_level; - debug_level = 0; /* look_for_file() is quite noisy */ + debug_level = false; /* look_for_file() is quite noisy */ if (entry.id <= WHATIS_MAN) found = look_for_file (manpath, entry.ext, entry.name ? entry.name @@ -1051,6 +1046,7 @@ int purge_missing (const char *manpath, const char *catpath, count += purge_whatis (dbf, catpath, 1, nicekey, &entry, found, db_mtime); + gl_list_free (found); free (nicekey); free_mandata_elements (&entry); diff --git a/src/descriptions.c b/src/descriptions.c index 009a50ba..09295b8e 100644 --- a/src/descriptions.c +++ b/src/descriptions.c @@ -27,21 +27,36 @@ #include <string.h> #include <stdlib.h> +#include "gl_array_list.h" +#include "gl_xlist.h" + #include "manconfig.h" #include "descriptions.h" +/* Free a page description. */ +void page_description_free (const void *value) +{ + struct page_description *desc = (struct page_description *) value; + + free (desc->name); + free (desc->whatis); + free (desc); +} + /* Parse the description in a whatis line returned by find_name() into a - * sequence of names and whatis descriptions. + * list of names and whatis descriptions. */ -struct page_description *parse_descriptions (const char *base, - const char *whatis) +gl_list_t parse_descriptions (const char *base, const char *whatis) { const char *sep, *nextsep; - struct page_description *desc = NULL, *head = NULL; + gl_list_t descs; int seen_base = 0; + descs = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, + page_description_free, true); + if (!whatis) - return NULL; + return descs; sep = whatis; @@ -74,7 +89,7 @@ struct page_description *parse_descriptions (const char *base, dash = strstr (record, " - "); if (dash) names = xstrndup (record, dash - record); - else if (!desc) + else if (!gl_list_size (descs)) /* Some pages have a NAME section with just the page * name and no whatis. We might as well include * this. @@ -93,6 +108,7 @@ struct page_description *parse_descriptions (const char *base, for (token = strtok (names, ","); token; token = strtok (NULL, ",")) { char *name = trim_spaces (token); + struct page_description *desc; /* Skip name tokens containing whitespace. They are * almost never useful as manual page names. @@ -103,16 +119,10 @@ struct page_description *parse_descriptions (const char *base, } /* Allocate new description node. */ - if (head) { - desc->next = xmalloc (sizeof *desc); - desc = desc->next; - } else { - desc = xmalloc (sizeof *desc); - head = desc; - } + desc = xmalloc (sizeof *desc); desc->name = name; /* steal memory */ desc->whatis = dash ? trim_spaces (dash + 3) : NULL; - desc->next = NULL; + gl_list_add_last (descs, desc); if (base && STREQ (base, desc->name)) seen_base = 1; @@ -129,33 +139,18 @@ next: * list. */ if (base && !seen_base) { - if (head) { - desc->next = xmalloc (sizeof *desc); - desc = desc->next; - desc->whatis = - head->whatis ? xstrdup (head->whatis) : NULL; - } else { - desc = xmalloc (sizeof *desc); - head = desc; - desc->whatis = NULL; - } + struct page_description *desc = xmalloc (sizeof *desc); + desc->name = xstrdup (base); - desc->next = NULL; + desc->whatis = NULL; + if (gl_list_size (descs)) { + const struct page_description *first = + gl_list_get_at (descs, 0); + if (first->whatis) + desc->whatis = xstrdup (first->whatis); + } + gl_list_add_last (descs, desc); } - return head; -} - -/* Free a description list and all its contents. */ -void free_descriptions (struct page_description *head) -{ - struct page_description *desc = head, *prev; - - while (desc) { - free (desc->name); - free (desc->whatis); - prev = desc; - desc = desc->next; - free (prev); - } + return descs; } diff --git a/src/descriptions.h b/src/descriptions.h index a0161be8..38ae412a 100644 --- a/src/descriptions.h +++ b/src/descriptions.h @@ -20,21 +20,18 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "gl_list.h" + #include "db_storage.h" struct page_description { char *name; char *whatis; - struct page_description *next; }; -struct ult_trace; - -extern struct page_description *parse_descriptions (const char *base, - const char *whatis); -extern void store_descriptions (MYDBM_FILE dbf, - const struct page_description *head, +/* Returns a list of struct page_description. */ +extern gl_list_t parse_descriptions (const char *base, const char *whatis); +extern void store_descriptions (MYDBM_FILE dbf, gl_list_t descs, struct mandata *info, const char *path, const char *base, - struct ult_trace *trace); -extern void free_descriptions (struct page_description *head); + gl_list_t trace); diff --git a/src/descriptions_store.c b/src/descriptions_store.c index c473aee5..47d0b912 100644 --- a/src/descriptions_store.c +++ b/src/descriptions_store.c @@ -24,6 +24,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -31,9 +32,12 @@ #include "gettext.h" #define _(String) gettext (String) +#include "error.h" +#include "gl_list.h" + #include "manconfig.h" -#include "error.h" +#include "glcontainers.h" #include "db_storage.h" @@ -60,39 +64,38 @@ static int is_prefix (const char *path, const char *dir) /* Take a list of descriptions returned by parse_descriptions() and store * it into the database. */ -void store_descriptions (MYDBM_FILE dbf, const struct page_description *head, - struct mandata *info, - const char *path, const char *base, - struct ult_trace *trace) +void store_descriptions (MYDBM_FILE dbf, gl_list_t descs, struct mandata *info, + const char *path, const char *base, gl_list_t trace) { const struct page_description *desc; char save_id = info->id; - size_t i; + const char *trace_name; - if (trace) { - for (i = 0; i < trace->len; ++i) - debug ("trace->names[%zu] = '%s'\n", - i, trace->names[i]); + if (gl_list_size (descs) && trace) { + GL_LIST_FOREACH_START (trace, trace_name) + debug ("trace: '%s'\n", trace_name); + GL_LIST_FOREACH_END (trace); } - for (desc = head; desc; desc = desc->next) { + GL_LIST_FOREACH_START (descs, desc) { /* Either it's the real thing or merely a reference. Get the * id and pointer right in either case. */ - int found_real_page = 0; - int found_external = 0; + bool found_real_page = false; + bool found_external = false; if (STREQ (base, desc->name)) { info->id = save_id; info->pointer = NULL; info->whatis = desc->whatis; - found_real_page = 1; + found_real_page = true; } else if (trace) { - for (i = 0; i < trace->len; ++i) { + size_t i = 0; + GL_LIST_FOREACH_START (trace, trace_name) { struct mandata trace_info; char *buf; - buf = filename_info (trace->names[i], + buf = filename_info (trace_name, &trace_info, ""); if (trace_info.name && STREQ (trace_info.name, desc->name)) { @@ -101,24 +104,25 @@ void store_descriptions (MYDBM_FILE dbf, const struct page_description *head, * hierarchy; skip this * description. */ - found_external = 1; + found_external = true; free (trace_info.name); free (buf); break; } - if (i == trace->len - 1 && + if (i == gl_list_size (trace) - 1 && save_id == SO_MAN) info->id = ULT_MAN; else info->id = save_id; info->pointer = NULL; info->whatis = desc->whatis; - found_real_page = 1; + found_real_page = true; } free (trace_info.name); free (buf); - } + ++i; + } GL_LIST_FOREACH_END (trace); } if (found_external) { @@ -144,5 +148,5 @@ void store_descriptions (MYDBM_FILE dbf, const struct page_description *head, gripe_bad_store (base, info->ext); break; } - } + } GL_LIST_FOREACH_END (descs); } diff --git a/src/globbing.c b/src/globbing.c index 2fc8e24a..017c3611 100644 --- a/src/globbing.c +++ b/src/globbing.c @@ -27,6 +27,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <string.h> #include <stdlib.h> #include <ctype.h> @@ -35,13 +36,17 @@ #include <dirent.h> #include "fnmatch.h" +#include "gl_array_list.h" +#include "gl_hash_map.h" +#include "gl_xlist.h" +#include "gl_xmap.h" #include "regex.h" #include "xvasprintf.h" #include "manconfig.h" #include "error.h" -#include "hashtable.h" +#include "glcontainers.h" #include "cleanup.h" #include "xregcomp.h" @@ -109,23 +114,23 @@ static int parse_layout (const char *layout) } } -struct dirent_hashent { +struct dirent_names { char **names; size_t names_len, names_max; }; -static void dirent_hashtable_free (void *defn) +static void dirent_names_free (const void *value) { - struct dirent_hashent *hashent = defn; + struct dirent_names *cache = (struct dirent_names *) value; size_t i; - for (i = 0; i < hashent->names_len; ++i) - free (hashent->names[i]); - free (hashent->names); - free (hashent); + for (i = 0; i < cache->names_len; ++i) + free (cache->names[i]); + free (cache->names); + free (cache); } -static struct hashtable *dirent_hash = NULL; +static gl_map_t dirent_map = NULL; static int cache_compare (const void *a, const void *b) { @@ -134,17 +139,17 @@ static int cache_compare (const void *a, const void *b) return strcasecmp (left, right); } -static struct dirent_hashent *update_directory_cache (const char *path) +static struct dirent_names *update_directory_cache (const char *path) { - struct dirent_hashent *cache; + struct dirent_names *cache; DIR *dir; struct dirent *entry; - if (!dirent_hash) { - dirent_hash = hashtable_create (&dirent_hashtable_free); - push_cleanup ((cleanup_fun) hashtable_free, dirent_hash, 0); + if (!dirent_map) { + dirent_map = new_string_map (GL_HASH_MAP, dirent_names_free); + push_cleanup ((cleanup_fun) gl_map_free, dirent_map, 0); } - cache = hashtable_lookup (dirent_hash, path, strlen (path)); + cache = (struct dirent_names *) gl_map_get (dirent_map, path); /* Check whether we've got this one already. */ if (cache) { @@ -160,7 +165,7 @@ static struct dirent_hashent *update_directory_cache (const char *path) return NULL; } - cache = XMALLOC (struct dirent_hashent); + cache = XMALLOC (struct dirent_names); cache->names_len = 0; cache->names_max = 1024; cache->names = XNMALLOC (cache->names_max, char *); @@ -179,7 +184,7 @@ static struct dirent_hashent *update_directory_cache (const char *path) qsort (cache->names, cache->names_len, sizeof *cache->names, &cache_compare); - hashtable_install (dirent_hash, path, strlen (path), cache); + gl_map_put (dirent_map, xstrdup (path), cache); closedir (dir); return cache; @@ -197,34 +202,16 @@ static int pattern_compare (const void *a, const void *b) return strncasecmp (key->pattern, memb, key->len); } -static void clear_glob (glob_t *pglob) +static void match_in_directory (const char *path, const char *pattern, + int opts, gl_list_t matched) { - /* look_for_file declares this static, so it's zero-initialised. - * globfree() can deal with checking it before freeing. - */ - globfree (pglob); - - pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; - pglob->gl_offs = 0; -} - -static void match_in_directory (const char *path, const char *pattern, int opts, - glob_t *pglob, size_t *allocated) -{ - struct dirent_hashent *cache; - size_t my_allocated = 0; + struct dirent_names *cache; int flags; regex_t preg; struct pattern_bsearch pattern_start = { NULL, -1 }; char **bsearched; size_t i; - if (!allocated) - allocated = &my_allocated; - if (!*allocated) - clear_glob (pglob); - cache = update_directory_cache (path); if (!cache) { debug ("directory cache update failed\n"); @@ -233,12 +220,6 @@ static void match_in_directory (const char *path, const char *pattern, int opts, debug ("globbing pattern in %s: %s\n", path, pattern); - if (!*allocated) { - *allocated = 4; - pglob->gl_pathv = XNMALLOC (*allocated, char *); - pglob->gl_pathv[0] = NULL; - } - if (opts & LFF_REGEX) flags = REG_EXTENDED | REG_NOSUB | ((opts & LFF_MATCHCASE) ? 0 : REG_ICASE); @@ -280,46 +261,25 @@ static void match_in_directory (const char *path, const char *pattern, int opts, debug ("matched: %s/%s\n", path, cache->names[i]); - if (pglob->gl_pathc >= *allocated) { - *allocated *= 2; - pglob->gl_pathv = xnrealloc ( - pglob->gl_pathv, *allocated, sizeof (char *)); - } - pglob->gl_pathv[pglob->gl_pathc++] = - xasprintf ("%s/%s", path, cache->names[i]); + gl_list_add_last (matched, + xasprintf ("%s/%s", path, cache->names[i])); } if (opts & LFF_REGEX) regfree (&preg); else free (pattern_start.pattern); - - if (pglob->gl_pathc >= *allocated) { - *allocated *= 2; - pglob->gl_pathv = xnrealloc (pglob->gl_pathv, - *allocated, sizeof (char *)); - } - pglob->gl_pathv[pglob->gl_pathc] = NULL; - - return; } -char **look_for_file (const char *hier, const char *sec, - const char *unesc_name, int cat, int opts) +gl_list_t look_for_file (const char *hier, const char *sec, + const char *unesc_name, int cat, int opts) { + gl_list_t matched; char *pattern, *path = NULL; - static glob_t gbuf; - static int cleanup_installed = 0; static int layout = -1; char *name; - if (!cleanup_installed) { - /* appease valgrind */ - push_cleanup ((cleanup_fun) globfree, &gbuf, 0); - cleanup_installed = 1; - } - - clear_glob (&gbuf); + matched = new_string_list (GL_ARRAY_LIST, false); /* This routine only does a minimum amount of matching. It does not find cat files in the alternate cat directory. */ @@ -337,41 +297,39 @@ char **look_for_file (const char *hier, const char *sec, /* allow lookups like "3x foo" to match "../man3/foo.3x" */ if (layout & LAYOUT_GNU) { - glob_t dirs; - size_t i; - size_t allocated = 0; + gl_list_t dirs; + const char *dir; - memset (&dirs, 0, sizeof (dirs)); + dirs = new_string_list (GL_ARRAY_LIST, false); pattern = xasprintf ("%s\t*", cat ? "cat" : "man"); *strrchr (pattern, '\t') = *sec; - match_in_directory (hier, pattern, LFF_MATCHCASE, &dirs, NULL); + match_in_directory (hier, pattern, LFF_MATCHCASE, dirs); free (pattern); pattern = make_pattern (name, sec, opts); - for (i = 0; i < dirs.gl_pathc; ++i) { + GL_LIST_FOREACH_START (dirs, dir) { if (path) *path = '\0'; - match_in_directory (dirs.gl_pathv[i], pattern, opts, - &gbuf, &allocated); - } + match_in_directory (dir, pattern, opts, matched); + } GL_LIST_FOREACH_END (dirs); free (pattern); - globfree (&dirs); + gl_list_free (dirs); } /* Try HPUX style compressed man pages */ - if ((layout & LAYOUT_HPUX) && gbuf.gl_pathc == 0) { + if ((layout & LAYOUT_HPUX) && gl_list_size (matched) == 0) { if (path) *path = '\0'; path = appendstr (path, hier, cat ? "/cat" : "/man", sec, ".Z", (void *) 0); pattern = make_pattern (name, sec, opts); - match_in_directory (path, pattern, opts, &gbuf, NULL); + match_in_directory (path, pattern, opts, matched); free (pattern); } /* Try man pages without the section extension --- IRIX man pages */ - if ((layout & LAYOUT_IRIX) && gbuf.gl_pathc == 0) { + if ((layout & LAYOUT_IRIX) && gl_list_size (matched) == 0) { if (path) *path = '\0'; path = appendstr (path, hier, cat ? "/cat" : "/man", sec, @@ -381,12 +339,12 @@ char **look_for_file (const char *hier, const char *sec, else pattern = xasprintf ("%s.*", name); - match_in_directory (path, pattern, opts, &gbuf, NULL); + match_in_directory (path, pattern, opts, matched); free (pattern); } /* Try Solaris style man page directories */ - if ((layout & LAYOUT_SOLARIS) && gbuf.gl_pathc == 0) { + if ((layout & LAYOUT_SOLARIS) && gl_list_size (matched) == 0) { if (path) *path = '\0'; /* TODO: This needs to be man/sec*, not just man/sec. */ @@ -394,12 +352,12 @@ char **look_for_file (const char *hier, const char *sec, (void *) 0); pattern = make_pattern (name, sec, opts); - match_in_directory (path, pattern, opts, &gbuf, NULL); + match_in_directory (path, pattern, opts, matched); free (pattern); } /* BSD cat pages take the extension .0 */ - if ((layout & LAYOUT_BSD) && gbuf.gl_pathc == 0) { + if ((layout & LAYOUT_BSD) && gl_list_size (matched) == 0) { if (path) *path = '\0'; if (cat) { @@ -412,40 +370,34 @@ char **look_for_file (const char *hier, const char *sec, path = appendstr (path, hier, "/man", sec, (void *) 0); pattern = make_pattern (name, sec, opts); } - match_in_directory (path, pattern, opts, &gbuf, NULL); + match_in_directory (path, pattern, opts, matched); free (pattern); } free (name); free (path); - if (gbuf.gl_pathc == 0) - return NULL; - else - return gbuf.gl_pathv; + return matched; } -char **expand_path (const char *path) +gl_list_t expand_path (const char *path) { int res = 0; - char **result = NULL; + gl_list_t result; glob_t globbuf; - size_t i; + + result = new_string_list (GL_ARRAY_LIST, false); res = glob (path, GLOB_NOCHECK, NULL, &globbuf); /* if glob failed, return the given path */ - if (res != 0) { - result = XNMALLOC (2, char *); - result[0] = xstrdup (path); - result[1] = NULL; - return result; - } - - result = XNMALLOC (globbuf.gl_pathc + 1, char *); - for (i = 0; i < globbuf.gl_pathc; i++) { - result[i] = xstrdup (globbuf.gl_pathv[i]); + if (res != 0) + gl_list_add_last (result, xstrdup (path)); + else { + size_t i; + for (i = 0; i < globbuf.gl_pathc; ++i) + gl_list_add_last (result, + xstrdup (globbuf.gl_pathv[i])); } - result[globbuf.gl_pathc] = NULL; globfree (&globbuf); diff --git a/src/globbing.h b/src/globbing.h index 1c811418..ea9ff001 100644 --- a/src/globbing.h +++ b/src/globbing.h @@ -20,6 +20,8 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "gl_list.h" + enum look_for_file_opts { LFF_MATCHCASE = 1, LFF_REGEX = 2, @@ -27,8 +29,8 @@ enum look_for_file_opts { }; /* globbing.c */ -extern char **look_for_file (const char *hier, const char *sec, - const char *unesc_name, int cat, int opts); +extern gl_list_t look_for_file (const char *hier, const char *sec, + const char *unesc_name, int cat, int opts); /* Expand path with wildcards into list of all existing directories. */ -extern char **expand_path (const char *path); +extern gl_list_t expand_path (const char *path); diff --git a/src/globbing_test.c b/src/globbing_test.c index eb4070a1..5f0878fa 100644 --- a/src/globbing_test.c +++ b/src/globbing_test.c @@ -25,10 +25,12 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include "argp.h" +#include "gl_list.h" #include "progname.h" #include "gettext.h" @@ -38,15 +40,16 @@ #include "manconfig.h" #include "error.h" +#include "glcontainers.h" #include "globbing.h" #include "sandbox.h" man_sandbox *sandbox; /* unused, but needed by libman */ extern const char *extension; -static int match_case = 0; -static int regex_opt = 0; -static int wildcard = 0; +static bool match_case = false; +static bool regex_opt = false; +static bool wildcard = false; static char **remaining_args; const char *argp_program_version = "globbing " PACKAGE_VERSION; @@ -70,22 +73,22 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { case 'd': - debug_level = 1; + debug_level = true; return 0; case 'e': extension = arg; return 0; case 'i': - match_case = 0; + match_case = false; return 0; case 'I': - match_case = 1; + match_case = true; return 0; case 'r': - regex_opt = 1; + regex_opt = true; return 0; case 'w': - wildcard = 1; + wildcard = true; return 0; case 'h': argp_state_help (state, state->out_stream, @@ -115,16 +118,18 @@ int main (int argc, char **argv) exit (FAIL); for (i = 0; i <= 1; i++) { - char **files; + gl_list_t files; + const char *file; files = look_for_file (remaining_args[0], remaining_args[1], remaining_args[2], i, (match_case ? LFF_MATCHCASE : 0) | (regex_opt ? LFF_REGEX : 0) | (wildcard ? LFF_WILDCARD : 0)); - if (files) - while (*files) - printf ("%s\n", *files++); + GL_LIST_FOREACH_START (files, file) + printf ("%s\n", file); + GL_LIST_FOREACH_END (files); + gl_list_free (files); } return 0; } diff --git a/src/lexgrog_test.c b/src/lexgrog_test.c index c310aa0c..4fb39fd1 100644 --- a/src/lexgrog_test.c +++ b/src/lexgrog_test.c @@ -26,6 +26,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -33,6 +34,8 @@ #include <sys/stat.h> #include "argp.h" +#include "error.h" +#include "gl_list.h" #include "progname.h" #include "gettext.h" @@ -42,7 +45,7 @@ #include "manconfig.h" #include "cleanup.h" -#include "error.h" +#include "glcontainers.h" #include "pipeline.h" #include "sandbox.h" #include "security.h" @@ -53,7 +56,8 @@ int quiet = 1; man_sandbox *sandbox; -static int parse_man = 0, parse_cat = 0, show_whatis = 0, show_filters = 0; +static bool parse_man = false, parse_cat = false; +static bool show_whatis = false, show_filters = false; static const char *encoding = NULL; static char **files; static int num_files; @@ -80,19 +84,19 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { case 'd': - debug_level = 1; + debug_level = true; return 0; case 'm': - parse_man = 1; + parse_man = true; return 0; case 'c': - parse_cat = 1; + parse_cat = true; return 0; case 'w': - show_whatis = 1; + show_whatis = true; return 0; case 'f': - show_filters = 1; + show_filters = true; return 0; case 'E': encoding = arg; @@ -119,9 +123,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) "-m -c"); /* defaults: --man, --whatis */ if (!parse_man && !parse_cat) - parse_man = 1; + parse_man = true; if (!show_whatis && !show_filters) - show_whatis = 1; + show_whatis = true; return 0; } return ARGP_ERR_UNKNOWN; @@ -148,7 +152,7 @@ int main (int argc, char **argv) { int type = 0; int i; - int some_failed = 0; + bool some_failed = false; set_program_name (argv[0]); @@ -173,7 +177,7 @@ int main (int argc, char **argv) for (i = 0; i < num_files; ++i) { lexgrog lg; const char *file; - int found = 0; + bool found = false; lg.type = type; @@ -205,13 +209,12 @@ int main (int argc, char **argv) } if (file && find_name (file, "-", &lg, encoding)) { - struct page_description *descs = - parse_descriptions (NULL, lg.whatis); + gl_list_t descs = parse_descriptions (NULL, lg.whatis); const struct page_description *desc; - for (desc = descs; desc; desc = desc->next) { + GL_LIST_FOREACH_START (descs, desc) { if (!desc->name || !desc->whatis) continue; - found = 1; + found = true; printf ("%s", files[i]); if (show_filters) printf (" (%s)", lg.filters); @@ -219,18 +222,20 @@ int main (int argc, char **argv) printf (": \"%s - %s\"", desc->name, desc->whatis); printf ("\n"); - } - free_descriptions (descs); + } GL_LIST_FOREACH_END (descs); + gl_list_free (descs); free (lg.filters); free (lg.whatis); } if (!found) { printf ("%s: parse failed\n", files[i]); - some_failed = 1; + some_failed = true; } } + sandbox_free (sandbox); + if (some_failed) return FATAL; else @@ -40,6 +40,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -48,18 +49,8 @@ #include <errno.h> #include <termios.h> #include <unistd.h> - -#ifndef R_OK -# define R_OK 4 -# define X_OK 1 -#endif /* !R_OK */ - #include <limits.h> - -#if HAVE_FCNTL_H -# include <fcntl.h> -#endif - +#include <fcntl.h> #include <ctype.h> #include <signal.h> #include <time.h> @@ -68,13 +59,19 @@ #include "argp.h" #include "dirname.h" +#include "gl_array_list.h" +#include "gl_hash_map.h" +#include "gl_list.h" +#include "gl_xlist.h" +#include "gl_xmap.h" #include "minmax.h" #include "progname.h" #include "regex.h" #include "stat-time.h" #include "utimens.h" -#include "xvasprintf.h" #include "xgetcwd.h" +#include "xvasprintf.h" +#include "xstdopen.h" #include "gettext.h" #include <locale.h> @@ -85,7 +82,7 @@ #include "error.h" #include "cleanup.h" -#include "hashtable.h" +#include "glcontainers.h" #include "pipeline.h" #include "pathsearch.h" #include "linelength.h" @@ -137,7 +134,7 @@ char *lang; #define TFMT_PROG "mandb_tfmt" #undef ALT_EXT_FORMAT /* allow external formatters located in cat hierarchy */ -static int global_manpath = -1; /* global or user manual page hierarchy? */ +static bool global_manpath; /* global or user manual page hierarchy? */ static int skip; /* page exists but has been skipped */ #if defined _AIX || defined __sgi @@ -175,27 +172,20 @@ enum opts { OPT_MAX }; -struct string_llist; -struct string_llist { - const char *name; - struct string_llist *next; -}; - - -static char *manpathlist[MAXDIRS]; +static gl_list_t manpathlist; /* globals */ int quiet = 1; char *database = NULL; extern const char *extension; /* for globbing.c */ extern char *user_config_file; /* defined in manp.c */ -extern int disable_cache; +extern bool disable_cache; extern int min_cat_width, max_cat_width, cat_width; man_sandbox *sandbox; /* locals */ static const char *alt_system_name; -static const char **section_list; +static gl_list_t section_list; static const char *section; static char *colon_sep_section_list; static const char *preprocessors; @@ -207,33 +197,33 @@ static char *less; static const char *std_sections[] = STD_SECTIONS; static char *manp; static const char *external; -static struct hashtable *db_hash = NULL; +static gl_map_t db_map = NULL; -static int troff; +static bool troff; static const char *roff_device = NULL; static const char *want_encoding = NULL; #ifdef NROFF_WARNINGS static const char default_roff_warnings[] = "mac"; -static struct string_llist *roff_warnings = NULL; +static gl_list_t roff_warnings; #endif /* NROFF_WARNINGS */ -static int global_apropos; -static int print_where, print_where_cat; -static int catman; -static int local_man_file; -static int findall; -static int update; -static int match_case; -static int regex_opt; -static int wildcard; -static int names_only; +static bool global_apropos; +static bool print_where, print_where_cat; +static bool catman; +static bool local_man_file; +static bool findall; +static bool update; +static bool match_case; +static bool regex_opt; +static bool wildcard; +static bool names_only; static int ult_flags = SO_LINK | SOFT_LINK | HARD_LINK; static const char *recode = NULL; -static int no_hyphenation; -static int no_justification; -static int subpages = 1; +static bool no_hyphenation; +static bool no_justification; +static bool subpages = true; -static int ascii; /* insert tr in the output pipe */ -static int save_cat; /* security breach? Can we save the cat? */ +static bool ascii; /* insert tr in the output pipe */ +static bool save_cat; /* security breach? Can we save the cat? */ static int first_arg; @@ -248,9 +238,9 @@ static struct timespec man_modtime; /* modtime of man page, for * commit_tmp_cat() */ # ifdef TROFF_IS_GROFF -static int ditroff; +static bool ditroff; static const char *gxditview; -static int htmlout; +static bool htmlout; static const char *html_pager; # endif /* TROFF_IS_GROFF */ @@ -352,7 +342,7 @@ static void init_html_pager (void) static error_t parse_opt (int key, char *arg, struct argp_state *state) { - static int apropos, whatis; /* retain values between calls */ + static bool apropos, whatis; /* retain values between calls */ /* Please keep these keys in the same order as in options above. */ switch (key) { @@ -360,7 +350,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) user_config_file = arg; return 0; case 'd': - debug_level = 1; + debug_level = true; return 0; case 'D': /* discard all preset options */ @@ -369,11 +359,11 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) print_where = print_where_cat = ascii = match_case = regex_opt = wildcard = names_only = - no_hyphenation = no_justification = 0; + no_hyphenation = no_justification = false; #ifdef TROFF_IS_GROFF - ditroff = 0; + ditroff = false; gxditview = NULL; - htmlout = 0; + htmlout = false; init_html_pager (); #endif roff_device = want_encoding = extension = pager = @@ -390,13 +380,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) const char *warning; for (warning = strtok (s, ","); warning; - warning = strtok (NULL, ",")) { - struct string_llist *new; - new = xmalloc (sizeof *new); - new->name = xstrdup (warning); - new->next = roff_warnings; - roff_warnings = new; - } + warning = strtok (NULL, ",")) + gl_list_add_last (roff_warnings, + xstrdup (warning)); free (s); } @@ -405,26 +391,26 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) case 'f': external = WHATIS; - whatis = 1; + whatis = true; return 0; case 'k': external = APROPOS; - apropos = 1; + apropos = true; return 0; case 'K': - global_apropos = 1; + global_apropos = true; return 0; case 'w': - print_where = 1; + print_where = true; return 0; case 'W': - print_where_cat = 1; + print_where_cat = true; return 0; case 'l': - local_man_file = 1; + local_man_file = true; return 0; case 'c': - catman = 1; + catman = true; return 0; case 'R': recode = arg; @@ -449,30 +435,30 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) extension = arg; return 0; case 'i': - match_case = 0; + match_case = false; return 0; case 'I': - match_case = 1; + match_case = true; return 0; case OPT_REGEX: - regex_opt = 1; - findall = 1; + regex_opt = true; + findall = true; return 0; case OPT_WILDCARD: - wildcard = 1; - findall = 1; + wildcard = true; + findall = true; return 0; case OPT_NAMES: - names_only = 1; + names_only = true; return 0; case 'a': - findall = 1; + findall = true; return 0; case 'u': - update = 1; + update = true; return 0; case OPT_NO_SUBPAGES: - subpages = 0; + subpages = false; return 0; case 'P': @@ -482,7 +468,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) prompt_string = arg; return 0; case '7': - ascii = 1; + ascii = true; return 0; case 'E': want_encoding = arg; @@ -490,17 +476,17 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) roff_device = want_encoding; return 0; case OPT_NO_HYPHENATION: - no_hyphenation = 1; + no_hyphenation = true; return 0; case OPT_NO_JUSTIFICATION: - no_justification = 1; + no_justification = true; return 0; case 'p': preprocessors = arg; return 0; #ifdef HAS_TROFF case 't': - troff = 1; + troff = true; return 0; case 'T': /* Traditional nroff knows -T; troff does not (gets @@ -508,27 +494,27 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) * does -T imply -t? */ roff_device = (arg ? arg : "ps"); - troff = 1; + troff = true; return 0; case 'H': # ifdef TROFF_IS_GROFF if (arg) html_pager = arg; - htmlout = 1; - troff = 1; + htmlout = true; + troff = true; roff_device = "html"; # endif /* TROFF_IS_GROFF */ return 0; case 'X': # ifdef TROFF_IS_GROFF - troff = 1; + troff = true; gxditview = (arg ? arg : "75"); # endif /* TROFF_IS_GROFF */ return 0; case 'Z': # ifdef TROFF_IS_GROFF - ditroff = 1; - troff = 1; + ditroff = true; + troff = true; # endif /* TROFF_IS_GROFF */ return 0; #endif /* HAS_TROFF */ @@ -539,8 +525,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) break; case ARGP_KEY_SUCCESS: /* check for incompatible options */ - if (troff + whatis + apropos + catman + - (print_where || print_where_cat) > 1) { + if ((int) troff + (int) whatis + (int) apropos + + (int) catman + + (int) (print_where || print_where_cat) > 1) { char *badopts = xasprintf ("%s%s%s%s%s%s", troff ? "-[tTZH] " : "", @@ -553,7 +540,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) _("%s: incompatible options"), badopts); } - if (regex_opt + wildcard > 1) { + if ((int) regex_opt + (int) wildcard > 1) { char *badopts = xasprintf ("%s%s", regex_opt ? "--regex " : "", @@ -618,48 +605,6 @@ static void gripe_no_name (const char *sect) exit (FAIL); } -/* In case we're set-id, double-check that our standard file descriptors are - * open in a standard way. See: - * - * http://austingroupbugs.net/view.php?id=173 - */ -static void check_standard_fds (void) -{ - int flags, mode; - - /* We can't even write an error message in this case, so check it - * first. - */ - flags = fcntl (2, F_GETFL); - if (flags < 0) - exit (FATAL); - mode = flags & O_ACCMODE; - if (mode != O_WRONLY && mode != O_RDWR) - exit (FATAL); - - flags = fcntl (0, F_GETFL); - if (flags < 0) { - fprintf (stderr, "stdin not open!\n"); - exit (FATAL); - } - mode = flags & O_ACCMODE; - if (mode != O_RDONLY && mode != O_RDWR) { - fprintf (stderr, "stdin not open for reading!\n"); - exit (FATAL); - } - - flags = fcntl (1, F_GETFL); - if (flags < 0) { - fprintf (stderr, "stdout not open!\n"); - exit (FATAL); - } - mode = flags & O_ACCMODE; - if (mode != O_WRONLY && mode != O_RDWR) { - fprintf (stderr, "stdout not open for writing!\n"); - exit (FATAL); - } -} - static struct termios tms; static int tms_set = 0; static pid_t tms_pid = 0; @@ -716,7 +661,7 @@ static void heirloom_line_length (void *data) } #endif /* HEIRLOOM_NROFF */ -static pipecmd *add_roff_line_length (pipecmd *cmd, int *save_cat_p) +static pipecmd *add_roff_line_length (pipecmd *cmd, bool *save_cat_p) { int length; pipecmd *ret = NULL; @@ -733,7 +678,7 @@ static pipecmd *add_roff_line_length (pipecmd *cmd, int *save_cat_p) debug ("Terminal width %d not within cat page range " "[%d, %d]\n", line_length, min_cat_width, max_cat_width); - *save_cat_p = 0; + *save_cat_p = false; } } @@ -976,17 +921,17 @@ static char *locale_manpath (const char *manpath) */ static const char *is_section (const char *name) { - const char **vs; + const char *vs; - for (vs = section_list; *vs; vs++) { - if (STREQ (*vs, name)) + GL_LIST_FOREACH_START (section_list, vs) { + if (STREQ (vs, name)) return name; /* allow e.g. 3perl but disallow 8139too and libfoo */ - if (strlen (*vs) == 1 && CTYPE (isdigit, **vs) && + if (strlen (vs) == 1 && CTYPE (isdigit, *vs) && strlen (name) > 1 && !CTYPE (isdigit, name[1]) && - STRNEQ (*vs, name, 1)) + STRNEQ (vs, name, 1)) return name; - } + } GL_LIST_FOREACH_END (section_list); return NULL; } @@ -1067,27 +1012,27 @@ static char *get_preprocessors (pipeline *decomp, const char *dbfilters, if (dbfilters && (dbfilters[0] != '-') && !preprocessors) { pp_string = xstrdup (dbfilters); pp_source = "database"; - save_cat = 1; + save_cat = true; } else if (preprocessors) { pp_string = xstrdup (preprocessors); pp_source = "command line"; - save_cat = 0; + save_cat = false; } else if ((pp_string = get_preprocessors_from_file (decomp, prefixes))) { pp_source = "file"; - save_cat = 1; + save_cat = true; } else if ((env = getenv ("MANROFFSEQ"))) { pp_string = xstrdup (env); pp_source = "environment"; - save_cat = 0; + save_cat = false; } else if (!dbfilters) { pp_string = xstrdup (DEFAULT_MANROFFSEQ); pp_source = "default"; - save_cat = 1; + save_cat = true; } else { pp_string = xstrdup (""); pp_source = "no filters"; - save_cat = 1; + save_cat = true; } debug ("pre-processors `%s' from %s\n", pp_string, pp_source); @@ -1311,7 +1256,7 @@ static pipeline *make_roff_command (const char *dir, const char *file, do { #ifdef NROFF_WARNINGS - struct string_llist *cur; + const char *warning; #endif /* NROFF_WARNINGS */ int wants_dev = 0; /* filter wants a dev argument */ int wants_post = 0; /* postprocessor arguments */ @@ -1359,7 +1304,7 @@ static pipeline *make_roff_command (const char *dir, const char *file, if (troff) { cmd = pipecmd_new_argstr (get_def ("troff", TROFF)); - save_cat = 0; + save_cat = false; } else cmd = pipecmd_new_argstr (get_def ("nroff", NROFF)); @@ -1379,9 +1324,9 @@ static pipeline *make_roff_command (const char *dir, const char *file, #endif /* TROFF_IS_GROFF || HEIRLOOM_NROFF */ #ifdef NROFF_WARNINGS - for (cur = roff_warnings; cur; - cur = cur->next) - pipecmd_argf (cmd, "-w%s", cur->name); + GL_LIST_FOREACH_START (roff_warnings, warning) + pipecmd_argf (cmd, "-w%s", warning); + GL_LIST_FOREACH_END (roff_warnings); #endif /* NROFF_WARNINGS */ #ifdef HEIRLOOM_NROFF @@ -1478,7 +1423,7 @@ static pipeline *make_browser (const char *pattern, const char *file) pipeline *p; pipecmd *cmd; char *browser = xmalloc (1); - int found_percent_s = 0; + bool found_percent_s = false; char *percent; char *esc_file; @@ -1502,7 +1447,7 @@ static pipeline *make_browser (const char *pattern, const char *file) browser = appendstr (browser, esc_file, (void *) 0); free (esc_file); - found_percent_s = 1; + found_percent_s = true; break; default: len = strlen (browser); /* cannot be NULL */ @@ -2204,7 +2149,7 @@ static int display (const char *dir, const char *man_file, int prefixes = 0; pipeline *format_cmd; /* command to format man_file to stdout */ char *formatted_encoding = NULL; - int display_to_stdout; + bool display_to_stdout; pipeline *decomp = NULL; int decomp_errno = 0; @@ -2308,10 +2253,10 @@ static int display (const char *dir, const char *man_file, display_to_stdout = troff; #ifdef TROFF_IS_GROFF if (htmlout) - display_to_stdout = 0; + display_to_stdout = false; #endif if (recode) - display_to_stdout = 1; + display_to_stdout = true; if (display_to_stdout) { /* If we're reading stdin via '-l -', man_file is "". See @@ -2367,7 +2312,7 @@ static int display (const char *dir, const char *man_file, || local_man_file || recode || disable_cache) - save_cat = 0; + save_cat = false; if (!man_file) { /* Stray cat. */ @@ -2375,7 +2320,7 @@ static int display (const char *dir, const char *man_file, format = 0; } else if (!cat_file) { assert (man_file); - save_cat = 0; + save_cat = false; format = 1; } else if (format && save_cat) { char *cat_dir; @@ -2419,7 +2364,7 @@ static int display (const char *dir, const char *man_file, (format ? man_file : cat_file, R_OK); debug ("format: %d, save_cat: %d, found: %d\n", - format, save_cat, found); + format, (int) save_cat, found); if (!found) { pipeline_free (format_cmd); @@ -2692,25 +2637,25 @@ static int get_ult_flags (char from_db, char id) } /* Is this candidate substantially a duplicate of a previous one? - * Returns non-zero if so, otherwise zero. + * Returns true if so, otherwise false. */ -static int duplicate_candidates (struct candidate *left, - struct candidate *right) +static bool duplicate_candidates (struct candidate *left, + struct candidate *right) { const char *slash1, *slash2; struct locale_bits bits1, bits2; - int ret; + bool ret; if (left->ult && right->ult && STREQ (left->ult, right->ult)) - return 1; /* same ultimate source file */ + return true; /* same ultimate source file */ if (!STREQ (left->source->name, right->source->name) || !STREQ (left->source->sec, right->source->sec) || !STREQ (left->source->ext, right->source->ext)) - return 0; /* different name/section/extension */ + return false; /* different name/section/extension */ if (STREQ (left->path, right->path)) - return 1; /* same path */ + return true; /* same path */ /* Figure out if we've had a sufficiently similar candidate for this * language already. @@ -2720,7 +2665,7 @@ static int duplicate_candidates (struct candidate *left, if (!slash1 || !slash2 || !STRNEQ (left->path, right->path, MAX (slash1 - left->path, slash2 - right->path))) - return 0; /* different path base */ + return false; /* different path base */ unpack_locale_bits (++slash1, &bits1); unpack_locale_bits (++slash2, &bits2); @@ -2728,12 +2673,12 @@ static int duplicate_candidates (struct candidate *left, if (!STREQ (bits1.language, bits2.language) || !STREQ (bits1.territory, bits2.territory) || !STREQ (bits1.modifier, bits2.modifier)) - ret = 0; /* different language/territory/modifier */ + ret = false; /* different language/territory/modifier */ else /* Everything seems to be the same; we can find nothing to * choose between them. */ - ret = 1; + ret = true; free_locale_bits (&bits1); free_locale_bits (&bits2); @@ -2744,7 +2689,6 @@ static int compare_candidates (const struct candidate *left, const struct candidate *right) { const struct mandata *lsource = left->source, *rsource = right->source; - int sec_left = 0, sec_right = 0; int cmp; const char *slash1, *slash2; @@ -2771,7 +2715,7 @@ static int compare_candidates (const struct candidate *left, * moved out of order with respect to their parent sections. */ if (strcmp (lsource->ext, rsource->ext)) { - const char **sp; + size_t index_left, index_right; /* If the user asked for an explicit section, sort exact * matches first. @@ -2787,24 +2731,30 @@ static int compare_candidates (const struct candidate *left, } /* Find out whether lsource->ext is ahead of rsource->ext in - * section_list. + * section_list. Sections missing from section_list are + * sorted to the end. */ - for (sp = section_list; *sp; ++sp) { - if (!*(*sp + 1)) { - /* No extension */ - if (!sec_left && **sp == *(lsource->ext)) - sec_left = sp - section_list + 1; - if (!sec_right && **sp == *(rsource->ext)) - sec_right = sp - section_list + 1; - } else if (STREQ (*sp, lsource->ext)) { - sec_left = sp - section_list + 1; - } else if (STREQ (*sp, rsource->ext)) { - sec_right = sp - section_list + 1; - } - /* Keep looking for a more specific match */ + index_left = gl_list_indexof (section_list, lsource->ext); + if (index_left == (size_t) -1 && strlen (lsource->ext) > 1) { + char *sec_left = xstrndup (lsource->ext, 1); + index_left = gl_list_indexof (section_list, sec_left); + free (sec_left); + if (index_left == (size_t) -1) + index_left = gl_list_size (section_list); + } + index_right = gl_list_indexof (section_list, rsource->ext); + if (index_right == (size_t) -1 && strlen (rsource->ext) > 1) { + char *sec_right = xstrndup (rsource->ext, 1); + index_right = gl_list_indexof (section_list, + sec_right); + free (sec_right); + if (index_right == (size_t) -1) + index_right = gl_list_size (section_list); } - if (sec_left != sec_right) - return sec_left - sec_right; + if (index_left < index_right) + return -1; + else if (index_left > index_right) + return 1; cmp = strcmp (lsource->sec, rsource->sec); if (cmp) @@ -3086,8 +3036,8 @@ static int try_section (const char *path, const char *sec, const char *name, struct candidate **cand_head) { int found = 0; - char **names = NULL, **np; - size_t names_len = 0; + gl_list_t names = NULL; + const char *found_name; char cat = 0; int lff_opts = (match_case ? LFF_MATCHCASE : 0) | (regex_opt ? LFF_REGEX : 0) | @@ -3101,7 +3051,7 @@ static int try_section (const char *path, const char *sec, const char *name, */ names = look_for_file (path, sec, name, 0, lff_opts); - if (!names) + if (!gl_list_size (names)) /* * No files match. * See if there's a preformatted page around that @@ -3113,18 +3063,17 @@ static int try_section (const char *path, const char *sec, const char *name, return 1; if (!troff && !want_encoding && !recode) { + gl_list_free (names); names = look_for_file (path, sec, name, 1, lff_opts); cat = 1; } } - for (np = names; np && *np; np++) - ++names_len; - order_files (path, names, names_len); + order_files (path, &names); - for (np = names; np && *np; np++) { + GL_LIST_FOREACH_START (names, found_name) { struct mandata *info = infoalloc (); - char *info_buffer = filename_info (*np, info, name); + char *info_buffer = filename_info (found_name, info, name); const char *ult; int f; @@ -3138,16 +3087,16 @@ static int try_section (const char *path, const char *sec, const char *name, * must be either ULT_MAN or SO_MAN. ult_src() can tell us * which. */ - ult = ult_src (*np, path, NULL, ult_flags, NULL); + ult = ult_src (found_name, path, NULL, ult_flags, NULL); if (!ult) { /* already warned */ - debug ("try_section(): bad link %s\n", *np); + debug ("try_section(): bad link %s\n", found_name); free (info_buffer); info->addr = NULL; free_mandata_struct (info); continue; } - if (STREQ (ult, *np)) + if (STREQ (ult, found_name)) info->id = ULT_MAN; else info->id = SO_MAN; @@ -3164,8 +3113,9 @@ static int try_section (const char *path, const char *sec, const char *name, free_mandata_struct (info); } /* Don't free info and info_buffer here. */ - } + } GL_LIST_FOREACH_END (names); + gl_list_free (names); return found; } @@ -3355,11 +3305,6 @@ static int display_database_check (struct candidate *candp) return exists; } -static void db_hashtable_free (void *defn) -{ - free_mandata_struct (defn); -} - #ifdef MAN_DB_UPDATES static int maybe_update_file (const char *manpath, const char *name, struct mandata *info) @@ -3418,16 +3363,26 @@ static int maybe_update_file (const char *manpath, const char *name, #define TRY_DATABASE_UPDATED -3 #endif /* MAN_DB_UPDATES */ +static void db_map_value_free (const void *value) +{ + /* The value may be NULL to indicate that opening the database at + * this location already failed. + */ + if (value) + gl_list_free ((gl_list_t) value); +} + /* Look for a page in the database. If db not accessible, return -1, otherwise return number of pages found. */ static int try_db (const char *manpath, const char *sec, const char *name, struct candidate **cand_head) { - struct mandata *loc, *data; + gl_list_t matches; + struct mandata *loc; char *catpath; int found = 0; #ifdef MAN_DB_UPDATES - int found_stale = 0; + bool found_stale = false; #endif /* MAN_DB_UPDATES */ /* find out where our db for this manpath should be */ @@ -3440,13 +3395,11 @@ static int try_db (const char *manpath, const char *sec, const char *name, } else database = mkdbname (manpath); - if (!db_hash) - db_hash = hashtable_create (&db_hashtable_free); + if (!db_map) + db_map = new_string_map (GL_HASH_MAP, db_map_value_free); - /* Have we looked here already? */ - data = hashtable_lookup (db_hash, manpath, strlen (manpath)); - - if (!data) { + /* If we haven't looked here already, do so now. */ + if (!gl_map_search (db_map, manpath, (const void **) &matches)) { MYDBM_FILE dbf; dbf = MYDBM_RDOPEN (database); @@ -3460,14 +3413,13 @@ static int try_db (const char *manpath, const char *sec, const char *name, /* if section is set, only return those that match, otherwise NULL retrieves all available */ if (regex_opt || wildcard) - data = dblookup_pattern + matches = dblookup_pattern (dbf, name, section, match_case, regex_opt, !names_only); else - data = dblookup_all (dbf, name, section, - match_case); - hashtable_install (db_hash, manpath, strlen (manpath), - data); + matches = dblookup_all (dbf, name, section, + match_case); + gl_map_put (db_map, xstrdup (manpath), matches); MYDBM_CLOSE (dbf); dbf = NULL; #ifdef MAN_DB_CREATES @@ -3475,60 +3427,50 @@ static int try_db (const char *manpath, const char *sec, const char *name, /* create one */ debug ("Failed to open %s O_RDONLY\n", database); if (run_mandb (1, manpath, NULL)) { - data = infoalloc (); - data->next = NULL; - data->addr = NULL; - hashtable_install (db_hash, - manpath, strlen (manpath), - data); + gl_map_put (db_map, xstrdup (manpath), NULL); return TRY_DATABASE_OPEN_FAILED; } return TRY_DATABASE_CREATED; #endif /* MAN_DB_CREATES */ } else { debug ("Failed to open %s O_RDONLY\n", database); - data = infoalloc (); - data->next = (struct mandata *) NULL; - data->addr = NULL; - hashtable_install (db_hash, manpath, strlen (manpath), - data); + gl_map_put (db_map, xstrdup (manpath), NULL); return TRY_DATABASE_OPEN_FAILED; } + assert (matches != NULL); } - /* if we already know that there is nothing here, get on with it */ - if (!data) - return 0; - - /* We already tried (and failed) to open this db before */ - if (!data->addr) + /* We already tried (and failed) to open this db before. */ + if (!matches) return TRY_DATABASE_OPEN_FAILED; #ifdef MAN_DB_UPDATES /* Check that all the entries found are up to date. If not, the * caller should try again. */ - for (loc = data; loc; loc = loc->next) + GL_LIST_FOREACH_START (matches, loc) if (STREQ (sec, loc->sec) && (!extension || STREQ (extension, loc->ext) || STREQ (extension, loc->ext + strlen (sec)))) if (maybe_update_file (manpath, name, loc)) - found_stale = 1; + found_stale = true; + GL_LIST_FOREACH_END (matches); if (found_stale) { - hashtable_remove (db_hash, manpath, strlen (manpath)); + gl_map_remove (db_map, manpath); return TRY_DATABASE_UPDATED; } #endif /* MAN_DB_UPDATES */ /* cycle through the mandata structures (there's usually only 1 or 2) and see what we have w.r.t. the current section */ - for (loc = data; loc; loc = loc->next) + GL_LIST_FOREACH_START (matches, loc) if (STREQ (sec, loc->sec) && (!extension || STREQ (extension, loc->ext) || STREQ (extension, loc->ext + strlen (sec)))) found += add_candidate (cand_head, CANDIDATE_DATABASE, 0, name, manpath, NULL, loc); + GL_LIST_FOREACH_END (matches); return found; } @@ -3673,8 +3615,8 @@ static int do_global_apropos_section (const char *path, const char *sec, const char *name) { int found = 0; - char **names, **np; - size_t names_len = 0; + gl_list_t names; + const char *found_name; regex_t search; global_manpath = is_global_mandir (path); @@ -3684,6 +3626,7 @@ static int do_global_apropos_section (const char *path, const char *sec, debug ("searching in %s, section %s\n", path, sec); names = look_for_file (path, sec, "*", 0, LFF_WILDCARD); + if (regex_opt) xregcomp (&search, name, REG_EXTENDED | REG_NOSUB | @@ -3691,33 +3634,31 @@ static int do_global_apropos_section (const char *path, const char *sec, else memset (&search, 0, sizeof search); - for (np = names; np && *np; ++np) - ++names_len; - order_files (path, names, names_len); + order_files (path, &names); - for (np = names; np && *np; ++np) { + GL_LIST_FOREACH_START (names, found_name) { struct mandata *info; char *info_buffer; char *title = NULL; const char *man_file; char *cat_file = NULL; - if (!grep (*np, name, &search)) + if (!grep (found_name, name, &search)) continue; info = infoalloc (); - info_buffer = filename_info (*np, info, NULL); + info_buffer = filename_info (found_name, info, NULL); if (!info_buffer) goto next; info->addr = info_buffer; title = xasprintf ("%s(%s)", strchr (info_buffer, '\0') + 1, info->ext); - man_file = ult_src (*np, path, NULL, ult_flags, NULL); + man_file = ult_src (found_name, path, NULL, ult_flags, NULL); if (!man_file) goto next; lang = lang_dir (man_file); - cat_file = find_cat_file (path, *np, man_file); + cat_file = find_cat_file (path, found_name, man_file); if (display (path, man_file, cat_file, title, NULL)) found = 1; free (lang); @@ -3727,7 +3668,9 @@ next: free (cat_file); free (title); free_mandata_struct (info); - } + } GL_LIST_FOREACH_END (names); + + gl_list_free (names); if (regex_opt) regfree (&search); @@ -3740,23 +3683,26 @@ next: static int do_global_apropos (const char *name, int *found) { - const char **my_section_list; - const char **sp; - char **mp; + gl_list_t my_section_list; + const char *sec; if (section) { - my_section_list = XNMALLOC (2, const char *); - my_section_list[0] = section; - my_section_list[1] = NULL; + my_section_list = gl_list_create_empty (GL_ARRAY_LIST, NULL, + NULL, NULL, false); + gl_list_add_last (my_section_list, section); } else my_section_list = section_list; - for (sp = my_section_list; *sp; sp++) - for (mp = manpathlist; *mp; mp++) - *found += do_global_apropos_section (*mp, *sp, name); + GL_LIST_FOREACH_START (my_section_list, sec) { + char *mp; + + GL_LIST_FOREACH_START (manpathlist, mp) + *found += do_global_apropos_section (mp, sec, name); + GL_LIST_FOREACH_END (manpathlist); + } GL_LIST_FOREACH_END (my_section_list); if (section) - free (my_section_list); + gl_list_free (my_section_list); return *found ? OK : NOT_FOUND; } @@ -3768,10 +3714,10 @@ static int man (const char *name, int *found); static int local_man_loop (const char *argv) { int exit_status = OK; - int local_mf = local_man_file; + bool local_mf = local_man_file; drop_effective_privs (); - local_man_file = 1; + local_man_file = true; if (strcmp (argv, "-") == 0) display (NULL, "", NULL, "(stdin)", NULL); else { @@ -3806,7 +3752,7 @@ static int local_man_loop (const char *argv) if (directory_on_path (argv_dir)) { char *argv_base = base_name (argv); char *new_manp, *nm; - char **old_manpathlist, **mp; + gl_list_t old_manpathlist; debug ("recalculating manpath for executable " "in %s\n", argv_dir); @@ -3821,18 +3767,13 @@ static int local_man_loop (const char *argv) free (new_manp); new_manp = nm; - old_manpathlist = XNMALLOC (MAXDIRS, char *); - memcpy (old_manpathlist, manpathlist, - MAXDIRS * sizeof (*manpathlist)); - create_pathlist (new_manp, manpathlist); + old_manpathlist = manpathlist; + manpathlist = create_pathlist (new_manp); man (argv_base, &found); - for (mp = manpathlist; *mp; ++mp) - free (*mp); - memcpy (manpathlist, old_manpathlist, - MAXDIRS * sizeof (*manpathlist)); - free (old_manpathlist); + free_pathlist (manpathlist); + manpathlist = old_manpathlist; executable_out: free (new_manp); free (argv_base); @@ -3901,10 +3842,12 @@ static void locate_page_in_manpath (const char *page_section, struct candidate **candidates, int *found) { - char **mp; + char *mp; - for (mp = manpathlist; *mp; mp++) - *found += locate_page (*mp, page_section, page_name, candidates); + GL_LIST_FOREACH_START (manpathlist, mp) + *found += locate_page (mp, page_section, page_name, + candidates); + GL_LIST_FOREACH_END (manpathlist); } /* @@ -3939,11 +3882,11 @@ static int man (const char *name, int *found) if (section) locate_page_in_manpath (section, name, &candidates, found); else { - const char **sp; + const char *sec; - for (sp = section_list; *sp; sp++) { - locate_page_in_manpath (*sp, name, &candidates, found); - } + GL_LIST_FOREACH_START (section_list, sec) + locate_page_in_manpath (sec, name, &candidates, found); + GL_LIST_FOREACH_END (section_list); } split_page_name (name, &page_name, &page_section); @@ -3969,20 +3912,20 @@ static int man (const char *name, int *found) } -static const char **get_section_list (void) +static gl_list_t get_section_list (void) { - int i = 0; - const char **config_sections; - const char **sections = NULL; + gl_list_t config_sections, sections; const char *sec; /* Section list from configuration file, or STD_SECTIONS if it's * empty. */ config_sections = get_sections (); - if (!*config_sections) { - free (config_sections); - config_sections = std_sections; + if (!gl_list_size (config_sections)) { + int i; + for (i = 0; std_sections[i]; ++i) + gl_list_add_last (config_sections, + xstrdup (std_sections[i])); } if (colon_sep_section_list == NULL) @@ -3994,17 +3937,16 @@ static const char **get_section_list (void) * man's -s option takes a comma-separated list, so we accept that * too for compatibility. */ + sections = new_string_list (GL_ARRAY_LIST, true); for (sec = strtok (colon_sep_section_list, ":,"); sec; - sec = strtok (NULL, ":,")) { - sections = xnrealloc (sections, i + 2, sizeof *sections); - sections[i++] = sec; - } + sec = strtok (NULL, ":,")) + gl_list_add_last (sections, xstrdup (sec)); - if (i > 0) { - sections[i] = NULL; + if (gl_list_size (sections)) { + gl_list_free (config_sections); return sections; } else { - free (sections); + gl_list_free (sections); return config_sections; } } @@ -4086,8 +4028,6 @@ int main (int argc, char *argv[]) set_program_name (argv[0]); - check_standard_fds (); - init_debug (); pipeline_install_post_fork (pop_all_cleanups); sandbox = sandbox_init (); @@ -4103,6 +4043,8 @@ int main (int argc, char *argv[]) multiple_locale = getenv ("LANGUAGE"); internal_locale = xstrdup (internal_locale ? internal_locale : "C"); + xstdopen (); + /* export argv, it might be needed when invoking the vendor supplied browser */ #if defined _AIX || defined __sgi global_argv = argv; @@ -4114,6 +4056,10 @@ int main (int argc, char *argv[]) init_html_pager (); #endif /* TROFF_IS_GROFF */ +#ifdef NROFF_WARNINGS + roff_warnings = new_string_list (GL_ARRAY_LIST, true); +#endif /* NROFF_WARNINGS */ + /* First of all, find out if $MANOPT is set. If so, put it in *argv[] format for argp to play with. */ argv_env = manopt_to_env (&argc_env); @@ -4226,7 +4172,7 @@ int main (int argc, char *argv[]) debug ("manpath search path (with duplicates) = %s\n", manp); - create_pathlist (manp, manpathlist); + manpathlist = create_pathlist (manp); /* man issued with `-l' option */ if (local_man_file) { @@ -4288,14 +4234,14 @@ int main (int argc, char *argv[]) if (global_apropos) status = do_global_apropos (nextarg, &found); else { - int found_subpage = 0; + bool found_subpage = false; if (subpages && first_arg < argc) { char *subname = xasprintf ( "%s-%s", nextarg, argv[first_arg]); status = man (subname, &found); free (subname); if (status == OK) { - found_subpage = 1; + found_subpage = true; ++first_arg; } } @@ -4305,7 +4251,7 @@ int main (int argc, char *argv[]) status = man (subname, &found); free (subname); if (status == OK) { - found_subpage = 1; + found_subpage = true; ++first_arg; } } @@ -4314,15 +4260,17 @@ int main (int argc, char *argv[]) } /* clean out the cache of database lookups for each man page */ - hashtable_free (db_hash); - db_hash = NULL; + if (db_map) { + gl_map_free (db_map); + db_map = NULL; + } if (section && maybe_section) { if (status != OK && !catman) { /* Maybe the section wasn't a section after * all? e.g. 'man 9wm fvwm'. */ - int found_subpage = 0; + bool found_subpage = false; debug ("\nRetrying section %s as name\n", section); tmp = section; @@ -4333,14 +4281,16 @@ int main (int argc, char *argv[]) status = man (subname, &found); free (subname); if (status == OK) { - found_subpage = 1; + found_subpage = true; ++first_arg; } } if (!found_subpage) status = man (tmp, &found); - hashtable_free (db_hash); - db_hash = NULL; + if (db_map) { + gl_map_free (db_map); + db_map = NULL; + } /* ... but don't gripe about it if it doesn't * work! */ @@ -4385,13 +4335,17 @@ int main (int argc, char *argv[]) chkr_garbage_detector (); } - hashtable_free (db_hash); - db_hash = NULL; + if (db_map) { + gl_map_free (db_map); + db_map = NULL; + } drop_effective_privs (); free (database); + gl_list_free (section_list); free_pathlist (manpathlist); free (internal_locale); + sandbox_free (sandbox); exit (exit_status); } diff --git a/src/manconv_main.c b/src/manconv_main.c index 75c08ab0..949c6b6f 100644 --- a/src/manconv_main.c +++ b/src/manconv_main.c @@ -24,6 +24,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -111,7 +112,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) (void *) 0); return 0; case 'd': - debug_level = 1; + debug_level = true; return 0; case 'q': quiet = 1; @@ -178,5 +179,7 @@ int main (int argc, char *argv[]) pipeline_wait (p); + sandbox_free (sandbox); + return 0; } diff --git a/src/mandb.c b/src/mandb.c index 90325d91..0a06c714 100644 --- a/src/mandb.c +++ b/src/mandb.c @@ -30,6 +30,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -48,6 +49,9 @@ #include "argp.h" #include "dirname.h" +#include "gl_hash_map.h" +#include "gl_list.h" +#include "gl_xmap.h" #include "progname.h" #include "stat-time.h" #include "timespec.h" @@ -63,7 +67,7 @@ #include "error.h" #include "cleanup.h" -#include "hashtable.h" +#include "glcontainers.h" #include "pipeline.h" #include "sandbox.h" #include "security.h" @@ -75,11 +79,11 @@ #include "manp.h" int quiet = 1; -extern int opt_test; /* don't update db */ +extern bool opt_test; /* don't update db */ char *manp; char *database = NULL; extern char *extension; /* for globbing.c */ -extern int force_rescan; /* for check_mandirs.c */ +extern bool force_rescan; /* for check_mandirs.c */ static char *single_filename = NULL; extern char *user_config_file; /* for manp.c */ #ifdef MAN_OWNER @@ -90,10 +94,10 @@ man_sandbox *sandbox; static int purged = 0; static int strays = 0; -static int check_for_strays = 1; -static int purge = 1; -static int user; -static int create; +static bool check_for_strays = true; +static bool purge = true; +static bool user; +static bool create; static const char *arg_manp; struct tried_catdirs_entry { @@ -127,32 +131,32 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) switch (key) { case 'd': - debug_level = 1; + debug_level = true; return 0; case 'q': ++quiet_temp; return 0; case 's': - check_for_strays = 0; + check_for_strays = false; return 0; case 'p': - purge = 0; + purge = false; return 0; case 'u': - user = 1; + user = true; return 0; case 'c': - create = 1; - purge = 0; + create = true; + purge = false; return 0; case 't': - opt_test = 1; + opt_test = true; return 0; case 'f': single_filename = arg; - create = 0; - purge = 0; - check_for_strays = 0; + create = false; + purge = false; + check_for_strays = false; return 0; case 'C': user_config_file = arg; @@ -202,7 +206,7 @@ extern uid_t ruid; extern uid_t euid; #endif /* MAN_OWNER */ -static char *manpathlist[MAXDIRS]; +static gl_list_t manpathlist; extern int pages; @@ -437,7 +441,8 @@ static void cleanup (void *arg) /* sort out the database names */ static int mandb (struct dbpaths *dbpaths, - const char *catpath, const char *manpath, int global_manpath) + const char *catpath, const char *manpath, + bool global_manpath) { int ret, amount; char *dbname; @@ -551,8 +556,8 @@ static int mandb (struct dbpaths *dbpaths, return amount; } -static int process_manpath (const char *manpath, int global_manpath, - struct hashtable *tried_catdirs) +static int process_manpath (const char *manpath, bool global_manpath, + gl_map_t tried_catdirs) { char *catpath; struct tried_catdirs_entry *tried; @@ -572,7 +577,7 @@ static int process_manpath (const char *manpath, int global_manpath, tried = XMALLOC (struct tried_catdirs_entry); tried->manpath = xstrdup (manpath); tried->seen = 0; - hashtable_install (tried_catdirs, catpath, strlen (catpath), tried); + gl_map_put (tried_catdirs, xstrdup (catpath), tried); if (stat (manpath, &st) < 0 || !S_ISDIR (st.st_mode)) goto out; @@ -590,7 +595,7 @@ static int process_manpath (const char *manpath, int global_manpath, } else run_mandb = 1; - force_rescan = 0; + force_rescan = false; if (purge) { database = mkdbname (catpath); purged += purge_missing (manpath, catpath, run_mandb); @@ -648,21 +653,21 @@ static int is_lang_dir (const char *base) (!base[2] || base[2] < 'a' || base[2] > 'z'); } -static void tried_catdirs_free (void *defn) +static void tried_catdirs_free (const void *value) { - struct tried_catdirs_entry *tried = defn; + struct tried_catdirs_entry *tried = + (struct tried_catdirs_entry *) value; free (tried->manpath); free (tried); } -static void purge_catdir (const struct hashtable *tried_catdirs, - const char *path) +static void purge_catdir (gl_map_t tried_catdirs, const char *path) { struct stat st; if (stat (path, &st) == 0 && S_ISDIR (st.st_mode) && - !hashtable_lookup (tried_catdirs, path, strlen (path))) { + !gl_map_get (tried_catdirs, path)) { if (!quiet) printf (_("Removing obsolete cat directory %s...\n"), path); @@ -714,14 +719,12 @@ static void purge_catsubdirs (const char *manpath, const char *catpath) * the usual NLS pattern (two lower-case letters followed by nothing or a * non-letter). */ -static void purge_catdirs (const struct hashtable *tried_catdirs) +static void purge_catdirs (gl_map_t tried_catdirs) { - struct hashtable_iter *iter = NULL; - const struct nlist *elt; + const char *path; + struct tried_catdirs_entry *tried; - while ((elt = hashtable_iterate (tried_catdirs, &iter)) != NULL) { - const char *path = elt->name; - struct tried_catdirs_entry *tried = elt->defn; + GL_MAP_FOREACH_START (tried_catdirs, path, tried) { char *base; DIR *dir; struct dirent *subdirent; @@ -741,6 +744,7 @@ static void purge_catdirs (const struct hashtable *tried_catdirs) continue; while ((subdirent = readdir (dir)) != NULL) { char *subdirpath; + const struct tried_catdirs_entry *subtried; if (STREQ (subdirent->d_name, ".") || STREQ (subdirent->d_name, "..")) @@ -753,30 +757,30 @@ static void purge_catdirs (const struct hashtable *tried_catdirs) subdirpath = xasprintf ("%s/%s", path, subdirent->d_name); - tried = hashtable_lookup (tried_catdirs, subdirpath, - strlen (subdirpath)); - if (tried && tried->seen) { + subtried = gl_map_get (tried_catdirs, subdirpath); + if (subtried && subtried->seen) { debug ("Seen mandir for %s; not deleting\n", subdirpath); /* However, we may still need to purge cat* * subdirectories. */ - purge_catsubdirs (tried->manpath, subdirpath); + purge_catsubdirs (subtried->manpath, + subdirpath); } else purge_catdir (tried_catdirs, subdirpath); free (subdirpath); } closedir (dir); - } + } GL_MAP_FOREACH_END (tried_catdirs); } int main (int argc, char *argv[]) { char *sys_manp; int amount = 0; - char **mp; - struct hashtable *tried_catdirs; + char *mp; + gl_map_t tried_catdirs; #ifdef SIGPIPE struct sigaction sa; #endif /* SIGPIPE */ @@ -822,7 +826,7 @@ int main (int argc, char *argv[]) #ifdef MAN_OWNER man_owner = get_man_owner (); if (!user && euid != 0 && euid != man_owner->pw_uid) - user = 1; + user = true; #endif /* MAN_OWNER */ read_config_file (user); @@ -848,16 +852,16 @@ int main (int argc, char *argv[]) debug ("manpath=%s\n", manp); - /* get the manpath as an array of pointers */ - create_pathlist (manp, manpathlist); + /* get the manpath as a list of pointers */ + manpathlist = create_pathlist (manp); /* finished manpath processing, regain privs */ regain_effective_privs (); - tried_catdirs = hashtable_create (tried_catdirs_free); + tried_catdirs = new_string_map (GL_HASH_MAP, tried_catdirs_free); - for (mp = manpathlist; *mp; mp++) { - int global_manpath = is_global_mandir (*mp); + GL_LIST_FOREACH_START (manpathlist, mp) { + bool global_manpath = is_global_mandir (mp); int ret; DIR *dir; struct dirent *subdirent; @@ -869,14 +873,14 @@ int main (int argc, char *argv[]) drop_effective_privs (); } - ret = process_manpath (*mp, global_manpath, tried_catdirs); + ret = process_manpath (mp, global_manpath, tried_catdirs); if (ret < 0) exit (FATAL); amount += ret; - dir = opendir (*mp); + dir = opendir (mp); if (!dir) { - error (0, errno, _("can't search directory %s"), *mp); + error (0, errno, _("can't search directory %s"), mp); goto next_manpath; } @@ -890,7 +894,7 @@ int main (int argc, char *argv[]) if (STRNEQ (subdirent->d_name, "man", 3)) continue; - subdirpath = xasprintf ("%s/%s", *mp, + subdirpath = xasprintf ("%s/%s", mp, subdirent->d_name); ret = process_manpath (subdirpath, global_manpath, tried_catdirs); @@ -907,10 +911,10 @@ next_manpath: regain_effective_privs (); chkr_garbage_detector (); - } + } GL_LIST_FOREACH_END (manpathlist); purge_catdirs (tried_catdirs); - hashtable_free (tried_catdirs); + gl_map_free (tried_catdirs); if (!quiet) { printf (ngettext ("%d man subdirectory contained newer " @@ -950,5 +954,6 @@ next_manpath: if (must_create && STREQ (must_create, "1")) exit (FAIL); } + sandbox_free (sandbox); exit (OK); } @@ -47,6 +47,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdio.h> #include <ctype.h> #include <sys/types.h> @@ -54,11 +55,15 @@ #include <assert.h> #include <errno.h> #include <dirent.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "canonicalize.h" +#include "gl_array_list.h" +#include "gl_linkedhash_list.h" +#include "gl_xlist.h" #include "xgetcwd.h" #include "xvasprintf.h" @@ -69,77 +74,76 @@ #include "error.h" #include "cleanup.h" +#include "glcontainers.h" #include "security.h" #include "manp.h" #include "globbing.h" -struct list { +enum config_flag { + MANDATORY, + MANPATH_MAP, + MANDB_MAP, + MANDB_MAP_USER, + DEFINE, + DEFINE_USER, + SECTION, + SECTION_USER +}; + +struct config_item { char *key; char *cont; - int flag; - struct list *next; + enum config_flag flag; }; -static struct list *namestore, *tailstore; - -#define SECTION_USER -6 -#define SECTION -5 -#define DEFINE_USER -4 -#define DEFINE -3 -#define MANDB_MAP_USER -2 -#define MANDB_MAP -1 -#define MANPATH_MAP 0 -#define MANDATORY 1 - -/* DIRLIST list[MAXDIRS]; */ -static char *tmplist[MAXDIRS]; +static gl_list_t config; char *user_config_file = NULL; -int disable_cache; +bool disable_cache; int min_cat_width = 80, max_cat_width = 80, cat_width = 0; -static char *has_mandir (const char *p); +static void add_man_subdirs (gl_list_t list, const char *p); static char *fsstnd (const char *path); -static char *def_path (int flag); -static void add_dir_to_list (char **lp, const char *dir); -static char **add_dir_to_path_list (char **mphead, char **mp, const char *p); +static char *def_path (enum config_flag flag); +static void add_dir_to_list (gl_list_t list, const char *dir); +static void add_dir_to_path_list (gl_list_t list, const char *p); -static void add_to_list (const char *key, const char *cont, int flag) +static void config_item_free (const void *elt) { - struct list *list = XMALLOC (struct list); - list->key = xstrdup (key); - list->cont = xstrdup (cont); - list->flag = flag; - list->next = NULL; - if (tailstore) - tailstore->next = list; - tailstore = list; - if (!namestore) - namestore = list; + /* gl_list declares the argument as const, but there doesn't seem to + * be a good reason for this. + */ + struct config_item *item = (struct config_item *) elt; + free (item->key); + free (item->cont); + free (item); } -static const char *get_from_list (const char *key, int flag) +static void add_config (const char *key, const char *cont, + enum config_flag flag) { - struct list *list; - - for (list = namestore; list; list = list->next) - if (flag == list->flag && STREQ (key, list->key)) - return list->cont; - - return NULL; + struct config_item *item = XMALLOC (struct config_item); + item->key = xstrdup (key); + item->cont = xstrdup (cont); + item->flag = flag; + gl_list_add_last (config, item); } -static struct list *iterate_over_list (struct list *prev, char *key, int flag) +static const char *get_config (const char *key, enum config_flag flag) { - struct list *list; + const struct config_item *item; + char *cont = NULL; - for (list = prev ? prev->next : namestore; list; list = list->next) - if (flag == list->flag && STREQ (key, list->key)) - return list; + GL_LIST_FOREACH_START (config, item) + if (flag == item->flag && STREQ (key, item->key)) { + cont = item->cont; + break; + } + GL_LIST_FOREACH_END (config); - return NULL; + return cont; } /* Must not return DEFINEs set in ~/.manpath. This is used to fetch @@ -154,25 +158,52 @@ const char *get_def (const char *thing, const char *def) if (!running_setuid ()) return get_def_user (thing, def); - config_def = get_from_list (thing, DEFINE); + config_def = get_config (thing, DEFINE); return config_def ? config_def : def; } const char *get_def_user (const char *thing, const char *def) { - const char *config_def = get_from_list (thing, DEFINE_USER); + const char *config_def = get_config (thing, DEFINE_USER); if (!config_def) - config_def = get_from_list (thing, DEFINE); + config_def = get_config (thing, DEFINE); return config_def ? config_def : def; } +static const char *describe_flag (enum config_flag flag) +{ + switch (flag) { + case MANDATORY: + return "MANDATORY"; + case MANPATH_MAP: + return "MANPATH_MAP"; + case MANDB_MAP: + return "MANDB_MAP"; + case MANDB_MAP_USER: + return "MANDB_MAP_USER"; + case DEFINE: + return "DEFINE"; + case DEFINE_USER: + return "DEFINE_USER"; + case SECTION: + return "SECTION"; + case SECTION_USER: + return "SECTION_USER"; + default: + error (FATAL, 0, "impossible config_flag value %d", + flag); + abort (); /* error should have exited */ + } +} + static void print_list (void) { - struct list *list; + const struct config_item *item; - for (list = namestore; list; list = list->next) - debug ("`%s'\t`%s'\t`%d'\n", - list->key, list->cont, list->flag); + GL_LIST_FOREACH_START (config, item) + debug ("`%s'\t`%s'\t`%s'\n", + item->key, item->cont, describe_flag (item->flag)); + GL_LIST_FOREACH_END (config); } static void add_sections (char *sections, int user) @@ -182,44 +213,40 @@ static void add_sections (char *sections, int user) for (sect = strtok (section_list, " "); sect; sect = strtok (NULL, " ")) { - add_to_list (sect, "", user ? SECTION_USER : SECTION); + add_config (sect, "", user ? SECTION_USER : SECTION); debug ("Added section `%s'.\n", sect); } free (section_list); } -const char **get_sections (void) +gl_list_t get_sections (void) { - struct list *list; + const struct config_item *item; int length_user = 0, length = 0; - const char **sections, **sectionp; - int flag; + gl_list_t sections; + enum config_flag flag; - for (list = namestore; list; list = list->next) { - if (list->flag == SECTION_USER) + GL_LIST_FOREACH_START (config, item) { + if (item->flag == SECTION_USER) length_user++; - else if (list->flag == SECTION) + else if (item->flag == SECTION) length++; - } - if (length_user) { - sections = xnmalloc (length_user + 1, sizeof *sections); + } GL_LIST_FOREACH_END (config); + sections = new_string_list (GL_ARRAY_LIST, true); + if (length_user) flag = SECTION_USER; - } else { - sections = xnmalloc (length + 1, sizeof *sections); + else flag = SECTION; - } - sectionp = sections; - for (list = namestore; list; list = list->next) - if (list->flag == flag) - *sectionp++ = list->key; - *sectionp = NULL; + GL_LIST_FOREACH_START (config, item) + if (item->flag == flag) + gl_list_add_last (sections, xstrdup (item->key)); + GL_LIST_FOREACH_END (config); return sections; } -static void add_def (char *thing, char *config_def, int flag, int user) +static void add_def (const char *thing, const char *config_def, int user) { - add_to_list (thing, flag == 2 ? config_def : "", - user ? DEFINE_USER : DEFINE); + add_config (thing, config_def, user ? DEFINE_USER : DEFINE); debug ("Defined `%s' as `%s'.\n", thing, config_def); } @@ -229,24 +256,19 @@ static void add_manpath_map (const char *path, const char *mandir) if (!path || !mandir) return; - add_to_list (path, mandir, MANPATH_MAP); + add_config (path, mandir, MANPATH_MAP); debug ("Path `%s' mapped to mandir `%s'.\n", path, mandir); } -static void add_mandb_map (const char *mandir, const char *catdir, - int flag, int user) +static void add_mandb_map (const char *mandir, const char *catdir, int user) { char *tmpcatdir; - assert (flag > 0); - if (!mandir) return; - if (flag == 1) - tmpcatdir = xstrdup (mandir); - else if (STREQ (catdir, "FSSTND")) + if (STREQ (catdir, "FSSTND")) tmpcatdir = fsstnd (mandir); else tmpcatdir = xstrdup (catdir); @@ -254,7 +276,7 @@ static void add_mandb_map (const char *mandir, const char *catdir, if (!tmpcatdir) return; - add_to_list (mandir, tmpcatdir, user ? MANDB_MAP_USER : MANDB_MAP); + add_config (mandir, tmpcatdir, user ? MANDB_MAP_USER : MANDB_MAP); debug ("%s mandir `%s', catdir `%s'.\n", user ? "User" : "Global", mandir, tmpcatdir); @@ -267,7 +289,7 @@ static void add_mandatory (const char *mandir) if (!mandir) return; - add_to_list (mandir, "", MANDATORY); + add_config (mandir, "", MANDATORY); debug ("Mandatory mandir `%s'.\n", mandir); } @@ -339,11 +361,6 @@ static void gripe_not_directory (const char *dir) error (0, 0, _("warning: %s isn't a directory"), dir); } -static void gripe_overlong_list (void) -{ - error (FAIL, 0, _("manpath list too long")); -} - /* accept a manpath list, separated with ':', return the associated catpath list */ char *cat_manpath (char *manp) @@ -352,9 +369,9 @@ char *cat_manpath (char *manp) const char *path, *catdir; for (path = strsep (&manp, ":"); path; path = strsep (&manp, ":")) { - catdir = get_from_list (path, MANDB_MAP_USER); + catdir = get_config (path, MANDB_MAP_USER); if (!catdir) - catdir = get_from_list (path, MANDB_MAP); + catdir = get_config (path, MANDB_MAP); catp = catdir ? pathappend (catp, catdir) : pathappend (catp, path); } @@ -697,7 +714,7 @@ char *get_manpath (const char *systems) char *manpathlist; /* need to read config file even if MANPATH set, for mandb(8) */ - read_config_file (0); + read_config_file (false); manpathlist = getenv ("MANPATH"); if (manpathlist && *manpathlist) { @@ -756,7 +773,7 @@ char *get_manpath (const char *systems) } /* Parse the manpath.config file, extracting appropriate information. */ -static void add_to_dirlist (FILE *config, int user) +static void add_to_dirlist (FILE *config_file, int user) { char *bp; char *buf = NULL; @@ -765,7 +782,7 @@ static void add_to_dirlist (FILE *config, int user) int val; int c; - while (getline (&buf, &n, config) >= 0) { + while (getline (&buf, &n, config_file) >= 0) { bp = buf; while (CTYPE (isspace, *bp)) @@ -778,7 +795,7 @@ static void add_to_dirlist (FILE *config, int user) if (*bp == '#' || *bp == '\0') goto next; else if (strncmp (bp, "NOCACHE", 7) == 0) - disable_cache = 1; + disable_cache = true; else if (strncmp (bp, "NO", 2) == 0) goto next; /* match any word starting with NO */ else if (sscanf (bp, "MANBIN %*s") == 1) @@ -790,10 +807,10 @@ static void add_to_dirlist (FILE *config, int user) add_manpath_map (key, cont); else if ((c = sscanf (bp, "MANDB_MAP %511s %511s", key, cont)) > 0) - add_mandb_map (key, cont, c, user); + add_mandb_map (key, c == 2 ? cont : key, user); else if ((c = sscanf (bp, "DEFINE %511s %511[^\n]", key, cont)) > 0) - add_def (key, cont, c, user); + add_def (key, c == 2 ? cont : "", user); else if (sscanf (bp, "SECTION %511[^\n]", cont) == 1) add_sections (cont, user); else if (sscanf (bp, "SECTIONS %511[^\n]", cont) == 1) @@ -820,28 +837,20 @@ next: static void free_config_file (void *unused ATTRIBUTE_UNUSED) { - struct list *list = namestore, *prev; - - while (list) { - free (list->key); - free (list->cont); - prev = list; - list = list->next; - free (prev); - } - - namestore = tailstore = NULL; + gl_list_free (config); } -void read_config_file (int optional) +void read_config_file (bool optional) { static int done = 0; char *dotmanpath = NULL; - FILE *config; + FILE *config_file; if (done) return; + config = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, + config_item_free, true); push_cleanup (free_config_file, NULL, 0); if (user_config_file) @@ -852,18 +861,18 @@ void read_config_file (int optional) dotmanpath = xasprintf ("%s/.manpath", home); } if (dotmanpath) { - config = fopen (dotmanpath, "r"); - if (config != NULL) { + config_file = fopen (dotmanpath, "r"); + if (config_file != NULL) { debug ("From the config file %s:\n\n", dotmanpath); - add_to_dirlist (config, 1); - fclose (config); + add_to_dirlist (config_file, 1); + fclose (config_file); } free (dotmanpath); } if (getenv ("MAN_TEST_DISABLE_SYSTEM_CONFIG") == NULL) { - config = fopen (CONFIG_FILE, "r"); - if (config == NULL) { + config_file = fopen (CONFIG_FILE, "r"); + if (config_file == NULL) { if (optional) debug ("can't open %s; continuing anyway\n", CONFIG_FILE); @@ -875,8 +884,8 @@ void read_config_file (int optional) } else { debug ("From the config file %s:\n\n", CONFIG_FILE); - add_to_dirlist (config, 0); - fclose (config); + add_to_dirlist (config_file, 0); + fclose (config_file); } } @@ -890,34 +899,34 @@ void read_config_file (int optional) * Construct the default manpath. This picks up mandatory manpaths * only. */ -static char *def_path (int flag) +static char *def_path (enum config_flag flag) { char *manpath = NULL; - struct list *list; + const struct config_item *item; - for (list = namestore; list; list = list->next) - if (list->flag == flag) { - char **expanded_dirs; - int i; + GL_LIST_FOREACH_START (config, item) + if (item->flag == flag) { + gl_list_t expanded_dirs; + const char *expanded_dir; - expanded_dirs = expand_path (list->key); - for (i = 0; expanded_dirs[i]; i++) { - int status = is_directory (expanded_dirs[i]); + expanded_dirs = expand_path (item->key); + GL_LIST_FOREACH_START (expanded_dirs, expanded_dir) { + int status = is_directory (expanded_dir); if (status < 0) - gripe_stat_file (expanded_dirs[i]); + gripe_stat_file (expanded_dir); else if (status == 0 && !quiet) error (0, 0, _("warning: mandatory " "directory %s doesn't exist"), - expanded_dirs[i]); + expanded_dir); else if (status == 1) - manpath = pathappend - (manpath, expanded_dirs[i]); - free (expanded_dirs[i]); - } - free (expanded_dirs); + manpath = pathappend (manpath, + expanded_dir); + } GL_LIST_FOREACH_END (expanded_dirs); + gl_list_free (expanded_dirs); } + GL_LIST_FOREACH_END (config); /* If we have complete config file failure... */ if (!manpath) @@ -928,9 +937,9 @@ static char *def_path (int flag) /* * If specified with configure, append OVERRIDE_DIR to dir param and add it - * to the lp list. + * to list. */ -static void insert_override_dir (char **lp, const char *dir) +static void insert_override_dir (gl_list_t list, const char *dir) { char *override_dir = NULL; @@ -938,7 +947,7 @@ static void insert_override_dir (char **lp, const char *dir) return; if ((override_dir = xasprintf ("%s/%s", dir, OVERRIDE_DIR))) { - add_dir_to_list (lp, override_dir); + add_dir_to_list (list, override_dir); free (override_dir); } } @@ -956,19 +965,20 @@ static void insert_override_dir (char **lp, const char *dir) */ char *get_manpath_from_path (const char *path, int mandatory) { + gl_list_t tmplist; + const struct config_item *config_item; int len; char *tmppath; - char *t; char *p; - char **lp; char *end; char *manpathlist; - struct list *list; + char *item; + tmplist = new_string_list (GL_LINKEDHASH_LIST, false); tmppath = xstrdup (path); for (end = p = tmppath; end; p = end + 1) { - struct list *mandir_list; + bool manpath_map_found = false; end = strchr (p, ':'); if (end) @@ -980,43 +990,28 @@ char *get_manpath_from_path (const char *path, int mandatory) debug ("\npath directory %s ", p); - mandir_list = iterate_over_list (NULL, p, MANPATH_MAP); - - /* - * The directory we're working on is in the config file. - * If we haven't added it to the list yet, do. - */ - - if (mandir_list) { - debug ("is in the config file\n"); - while (mandir_list) { - insert_override_dir (tmplist, - mandir_list->cont); - add_dir_to_list (tmplist, mandir_list->cont); - mandir_list = iterate_over_list - (mandir_list, p, MANPATH_MAP); - } - - /* The directory we're working on isn't in the config file. - See if it has ../man or man subdirectories. - If so, and it hasn't been added to the list, do. */ - - } else { + /* If the directory we're working on has MANPATH_MAP entries + * in the config file, add them to the list. + */ + GL_LIST_FOREACH_START (config, config_item) { + if (MANPATH_MAP != config_item->flag || + !STREQ (p, config_item->key)) + continue; + if (!manpath_map_found) + debug ("is in the config file\n"); + manpath_map_found = true; + insert_override_dir (tmplist, config_item->cont); + add_dir_to_list (tmplist, config_item->cont); + } GL_LIST_FOREACH_END (config); + + /* The directory we're working on isn't in the config file. + See if it has ../man, man, ../share/man, or share/man + subdirectories. If so, and they haven't been added to + the list, do. */ + + if (!manpath_map_found) { debug ("is not in the config file\n"); - - t = has_mandir (p); - if (t) { - debug ("but does have a ../man, man, " - "../share/man, or share/man " - "subdirectory\n"); - - insert_override_dir (tmplist, t); - add_dir_to_list (tmplist, t); - free (t); - } else - debug ("and doesn't have ../man, man, " - "../share/man, or share/man " - "subdirectories\n"); + add_man_subdirs (tmplist, p); } } @@ -1025,19 +1020,19 @@ char *get_manpath_from_path (const char *path, int mandatory) if (mandatory) { debug ("\nadding mandatory man directories\n\n"); - for (list = namestore; list; list = list->next) - if (list->flag == MANDATORY) { - insert_override_dir (tmplist, list->key); - add_dir_to_list (tmplist, list->key); + GL_LIST_FOREACH_START (config, config_item) { + if (config_item->flag == MANDATORY) { + insert_override_dir (tmplist, + config_item->key); + add_dir_to_list (tmplist, config_item->key); } + } GL_LIST_FOREACH_END (config); } len = 0; - lp = tmplist; - while (*lp != NULL) { - len += strlen (*lp) + 1; - lp++; - } + GL_LIST_FOREACH_START (tmplist, item) + len += strlen (item) + 1; + GL_LIST_FOREACH_END (tmplist); if (!len) /* No path elements in configuration file or with @@ -1048,38 +1043,29 @@ char *get_manpath_from_path (const char *path, int mandatory) manpathlist = xmalloc (len); *manpathlist = '\0'; - lp = tmplist; p = manpathlist; - while (*lp != NULL) { - len = strlen (*lp); - memcpy (p, *lp, len); - free (*lp); - *lp = NULL; + GL_LIST_FOREACH_START (tmplist, item) { + len = strlen (item); + memcpy (p, item, len); p += len; *p++ = ':'; - lp++; - } + } GL_LIST_FOREACH_END (tmplist); p[-1] = '\0'; + gl_list_free (tmplist); + return manpathlist; } /* Add a directory to the manpath list if it isn't already there. */ -static void add_expanded_dir_to_list (char **lp, const char *dir) +static void add_expanded_dir_to_list (gl_list_t list, const char *dir) { int status; - int pos = 0; - - while (*lp != NULL) { - if (pos > MAXDIRS - 1) - gripe_overlong_list (); - if (!strcmp (*lp, dir)) { - debug ("%s is already in the manpath\n", dir); - return; - } - lp++; - pos++; + + if (gl_list_search (list, dir)) { + debug ("%s is already in the manpath\n", dir); + return; } /* Not found -- add it. */ @@ -1092,8 +1078,7 @@ static void add_expanded_dir_to_list (char **lp, const char *dir) gripe_not_directory (dir); else if (status == 1) { debug ("adding %s to manpath\n", dir); - - *lp = xstrdup (dir); + gl_list_add_last (list, xstrdup (dir)); } } @@ -1101,25 +1086,25 @@ static void add_expanded_dir_to_list (char **lp, const char *dir) * Add a directory to the manpath list if it isn't already there, expanding * wildcards. */ -static void add_dir_to_list (char **lp, const char *dir) +static void add_dir_to_list (gl_list_t list, const char *dir) { - char **expanded_dirs; - int i; + gl_list_t expanded_dirs; + const char *expanded_dir; expanded_dirs = expand_path (dir); - for (i = 0; expanded_dirs[i]; i++) { - add_expanded_dir_to_list (lp, expanded_dirs[i]); - free (expanded_dirs[i]); - } - free (expanded_dirs); + GL_LIST_FOREACH_START (expanded_dirs, expanded_dir) + add_expanded_dir_to_list (list, expanded_dir); + GL_LIST_FOREACH_END (expanded_dirs); + gl_list_free (expanded_dirs); } /* path does not exist in config file: check to see if path/../man, - path/man, path/../share/man, or path/share/man exist. If so return - it, if not return NULL. */ -static char *has_mandir (const char *path) + path/man, path/../share/man, or path/share/man exist, and add them to the + list if they do. */ +static void add_man_subdirs (gl_list_t list, const char *path) { char *newpath; + int found = 0; /* don't assume anything about path, especially that it ends in "bin" or even has a '/' in it! */ @@ -1127,113 +1112,126 @@ static char *has_mandir (const char *path) char *subdir = strrchr (path, '/'); if (subdir) { newpath = xasprintf ("%.*s/man", (int) (subdir - path), path); - if (is_directory (newpath) == 1) - return newpath; + if (is_directory (newpath) == 1) { + insert_override_dir (list, newpath); + add_dir_to_list (list, newpath); + found = 1; + } free (newpath); } newpath = xasprintf ("%s/man", path); - if (is_directory (newpath) == 1) - return newpath; + if (is_directory (newpath) == 1) { + insert_override_dir (list, newpath); + add_dir_to_list (list, newpath); + found = 1; + } free (newpath); if (subdir) { newpath = xasprintf ("%.*s/share/man", (int) (subdir - path), path); - if (is_directory (newpath) == 1) - return newpath; + if (is_directory (newpath) == 1) { + insert_override_dir (list, newpath); + add_dir_to_list (list, newpath); + found = 1; + } free (newpath); } newpath = xasprintf ("%s/share/man", path); - if (is_directory (newpath) == 1) - return newpath; + if (is_directory (newpath) == 1) { + insert_override_dir (list, newpath); + add_dir_to_list (list, newpath); + found = 1; + } free (newpath); - return NULL; + if (!found) + debug ("and doesn't have ../man, man, ../share/man, or " + "share/man subdirectories\n"); } -static char **add_dir_to_path_list (char **mphead, char **mp, const char *p) +static void add_dir_to_path_list (gl_list_t list, const char *p) { - int status, i; - char *cwd, *d, **expanded_dirs; - - if (mp - mphead > MAXDIRS - 1) - gripe_overlong_list (); + gl_list_t expanded_dirs; + char *expanded_dir; expanded_dirs = expand_path (p); - for (i = 0; expanded_dirs[i]; i++) { - d = expanded_dirs[i]; - - status = is_directory (d); + GL_LIST_FOREACH_START (expanded_dirs, expanded_dir) { + int status = is_directory (expanded_dir); if (status < 0) - gripe_stat_file (d); + gripe_stat_file (expanded_dir); else if (status == 0) - gripe_not_directory (d); + gripe_not_directory (expanded_dir); else { + char *path; + /* deal with relative paths */ - if (*d != '/') { - cwd = xgetcwd (); + if (*expanded_dir != '/') { + char *cwd = xgetcwd (); if (!cwd) error (FATAL, errno, _("can't determine current directory")); - *mp = appendstr (cwd, "/", d, (void *) 0); + path = appendstr (cwd, "/", expanded_dir, + (void *) 0); } else - *mp = xstrdup (d); + path = xstrdup (expanded_dir); - debug ("adding %s to manpathlist\n", *mp); - mp++; + debug ("adding %s to manpathlist\n", path); + gl_list_add_last (list, path); } - free (d); - } - free (expanded_dirs); - - return mp; + } GL_LIST_FOREACH_END (expanded_dirs); + gl_list_free (expanded_dirs); } -void create_pathlist (const char *manp, char **mp) +gl_list_t create_pathlist (const char *manp) { + gl_list_t list; + gl_list_iterator_t iter; + gl_list_node_t node; const char *p, *end; - char **mphead = mp; /* Expand the manpath into a list for easier handling. */ + list = new_string_list (GL_LINKEDHASH_LIST, true); for (p = manp;; p = end + 1) { end = strchr (p, ':'); if (end) { char *element = xstrndup (p, end - p); - mp = add_dir_to_path_list (mphead, mp, element); + add_dir_to_path_list (list, element); free (element); } else { - mp = add_dir_to_path_list (mphead, mp, p); + add_dir_to_path_list (list, p); break; } } - *mp = NULL; /* Eliminate duplicates due to symlinks. */ - mp = mphead; - while (*mp) { + iter = gl_list_iterator (list); + while (gl_list_iterator_next (&iter, (const void **) &p, &node)) { char *target; - char **dupcheck; - int found_dup = 0; + gl_list_iterator_t dupcheck_iter; + const char *dupcheck; + gl_list_node_t dupcheck_node; /* After resolving all symlinks, is the target also in the * manpath? */ - target = canonicalize_file_name (*mp); - if (!target) { - ++mp; + target = canonicalize_file_name (p); + if (!target) continue; - } /* Only check up to the current list position, to keep item * order stable across deduplication. */ - for (dupcheck = mphead; *dupcheck && dupcheck != mp; - ++dupcheck) { + dupcheck_iter = gl_list_iterator (list); + while (gl_list_iterator_next (&dupcheck_iter, + (const void **) &dupcheck, + &dupcheck_node) && + dupcheck_node != node) { char *dupcheck_target = canonicalize_file_name - (*dupcheck); + (dupcheck); if (!dupcheck_target) continue; if (!STREQ (target, dupcheck_target)) { @@ -1241,54 +1239,48 @@ void create_pathlist (const char *manp, char **mp) continue; } free (dupcheck_target); - debug ("Removing duplicate manpath entry %s (%td) -> " - "%s (%td)\n", - *mp, mp - mphead, - *dupcheck, dupcheck - mphead); - free (*mp); - for (dupcheck = mp; *(dupcheck + 1); ++dupcheck) - *dupcheck = *(dupcheck + 1); - *dupcheck = NULL; - found_dup = 1; + debug ("Removing duplicate manpath entry %s -> %s\n", + p, dupcheck); + gl_list_remove_node (list, node); break; } + gl_list_iterator_free (&dupcheck_iter); free (target); - if (!found_dup) - ++mp; } + gl_list_iterator_free (&iter); if (debug_level) { - int first = 1; + bool first = true; debug ("final search path = "); - for (mp = mphead; *mp; ++mp) { + GL_LIST_FOREACH_START (list, p) { if (first) { - debug ("%s", *mp); - first = 0; + debug ("%s", p); + first = false; } else - debug (":%s", *mp); - } + debug (":%s", p); + } GL_LIST_FOREACH_END (list); debug ("\n"); } + + return list; } -void free_pathlist (char **mp) +void free_pathlist (gl_list_t list) { - while (*mp) { - free (*mp); - *mp++ = NULL; - } + gl_list_free (list); } /* Routine to get list of named system and user manpaths (in reverse order). */ char *get_mandb_manpath (void) { char *manpath = NULL; - struct list *list; + const struct config_item *item; - for (list = namestore; list; list = list->next) - if (list->flag == MANDB_MAP || list->flag == MANDB_MAP_USER) - manpath = pathappend (manpath, list->key); + GL_LIST_FOREACH_START (config, item) + if (item->flag == MANDB_MAP || item->flag == MANDB_MAP_USER) + manpath = pathappend (manpath, item->key); + GL_LIST_FOREACH_END (config); return manpath; } @@ -1308,16 +1300,17 @@ char *get_mandb_manpath (void) */ char *get_catpath (const char *name, int cattype) { - struct list *list; - - for (list = namestore; list; list = list->next) - if (((cattype & SYSTEM_CAT) && list->flag == MANDB_MAP) || - ((cattype & USER_CAT) && list->flag == MANDB_MAP_USER)) { - size_t manlen = strlen (list->key); - if (STRNEQ (name, list->key, manlen)) { + const struct config_item *item; + char *ret = NULL; + + GL_LIST_FOREACH_START (config, item) + if (((cattype & SYSTEM_CAT) && item->flag == MANDB_MAP) || + ((cattype & USER_CAT) && item->flag == MANDB_MAP_USER)) { + size_t manlen = strlen (item->key); + if (STRNEQ (name, item->key, manlen)) { const char *suffix; char *infix; - char *catpath = xstrdup (list->cont); + char *catpath = xstrdup (item->cont); /* For NLS subdirectories (e.g. * /usr/share/man/de -> /var/cache/man/de), @@ -1325,10 +1318,12 @@ char *get_catpath (const char *name, int cattype) * long as this strictly follows the key. */ suffix = strrchr (name, '/'); - if (!suffix) - return appendstr (catpath, - name + manlen, - (void *) 0); + if (!suffix) { + ret = appendstr (catpath, + name + manlen, + (void *) 0); + break; + } while (suffix > name + manlen) if (*--suffix == '/') @@ -1349,25 +1344,32 @@ char *get_catpath (const char *name, int cattype) } catpath = appendstr (catpath, suffix, (void *) 0); - return catpath; + ret = catpath; + break; } } + GL_LIST_FOREACH_END (config); - return NULL; + return ret; } /* Check to see if the supplied man directory is a system-wide mandir. * Obviously, user directories must not be included here. */ -int is_global_mandir (const char *dir) +bool is_global_mandir (const char *dir) { - struct list *list; + const struct config_item *item; + bool ret = false; + + GL_LIST_FOREACH_START (config, item) + if (item->flag == MANDB_MAP && + STRNEQ (dir, item->key, strlen (item->key))) { + ret = true; + break; + } + GL_LIST_FOREACH_END (config); - for (list = namestore; list; list = list->next) - if (list->flag == MANDB_MAP && - STRNEQ (dir, list->key, strlen (list->key))) - return 1; - return 0; + return ret; } /* Accept a manpath (not a full pathname to a file) and return an FSSTND @@ -22,6 +22,10 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <stdbool.h> + +#include "gl_list.h" + struct locale_bits { char *language; char *territory; @@ -36,12 +40,12 @@ extern void free_locale_bits (struct locale_bits *bits); extern char *add_nls_manpaths (const char *manpathlist, const char *locales); extern char *get_manpath (const char *systems); extern char *get_manpath_from_path (const char *path, int mandatory); -extern void create_pathlist (const char *manp, char **mp); -extern void free_pathlist (char **mp); +extern gl_list_t create_pathlist (const char *manp); +extern void free_pathlist (gl_list_t list); extern char *get_mandb_manpath (void); extern char *get_catpath (const char *name, int cattype); -extern int is_global_mandir (const char *dir); -extern void read_config_file (int optional); +extern bool is_global_mandir (const char *dir); +extern void read_config_file (bool optional); extern const char *get_def (const char *thing, const char *def); extern const char *get_def_user (const char *thing, const char *def); -extern const char **get_sections (void); +extern gl_list_t get_sections (void); diff --git a/src/manpath.c b/src/manpath.c index de3a2948..97e27376 100644 --- a/src/manpath.c +++ b/src/manpath.c @@ -27,6 +27,7 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -51,8 +52,8 @@ int quiet = 0; man_sandbox *sandbox; /* unused, but needed by libman */ -static int cat = 0; -static int global = 0; +static bool cat = false; +static bool global = false; static const char *alt_system = ""; extern char *user_config_file; @@ -75,14 +76,14 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { case 'c': - cat = 1; + cat = true; return 0; case 'g': - global = 1; + global = true; quiet = 1; return 0; case 'd': - debug_level = 1; + debug_level = true; return 0; case 'q': quiet = 1; diff --git a/src/straycats.c b/src/straycats.c index 51f66170..0f4c50ee 100644 --- a/src/straycats.c +++ b/src/straycats.c @@ -28,6 +28,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -40,6 +41,8 @@ #include "canonicalize.h" #include "dirname.h" +#include "gl_array_list.h" +#include "gl_xlist.h" #include "gettext.h" #define _(String) gettext (String) @@ -47,6 +50,7 @@ #include "manconfig.h" #include "error.h" +#include "glcontainers.h" #include "pipeline.h" #include "decompress.h" #include "encodings.h" @@ -70,8 +74,8 @@ static int check_for_stray (MYDBM_FILE dbf) { DIR *cdir; struct dirent *catlist; - char **names; - size_t names_len, names_max, i; + gl_list_t names; + const char *name; size_t lenman, lencat; int strays = 0; @@ -81,30 +85,24 @@ static int check_for_stray (MYDBM_FILE dbf) return 0; } - names_len = 0; - names_max = 1024; - names = XNMALLOC (names_max, char *); + names = new_string_list (GL_ARRAY_LIST, false); while ((catlist = readdir (cdir)) != NULL) { if (*catlist->d_name == '.' && strlen (catlist->d_name) < (size_t) 3) continue; - if (names_len >= names_max) { - names_max *= 2; - names = xnrealloc (names, names_max, sizeof (char *)); - } - names[names_len++] = xstrdup (catlist->d_name); + gl_list_add_last (names, xstrdup (catlist->d_name)); } closedir (cdir); - order_files (catdir, names, names_len); + order_files (catdir, &names); mandir = appendstr (mandir, "/", (void *) 0); catdir = appendstr (catdir, "/", (void *) 0); lenman = strlen (mandir); lencat = strlen (catdir); - for (i = 0; i < names_len; ++i) { + GL_LIST_FOREACH_START (names, name) { struct mandata info; char *ext, *section; short found; @@ -116,8 +114,8 @@ static int check_for_stray (MYDBM_FILE dbf) memset (&info, 0, sizeof (struct mandata)); *(mandir + lenman) = *(catdir + lencat) = '\0'; - mandir = appendstr (mandir, names[i], (void *) 0); - catdir = appendstr (catdir, names[i], (void *) 0); + mandir = appendstr (mandir, name, (void *) 0); + catdir = appendstr (catdir, name, (void *) 0); ext = strrchr (mandir, '.'); if (!ext) { @@ -126,7 +124,7 @@ static int check_for_stray (MYDBM_FILE dbf) _("warning: %s: " "ignoring bogus filename"), catdir); - goto next_name; + continue; #if defined(COMP_SRC) || defined(COMP_CAT) @@ -197,13 +195,9 @@ static int check_for_stray (MYDBM_FILE dbf) further */ mandir_base = base_name (mandir); exists = dblookup_exact (dbf, mandir_base, info.ext, - 1); -#ifndef FAVOUR_STRAYCATS - if (exists && exists->id != WHATIS_CAT) -#else /* FAVOUR_STRAYCATS */ - if (exists && exists->id != WHATIS_CAT && - exists->id != WHATIS_MAN) -#endif /* !FAVOUR_STRAYCATS */ + true); + if (exists && + compare_ids (STRAY_CAT, exists->id, 0) >= 0) goto next_exists; debug ("%s(%s) is not in the db.\n", mandir_base, info.ext); @@ -270,17 +264,14 @@ static int check_for_stray (MYDBM_FILE dbf) if (find_name_decompressed (decomp, catdir_base, &lg)) { - struct page_description *descs; + gl_list_t descs; strays++; descs = parse_descriptions (mandir_base, lg.whatis); - if (descs) { - store_descriptions - (dbf, descs, &info, - NULL, mandir_base, - NULL); - free_descriptions (descs); - } + store_descriptions (dbf, descs, &info, + NULL, mandir_base, + NULL); + gl_list_free (descs); } else if (quiet < 2) error (0, 0, _("warning: %s: whatis parse for %s(%s) failed"), catdir, mandir_base, info.sec); @@ -295,10 +286,8 @@ next_exists: } next_section: free (section); -next_name: - free (names[i]); - } - free (names); + } GL_LIST_FOREACH_END (names); + gl_list_free (names); return strays; } diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index 3c56222a..74cae23b 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -98,6 +98,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \ $(top_srcdir)/m4/man-arg-db.m4 \ $(top_srcdir)/m4/man-arg-device.m4 \ $(top_srcdir)/m4/man-arg-mandirs.m4 \ + $(top_srcdir)/m4/man-arg-manual.m4 \ $(top_srcdir)/m4/man-arg-override-dir.m4 \ $(top_srcdir)/m4/man-arg-sections.m4 \ $(top_srcdir)/m4/man-arg-setuid.m4 \ @@ -120,7 +121,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \ $(top_srcdir)/gl/m4/btowc.m4 \ $(top_srcdir)/gl/m4/builtin-expect.m4 \ $(top_srcdir)/gl/m4/canonicalize.m4 \ - $(top_srcdir)/gl/m4/chdir-long.m4 \ + $(top_srcdir)/gl/m4/chdir-long.m4 $(top_srcdir)/gl/m4/chown.m4 \ $(top_srcdir)/gl/m4/clock_time.m4 $(top_srcdir)/gl/m4/close.m4 \ $(top_srcdir)/gl/m4/closedir.m4 $(top_srcdir)/gl/m4/codeset.m4 \ $(top_srcdir)/gl/m4/d-ino.m4 $(top_srcdir)/gl/m4/d-type.m4 \ @@ -164,7 +165,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/man-arg-automatic-create.m4 \ $(top_srcdir)/gl/m4/intmax_t.m4 \ $(top_srcdir)/gl/m4/inttypes_h.m4 $(top_srcdir)/gl/m4/ioctl.m4 \ $(top_srcdir)/gl/m4/langinfo_h.m4 \ - $(top_srcdir)/gl/m4/largefile.m4 \ + $(top_srcdir)/gl/m4/largefile.m4 $(top_srcdir)/gl/m4/lchown.m4 \ $(top_srcdir)/gl/m4/lib-ignore.m4 \ $(top_srcdir)/gl/m4/lib-ld.m4 $(top_srcdir)/gl/m4/lib-link.m4 \ $(top_srcdir)/gl/m4/lib-prefix.m4 \ diff --git a/src/ult_src.c b/src/ult_src.c index 15c2e52b..2b0ba278 100644 --- a/src/ult_src.c +++ b/src/ult_src.c @@ -46,6 +46,7 @@ #include "canonicalize.h" #include "dirname.h" #include "error.h" +#include "gl_xlist.h" #include "xvasprintf.h" #include "gettext.h" @@ -205,43 +206,24 @@ static char *find_include (const char *name, const char *path, } else { /* Try globbing - the file suffix might be missing. */ char *temp_file_asterisk = xasprintf ("%s*", temp_file); - char **candidate_files = expand_path (temp_file_asterisk); - int i; + gl_list_t candidate_files = expand_path (temp_file_asterisk); free (temp_file_asterisk); - if (CAN_ACCESS (candidate_files[0], F_OK)) { - free (ret); - ret = canonicalize_file_name (candidate_files[0]); + if (gl_list_size (candidate_files)) { + const char *candidate_file = gl_list_get_at + (candidate_files, 0); + if (CAN_ACCESS (candidate_file, F_OK)) { + free (ret); + ret = canonicalize_file_name (candidate_file); + } } - for (i = 0; candidate_files[i]; i++) - free (candidate_files[i]); - free (candidate_files); + gl_list_free (candidate_files); } free (temp_file); return ret; } -static void ult_trace (struct ult_trace *trace, const char *s) -{ - if (!trace) - return; - if (trace->len >= trace->max) { - trace->max *= 2; - trace->names = xnrealloc (trace->names, trace->max, - sizeof (char *)); - } - trace->names[trace->len++] = xstrdup (s); -} - -void free_ult_trace (struct ult_trace *trace) -{ - size_t i; - for (i = 0; i < trace->len; ++i) - free (trace->names[i]); - free (trace->names); -} - /* * recursive function which finds the ultimate source file by following * any ".so filename" directives in the first line of the man pages. @@ -251,21 +233,15 @@ void free_ult_trace (struct ult_trace *trace) * flags is a combination of SO_LINK | SOFT_LINK | HARD_LINK */ const char *ult_src (const char *name, const char *path, - struct stat *buf, int flags, struct ult_trace *trace) + struct stat *buf, int flags, gl_list_t trace) { static char *base; /* must be static */ static short recurse; /* must be static */ /* initialise the function */ - if (trace) { - if (!trace->names) { - trace->len = 0; - trace->max = 16; - trace->names = XNMALLOC (trace->max, char *); - } - ult_trace (trace, name); - } + if (trace) + gl_list_add_last (trace, name); /* as ult_softlink() & ult_hardlink() do all of their respective * resolving in one call, only need to sort them out once @@ -400,6 +376,6 @@ const char *ult_src (const char *name, const char *path, /* We have the ultimate source */ if (trace) - ult_trace (trace, base); + gl_list_add_last (trace, base); return base; } diff --git a/src/ult_src.h b/src/ult_src.h index 6fad4706..857700d4 100644 --- a/src/ult_src.h +++ b/src/ult_src.h @@ -22,22 +22,18 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "gl_list.h" + #define SO_LINK 0001 #define SOFT_LINK 0002 #define HARD_LINK 0004 -/* Trace of the link chain from a given file. Any names listed here should - * not have WHATIS_MAN entries created for them. - */ -struct ult_trace { - char **names; - size_t len; - size_t max; -}; - struct stat; +/* If ult_trace is non-NULL, it should be a gl_list_t of const char * which + * ult_src populates with the trace of the link chain from a given file. + * Any names listed here should not have WHATIS_MAN entries created for + * them. + */ extern const char *ult_src (const char *name, const char *path, - struct stat *buf, int flags, - struct ult_trace *trace); -extern void free_ult_trace (struct ult_trace *trace); + struct stat *buf, int flags, gl_list_t trace); diff --git a/src/whatis.c b/src/whatis.c index ee43f10a..8b648121 100644 --- a/src/whatis.c +++ b/src/whatis.c @@ -34,6 +34,7 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -56,6 +57,9 @@ #include "argp.h" #include "dirname.h" +#include "gl_hash_set.h" +#include "gl_list.h" +#include "gl_xset.h" #include "fnmatch.h" #include "progname.h" #include "xvasprintf.h" @@ -64,11 +68,10 @@ #include "cleanup.h" #include "error.h" +#include "glcontainers.h" #include "pipeline.h" #include "pathsearch.h" #include "linelength.h" -#include "hashtable.h" -#include "lower.h" #include "wordfnmatch.h" #include "xregcomp.h" #include "encodings.h" @@ -79,13 +82,13 @@ #include "manp.h" -static char *manpathlist[MAXDIRS]; +static gl_list_t manpathlist; extern char *user_config_file; static char **keywords; static int num_keywords; -int am_apropos; +bool am_apropos; char *database; int quiet = 1; man_sandbox *sandbox; @@ -95,14 +98,14 @@ iconv_t conv_to_locale; #endif /* HAVE_ICONV */ static regex_t *preg; -static int regex_opt; -static int exact; +static bool regex_opt; +static bool exact; -static int wildcard; +static bool wildcard; -static int require_all; +static bool require_all; -static int long_output; +static bool long_output; static char **sections; @@ -111,7 +114,7 @@ static const char *alt_systems = ""; static const char *locale = NULL; static char *multiple_locale = NULL, *internal_locale; -static struct hashtable *display_seen = NULL; +static gl_set_t display_seen = NULL; const char *argp_program_version; /* initialised in main */ const char *argp_program_bug_address = PACKAGE_BUGREPORT; @@ -167,33 +170,33 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { case 'd': - debug_level = 1; + debug_level = true; return 0; case 'v': quiet = 0; return 0; case 'r': - regex_opt = 1; + regex_opt = true; return 0; case 'e': /* Only makes sense for apropos, but has * historically been accepted by whatis anyway. */ - regex_opt = 0; - exact = 1; + regex_opt = false; + exact = true; return 0; case 'w': - regex_opt = 0; - wildcard = 1; + regex_opt = false; + wildcard = true; return 0; case 'a': if (am_apropos) - require_all = 1; + require_all = true; else argp_usage (state); return 0; case 'l': - long_output = 1; + long_output = true; return 0; case 's': sections = split_sections (arg); @@ -212,11 +215,11 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) return 0; case 'f': /* helpful override if program name detection fails */ - am_apropos = 0; + am_apropos = false; return 0; case 'k': /* helpful override if program name detection fails */ - am_apropos = 1; + am_apropos = true; return 0; case 'h': argp_state_help (state, state->out_stream, @@ -233,7 +236,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) exit (FAIL); case ARGP_KEY_SUCCESS: if (am_apropos && !exact && !wildcard) - regex_opt = 1; + regex_opt = true; return 0; } return ARGP_ERR_UNKNOWN; @@ -321,7 +324,7 @@ static char *simple_convert (iconv_t conv, char *string) * legacy mechanism. */ static void use_grep (const char * const *pages, int num_pages, char *manpath, - int *found) + bool *found) { char *whatis_file = xasprintf ("%s/whatis", manpath); @@ -361,7 +364,7 @@ static void use_grep (const char * const *pages, int num_pages, char *manpath, grep_pl = pipeline_new_commands (grep_cmd, (void *) 0); if (pipeline_run (grep_pl) == 0) - found[i] = 1; + found[i] = true; free (anchored_page); } @@ -387,7 +390,7 @@ static struct mandata *resolve_pointers (MYDBM_FILE dbf, struct mandata *info, * arbitrary: it's just there to avoid an infinite loop. */ newpage = info->pointer; - info = dblookup_exact (dbf, newpage, info->ext, 1); + info = dblookup_exact (dbf, newpage, info->ext, true); for (rounds = 0; rounds < 10; rounds++) { struct mandata *newinfo; @@ -400,7 +403,7 @@ static struct mandata *resolve_pointers (MYDBM_FILE dbf, struct mandata *info, STREQ (info->pointer, newpage))) return info; - newinfo = dblookup_exact (dbf, info->pointer, info->ext, 1); + newinfo = dblookup_exact (dbf, info->pointer, info->ext, true); free_mandata_struct (info); info = newinfo; } @@ -451,9 +454,9 @@ static void display (MYDBM_FILE dbf, struct mandata *info, const char *page) page_name = page; key = xasprintf ("%s (%s)", page_name, newinfo->ext); - if (hashtable_lookup_structure (display_seen, key, strlen (key))) + if (gl_set_search (display_seen, key)) goto out; - hashtable_install (display_seen, key, strlen (key), NULL); + gl_set_add (display_seen, xstrdup (key)); line_len = get_line_length (); @@ -499,56 +502,45 @@ out: static int do_whatis_section (MYDBM_FILE dbf, const char *page, const char *section) { + gl_list_t infos; struct mandata *info; int count = 0; - info = dblookup_all (dbf, page, section, 0); - while (info) { - struct mandata *pinfo; - + infos = dblookup_all (dbf, page, section, false); + GL_LIST_FOREACH_START (infos, info) { display (dbf, info, page); count++; - pinfo = info->next; /* go on to next structure */ - free_mandata_elements (info); - free (info); - info = pinfo; - } + } GL_LIST_FOREACH_END (infos); + gl_list_free (infos); return count; } -static int suitable_manpath (const char *manpath, const char *page_dir) +static bool suitable_manpath (const char *manpath, const char *page_dir) { char *page_manp, *pm; - char *page_manpathlist[MAXDIRS], **mp; - int ret; + gl_list_t page_manpathlist; + bool ret; page_manp = get_manpath_from_path (page_dir, 0); if (!page_manp || !*page_manp) { free (page_manp); - return 0; + return false; } pm = locale_manpath (page_manp); free (page_manp); page_manp = pm; - create_pathlist (page_manp, page_manpathlist); + page_manpathlist = create_pathlist (page_manp); - ret = 0; - for (mp = page_manpathlist; *mp; ++mp) { - if (STREQ (*mp, manpath)) { - ret = 1; - break; - } - } + ret = gl_list_search (page_manpathlist, manpath) ? true : false; - for (mp = page_manpathlist; *mp; ++mp) - free (*mp); + free_pathlist (page_manpathlist); free (page_manp); return ret; } static void do_whatis (MYDBM_FILE dbf, const char * const *pages, int num_pages, - const char *manpath, int *found) + const char *manpath, bool *found) { int i; @@ -586,39 +578,39 @@ static void do_whatis (MYDBM_FILE dbf, for (section = sections; *section; ++section) { if (do_whatis_section (dbf, page, *section)) - found[i] = 1; + found[i] = true; } } else { if (do_whatis_section (dbf, page, NULL)) - found[i] = 1; + found[i] = true; } free (page); } } -static int any_set (int num_pages, int *found_here) +static bool any_set (int num_pages, bool *found_here) { int i; for (i = 0; i < num_pages; ++i) if (found_here[i]) - return 1; - return 0; + return true; + return false; } -static int all_set (int num_pages, int *found_here) +static bool all_set (int num_pages, bool *found_here) { int i; for (i = 0; i < num_pages; ++i) if (!found_here[i]) - return 0; - return 1; + return false; + return true; } static void parse_name (const char * const *pages, int num_pages, - const char *dbname, int *found, int *found_here) + const char *dbname, bool *found, bool *found_here) { int i; @@ -626,57 +618,50 @@ static void parse_name (const char * const *pages, int num_pages, for (i = 0; i < num_pages; ++i) { if (regexec (&preg[i], dbname, 0, (regmatch_t *) 0, 0) == 0) - found[i] = found_here[i] = 1; + found[i] = found_here[i] = true; } return; } if (am_apropos && !wildcard) { - char *lowdbname = lower (dbname); - for (i = 0; i < num_pages; ++i) { - if (STREQ (lowdbname, pages[i])) - found[i] = found_here[i] = 1; + if (strcasecmp (dbname, pages[i]) == 0) + found[i] = found_here[i] = true; } - free (lowdbname); return; } for (i = 0; i < num_pages; ++i) { - if (fnmatch (pages[i], dbname, 0) == 0) - found[i] = found_here[i] = 1; + if (fnmatch (pages[i], dbname, FNM_CASEFOLD) == 0) + found[i] = found_here[i] = true; } } -/* return 1 on word match */ -static int match (const char *lowpage, const char *whatis) +/* return true on word match */ +static bool match (const char *page, const char *whatis) { - char *lowwhatis = lower (whatis); - size_t len = strlen (lowpage); - char *p, *begin; + size_t len = strlen (page); + const char *begin; + char *p; - begin = lowwhatis; + begin = whatis; /* check for string match, then see if it is a _word_ */ - while (lowwhatis && (p = strstr (lowwhatis, lowpage))) { + while (whatis && (p = strcasestr (whatis, page))) { char *left = p - 1; char *right = p + len; - if ((p == begin || (!CTYPE (islower, *left) && *left != '_')) && - (!*right || (!CTYPE (islower, *right) && *right != '_'))) { - free (begin); - return 1; - } - lowwhatis = p + 1; + if ((p == begin || (!CTYPE (isalpha, *left) && *left != '_')) && + (!*right || (!CTYPE (isalpha, *right) && *right != '_'))) + return true; + whatis = p + 1; } - free (begin); - return 0; + return false; } -static void parse_whatis (const char * const *pages, char * const *lowpages, - int num_pages, const char *whatis, - int *found, int *found_here) +static void parse_whatis (const char * const *pages, int num_pages, + const char *whatis, bool *found, bool *found_here) { int i; @@ -684,7 +669,7 @@ static void parse_whatis (const char * const *pages, char * const *lowpages, for (i = 0; i < num_pages; ++i) { if (regexec (&preg[i], whatis, 0, (regmatch_t *) 0, 0) == 0) - found[i] = found_here[i] = 1; + found[i] = found_here[i] = true; } return; } @@ -693,18 +678,18 @@ static void parse_whatis (const char * const *pages, char * const *lowpages, for (i = 0; i < num_pages; ++i) { if (exact) { if (fnmatch (pages[i], whatis, 0) == 0) - found[i] = found_here[i] = 1; + found[i] = found_here[i] = true; } else { if (word_fnmatch (pages[i], whatis)) - found[i] = found_here[i] = 1; + found[i] = found_here[i] = true; } } return; } for (i = 0; i < num_pages; ++i) { - if (match (lowpages[i], whatis)) - found[i] = found_here[i] = 1; + if (match (pages[i], whatis)) + found[i] = found_here[i] = true; } } @@ -715,25 +700,18 @@ static void parse_whatis (const char * const *pages, char * const *lowpages, /* scan for the page, print any matches */ static void do_apropos (MYDBM_FILE dbf, - const char * const *pages, int num_pages, int *found) + const char * const *pages, int num_pages, bool *found) { datum key, cont; - char **lowpages; - int *found_here; - int (*combine) (int, int *); - int i; + bool *found_here; + bool (*combine) (int, bool *); #ifndef BTREE datum nextkey; #else /* BTREE */ int end; #endif /* !BTREE */ - lowpages = XNMALLOC (num_pages, char *); - for (i = 0; i < num_pages; ++i) { - lowpages[i] = lower (pages[i]); - debug ("lower(%s) = \"%s\"\n", pages[i], lowpages[i]); - } - found_here = XNMALLOC (num_pages, int); + found_here = XNMALLOC (num_pages, bool); combine = require_all ? all_set : any_set; #ifndef BTREE @@ -797,19 +775,17 @@ static void do_apropos (MYDBM_FILE dbf, *tab = '\0'; memset (found_here, 0, num_pages * sizeof (*found_here)); + parse_name (pages, num_pages, + MYDBM_DPTR (key), found, found_here); if (am_apropos) { char *whatis; - parse_name ((const char **) lowpages, num_pages, - MYDBM_DPTR (key), found, found_here); whatis = info.whatis ? xstrdup (info.whatis) : NULL; if (!combine (num_pages, found_here) && whatis) - parse_whatis (pages, lowpages, num_pages, + parse_whatis (pages, num_pages, whatis, found, found_here); free (whatis); - } else - parse_name (pages, num_pages, - MYDBM_DPTR (key), found, found_here); + } if (combine (num_pages, found_here)) display (dbf, &info, MYDBM_DPTR (key)); @@ -831,31 +807,28 @@ nextpage: } free (found_here); - - for (i = 0; i < num_pages; ++i) - free (lowpages[i]); - free (lowpages); } /* loop through the man paths, searching for a match */ -static int search (const char * const *pages, int num_pages) +static bool search (const char * const *pages, int num_pages) { - int *found = XCALLOC (num_pages, int); - char *catpath, **mp; - int any_found, i; + bool *found = XCALLOC (num_pages, bool); + char *catpath, *mp; + bool any_found; + int i; - for (mp = manpathlist; *mp; mp++) { + GL_LIST_FOREACH_START (manpathlist, mp) { MYDBM_FILE dbf; - catpath = get_catpath (*mp, SYSTEM_CAT | USER_CAT); + catpath = get_catpath (mp, SYSTEM_CAT | USER_CAT); if (catpath) { database = mkdbname (catpath); free (catpath); } else - database = mkdbname (*mp); + database = mkdbname (mp); - debug ("path=%s\n", *mp); + debug ("path=%s\n", mp); dbf = MYDBM_RDOPEN (database); if (dbf && dbver_rd (dbf)) { @@ -863,7 +836,7 @@ static int search (const char * const *pages, int num_pages) dbf = NULL; } if (!dbf) { - use_grep (pages, num_pages, *mp, found); + use_grep (pages, num_pages, mp, found); continue; } @@ -873,19 +846,19 @@ static int search (const char * const *pages, int num_pages) if (regex_opt || wildcard) do_apropos (dbf, pages, num_pages, found); else - do_whatis (dbf, pages, num_pages, *mp, found); + do_whatis (dbf, pages, num_pages, mp, found); } free (database); database = NULL; MYDBM_CLOSE (dbf); - } + } GL_LIST_FOREACH_END (manpathlist); chkr_garbage_detector (); - any_found = 0; + any_found = false; for (i = 0; i < num_pages; ++i) { if (found[i]) - any_found = 1; + any_found = true; else fprintf (stderr, _("%s: nothing appropriate.\n"), pages[i]); @@ -906,11 +879,11 @@ int main (int argc, char *argv[]) set_program_name (argv[0]); program_base_name = base_name (program_name); if (STREQ (program_base_name, APROPOS_NAME)) { - am_apropos = 1; + am_apropos = true; argp_program_version = "apropos " PACKAGE_VERSION; } else { struct argp_option *optionp; - am_apropos = 0; + am_apropos = false; argp_program_version = "whatis " PACKAGE_VERSION; for (optionp = (struct argp_option *) whatis_argp.options; optionp->name || optionp->key || optionp->arg || @@ -969,9 +942,9 @@ int main (int argc, char *argv[]) else free (get_manpath (NULL)); - create_pathlist (manp, manpathlist); + manpathlist = create_pathlist (manp); - display_seen = hashtable_create (&null_hashtable_free); + display_seen = new_string_set (GL_HASH_SET); #ifdef HAVE_ICONV locale_charset = xasprintf ("%s//IGNORE", get_locale_charset ()); @@ -1001,9 +974,10 @@ int main (int argc, char *argv[]) if (conv_to_locale != (iconv_t) -1) iconv_close (conv_to_locale); #endif /* HAVE_ICONV */ - hashtable_free (display_seen); + gl_set_free (display_seen); free_pathlist (manpathlist); free (manp); free (internal_locale); + sandbox_free (sandbox); exit (status); } diff --git a/src/zsoelim.c b/src/zsoelim.c index a7225f64..b2e62052 100644 --- a/src/zsoelim.c +++ b/src/zsoelim.c @@ -816,6 +816,8 @@ char *yytext; #define PIPE so_pipe[so_stack_ptr] #include "dirname.h" +#include "gl_linkedhash_list.h" +#include "gl_xlist.h" #include "xgetcwd.h" #include "xvasprintf.h" @@ -826,6 +828,7 @@ char *yytext; #include "manconfig.h" #include "error.h" +#include "glcontainers.h" #include "pipeline.h" #include "decompress.h" @@ -845,12 +848,12 @@ static int so_line[MAX_SO_DEPTH]; static pipeline *so_pipe[MAX_SO_DEPTH]; static int so_stack_ptr; static int no_newline; -static char * const *so_manpathlist; +static gl_list_t so_manpathlist; static const char *so_parent_path; struct zsoelim_stdin_data { char *path; - char * const *manpathlist; + gl_list_t manpathlist; }; /* The flex documentation says that yyin is only used by YY_INPUT, so we @@ -868,9 +871,9 @@ struct zsoelim_stdin_data { result = YY_NULL; \ } #define YY_NO_INPUT -#line 872 "zsoelim.c" +#line 875 "zsoelim.c" -#line 874 "zsoelim.c" +#line 877 "zsoelim.c" #define INITIAL 0 #define so 1 @@ -1093,10 +1096,10 @@ YY_DECL } { -#line 128 "zsoelim.l" +#line 131 "zsoelim.l" -#line 1100 "zsoelim.c" +#line 1103 "zsoelim.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1144,7 +1147,7 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 130 "zsoelim.l" +#line 133 "zsoelim.l" { no_newline = 1; ECHO; @@ -1153,7 +1156,7 @@ YY_RULE_SETUP YY_BREAK case 2: YY_RULE_SETUP -#line 136 "zsoelim.l" +#line 139 "zsoelim.l" { no_newline = 1; BEGIN (so); /* Now we're in the .so environment */ @@ -1161,7 +1164,7 @@ YY_RULE_SETUP YY_BREAK case 3: YY_RULE_SETUP -#line 141 "zsoelim.l" +#line 144 "zsoelim.l" { no_newline = 1; ECHO; /* Now we're in the .lf environment */ @@ -1169,26 +1172,26 @@ YY_RULE_SETUP } YY_BREAK case 4: -#line 148 "zsoelim.l" +#line 151 "zsoelim.l" case 5: /* rule 5 can match eol */ -#line 149 "zsoelim.l" +#line 152 "zsoelim.l" case 6: /* rule 6 can match eol */ -#line 150 "zsoelim.l" +#line 153 "zsoelim.l" case 7: /* rule 7 can match eol */ -#line 151 "zsoelim.l" +#line 154 "zsoelim.l" case 8: /* rule 8 can match eol */ -#line 152 "zsoelim.l" +#line 155 "zsoelim.l" case 9: /* rule 9 can match eol */ -#line 153 "zsoelim.l" +#line 156 "zsoelim.l" case 10: /* rule 10 can match eol */ YY_RULE_SETUP -#line 153 "zsoelim.l" +#line 156 "zsoelim.l" { no_newline = 1; ECHO; @@ -1197,7 +1200,7 @@ YY_RULE_SETUP case 11: /* rule 11 can match eol */ YY_RULE_SETUP -#line 158 "zsoelim.l" +#line 161 "zsoelim.l" { no_newline = 0; putchar ('\n'); @@ -1206,7 +1209,7 @@ YY_RULE_SETUP YY_BREAK case 12: YY_RULE_SETUP -#line 165 "zsoelim.l" +#line 168 "zsoelim.l" { /* file names including whitespace ? */ if (so_stack_ptr == MAX_SO_DEPTH - 1) error (FATAL, 0, @@ -1242,7 +1245,7 @@ YY_RULE_SETUP case 13: /* rule 13 can match eol */ YY_RULE_SETUP -#line 197 "zsoelim.l" +#line 200 "zsoelim.l" { no_newline = 0; BEGIN (INITIAL); @@ -1251,7 +1254,7 @@ YY_RULE_SETUP case 14: /* rule 14 can match eol */ YY_RULE_SETUP -#line 202 "zsoelim.l" +#line 205 "zsoelim.l" { no_newline = 0; error (OK, 0, @@ -1265,7 +1268,7 @@ YY_RULE_SETUP YY_BREAK case 15: YY_RULE_SETUP -#line 213 "zsoelim.l" +#line 216 "zsoelim.l" { no_newline = 1; ECHO; @@ -1274,7 +1277,7 @@ YY_RULE_SETUP YY_BREAK case 16: YY_RULE_SETUP -#line 219 "zsoelim.l" +#line 222 "zsoelim.l" { no_newline = 1; ECHO; @@ -1283,7 +1286,7 @@ YY_RULE_SETUP case 17: /* rule 17 can match eol */ YY_RULE_SETUP -#line 224 "zsoelim.l" +#line 227 "zsoelim.l" { no_newline = 0; putchar ('\n'); @@ -1292,7 +1295,7 @@ YY_RULE_SETUP YY_BREAK case 18: YY_RULE_SETUP -#line 231 "zsoelim.l" +#line 234 "zsoelim.l" { no_newline = 1; ECHO; @@ -1303,7 +1306,7 @@ YY_RULE_SETUP YY_BREAK case 19: YY_RULE_SETUP -#line 239 "zsoelim.l" +#line 242 "zsoelim.l" { /* file names including whitespace ?? */ no_newline = 1; ECHO; @@ -1317,7 +1320,7 @@ YY_RULE_SETUP YY_BREAK case 20: YY_RULE_SETUP -#line 250 "zsoelim.l" +#line 253 "zsoelim.l" { no_newline = 1; ECHO; @@ -1326,7 +1329,7 @@ YY_RULE_SETUP case 21: /* rule 21 can match eol */ YY_RULE_SETUP -#line 255 "zsoelim.l" +#line 258 "zsoelim.l" { no_newline = 0; putchar ('\n'); @@ -1336,7 +1339,7 @@ YY_RULE_SETUP YY_BREAK case 22: YY_RULE_SETUP -#line 262 "zsoelim.l" +#line 265 "zsoelim.l" { no_newline = 1; error (OK, 0, @@ -1350,7 +1353,7 @@ YY_RULE_SETUP case 23: /* rule 23 can match eol */ YY_RULE_SETUP -#line 272 "zsoelim.l" +#line 275 "zsoelim.l" { no_newline = 0; error (OK, 0, @@ -1368,14 +1371,13 @@ case YY_STATE_EOF(de): case YY_STATE_EOF(end_request): case YY_STATE_EOF(lfnumber): case YY_STATE_EOF(lfname): -#line 283 "zsoelim.l" +#line 286 "zsoelim.l" { pipeline_wait (PIPE); pipeline_free (PIPE); PIPE = NULL; free (NAME); NAME = NULL; - so_manpathlist = NULL; if (no_newline) putchar ('\n'); @@ -1393,10 +1395,10 @@ case YY_STATE_EOF(lfname): YY_BREAK case 24: YY_RULE_SETUP -#line 304 "zsoelim.l" +#line 306 "zsoelim.l" ECHO; YY_BREAK -#line 1400 "zsoelim.c" +#line 1402 "zsoelim.c" case YY_END_OF_BUFFER: { @@ -2355,7 +2357,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 304 "zsoelim.l" +#line 306 "zsoelim.l" #ifdef ACCEPT_QUOTES @@ -2375,7 +2377,7 @@ static void zap_quotes (void) #endif /* initialise the stack and call the parser */ -void zsoelim_parse_file (char * const *manpathlist, const char *parent_path) +void zsoelim_parse_file (gl_list_t manpathlist, const char *parent_path) { #ifdef PP_COOKIE const char *line; @@ -2432,11 +2434,10 @@ static pipeline *try_compressed (char **filename) /* This routine is used to open the specified file or uncompress a compressed version and open that instead */ -int zsoelim_open_file (const char *filename, char * const *manpathlist, +int zsoelim_open_file (const char *filename, gl_list_t manpathlist, const char *parent_path) { pipeline *decomp; - char * const *mp; if (parent_path) debug ("opening %s (parent path: %s)\n", @@ -2449,6 +2450,7 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, NAME = xstrdup (filename); } else { char *compfile; + const char *mp; /* If there is no parent path, try opening directly first. */ if (!parent_path) { @@ -2462,7 +2464,7 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, free (compfile); } - if (manpathlist && strchr (filename, '/')) { + if (strchr (filename, '/')) { /* File name with a directory part. Try looking it * up within each manpath entry. */ @@ -2479,11 +2481,11 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, free (compfile); } - for (mp = manpathlist; *mp; ++mp) { - if (parent_path && STREQ (*mp, parent_path)) + GL_LIST_FOREACH_START (manpathlist, mp) { + if (parent_path && STREQ (mp, parent_path)) continue; - compfile = xasprintf ("%s/%s.", *mp, filename); + compfile = xasprintf ("%s/%s.", mp, filename); decomp = try_compressed (&compfile); if (decomp) { @@ -2492,14 +2494,14 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, } free (compfile); - } - } else if (manpathlist) { + } GL_LIST_FOREACH_END (manpathlist); + } else { /* File name with no directory part. Try searching * the manpath. */ char *name, *sec, *dot; - char **names; - char **np; + gl_list_t names; + const char *found_name; name = xstrdup (filename); dot = strchr (name, '.'); @@ -2516,29 +2518,34 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, if (parent_path) { names = look_for_file (parent_path, sec, name, 0, LFF_MATCHCASE); - for (np = names; np && *np; ++np) { - decomp = decompress_open (*np); + GL_LIST_FOREACH_START (names, found_name) { + decomp = decompress_open (found_name); if (decomp) { - NAME = xstrdup (*np); + NAME = xstrdup (found_name); + gl_list_free (names); goto out; } - } + } GL_LIST_FOREACH_END (names); + gl_list_free (names); } - for (mp = manpathlist; *mp; ++mp) { - if (parent_path && STREQ (*mp, parent_path)) + GL_LIST_FOREACH_START (manpathlist, mp) { + if (parent_path && STREQ (mp, parent_path)) continue; - names = look_for_file (*mp, sec, name, + names = look_for_file (mp, sec, name, 0, LFF_MATCHCASE); - for (np = names; np && *np; ++np) { - decomp = decompress_open (*np); + GL_LIST_FOREACH_START (names, found_name) { + decomp = decompress_open (found_name); if (decomp) { - NAME = xstrdup (*np); + NAME = xstrdup (found_name); + gl_list_free (names); + free (name); goto out; } - } - } + } GL_LIST_FOREACH_END (names); + gl_list_free (names); + } GL_LIST_FOREACH_END (manpathlist); free (name); } @@ -2575,13 +2582,17 @@ out: void zsoelim_stdin (void *data) { struct zsoelim_stdin_data *zsoelim_data = data; + gl_list_t empty; - zsoelim_open_file ("-", NULL, zsoelim_data->path); + empty = gl_list_create_empty (GL_LINKEDHASH_LIST, NULL, NULL, NULL, + true); + zsoelim_open_file ("-", empty, zsoelim_data->path); + gl_list_free (empty); zsoelim_parse_file (zsoelim_data->manpathlist, zsoelim_data->path); } struct zsoelim_stdin_data *zsoelim_stdin_data_new (const char *path, - char * const *manpathlist) + gl_list_t manpathlist) { struct zsoelim_stdin_data *data = XMALLOC (struct zsoelim_stdin_data); diff --git a/src/zsoelim.h b/src/zsoelim.h index f17c08e8..4aaf53d6 100644 --- a/src/zsoelim.h +++ b/src/zsoelim.h @@ -20,13 +20,15 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -int zsoelim_open_file (const char *filename, char * const *manpathlist, +#include "gl_list.h" + +int zsoelim_open_file (const char *filename, gl_list_t manpathlist, const char *parent_path); -void zsoelim_parse_file (char * const *manpathlist, const char *parent_path); +void zsoelim_parse_file (gl_list_t manpathlist, const char *parent_path); struct zsoelim_stdin_data; void zsoelim_stdin (void *data); struct zsoelim_stdin_data *zsoelim_stdin_data_new (const char *path, - char * const *manpathlist); + gl_list_t manpathlist); void zsoelim_stdin_data_free (void *data); diff --git a/src/zsoelim.l b/src/zsoelim.l index b3dc7807..346dfbd3 100644 --- a/src/zsoelim.l +++ b/src/zsoelim.l @@ -59,6 +59,8 @@ #define PIPE so_pipe[so_stack_ptr] #include "dirname.h" +#include "gl_linkedhash_list.h" +#include "gl_xlist.h" #include "xgetcwd.h" #include "xvasprintf.h" @@ -69,6 +71,7 @@ #include "manconfig.h" #include "error.h" +#include "glcontainers.h" #include "pipeline.h" #include "decompress.h" @@ -88,12 +91,12 @@ static int so_line[MAX_SO_DEPTH]; static pipeline *so_pipe[MAX_SO_DEPTH]; static int so_stack_ptr; static int no_newline; -static char * const *so_manpathlist; +static gl_list_t so_manpathlist; static const char *so_parent_path; struct zsoelim_stdin_data { char *path; - char * const *manpathlist; + gl_list_t manpathlist; }; /* The flex documentation says that yyin is only used by YY_INPUT, so we @@ -286,7 +289,6 @@ W [ \t] PIPE = NULL; free (NAME); NAME = NULL; - so_manpathlist = NULL; if (no_newline) putchar ('\n'); @@ -320,7 +322,7 @@ static void zap_quotes (void) #endif /* initialise the stack and call the parser */ -void zsoelim_parse_file (char * const *manpathlist, const char *parent_path) +void zsoelim_parse_file (gl_list_t manpathlist, const char *parent_path) { #ifdef PP_COOKIE const char *line; @@ -377,11 +379,10 @@ static pipeline *try_compressed (char **filename) /* This routine is used to open the specified file or uncompress a compressed version and open that instead */ -int zsoelim_open_file (const char *filename, char * const *manpathlist, +int zsoelim_open_file (const char *filename, gl_list_t manpathlist, const char *parent_path) { pipeline *decomp; - char * const *mp; if (parent_path) debug ("opening %s (parent path: %s)\n", @@ -394,6 +395,7 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, NAME = xstrdup (filename); } else { char *compfile; + const char *mp; /* If there is no parent path, try opening directly first. */ if (!parent_path) { @@ -407,7 +409,7 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, free (compfile); } - if (manpathlist && strchr (filename, '/')) { + if (strchr (filename, '/')) { /* File name with a directory part. Try looking it * up within each manpath entry. */ @@ -424,11 +426,11 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, free (compfile); } - for (mp = manpathlist; *mp; ++mp) { - if (parent_path && STREQ (*mp, parent_path)) + GL_LIST_FOREACH_START (manpathlist, mp) { + if (parent_path && STREQ (mp, parent_path)) continue; - compfile = xasprintf ("%s/%s.", *mp, filename); + compfile = xasprintf ("%s/%s.", mp, filename); decomp = try_compressed (&compfile); if (decomp) { @@ -437,14 +439,14 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, } free (compfile); - } - } else if (manpathlist) { + } GL_LIST_FOREACH_END (manpathlist); + } else { /* File name with no directory part. Try searching * the manpath. */ char *name, *sec, *dot; - char **names; - char **np; + gl_list_t names; + const char *found_name; name = xstrdup (filename); dot = strchr (name, '.'); @@ -461,29 +463,34 @@ int zsoelim_open_file (const char *filename, char * const *manpathlist, if (parent_path) { names = look_for_file (parent_path, sec, name, 0, LFF_MATCHCASE); - for (np = names; np && *np; ++np) { - decomp = decompress_open (*np); + GL_LIST_FOREACH_START (names, found_name) { + decomp = decompress_open (found_name); if (decomp) { - NAME = xstrdup (*np); + NAME = xstrdup (found_name); + gl_list_free (names); goto out; } - } + } GL_LIST_FOREACH_END (names); + gl_list_free (names); } - for (mp = manpathlist; *mp; ++mp) { - if (parent_path && STREQ (*mp, parent_path)) + GL_LIST_FOREACH_START (manpathlist, mp) { + if (parent_path && STREQ (mp, parent_path)) continue; - names = look_for_file (*mp, sec, name, + names = look_for_file (mp, sec, name, 0, LFF_MATCHCASE); - for (np = names; np && *np; ++np) { - decomp = decompress_open (*np); + GL_LIST_FOREACH_START (names, found_name) { + decomp = decompress_open (found_name); if (decomp) { - NAME = xstrdup (*np); + NAME = xstrdup (found_name); + gl_list_free (names); + free (name); goto out; } - } - } + } GL_LIST_FOREACH_END (names); + gl_list_free (names); + } GL_LIST_FOREACH_END (manpathlist); free (name); } @@ -520,13 +527,17 @@ out: void zsoelim_stdin (void *data) { struct zsoelim_stdin_data *zsoelim_data = data; + gl_list_t empty; - zsoelim_open_file ("-", NULL, zsoelim_data->path); + empty = gl_list_create_empty (GL_LINKEDHASH_LIST, NULL, NULL, NULL, + true); + zsoelim_open_file ("-", empty, zsoelim_data->path); + gl_list_free (empty); zsoelim_parse_file (zsoelim_data->manpathlist, zsoelim_data->path); } struct zsoelim_stdin_data *zsoelim_stdin_data_new (const char *path, - char * const *manpathlist) + gl_list_t manpathlist) { struct zsoelim_stdin_data *data = XMALLOC (struct zsoelim_stdin_data); diff --git a/src/zsoelim_main.c b/src/zsoelim_main.c index ef6d1b67..da0b0fa0 100644 --- a/src/zsoelim_main.c +++ b/src/zsoelim_main.c @@ -27,9 +27,11 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include <stdbool.h> #include <stdlib.h> #include "argp.h" +#include "gl_list.h" #include "progname.h" #include "xvasprintf.h" @@ -52,7 +54,7 @@ int quiet = 1; man_sandbox *sandbox; -static char *manpathlist[MAXDIRS]; +static gl_list_t manpathlist; static char **files; static int num_files; @@ -75,7 +77,7 @@ static error_t parse_opt (int key, char *arg ATTRIBUTE_UNUSED, { switch (key) { case 'd': - debug_level = 1; + debug_level = true; return 0; case 'C': return 0; /* compatibility with GNU soelim */ @@ -140,7 +142,7 @@ int main (int argc, char *argv[]) manp = add_nls_manpaths (get_manpath (NULL), all_locales); free (all_locales); - create_pathlist (manp, manpathlist); + manpathlist = create_pathlist (manp); /* parse files in command line order */ for (i = 0; i < num_files; ++i) { @@ -152,6 +154,7 @@ int main (int argc, char *argv[]) free_pathlist (manpathlist); free (manp); free (internal_locale); + sandbox_free (sandbox); return OK; } |