]>
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 | ||
817f7557 | 31 | #include "lib/assert.h" |
060a1182 | 32 | #include "lib/build.h" |
d20b1a83 | 33 | #include "lib/clean.h" |
2c80538d | 34 | #include "lib/command.h" |
5f9bc3d2 | 35 | #include "lib/dist.h" |
0a333c90 | 36 | #include "lib/image.h" |
ecdd76bd | 37 | #include "lib/info.h" |
32bbeefc | 38 | #include "lib/progressbar.h" |
d20b1a83 | 39 | #include "lib/provides.h" |
3467dd08 | 40 | #include "lib/repo.h" |
418f36f6 | 41 | #include "lib/repolist.h" |
d20b1a83 | 42 | #include "lib/requires.h" |
beee2bda | 43 | #include "lib/shell.h" |
d20b1a83 | 44 | #include "lib/search.h" |
2c80538d MT |
45 | #include "lib/terminal.h" |
46 | #include "lib/version.h" | |
fa640ef1 MT |
47 | |
48 | #define MAX_REPOS 16 | |
49 | ||
50 | struct config { | |
51 | const char* distro; | |
52 | char* arch; | |
53 | int flags; | |
54 | ||
55 | // Repos | |
56 | const char* enable_repos[MAX_REPOS]; | |
57 | unsigned int num_enable_repos; | |
58 | const char* disable_repos[MAX_REPOS]; | |
59 | unsigned int num_disable_repos; | |
60 | }; | |
61 | ||
62 | static int cli_main(struct pakfire* pakfire, int argc, char* argv[]) { | |
63 | static const struct command commands[] = { | |
060a1182 | 64 | { "build", 0, cli_build }, |
d20b1a83 | 65 | { "clean", 0, cli_clean }, |
5f9bc3d2 | 66 | { "dist", 0, cli_dist }, |
0a333c90 | 67 | { "image", 0, cli_image }, |
ecdd76bd | 68 | { "info", 0, cli_info }, |
d20b1a83 | 69 | { "provides", 0, cli_provides }, |
3467dd08 | 70 | { "repo", 0, cli_repo }, |
d20b1a83 MT |
71 | { "repolist", 0, cli_repolist }, |
72 | { "requires", 0, cli_requires }, | |
beee2bda | 73 | { "shell", 0, cli_shell }, |
d20b1a83 | 74 | { "search", 0, cli_search }, |
fa640ef1 MT |
75 | { NULL }, |
76 | }; | |
77 | ||
78 | return command_dispatch(pakfire, commands, argc, argv); | |
79 | } | |
80 | ||
81 | static void help(void) { | |
82 | printf( | |
83 | "%s [OPTIONS...] COMMAND\n\n" | |
84 | "Options:\n" | |
85 | " -a --arch Run in different architecture\n" | |
3537c6d1 | 86 | " --distro Selects the distribution to compile for\n" |
fa640ef1 MT |
87 | " --debug Run in debug mode\n" |
88 | " -h --help Show help\n" | |
fa640ef1 | 89 | " --version Show version\n" |
fa640ef1 MT |
90 | "\n" |
91 | "Commands:\n" | |
fa640ef1 MT |
92 | " search Search for packages\n" |
93 | " provides Shows which package provides a dependency\n" | |
94 | " requires Shows which package requries a dependency\n" | |
95 | " repolist Show all configured repositories\n" | |
96 | " clean Cleans up no longer needed resources\n", | |
97 | program_invocation_short_name | |
98 | ); | |
99 | ||
100 | exit(0); | |
101 | } | |
102 | ||
103 | static int parse_argv(struct config* config, int argc, char* argv[]) { | |
104 | enum { | |
105 | ARG_DEBUG, | |
106 | ARG_DISTRO, | |
107 | ARG_VERSION, | |
108 | ||
109 | // Repos | |
110 | ARG_ENABLE_REPO, | |
111 | ARG_DISABLE_REPO, | |
112 | }; | |
113 | ||
114 | static const struct option options[] = { | |
115 | { "arch", required_argument, NULL, 'a' }, | |
116 | { "debug", no_argument, NULL, ARG_DEBUG }, | |
117 | { "distro", required_argument, NULL, ARG_DISTRO }, | |
118 | { "help", no_argument, NULL, 'h' }, | |
119 | { "version", no_argument, NULL, ARG_VERSION }, | |
120 | ||
121 | // Repos | |
122 | { "enable-repo", required_argument, NULL, ARG_ENABLE_REPO }, | |
123 | { "disable-repo", required_argument, NULL, ARG_DISABLE_REPO }, | |
124 | { NULL }, | |
125 | }; | |
126 | int c; | |
127 | ||
128 | for (;;) { | |
129 | c = getopt_long(argc, argv, "ah", options, NULL); | |
130 | if (c < 0) | |
131 | break; | |
132 | ||
133 | switch (c) { | |
134 | case 'a': | |
135 | config->arch = optarg; | |
136 | break; | |
137 | ||
138 | case 'h': | |
139 | help(); | |
140 | ||
141 | case ARG_DEBUG: | |
142 | config->flags |= PAKFIRE_FLAGS_DEBUG; | |
143 | break; | |
144 | ||
145 | case ARG_DISTRO: | |
146 | config->distro = optarg; | |
147 | break; | |
148 | ||
149 | case ARG_VERSION: | |
150 | cli_version(); | |
151 | exit(0); | |
152 | ||
153 | case ARG_ENABLE_REPO: | |
154 | if (config->num_enable_repos >= MAX_REPOS) | |
155 | return -ENOBUFS; | |
156 | ||
157 | config->enable_repos[config->num_enable_repos++] = optarg; | |
158 | break; | |
159 | ||
160 | case ARG_DISABLE_REPO: | |
161 | if (config->num_disable_repos >= MAX_REPOS) | |
162 | return -ENOBUFS; | |
163 | ||
164 | config->disable_repos[config->num_disable_repos++] = optarg; | |
165 | break; | |
166 | ||
167 | case '?': | |
101b03bb | 168 | break; |
fa640ef1 MT |
169 | |
170 | default: | |
817f7557 | 171 | assert_unreachable(); |
fa640ef1 MT |
172 | } |
173 | } | |
174 | ||
175 | return 0; | |
176 | } | |
177 | ||
178 | static void cli_set_repo_enabled(struct pakfire* pakfire, const char* name, int enabled) { | |
179 | struct pakfire_repo* repo = NULL; | |
180 | ||
181 | // Find the repository | |
182 | repo = pakfire_get_repo(pakfire, name); | |
183 | ||
184 | // Ignore if the repository could not be found | |
185 | if (!repo) | |
186 | return; | |
187 | ||
188 | // Set status | |
189 | pakfire_repo_set_enabled(repo, enabled); | |
190 | pakfire_repo_unref(repo); | |
191 | } | |
192 | ||
193 | static FILE* open_distro_config(const char* distro) { | |
194 | char path[PATH_MAX]; | |
195 | FILE* f = NULL; | |
196 | int r; | |
197 | ||
198 | // XXX hard-coded path | |
199 | ||
200 | // Make the path | |
201 | r = snprintf(path, sizeof(path), "/etc/pakfire/distros/%s.conf", distro); | |
202 | if (r < 0) | |
203 | return NULL; | |
204 | ||
205 | // Open the configuration file | |
206 | f = fopen(path, "r"); | |
207 | if (!f) { | |
208 | switch (errno) { | |
209 | case ENOENT: | |
210 | fprintf(stderr, "Could not find distro '%s': %m\n", distro); | |
211 | break; | |
212 | ||
213 | default: | |
214 | break; | |
215 | } | |
216 | } | |
217 | ||
218 | return f; | |
219 | } | |
220 | ||
221 | static int setup_pakfire(const struct config* config, struct pakfire** pakfire) { | |
222 | struct pakfire* p = NULL; | |
223 | FILE* f = NULL; | |
224 | int r; | |
225 | ||
226 | // Open the distro configuration | |
227 | f = open_distro_config(config->distro); | |
228 | if (!f) { | |
fa640ef1 MT |
229 | r = 1; |
230 | goto ERROR; | |
231 | } | |
232 | ||
233 | // Initialize Pakfire | |
234 | r = pakfire_create(&p, NULL, config->arch, f, config->flags, NULL, NULL); | |
235 | if (r) | |
236 | goto ERROR; | |
237 | ||
32bbeefc MT |
238 | // Setup progress callback |
239 | pakfire_set_setup_progress_callback(p, cli_setup_progressbar, NULL); | |
240 | ||
fa640ef1 MT |
241 | // Enable repositories |
242 | for (unsigned int i = 0; i < config->num_enable_repos; i++) | |
243 | cli_set_repo_enabled(p, config->enable_repos[i], 1); | |
244 | ||
245 | // Disable repositories | |
246 | for (unsigned int i = 0; i < config->num_disable_repos; i++) | |
247 | cli_set_repo_enabled(p, config->disable_repos[i], 0); | |
248 | ||
249 | // Return pointer | |
250 | *pakfire = p; | |
251 | ||
252 | ERROR: | |
253 | if (f) | |
254 | fclose(f); | |
255 | ||
256 | return r; | |
257 | } | |
258 | ||
259 | int main(int argc, char* argv[]) { | |
260 | struct pakfire* pakfire = NULL; | |
261 | int r; | |
262 | ||
263 | struct config config = { | |
264 | // XXX hard-coded distro | |
265 | .distro = "ipfire3", | |
266 | .arch = NULL, | |
0d54159f | 267 | .flags = PAKFIRE_FLAGS_BUILD, |
fa640ef1 MT |
268 | }; |
269 | ||
270 | // Parse command line arguments | |
271 | r = parse_argv(&config, argc, argv); | |
272 | if (r) | |
273 | goto ERROR; | |
274 | ||
275 | // Setup Pakfire | |
276 | r = setup_pakfire(&config, &pakfire); | |
277 | if (r) | |
278 | goto ERROR; | |
279 | ||
280 | // Run a command | |
101b03bb | 281 | r = cli_main(pakfire, argc, argv); |
fa640ef1 MT |
282 | |
283 | ERROR: | |
284 | if (pakfire) | |
285 | pakfire_unref(pakfire); | |
286 | ||
287 | return r; | |
288 | } |