-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinfmt.c
98 lines (75 loc) · 1.64 KB
/
binfmt.c
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
/*
* Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
*
* GPL v2
*/
#include <common.h>
#include <binfmt.h>
#include <libbb.h>
#include <malloc.h>
#include <command.h>
#include <errno.h>
static LIST_HEAD(binfmt_hooks);
static int binfmt_run(char *file, int argc, char **argv)
{
struct binfmt_hook *b;
enum filetype type = file_name_detect_type(file);
int ret;
list_for_each_entry(b, &binfmt_hooks, list) {
if (b->type != type)
continue;
ret = b->hook(b, file, argc, argv);
if (ret != -ERESTARTNOHAND)
return ret;
}
return -ENOENT;
}
/*
* This converts the original '/executable <args>' into
* 'barebox_cmd <args> /executable'
*/
static int binfmt_exec_excute(struct binfmt_hook *b, char *file, int argc, char **argv)
{
char **newargv = xzalloc(sizeof(char*) * (argc + 1));
int ret, i;
newargv[0] = b->exec;
for (i = 1 ; i < argc; i++)
newargv[i] = argv[i];
newargv[i] = file;
ret = execute_binfmt(argc + 1, newargv);
free(newargv);
return ret;
}
int execute_binfmt(int argc, char **argv)
{
int ret;
char *path;
if (strchr(argv[0], '/'))
return binfmt_run(argv[0], argc, argv);
if (find_cmd(argv[0]))
return execute_command(argc, &argv[0]);
path = find_execable(argv[0]);
if (path) {
ret = binfmt_run(path, argc, argv);
free(path);
return ret;
}
return -ENOENT;
}
int binfmt_register(struct binfmt_hook *b)
{
if (!b || !b->type)
return -EIO;
if (!b->hook && !b->exec)
return -EIO;
if (b->exec)
b->hook = binfmt_exec_excute;
list_add_tail(&b->list, &binfmt_hooks);
return 0;
}
void binfmt_unregister(struct binfmt_hook *b)
{
if (!b)
return;
list_del(&b->list);
}