Path: blob/main/usr.sbin/crunch/crunchgen/crunched_main.c
107769 views
/*1* Copyright (c) 1994 University of Maryland2* All Rights Reserved.3*4* Permission to use, copy, modify, distribute, and sell this software and its5* documentation for any purpose is hereby granted without fee, provided that6* the above copyright notice appear in all copies and that both that7* copyright notice and this permission notice appear in supporting8* documentation, and that the name of U.M. not be used in advertising or9* publicity pertaining to distribution of the software without specific,10* written prior permission. U.M. makes no representations about the11* suitability of this software for any purpose. It is provided "as is"12* without express or implied warranty.13*14* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.16* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES17* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION18* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN19* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.20*21* Author: James da Silva, Systems Design and Analysis Group22* Computer Science Department23* University of Maryland at College Park24*/25/*-26* SPDX-License-Identifier: BSD-2-Clause27*28* Copyright 2020 Alex Richardson <[email protected]>29*30* This software was developed by SRI International and the University of31* Cambridge Computer Laboratory (Department of Computer Science and32* Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the33* DARPA SSITH research programme.34*35* Redistribution and use in source and binary forms, with or without36* modification, are permitted provided that the following conditions37* are met:38* 1. Redistributions of source code must retain the above copyright39* notice, this list of conditions and the following disclaimer.40* 2. Redistributions in binary form must reproduce the above copyright41* notice, this list of conditions and the following disclaimer in the42* documentation and/or other materials provided with the distribution.43*44* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND45* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE46* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE47* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE48* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL49* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS50* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)51* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT52* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY53* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF54* SUCH DAMAGE.55*56*/57/*58* crunched_main.c - main program for crunched binaries, it branches to a59* particular subprogram based on the value of argv[0]. Also included60* is a little program invoked when the crunched binary is called via61* its EXECNAME. This one prints out the list of compiled-in binaries,62* or calls one of them based on argv[1]. This allows the testing of63* the crunched binary without creating all the links.64*/6566#include <sys/param.h>67#include <sys/auxv.h>68#include <sys/sysctl.h>6970#include <err.h>71#include <stdio.h>72#include <stdlib.h>73#include <string.h>7475typedef int crunched_stub_t(int, char **, char **);7677struct stub {78const char *name;79crunched_stub_t *f;80};8182extern const char *__progname;83extern struct stub entry_points[];84extern int num_entry_points;8586static void crunched_usage(int);8788crunched_stub_t crunched_main;89crunched_stub_t crunched_list;9091static struct stub *92find_entry_point(const char *basename)93{94for (int i = 0; i < num_entry_points; i++) {95struct stub *ep = &entry_points[i];96if (!strcmp(basename, ep->name))97return (ep);98}99return (NULL);100}101102static const char *103get_basename(const char *exe_path)104{105const char *slash = strrchr(exe_path, '/');106return (slash ? slash + 1 : exe_path);107}108109int110main(int argc, char **argv, char **envp)111{112struct stub *ep = NULL;113const char *basename = NULL;114char buf[MAXPATHLEN];115116/*117* Look at __progname first (this will be set if the crunched binary is118* invoked directly).119*/120if (__progname) {121basename = get_basename(__progname);122ep = find_entry_point(basename);123}124125/*126* Otherwise try to find entry point based on argv[0] (this works for127* both symlinks as well as hardlinks). However, it does not work when128* su invokes a crunched shell because it sets argv[0] to _su when129* invoking the shell. In that case we look at AT_EXECPATH as a130* fallback.131*/132if (ep == NULL) {133basename = get_basename(argv[0]);134ep = find_entry_point(basename);135}136137/*138* If we didn't find the entry point based on __progname or argv[0],139* try AT_EXECPATH to get the actual binary that was executed.140*/141if (ep == NULL) {142int error = elf_aux_info(AT_EXECPATH, &buf, sizeof(buf));143144if (error == 0) {145const char *exe_name = get_basename(buf);146/*147* Keep using argv[0] if AT_EXECPATH is the crunched148* binary so that symlinks to the crunched binary report149* "not compiled in" instead of invoking150* crunched_main().151*/152if (strcmp(exe_name, EXECNAME) != 0) {153basename = exe_name;154ep = find_entry_point(basename);155}156} else {157warnc(error, "elf_aux_info(AT_EXECPATH) failed");158}159}160161if (basename == NULL || *basename == '\0')162crunched_usage(1);163164if (ep != NULL) {165return ep->f(argc, argv, envp);166} else {167fprintf(stderr, "%s: %s not compiled in\n\n",168EXECNAME, basename);169crunched_usage(1);170}171}172173int174crunched_main(int argc, char **argv, char **envp)175{176if (argc <= 1)177crunched_usage(0);178179__progname = get_basename(argv[1]);180return main(--argc, ++argv, envp);181}182183int184crunched_list(int argc __unused, char **argv __unused, char **envp __unused)185{186for (int i = 0; i < num_entry_points - 2; i++)187printf("%s\n", entry_points[i].name);188return (0);189}190191static void192crunched_usage(int code)193{194int columns, len;195FILE *out = stdout;196if (code > 0)197out = stderr;198199fprintf(out,200"usage: %s program [args ...]\n"201" %s --list\n"202" program [args ...]\n"203"\n"204"%s combines several programs in one executable. Create a link to this\n"205"executable with the program name to run that program, or give the program\n"206"name as the first argument.\n"207"\n"208"Currently defined programs:\n",209EXECNAME, EXECNAME, EXECNAME);210columns = 0;211for (int i = 0; i < num_entry_points - 2; i++) {212struct stub *ep = &entry_points[i];213len = strlen(ep->name) + 1;214if (columns + len < 80)215columns += len;216else {217fprintf(out, "\n");218columns = len;219}220fprintf(out, " %s", ep->name);221}222fprintf(out, "\n");223exit(code);224}225226/* end of crunched_main.c */227228229