1e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#include <errno.h>
2e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#include <mach/mach.h>
3e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#include <signal.h>
4e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#include <stdio.h>
5e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#include <stdint.h>
6e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#include <stdlib.h>
7e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#include <spawn.h>
8e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#include <unistd.h>
9e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton
10e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Claytonstatic void
11e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Claytonexit_with_errno (int err, const char *prefix)
12e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton{
13e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    if (err)
14e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    {
15e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        fprintf (stderr,
16e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton                 "%s%s",
17e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton                 prefix ? prefix : "",
18e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton                 strerror(err));
19e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        exit (err);
20e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    }
21e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton}
22e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton
23e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Claytonstatic pid_t
24e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Claytonspawn_process (const char **argv,
25e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton               const char **envp,
26e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton               cpu_type_t cpu_type,
27e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton               int &err)
28e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton{
29e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    pid_t pid = 0;
30e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton
31e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    const posix_spawn_file_actions_t *file_actions = NULL;
32e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    posix_spawnattr_t attr;
33e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    err = posix_spawnattr_init (&attr);
34e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    if (err)
35e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        return pid;
36e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton
37e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    short flags = POSIX_SPAWN_SETEXEC | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
38e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    err = posix_spawnattr_setflags (&attr, flags);
39e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    if (err == 0)
40e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    {
41e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        // Use the default signal masks
42e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        sigset_t no_signals;
43e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        sigset_t all_signals;
44e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        sigemptyset (&no_signals);
45e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        sigfillset (&all_signals);
46e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        posix_spawnattr_setsigmask(&attr, &no_signals);
47e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        posix_spawnattr_setsigdefault(&attr, &all_signals);
48e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton
49e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        if (cpu_type != 0)
50e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        {
51e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton            size_t ocount = 0;
52e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton            err = posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount);
53e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        }
54e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton
55e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        if (err == 0)
56e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        {
57e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton            err = posix_spawn (&pid,
58e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton                               argv[0],
59e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton                               file_actions,
60e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton                               &attr,
61e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton                               (char * const *)argv,
62e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton                               (char * const *)envp);
63e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        }
64e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton
65e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        posix_spawnattr_destroy(&attr);
66e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    }
67e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    return pid;
68e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton}
69e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton
70e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Claytonint
71e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Claytonmain (int argc, char const **argv)
72e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton{
73e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    printf ("pid %i: Pointer size is %zu.\n", getpid(), sizeof(void *));
74e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    int err = 0;    // Set breakpoint 1 here
75e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#if defined (__x86_64__)
76e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    if (sizeof(void *) == 8)
77e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    {
78e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        spawn_process (argv, NULL, CPU_TYPE_I386, err);
79e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        if (err)
80e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton            exit_with_errno (err, "posix_spawn i386 error");
81e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    }
82e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    else
83e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    {
84e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        spawn_process (argv, NULL, CPU_TYPE_X86_64, err);
85e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        if (err)
86e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton            exit_with_errno (err, "posix_spawn x86_64 error");
87e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    }
88e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#else
89e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    spawn_process (argv, NULL, 0, err);
90e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    if (err)
91e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton        exit_with_errno (err, "posix_spawn x86_64 error");
92e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton#endif
93e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton    return 0;
94e3f9bfdfe3d09ef089f2aef3fb8701c8721f6f45Greg Clayton}
95