]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/cat.c
Merge pull request #1693 from ssahani/word
[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
755a02c6 22#include <errno.h>
abad76cc 23#include <fcntl.h>
3f6fd1ba
LP
24#include <getopt.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <unistd.h>
755a02c6 28
3f6fd1ba 29#include "sd-journal.h"
755a02c6 30
3ffd4af2 31#include "fd-util.h"
07630cea 32#include "string-util.h"
755a02c6 33#include "util.h"
755a02c6
LP
34
35static char *arg_identifier = NULL;
d508ac0b 36static int arg_priority = LOG_INFO;
755a02c6
LP
37static bool arg_level_prefix = true;
38
601185b4 39static void help(void) {
755a02c6
LP
40 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
41 "Execute process with stdout/stderr connected to the journal.\n\n"
42 " -h --help Show this help\n"
43 " --version Show package version\n"
44 " -t --identifier=STRING Set syslog identifier\n"
45 " -p --priority=PRIORITY Set priority value (0..7)\n"
601185b4
ZJS
46 " --level-prefix=BOOL Control whether level prefix shall be parsed\n"
47 , program_invocation_short_name);
755a02c6
LP
48}
49
50static int parse_argv(int argc, char *argv[]) {
51
52 enum {
53 ARG_VERSION = 0x100,
54 ARG_LEVEL_PREFIX
55 };
56
57 static const struct option options[] = {
58 { "help", no_argument, NULL, 'h' },
9aac0b2c 59 { "version", no_argument, NULL, ARG_VERSION },
755a02c6
LP
60 { "identifier", required_argument, NULL, 't' },
61 { "priority", required_argument, NULL, 'p' },
62 { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX },
eb9da376 63 {}
755a02c6
LP
64 };
65
66 int c;
67
68 assert(argc >= 0);
69 assert(argv);
70
601185b4 71 while ((c = getopt_long(argc, argv, "+ht:p:", options, NULL)) >= 0)
755a02c6
LP
72
73 switch (c) {
74
75 case 'h':
601185b4
ZJS
76 help();
77 return 0;
755a02c6
LP
78
79 case ARG_VERSION:
3f6fd1ba 80 return version();
755a02c6
LP
81
82 case 't':
83 free(arg_identifier);
84 if (isempty(optarg))
85 arg_identifier = NULL;
86 else {
87 arg_identifier = strdup(optarg);
0d0f0c50
SL
88 if (!arg_identifier)
89 return log_oom();
755a02c6
LP
90 }
91 break;
92
93 case 'p':
94 arg_priority = log_level_from_string(optarg);
95 if (arg_priority < 0) {
96 log_error("Failed to parse priority value.");
e4603df5 97 return -EINVAL;
755a02c6
LP
98 }
99 break;
100
101 case ARG_LEVEL_PREFIX: {
102 int k;
103
104 k = parse_boolean(optarg);
939c173f
LP
105 if (k < 0)
106 return log_error_errno(k, "Failed to parse level prefix value.");
107
755a02c6
LP
108 arg_level_prefix = k;
109 break;
110 }
111
eb9da376 112 case '?':
755a02c6 113 return -EINVAL;
eb9da376
LP
114
115 default:
116 assert_not_reached("Unhandled option");
755a02c6 117 }
755a02c6
LP
118
119 return 1;
120}
121
122int main(int argc, char *argv[]) {
939c173f
LP
123 _cleanup_close_ int fd = -1, saved_stderr = -1;
124 int r;
755a02c6
LP
125
126 log_parse_environment();
127 log_open();
128
129 r = parse_argv(argc, argv);
130 if (r <= 0)
131 goto finish;
132
133 fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
134 if (fd < 0) {
939c173f 135 r = log_error_errno(fd, "Failed to create stream fd: %m");
755a02c6
LP
136 goto finish;
137 }
138
139 saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);
140
141 if (dup3(fd, STDOUT_FILENO, 0) < 0 ||
142 dup3(fd, STDERR_FILENO, 0) < 0) {
76ef789d 143 r = log_error_errno(errno, "Failed to duplicate fd: %m");
755a02c6
LP
144 goto finish;
145 }
146
147 if (fd >= 3)
03e334a1 148 safe_close(fd);
755a02c6
LP
149 fd = -1;
150
151 if (argc <= optind)
939c173f 152 (void) execl("/bin/cat", "/bin/cat", NULL);
755a02c6 153 else
939c173f 154 (void) execvp(argv[optind], argv + optind);
9aac0b2c
LP
155 r = -errno;
156
755a02c6
LP
157 /* Let's try to restore a working stderr, so we can print the error message */
158 if (saved_stderr >= 0)
939c173f 159 (void) dup3(saved_stderr, STDERR_FILENO, 0);
755a02c6 160
da927ba9 161 log_error_errno(r, "Failed to execute process: %m");
755a02c6
LP
162
163finish:
755a02c6
LP
164 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
165}