summaryrefslogtreecommitdiffhomepage
path: root/src/main/perk.c
blob: 94be2944924b8be66cef0f010ebdbef18313ad7f (plain)
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
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <perk/perk.h>
#include "perk_impl.h"

static int perk_parse_opts(struct perk_ctx * ctx)
{
	int		i;
	char *		ch;
	const char **	popt;

	for (i=1; i<ctx->argc; i++) {
		ch = ctx->argv[i];

		if (*ch == '-') {
			switch (*++ch) {
				case 'i':
					popt = &ctx->fname;
					break;
				case 'h':
					ctx->flags = PERK_HELP;
					return 0;
				default:
					ctx->status = PERK_BAD_OPT;
					return ctx->status;
			}

			while ((*++ch == '\t') || (*ch == ' '));

			if (!*ch) {
				if (++i < ctx->argc)
					*popt = ctx->argv[i];
				else
					ctx->status = PERK_BAD_OPT_VAL;
			} else
				*popt = ch;
		} else if (!ctx->fname)
			ctx->fname = ch;
		else
			ctx->status = PERK_BAD_OPT;

	}

	return ctx->status;
}


static int perk_map_input(struct perk_ctx * ctx)
{
	ctx->fd = open(ctx->fname,O_RDONLY | O_CLOEXEC);

	if (ctx->fd < 0) {
		ctx->status = PERK_IO_ERROR;
		return ctx->status;
	}

	ctx->status = pe_map_raw_image(ctx->fd,0,PROT_READ,&ctx->map);

	return ctx->status;
}


static int perk_exit(struct perk_ctx * ctx)
{
	if (ctx->map.addr)
		pe_unmap_raw_image(&ctx->map);

	return ctx->status;
}


static int perk_run(struct perk_ctx * ctx)
{
	struct pe_image_meta * meta;

	if (perk_map_input(ctx))
		return perk_exit(ctx);

	if ((ctx->status = pe_get_image_meta(&ctx->map,&meta)))
		return perk_exit(ctx);

	/* pre-alpha default output */
	pe_output_export_symbols(
		meta,
		PERK_OUTPUT_FORMAT_LIST | PERK_OUTPUT_FIELD_NAME,
		stdout);

	ctx->status = pe_free_image_meta(meta);

	return perk_exit(ctx);
}

static int perk_main(int argc, char * argv[], char * envp[])
{
	struct perk_ctx ctx = {argc,argv,envp};

	if (perk_parse_opts(&ctx))
		return ctx.status;
	else
		return perk_run(&ctx);
}

#ifdef PERK_APP
__typeof(perk_main) main __attribute__((alias("perk_main")));
#endif