#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
struct stub {
const char *name;
int (*f)(int, char **, char **);
};
static const struct stub entry_points[];
static int crunched_main(int argc, char **, char **);
static int cmpstringp(const void *, const void *);
static void crunched_usage(void) __dead2;
int
main(int argc, char **argv, char **envp)
{
const char *slash, *basename;
const struct stub *ep;
if (argv[0] == NULL || *argv[0] == '\0')
crunched_usage();
slash = strrchr(argv[0], '/');
basename = slash ? slash+1 : argv[0];
for (ep = entry_points; ep->name != NULL; ep++)
if (strcmp(basename, ep->name) == 0)
return ep->f(argc, argv, envp);
fprintf(stderr, "%s: %s not compiled in\n", EXECNAME, basename);
crunched_usage();
}
static int
crunched_main(int argc, char **argv, char **envp)
{
if (argc <= 1)
crunched_usage();
return main(--argc, ++argv, envp);
}
static int
cmpstringp(const void *p1, const void *p2)
{
const char *s1 = *(char * const *)p1;
const char *s2 = *(char * const *)p2;
return strcmp(s1, s2);
}
__dead2
static void
crunched_usage(void)
{
int nprog = 0, columns = 0;
int i, len;
const struct stub *ep;
const char **prognames;
for (ep = entry_points; ep->name != NULL; ep++)
nprog++;
if ((prognames = malloc(nprog * sizeof(char *))) == NULL)
err(EXIT_FAILURE, "malloc");
for (i = 0; i < nprog; i++)
prognames[i] = entry_points[i].name;
qsort(prognames, nprog, sizeof(char *), cmpstringp);
fprintf(stderr,
"usage: %s <prog> <args> ..., where <prog> is one of:\n",
EXECNAME);
for (i = 0; i < nprog; i++) {
if (strcmp(EXECNAME, prognames[i]) == 0)
continue;
len = strlen(prognames[i]) + 1;
if (columns+len < 80)
columns += len;
else {
fprintf(stderr, "\n");
columns = len;
}
fprintf(stderr, " %s", prognames[i]);
}
fprintf(stderr, "\n");
free(prognames);
exit(1);
}