📄 main.cpp
字号:
/* main.cpp -- This file is part of the UPX executable compressor. Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996-2007 Laszlo Molnar All Rights Reserved. UPX and the UCL library are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer Laszlo Molnar <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net> */#include "conf.h"#include "mygetopt.h"#include "file.h"#include "packer.h"#include "p_elf.h"#if 1 && defined(__DJGPP__)#include <crt0.h>int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;#endif/*************************************************************************// options**************************************************************************/void options_t::reset(){ options_t *o = this; memset(o, 0, sizeof(*o)); o->crp.reset(); o->cmd = CMD_NONE; o->method = M_NONE; o->level = -1; o->filter = FT_NONE; o->backup = -1; o->overlay = -1; o->preserve_mode = true; o->preserve_ownership = true; o->preserve_timestamp = true; o->console = CON_FILE;#if defined(__DJGPP__) o->console = CON_INIT;#elif defined(USE_SCREEN_WIN32) o->console = CON_INIT;#elif 1 && defined(__linux__) o->console = CON_INIT;#endif o->verbose = 2; o->win32_pe.compress_exports = 1; o->win32_pe.compress_icons = 2; o->win32_pe.compress_resources = -1; for (unsigned i = 0; i < TABLESIZE(o->win32_pe.compress_rt); i++) o->win32_pe.compress_rt[i] = -1; o->win32_pe.compress_rt[24] = false; // 24 == RT_MANIFEST o->win32_pe.strip_relocs = -1; o->win32_pe.keep_resource = "";}static options_t global_options;options_t *opt = &global_options;static int done_output_name = 0;static int done_script_name = 0;const char *argv0 = "";const char *progname = "";static int num_files = -1;static int exit_code = EXIT_OK;/*************************************************************************// exit handlers**************************************************************************/#if defined(__GNUC__)static void do_exit(void) __attribute__((__noreturn__));#endifstatic void do_exit(void){ static bool in_exit = false; if (in_exit) exit(exit_code); in_exit = true; fflush(con_term); fflush(stderr); exit(exit_code);}#define EXIT_FATAL 3static bool set_eec(int ec, int *eec){ if (ec == EXIT_FATAL) { *eec = EXIT_ERROR; return 1; } else if (ec < 0 || ec == EXIT_ERROR) { *eec = EXIT_ERROR; } else if (ec == EXIT_WARN) { if (!opt->ignorewarn) if (*eec == EXIT_OK) *eec = ec; } else if (ec == EXIT_OK) { /* do nothing */ } else { assert(0); } return 0;}bool set_ec(int ec){ return set_eec(ec,&exit_code);}void e_exit(int ec){ (void) set_ec(ec); do_exit();}void e_usage(void){ show_usage(); e_exit(EXIT_USAGE);}void e_memory(void){ show_head(); fflush(con_term); fprintf(stderr,"%s: out of memory\n", argv0); e_exit(EXIT_MEMORY);}static void e_method(int m, int l){ fflush(con_term); fprintf(stderr,"%s: illegal method option -- %d/%d\n", argv0, m, l); e_usage();}static void e_optarg(const char *n){ fflush(con_term); fprintf(stderr,"%s: invalid argument in option '%s'\n", argv0, n); e_exit(EXIT_USAGE);}static void e_optval(const char *n){ fflush(con_term); fprintf(stderr,"%s: invalid value for option '%s'\n", argv0, n); e_exit(EXIT_USAGE);}#if defined(OPTIONS_VAR)void e_envopt(const char *n){ fflush(con_term); if (n) fprintf(stderr,"%s: invalid string '%s' in environment variable '%s'\n", argv0, n, OPTIONS_VAR); else fprintf(stderr,"%s: illegal option in environment variable '%s'\n", argv0, OPTIONS_VAR); e_exit(EXIT_USAGE);}#endif /* defined(OPTIONS_VAR) */void __acc_cdecl_sighandler e_sighandler(int signum){ UNUSED(signum); e_exit(EXIT_FATAL);}/*************************************************************************// check options**************************************************************************/void check_not_both(bool e1, bool e2, const char *c1, const char *c2){ if (e1 && e2) { fprintf(stderr,"%s: ",argv0); fprintf(stderr,"cannot use both '%s' and '%s'\n", c1, c2); e_usage(); }}void check_options(int i, int argc){ assert(i <= argc); if (opt->cmd != CMD_COMPRESS) { // invalidate compression options opt->method = 0; opt->level = 0; opt->exact = 0; opt->small = 0; opt->crp.reset(); } // set default overlay action if (!(opt->cmd == CMD_COMPRESS || opt->cmd == CMD_DECOMPRESS)) opt->overlay = opt->COPY_OVERLAY; else if (opt->overlay < 0) opt->overlay = opt->COPY_OVERLAY; check_not_both(opt->exact, opt->overlay == opt->STRIP_OVERLAY, "--exact", "--overlay=strip"); // set default backup option if (opt->backup < 0) opt->backup = 0; if (!(opt->cmd == CMD_COMPRESS || opt->cmd == CMD_DECOMPRESS)) opt->backup = 1; check_not_both(opt->to_stdout, opt->output_name != NULL, "--stdout", "-o"); if (opt->to_stdout && opt->cmd == CMD_COMPRESS) { fprintf(stderr,"%s: cannot use '--stdout' when compressing\n", argv0); e_usage(); } if (opt->to_stdout || opt->output_name) { if (i + 1 != argc) { fprintf(stderr,"%s: need exactly one argument when using '%s'\n", argv0, opt->to_stdout ? "--stdout" : "-o"); e_usage(); } }}/*************************************************************************// misc**************************************************************************/void e_help(void){ show_help(); e_exit(EXIT_USAGE);}static void set_term(FILE *f){ if (f) con_term = f; else con_term = acc_isatty(STDIN_FILENO) ? stderr : stdout;}static void set_cmd(int cmd){ if (cmd > opt->cmd) opt->cmd = cmd;}static bool set_method(int m, int l){ if (m > 0) { if (!Packer::isValidCompressionMethod(m)) return false;#if 1 // something like "--brute --lzma" should not disable "--brute" if (!opt->all_methods)#endif { opt->method = m; opt->all_methods = false; } } if (l > 0) opt->level = l; set_cmd(CMD_COMPRESS); return true;}static void set_output_name(const char *n, bool allow_m){#if 1 if (done_output_name > 0) { fprintf(stderr,"%s: option '-o' more than once given\n",argv0); e_usage(); }#endif if (!n || !n[0] || (!allow_m && n[0] == '-')) { fprintf(stderr,"%s: missing output name\n",argv0); e_usage(); } if (strlen(n) >= ACC_FN_PATH_MAX - 4) { fprintf(stderr,"%s: output name too long\n",argv0); e_usage(); } opt->output_name = n; done_output_name++;}static void set_script_name(const char *n, bool allow_m){#if 1 if (done_script_name > 0) { fprintf(stderr,"%s: option '--script' more than once given\n",argv0); e_usage(); }#endif if (!n || !n[0] || (!allow_m && n[0] == '-')) { fprintf(stderr,"%s: missing script name\n",argv0); e_usage(); } if (strlen(n) >= (size_t)opt->o_unix.SCRIPT_MAX - 3) { fprintf(stderr,"%s: script name too long\n",argv0); e_usage(); } opt->o_unix.script_name = n; done_script_name++;}/*************************************************************************// get options**************************************************************************/staticchar* prepare_shortopts(char *buf, const char *n, const struct mfx_option *longopts){ char *o = buf; for ( ; n && *n; n++) if (*n != ' ') *o++ = *n; *o = 0; for ( ; longopts && longopts->name; longopts++) { int v = longopts->val;#if !defined(NDEBUG) assert(longopts->name[0] != '\0'); assert(longopts->name[0] != '-'); if (longopts->has_arg & 0x20) assert((longopts->has_arg & 0xf) == 1);#endif#if 0 static char vopts[1024]; if (v > 0 && v < 1024) { if (vopts[v] && strchr(buf,v) == NULL) printf("warning: duplicate option %d ('%c')!\n", v, v & 127); vopts[v] = 1; }#endif if (v > 0 && v < 256 && strchr(buf,v) == NULL) { *o++ = (char) v; if ((longopts->has_arg & 0xf) >= 1) *o++ = ':'; if ((longopts->has_arg & 0xf) >= 2) *o++ = ':'; *o = 0; } if (longopts->has_arg & 0x20) assert((longopts->has_arg & 0xf) == 1); } return buf;}template <class T>int getoptvar(T *var, const T min_value, const T max_value, const char *arg_fatal){ const char *p = mfx_optarg; char *endptr; int r = 0; long n; T v; if (!p || !p[0]) { r = -1; goto error; } // avoid interpretation as octal value while (p[0] == '0' && isdigit(p[1])) p++; n = strtol(p, &endptr, 0); if (*endptr != '\0') { r = -2; goto error; } v = (T) n; if (v < min_value) { r = -3; goto error; } if (v > max_value) { r = -4; goto error; } *var = v; goto done;error: if (arg_fatal != NULL) e_optval(arg_fatal);done: return r;}#if 1 && (ACC_CC_GNUC >= 0x030300)template <class T, T default_value, T min_value, T max_value>int getoptvar(OptVar<T,default_value,min_value,max_value> *var, const char *arg_fatal){ T v = default_value; int r = getoptvar(&v, min_value, max_value, arg_fatal); if (r == 0) *var = v; return r;}#elsetemplate <class T>int getoptvar(T *var, const char *arg_fatal){ typename T::Type v = T::default_value_c; int r = getoptvar(&v, T::min_value_c, T::max_value_c, arg_fatal); if (r == 0) *var = v; return r;}#endifstatic int do_option(int optc, const char *arg){ int i = 0; switch (optc) {#if 0 // FIXME: to_stdout doesn't work because of console code mess //case 'c': case 517: opt->to_stdout = true; break;#endif case 'd': set_cmd(CMD_DECOMPRESS); break; case 'D': opt->debug.debug_level++; break; case 'f': opt->force++; break; case 909: set_cmd(CMD_FILEINFO); break; case 'h': case 'H': case '?': set_cmd(CMD_HELP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -