]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/cat.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[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 <errno.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28
29 #include "sd-journal.h"
30
31 #include "fd-util.h"
32 #include "parse-util.h"
33 #include "string-util.h"
34 #include "util.h"
35
36 static char *arg_identifier = NULL;
37 static int arg_priority = LOG_INFO;
38 static bool arg_level_prefix = true;
39
40 static void help(void) {
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
51 static int parse_argv(int argc, char *argv[]) {
52
53 enum {
54 ARG_VERSION = 0x100,
55 ARG_LEVEL_PREFIX
56 };
57
58 static const struct option options[] = {
59 { "help", no_argument, NULL, 'h' },
60 { "version", no_argument, NULL, ARG_VERSION },
61 { "identifier", required_argument, NULL, 't' },
62 { "priority", required_argument, NULL, 'p' },
63 { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX },
64 {}
65 };
66
67 int c;
68
69 assert(argc >= 0);
70 assert(argv);
71
72 while ((c = getopt_long(argc, argv, "+ht:p:", options, NULL)) >= 0)
73
74 switch (c) {
75
76 case 'h':
77 help();
78 return 0;
79
80 case ARG_VERSION:
81 return version();
82
83 case 't':
84 free(arg_identifier);
85 if (isempty(optarg))
86 arg_identifier = NULL;
87 else {
88 arg_identifier = strdup(optarg);
89 if (!arg_identifier)
90 return log_oom();
91 }
92 break;
93
94 case 'p':
95 arg_priority = log_level_from_string(optarg);
96 if (arg_priority < 0) {
97 log_error("Failed to parse priority value.");
98 return -EINVAL;
99 }
100 break;
101
102 case ARG_LEVEL_PREFIX: {
103 int k;
104
105 k = parse_boolean(optarg);
106 if (k < 0)
107 return log_error_errno(k, "Failed to parse level prefix value.");
108
109 arg_level_prefix = k;
110 break;
111 }
112
113 case '?':
114 return -EINVAL;
115
116 default:
117 assert_not_reached("Unhandled option");
118 }
119
120 return 1;
121 }
122
123 int main(int argc, char *argv[]) {
124 _cleanup_close_ int fd = -1, saved_stderr = -1;
125 int r;
126
127 log_parse_environment();
128 log_open();
129
130 r = parse_argv(argc, argv);
131 if (r <= 0)
132 goto finish;
133
134 fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
135 if (fd < 0) {
136 r = log_error_errno(fd, "Failed to create stream fd: %m");
137 goto finish;
138 }
139
140 saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);
141
142 if (dup3(fd, STDOUT_FILENO, 0) < 0 ||
143 dup3(fd, STDERR_FILENO, 0) < 0) {
144 r = log_error_errno(errno, "Failed to duplicate fd: %m");
145 goto finish;
146 }
147
148 if (fd >= 3)
149 safe_close(fd);
150 fd = -1;
151
152 if (argc <= optind)
153 (void) execl("/bin/cat", "/bin/cat", NULL);
154 else
155 (void) execvp(argv[optind], argv + optind);
156 r = -errno;
157
158 /* Let's try to restore a working stderr, so we can print the error message */
159 if (saved_stderr >= 0)
160 (void) dup3(saved_stderr, STDERR_FILENO, 0);
161
162 log_error_errno(r, "Failed to execute process: %m");
163
164 finish:
165 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
166 }