[Pinfo-devel] r19 - pinfo/trunk/src

Bas Zoetekouw bas at costa.debian.org
Sun Jul 24 23:04:10 UTC 2005


Author: bas
Date: 2005-07-24 23:04:09 +0000 (Sun, 24 Jul 2005)
New Revision: 19

Modified:
   pinfo/trunk/src/datatypes.c
   pinfo/trunk/src/filehandling_functions.c
   pinfo/trunk/src/filehandling_functions.h
Log:
Fixed the path search for info dirs:
 - use correct default info dirs as defined by FHS in datatypes.c
 - rewrote initpaths() in filehandling_functions.c;  
   - added better support for languages (a locale of en_GB.UTF8 now causes
	 pinfo to also search for .../info/en_GB and .../info/en dirs) 
   - added a check to make sure we don't use anu duplicate paths (caused by
	 symlinks or so) (fixes Debian bug #181907)


Modified: pinfo/trunk/src/datatypes.c
===================================================================
--- pinfo/trunk/src/datatypes.c	2005-07-23 20:08:22 UTC (rev 18)
+++ pinfo/trunk/src/datatypes.c	2005-07-24 23:04:09 UTC (rev 19)
@@ -11,7 +11,7 @@
 char *maileditor = "mail";
 char *printutility = "lpr";
 char *manlinks = "1:8:2:3:4:5:6:7:9:n:l:p:o:3X11:3Xt:3X:3x";
-char *configuredinfopath = "/usr/info:/usr/share/info:/usr/local/info";
+char *configuredinfopath = "/usr/share/info:/usr/local/share/info:/opt/info";
 char *ignoredmacros = 0;
 char *rcfile = NULL;
 

Modified: pinfo/trunk/src/filehandling_functions.c
===================================================================
--- pinfo/trunk/src/filehandling_functions.c	2005-07-23 20:08:22 UTC (rev 18)
+++ pinfo/trunk/src/filehandling_functions.c	2005-07-24 23:04:09 UTC (rev 19)
@@ -802,101 +802,200 @@
 	return 0;			/* path not found in previous links */
 }
 
