1 // Functions for handling event triggers
2 //
3 // Because most of these functions can be called by signal handler, it is important to make it well
4 // defined when these functions produce output or perform memory allocations, since such functions
5 // may not be safely called by signal handlers.
6 #ifndef FISH_EVENT_H
7 #define FISH_EVENT_H
8 
9 #include <unistd.h>
10 
11 #include <map>
12 #include <memory>
13 #include <vector>
14 
15 #include "common.h"
16 #include "io.h"
17 
18 /// The process id that is used to match any process id.
19 #define EVENT_ANY_PID 0
20 
21 /// Enumeration of event types.
22 enum class event_type_t {
23     /// Matches any event type (Not always any event, as the function name may limit the choice as
24     /// well.
25     any,
26     /// An event triggered by a signal.
27     signal,
28     /// An event triggered by a variable update.
29     variable,
30     /// An event triggered by a process exit.
31     process_exit,
32     /// An event triggered by a job exit.
33     job_exit,
34     /// An event triggered by a job exit, triggering the 'caller'-style events only.
35     caller_exit,
36     /// A generic event.
37     generic,
38 };
39 
40 /// Null-terminated list of valid event filter names.
41 /// These are what are valid to pass to 'functions --handlers-type'
42 extern const wchar_t *const event_filter_names[];
43 
44 /// Properties of an event.
45 struct event_description_t {
46     /// Helper type for on-job-exit events.
47     struct job_spec_t {
48         // pid requested by the event, or ANY_PID for all.
49         pid_t pid;
50 
51         // internal_job_id of the job to match.
52         // If this is 0, we match either all jobs (pid == ANY_PID) or no jobs (otherwise).
53         uint64_t internal_job_id;
54     };
55 
56     /// The event type.
57     event_type_t type;
58 
59     /// The type-specific parameter. The int types are one of the following:
60     ///
61     /// signal: Signal number for signal-type events.Use EVENT_ANY_SIGNAL to match any signal
62     /// pid: Process id for process-type events. Use EVENT_ANY_PID to match any pid.
63     /// jobspec: Info for on-job-exit events.
64     /// caller_id: Internal job id for caller_exit type events
65     union {
66         int signal;
67         pid_t pid;
68         job_spec_t jobspec;
69         uint64_t caller_id;
70     } param1{};
71 
72     /// The string types are one of the following:
73     ///
74     /// variable: Variable name for variable-type events.
75     /// param: The parameter describing this generic event.
76     wcstring str_param1{};
77 
event_description_tevent_description_t78     explicit event_description_t(event_type_t t) : type(t) {}
79     static event_description_t signal(int sig);
80     static event_description_t variable(wcstring str);
81     static event_description_t generic(wcstring str);
82 };
83 
84 /// Represents a handler for an event.
85 struct event_handler_t {
86     /// Properties of the event to match.
87     event_description_t desc;
88 
89     /// Name of the function to invoke.
90     wcstring function_name{};
91 
event_handler_tevent_handler_t92     explicit event_handler_t(event_type_t t) : desc(t) {}
event_handler_tevent_handler_t93     event_handler_t(event_description_t d, wcstring name)
94         : desc(std::move(d)), function_name(std::move(name)) {}
95 };
96 using event_handler_list_t = std::vector<std::shared_ptr<event_handler_t>>;
97 
98 /// Represents a event that is fired, or capable of being fired.
99 struct event_t {
100     /// Properties of the event.
101     event_description_t desc;
102 
103     /// Arguments to any handler.
104     wcstring_list_t arguments{};
105 
event_tevent_t106     explicit event_t(event_type_t t) : desc(t) {}
107 
108     /// Create an event_type_t::variable event.
109     static event_t variable(wcstring name, wcstring_list_t args);
110 
111     /// Create a PROCESS_EXIT event.
112     static event_t process_exit(pid_t pid, int status);
113 
114     /// Create a JOB_EXIT event. The pgid should be positive.
115     /// The reported status is always 0 for historical reasons.
116     static event_t job_exit(pid_t pgid, internal_job_id_t jid);
117 
118     /// Create a caller_exit event.
119     static event_t caller_exit(uint64_t internal_job_id, int job_id);
120 };
121 
122 class parser_t;
123 
124 /// Add an event handler.
125 void event_add_handler(std::shared_ptr<event_handler_t> eh);
126 
127 /// Remove all events for the given function name.
128 void event_remove_function_handlers(const wcstring &name);
129 
130 /// Return all event handlers for the given function.
131 event_handler_list_t event_get_function_handlers(const wcstring &name);
132 
133 /// Returns whether an event listener is registered for the given signal. This is safe to call from
134 /// a signal handler.
135 bool event_is_signal_observed(int signal);
136 
137 /// Fire the specified event \p event, executing it on \p parser.
138 void event_fire(parser_t &parser, const event_t &event);
139 
140 /// Fire all delayed events attached to the given parser.
141 void event_fire_delayed(parser_t &parser);
142 
143 /// Enqueue a signal event. Invoked from a signal handler.
144 void event_enqueue_signal(int signal);
145 
146 /// Print all events. If type_filter is not empty, only output events with that type.
147 void event_print(io_streams_t &streams, const wcstring &type_filter);
148 
149 /// Returns a string describing the specified event.
150 wcstring event_get_desc(const parser_t &parser, const event_t &e);
151 
152 /// Fire a generic event with the specified name.
153 void event_fire_generic(parser_t &parser, const wchar_t *name,
154                         const wcstring_list_t *args = nullptr);
155 
156 #endif
157