LCOV - code coverage report
Current view: top level - journal - cat.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 25 72 34.7 %
Date: 2019-08-22 15:41:25 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <fcntl.h>
       5             : #include <getopt.h>
       6             : #include <stdio.h>
       7             : #include <stdlib.h>
       8             : #include <unistd.h>
       9             : 
      10             : #include "sd-journal.h"
      11             : 
      12             : #include "alloc-util.h"
      13             : #include "fd-util.h"
      14             : #include "main-func.h"
      15             : #include "parse-util.h"
      16             : #include "pretty-print.h"
      17             : #include "string-util.h"
      18             : #include "syslog-util.h"
      19             : #include "util.h"
      20             : 
      21             : static const char *arg_identifier = NULL;
      22             : static int arg_priority = LOG_INFO;
      23             : static int arg_stderr_priority = -1;
      24             : static bool arg_level_prefix = true;
      25             : 
      26           3 : static int help(void) {
      27           3 :         _cleanup_free_ char *link = NULL;
      28             :         int r;
      29             : 
      30           3 :         r = terminal_urlify_man("systemd-cat", "1", &link);
      31           3 :         if (r < 0)
      32           0 :                 return log_oom();
      33             : 
      34           3 :         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
      35             :                "Execute process with stdout/stderr connected to the journal.\n\n"
      36             :                "  -h --help                      Show this help\n"
      37             :                "     --version                   Show package version\n"
      38             :                "  -t --identifier=STRING         Set syslog identifier\n"
      39             :                "  -p --priority=PRIORITY         Set priority value (0..7)\n"
      40             :                "     --stderr-priority=PRIORITY  Set priority value (0..7) used for stderr\n"
      41             :                "     --level-prefix=BOOL         Control whether level prefix shall be parsed\n"
      42             :                "\nSee the %s for details.\n"
      43             :                , program_invocation_short_name
      44             :                , link
      45             :         );
      46             : 
      47           3 :         return 0;
      48             : }
      49             : 
      50           4 : static int parse_argv(int argc, char *argv[]) {
      51             : 
      52             :         enum {
      53             :                 ARG_VERSION = 0x100,
      54             :                 ARG_STDERR_PRIORITY,
      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             :                 { "stderr-priority", required_argument, NULL, ARG_STDERR_PRIORITY },
      64             :                 { "level-prefix",    required_argument, NULL, ARG_LEVEL_PREFIX    },
      65             :                 {}
      66             :         };
      67             : 
      68             :         int c;
      69             : 
      70           4 :         assert(argc >= 0);
      71           4 :         assert(argv);
      72             : 
      73           4 :         while ((c = getopt_long(argc, argv, "+ht:p:", options, NULL)) >= 0)
      74             : 
      75           4 :                 switch (c) {
      76             : 
      77           3 :                 case 'h':
      78           3 :                         help();
      79           3 :                         return 0;
      80             : 
      81           0 :                 case ARG_VERSION:
      82           0 :                         return version();
      83             : 
      84           0 :                 case 't':
      85           0 :                         if (isempty(optarg))
      86           0 :                                 arg_identifier = NULL;
      87             :                         else
      88           0 :                                 arg_identifier = optarg;
      89           0 :                         break;
      90             : 
      91           0 :                 case 'p':
      92           0 :                         arg_priority = log_level_from_string(optarg);
      93           0 :                         if (arg_priority < 0)
      94           0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
      95             :                                                        "Failed to parse priority value.");
      96           0 :                         break;
      97             : 
      98           0 :                 case ARG_STDERR_PRIORITY:
      99           0 :                         arg_stderr_priority = log_level_from_string(optarg);
     100           0 :                         if (arg_stderr_priority < 0)
     101           0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     102             :                                                        "Failed to parse stderr priority value.");
     103           0 :                         break;
     104             : 
     105           0 :                 case ARG_LEVEL_PREFIX: {
     106             :                         int k;
     107             : 
     108           0 :                         k = parse_boolean(optarg);
     109           0 :                         if (k < 0)
     110           0 :                                 return log_error_errno(k, "Failed to parse level prefix value.");
     111             : 
     112           0 :                         arg_level_prefix = k;
     113           0 :                         break;
     114             :                 }
     115             : 
     116           1 :                 case '?':
     117           1 :                         return -EINVAL;
     118             : 
     119           0 :                 default:
     120           0 :                         assert_not_reached("Unhandled option");
     121             :                 }
     122             : 
     123           0 :         return 1;
     124             : }
     125             : 
     126           4 : static int run(int argc, char *argv[]) {
     127           4 :         _cleanup_close_ int outfd = -1, errfd = -1, saved_stderr = -1;
     128             :         int r;
     129             : 
     130           4 :         log_show_color(true);
     131           4 :         log_parse_environment();
     132           4 :         log_open();
     133             : 
     134           4 :         r = parse_argv(argc, argv);
     135           4 :         if (r <= 0)
     136           4 :                 return r;
     137             : 
     138           0 :         outfd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
     139           0 :         if (outfd < 0)
     140           0 :                 return log_error_errno(outfd, "Failed to create stream fd: %m");
     141             : 
     142           0 :         if (arg_stderr_priority >= 0 && arg_stderr_priority != arg_priority) {
     143           0 :                 errfd = sd_journal_stream_fd(arg_identifier, arg_stderr_priority, arg_level_prefix);
     144           0 :                 if (errfd < 0)
     145           0 :                         return log_error_errno(errfd, "Failed to create stream fd: %m");
     146             :         }
     147             : 
     148           0 :         saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);
     149             : 
     150           0 :         r = rearrange_stdio(STDIN_FILENO, outfd, errfd < 0 ? outfd : errfd); /* Invalidates fd on success + error! */
     151           0 :         TAKE_FD(outfd);
     152           0 :         TAKE_FD(errfd);
     153           0 :         if (r < 0)
     154           0 :                 return log_error_errno(r, "Failed to rearrange stdout/stderr: %m");
     155             : 
     156           0 :         if (argc <= optind)
     157           0 :                 (void) execl("/bin/cat", "/bin/cat", NULL);
     158             :         else
     159           0 :                 (void) execvp(argv[optind], argv + optind);
     160           0 :         r = -errno;
     161             : 
     162             :         /* Let's try to restore a working stderr, so we can print the error message */
     163           0 :         if (saved_stderr >= 0)
     164           0 :                 (void) dup3(saved_stderr, STDERR_FILENO, 0);
     165             : 
     166           0 :         return log_error_errno(r, "Failed to execute process: %m");
     167             : }
     168             : 
     169           4 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14