(root)/
util-linux-2.39/
sys-utils/
setarch.c
       1  /*
       2   * Copyright (C) 2003-2007 Red Hat, Inc.
       3   *
       4   * This file is part of util-linux.
       5   *
       6   * This file is free software; you can redistribute it and/or modify
       7   * it under the terms of the GNU General Public License as published by
       8   * the Free Software Foundation; either version 2 of the License, or
       9   * (at your option) any later version.
      10   *
      11   * This file is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14   * GNU General Public License for more details.
      15   *
      16   *
      17   * Written by Elliot Lee <sopwith@redhat.com>
      18   * New personality options & code added by Jindrich Novy <jnovy@redhat.com>
      19   * ADD_NO_RANDOMIZE flag added by Arjan van de Ven <arjanv@redhat.com>
      20   * Help and MIPS support from Mike Frysinger (vapier@gentoo.org)
      21   * Better error handling from Dmitry V. Levin (ldv@altlinux.org)
      22   *
      23   * based on ideas from the ppc32 util by Guy Streeter (2002-01), based on the
      24   * sparc32 util by Jakub Jelinek (1998, 1999)
      25   */
      26  
      27  #include <sys/personality.h>
      28  #include <unistd.h>
      29  #include <stdio.h>
      30  #include <string.h>
      31  #include <stdlib.h>
      32  #include <getopt.h>
      33  #include <limits.h>
      34  #include <sys/utsname.h>
      35  #include "nls.h"
      36  #include "c.h"
      37  #include "closestream.h"
      38  #include "sysfs.h"
      39  #include "strutils.h"
      40  
      41  #ifndef HAVE_PERSONALITY
      42  # include <syscall.h>
      43  # define personality(pers) ((long)syscall(SYS_personality, pers))
      44  #endif
      45  
      46  #define turn_on(_flag, _opts) \
      47  	do { \
      48  		(_opts) |= _flag; \
      49  		if (verbose) \
      50  			printf(_("Switching on %s.\n"), #_flag); \
      51  	} while(0)
      52  
      53  #ifndef UNAME26
      54  # define UNAME26                 0x0020000
      55  #endif
      56  #ifndef ADDR_NO_RANDOMIZE
      57  # define ADDR_NO_RANDOMIZE       0x0040000
      58  #endif
      59  #ifndef FDPIC_FUNCPTRS
      60  # define FDPIC_FUNCPTRS          0x0080000
      61  #endif
      62  #ifndef MMAP_PAGE_ZERO
      63  # define MMAP_PAGE_ZERO          0x0100000
      64  #endif
      65  #ifndef ADDR_COMPAT_LAYOUT
      66  # define ADDR_COMPAT_LAYOUT      0x0200000
      67  #endif
      68  #ifndef READ_IMPLIES_EXEC
      69  # define READ_IMPLIES_EXEC       0x0400000
      70  #endif
      71  #ifndef ADDR_LIMIT_32BIT
      72  # define ADDR_LIMIT_32BIT        0x0800000
      73  #endif
      74  #ifndef SHORT_INODE
      75  # define SHORT_INODE             0x1000000
      76  #endif
      77  #ifndef WHOLE_SECONDS
      78  # define WHOLE_SECONDS           0x2000000
      79  #endif
      80  #ifndef STICKY_TIMEOUTS
      81  # define STICKY_TIMEOUTS         0x4000000
      82  #endif
      83  #ifndef ADDR_LIMIT_3GB
      84  # define ADDR_LIMIT_3GB          0x8000000
      85  #endif
      86  
      87  #define ALL_PERSONALITIES \
      88      X(PER_LINUX) \
      89      X(PER_LINUX_32BIT) \
      90      X(PER_LINUX_FDPIC) \
      91      X(PER_SVR4) \
      92      X(PER_SVR3) \
      93      X(PER_SCOSVR3) \
      94      X(PER_OSR5) \
      95      X(PER_WYSEV386) \
      96      X(PER_ISCR4) \
      97      X(PER_BSD) \
      98      X(PER_SUNOS) \
      99      X(PER_XENIX) \
     100      X(PER_LINUX32) \
     101      X(PER_LINUX32_3GB) \
     102      X(PER_IRIX32) \
     103      X(PER_IRIXN32) \
     104      X(PER_IRIX64) \
     105      X(PER_RISCOS) \
     106      X(PER_SOLARIS) \
     107      X(PER_UW7) \
     108      X(PER_OSF4) \
     109      X(PER_HPUX) \
     110  
     111  
     112  #define ALL_OPTIONS \
     113      X(UNAME26) \
     114      X(ADDR_NO_RANDOMIZE) \
     115      X(FDPIC_FUNCPTRS) \
     116      X(MMAP_PAGE_ZERO) \
     117      X(ADDR_COMPAT_LAYOUT) \
     118      X(READ_IMPLIES_EXEC) \
     119      X(ADDR_LIMIT_32BIT) \
     120      X(SHORT_INODE) \
     121      X(WHOLE_SECONDS) \
     122      X(STICKY_TIMEOUTS) \
     123      X(ADDR_LIMIT_3GB) \
     124  
     125  
     126  struct arch_domain {
     127  	int		perval;		/* PER_* */
     128  	const char	*target_arch;
     129  	const char	*result_arch;
     130  };
     131  
     132  
     133  static void __attribute__((__noreturn__)) usage(int archwrapper)
     134  {
     135  	fputs(USAGE_HEADER, stdout);
     136  	if (!archwrapper)
     137  		printf(_(" %s [<arch>] [options] [<program> [<argument>...]]\n"), program_invocation_short_name);
     138  	else
     139  		printf(_(" %s [options] [<program> [<argument>...]]\n"), program_invocation_short_name);
     140  
     141  	fputs(USAGE_SEPARATOR, stdout);
     142  	fputs(_("Change the reported architecture and set personality flags.\n"), stdout);
     143  
     144  	fputs(USAGE_OPTIONS, stdout);
     145  	fputs(_(" -B, --32bit              turns on ADDR_LIMIT_32BIT\n"), stdout);
     146  	fputs(_(" -F, --fdpic-funcptrs     makes function pointers point to descriptors\n"), stdout);
     147  	fputs(_(" -I, --short-inode        turns on SHORT_INODE\n"), stdout);
     148  	fputs(_(" -L, --addr-compat-layout changes the way virtual memory is allocated\n"), stdout);
     149  	fputs(_(" -R, --addr-no-randomize  disables randomization of the virtual address space\n"), stdout);
     150  	fputs(_(" -S, --whole-seconds      turns on WHOLE_SECONDS\n"), stdout);
     151  	fputs(_(" -T, --sticky-timeouts    turns on STICKY_TIMEOUTS\n"), stdout);
     152  	fputs(_(" -X, --read-implies-exec  turns on READ_IMPLIES_EXEC\n"), stdout);
     153  	fputs(_(" -Z, --mmap-page-zero     turns on MMAP_PAGE_ZERO\n"), stdout);
     154  	fputs(_(" -3, --3gb                limits the used address space to a maximum of 3 GB\n"), stdout);
     155  	fputs(_("     --4gb                ignored (for backward compatibility only)\n"), stdout);
     156  	fputs(_("     --uname-2.6          turns on UNAME26\n"), stdout);
     157  	fputs(_(" -v, --verbose            say what options are being switched on\n"), stdout);
     158  
     159  	if (!archwrapper) {
     160  		fputs(_("     --list               list settable architectures, and exit\n"), stdout);
     161  		fputs(_("     --show[=personality] show current or specific personality and exit\n"), stdout);
     162  	}
     163  
     164  	fputs(USAGE_SEPARATOR, stdout);
     165  	printf(USAGE_HELP_OPTIONS(26));
     166  	printf(USAGE_MAN_TAIL("setarch(8)"));
     167  
     168  	exit(EXIT_SUCCESS);
     169  }
     170  
     171  /*
     172   * Returns inilialized list of all available execution domains.
     173   */
     174  static struct arch_domain *init_arch_domains(void)
     175  {
     176  	static struct utsname un;
     177  	size_t i;
     178  
     179  	static struct arch_domain transitions[] =
     180  	{
     181  		{UNAME26,	"uname26",	NULL},
     182  		{PER_LINUX32,	"linux32",	NULL},
     183  		{PER_LINUX,	"linux64",	NULL},
     184  #if defined(__powerpc__) || defined(__powerpc64__)
     185  # ifdef __BIG_ENDIAN__
     186  		{PER_LINUX32,	"ppc32",	"ppc"},
     187  		{PER_LINUX32,	"ppc",		"ppc"},
     188  		{PER_LINUX,	"ppc64",	"ppc64"},
     189  		{PER_LINUX,	"ppc64pseries",	"ppc64"},
     190  		{PER_LINUX,	"ppc64iseries",	"ppc64"},
     191  # else
     192  		{PER_LINUX32,	"ppc32",	"ppcle"},
     193  		{PER_LINUX32,	"ppc",		"ppcle"},
     194  		{PER_LINUX32,	"ppc32le",	"ppcle"},
     195  		{PER_LINUX32,	"ppcle",	"ppcle"},
     196  		{PER_LINUX,	"ppc64le",	"ppc64le"},
     197  # endif
     198  #endif
     199  #if defined(__x86_64__) || defined(__i386__) || defined(__ia64__)
     200  		{PER_LINUX32,	"i386",		"i386"},
     201  		{PER_LINUX32,	"i486",		"i386"},
     202  		{PER_LINUX32,	"i586",		"i386"},
     203  		{PER_LINUX32,	"i686",		"i386"},
     204  		{PER_LINUX32,	"athlon",	"i386"},
     205  #endif
     206  #if defined(__x86_64__) || defined(__i386__)
     207  		{PER_LINUX,	"x86_64",	"x86_64"},
     208  #endif
     209  #if defined(__ia64__) || defined(__i386__)
     210  		{PER_LINUX,	"ia64",		"ia64"},
     211  #endif
     212  #if defined(__hppa__)
     213  		{PER_LINUX32,	"parisc32",	"parisc"},
     214  		{PER_LINUX32,	"parisc",	"parisc"},
     215  		{PER_LINUX,	"parisc64",	"parisc64"},
     216  #endif
     217  #if defined(__s390x__) || defined(__s390__)
     218  		{PER_LINUX32,	"s390",		"s390"},
     219  		{PER_LINUX,	"s390x",	"s390x"},
     220  #endif
     221  #if defined(__sparc64__) || defined(__sparc__)
     222  		{PER_LINUX32,	"sparc",	"sparc"},
     223  		{PER_LINUX32,	"sparc32bash",	"sparc"},
     224  		{PER_LINUX32,	"sparc32",	"sparc"},
     225  		{PER_LINUX,	"sparc64",	"sparc64"},
     226  #endif
     227  #if defined(__mips64__) || defined(__mips__)
     228  		{PER_LINUX32,	"mips32",	"mips"},
     229  		{PER_LINUX32,	"mips",		"mips"},
     230  		{PER_LINUX,	"mips64",	"mips64"},
     231  #endif
     232  #if defined(__alpha__)
     233  		{PER_LINUX,	"alpha",	"alpha"},
     234  		{PER_LINUX,	"alphaev5",	"alpha"},
     235  		{PER_LINUX,	"alphaev56",	"alpha"},
     236  		{PER_LINUX,	"alphaev6",	"alpha"},
     237  		{PER_LINUX,	"alphaev67",	"alpha"},
     238  #endif
     239  #if defined(__loongarch__)
     240  		{PER_LINUX,	"loongarch",	"loongarch64"},
     241  		{PER_LINUX,	"loongarch64",	"loongarch64"},
     242  #endif
     243  #if defined(__e2k__)
     244  		{PER_LINUX,	"e2k",      "e2k"},
     245  		{PER_LINUX,	"e2kv4",	"e2k"},
     246  		{PER_LINUX,	"e2kv5",	"e2k"},
     247  		{PER_LINUX,	"e2kv6",	"e2k"},
     248  		{PER_LINUX,	"e2k4c",	"e2k"},
     249  		{PER_LINUX,	"e2k8c",	"e2k"},
     250  		{PER_LINUX,	"e2k1cp",	"e2k"},
     251  		{PER_LINUX,	"e2k8c2",	"e2k"},
     252  		{PER_LINUX,	"e2k12c",	"e2k"},
     253  		{PER_LINUX,	"e2k16c",	"e2k"},
     254  		{PER_LINUX,	"e2k2c3",	"e2k"},
     255  #endif
     256  #if defined(__arm__) || defined(__aarch64__)
     257  # ifdef __BIG_ENDIAN__
     258  		{PER_LINUX32,	"armv7b",	"arm"},
     259  		{PER_LINUX32,	"armv8b",	"arm"},
     260  # else
     261  		{PER_LINUX32,	"armv7l",	"arm"},
     262  		{PER_LINUX32,	"armv8l",	"arm"},
     263  # endif
     264  		{PER_LINUX32,	"armh",		"arm"},
     265  		{PER_LINUX32,	"arm",		"arm"},
     266  		{PER_LINUX,	"arm64",	"aarch64"},
     267  		{PER_LINUX,	"aarch64",	"aarch64"},
     268  #endif
     269  		/* place holder, will be filled up at runtime */
     270  		{-1,		NULL,		NULL},
     271  		{-1,		NULL,		NULL}
     272  	};
     273  
     274  	/* Add the trivial transition {PER_LINUX, machine, machine} if no
     275  	 * such target_arch is hardcoded yet.  */
     276  	uname(&un);
     277  	for (i = 0; transitions[i].perval >= 0; i++)
     278  		if (!strcmp(un.machine, transitions[i].target_arch))
     279  			break;
     280  	if (transitions[i].perval < 0) {
     281  		int wrdsz = sysfs_get_address_bits(NULL);
     282  		if (wrdsz < 0)
     283  			wrdsz = CHAR_BIT * sizeof(void *);
     284  		if (wrdsz == 32 || wrdsz == 64) {
     285  			/* fill up the place holder */
     286  			transitions[i].perval = wrdsz == 32 ? PER_LINUX32 : PER_LINUX;
     287  			transitions[i].target_arch = un.machine;
     288  			transitions[i].result_arch = un.machine;
     289  		}
     290  	}
     291  
     292  	return transitions;
     293  }
     294  
     295  /*
     296   * List all execution domains from transitions
     297   */
     298  static void list_arch_domains(struct arch_domain *doms)
     299  {
     300  	struct arch_domain *d;
     301  
     302  	for (d = doms; d->target_arch != NULL; d++)
     303  		printf("%s\n", d->target_arch);
     304  }
     305  
     306  static struct arch_domain *get_arch_domain(struct arch_domain *doms, const char *pers)
     307  {
     308  	struct arch_domain *d;
     309  
     310  	for (d = doms; d && d->perval >= 0; d++) {
     311  		if (!strcmp(pers, d->target_arch))
     312  			break;
     313  	}
     314  
     315  	return !d || d->perval < 0 ? NULL : d;
     316  }
     317  
     318  static void verify_arch_domain(struct arch_domain *doms, struct arch_domain *target, const char *wanted)
     319  {
     320  	struct utsname un;
     321  
     322  	if (!doms || !target || !target->result_arch)
     323  		return;
     324  
     325  	uname(&un);
     326  
     327  	if (!strcmp(un.machine, target->result_arch))
     328  		return;
     329  
     330  	if (!strcmp(target->result_arch, "i386") ||
     331  	    !strcmp(target->result_arch, "arm")) {
     332  		struct arch_domain *dom;
     333  		for (dom = doms; dom->target_arch != NULL; dom++) {
     334  			if (!dom->result_arch || strcmp(dom->result_arch, target->result_arch))
     335  				continue;
     336  			if (!strcmp(dom->target_arch, un.machine))
     337  				return;
     338  		}
     339  	}
     340  
     341  	errx(EXIT_FAILURE, _("Kernel cannot set architecture to %s"), wanted);
     342  }
     343  
     344  static const struct { int value; const char * const name; } all_personalities[] = {
     345  #define X(opt) { .value = opt, .name = #opt },
     346  	ALL_PERSONALITIES
     347  #undef X
     348  };
     349  
     350  static const struct { int value; const char * const name; } all_options[] = {
     351  #define X(opt) { .value = opt, .name = #opt },
     352  	ALL_OPTIONS
     353  #undef X
     354  };
     355  
     356  static void show_personality(int pers)
     357  {
     358  	int options;
     359  	size_t i;
     360  
     361  	/* Test for exact matches including options */
     362  	for (i = 0; i < ARRAY_SIZE(all_personalities); i++) {
     363  		if (pers == all_personalities[i].value) {
     364  			printf("%s\n", all_personalities[i].name);
     365  			return;
     366  		}
     367  	}
     368  
     369  	options = pers & ~PER_MASK;
     370  	pers &= PER_MASK;
     371  
     372  	/* Second test for type-only matches */
     373  	for (i = 0; i < ARRAY_SIZE(all_personalities); i++) {
     374  		if (pers == all_personalities[i].value) {
     375  			printf("%s", all_personalities[i].name);
     376  			break;
     377  		}
     378  	}
     379  
     380  	if (i == ARRAY_SIZE(all_personalities))
     381  		printf("0x%02x", pers);
     382  
     383  	if (options) {
     384  		printf(" (");
     385  
     386  		for (i = 0; i < ARRAY_SIZE(all_options); i++) {
     387  			if (options & all_options[i].value) {
     388  				printf("%s", all_options[i].name);
     389  
     390  				options &= ~all_options[i].value;
     391  				if (options)
     392  					printf(" ");
     393  			}
     394  		}
     395  		if (options)
     396  			printf("0x%08x", options);
     397  		printf(")");
     398  	}
     399  	printf("\n");
     400  }
     401  
     402  static void show_current_personality(void)
     403  {
     404  	int pers = personality(0xffffffff);
     405  	if (pers == -1)
     406  		err(EXIT_FAILURE, _("Can not get current kernel personality"));
     407  
     408  	show_personality(pers);
     409  }
     410  
     411  int main(int argc, char *argv[])
     412  {
     413  	const char *arch = NULL;
     414  	unsigned long options = 0;
     415  	int verbose = 0;
     416  	int archwrapper;
     417  	int c;
     418  	struct arch_domain *doms = NULL, *target = NULL;
     419  	unsigned long pers_value = 0;
     420  	char *shell = NULL, *shell_arg = NULL;
     421  
     422  	/* Options without equivalent short options */
     423  	enum {
     424  		OPT_4GB = CHAR_MAX + 1,
     425  		OPT_UNAME26,
     426  		OPT_LIST,
     427  		OPT_SHOW,
     428  	};
     429  
     430  	/* Options --3gb and --4gb are for compatibility with an old
     431  	 * Debian setarch implementation.  */
     432  	static const struct option longopts[] = {
     433  		{"help",		no_argument,		NULL,	'h'},
     434  		{"version",		no_argument,		NULL,	'V'},
     435  		{"verbose",		no_argument,		NULL,	'v'},
     436  		{"addr-no-randomize",	no_argument,		NULL,	'R'},
     437  		{"fdpic-funcptrs",	no_argument,		NULL,	'F'},
     438  		{"mmap-page-zero",	no_argument,		NULL,	'Z'},
     439  		{"addr-compat-layout",	no_argument,		NULL,	'L'},
     440  		{"read-implies-exec",	no_argument,		NULL,	'X'},
     441  		{"32bit",		no_argument,		NULL,	'B'},
     442  		{"short-inode",		no_argument,		NULL,	'I'},
     443  		{"whole-seconds",	no_argument,		NULL,	'S'},
     444  		{"sticky-timeouts",	no_argument,		NULL,	'T'},
     445  		{"3gb",			no_argument,		NULL,	'3'},
     446  		{"4gb",			no_argument,		NULL,	OPT_4GB},
     447  		{"uname-2.6",		no_argument,		NULL,	OPT_UNAME26},
     448  		{"list",		no_argument,		NULL,	OPT_LIST},
     449  		{"show",		optional_argument,	NULL,	OPT_SHOW},
     450  		{NULL,			0,			NULL,	0}
     451  	};
     452  
     453  	setlocale(LC_ALL, "");
     454  	bindtextdomain(PACKAGE, LOCALEDIR);
     455  	textdomain(PACKAGE);
     456  	close_stdout_atexit();
     457  
     458  	if (argc < 1) {
     459  		warnx(_("Not enough arguments"));
     460  		errtryhelp(EXIT_FAILURE);
     461  	}
     462  	archwrapper = strcmp(program_invocation_short_name, "setarch") != 0;
     463  	if (archwrapper) {
     464  		arch = program_invocation_short_name;	/* symlinks to setarch */
     465  
     466  		/* Don't use ifdef sparc here, we get "Unrecognized architecture"
     467  		 * error message later if necessary */
     468  		if (strcmp(arch, "sparc32bash") == 0) {
     469  			shell = "/bin/bash";
     470  			shell_arg = "";
     471  			goto set_arch;
     472  		}
     473  	} else {
     474  		if (1 < argc && *argv[1] != '-') {
     475  			arch = argv[1];
     476  			argv[1] = argv[0];	/* for getopt_long() to get the program name */
     477  			argv++;
     478  			argc--;
     479  		}
     480  	}
     481  
     482  	while ((c = getopt_long(argc, argv, "+hVv3BFILRSTXZ", longopts, NULL)) != -1) {
     483  		switch (c) {
     484  		case 'v':
     485  			verbose = 1;
     486  			break;
     487  		case 'R':
     488  			turn_on(ADDR_NO_RANDOMIZE, options);
     489  			break;
     490  		case 'F':
     491  			turn_on(FDPIC_FUNCPTRS, options);
     492  			break;
     493  		case 'Z':
     494  			turn_on(MMAP_PAGE_ZERO, options);
     495  			break;
     496  		case 'L':
     497  			turn_on(ADDR_COMPAT_LAYOUT, options);
     498  			break;
     499  		case 'X':
     500  			turn_on(READ_IMPLIES_EXEC, options);
     501  			break;
     502  		case 'B':
     503  			turn_on(ADDR_LIMIT_32BIT, options);
     504  			break;
     505  		case 'I':
     506  			turn_on(SHORT_INODE, options);
     507  			break;
     508  		case 'S':
     509  			turn_on(WHOLE_SECONDS, options);
     510  			break;
     511  		case 'T':
     512  			turn_on(STICKY_TIMEOUTS, options);
     513  			break;
     514  		case '3':
     515  			turn_on(ADDR_LIMIT_3GB, options);
     516  			break;
     517  		case OPT_4GB:	/* just ignore this one */
     518  			break;
     519  		case OPT_UNAME26:
     520  			turn_on(UNAME26, options);
     521  			break;
     522  		case OPT_LIST:
     523  			if (!archwrapper) {
     524  				list_arch_domains(init_arch_domains());
     525  				return EXIT_SUCCESS;
     526  			} else
     527  				warnx(_("unrecognized option '--list'"));
     528  			goto error_getopts;
     529  		case OPT_SHOW:
     530  			if (!archwrapper) {
     531  				if (!optarg || strcmp(optarg, "current") == 0)
     532  					show_current_personality();
     533  				else
     534  					show_personality(str2num_or_err(
     535  						optarg, 16,
     536  						_("could not parse personality"),
     537  						0, INT_MAX));
     538  				return EXIT_SUCCESS;
     539  			} else
     540  				warnx(_("unrecognized option '--show'"));
     541  			goto error_getopts;
     542  
     543  error_getopts:
     544  		default:
     545  			errtryhelp(EXIT_FAILURE);
     546  		case 'h':
     547  			usage(archwrapper);
     548  		case 'V':
     549  			print_version(EXIT_SUCCESS);
     550  		}
     551  	}
     552  
     553  	if (!arch && !options)
     554  		errx(EXIT_FAILURE, _("no architecture argument or personality flags specified"));
     555  
     556  	argc -= optind;
     557  	argv += optind;
     558  
     559  set_arch:
     560  	/* get execution domain (architecture) */
     561  	if (arch) {
     562  		doms = init_arch_domains();
     563  		target = get_arch_domain(doms, arch);
     564  
     565  		if (!target)
     566  			errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), arch);
     567  		pers_value = target->perval;
     568  	}
     569  
     570  	/* add personality flags */
     571  	pers_value |= options;
     572  
     573  	/* call kernel */
     574  	if (personality(pers_value) < 0) {
     575  		/*
     576  		 * Depending on architecture and kernel version, personality
     577  		 * syscall is either capable or incapable of returning an error.
     578  		 * If the return value is not an error, then it's the previous
     579  		 * personality value, which can be an arbitrary value
     580  		 * undistinguishable from an error value.
     581  		 * To make things clear, a second call is needed.
     582  		 */
     583  		if (personality(pers_value) < 0)
     584  			err(EXIT_FAILURE, _("failed to set personality to %s"), arch);
     585  	}
     586  
     587  	/* make sure architecture is set as expected */
     588  	if (arch)
     589  		verify_arch_domain(doms, target, arch);
     590  
     591  	if (!argc) {
     592  		shell = "/bin/sh";
     593  		shell_arg = "-sh";
     594  	}
     595  	if (verbose) {
     596  		printf(_("Execute command `%s'.\n"), shell ? shell : argv[0]);
     597  		/* flush all output streams before exec */
     598  		fflush(NULL);
     599  	}
     600  
     601  	/* Execute shell */
     602  	if (shell) {
     603  		execl(shell, shell_arg, (char *)NULL);
     604  		errexec(shell);
     605  	}
     606  
     607  	/* Execute on command line specified command */
     608  	execvp(argv[0], argv);
     609  	errexec(argv[0]);
     610  }