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