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