Skip to content

Commit 9200bb3

Browse files
committed
journalctl: make pcre2 a dlopen() dependency
Let's make use of the library if it is installed, but otherwise just generate a nice error and provide all other functionality.
1 parent 046c913 commit 9200bb3

File tree

5 files changed

+108
-25
lines changed

5 files changed

+108
-25
lines changed

meson.build

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,8 +1798,8 @@ public_programs += executable(
17981798
libqrencode,
17991799
libxz,
18001800
liblz4,
1801-
libpcre2,
1802-
libzstd],
1801+
libzstd,
1802+
libdl],
18031803
install_rpath : rootlibexecdir,
18041804
install : true,
18051805
install_dir : rootbindir)

src/journal/journalctl.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include "pager.h"
5757
#include "parse-util.h"
5858
#include "path-util.h"
59+
#include "pcre2-dlopen.h"
5960
#include "pretty-print.h"
6061
#include "rlimit-util.h"
6162
#include "set.h"
@@ -160,20 +161,20 @@ typedef struct BootId {
160161
} BootId;
161162

162163
#if HAVE_PCRE2
163-
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, pcre2_match_data_free);
164-
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, pcre2_code_free);
164+
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, sym_pcre2_match_data_free);
165+
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, sym_pcre2_code_free);
165166

