LCOV - code coverage report
Current view: top level - core - show-status.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 1 53 1.9 %
Date: 2019-08-22 15:41:25 Functions: 2 7 28.6 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <fcntl.h>
       4             : #include <sys/stat.h>
       5             : #include <sys/types.h>
       6             : 
       7             : #include "alloc-util.h"
       8             : #include "fd-util.h"
       9             : #include "io-util.h"
      10             : #include "parse-util.h"
      11             : #include "show-status.h"
      12             : #include "string-table.h"
      13             : #include "string-util.h"
      14             : #include "terminal-util.h"
      15             : #include "util.h"
      16             : 
      17             : static const char* const show_status_table[_SHOW_STATUS_MAX] = {
      18             :         [SHOW_STATUS_NO]        = "no",
      19             :         [SHOW_STATUS_AUTO]      = "auto",
      20             :         [SHOW_STATUS_TEMPORARY] = "temporary",
      21             :         [SHOW_STATUS_YES]       = "yes",
      22             : };
      23             : 
      24          12 : DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(show_status, ShowStatus, SHOW_STATUS_YES);
      25             : 
      26           0 : int parse_show_status(const char *v, ShowStatus *ret) {
      27             :         ShowStatus s;
      28             : 
      29           0 :         assert(ret);
      30             : 
      31           0 :         s = show_status_from_string(v);
      32           0 :         if (s < 0 || s == SHOW_STATUS_TEMPORARY)
      33           0 :                 return -EINVAL;
      34             : 
      35           0 :         *ret = s;
      36           0 :         return 0;
      37             : }
      38             : 
      39           0 : int status_vprintf(const char *status, ShowStatusFlags flags, const char *format, va_list ap) {
      40             :         static const char status_indent[] = "         "; /* "[" STATUS "] " */
      41           0 :         _cleanup_free_ char *s = NULL;
      42           0 :         _cleanup_close_ int fd = -1;
      43           0 :         struct iovec iovec[7] = {};
      44           0 :         int n = 0;
      45             :         static bool prev_ephemeral;
      46             : 
      47           0 :         assert(format);
      48             : 
      49             :         /* This is independent of logging, as status messages are
      50             :          * optional and go exclusively to the console. */
      51             : 
      52           0 :         if (vasprintf(&s, format, ap) < 0)
      53           0 :                 return log_oom();
      54             : 
      55             :         /* Before you ask: yes, on purpose we open/close the console for each status line we write individually. This
      56             :          * is a good strategy to avoid PID 1 getting killed by the kernel's SAK concept (it doesn't fix this entirely,
      57             :          * but minimizes the time window the kernel might end up killing PID 1 due to SAK). It also makes things easier
      58             :          * for us so that we don't have to recover from hangups and suchlike triggered on the console. */
      59             : 
      60           0 :         fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
      61           0 :         if (fd < 0)
      62           0 :                 return fd;
      63             : 
      64           0 :         if (FLAGS_SET(flags, SHOW_STATUS_ELLIPSIZE)) {
      65             :                 char *e;
      66             :                 size_t emax, sl;
      67             :                 int c;
      68             : 
      69           0 :                 c = fd_columns(fd);
      70           0 :                 if (c <= 0)
      71           0 :                         c = 80;
      72             : 
      73           0 :                 sl = status ? sizeof(status_indent)-1 : 0;
      74             : 
      75           0 :                 emax = c - sl - 1;
      76           0 :                 if (emax < 3)
      77           0 :                         emax = 3;
      78             : 
      79           0 :                 e = ellipsize(s, emax, 50);
      80           0 :                 if (e)
      81           0 :                         free_and_replace(s, e);
      82             :         }
      83             : 
      84           0 :         if (prev_ephemeral)
      85           0 :                 iovec[n++] = IOVEC_MAKE_STRING(ANSI_REVERSE_LINEFEED "\r" ANSI_ERASE_TO_END_OF_LINE);
      86             : 
      87           0 :         if (status) {
      88           0 :                 if (!isempty(status)) {
      89           0 :                         iovec[n++] = IOVEC_MAKE_STRING("[");
      90           0 :                         iovec[n++] = IOVEC_MAKE_STRING(status);
      91           0 :                         iovec[n++] = IOVEC_MAKE_STRING("] ");
      92             :                 } else
      93           0 :                         iovec[n++] = IOVEC_MAKE_STRING(status_indent);
      94             :         }
      95             : 
      96           0 :         iovec[n++] = IOVEC_MAKE_STRING(s);
      97           0 :         iovec[n++] = IOVEC_MAKE_STRING("\n");
      98             : 
      99           0 :         if (prev_ephemeral && !FLAGS_SET(flags, SHOW_STATUS_EPHEMERAL))
     100           0 :                 iovec[n++] = IOVEC_MAKE_STRING(ANSI_ERASE_TO_END_OF_LINE);
     101           0 :         prev_ephemeral = FLAGS_SET(flags, SHOW_STATUS_EPHEMERAL) ;
     102             : 
     103           0 :         if (writev(fd, iovec, n) < 0)
     104           0 :                 return -errno;
     105             : 
     106           0 :         return 0;
     107             : }
     108             : 
     109           0 : int status_printf(const char *status, ShowStatusFlags flags, const char *format, ...) {
     110             :         va_list ap;
     111             :         int r;
     112             : 
     113           0 :         assert(format);
     114             : 
     115           0 :         va_start(ap, format);
     116           0 :         r = status_vprintf(status, flags, format, ap);
     117           0 :         va_end(ap);
     118             : 
     119           0 :         return r;
     120             : }
     121             : 
     122             : static const char* const status_unit_format_table[_STATUS_UNIT_FORMAT_MAX] = {
     123             :         [STATUS_UNIT_FORMAT_NAME]        = "name",
     124             :         [STATUS_UNIT_FORMAT_DESCRIPTION] = "description",
     125             : };
     126             : 
     127           0 : DEFINE_STRING_TABLE_LOOKUP(status_unit_format, StatusUnitFormat);

Generated by: LCOV version 1.14