Subject: bin/31053: Enhancement: getconf -a to list all applicable variables
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <rillig@NetBSD.org>
List: netbsd-bugs
Date: 08/24/2005 07:22:00
	Note: There was a bad value `' for the field `Confidential'.
	It was set to the default value of `yes'.

>Number:         31053
>Category:       bin
>Synopsis:       Enhancement: getconf -a to list all applicable variables
>Confidential:   yes
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed Aug 24 07:22:00 +0000 2005
>Originator:     Roland Illig
>Release:        NetBSD 3.99.7
>Organization:
	
>Environment:
	
	
System: NetBSD baccf5ee.roland-illig.de 3.99.7 NetBSD 3.99.7 (GENERIC) #1: Mon Jul 18 06:33:01 CEST 2005 build@baccf5ee.roland-illig.de:/home/build/build-2005-07-17/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:

I have extended getconf(1) to accept the -a flag instead of a variable
name. An example output is:

./getconf -a .
LINK_MAX = 32767
NAME_MAX = 255
PATH_MAX = 1024
PIPE_BUF = 512
_POSIX_CHOWN_RESTRICTED = 1
_POSIX_NO_TRUNC = 1
_POSIX_SYNC_IO = 1
FILESIZEBITS = 42

	
>How-To-Repeat:
	
>Fix:
	

Index: Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/getconf/Makefile,v
retrieving revision 1.4
diff -u -p -r1.4 Makefile
--- Makefile	9 Jan 1997 20:19:43 -0000	1.4
+++ Makefile	24 Aug 2005 06:44:33 -0000
@@ -1,5 +1,6 @@
 # 	$NetBSD: Makefile,v 1.4 1997/01/09 20:19:43 tls Exp $
 
-PROG=getconf
+PROG=	getconf
+WARNS=	4
 
 .include <bsd.prog.mk>
Index: getconf.1
===================================================================
RCS file: /cvsroot/src/usr.bin/getconf/getconf.1,v
retrieving revision 1.9
diff -u -p -r1.9 getconf.1
--- getconf.1	10 Nov 2004 13:43:39 -0000	1.9
+++ getconf.1	24 Aug 2005 06:44:33 -0000
@@ -34,7 +34,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 10, 2004
+.Dd August 24, 2005
 .Dt GETCONF 1
 .Os
 .Sh NAME
@@ -44,8 +44,13 @@
 .Nm
 .Ar system_var
 .Nm
+.Fl a
+.Nm
 .Ar path_var
 .Ar pathname
+.Nm
+.Fl a
+.Ar pathname
 .Sh DESCRIPTION
 The
 .Nm
@@ -71,6 +76,17 @@ The names of the pathname variables are 
 with the leading
 .Dq Li _PC_
 removed.
+.Pp
+When invoked with the option
+.Fl a ,
+.Nm
+writes a list of all applicable variables and their values to the
+standard output, in the format
+.Do
+.Va name
+=
+.Va value
+.Dc .
 .Sh EXIT STATUS
 The
 .Nm
Index: getconf.c
===================================================================
RCS file: /cvsroot/src/usr.bin/getconf/getconf.c,v
retrieving revision 1.22
diff -u -p -r1.22 getconf.c
--- getconf.c	10 Nov 2004 04:02:52 -0000	1.22
+++ getconf.c	24 Aug 2005 06:44:33 -0000
@@ -50,9 +50,6 @@ __RCSID("$NetBSD: getconf.c,v 1.22 2004/
 #include <unistd.h>
 #include <string.h>
 
-int	main __P((int, char **));
-static void usage __P((void));
-
 struct conf_variable
 {
   const char *name;
@@ -60,7 +57,12 @@ struct conf_variable
   long value;
 };
 
-const struct conf_variable conf_table[] =
+static void print_longvar(const char *, long);
+static void print_strvar(const char *, const char *);
+static void printvar(const struct conf_variable *, const char *);
+static void usage(void);
+
+static const struct conf_variable conf_table[] =
 {
   { "PATH",			CONFSTR,	_CS_PATH		},
 
@@ -170,57 +172,101 @@ const struct conf_variable conf_table[] 
   { "GETGR_R_SIZE_MAX",		SYSCONF,	_SC_GETGR_R_SIZE_MAX	},
   { "GETPW_R_SIZE_MAX",		SYSCONF,	_SC_GETPW_R_SIZE_MAX	},
 
-  { NULL }
+  { NULL, CONSTANT, 0L }
 };
 
+static int a_flag = 0;		/* list all variables */
 
 int
-main(argc, argv)
-	int argc;
-	char **argv;
+main(int argc, char **argv)
 {
 	int ch;
 	const struct conf_variable *cp;
-
-	long val;
-	size_t slen;
-	char * sval;
+	const char *varname, *pathname;
+	int found;
 
 	setlocale(LC_ALL, "");
 
-	while ((ch = getopt(argc, argv, "")) != -1) {
+	while ((ch = getopt(argc, argv, "a")) != -1) {
 		switch (ch) {
+		case 'a':
+			a_flag = 1;
+			break;
+
 		case '?':
 		default:
 			usage();
+			/* NOTREACHED */
 		}
 	}
 	argc -= optind;
 	argv += optind;
 
-	if (argc < 1 || argc > 2) {
+	varname = NULL;		/* XXX: gcc -Wuninitialized */
+	if (!a_flag && argc == 0) {
 		usage();
 		/* NOTREACHED */
 	}
+	if (!a_flag) {
+		varname = argv[0];
+		argc--, argv++;
+	}
+	if (argc != 0 && argc != 1) {
+		usage();
+		/* NOTREACHED */
+	}
+	pathname = argv[0];	/* may be NULL */
 
+	found = 0;
 	for (cp = conf_table; cp->name != NULL; cp++) {
-		if (strcmp(*argv, cp->name) == 0)
-			break;
+		if (a_flag || strcmp(varname, cp->name) == 0) {
+			if ((cp->type == PATHCONF) == (pathname != NULL)) {
+				printvar (cp, pathname);
+				found = 1;
+			} else if (!a_flag) {
+				errx(1, "%s: invalid variable type", cp->name);
+				/* NOTREACHED */
+			}
+		}
 	}
-	if (cp->name == NULL) {
-		errx(1, "%s: unknown variable", *argv);
+
+	if (!a_flag && !found) {
+		errx(1, "%s: unknown variable", varname);
 		/* NOTREACHED */
 	}
 
-	if (cp->type == PATHCONF) {
-		if (argc != 2) usage();
-	} else {
-		if (argc != 1) usage();
-	}
+	(void)fflush(stdout);
+	return ferror(stdout) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+static void
+print_longvar(const char *name, long value)
+{
+	if (a_flag)
+		printf("%s = %ld\n", name, value);
+	else
+		printf("%ld\n", value);
+}
+
+static void
+print_strvar(const char *name, const char *sval)
+{
+	if (a_flag)
+		printf("%s = %s\n", name, sval);
+	else
+		printf("%s\n", sval);
+}
+
+static void
+printvar(const struct conf_variable *cp, const char *pathname)
+{
+	size_t slen;
+	char * sval;
+	long val;
 
 	switch (cp->type) {
 	case CONSTANT:
-		printf("%ld\n", cp->value);
+		print_longvar(cp->name, cp->value);
 		break;
 
 	case CONFSTR:
@@ -230,7 +276,7 @@ main(argc, argv)
 			err(1, "malloc");
 
 		confstr(cp->value, sval, slen);
-		printf("%s\n", sval);
+		print_strvar(cp->name, sval);
 		break;
 
 	case SYSCONF:
@@ -241,35 +287,38 @@ main(argc, argv)
 				/* NOTREACHED */
 			}
 
-			printf ("undefined\n");
+			print_strvar(cp->name, "undefined");
 		} else {
-			printf("%ld\n", val);
+			print_longvar(cp->name, val);
 		}
 		break;
 
 	case PATHCONF:
 		errno = 0;
-		if ((val = pathconf(argv[1], cp->value)) == -1) {
+		if ((val = pathconf(pathname, cp->value)) == -1) {
 			if (errno != 0) {
-				err(1, "%s", argv[1]);
+				if (a_flag && errno == EINVAL) {
+					/* Just skip invalid variables */
+					return;
+				}
+				err(1, "%s", pathname);
 				/* NOTREACHED */
 			}
 
-			printf ("undefined\n");
+			print_strvar(cp->name, "undefined");
 		} else {
-			printf ("%ld\n", val);
+			print_longvar(cp->name, val);
 		}
 		break;
 	}
-
-	exit (ferror(stdout));
 }
 
-
 static void
-usage()
+usage(void)
 {
-  fprintf (stderr, "usage: getconf system_var\n");
-  fprintf (stderr, "       getconf path_var pathname\n");
-  exit(1);
+	fprintf(stderr, "usage: getconf system_var\n");
+	fprintf(stderr, "       getconf -a\n");
+	fprintf(stderr, "       getconf path_var pathname\n");
+	fprintf(stderr, "       getconf -a pathname\n");
+	exit(EXIT_FAILURE);
 }

>Unformatted: