1 /*
2  * Copyright (c) 1994 University of Maryland
3  * All Rights Reserved.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of U.M. not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  U.M. makes no representations about the
12  * suitability of this software for any purpose.  It is provided "as is"
13  * without express or implied warranty.
14  *
15  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
17  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Author: James da Silva, Systems Design and Analysis Group
23  *			   Computer Science Department
24  *			   University of Maryland at College Park
25  */
26 /*
27  * crunched_main.c - main program for crunched binaries, it branches to a
28  * 	particular subprogram based on the value of argv[0].  Also included
29  *	is a little program invoked when the crunched binary is called via
30  *	its EXECNAME.  This one prints out the list of compiled-in binaries,
31  *	or calls one of them based on argv[1].   This allows the testing of
32  *	the crunched binary without creating all the links.
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <err.h>
39 
40 struct stub {
41 	const char *name;
42 	int (*f)(int, char **, char **);
43 };
44 
45 static const struct stub entry_points[];
46 
47 static int crunched_main(int argc, char **, char **);
48 static int cmpstringp(const void *, const void *);
49 static void crunched_usage(void) __dead2;
50 
51 
52 int
53 main(int argc, char **argv, char **envp)
54 {
55 	const char *slash, *basename;
56 	const struct stub *ep;
57 
58 	if (argv[0] == NULL || *argv[0] == '\0')
59 		crunched_usage();
60 
61 	slash = strrchr(argv[0], '/');
62 	basename = slash ? slash+1 : argv[0];
63 
64 	for (ep = entry_points; ep->name != NULL; ep++)
65 		if (strcmp(basename, ep->name) == 0)
66 			return ep->f(argc, argv, envp);
67 
68 	fprintf(stderr, "%s: %s not compiled in\n", EXECNAME, basename);
69 	crunched_usage();
70 }
71 
72 
73 static int
74 crunched_main(int argc, char **argv, char **envp)
75 {
76 	if (argc <= 1)
77 		crunched_usage();
78 
79 	return main(--argc, ++argv, envp);
80 }
81 
82 
83 static int
84 cmpstringp(const void *p1, const void *p2)
85 {
86 	const char *s1 = *(const char **)p1;
87 	const char *s2 = *(const char **)p2;
88 	return strcmp(s1, s2);
89 }
90 
91 
92 static void
93 crunched_usage()
94 {
95 	int nprog = 0, columns = 0;
96 	int i, len;
97 	const struct stub *ep;
98 	const char **prognames;
99 
100 	for (ep = entry_points; ep->name != NULL; ep++)
101 		nprog++;
102 	if ((prognames = malloc(nprog * sizeof(char *))) == NULL)
103 		err(EXIT_FAILURE, "malloc");
104 	for (i = 0; i < nprog; i++)
105 		prognames[i] = entry_points[i].name;
106 	qsort(prognames, nprog, sizeof(char *), cmpstringp);
107 
108 	fprintf(stderr,
109 		"usage: %s <prog> <args> ..., where <prog> is one of:\n",
110 		EXECNAME);
111 	for (i = 0; i < nprog; i++) {
112 		if (strcmp(EXECNAME, prognames[i]) == 0)
113 			continue;
114 		len = strlen(prognames[i]) + 1;
115 		if (columns+len < 80)
116 			columns += len;
117 		else {
118 			fprintf(stderr, "\n");
119 			columns = len;
120 		}
121 		fprintf(stderr, " %s", prognames[i]);
122 	}
123 	fprintf(stderr, "\n");
124 	free(prognames);
125 	exit(1);
126 }
127 
128 /* end of crunched_main.c */
129