Coverage Report

Created: 2025-10-10 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tmux/cmd-display-message.c
Line
Count
Source
1
/* $OpenBSD$ */
2
3
/*
4
 * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
21
#include <stdlib.h>
22
#include <time.h>
23
24
#include "tmux.h"
25
26
/*
27
 * Displays a message in the status line.
28
 */
29
30
#define DISPLAY_MESSAGE_TEMPLATE      \
31
0
  "[#{session_name}] #{window_index}:"    \
32
0
  "#{window_name}, current pane #{pane_index} " \
33
0
  "- (%H:%M %d-%b-%y)"
34
35
static enum cmd_retval  cmd_display_message_exec(struct cmd *,
36
          struct cmdq_item *);
37
38
const struct cmd_entry cmd_display_message_entry = {
39
  .name = "display-message",
40
  .alias = "display",
41
42
  .args = { "aCc:d:lINpt:F:v", 0, 1, NULL },
43
  .usage = "[-aCIlNpv] [-c target-client] [-d delay] [-F format] "
44
     CMD_TARGET_PANE_USAGE " [message]",
45
46
  .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
47
48
  .flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL,
49
  .exec = cmd_display_message_exec
50
};
51
52
static void
53
cmd_display_message_each(const char *key, const char *value, void *arg)
54
0
{
55
0
  struct cmdq_item  *item = arg;
56
57
0
  cmdq_print(item, "%s=%s", key, value);
58
0
}
59
60
static enum cmd_retval
61
cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
62
0
{
63
0
  struct args   *args = cmd_get_args(self);
64
0
  struct cmd_find_state *target = cmdq_get_target(item);
65
0
  struct client   *tc = cmdq_get_target_client(item), *c;
66
0
  struct session    *s = target->s;
67
0
  struct winlink    *wl = target->wl;
68
0
  struct window_pane  *wp = target->wp;
69
0
  const char    *template;
70
0
  char      *msg, *cause;
71
0
  int      delay = -1, flags, Nflag = args_has(args, 'N');
72
0
  int      Cflag = args_has(args, 'C');
73
0
  struct format_tree  *ft;
74
0
  u_int      count = args_count(args);
75
0
  struct evbuffer   *evb;
76
77
0
  if (args_has(args, 'I')) {
78
0
    if (wp == NULL)
79
0
      return (CMD_RETURN_NORMAL);
80
0
    switch (window_pane_start_input(wp, item, &cause)) {
81
0
    case -1:
82
0
      cmdq_error(item, "%s", cause);
83
0
      free(cause);
84
0
      return (CMD_RETURN_ERROR);
85
0
    case 1:
86
0
      return (CMD_RETURN_NORMAL);
87
0
    case 0:
88
0
      return (CMD_RETURN_WAIT);
89
0
    }
90
0
  }
91
92
0
  if (args_has(args, 'F') && count != 0) {
93
0
    cmdq_error(item, "only one of -F or argument must be given");
94
0
    return (CMD_RETURN_ERROR);
95
0
  }
96
97
0
  if (args_has(args, 'd')) {
98
0
    delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause);
99
0
    if (cause != NULL) {
100
0
      cmdq_error(item, "delay %s", cause);
101
0
      free(cause);
102
0
      return (CMD_RETURN_ERROR);
103
0
    }
104
0
  }
105
106
0
  if (count != 0)
107
0
    template = args_string(args, 0);
108
0
  else
109
0
    template = args_get(args, 'F');
110
0
  if (template == NULL)
111
0
    template = DISPLAY_MESSAGE_TEMPLATE;
112
113
  /*
114
   * -c is intended to be the client where the message should be
115
   * displayed if -p is not given. But it makes sense to use it for the
116
   * formats too, assuming it matches the session. If it doesn't, use the
117
   * best client for the session.
118
   */
119
0
  if (tc != NULL && tc->session == s)
120
0
    c = tc;
121
0
  else if (s != NULL)
122
0
    c = cmd_find_best_client(s);
123
0
  else
124
0
    c = NULL;
125
0
  if (args_has(args, 'v'))
126
0
    flags = FORMAT_VERBOSE;
127
0
  else
128
0
    flags = 0;
129
0
  ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, flags);
130
0
  format_defaults(ft, c, s, wl, wp);
131
132
0
  if (args_has(args, 'a')) {
133
0
    format_each(ft, cmd_display_message_each, item);
134
0
    return (CMD_RETURN_NORMAL);
135
0
  }
136
137
0
  if (args_has(args, 'l'))
138
0
    msg = xstrdup(template);
139
0
  else
140
0
    msg = format_expand_time(ft, template);
141
142
0
  if (cmdq_get_client(item) == NULL)
143
0
    cmdq_error(item, "%s", msg);
144
0
  else if (args_has(args, 'p'))
145
0
    cmdq_print(item, "%s", msg);
146
0
  else if (tc != NULL && (tc->flags & CLIENT_CONTROL)) {
147
0
    evb = evbuffer_new();
148
0
    if (evb == NULL)
149
0
      fatalx("out of memory");
150
0
    evbuffer_add_printf(evb, "%%message %s", msg);
151
0
    server_client_print(tc, 0, evb);
152
0
    evbuffer_free(evb);
153
0
  } else if (tc != NULL)
154
0
    status_message_set(tc, delay, 0, Nflag, Cflag, "%s", msg);
155
0
  free(msg);
156
157
0
  format_free(ft);
158
159
0
  return (CMD_RETURN_NORMAL);
160
0
}