]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/cat.c
resolved: avoid possible dereference of null pointer
[thirdparty/systemd.git] / src / journal / cat.c
CommitLineData
755a02c6
LP
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
5430f7f2
LP
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
755a02c6
LP
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
5430f7f2 16 Lesser General Public License for more details.
755a02c6 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
755a02c6
LP
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>
abad76cc 28#include <fcntl.h>
755a02c6 29
73f860db 30#include "systemd/sd-journal.h"
755a02c6
LP
31
32#include "util.h"
33#include "build.h"
34
35static char *arg_identifier = NULL;
d508ac0b 36static int arg_priority = LOG_INFO;
755a02c6
LP
37static bool arg_level_prefix = true;
38
39static 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
53static 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' },
9aac0b2c 62 { "version", no_argument, NULL, ARG_VERSION },
755a02c6
LP
63 { "identifier", required_argument, NULL, 't' },
64 { "priority", required_argument, NULL, 'p' },
65 { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX },
eb9da376 66 {}
755a02c6
LP
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':
eb9da376 79 return help();
755a02c6
LP
80
81 case ARG_VERSION:
82 puts(PACKAGE_STRING);
755a02c6
LP
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);
0d0f0c50
SL
92 if (!arg_identifier)
93 return log_oom();
755a02c6
LP
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
eb9da376 117 case '?':
755a02c6 118 return -EINVAL;
eb9da376
LP
119
120 default:
121 assert_not_reached("Unhandled option");
755a02c6
LP
122 }
123 }
124
125 return 1;
126}
127
128int 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) {
9aac0b2c 140 log_error("Failed to create stream fd: %s", strerror(-fd));
755a02c6
LP
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) {
9aac0b2c 149 log_error("Failed to duplicate fd: %m");
755a02c6
LP
150 r = -errno;
151 goto finish;
152 }
153
154 if (fd >= 3)
03e334a1 155 safe_close(fd);
755a02c6
LP
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
9aac0b2c
LP
164 r = -errno;
165
755a02c6
LP
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
9aac0b2c 170 log_error("Failed to execute process: %s", strerror(-r));
755a02c6
LP
171
172finish:
03e334a1
LP
173 safe_close(fd);
174 safe_close(saved_stderr);
755a02c6
LP
175
176 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
177}