]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/cat.c
journal/compress: return early in uncompress_startswith
[thirdparty/systemd.git] / src / journal / cat.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2012 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdio.h>
23 #include <getopt.h>
24 #include <assert.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <fcntl.h>
29
30 #include <systemd/sd-journal.h>
31
32 #include "util.h"
33 #include "build.h"
34
35 static char *arg_identifier = NULL;
36 static int arg_priority = LOG_INFO;
37 static bool arg_level_prefix = true;
38
39 static int help(void) {
40
41 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
42 "Execute process with stdout/stderr connected to the journal.\n\n"
43 " -h --help Show this help\n"
44 " --version Show package version\n"
45 " -t --identifier=STRING Set syslog identifier\n"
46 " -p --priority=PRIORITY Set priority value (0..7)\n"
47 " --level-prefix=BOOL Control whether level prefix shall be parsed\n",
48 program_invocation_short_name);
49
50 return 0;
51 }
52
53 static int parse_argv(int argc, char *argv[]) {
54
55 enum {
56 ARG_VERSION = 0x100,
57 ARG_LEVEL_PREFIX
58 };
59
60 static const struct option options[] = {
61 { "help", no_argument, NULL, 'h' },
62 { "version", no_argument, NULL, ARG_VERSION },
63 { "identifier", required_argument, NULL, 't' },
64 { "priority", required_argument, NULL, 'p' },
65 { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX },
66 {}
67 };
68
69 int c;
70
71 assert(argc >= 0);
72 assert(argv);
73
74 while ((c = getopt_long(argc, argv, "+ht:p:", options, NULL)) >= 0) {
75
76 switch (c) {
77
78 case 'h':
79 return help();
80
81 case ARG_VERSION:
82 puts(PACKAGE_STRING);
83 puts(SYSTEMD_FEATURES);
84 return 0;
85
86 case 't':
87 free(arg_identifier);
88 if (isempty(optarg))
89 arg_identifier = NULL;
90 else {
91 arg_identifier = strdup(optarg);
92 if (!arg_identifier)
93 return log_oom();
94 }
95 break;
96
97 case 'p':
98 arg_priority = log_level_from_string(optarg);
99 if (arg_priority < 0) {
100 log_error("Failed to parse priority value.");
101 return arg_priority;
102 }
103 break;
104
105 case ARG_LEVEL_PREFIX: {
106 int k;
107
108 k = parse_boolean(optarg);
109 if (k < 0) {
110 log_error("Failed to parse level prefix value.");
111 return k;
112 }
113 arg_level_prefix = k;
114 break;
115 }
116
117 case '?':
118 return -EINVAL;
119
120 default:
121 assert_not_reached("Unhandled option");
122 }
123 }
124
125 return 1;
126 }
127
128 int main(int argc, char *argv[]) {
129 int r, fd = -1, saved_stderr = -1;
130
131 log_parse_environment();
132 log_open();
133
134 r = parse_argv(argc, argv);
135 if (r <= 0)
136 goto finish;
137
138 fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
139 if (fd < 0) {
140 log_error("Failed to create stream fd: %s", strerror(-fd));
141 r = fd;
142 goto finish;
143 }
144
145 saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);
146
147 if (dup3(fd, STDOUT_FILENO, 0) < 0 ||
148 dup3(fd, STDERR_FILENO, 0) < 0) {
149 log_error("Failed to duplicate fd: %m");
150 r = -errno;
151 goto finish;
152 }
153
154 if (fd >= 3)
155 safe_close(fd);
156
157 fd = -1;
158
159 if (argc <= optind)
160 execl("/bin/cat", "/bin/cat", NULL);
161 else
162 execvp(argv[optind], argv + optind);
163
164 r = -errno;
165
166 /* Let's try to restore a working stderr, so we can print the error message */
167 if (saved_stderr >= 0)
168 dup3(saved_stderr, STDERR_FILENO, 0);
169
170 log_error("Failed to execute process: %s", strerror(-r));
171
172 finish:
173 safe_close(fd);
174 safe_close(saved_stderr);
175
176 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
177 }