forked from ish-app/ish
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xX_main_Xx.h
123 lines (115 loc) · 3.62 KB
/
xX_main_Xx.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include "kernel/init.h"
#include "kernel/fs.h"
#include "fs/devices.h"
#include "fs/real.h"
#ifdef __APPLE__
#include <sys/resource.h>
#define IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY 1
#define IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE 1
#endif
void real_tty_reset_term(void);
static void exit_handler(struct task *task, int code) {
if (task->parent != NULL)
return;
real_tty_reset_term();
if (code & 0xff)
raise(code & 0xff);
exit(code >> 8);
}
// this function parses command line arguments and initializes global
// data structures. thanks programming discussions discord server for the name.
// https://discord.gg/9zT7NHP
static inline int xX_main_Xx(int argc, char *const argv[], const char *envp) {
#ifdef __APPLE__
// Enable case-sensitive filesystem mode on macOS, if possible.
// In order for this to succeed, either we need to be running as root, or
// be given the com.apple.private.iopol.case_sensitivity entitlement. The
// second option isn't possible so you'll need to give iSH the setuid root
// bit. In that case it's important to drop root permissions ASAP.
// https://worthdoingbadly.com/casesensitive-iossim/
int iopol_err = setiopolicy_np(IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY,
IOPOL_SCOPE_PROCESS,
IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE);
if (iopol_err != 0 && errno != EPERM)
perror("could not enable case sensitivity");
setgid(getgid());
setuid(getuid());
#endif
// parse cli options
int opt;
const char *root = NULL;
const char *workdir = NULL;
const struct fs_ops *fs = &realfs;
const char *console = "/dev/tty1";
while ((opt = getopt(argc, argv, "+r:f:d:c:")) != -1) {
switch (opt) {
case 'r':
case 'f':
root = optarg;
if (opt == 'f')
fs = &fakefs;
break;
case 'd':
workdir = optarg;
break;
case 'c':
console = optarg;
break;
}
}
char root_realpath[MAX_PATH + 1] = "/";
if (root != NULL && realpath(root, root_realpath) == NULL) {
perror(root);
exit(1);
}
if (fs == &fakefs)
strcat(root_realpath, "/data");
int err = mount_root(fs, root_realpath);
if (err < 0)
return err;
become_first_process();
current->thread = pthread_self();
char cwd[MAX_PATH + 1];
if (root == NULL && workdir == NULL) {
getcwd(cwd, sizeof(cwd));
workdir = cwd;
}
if (workdir != NULL) {
struct fd *pwd = generic_open(workdir, O_RDONLY_, 0);
if (IS_ERR(pwd)) {
fprintf(stderr, "error opening working dir: %ld\n", PTR_ERR(pwd));
return 1;
}
fs_chdir(current->fs, pwd);
}
char argv_copy[4096];
int i = optind;
size_t p = 0;
while (i < argc) {
strcpy(&argv_copy[p], argv[i]);
p += strlen(argv[i]) + 1;
i++;
}
argv_copy[p] = '\0';
if (argv[optind] == NULL)
return _ENOENT;
err = do_execve(argv[optind], argc - optind, argv_copy, envp == NULL ? "\0" : envp);
if (err < 0)
return err;
tty_drivers[TTY_CONSOLE_MAJOR] = &real_tty_driver;
if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
err = create_stdio(console, TTY_CONSOLE_MAJOR, 1);
if (err < 0)
return err;
} else {
err = create_piped_stdio();
if (err < 0)
return err;
}
exit_hook = exit_handler;
return 0;
}