示例#1
0
文件: whatis.c 项目: Shivox/man-db
/* scan for the page, print any matches */
static void do_apropos (MYDBM_FILE dbf,
			const char * const *pages, int num_pages, int *found)
{
	datum key, cont;
	char **lowpages;
	int *found_here;
	int (*combine) (int, int *);
	int i;
#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);
	combine = require_all ? all_set : any_set;

#ifndef BTREE
	key = MYDBM_FIRSTKEY (dbf);
	while (MYDBM_DPTR (key)) {
		cont = MYDBM_FETCH (dbf, key);
#else /* BTREE */
	end = btree_nextkeydata (dbf, &key, &cont);
	while (!end) {
#endif /* !BTREE */
		char *tab;
		struct mandata info;

		memset (&info, 0, sizeof (info));

		/* bug#4372, NULL pointer dereference in MYDBM_DPTR (cont),
		 * fix by [email protected] (J.H.M.Dassen), thanx Ray.
		 * cjwatson: In that case, complain and exit, otherwise we
		 * might loop (bug #95052).
		 */
		if (!MYDBM_DPTR (cont))
		{
			debug ("key was %s\n", MYDBM_DPTR (key));
			error (FATAL, 0,
			       _("Database %s corrupted; rebuild with "
				 "mandb --create"),
			       database);
		}

		if (*MYDBM_DPTR (key) == '$')
			goto nextpage;

		if (*MYDBM_DPTR (cont) == '\t')
			goto nextpage;

		/* a real page */

		split_content (MYDBM_DPTR (cont), &info);

		/* If there are sections given, does any of them match
		 * either the section or extension of this page?
		 */
		if (sections) {
			char * const *section;
			int matched = 0;

			for (section = sections; *section; ++section) {
				if (STREQ (*section, info.sec) ||
				    STREQ (*section, info.ext)) {
					matched = 1;
					break;
				}
			}

			if (!matched)
				goto nextpage;
		}

		tab = strrchr (MYDBM_DPTR (key), '\t');
		if (tab) 
			 *tab = '\0';

		memset (found_here, 0, num_pages * sizeof (*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,
					      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));

		if (tab)
			*tab = '\t';
nextpage:
#ifndef BTREE
		nextkey = MYDBM_NEXTKEY (dbf, key);
		MYDBM_FREE_DPTR (cont);
		MYDBM_FREE_DPTR (key);
		key = nextkey; 
#else /* BTREE */
		MYDBM_FREE_DPTR (cont);
		MYDBM_FREE_DPTR (key);
		end = btree_nextkeydata (dbf, &key, &cont);
#endif /* !BTREE */
		info.addr = NULL; /* == MYDBM_DPTR (cont), freed above */
		free_mandata_elements (&info);
	}

	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)
{
	int *found = XCALLOC (num_pages, int);
	char *catpath, **mp;
	int any_found, i;

	for (mp = manpathlist; *mp; mp++) {
		MYDBM_FILE dbf;

		catpath = get_catpath (*mp, SYSTEM_CAT | USER_CAT);
		
		if (catpath) {
			database = mkdbname (catpath);
			free (catpath);
		} else
			database = mkdbname (*mp);

		debug ("path=%s\n", *mp);

		dbf = MYDBM_RDOPEN (database);
		if (dbf && dbver_rd (dbf)) {
			MYDBM_CLOSE (dbf);
			dbf = NULL;
		}
		if (!dbf) {
			use_grep (pages, num_pages, *mp, found);
			continue;
		}

		if (am_apropos)
			do_apropos (dbf, pages, num_pages, found);
		else {
			if (regex_opt || wildcard)
				do_apropos (dbf, pages, num_pages, found);
			else
				do_whatis (dbf, pages, num_pages, *mp, found);
		}
		free (database);
		database = NULL;
		MYDBM_CLOSE (dbf);
	}

	chkr_garbage_detector ();

	any_found = 0;
	for (i = 0; i < num_pages; ++i) {
		if (found[i])
			any_found = 1;
		else
			fprintf (stderr, _("%s: nothing appropriate.\n"),
				 pages[i]);
	}

	free (found);
	return any_found;
}
示例#2
0
int dbstore (struct mandata *in, const char *base)
{
	datum oldkey, oldcont;

	memset (&oldkey, 0, sizeof oldkey);
	memset (&oldcont, 0, sizeof oldcont);

	/* create a simple key */
	MYDBM_SET (oldkey, name_to_key (base));
 	if (!*base) {
		dbprintf (in);
 		return 2;
 	}

	if (in->name) {
		error (0, 0, "in->name (%s) should not be set when calling "
			     "dbstore()!\n",
		       in->name);
		free (in->name);
		in->name = NULL;
	}

	/* get the content for the simple key */

	oldcont = MYDBM_FETCH (dbf, oldkey);

	if (MYDBM_DPTR (oldcont) == NULL) { 		/* situation (1) */
		if (!STREQ (base, MYDBM_DPTR (oldkey)))
			in->name = xstrdup (base);
		oldcont = make_content (in);
		if (MYDBM_REPLACE (dbf, oldkey, oldcont))
			gripe_replace_key (MYDBM_DPTR (oldkey));
		free (MYDBM_DPTR (oldcont));
		free (in->name);
		in->name = NULL;
	} else if (*MYDBM_DPTR (oldcont) == '\t') { 	/* situation (2) */
		datum newkey, newcont;

		memset (&newkey, 0, sizeof newkey);
		memset (&newcont, 0, sizeof newcont);

		newkey = make_multi_key (base, in->ext);
		newcont = make_content (in);

		/* Try to insert the new multi data */

		if (MYDBM_INSERT (dbf, newkey, newcont)) {
			datum cont;
			struct mandata info;
			int ret;

			MYDBM_FREE (MYDBM_DPTR (oldcont));
			cont = MYDBM_FETCH (dbf, newkey);
			split_content (MYDBM_DPTR (cont), &info);
			ret = replace_if_necessary (in, &info,
						    newkey, newcont);
			/* MYDBM_FREE (MYDBM_DPTR (cont)); */
			free_mandata_elements (&info);
			free (MYDBM_DPTR (newkey));
			free (MYDBM_DPTR (newcont));
			free (MYDBM_DPTR (oldkey));

			return ret;
		}

		/* Now lets add some info to the simple key's cont. */

		/* This next bit needs to be done first as we'll wipe out
		   MYDBM_DPTR (oldcont) otherwise (for NDBM only!) */

		free (MYDBM_DPTR (newkey));
		free (MYDBM_DPTR (newcont));

		MYDBM_SET (newcont, xasprintf (
			"%s\t%s\t%s", MYDBM_DPTR (oldcont), base, in->ext));
		MYDBM_FREE (MYDBM_DPTR (oldcont));

		/* Try to replace the old simple data with the new stuff */

		if (MYDBM_REPLACE (dbf, oldkey, newcont))
			gripe_replace_key (MYDBM_DPTR (oldkey));

		free (MYDBM_DPTR (newcont));
	} else { 				/* situation (3) */
		datum newkey, newcont, lastkey, lastcont;
		struct mandata old;
		char *old_name;

		memset (&newkey, 0, sizeof newkey);
		memset (&newcont, 0, sizeof newcont);
		memset (&lastkey, 0, sizeof lastkey);
		memset (&lastcont, 0, sizeof lastcont);

		/* Extract the old singular reference */

		split_content (MYDBM_DPTR (oldcont), &old);

		/* Create multi keys for both old
		   and new items, create new content */

		if (old.name)
			old_name = xstrdup (old.name);
		else
			old_name = xstrdup (MYDBM_DPTR (oldkey));

		lastkey = make_multi_key (old_name, old.ext);

		/* Check against identical multi keys before inserting
		   into db */

		if (STREQ (old_name, base) && STREQ (old.ext, in->ext)) {
			int ret;

			if (!STREQ (base, MYDBM_DPTR (oldkey)))
				in->name = xstrdup (base);
			newcont = make_content (in);
			ret = replace_if_necessary (in, &old, oldkey, newcont);
			/* MYDBM_FREE (MYDBM_DPTR (oldcont)); */
			free_mandata_elements (&old);
			free (MYDBM_DPTR (newcont));
			free (MYDBM_DPTR (lastkey));
			free (MYDBM_DPTR (oldkey));
			free (old_name);
			free (in->name);
			in->name = NULL;

			return ret;
		}

		/* Multi keys use the proper case, and so don't need a name
		 * field.
		 */
		if (old.name) {
			free (old.name);
			old.name = NULL;
		}

		lastcont = make_content (&old);

		/* We always replace here; if the multi key already exists
		 * in the database, then that indicates some kind of
		 * database corruption, but our new multi key is almost
		 * certainly better.
		 */
		if (MYDBM_REPLACE (dbf, lastkey, lastcont))
			gripe_replace_key (MYDBM_DPTR (lastkey));

		free (MYDBM_DPTR (lastkey));
		free (MYDBM_DPTR (lastcont));

		newkey = make_multi_key (base, in->ext);
		newcont = make_content (in);

		if (MYDBM_REPLACE (dbf, newkey, newcont))
			gripe_replace_key (MYDBM_DPTR (newkey));

		free (MYDBM_DPTR (newkey));
		free (MYDBM_DPTR (newcont));

		/* Now build a simple reference to the above two items */

		MYDBM_SET (newcont, xasprintf (
			"\t%s\t%s\t%s\t%s", old_name, old.ext, base, in->ext));

		if (MYDBM_REPLACE (dbf, oldkey, newcont))
			gripe_replace_key (MYDBM_DPTR (oldkey));

		/* MYDBM_FREE (MYDBM_DPTR (oldcont)); */
		free_mandata_elements (&old);
		free (MYDBM_DPTR (newcont));
		free (old_name);
	}

	free (MYDBM_DPTR (oldkey));
	return 0;
}