Reimplement setprogname() and getprogname() to be generic and portable
The RPM code contains setprogname()/getprogname() support implemented through compatiblity layer with very old GLIBC (internals supported back to '95 and earlier), before stabilization of the GNU C library. This compatiblity layer (__progname, __assert_progname, setprogname()) is supposed to support well archaic GLIBC, but on the other hand it pollutes the library namespace and introduces unpredicable compillation errors on BSD systems. The functions setprogname() and getprogname() are natively supported in NetBSD and work the same way as __progname from the GNU C library (they are even implemented in the same way - but with a slightly changed logic). The support for very old (20 years and older) GNU C Library is obfuscating the code, because it uses defines over defines without a word of explaination why to do so. It's important to note that the setprogname()/getprogname() was inconstiently implemented in the codebase, duplicating the code and/or functionality. Add new generic functions getprogname() and setprogname() and bind it to: - the current and for two decades stable GNU LIB C implementation, - the current NetBSD implementation (introduces to NetBSD in 2002), - fallback reimplementation functions of the setprogname() and getprogname() functionality for other systems. Don't support anymore old GNU Lib C internals and don't support older NetBSD systems, as they aren't supported for many years. Add to the codebase comments explaining the relevant codeparts.
This commit is contained in:
parent
159351d7f3
commit
61109446ac
|
@ -18,7 +18,7 @@ static pid_t pipeChild = 0;
|
|||
RPM_GNUC_NORETURN
|
||||
void argerror(const char * desc)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s\n"), __progname, desc);
|
||||
fprintf(stderr, _("%s: %s\n"), xgetprogname(), desc);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
#include "system.h"
|
||||
const char *__progname;
|
||||
|
||||
#include <rpm/rpmcli.h>
|
||||
#include <rpm/rpmlib.h> /* rpmEVR, rpmReadConfigFiles etc */
|
||||
|
@ -260,14 +259,6 @@ rpmcliInit(int argc, char *const argv[], struct poptOption * optionsTable)
|
|||
int rc;
|
||||
const char *ctx, *execPath;
|
||||
|
||||
setprogname(argv[0]); /* Retrofit glibc __progname */
|
||||
|
||||
/* XXX glibc churn sanity */
|
||||
if (__progname == NULL) {
|
||||
if ((__progname = strrchr(argv[0], '/')) != NULL) __progname++;
|
||||
else __progname = argv[0];
|
||||
}
|
||||
|
||||
#if defined(ENABLE_NLS)
|
||||
(void) setlocale(LC_ALL, "" );
|
||||
|
||||
|
@ -284,7 +275,7 @@ rpmcliInit(int argc, char *const argv[], struct poptOption * optionsTable)
|
|||
}
|
||||
|
||||
/* XXX hack to get popt working from build tree wrt lt-foo names */
|
||||
ctx = rstreqn(__progname, "lt-", 3) ? __progname + 3 : __progname;
|
||||
ctx = rstreqn(xgetprogname(), "lt-", 3) ? xgetprogname() + 3 : xgetprogname();
|
||||
|
||||
optCon = poptGetContext(ctx, argc, (const char **)argv, optionsTable, 0);
|
||||
{
|
||||
|
@ -301,12 +292,12 @@ rpmcliInit(int argc, char *const argv[], struct poptOption * optionsTable)
|
|||
/* Process all options, whine if unknown. */
|
||||
while ((rc = poptGetNextOpt(optCon)) > 0) {
|
||||
fprintf(stderr, _("%s: option table misconfigured (%d)\n"),
|
||||
__progname, rc);
|
||||
xgetprogname(), rc);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (rc < -1) {
|
||||
fprintf(stderr, "%s: %s: %s\n", __progname,
|
||||
fprintf(stderr, "%s: %s: %s\n", xgetprogname(),
|
||||
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
|
||||
poptStrerror(rc));
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
|
@ -26,7 +26,7 @@ struct rpmInstallArguments_s rpmIArgs = {
|
|||
RPM_GNUC_NORETURN
|
||||
static void argerror(const char * desc)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s\n"), __progname, desc);
|
||||
fprintf(stderr, _("%s: %s\n"), xgetprogname(), desc);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/misc
|
|||
|
||||
EXTRA_DIST = \
|
||||
fnmatch.c fnmatch.h \
|
||||
rpmxprogname.c rpmxprogname.h \
|
||||
stpcpy.c stpncpy.c
|
||||
|
||||
noinst_LTLIBRARIES = libmisc.la
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* Original author: Kamil Rytarowski
|
||||
File: rpmxprogname.c
|
||||
Date of creation: 2013-08-10
|
||||
License: the same as RPM itself */
|
||||
|
||||
#include "rpmxprogname.h"
|
||||
|
||||
#include <string.h> /* strrchr */
|
||||
|
||||
char *_rpmxprogname = NULL;
|
||||
|
||||
char *_rpmxgetprogname(void)
|
||||
{
|
||||
const char *empty = "";
|
||||
|
||||
if (_rpmxprognam != NULL) /* never return NULL string */
|
||||
return _rpmxprogname;
|
||||
else
|
||||
return empty;
|
||||
}
|
||||
|
||||
void _rpmxsetprogname(const char *pn)
|
||||
{
|
||||
if (pn != NULL && _rpmxprogname == NULL /* set the value only once */) {
|
||||
char *p = strrchr(pn, '/'); /* locate the last occurence of '/' */
|
||||
if (p != NULL)
|
||||
_rpmxprogname = p + 1 /* strip beginning '/' */;
|
||||
else
|
||||
_rpmxprogname = pn;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _RPMXPROGNAME_H */
|
|
@ -0,0 +1,13 @@
|
|||
/* Original author: Kamil Rytarowski
|
||||
File: rpmxprogname.c
|
||||
Date of creation: 2013-08-10
|
||||
License: the same as RPM itself */
|
||||
|
||||
#ifndef _RPMXPROGNAME_H
|
||||
#define _RPMXPROGNAME_H
|
||||
|
||||
char *_rpmxgetprogname(void);
|
||||
void _rpmxsetprogname(const char *pn);
|
||||
|
||||
#endif /* _RPMXPROGNAME_H */
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
/* rpmarchive: spit out the main archive portion of a package */
|
||||
|
||||
#include "system.h"
|
||||
const char *__progname;
|
||||
|
||||
#include <rpm/rpmlib.h> /* rpmReadPackageFile .. */
|
||||
#include <rpm/rpmtag.h>
|
||||
|
@ -21,7 +20,8 @@ int main(int argc, char *argv[])
|
|||
off_t payload_size;
|
||||
FD_t gzdi;
|
||||
|
||||
setprogname(argv[0]); /* Retrofit glibc __progname */
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
rpmReadConfigFiles(NULL, NULL);
|
||||
if (argc == 1)
|
||||
fdi = fdDup(STDIN_FILENO);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "system.h"
|
||||
const char *__progname;
|
||||
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
|
@ -596,7 +595,12 @@ int main(int argc, char *argv[])
|
|||
|
||||
const char *pkg = NULL;
|
||||
int ec = 0;
|
||||
poptContext optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
|
||||
poptContext optCon = NULL;
|
||||
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
|
||||
/* Args required only when building, let lone --eval etc through */
|
||||
if (ba->buildAmount && poptPeekArg(optCon) == NULL) {
|
||||
|
|
6
rpmdb.c
6
rpmdb.c
|
@ -92,9 +92,13 @@ static int importDB(rpmts ts)
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ec = EXIT_FAILURE;
|
||||
poptContext optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
poptContext optCon = NULL;
|
||||
rpmts ts = NULL;
|
||||
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
|
||||
if (argc < 2 || poptPeekArg(optCon)) {
|
||||
printUsage(optCon, stderr, 0);
|
||||
goto exit;
|
||||
|
|
|
@ -49,10 +49,14 @@ static struct poptOption optionsTable[] = {
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ec = EXIT_FAILURE;
|
||||
poptContext optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
poptContext optCon = NULL;
|
||||
rpmts ts = rpmtsCreate();
|
||||
ARGV_const_t args = NULL;
|
||||
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
|
||||
if (argc < 2) {
|
||||
printUsage(optCon, stderr, 0);
|
||||
goto exit;
|
||||
|
|
7
rpmqv.c
7
rpmqv.c
|
@ -1,5 +1,4 @@
|
|||
#include "system.h"
|
||||
const char *__progname;
|
||||
|
||||
#include <rpm/rpmcli.h>
|
||||
#include <rpm/rpmlib.h> /* RPMSIGTAG, rpmReadPackageFile .. */
|
||||
|
@ -88,12 +87,14 @@ int main(int argc, char *argv[])
|
|||
int i;
|
||||
#endif
|
||||
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
|
||||
/* Set the major mode based on argv[0] */
|
||||
#ifdef IAM_RPMQV
|
||||
if (rstreq(__progname, "rpmquery")) bigMode = MODE_QUERY;
|
||||
if (rstreq(__progname, "rpmverify")) bigMode = MODE_VERIFY;
|
||||
if (rstreq(xgetprogname(), "rpmquery")) bigMode = MODE_QUERY;
|
||||
if (rstreq(xgetprogname(), "rpmverify")) bigMode = MODE_VERIFY;
|
||||
#endif
|
||||
|
||||
#if defined(IAM_RPMQV)
|
||||
|
|
|
@ -110,9 +110,13 @@ exit:
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ec = EXIT_FAILURE;
|
||||
poptContext optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
poptContext optCon = NULL;
|
||||
const char *arg;
|
||||
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
|
||||
if (argc <= 1) {
|
||||
printUsage(optCon, stderr, 0);
|
||||
goto exit;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "system.h"
|
||||
const char *__progname;
|
||||
|
||||
#include <rpm/rpmcli.h>
|
||||
#include <rpm/rpmbuild.h>
|
||||
|
@ -60,6 +59,8 @@ int main(int argc, char *argv[])
|
|||
poptContext optCon;
|
||||
int ec = 0;
|
||||
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
|
||||
if (rpmcliPipeOutput && initPipe())
|
||||
|
|
39
system.h
39
system.h
|
@ -92,20 +92,33 @@ extern int fdatasync(int fildes);
|
|||
#define xstrdup(_str) rstrdup((_str))
|
||||
#define _free(_ptr) rfree((_ptr))
|
||||
|
||||
/* Retrofit glibc __progname */
|
||||
#if defined __GLIBC__ && __GLIBC__ >= 2
|
||||
#if __GLIBC_MINOR__ >= 1
|
||||
#define __progname __assert_program_name
|
||||
/* To extract program's name: use calls (reimplemented or shipped with system):
|
||||
- void setprogname(const char *pn)
|
||||
- const char *getprogname(void)
|
||||
|
||||
setprogname(*pn) must be the first call in main() in order to set the name
|
||||
as soon as possible. */
|
||||
#if defined(__NetBSD__)
|
||||
/* `man setprogname' v. May 21, 2011 (NetBSD 6.1) says:
|
||||
Portable programs that wish to use getprogname() should call setprogname()
|
||||
in main(). In some systems (like NetBSD) it can be set only once and it is
|
||||
done before an execution of main() -- therefore calling it again has no
|
||||
effect.
|
||||
|
||||
Getprogname and setprogname function calls appeared in NetBSD 1.6
|
||||
(released in 2002). So nothing to (re)implement for this platform. */
|
||||
# include <stdlib.h> /* Make sure this header is included */
|
||||
# define xsetprogname(pn) setprogname(pn)
|
||||
# define xgetprogname(pn) getprogname(pn)
|
||||
#elif defined(__GLIBC__) /* GNU LIBC ships with (const *char *) __progname */
|
||||
# define xsetprogname(pn) /* No need to implement it in GNU LIBC. */
|
||||
extern const char *__progname;
|
||||
# define xgetprogname(pn) __progname
|
||||
#else /* Reimplement setprogname and getprogname */
|
||||
# include "misc/rpmxprogname.h"
|
||||
# define xsetprogname(pn) _rpmxsetprogname(pn)
|
||||
# define xgetprogname() _rpmxgetprogname()
|
||||
#endif
|
||||
#define setprogname(pn)
|
||||
#else
|
||||
#define __progname program_name
|
||||
#define setprogname(pn) \
|
||||
{ if ((__progname = strrchr(pn, '/')) != NULL) __progname++; \
|
||||
else __progname = pn; \
|
||||
}
|
||||
#endif
|
||||
extern const char *__progname;
|
||||
|
||||
/* Take care of NLS matters. */
|
||||
#if ENABLE_NLS
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "system.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -368,6 +369,8 @@ int main(int argc, char *argv[])
|
|||
POPT_TABLEEND
|
||||
};
|
||||
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = poptGetContext(argv[0], argc, (const char **) argv, opts, 0);
|
||||
if (argc < 2 || poptGetNextOpt(optCon) == 0) {
|
||||
poptPrintUsage(optCon, stderr, 0);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "system.h"
|
||||
const char *__progname;
|
||||
|
||||
#include <rpm/rpmbuild.h>
|
||||
#include <rpm/argv.h>
|
||||
|
@ -8,8 +7,6 @@ const char *__progname;
|
|||
|
||||
#include "debug.h"
|
||||
|
||||
char *progname;
|
||||
|
||||
static int print_provides;
|
||||
|
||||
static int print_requires;
|
||||
|
@ -75,10 +72,7 @@ main(int argc, char *argv[])
|
|||
int ec = 1;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if ((progname = strrchr(argv[0], '/')) != NULL)
|
||||
progname++;
|
||||
else
|
||||
progname = argv[0];
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
if (optCon == NULL)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "system.h"
|
||||
const char *__progname;
|
||||
|
||||
#include <rpm/rpmcli.h>
|
||||
#include <rpm/rpmlib.h> /* rpmReadPackageFile */
|
||||
|
@ -235,6 +234,8 @@ main(int argc, char *argv[])
|
|||
poptContext optCon;
|
||||
int ec = 0;
|
||||
|
||||
xsetprogname(argv[0]); /* Portability call -- see system.h */
|
||||
|
||||
optCon = rpmcliInit(argc, argv, optionsTable);
|
||||
if (optCon == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
Loading…
Reference in New Issue