1 /** \ingroup rpmcli
2  * \file lib/poptALL.c
3  *  Popt tables for all rpm modes.
4  */
5 
6 #include "system.h"
7 
8 #include <rpm/rpmcli.h>
9 #include <rpm/rpmlib.h>		/* rpmEVR, rpmReadConfigFiles etc */
10 #include <rpm/rpmlog.h>
11 #include <rpm/rpmstring.h>
12 #include <rpm/rpmfileutil.h>
13 
14 #include "debug.h"
15 
16 #define POPT_SHOWVERSION	-999
17 #define POPT_SHOWRC		-998
18 #define POPT_QUERYTAGS		-997
19 #define POPT_PREDEFINE		-996
20 #define POPT_DBPATH		-995
21 #define POPT_UNDEFINE		-994
22 #define POPT_PIPE		-993
23 #define POPT_LOAD		-992
24 
25 static int _debug = 0;
26 
27 extern int _rpm_nouserns;
28 
29 extern int _fsm_debug;
30 
31 extern int _print_pkts;
32 
33 extern int _psm_debug;
34 
35 /* XXX avoid -lrpmbuild linkage. */
36        int _rpmfc_debug;
37 
38 extern int _rpmts_stats;
39 
40 const char * rpmcliPipeOutput = NULL;
41 
42 const char * rpmcliRcfile = NULL;
43 
44 const char * rpmcliRootDir = "/";
45 
46 rpmQueryFlags rpmcliQueryFlags;
47 
48 rpmVSFlags rpmcliVSFlags;
49 
50 int rpmcliVfyLevelMask;
51 
52 extern int _rpmio_debug;
53 
54 static int rpmcliInitialized = -1;
55 
56 /**
57  * Display rpm version.
58  */
printVersion(FILE * fp)59 static void printVersion(FILE * fp)
60 {
61     fprintf(fp, _("RPM version %s\n"), rpmEVR);
62 }
63 
64 /**
65  * Make sure that config files have been read.
66  * @warning Options like --rcfile and --verbose must precede callers option.
67  */
rpmcliConfigured(void)68 void rpmcliConfigured(void)
69 {
70 
71     if (rpmcliInitialized < 0)
72 	rpmcliInitialized = rpmReadConfigFiles(rpmcliRcfile, NULL);
73     if (rpmcliInitialized)
74 	exit(EXIT_FAILURE);
75 }
76 
cliDefine(const char * arg,int predefine)77 static int cliDefine(const char *arg, int predefine)
78 {
79     int rc;
80     char *s, *t;
81     /* XXX Convert '-' in macro name to underscore, skip leading %. */
82     s = t = xstrdup(arg);
83     while (*t && !risspace(*t) && (*t != '(')) {
84 	if (*t == '-') *t = '_';
85 	t++;
86     }
87     t = s;
88     if (*t == '%') t++;
89 
90     rc = rpmDefineMacro(NULL, t, RMIL_CMDLINE);
91     if (!predefine && rc == 0)
92 	(void) rpmDefineMacro(rpmCLIMacroContext, t, RMIL_CMDLINE);
93 
94     free(s);
95     return rc;
96 }
97 
98 /**
99  */
rpmcliAllArgCallback(poptContext con,enum poptCallbackReason reason,const struct poptOption * opt,const char * arg,const void * data)100 static void rpmcliAllArgCallback( poptContext con,
101                 enum poptCallbackReason reason,
102                 const struct poptOption * opt, const char * arg,
103                 const void * data)
104 {
105 
106     /* XXX avoid accidental collisions with POPT_BIT_SET for flags */
107     if (opt->arg == NULL)
108     switch (opt->val) {
109     case 'q':
110 	rpmSetVerbosity(RPMLOG_WARNING);
111 	break;
112     case 'v':
113 	rpmIncreaseVerbosity();
114 	break;
115     case POPT_PREDEFINE:
116 	if (cliDefine(arg, 1))
117 	    exit(EXIT_FAILURE);
118 	break;
119     case 'D':
120 	rpmcliConfigured();
121 	if (cliDefine(arg, 0))
122 	    exit(EXIT_FAILURE);
123 	break;
124     case POPT_UNDEFINE:
125 	rpmcliConfigured();
126 	if (*arg == '%')
127 	    arg++;
128 	rpmPopMacro(NULL, arg);
129 	break;
130     case 'E':
131 	rpmcliConfigured();
132 	{   char *val = NULL;
133 	    if (rpmExpandMacros(NULL, arg, &val, 0) < 0)
134 		exit(EXIT_FAILURE);
135 	    fprintf(stdout, "%s\n", val);
136 	    free(val);
137 	}
138 	break;
139     case POPT_LOAD:
140 	rpmcliConfigured();
141 	if (rpmLoadMacroFile(NULL, arg)) {
142 	    fprintf(stderr, _("failed to load macro file %s\n"), arg);
143 	    exit(EXIT_FAILURE);
144 	}
145 	break;
146     case POPT_DBPATH:
147 	rpmcliConfigured();
148 	if (arg && arg[0] != '/') {
149 	    fprintf(stderr, _("arguments to --dbpath must begin with '/'\n"));
150 	    exit(EXIT_FAILURE);
151 	}
152 	rpmPushMacro(NULL, "_dbpath", NULL, arg, RMIL_CMDLINE);
153 	break;
154     case POPT_SHOWVERSION:
155 	printVersion(stdout);
156 	exit(EXIT_SUCCESS);
157 	break;
158     case POPT_SHOWRC:
159 	rpmcliConfigured();
160 	(void) rpmShowRC(stdout);
161 	exit(EXIT_SUCCESS);
162 	break;
163     case POPT_QUERYTAGS:
164 	rpmDisplayQueryTags(stdout);
165 	exit(EXIT_SUCCESS);
166 	break;
167     case POPT_PIPE:
168 	if (rpmcliPipeOutput) {
169 	    fprintf(stderr,
170 		    _("%s: error: more than one --pipe specified "
171 		      "(incompatible popt aliases?)\n"), xgetprogname());
172 	    exit(EXIT_FAILURE);
173 	}
174 	rpmcliPipeOutput = xstrdup(arg);
175 	break;
176     case RPMCLI_POPT_NODIGEST:
177 	rpmcliVSFlags |= RPMVSF_MASK_NODIGESTS;
178 	rpmcliVfyLevelMask |= RPMSIG_DIGEST_TYPE;
179 	break;
180     case RPMCLI_POPT_NOSIGNATURE:
181 	rpmcliVSFlags |= RPMVSF_MASK_NOSIGNATURES;
182 	rpmcliVfyLevelMask |= RPMSIG_SIGNATURE_TYPE;
183 	break;
184     case RPMCLI_POPT_NOHDRCHK:
185 	rpmcliVSFlags |= RPMVSF_NOHDRCHK;
186 	break;
187 
188     case RPMCLI_POPT_TARGETPLATFORM:
189 	rpmcliInitialized = rpmReadConfigFiles(rpmcliRcfile, arg);
190 	break;
191     }
192 }
193 
194 struct poptOption rpmcliAllPoptTable[] = {
195 /* FIX: cast? */
196  { NULL, '\0', POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA | POPT_CBFLAG_CONTINUE,
197         rpmcliAllArgCallback, 0, NULL, NULL },
198 
199  { "debug", 'd', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_debug, -1,
200         NULL, NULL },
201 
202  { "predefine", '\0', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_PREDEFINE,
203 	N_("predefine MACRO with value EXPR"),
204 	N_("'MACRO EXPR'") },
205  { "define", 'D', POPT_ARG_STRING, 0, 'D',
206 	N_("define MACRO with value EXPR"),
207 	N_("'MACRO EXPR'") },
208  { "undefine", '\0', POPT_ARG_STRING, 0, POPT_UNDEFINE,
209 	N_("undefine MACRO"),
210 	N_("MACRO") },
211  { "eval", 'E', POPT_ARG_STRING, 0, 'E',
212 	N_("print macro expansion of EXPR"),
213 	N_("'EXPR'") },
214  { "target", '\0', POPT_ARG_STRING, NULL,  RPMCLI_POPT_TARGETPLATFORM,
215         N_("Specify target platform"), N_("CPU-VENDOR-OS") },
216  { "macros", '\0', POPT_ARG_STRING, &macrofiles, 0,
217 	N_("read <FILE:...> instead of default file(s)"),
218 	N_("<FILE:...>") },
219  { "load", '\0', POPT_ARG_STRING, 0, POPT_LOAD,
220 	N_("load a single macro file"),
221 	N_("<FILE>") },
222 
223  /* XXX this is a bit out of place here but kinda unavoidable... */
224  { "noplugins", '\0', POPT_BIT_SET,
225 	&rpmIArgs.transFlags, RPMTRANS_FLAG_NOPLUGINS,
226 	N_("don't enable any plugins"), NULL },
227 
228  { "nodigest", '\0', 0, 0, RPMCLI_POPT_NODIGEST,
229         N_("don't verify package digest(s)"), NULL },
230  { "nohdrchk", '\0', POPT_ARGFLAG_DOC_HIDDEN, 0, RPMCLI_POPT_NOHDRCHK,
231         N_("don't verify database header(s) when retrieved"), NULL },
232  { "nosignature", '\0', 0, 0, RPMCLI_POPT_NOSIGNATURE,
233         N_("don't verify package signature(s)"), NULL },
234 
235  { "pipe", '\0', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_PIPE,
236 	N_("send stdout to CMD"),
237 	N_("CMD") },
238  { "rcfile", '\0', POPT_ARG_STRING, &rpmcliRcfile, 0,
239 	N_("read <FILE:...> instead of default file(s)"),
240 	N_("<FILE:...>") },
241  { "root", 'r', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &rpmcliRootDir, 0,
242 	N_("use ROOT as top level directory"),
243 	N_("ROOT") },
244  { "dbpath", '\0', POPT_ARG_STRING, 0, POPT_DBPATH,
245 	N_("use database in DIRECTORY"),
246 	N_("DIRECTORY") },
247 
248  { "querytags", '\0', 0, 0, POPT_QUERYTAGS,
249         N_("display known query tags"), NULL },
250  { "showrc", '\0', 0, NULL, POPT_SHOWRC,
251 	N_("display final rpmrc and macro configuration"), NULL },
252  { "quiet", '\0', 0, NULL, 'q',
253 	N_("provide less detailed output"), NULL},
254  { "verbose", 'v', 0, NULL, 'v',
255 	N_("provide more detailed output"), NULL},
256  { "version", '\0', 0, NULL, POPT_SHOWVERSION,
257 	N_("print the version of rpm being used"), NULL },
258 
259  { "fsmdebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_fsm_debug, -1,
260 	N_("debug payload file state machine"), NULL},
261  { "prtpkts", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_print_pkts, -1,
262 	NULL, NULL},
263  { "rpmfcdebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmfc_debug, -1,
264 	NULL, NULL},
265  { "rpmiodebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmio_debug, -1,
266 	N_("debug rpmio I/O"), NULL},
267  { "nouserns", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpm_nouserns, -1,
268 	N_("disable user namespace support"), NULL},
269  { "stats", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmts_stats, -1,
270 	NULL, NULL},
271 
272    POPT_TABLEEND
273 };
274 
275 poptContext
rpmcliFini(poptContext optCon)276 rpmcliFini(poptContext optCon)
277 {
278     poptFreeContext(optCon);
279     rpmFreeMacros(NULL);
280     rpmFreeMacros(rpmCLIMacroContext);
281     rpmFreeRpmrc();
282     rpmlogClose();
283     rpmcliInitialized = -1;
284 
285     return NULL;
286 }
287 
288 poptContext
rpmcliInit(int argc,char * const argv[],struct poptOption * optionsTable)289 rpmcliInit(int argc, char *const argv[], struct poptOption * optionsTable)
290 {
291     poptContext optCon;
292     int rc;
293     const char *ctx, *execPath;
294 
295 #if defined(ENABLE_NLS)
296     (void) setlocale(LC_ALL, "" );
297 
298     (void) bindtextdomain(PACKAGE, LOCALEDIR);
299     (void) textdomain(PACKAGE);
300 #endif
301 
302     rpmSetVerbosity(RPMLOG_NOTICE);
303 
304     if (optionsTable == NULL) {
305 	/* Read rpm configuration (if not already read). */
306 	rpmcliConfigured();
307 	return NULL;
308     }
309 
310     /* XXX hack to get popt working from build tree wrt lt-foo names */
311     ctx = rstreqn(xgetprogname(), "lt-", 3) ? xgetprogname() + 3 : xgetprogname();
312 
313     optCon = poptGetContext(ctx, argc, (const char **)argv, optionsTable, 0);
314     {
315 	char *poptfile = rpmGenPath(rpmConfigDir(), LIBRPMALIAS_FILENAME, NULL);
316 	(void) poptReadConfigFile(optCon, poptfile);
317 	free(poptfile);
318     }
319     (void) poptReadDefaultConfig(optCon, 1);
320 
321     if ((execPath = getenv("RPM_POPTEXEC_PATH")) == NULL)
322 	execPath = LIBRPMALIAS_EXECPATH;
323     poptSetExecPath(optCon, execPath, 1);
324 
325     /* Process all options, whine if unknown. */
326     while ((rc = poptGetNextOpt(optCon)) > 0) {
327 	fprintf(stderr, _("%s: option table misconfigured (%d)\n"),
328 		xgetprogname(), rc);
329 	exit(EXIT_FAILURE);
330     }
331 
332     if (rc < -1) {
333 	fprintf(stderr, "%s: %s: %s\n", xgetprogname(),
334 		poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
335 		poptStrerror(rc));
336 	exit(EXIT_FAILURE);
337     }
338 
339     /* Read rpm configuration (if not already read). */
340     rpmcliConfigured();
341 
342     if (_debug) {
343 	rpmIncreaseVerbosity();
344 	rpmIncreaseVerbosity();
345     }
346 
347     return optCon;
348 }
349