166167
static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) {
167168
int errorcode, r;
168169
PCRE2_SIZE erroroffset;
169170
pcre2_code *p;
170171

171-
p = pcre2_compile((PCRE2_SPTR8) pattern,
172-
PCRE2_ZERO_TERMINATED, flags, &errorcode, &erroroffset, NULL);
172+
p = sym_pcre2_compile((PCRE2_SPTR8) pattern,
173+
PCRE2_ZERO_TERMINATED, flags, &errorcode, &erroroffset, NULL);
173174
if (!p) {
174175
unsigned char buf[LINE_MAX];
175176

176-
r = pcre2_get_error_message(errorcode, buf, sizeof buf);
177+
r = sym_pcre2_get_error_message(errorcode, buf, sizeof buf);
177178

178179
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
179180
"Bad pattern \"%s\": %s", pattern,
@@ -183,7 +184,6 @@ static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out
183184
*out = p;
184185
return 0;
185186
}
186-
187187
#endif
188188

189189
static int add_matches_for_device(sd_journal *j, const char *devpath) {
@@ -1087,22 +1087,26 @@ static int parse_argv(int argc, char *argv[]) {
10871087
if (arg_pattern) {
10881088
unsigned flags;
10891089

1090+
r = dlopen_pcre2();
1091+
if (r < 0)
1092+
return r;
1093+
10901094
if (arg_case_sensitive >= 0)
10911095
flags = !arg_case_sensitive * PCRE2_CASELESS;
10921096
else {
1093-
_cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
1097+
_cleanup_(sym_pcre2_match_data_freep) pcre2_match_data *md = NULL;
10941098
bool has_case;
1095-
_cleanup_(pcre2_code_freep) pcre2_code *cs = NULL;
1099+
_cleanup_(sym_pcre2_code_freep) pcre2_code *cs = NULL;
10961100

1097-
md = pcre2_match_data_create(1, NULL);
1101+
md = sym_pcre2_match_data_create(1, NULL);
10981102
if (!md)
10991103
return log_oom();
11001104

11011105
r = pattern_compile("[[:upper:]]", 0, &cs);
11021106
if (r < 0)
11031107
return r;
11041108

1105-
r = pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL);
1109+
r = sym_pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL);
11061110
has_case = r >= 0;
11071111

11081112
flags = !has_case * PCRE2_CASELESS;
@@ -2630,12 +2634,12 @@ int main(int argc, char *argv[]) {
26302634

26312635
#if HAVE_PCRE2
26322636
if (arg_compiled_pattern) {
2633-
_cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
2637+
_cleanup_(sym_pcre2_match_data_freep) pcre2_match_data *md = NULL;
26342638
const void *message;
26352639
size_t len;
26362640
PCRE2_SIZE *ovec;
26372641

2638-
md = pcre2_match_data_create(1, NULL);
2642+
md = sym_pcre2_match_data_create(1, NULL);
26392643
if (!md)
26402644
return log_oom();
26412645

@@ -2652,13 +2656,13 @@ int main(int argc, char *argv[]) {
26522656

26532657
assert_se(message = startswith(message, "MESSAGE="));
26542658

2655-
r = pcre2_match(arg_compiled_pattern,
2656-
message,
2657-
len - strlen("MESSAGE="),
2658-
0, /* start at offset 0 in the subject */
2659-
0, /* default options */
2660-
md,
2661-
NULL);
2659+
r = sym_pcre2_match(arg_compiled_pattern,
2660+
message,
2661+
len - strlen("MESSAGE="),
2662+
0, /* start at offset 0 in the subject */
2663+
0, /* default options */
2664+
md,
2665+
NULL);
26622666
if (r == PCRE2_ERROR_NOMATCH) {
26632667
need_seek = true;
26642668
continue;
@@ -2667,14 +2671,14 @@ int main(int argc, char *argv[]) {
26672671
unsigned char buf[LINE_MAX];
26682672
int r2;
26692673

2670-
r2 = pcre2_get_error_message(r, buf, sizeof buf);
2674+
r2 = sym_pcre2_get_error_message(r, buf, sizeof buf);
26712675
log_error("Pattern matching failed: %s",
26722676
r2 < 0 ? "unknown error" : (char*) buf);
26732677
r = -EINVAL;
26742678
goto finish;
26752679
}
26762680

2677-
ovec = pcre2_get_ovector_pointer(md);
2681+
ovec = sym_pcre2_get_ovector_pointer(md);
26782682
highlight[0] = ovec[0];
26792683
highlight[1] = ovec[1];
26802684
}
@@ -2766,7 +2770,7 @@ int main(int argc, char *argv[]) {
27662770

27672771
#if HAVE_PCRE2
27682772
if (arg_compiled_pattern) {
2769-
pcre2_code_free(arg_compiled_pattern);
2773+
sym_pcre2_code_free(arg_compiled_pattern);
27702774

27712775
/* --grep was used, no error was thrown, but the pattern didn't
27722776
* match anything. Let's mimic grep's behavior here and return

src/journal/meson.build

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ journald_gperf_c = custom_target(
101101

102102
systemd_cat_sources = files('cat.c')
103103

104-
journalctl_sources = files('journalctl.c')
104+
journalctl_sources = files('''
105+
journalctl.c
106+
pcre2-dlopen.c
107+
pcre2-dlopen.h
108+
'''.split())
105109

106110
if conf.get('HAVE_QRENCODE') == 1
107111
journalctl_sources += files('journal-qrcode.c',

src/journal/pcre2-dlopen.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* SPDX-License-Identifier: LGPL-2.1+ */
2+
3+
#include "alloc-util.h"
4+
#include "dlfcn-util.h"
5+
#include "pcre2-dlopen.h"
6+
7+
#if HAVE_PCRE2
8+
static void *pcre2_dl = NULL;
9+
10+
pcre2_match_data* (*sym_pcre2_match_data_create)(uint32_t, pcre2_general_context *);
11+
void (*sym_pcre2_match_data_free)(pcre2_match_data *);
12+
void (*sym_pcre2_code_free)(pcre2_code *);
13+
pcre2_code* (*sym_pcre2_compile)(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, pcre2_compile_context *);
14+
int (*sym_pcre2_get_error_message)(int, PCRE2_UCHAR *, PCRE2_SIZE);
15+
int (*sym_pcre2_match)(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, pcre2_match_data *, pcre2_match_context *);
16+
PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *);
17+
18+
int dlopen_pcre2(void) {
19+
_cleanup_(dlclosep) void *dl = NULL;
20+
int r;
21+
22+
if (pcre2_dl)
23+
return 0; /* Already loaded */
24+
25+
dl = dlopen("libpcre2-8.so.0", RTLD_LAZY);
26+
if (!dl)
27+
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
28+
"PCRE2 support is not installed: %s", dlerror());
29+
30+
r = dlsym_many_and_warn(
31+
dl,
32+
LOG_ERR,
33+
&sym_pcre2_match_data_create, "pcre2_match_data_create_8",
34+
&sym_pcre2_match_data_free, "pcre2_match_data_free_8",
35+
&sym_pcre2_code_free, "pcre2_code_free_8",
36+
&sym_pcre2_compile, "pcre2_compile_8",
37+
&sym_pcre2_get_error_message, "pcre2_get_error_message_8",
38+
&sym_pcre2_match, "pcre2_match_8",
39+
&sym_pcre2_get_ovector_pointer, "pcre2_get_ovector_pointer_8",
40+
NULL);
41+
if (r < 0)
42+
return r;
43+
44+
/* Note that we never release the reference here, because there's no real reason to, after all this
45+
* was traditionally a regular shared library dependency which lives forever too. */
46+
pcre2_dl = TAKE_PTR(dl);
47+
48+
return 1;
49+
}
50+
51+
#else
52+
53+
int dlopen_pcre2(void) {
54+
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
55+
"PCRE2 support is not compiled in.");
56+
}
57+
#endif

src/journal/pcre2-dlopen.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* SPDX-License-Identifier: LGPL-2.1+ */
2+
#pragma once
3+
4+
#if HAVE_PCRE2
5+
6+
#define PCRE2_CODE_UNIT_WIDTH 8
7+
#include <pcre2.h>
8+
9+
extern pcre2_match_data* (*sym_pcre2_match_data_create)(uint32_t, pcre2_general_context *);
10+
extern void (*sym_pcre2_match_data_free)(pcre2_match_data *);
11+
extern void (*sym_pcre2_code_free)(pcre2_code *);
12+
extern pcre2_code* (*sym_pcre2_compile)(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, pcre2_compile_context *);
13+
extern int (*sym_pcre2_get_error_message)(int, PCRE2_UCHAR *, PCRE2_SIZE);
14+
extern int (*sym_pcre2_match)(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, pcre2_match_data *, pcre2_match_context *);
15+
extern PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *);
16+
#endif
17+
18+
int dlopen_pcre2(void);

0 commit comments

Comments
 (0)