Commit | Line | Data |
---|---|---|
1479465f GJ |
1 | /* |
2 | * dpkg-trigger - trigger management utility | |
3 | * | |
4 | * Copyright © 2007 Canonical Ltd. | |
5 | * Written by Ian Jackson <ijackson@chiark.greenend.org.uk> | |
6 | * Copyright © 2008-2014 Guillem Jover <guillem@debian.org> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | |
20 | */ | |
21 | ||
22 | #include <config.h> | |
23 | #include <compat.h> | |
24 | ||
25 | #include <sys/types.h> | |
26 | ||
27 | #include <fcntl.h> | |
28 | #if HAVE_LOCALE_H | |
29 | #include <locale.h> | |
30 | #endif | |
31 | #include <string.h> | |
32 | #include <unistd.h> | |
33 | #include <stdlib.h> | |
34 | #include <stdio.h> | |
35 | ||
36 | #include <dpkg/i18n.h> | |
37 | #include <dpkg/dpkg.h> | |
38 | #include <dpkg/dpkg-db.h> | |
39 | #include <dpkg/options.h> | |
40 | #include <dpkg/trigdeferred.h> | |
41 | #include <dpkg/triglib.h> | |
42 | #include <dpkg/pkg-spec.h> | |
43 | ||
44 | static const char printforhelp[] = N_( | |
45 | "Type dpkg-trigger --help for help about this utility."); | |
46 | ||
47 | static void DPKG_ATTR_NORET | |
48 | printversion(const struct cmdinfo *ci, const char *value) | |
49 | { | |
50 | printf(_("Debian %s package trigger utility version %s.\n"), | |
51 | dpkg_get_progname(), PACKAGE_RELEASE); | |
52 | ||
53 | printf(_( | |
54 | "This is free software; see the GNU General Public License version 2 or\n" | |
55 | "later for copying conditions. There is NO warranty.\n")); | |
56 | ||
57 | m_output(stdout, _("<standard output>")); | |
58 | ||
59 | exit(0); | |
60 | } | |
61 | ||
62 | static void DPKG_ATTR_NORET | |
63 | usage(const struct cmdinfo *ci, const char *value) | |
64 | { | |
65 | printf(_( | |
66 | "Usage: %s [<options> ...] <trigger-name>\n" | |
67 | " %s [<options> ...] <command>\n" | |
68 | "\n"), dpkg_get_progname(), dpkg_get_progname()); | |
69 | ||
70 | printf(_( | |
71 | "Commands:\n" | |
72 | " --check-supported Check if the running dpkg supports triggers.\n" | |
73 | "\n")); | |
74 | ||
75 | printf(_( | |
76 | " -?, --help Show this help message.\n" | |
77 | " --version Show the version.\n" | |
78 | "\n")); | |
79 | ||
80 | printf(_( | |
81 | "Options:\n" | |
82 | " --admindir=<directory> Use <directory> instead of %s.\n" | |
83 | " --by-package=<package> Override trigger awaiter (normally set\n" | |
84 | " by dpkg).\n" | |
85 | " --await Package needs to await the processing.\n" | |
86 | " --no-await No package needs to await the processing.\n" | |
87 | " --no-act Just test - don't actually change anything.\n" | |
88 | "\n"), ADMINDIR); | |
89 | ||
90 | m_output(stdout, _("<standard output>")); | |
91 | ||
92 | exit(0); | |
93 | } | |
94 | ||
95 | static const char *admindir; | |
96 | static int f_noact, f_check; | |
97 | static int f_await = 1; | |
98 | ||
99 | static const char *bypackage, *activate; | |
100 | static bool done_trig, ctrig; | |
101 | ||
102 | static void | |
103 | yespackage(const char *awname) | |
104 | { | |
105 | trigdef_update_printf(" %s", awname); | |
106 | } | |
107 | ||
108 | static const char * | |
109 | parse_awaiter_package(void) | |
110 | { | |
111 | struct dpkg_error err = DPKG_ERROR_INIT; | |
112 | struct pkginfo *pkg; | |
113 | ||
114 | if (!f_await) | |
115 | bypackage = "-"; | |
116 | ||
117 | if (bypackage == NULL) { | |
118 | const char *pkgname, *archname; | |
119 | ||
120 | pkgname = getenv("DPKG_MAINTSCRIPT_PACKAGE"); | |
121 | archname = getenv("DPKG_MAINTSCRIPT_ARCH"); | |
122 | if (pkgname == NULL || archname == NULL) | |
123 | badusage(_("must be called from a maintainer script" | |
124 | " (or with a --by-package option)")); | |
125 | ||
126 | pkg = pkg_spec_find_pkg(pkgname, archname, &err); | |
127 | } else if (strcmp(bypackage, "-") == 0) { | |
128 | pkg = NULL; | |
129 | } else { | |
130 | pkg = pkg_spec_parse_pkg(bypackage, &err); | |
131 | } | |
132 | ||
133 | /* Normalize the bypackage name if there was no error. */ | |
134 | if (pkg) | |
135 | bypackage = pkg_name(pkg, pnaw_nonambig); | |
136 | ||
137 | return err.str; | |
138 | } | |
139 | ||
140 | static void | |
141 | tdm_add_trig_begin(const char *trig) | |
142 | { | |
143 | ctrig = strcmp(trig, activate) == 0; | |
144 | trigdef_update_printf("%s", trig); | |
145 | if (!ctrig || done_trig) | |
146 | return; | |
147 | yespackage(bypackage); | |
148 | done_trig = true; | |
149 | } | |
150 | ||
151 | static void | |
152 | tdm_add_package(const char *awname) | |
153 | { | |
154 | if (ctrig && strcmp(awname, bypackage) == 0) | |
155 | return; | |
156 | yespackage(awname); | |
157 | } | |
158 | ||
159 | static void | |
160 | tdm_add_trig_end(void) | |
161 | { | |
162 | trigdef_update_printf("\n"); | |
163 | } | |
164 | ||
165 | static const struct trigdefmeths tdm_add = { | |
166 | .trig_begin = tdm_add_trig_begin, | |
167 | .package = tdm_add_package, | |
168 | .trig_end = tdm_add_trig_end, | |
169 | }; | |
170 | ||
171 | static int | |
172 | do_check(void) | |
173 | { | |
174 | enum trigdef_update_status uf; | |
175 | ||
176 | uf = trigdef_update_start(TDUF_NO_LOCK_OK); | |
177 | switch (uf) { | |
178 | case TDUS_ERROR_NO_DIR: | |
179 | notice(_("triggers data directory not yet created")); | |
180 | return 1; | |
181 | case TDUS_ERROR_NO_DEFERRED: | |
182 | notice(_("trigger records not yet in existence")); | |
183 | return 1; | |
184 | case TDUS_OK: | |
185 | case TDUS_ERROR_EMPTY_DEFERRED: | |
186 | return 0; | |
187 | default: | |
188 | internerr("unknown trigdef_update_start return value '%d'", uf); | |
189 | } | |
190 | } | |
191 | ||
192 | static const struct cmdinfo cmdinfos[] = { | |
193 | { "admindir", 0, 1, NULL, &admindir }, | |
194 | { "by-package", 'f', 1, NULL, &bypackage }, | |
195 | { "await", 0, 0, &f_await, NULL, NULL, 1 }, | |
196 | { "no-await", 0, 0, &f_await, NULL, NULL, 0 }, | |
197 | { "no-act", 0, 0, &f_noact, NULL, NULL, 1 }, | |
198 | { "check-supported", 0, 0, &f_check, NULL, NULL, 1 }, | |
199 | { "help", '?', 0, NULL, NULL, usage }, | |
200 | { "version", 0, 0, NULL, NULL, printversion }, | |
201 | { NULL } | |
202 | }; | |
203 | ||
204 | int | |
205 | main(int argc, const char *const *argv) | |
206 | { | |
207 | const char *badname; | |
208 | enum trigdef_update_flags tduf; | |
209 | enum trigdef_update_status tdus; | |
210 | ||
211 | dpkg_locales_init(PACKAGE); | |
212 | dpkg_program_init("dpkg-trigger"); | |
213 | dpkg_options_parse(&argv, cmdinfos, printforhelp); | |
214 | ||
215 | admindir = dpkg_db_set_dir(admindir); | |
216 | ||
217 | if (f_check) { | |
218 | if (*argv) | |
219 | badusage(_("--%s takes no arguments"), | |
220 | "check-supported"); | |
221 | return do_check(); | |
222 | } | |
223 | ||
224 | if (!*argv || argv[1]) | |
225 | badusage(_("takes one argument, the trigger name")); | |
226 | ||
227 | badname = parse_awaiter_package(); | |
228 | if (badname) | |
229 | badusage(_("illegal awaited package name '%.250s': %.250s"), | |
230 | bypackage, badname); | |
231 | ||
232 | activate = argv[0]; | |
233 | badname = trig_name_is_illegal(activate); | |
234 | if (badname) | |
235 | badusage(_("invalid trigger name '%.250s': %.250s"), | |
236 | activate, badname); | |
237 | ||
238 | trigdef_set_methods(&tdm_add); | |
239 | ||
240 | tduf = TDUF_NO_LOCK_OK; | |
241 | if (!f_noact) | |
242 | tduf |= TDUF_WRITE | TDUF_WRITE_IF_EMPTY; | |
243 | tdus = trigdef_update_start(tduf); | |
244 | if (tdus >= 0) { | |
245 | trigdef_parse(); | |
246 | if (!done_trig) | |
247 | trigdef_update_printf("%s %s\n", activate, bypackage); | |
248 | trigdef_process_done(); | |
249 | } | |
250 | ||
251 | dpkg_program_done(); | |
252 | ||
253 | return 0; | |
254 | } |