1/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2 *
3 * Copyright (C) 2004 Tresys Technology, LLC
4 *	This program is free software; you can redistribute it and/or modify
5 *  	it under the terms of the GNU General Public License as published by
6 *	the Free Software Foundation, version 2.
7 */
8
9#include <sepol/module.h>
10
11#include <getopt.h>
12#include <fcntl.h>
13#include <stdio.h>
14#include <errno.h>
15#include <sys/mman.h>
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <string.h>
21
22#define LINKPOLICY_VERSION "1.0"
23
24char *progname;
25extern char *optarg;
26extern int optind;
27
28static void usage(char *program_name)
29{
30	printf("usage: %s [-Vv] [-o outfile] basemodpkg modpkg1 [modpkg2]...\n",
31	       program_name);
32	exit(1);
33}
34
35static sepol_module_package_t *load_module(char *filename)
36{
37	int ret;
38	FILE *fp = NULL;
39	struct sepol_policy_file *pf = NULL;
40	sepol_module_package_t *p = NULL;
41
42	if (sepol_module_package_create(&p)) {
43		fprintf(stderr, "%s:  Out of memory\n", progname);
44		goto bad;
45	}
46	if (sepol_policy_file_create(&pf)) {
47		fprintf(stderr, "%s:  Out of memory\n", progname);
48		goto bad;
49	}
50	fp = fopen(filename, "r");
51	if (!fp) {
52		fprintf(stderr, "%s:  Could not open package %s:  %s", progname,
53			filename, strerror(errno));
54		goto bad;
55	}
56	sepol_policy_file_set_fp(pf, fp);
57
58	printf("%s:  loading package from file %s\n", progname, filename);
59
60	ret = sepol_module_package_read(p, pf, 0);
61	if (ret) {
62		fprintf(stderr, "%s:  Error while reading package from %s\n",
63			progname, filename);
64		goto bad;
65	}
66	fclose(fp);
67	sepol_policy_file_free(pf);
68	return p;
69      bad:
70	sepol_module_package_free(p);
71	sepol_policy_file_free(pf);
72	if (fp)
73		fclose(fp);
74	return NULL;
75}
76
77int main(int argc, char **argv)
78{
79	int ch, i, show_version = 0, verbose = 0, num_mods;
80	char *basename, *outname = NULL;
81	sepol_module_package_t *base, **mods;
82	FILE *outfile;
83	struct sepol_policy_file *pf;
84
85	progname = argv[0];
86
87	while ((ch = getopt(argc, argv, "o:Vv")) != EOF) {
88		switch (ch) {
89		case 'V':
90			show_version = 1;
91			break;
92		case 'v':
93			verbose = 1;
94			break;
95		case 'o':
96			outname = optarg;
97			break;
98		default:
99			usage(argv[0]);
100		}
101	}
102
103	if (show_version) {
104		printf("%s\n", LINKPOLICY_VERSION);
105		exit(0);
106	}
107
108	/* check args */
109	if (argc < 3 || !(optind != (argc - 1))) {
110		fprintf(stderr,
111			"%s:  You must provide the base module package and at least one other module package\n",
112			argv[0]);
113		usage(argv[0]);
114	}
115
116	basename = argv[optind++];
117	base = load_module(basename);
118	if (!base) {
119		fprintf(stderr,
120			"%s:  Could not load base module from file %s\n",
121			argv[0], basename);
122		exit(1);
123	}
124
125	num_mods = argc - optind;
126	mods =
127	    (sepol_module_package_t **) malloc(sizeof(sepol_module_package_t *)
128					       * num_mods);
129	if (!mods) {
130		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
131		exit(1);
132	}
133	memset(mods, 0, sizeof(sepol_module_package_t *) * num_mods);
134
135	for (i = 0; optind < argc; optind++, i++) {
136		mods[i] = load_module(argv[optind]);
137		if (!mods[i]) {
138			fprintf(stderr,
139				"%s:  Could not load module from file %s\n",
140				argv[0], argv[optind]);
141			exit(1);
142		}
143	}
144
145	if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) {
146		fprintf(stderr, "%s:  Error while linking packages\n", argv[0]);
147		exit(1);
148	}
149
150	if (outname) {
151		outfile = fopen(outname, "w");
152		if (!outfile) {
153			perror(outname);
154			exit(1);
155		}
156
157		if (sepol_policy_file_create(&pf)) {
158			fprintf(stderr, "%s:  Out of memory\n", argv[0]);
159			exit(1);
160		}
161		sepol_policy_file_set_fp(pf, outfile);
162		if (sepol_module_package_write(base, pf)) {
163			fprintf(stderr, "%s:  Error writing linked package.\n",
164				argv[0]);
165			exit(1);
166		}
167		sepol_policy_file_free(pf);
168		fclose(outfile);
169	}
170
171	sepol_module_package_free(base);
172	for (i = 0; i < num_mods; i++)
173		sepol_module_package_free(mods[i]);
174	free(mods);
175	exit(0);
176}
177