git: f122045e36dd - main - crunchgen: add --list option

From: Warner Losh <imp_at_FreeBSD.org>
Date: Wed, 17 Apr 2024 18:07:07 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=f122045e36dd009ecdc6b69a6f4b751c4b10b443

commit f122045e36dd009ecdc6b69a6f4b751c4b10b443
Author:     Martin Tournoij <martin@arp242.net>
AuthorDate: 2024-04-17 16:04:27 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-04-17 18:07:25 +0000

    crunchgen: add --list option
    
    "bsdbox --list" will print all tools in the binary, one per line. The
    main use case for this is to make it easier to create links:
    
            for t in $(bsdbox --list); do
                    ln -s bsdbox $t
            done
    
    The name --list was taken from busybox.
    
    This just adds a new "program" with the name "--list". I don't think we
    need to do real argument parsing here, and this is also how busybox does
    it.
    
    An additional minor change is that just "bsdbox" will no longer print
    the binary name itself ("bsdbox" in this case). Before it would do:
    
            % bsdbox
            usage: boxlike <prog> <args> ..., where <prog> is one of:
             cp ls mv bsdbox
    
    And now just:
    
            % bsdbox
            usage: boxlike <prog> <args> ..., where <prog> is one of:
             cp ls mv
    
    And just "bsdbox" will also exit with code 0 (and print to stdout)
    rather than exit with 0 and print to stderr
    
    Example output:
    
            % ./bsdbox
            usage: bsdbox program [args ...]
                   bsdbox --list
                   program [args ...]
    
            bsdbox combines several programs in one executable. Create a link to this
            executable with the program name to run that program, or give the program
            name as the first argument.
    
            Currently defined programs:
             true false tail head uname
    
            % ./bsdbox --list
            true
            false
            tail
            head
            uname
    
            % ./bsdbox uname -a
            FreeBSD freebsd 13.2-RELEASE-p4 FreeBSD 13.2-RELEASE-p4 GENERIC amd64
    
            % ln -s bsdbox uname
            % ./uname -a
            FreeBSD freebsd 13.2-RELEASE-p4 FreeBSD 13.2-RELEASE-p4 GENERIC amd64
    
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/894
    Signed-off-by: Martin Tournoij <martin@arp242.net>
    Reviewed by: imp
    Pull Request: https://github.com/freebsd/freebsd-src/pull/894
---
 usr.sbin/crunch/crunchgen/crunched_main.c | 60 +++++++++++++++++++++----------
 usr.sbin/crunch/crunchgen/crunchgen.c     | 10 ++++--
 2 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/usr.sbin/crunch/crunchgen/crunched_main.c b/usr.sbin/crunch/crunchgen/crunched_main.c
index 7de99b270ac7..a7f072378197 100644
--- a/usr.sbin/crunch/crunchgen/crunched_main.c
+++ b/usr.sbin/crunch/crunchgen/crunched_main.c
@@ -82,20 +82,21 @@ struct stub {
 
 extern const char *__progname;
 extern struct stub entry_points[];
+extern int num_entry_points;
 
-static void crunched_usage(void);
+static void crunched_usage(int);
 
 crunched_stub_t crunched_main;
+crunched_stub_t crunched_list;
 
 static struct stub *
 find_entry_point(const char *basename)
 {
-	struct stub *ep = NULL;
-
-	for (ep = entry_points; ep->name != NULL; ep++)
+	for (int i = 0; i < num_entry_points; i++) {
+		struct stub *ep = &entry_points[i];
 		if (!strcmp(basename, ep->name))
 			return (ep);
-
+	}
 	return (NULL);
 }
 
@@ -159,13 +160,14 @@ main(int argc, char **argv, char **envp)
 	}
 
 	if (basename == NULL || *basename == '\0')
-		crunched_usage();
+		crunched_usage(1);
 
 	if (ep != NULL) {
 		return ep->f(argc, argv, envp);
 	} else {
-		fprintf(stderr, "%s: %s not compiled in\n", EXECNAME, basename);
-		crunched_usage();
+		fprintf(stderr, "%s: %s not compiled in\n\n",
+		    EXECNAME, basename);
+		crunched_usage(1);
 	}
 }
 
@@ -173,33 +175,53 @@ int
 crunched_main(int argc, char **argv, char **envp)
 {
 	if (argc <= 1)
-		crunched_usage();
+		crunched_usage(0);
 
 	__progname = get_basename(argv[1]);
 	return main(--argc, ++argv, envp);
 }
 
+int
+crunched_list(int argc __unused, char **argv __unused, char **envp __unused)
+{
+	for (int i = 0; i < num_entry_points - 2; i++)
+		printf("%s\n", entry_points[i].name);
+	return (0);
+}
+
 static void
-crunched_usage(void)
+crunched_usage(int code)
 {
 	int columns, len;
-	struct stub *ep;
-
-	fprintf(stderr,
-	    "usage: %s <prog> <args> ..., where <prog> is one of:\n", EXECNAME);
+	FILE *out = stdout;
+	if (code > 0)
+		out = stderr;
+
+	fprintf(out,
+	    "usage: %s program [args ...]\n"
+	    "       %s --list\n"
+	    "       program [args ...]\n"
+	    "\n"
+	    "%s combines several programs in one executable. Create a link to this\n"
+	    "executable with the program name to run that program, or give the program\n"
+	    "name as the first argument.\n"
+	    "\n"
+	    "Currently defined programs:\n",
+	    EXECNAME, EXECNAME, EXECNAME);
 	columns = 0;
-	for (ep = entry_points; ep->name != NULL; ep++) {
+	for (int i = 0; i < num_entry_points - 2; i++) {
+		struct stub *ep = &entry_points[i];
 		len = strlen(ep->name) + 1;
 		if (columns + len < 80)
 			columns += len;
 		else {
-			fprintf(stderr, "\n");
+			fprintf(out, "\n");
 			columns = len;
 		}
-		fprintf(stderr, " %s", ep->name);
+		fprintf(out, " %s", ep->name);
 	}
-	fprintf(stderr, "\n");
-	exit(1);
+	fprintf(out, "\n");
+	exit(code);
 }
 
 /* end of crunched_main.c */
diff --git a/usr.sbin/crunch/crunchgen/crunchgen.c b/usr.sbin/crunch/crunchgen/crunchgen.c
index 462a13f9c897..065619936aa0 100644
--- a/usr.sbin/crunch/crunchgen/crunchgen.c
+++ b/usr.sbin/crunch/crunchgen/crunchgen.c
@@ -924,17 +924,23 @@ gen_output_cfile(void)
 		    "extern crunched_stub_t _crunched_%s_stub;\n",
 		    p->ident);
 
+	int n = 2; /* 2 because main and --list are added manually. */
 	fprintf(outcf, "\nstruct stub entry_points[] = {\n");
 	for (p = progs; p != NULL; p = p->next) {
+		n++;
 		fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
 		    p->name, p->ident);
-		for (s = p->links; s != NULL; s = s->next)
+		for (s = p->links; s != NULL; s = s->next) {
+			n++;
 			fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
 			    s->str, p->ident);
+		}
 	}
 
 	fprintf(outcf, "\t{ EXECNAME, crunched_main },\n");
-	fprintf(outcf, "\t{ NULL, NULL }\n};\n");
+	fprintf(outcf, "\t{ \"--list\", crunched_list }\n");
+	fprintf(outcf, "};\n\n");
+	fprintf(outcf, "int num_entry_points = %d;\n", n);
 	fclose(outcf);
 }