NetBSD-Bugs archive

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

bin/51062: Allow non numeric sections to be indexed and searched by apropos(1)



>Number:         51062
>Category:       bin
>Synopsis:       Allow non numeric sections to be indexed and searched by apropos(1)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Apr 12 15:40:00 +0000 2016
>Originator:     Abhinav Upadhyay
>Release:        CURRENT
>Organization:
>Environment:
>Description:
Apropos(1) doesn't allow searching for man pages in non-numeric sections. Also, makemandb(8) indexes only the first character of the section number and drops everything else.


The attached patch fixes both the problems. It also includes changes for tickets bin/51038, bin/51039, and bin/51040.

I can probably send a smaller patch if there is no interest in the aforementioned patches :)
>How-To-Repeat:
apropos -s 9lua systm


>Fix:
Index: apropos-utils.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/makemandb/apropos-utils.c,v
retrieving revision 1.22
diff -u -r1.22 apropos-utils.c
--- apropos-utils.c	31 Mar 2016 20:16:58 -0000	1.22
+++ apropos-utils.c	12 Apr 2016 15:31:27 -0000
@@ -300,18 +300,19 @@
  *  	In normal cases the function should return a handle to the db.
  */
 sqlite3 *
-init_db(int db_flag, const char *manconf)
+init_db(mandb_access_mode db_flag, const char *manconf)
 {
 	sqlite3 *db = NULL;
 	sqlite3_stmt *stmt;
 	struct stat sb;
 	int rc;
 	int create_db_flag = 0;
+	int access_mode;
 
 	char *dbpath = get_dbpath(manconf);
 	if (dbpath == NULL)
 		errx(EXIT_FAILURE, "_mandb entry not found in man.conf");
-	/* Check if the database exists or not */
+
 	if (!(stat(dbpath, &sb) == 0 && S_ISREG(sb.st_mode))) {
 		/* Database does not exist, check if DB_CREATE was specified, and set
 		 * flag to create the database schema
@@ -322,16 +323,23 @@
 			return NULL;
 		}
 		create_db_flag = 1;
+	} else {
+		/*
+		 * Database exists. Check if we have the permissions to read/write the files
+		 */
+		access_mode = db_flag == MANDB_CREATE || db_flag == MANDB_WRITE? R_OK | W_OK: R_OK;
+		if ((access(dbpath, access_mode)) != 0) {
+			warnx("Unable to access the database, please check permissions for %s", dbpath);
+			return NULL;
+		}
 	}
 
-	/* Now initialize the database connection */
 	sqlite3_initialize();
 	rc = sqlite3_open_v2(dbpath, &db, db_flag, NULL);
 
 	if (rc != SQLITE_OK) {
 		warnx("%s", sqlite3_errmsg(db));
-		sqlite3_shutdown();
-		return NULL;
+		goto error;
 	}
 
 	if (create_db_flag && create_db(db) < 0) {
@@ -379,8 +387,7 @@
 	return db;
 
 error:
-	sqlite3_close(db);
-	sqlite3_shutdown();
+	close_db(db);
 	return NULL;
 }
 
@@ -458,7 +465,7 @@
 }
 
 /*
- *  run_query --
+ *  run_query_internal --
  *  Performs the searches for the keywords entered by the user.
  *  The 2nd param: snippet_args is an array of strings providing values for the
  *  last three parameters to the snippet function of sqlite. (Look at the docs).
@@ -509,15 +516,20 @@
 	 * 2. I am using LIKE operator because '=' or IN operators do not seem to be
 	 * working with the compression option enabled.
 	 */
