a85d3e
driver, library interfaces: support alternate fd's for input/output/error/log.
@@ -126,6 +126,15 @@ struct pe_source_version {
|
|
126
126
|
const char * commit;
|
127
127
|
};
|
128
128
|
|
129
|
+
struct pe_fd_ctx {
|
130
|
+
int fdin;
|
131
|
+
int fdout;
|
132
|
+
int fderr;
|
133
|
+
int fdlog;
|
134
|
+
int fdcwd;
|
135
|
+
int fddst;
|
136
|
+
};
|
137
|
+
|
129
138
|
struct pe_error_info {
|
130
139
|
const struct pe_driver_ctx * edctx;
|
131
140
|
const struct pe_unit_ctx * euctx;
|
@@ -166,6 +175,7 @@ struct pe_info_string {
|
|
166
175
|
|
167
176
|
/* driver api */
|
168
177
|
perk_api int pe_get_driver_ctx (char ** argv, char ** envp, uint32_t flags,
|
178
|
+
const struct pe_fd_ctx *,
|
169
179
|
struct pe_driver_ctx **);
|
170
180
|
|
171
181
|
perk_api void pe_free_driver_ctx (struct pe_driver_ctx *);
|
@@ -175,8 +185,12 @@ perk_api int pe_get_unit_ctx (const struct pe_driver_ctx *, const cha
|
|
175
185
|
|
176
186
|
perk_api void pe_free_unit_ctx (struct pe_unit_ctx *);
|
177
187
|
|
188
|
+
perk_api int pe_get_driver_fdctx (const struct pe_driver_ctx *, struct pe_fd_ctx *);
|
189
|
+
perk_api int pe_set_driver_fdctx (struct pe_driver_ctx *, const struct pe_fd_ctx *);
|
190
|
+
|
178
191
|
/* utility api */
|
179
|
-
perk_api int pe_main (int, char **, char
|
192
|
+
perk_api int pe_main (int, char **, char **, const struct pe_fd_ctx *);
|
193
|
+
|
180
194
|
perk_api int pe_output_image_category (const struct pe_driver_ctx *, const struct pe_image_meta *, FILE *);
|
181
195
|
perk_api int pe_output_image_sections (const struct pe_driver_ctx *, const struct pe_image_meta *, FILE *);
|
182
196
|
perk_api int pe_output_image_symbols (const struct pe_driver_ctx *, const struct pe_image_meta *, FILE *);
|
@@ -9,6 +9,7 @@
|
|
9
9
|
|
10
10
|
|
11
11
|
|
12
|
+
|
12
13
|
|
13
14
|
|
14
15
|
|
@@ -31,15 +32,16 @@ static const char * const pe_ver_plain[6] = {
|
|
31
32
|
"",""
|
32
33
|
};
|
33
34
|
|
34
|
-
static ssize_t pe_version(struct pe_driver_ctx * dctx)
|
35
|
+
static ssize_t pe_version(int fdout, struct pe_driver_ctx * dctx)
|
35
36
|
{
|
36
37
|
const struct pe_source_version * verinfo;
|
37
38
|
const char * const * verclr;
|
38
39
|
|
39
40
|
verinfo = pe_source_version();
|
40
|
-
verclr = isatty(
|
41
|
+
verclr = isatty(fdout) ? pe_ver_color : pe_ver_plain;
|
41
42
|
|
42
|
-
return
|
43
|
+
return pe_dprintf(
|
44
|
+
fdout,vermsg,
|
43
45
|
verclr[0],dctx->program,verclr[1],
|
44
46
|
verclr[2],verinfo->major,verinfo->minor,
|
45
47
|
verinfo->revision,verclr[3],
|
@@ -81,20 +83,25 @@ static int pe_exit(struct pe_driver_ctx * dctx, int ret)
|
|
81
83
|
return ret;
|
82
84
|
}
|
83
85
|
|
84
|
-
int pe_main(int argc, char ** argv, char ** envp)
|
86
|
+
int pe_main(int argc, char ** argv, char ** envp, const struct pe_fd_ctx * fdctx)
|
85
87
|
{
|
86
88
|
int ret;
|
89
|
+
int fdout;
|
90
|
+
uint64_t flags;
|
87
91
|
struct pe_driver_ctx * dctx;
|
88
92
|
struct pe_unit_ctx * uctx;
|
89
93
|
const char ** unit;
|
90
94
|
|
91
|
-
|
95
|
+
flags = PERK_DRIVER_FLAGS;
|
96
|
+
fdout = fdctx ? fdctx->fdout : STDOUT_FILENO;
|
97
|
+
|
98
|
+
if ((ret = pe_get_driver_ctx(argv,envp,flags,fdctx,&dctx)))
|
92
99
|
return (ret == PERK_USAGE)
|
93
100
|
? !--argc
|
94
101
|
: PERK_ERROR;
|
95
102
|
|
96
103
|
if (dctx->cctx->drvflags & PERK_DRIVER_VERSION)
|
97
|
-
if ((pe_version(dctx)) < 0)
|
104
|
+
if ((pe_version(fdout,dctx)) < 0)
|
98
105
|
return pe_exit(dctx,PERK_ERROR);
|
99
106
|
|
100
107
|
for (unit=dctx->units; *unit; unit++) {
|
@@ -48,6 +48,7 @@ static uint32_t pe_argv_flags(uint32_t flags)
|
|
48
48
|
}
|
49
49
|
|
50
50
|
static int pe_driver_usage(
|
51
|
+
int fdout,
|
51
52
|
const char * program,
|
52
53
|
const char * arg,
|
53
54
|
const struct argv_option ** optv,
|
@@ -59,7 +60,7 @@ static int pe_driver_usage(
|
|
59
60
|
"Usage: %s [options] <file>...\n" "Options:\n",
|
60
61
|
program);
|
61
62
|
|
62
|
-
argv_usage(
|
63
|
+
argv_usage(fdout,header,optv,arg);
|
63
64
|
argv_free(meta);
|
64
65
|
|
65
66
|
return PERK_USAGE;
|
@@ -67,6 +68,7 @@ static int pe_driver_usage(
|
|
67
68
|
|
68
69
|
static struct pe_driver_ctx_impl * pe_driver_ctx_alloc(
|
69
70
|
struct argv_meta * meta,
|
71
|
+
const struct pe_fd_ctx * fdctx,
|
70
72
|
const struct pe_common_ctx * cctx,
|
71
73
|
size_t nunits)
|
72
74
|
{
|
@@ -82,8 +84,8 @@ static struct pe_driver_ctx_impl * pe_driver_ctx_alloc(
|
|
82
84
|
if (!(ictx = calloc(1,size)))
|
83
85
|
return 0;
|
84
86
|
|
85
|
-
|
86
|
-
|
87
|
+
memcpy(&ictx->ctx.fdctx,fdctx,sizeof(*fdctx));
|
88
|
+
memcpy(&ictx->ctx.cctx,cctx,sizeof(*cctx));
|
87
89
|
|
88
90
|
elements = sizeof(ictx->ctx.erribuf) / sizeof(*ictx->ctx.erribuf);
|
89
91
|
|
@@ -108,10 +110,11 @@ static int pe_get_driver_ctx_fail(struct argv_meta * meta)
|
|
108
110
|
}
|
109
111
|
|
110
112
|
int pe_get_driver_ctx(
|
111
|
-
char **
|
112
|
-
char **
|
113
|
-
uint32_t
|
114
|
-
struct
|
113
|
+
char ** argv,
|
114
|
+
char ** envp,
|
115
|
+
uint32_t flags,
|
116
|
+
const struct pe_fd_ctx * fdctx,
|
117
|
+
struct pe_driver_ctx ** pctx)
|
115
118
|
{
|
116
119
|
struct pe_driver_ctx_impl * ctx;
|
117
120
|
struct pe_common_ctx cctx;
|
@@ -124,6 +127,17 @@ int pe_get_driver_ctx(
|
|
124
127
|
|
125
128
|
(void)envp;
|
126
129
|
|
130
|
+
if (!fdctx) {
|
131
|
+
fdctx = &(const struct pe_fd_ctx) {
|
132
|
+
.fdin = STDIN_FILENO,
|
133
|
+
.fdout = STDOUT_FILENO,
|
134
|
+
.fderr = STDERR_FILENO,
|
135
|
+
.fdlog = (-1),
|
136
|
+
.fdcwd = AT_FDCWD,
|
137
|
+
.fddst = AT_FDCWD,
|
138
|
+
};
|
139
|
+
}
|
140
|
+
|
127
141
|
argv_optv_init(pe_default_options,optv);
|
128
142
|
|
129
143
|
if (!(meta = argv_get(
|
@@ -139,7 +153,10 @@ int pe_get_driver_ctx(
|
|
139
153
|
cctx.drvflags = flags;
|
140
154
|
|
141
155
|
if (!argv[1] && (flags & PERK_DRIVER_VERBOSITY_USAGE))
|
142
|
-
return pe_driver_usage(
|
156
|
+
return pe_driver_usage(
|
157
|
+
fdctx->fderr,
|
158
|
+
program,
|
159
|
+
0,optv,meta);
|
143
160
|
|
144
161
|
/* get options, count units */
|
145
162
|
for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
|
@@ -147,7 +164,10 @@ int pe_get_driver_ctx(
|
|
147
164
|
switch (entry->tag) {
|
148
165
|
case TAG_HELP:
|
149
166
|
if (flags & PERK_DRIVER_VERBOSITY_USAGE)
|
150
|
-
return pe_driver_usage(
|
167
|
+
return pe_driver_usage(
|
168
|
+
fdctx->fdout,
|
169
|
+
program,entry->arg,
|
170
|
+
optv,meta);
|
151
171
|
|
152
172
|
case TAG_VERSION:
|
153
173
|
cctx.drvflags |= PERK_DRIVER_VERSION;
|
@@ -202,7 +222,7 @@ int pe_get_driver_ctx(
|
|
202
222
|
else if (pretty && !strcmp(pretty,"dlltool"))
|
203
223
|
cctx.fmtflags |= PERK_PRETTY_DLLTOOL;
|
204
224
|
|
205
|
-
if (!(ctx = pe_driver_ctx_alloc(meta,&cctx,nunits)))
|
225
|
+
if (!(ctx = pe_driver_ctx_alloc(meta,fdctx,&cctx,nunits)))
|
206
226
|
return pe_get_driver_ctx_fail(meta);
|
207
227
|
|
208
228
|
ctx->ctx.program = program;
|
@@ -235,3 +255,39 @@ const struct pe_source_version * pe_source_version(void)
|
|
235
255
|
{
|
236
256
|
return &pe_src_version;
|
237
257
|
}
|
258
|
+
|
259
|
+
int pe_get_driver_fdctx(
|
260
|
+
const struct pe_driver_ctx * dctx,
|
261
|
+
struct pe_fd_ctx * fdctx)
|
262
|
+
{
|
263
|
+
struct pe_driver_ctx_impl * ictx;
|
264
|
+
|
265
|
+
ictx = pe_get_driver_ictx(dctx);
|
266
|
+
|
267
|
+
fdctx->fdin = ictx->fdctx.fdin;
|
268
|
+
fdctx->fdout = ictx->fdctx.fdout;
|
269
|
+
fdctx->fderr = ictx->fdctx.fderr;
|
270
|
+
fdctx->fdlog = ictx->fdctx.fdlog;
|
271
|
+
fdctx->fdcwd = ictx->fdctx.fdcwd;
|
272
|
+
fdctx->fddst = ictx->fdctx.fddst;
|
273
|
+
|
274
|
+
return 0;
|
275
|
+
}
|
276
|
+
|
277
|
+
int pe_set_driver_fdctx(
|
278
|
+
struct pe_driver_ctx * dctx,
|
279
|
+
const struct pe_fd_ctx * fdctx)
|
280
|
+
{
|
281
|
+
struct pe_driver_ctx_impl * ictx;
|
282
|
+
|
283
|
+
ictx = pe_get_driver_ictx(dctx);
|
284
|
+
|
285
|
+
ictx->fdctx.fdin = fdctx->fdin;
|
286
|
+
ictx->fdctx.fdout = fdctx->fdout;
|
287
|
+
ictx->fdctx.fderr = fdctx->fderr;
|
288
|
+
ictx->fdctx.fdlog = fdctx->fdlog;
|
289
|
+
ictx->fdctx.fdcwd = fdctx->fdcwd;
|
290
|
+
ictx->fdctx.fddst = fdctx->fddst;
|
291
|
+
|
292
|
+
return 0;
|
293
|
+
}
|
@@ -32,6 +32,7 @@ enum app_tags {
|
|
32
32
|
struct pe_driver_ctx_impl {
|
33
33
|
struct pe_common_ctx cctx;
|
34
34
|
struct pe_driver_ctx ctx;
|
35
|
+
struct pe_fd_ctx fdctx;
|
35
36
|
const struct pe_unit_ctx * euctx;
|
36
37
|
const char * eunit;
|
37
38
|
struct pe_error_info ** errinfp;
|
@@ -73,4 +74,46 @@ static inline void pe_driver_set_ectx(
|
|
73
74
|
ictx->eunit = unit;
|
74
75
|
}
|
75
76
|
|
77
|
+
static inline int pe_driver_fdin(const struct pe_driver_ctx * dctx)
|
78
|
+
{
|
79
|
+
struct pe_fd_ctx fdctx;
|
80
|
+
pe_get_driver_fdctx(dctx,&fdctx);
|
81
|
+
return fdctx.fdin;
|
82
|
+
}
|
83
|
+
|
84
|
+
static inline int pe_driver_fdout(const struct pe_driver_ctx * dctx)
|
85
|
+
{
|
86
|
+
struct pe_fd_ctx fdctx;
|
87
|
+
pe_get_driver_fdctx(dctx,&fdctx);
|
88
|
+
return fdctx.fdout;
|
89
|
+
}
|
90
|
+
|
91
|
+
static inline int pe_driver_fderr(const struct pe_driver_ctx * dctx)
|
92
|
+
{
|
93
|
+
struct pe_fd_ctx fdctx;
|
94
|
+
pe_get_driver_fdctx(dctx,&fdctx);
|
95
|
+
return fdctx.fderr;
|
96
|
+
}
|
97
|
+
|
98
|
+
static inline int pe_driver_fdlog(const struct pe_driver_ctx * dctx)
|
99
|
+
{
|
100
|
+
struct pe_fd_ctx fdctx;
|
101
|
+
pe_get_driver_fdctx(dctx,&fdctx);
|
102
|
+
return fdctx.fdlog;
|
103
|
+
}
|
104
|
+
|
105
|
+
static inline int pe_driver_fdcwd(const struct pe_driver_ctx * dctx)
|
106
|
+
{
|
107
|
+
struct pe_fd_ctx fdctx;
|
108
|
+
pe_get_driver_fdctx(dctx,&fdctx);
|
109
|
+
return fdctx.fdcwd;
|
110
|
+
}
|
111
|
+
|
112
|
+
static inline int pe_driver_fddst(const struct pe_driver_ctx * dctx)
|
113
|
+
{
|
114
|
+
struct pe_fd_ctx fdctx;
|
115
|
+
pe_get_driver_fdctx(dctx,&fdctx);
|
116
|
+
return fdctx.fddst;
|
117
|
+
}
|
118
|
+
|
76
119
|
|
@@ -8,5 +8,5 @@
|
|
8
8
|
|
9
9
|
int main(int argc, char ** argv, char ** envp)
|
10
10
|
{
|
11
|
-
return pe_main(argc,argv,envp);
|
11
|
+
return pe_main(argc,argv,envp,0);
|
12
12
|
}
|