]>
Commit | Line | Data |
---|---|---|
fa640ef1 MT |
1 | /*############################################################################# |
2 | # # | |
3 | # Pakfire - The IPFire package management system # | |
4 | # Copyright (C) 2023 Pakfire development team # | |
5 | # # | |
6 | # This program is free software: you can redistribute it and/or modify # | |
7 | # it under the terms of the GNU General Public License as published by # | |
8 | # the Free Software Foundation, either version 3 of the License, or # | |
9 | # (at your option) any later version. # | |
10 | # # | |
11 | # This program is distributed in the hope that it will be useful, # | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
14 | # GNU General Public License for more details. # | |
15 | # # | |
16 | # You should have received a copy of the GNU General Public License # | |
17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
18 | # # | |
19 | #############################################################################*/ | |
20 | ||
21 | #include <errno.h> | |
22 | #include <getopt.h> | |
23 | #include <limits.h> | |
24 | #include <stdio.h> | |
25 | #include <stdlib.h> | |
26 | #include <unistd.h> | |
27 | ||
28 | #include <pakfire/pakfire.h> | |
29 | #include <pakfire/string.h> | |
30 | ||
d20b1a83 | 31 | #include "lib/clean.h" |
2c80538d | 32 | #include "lib/command.h" |
d20b1a83 | 33 | #include "lib/provides.h" |
418f36f6 | 34 | #include "lib/repolist.h" |
d20b1a83 MT |
35 | #include "lib/requires.h" |
36 | #include "lib/search.h" | |
2c80538d MT |
37 | #include "lib/terminal.h" |
38 | #include "lib/version.h" | |
fa640ef1 MT |
39 | |
40 | #define MAX_REPOS 16 | |
41 | ||
42 | struct config { | |
43 | const char* distro; | |
44 | char* arch; | |
45 | int flags; | |
46 | ||
47 | // Repos | |
48 | const char* enable_repos[MAX_REPOS]; | |
49 | unsigned int num_enable_repos; | |
50 | const char* disable_repos[MAX_REPOS]; | |
51 | unsigned int num_disable_repos; | |
52 | }; | |
53 | ||
54 | static int cli_main(struct pakfire* pakfire, int argc, char* argv[]) { | |
55 | static const struct command commands[] = { | |
d20b1a83 MT |
56 | { "clean", 0, cli_clean }, |
57 | { "provides", 0, cli_provides }, | |
58 | { "repolist", 0, cli_repolist }, | |
59 | { "requires", 0, cli_requires }, | |
60 | { "search", 0, cli_search }, | |
fa640ef1 MT |
61 | { NULL }, |
62 | }; | |
63 | ||
64 | return command_dispatch(pakfire, commands, argc, argv); | |
65 | } | |
66 | ||
67 | static void help(void) { | |
68 | printf( | |
69 | "%s [OPTIONS...] COMMAND\n\n" | |
70 | "Options:\n" | |
71 | " -a --arch Run in different architecture\n" | |
3537c6d1 | 72 | " --distro Selects the distribution to compile for\n" |
fa640ef1 MT |
73 | " --debug Run in debug mode\n" |
74 | " -h --help Show help\n" | |
fa640ef1 | 75 | " --version Show version\n" |
fa640ef1 MT |
76 | "\n" |
77 | "Commands:\n" | |
fa640ef1 MT |
78 | " search Search for packages\n" |
79 | " provides Shows which package provides a dependency\n" | |
80 | " requires Shows which package requries a dependency\n" | |
81 | " repolist Show all configured repositories\n" | |
82 | " clean Cleans up no longer needed resources\n", | |
83 | program_invocation_short_name | |
84 | ); | |
85 | ||
86 | exit(0); | |
87 | } | |
88 | ||
89 | static int parse_argv(struct config* config, int argc, char* argv[]) { | |
90 | enum { | |
91 | ARG_DEBUG, | |
92 | ARG_DISTRO, | |
93 | ARG_VERSION, | |
94 | ||
95 | // Repos | |
96 | ARG_ENABLE_REPO, | |
97 | ARG_DISABLE_REPO, | |
98 | }; | |
99 | ||
100 | static const struct option options[] = { | |
101 | { "arch", required_argument, NULL, 'a' }, | |
102 | { "debug", no_argument, NULL, ARG_DEBUG }, | |
103 | { "distro", required_argument, NULL, ARG_DISTRO }, | |
104 | { "help", no_argument, NULL, 'h' }, | |
105 | { "version", no_argument, NULL, ARG_VERSION }, | |
106 | ||
107 | // Repos | |
108 | { "enable-repo", required_argument, NULL, ARG_ENABLE_REPO }, | |
109 | { "disable-repo", required_argument, NULL, ARG_DISABLE_REPO }, | |
110 | { NULL }, | |
111 | }; | |
112 | int c; | |
113 | ||
114 | for (;;) { | |
115 | c = getopt_long(argc, argv, "ah", options, NULL); | |
116 | if (c < 0) | |
117 | break; | |
118 | ||
119 | switch (c) { | |
120 | case 'a': | |
121 | config->arch = optarg; | |
122 | break; | |
123 | ||
124 | case 'h': | |
125 | help(); | |
126 | ||
127 | case ARG_DEBUG: | |
128 | config->flags |= PAKFIRE_FLAGS_DEBUG; | |
129 | break; | |
130 | ||
131 | case ARG_DISTRO: | |
132 | config->distro = optarg; | |
133 | break; | |
134 | ||
135 | case ARG_VERSION: | |
136 | cli_version(); | |
137 | exit(0); | |
138 | ||
139 | case ARG_ENABLE_REPO: | |
140 | if (config->num_enable_repos >= MAX_REPOS) | |
141 | return -ENOBUFS; | |
142 | ||
143 | config->enable_repos[config->num_enable_repos++] = optarg; | |
144 | break; | |
145 | ||
146 | case ARG_DISABLE_REPO: | |
147 | if (config->num_disable_repos >= MAX_REPOS) | |
148 | return -ENOBUFS; | |
149 | ||
150 | config->disable_repos[config->num_disable_repos++] = optarg; | |
151 | break; | |
152 | ||
153 | case '?': | |
154 | return -EINVAL; | |
155 | ||
156 | default: | |
157 | break; | |
158 | } | |
159 | } | |
160 | ||
161 | return 0; | |
162 | } | |
163 | ||
164 | static void cli_set_repo_enabled(struct pakfire* pakfire, const char* name, int enabled) { | |
165 | struct pakfire_repo* repo = NULL; | |
166 | ||
167 | // Find the repository | |
168 | repo = pakfire_get_repo(pakfire, name); | |
169 | ||
170 | // Ignore if the repository could not be found | |
171 | if (!repo) | |
172 | return; | |
173 | ||
174 | // Set status | |
175 | pakfire_repo_set_enabled(repo, enabled); | |
176 | pakfire_repo_unref(repo); | |
177 | } | |
178 | ||
179 | static FILE* open_distro_config(const char* distro) { | |
180 | char path[PATH_MAX]; | |
181 | FILE* f = NULL; | |
182 | int r; | |
183 | ||
184 | // XXX hard-coded path | |
185 | ||
186 | // Make the path | |
187 | r = snprintf(path, sizeof(path), "/etc/pakfire/distros/%s.conf", distro); | |
188 | if (r < 0) | |
189 | return NULL; | |
190 | ||
191 | // Open the configuration file | |
192 | f = fopen(path, "r"); | |
193 | if (!f) { | |
194 | switch (errno) { | |
195 | case ENOENT: | |
196 | fprintf(stderr, "Could not find distro '%s': %m\n", distro); | |
197 | break; | |
198 | ||
199 | default: | |
200 | break; | |
201 | } | |
202 | } | |
203 | ||
204 | return f; | |
205 | } | |
206 | ||
207 | static int setup_pakfire(const struct config* config, struct pakfire** pakfire) { | |
208 | struct pakfire* p = NULL; | |
209 | FILE* f = NULL; | |
210 | int r; | |
211 | ||
212 | // Open the distro configuration | |
213 | f = open_distro_config(config->distro); | |
214 | if (!f) { | |
fa640ef1 MT |
215 | r = 1; |
216 | goto ERROR; | |
217 | } | |
218 | ||
219 | // Initialize Pakfire | |
220 | r = pakfire_create(&p, NULL, config->arch, f, config->flags, NULL, NULL); | |
221 | if (r) | |
222 | goto ERROR; | |
223 | ||
224 | // Enable repositories | |
225 | for (unsigned int i = 0; i < config->num_enable_repos; i++) | |
226 | cli_set_repo_enabled(p, config->enable_repos[i], 1); | |
227 | ||
228 | // Disable repositories | |
229 | for (unsigned int i = 0; i < config->num_disable_repos; i++) | |
230 | cli_set_repo_enabled(p, config->disable_repos[i], 0); | |
231 | ||
232 | // Return pointer | |
233 | *pakfire = p; | |
234 | ||
235 | ERROR: | |
236 | if (f) | |
237 | fclose(f); | |
238 | ||
239 | return r; | |
240 | } | |
241 | ||
242 | int main(int argc, char* argv[]) { | |
243 | struct pakfire* pakfire = NULL; | |
244 | int r; | |
245 | ||
246 | struct config config = { | |
247 | // XXX hard-coded distro | |
248 | .distro = "ipfire3", | |
249 | .arch = NULL, | |
0d54159f | 250 | .flags = PAKFIRE_FLAGS_BUILD, |
fa640ef1 MT |
251 | }; |
252 | ||
253 | // Parse command line arguments | |
254 | r = parse_argv(&config, argc, argv); | |
255 | if (r) | |
256 | goto ERROR; | |
257 | ||
258 | // Setup Pakfire | |
259 | r = setup_pakfire(&config, &pakfire); | |
260 | if (r) | |
261 | goto ERROR; | |
262 | ||
263 | // Run a command | |
264 | r = cli_main(pakfire, argc - optind, argv + optind); | |
265 | ||
266 | ERROR: | |
267 | if (pakfire) | |
268 | pakfire_unref(pakfire); | |
269 | ||
270 | return r; | |
271 | } |