+	char *sections_str = args->sec_nums;
+	char *temp;
+	if (sections_str) {
+		while (*sections_str) {
+			size_t len = strcspn(sections_str, " ");
+			char *sec = sections_str;
+			if (sections_str[len] == 0) {
+				sections_str += len;
+			} else {
+				sections_str[len] = 0;
+				sections_str += len + 1;
+			}
+			easprintf(&temp, "\'%s\',", sec);
 
-	if (args->sec_nums) {
-		char *temp;
-		int i;
-
-		for (i = 0; i < SECMAX; i++) {
-			if (args->sec_nums[i] == 0)
-				continue;
-			easprintf(&temp, " OR section = \'%d\'", i + 1);
 			if (section_clause) {
 				concat(&section_clause, temp);
 				free(temp);
@@ -529,9 +541,11 @@
 			/*
 			 * At least one section requested, add glue for query.
 			 */
+			size_t section_clause_len = strlen(section_clause);
+			if (section_clause[section_clause_len - 1] == ',')
+				section_clause[section_clause_len - 1] = 0;
 			temp = section_clause;
-			/* Skip " OR " before first term. */
-			easprintf(&section_clause, " AND (%s)", temp + 4);
+			easprintf(&section_clause, " AND section IN (%s)", temp);
 			free(temp);
 		}
 	}
Index: apropos-utils.h
===================================================================
RCS file: /cvsroot/src/usr.sbin/makemandb/apropos-utils.h,v
retrieving revision 1.9
diff -u -r1.9 apropos-utils.h
--- apropos-utils.h	2 Apr 2013 17:16:50 -0000	1.9
+++ apropos-utils.h	12 Apr 2016 15:31:27 -0000
@@ -36,12 +36,14 @@
 #include "sqlite3.h"
 
 #define MANCONF "/etc/man.conf"
-#define SECMAX 9
 
 /* Flags for opening the database */
-#define MANDB_READONLY SQLITE_OPEN_READONLY
-#define MANDB_WRITE SQLITE_OPEN_READWRITE
-#define MANDB_CREATE SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
+typedef enum mandb_access_mode {
+	MANDB_READONLY = SQLITE_OPEN_READONLY,
+	MANDB_WRITE = SQLITE_OPEN_READWRITE,
+	MANDB_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
+} mandb_access_mode;
+
 
 #define APROPOS_SCHEMA_VERSION 20120507
 
@@ -71,7 +73,7 @@
 
 typedef struct query_args {
 	const char *search_str;		// user query
-	int *sec_nums;		// Section in which to do the search
+	char *sec_nums;		// Section in which to do the search
 	int nrec;			// number of records to fetch
 	int offset;		//From which position to start processing the records
 	int legacy;
@@ -92,7 +94,7 @@
 char *lower(char *);
 void concat(char **, const char *);
 void concat2(char **, const char *, size_t);
-sqlite3 *init_db(int, const char *);
+sqlite3 *init_db(mandb_access_mode, const char *);
 void close_db(sqlite3 *);
 char *get_dbpath(const char *);
 int run_query(sqlite3 *, query_format, query_args *);
Index: apropos.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/makemandb/apropos.c,v
retrieving revision 1.18
diff -u -r1.18 apropos.c
--- apropos.c	31 Mar 2016 20:13:37 -0000	1.18
+++ apropos.c	12 Apr 2016 15:31:27 -0000
@@ -43,7 +43,7 @@
 #include "apropos-utils.h"
 
 typedef struct apropos_flags {
-	int sec_nums[SECMAX];
+	char *sec_nums;
 	int nresults;
 	int pager;
 	int no_context;
@@ -58,6 +58,8 @@
 	apropos_flags *aflags;
 } callback_data;
 
+static const unsigned int sections_args_length = 16;
+
 static char *remove_stopwords(const char *);
 static int query_callback(void *, const char * , const char *, const char *,
 	const char *, size_t);
@@ -69,6 +71,7 @@
 parseargs(int argc, char **argv, struct apropos_flags *aflags)
 {
 	int ch;
+	char sec[2] = {0};
 	while ((ch = getopt(argc, argv, "123456789Cchiln:PprS:s:")) != -1) {
 		switch (ch) {
 		case '1':
@@ -80,7 +83,13 @@
 		case '7':
 		case '8':
 		case '9':
-			aflags->sec_nums[ch - '1'] = 1;
+			/* Generate a space separated list of all the requested sections */
+			sec[0] = (char) ch ;
+			if (aflags->sec_nums == NULL) {
+				aflags->sec_nums = emalloc(sections_args_length);
+				memcpy(aflags->sec_nums, sec, 2);
+			} else
+				concat2(&aflags->sec_nums, sec, 1);
 			break;
 		case 'C':
 			aflags->no_context = 1;
@@ -115,10 +124,12 @@
 			aflags->machine = optarg;
 			break;
 		case 's':
-			ch = atoi(optarg);
-			if (ch < 1 || ch > 9)
-				errx(EXIT_FAILURE, "Invalid section");
-			aflags->sec_nums[ch - 1] = 1;
+			if (aflags->sec_nums == NULL) {
+				size_t arglen = strlen(optarg);
+				aflags->sec_nums = arglen > sections_args_length? emalloc(arglen + 1): emalloc(sections_args_length);
+				memcpy(aflags->sec_nums, optarg, arglen + 1);
+			} else
+				concat(&aflags->sec_nums, optarg);
 			break;
 		case '?':
 		default:
@@ -140,6 +151,7 @@
 	cbdata.out = stdout;		// the default output stream
 	cbdata.count = 0;
 	apropos_flags aflags;
+	aflags.sec_nums = NULL;
 	cbdata.aflags = &aflags;
 	sqlite3 *db;
 	setprogname(argv[0]);
@@ -169,12 +181,6 @@
 
 	parseargs(argc, argv, &aflags);
 
-	/*
-	 * If the user specifies a section number as an option, the
-	 * corresponding index element in sec_nums is set to the string
-	 * representing that section number.
-	 */
-
 	argc -= optind;
 	argv += optind;
 
@@ -232,6 +238,7 @@
 		fprintf(cbdata.out, "</table>\n</body>\n</html>\n");
 
 	free(query);
+	free(aflags.sec_nums);
 	close_db(db);
 	if (errmsg) {
 		warnx("%s", errmsg);
Index: makemandb.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/makemandb/makemandb.c,v
retrieving revision 1.33
diff -u -r1.33 makemandb.c
--- makemandb.c	31 Mar 2016 20:17:58 -0000	1.33
+++ makemandb.c	12 Apr 2016 15:31:28 -0000
@@ -71,7 +71,7 @@
 	secbuff exit_status; // EXIT STATUS
 	secbuff diagnostics; // DIAGNOSTICS
 	secbuff errors; // ERRORS
-	char section[2];
+	char *section;
 
 	int xr_found; // To track whether a .Xr was seen when parsing a section
 
@@ -702,7 +702,7 @@
 	for (;;) {
 		r = archive_read_data(a, buf + off, *len - off);
 		if (r == ARCHIVE_OK) {
-			archive_read_close(a);
+			archive_read_finish(a);
 			*bufp = buf;
 			*len = off;
 			return 0;
@@ -718,7 +718,7 @@
 				if (mflags.verbosity)
 					warnx("File too large: %s", file);
 				free(buf);
-				archive_read_close(a);
+				archive_read_finish(a);
 				return -1;
 			}
 			buf = erealloc(buf, *len);
@@ -727,7 +727,7 @@
 
 archive_error:
 	warnx("Error while reading `%s': %s", file, archive_error_string(a));
-	archive_read_close(a);
+	archive_read_finish(a);
 	return -1;
 }
 
@@ -773,7 +773,7 @@
 	rc = sqlite3_prepare_v2(db, sqlstr, -1, &stmt, NULL);
 	if (rc != SQLITE_OK) {
 		if (mflags.verbosity)
-		warnx("%s", sqlite3_errmsg(db));
+			warnx("%s", sqlite3_errmsg(db));
 		close_db(db);
 		errx(EXIT_FAILURE, "Could not query file cache");
 	}
@@ -945,15 +945,15 @@
 	if (md) {
 		const struct mdoc_meta *md_meta = mdoc_meta(md);
 		if (md_meta->msec == NULL) {
-			rec->section[0] = '?';
+			easprintf(&rec->section, "%s", "?");
 		} else
-			rec->section[0] = md_meta->msec[0];
+			rec->section = estrdup(md_meta->msec);
 	} else if (m) {
 		const struct man_meta *m_meta = man_meta(m);
 		if (m_meta->msec == NULL)
-			rec->section[0] = '?';
+			easprintf(&rec->section, "%s", "?");
 		else
-			rec->section[0] = m_meta->msec[0];
+			rec->section = estrdup(m_meta->msec);
 	} else
 		return;
 
@@ -1574,7 +1574,7 @@
 		char *tmp;
 		rec->links = estrdup(rec->name);
 		free(rec->name);
-		int sz = strcspn(rec->links, " \0");
+		size_t sz = strcspn(rec->links, " \0");
 		rec->name = emalloc(sz + 1);
 		memcpy(rec->name, rec->links, sz);
 		if(rec->name[sz - 1] == ',')
@@ -1980,6 +1980,9 @@
 
 	free(rec->md5_hash);
 	rec->md5_hash = NULL;
+
+	free(rec->section);
+	rec->section = NULL;
 }
 
 /*



Home | Main Index | Thread Index | Old Index