-	void
+/* returns the number of chars ch in string str */
+unsigned int
+charcount(const char *str, const char ch)
+{
+	int num = 0;
+	const char *c;
+
+	c = str;
+	
+	while (*c != '\0')
+	{
+		if (*c++ == ch)
+			num++;
+	}
+	return num;
+}
+
+/* 
+ * find the paths where info files are to be found, 
+ * and put them in the global var infopaths[]
+ */
+void
 initpaths()
 {
-	char curdir[1024];
-	int i, infolen, wsklen;
-	int localdir = 0, globaldir = 0;	/* flags, which say if the /usr/local/info *
-										 * and /usr/info were defined in $INFOPATH */
-	int sharedir = 0;		/* the same for /usr/share/info */
-	char *lang = getenv("LANG");
-	char *infopath;
-	char *wsk;
-	char **tmpinfopaths;		/*for use for sorting */
+	char emptystr[1] = "";
+	char **paths = NULL;
+	char *infopath = NULL, *langpath = NULL;
+	char *c, *dir, *env;
+	char *lang, *langshort = NULL;
+	int ret;
+	unsigned int i, j, maxpaths, numpaths = 0, infolen, langlen;
+	size_t len;
+	struct stat sbuf;
+	ino_t *inodes;
 
-	getcwd(curdir, 1024);
+	/* first concat the paths */
+	env = getenv("INFOPATH");
+	if (env == NULL)
+	{
+		env = emptystr;
+	}
+	infolen = strlen(env) + strlen(configuredinfopath) + 2;
+	infopath = (char *) xmalloc( infolen );
+	strcat(infopath, env);
+	strcat(infopath, ":");
+	strcat(infopath, configuredinfopath);
 
-	infopaths = xmalloc(5 * sizeof(char *));
+	/* alloc the paths[] array */
+	maxpaths = 3 * (charcount( infopath, ':' ) + 1); // *3 for $LANG
+	paths = (char **) xmalloc( maxpaths * sizeof(char *) );
 
-	infopathcount = 0;
-
-	if (getenv("INFOPATH") != NULL)	/* check paths in $INFOPATH variable */
+	/* split at ':' and put the path components into paths[] */
+	c = infopath;
+	while (dir = strsep(&c, ":"))
 	{
-		infopath = xmalloc(strlen(getenv("INFOPATH")) + strlen(configuredinfopath) + 100);
-		/*
-		 * +5(well, +100) of overrun buffer, since the following while loop
-		 *  can be coded simplier this way
-		 */
-		wsk = infopath;
-		strcpy(infopath, getenv("INFOPATH"));	/* copy the environmental path string */
-		strcat(infopath, ":");
-		strcat(infopath, configuredinfopath);	/* concatenate the paths from config file to the path string */
+		/* if this actually is a non-empty string, add it to paths[] */
+		if ( dir && strlen(dir)>0 ) 
+		{
+			paths[numpaths++] = dir;
+		}
 	}
-	else
+
+	/* get the current $LANG, if any (to use for localized info pages) */
+	lang = strdup(getenv("LANG"));
+	/* fix the lang string */
+	for (i=0; lang[i]!='\0'; i++)
 	{
-		infopath = xmalloc(strlen(configuredinfopath) + 100);
-		wsk = infopath;
-		strcpy(infopath, configuredinfopath);
+		/* cut off the charset */
+		if (lang[i]=='.') 
+		{
+			lang[i]='\0';
+		}
+		/* if lang is sublocalized (nl_BE or so), also use short version */
+		if (lang[i]=='_')
+		{
+			langshort = strdup(lang);
+			langshort[i] = '\0';
+		}
 	}
-	infolen = strlen(infopath);
-	for (i = 0; i < infolen; i++)
-		if (infopath[i] == ':')
-			infopath[i] = 0;
-	while (wsk < infopath + infolen)
+	/* if we have a LANG defined, add paths with this lang to the paths[] */
+	if (lang && strlen(lang)>0 )
 	{
-		infopaths = xrealloc(infopaths,(infopathcount + 2) * sizeof(char *));
-		wsklen = strlen(wsk);
-		if (!isininfopath(wsk))
+		/* crude upper limit */
+		langlen = infolen + (strlen(lang)+2) * numpaths + 1;
+		if (langshort!=NULL) langlen *= 2;
+		langpath = (char *) xmalloc( langlen * sizeof(char) );
+
+		c = langpath; 
+		for (i=0; i<numpaths; i++)
 		{
-			if (wsklen)
+			/* TODO: check for negative return values of sprintf */
+			len = sprintf(c, "%s/%s", paths[i], lang);
+			/* add the lang specific dir at the beginning */
+			paths[numpaths+i] = paths[i];
+			paths[i] = c;
+
+			c += len+1;
+			
+			if (langshort) 
 			{
-				if (wsk[wsklen - 1] == '/')
-					wsk[wsklen - 1] = 0;
+				/* TODO: check for negative return values of sprintf */
+				len = sprintf(c, "%s/%s", paths[numpaths+i], langshort);
+				/* add the lang specific dir at the beginning */
+				paths[2*numpaths+i] = paths[numpaths+i];
+				paths[numpaths+i] = c;
+
+				c += len+1;
 			}
-			if (lang)
-			{
-				infopaths[infopathcount] = xmalloc(wsklen + strlen(lang) + 2);
-				sprintf(infopaths[infopathcount], "%s/%s", wsk, lang);	/* with $lang */
-				infopathcount++;
-				infopaths[infopathcount] = xmalloc(wsklen + 1);
-				strcpy(infopaths[infopathcount], wsk);	/* without $lang */
-				infopathcount++;
-				infopaths = xrealloc(infopaths, sizeof(char *) *(infopathcount + 5));
-			}
-			else
-			{
-				infopaths[infopathcount] = xmalloc(wsklen + 1);
-				strcpy(infopaths[infopathcount], wsk);
-				infopathcount++;
-				infopaths = xrealloc(infopaths, sizeof(char *) *(infopathcount + 5));
-			}
+
 		}
-		wsk += wsklen + 1;	/*this will go to infopath[infolen+1]
-							  at the last token!!! */
+		numpaths *= (langshort?3:2);
 	}
-	xfree(infopath);
-	infopath = 0;
 
-	/* now we should sort our paths so that the national directories come first
-	   before handling, they are interlaced:
-	   .../info1/LANG|.../info1.../info2/LANG|.../info2|... */
+#ifdef ___DEBUG___
+	/* for debugging */
+	for (i=0; i<numpaths; i++)
+		fprintf(stderr,"--> %s\n", paths[i]);
+#endif
 
-	if (lang)
+	/* ok, now we have all the (possibly) revelevant paths in paths[] */
+	/* now loop over them, see if they are valid and if they are duplicates*/
+	inodes = (ino_t *) xmalloc( maxpaths * sizeof(ino_t *) );
+	numpaths = 0;
+	len = 0;
+	for (i=0; i< maxpaths; i++)
 	{
-		tmpinfopaths = xmalloc(infopathcount * sizeof(char *));
-		for (i = 1; i < infopathcount; i += 2)
-			tmpinfopaths[(int)(i / 2) + infopathcount / 2] = infopaths[i];
-		for (i = 0; i < infopathcount; i += 2)
-			tmpinfopaths[(int)(i / 2)] = infopaths[i];
-		xfree(infopaths);
-		infopaths = tmpinfopaths;
+		/* stat() the dir */
+		ret = stat( paths[i], &sbuf);
+		/* and see if it could be opened */
+		if (ret < 0)
+		{
+#ifdef ___DEBUG___
+			fprintf(stderr, "error while opening `%s': %s\n", 
+					paths[i], strerror(errno) );
+#endif 
+			paths[i] = NULL;
+			inodes[i] = 0;
+		}
+		else
+		{
+			inodes[i] = sbuf.st_ino;
+		}
+
+		/* now check if this path is a duplicate */
+		for (j=0; j<i; j++)
+		{
+			if (inodes[j]==inodes[i]) paths[i] = NULL;
+		}
+
+		/* calculate the total number of vali paths and the size of teh strings */
+		if (paths[i]!=NULL) 
+		{
+			numpaths++;
+			len += strlen(paths[i]) + 1;
+		}
 	}
 
-	/*  infopaths[infopathcount] = xmalloc(5); */
-	/*  strcpy(infopaths[infopathcount], "."); */	/* for ./ */
-	/*  infopathcount++; */
+
+	/* and alloc and copy to global var */
+	infopathcount = numpaths;
+	infopaths = (char **) xmalloc( numpaths * sizeof(char *) );
+	c = (char *) xmalloc( len * sizeof(char) );
+	j=0;
+	for (i=0; i<maxpaths; i++)
+	{
+		if (paths[i]!=NULL)
+		{
+			/* copy path to c buffer */
+			strcpy(c, paths[i]);	
+			infopaths[j++] = c;
+			c += strlen(paths[i]) + 1;
+		}
+	}
+	
+
+	xfree(infopath);
+	xfree(langpath);
+	xfree(paths);
+	xfree(lang);
+	xfree(langshort);
+	xfree(inodes);
+
+#ifdef ___DEBUG___
+	/* for debugging */
+	fprintf(stderr, "%i valid info paths found:\n", infopathcount);
+	for (i=0; i<infopathcount; i++)
+		if (infopaths[i]) fprintf(stderr,"--> %s\n", infopaths[i]);
+#endif
+
+
 }
+
+
+
 	void
 create_indirect_tag_table()
 {

Modified: pinfo/trunk/src/filehandling_functions.h
===================================================================
--- pinfo/trunk/src/filehandling_functions.h	2005-07-23 20:08:22 UTC (rev 18)
+++ pinfo/trunk/src/filehandling_functions.h	2005-07-24 23:04:09 UTC (rev 19)
@@ -2,7 +2,12 @@
 #define __FILEHANDLING_FUNCTIONS_H
 
 #include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
 
+
 #define INFO_TAG 0x1f
 #define INDIRECT_TAG 0x7f
 




More information about the Pinfo-devel mailing list