1 /* ws_pipe.h
2 *
3 * Routines for handling pipes.
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #ifndef __WS_PIPE_H__
13 #define __WS_PIPE_H__
14
15 // ws_symbol_export and WS_INVALID_PID
16 #include "wsutil/processes.h"
17
18 #include <glib.h>
19
20 #ifdef _WIN32
21 #include <windows.h>
22 #include <io.h>
23 #define ws_pipe_handle HANDLE
24 #define ws_get_pipe_handle(pipe_fd) ((HANDLE)_get_osfhandle(pipe_fd))
25 #else
26 #define ws_pipe_handle int
27 #define ws_get_pipe_handle(pipe_fd) (pipe_fd)
28 #endif
29
30 typedef struct _ws_pipe_t {
31 GPid pid;
32 gchar *stderr_msg;
33 gint exitcode;
34 gint stdin_fd;
35 gint stdout_fd;
36 gint stderr_fd;
37 #ifdef _WIN32
38 HANDLE threadId;
39 #endif
40 } ws_pipe_t;
41
42 /**
43 * @brief Run a process using g_spawn_sync on UNIX and Linux, and
44 * CreateProcess on Windows. Wait for it to finish.
45 * @param [IN] working_directory Initial working directory.
46 * @param [IN] command Command to run.
47 * @param [IN] argc Number of arguments for the command, not including the command itself.
48 * @param [IN] args Arguments for the command, not including the command itself.
49 * The last element must be NULL.
50 * @param [OUT] command_output If not NULL, receives a copy of the command output. Must be g_freed.
51 * @return TRUE on success or FALSE on failure.
52 */
53 WS_DLL_PUBLIC gboolean ws_pipe_spawn_sync(const gchar * working_directory, const gchar * command, gint argc, gchar ** args, gchar ** command_output);
54
55 /**
56 * @brief Initialize a ws_pipe_t struct. Sets .pid to WS_INVALID_PID and all other members to 0 or NULL.
57 * @param ws_pipe [IN] The pipe to initialize.
58 */
59 WS_DLL_PUBLIC void ws_pipe_init(ws_pipe_t *ws_pipe);
60
61 /**
62 * @brief Checks whether a pipe is valid (for reading or writing).
63 */
ws_pipe_valid(ws_pipe_t * ws_pipe)64 static inline gboolean ws_pipe_valid(ws_pipe_t *ws_pipe)
65 {
66 return ws_pipe && ws_pipe->pid && ws_pipe->pid != WS_INVALID_PID;
67 }
68
69 /**
70 * @brief Start a process using g_spawn_sync on UNIX and Linux, and CreateProcess on Windows.
71 * @param ws_pipe The process PID, stdio descriptors, etc.
72 * @param args The command to run along with its arguments.
73 * @return A valid PID on success, otherwise WS_INVALID_PID.
74 */
75 WS_DLL_PUBLIC GPid ws_pipe_spawn_async (ws_pipe_t * ws_pipe, GPtrArray * args );
76
77 /**
78 * @brief Stop a process started with ws_pipe_spawn_async
79 * @param ws_pipe The process PID, stdio descriptors, etc.
80 */
81 WS_DLL_PUBLIC void ws_pipe_close(ws_pipe_t * ws_pipe);
82
83 #ifdef _WIN32
84 /**
85 * @brief Wait for a set of handles using WaitForMultipleObjects. Windows only.
86 * @param pipe_handles An array of handles
87 * @param num_pipe_handles The size of the array.
88 * @param pid Child process PID.
89 * @return TRUE on success or FALSE on failure.
90 */
91 WS_DLL_PUBLIC gboolean ws_pipe_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid);
92 #endif
93
94 /**
95 * @brief Check to see if a file descriptor has data available.
96 * @param pipe_fd File descriptor, usually ws_pipe_t .stdout_fd or .stderr_fd.
97 * @return TRUE if data is available or FALSE otherwise.
98 */
99 WS_DLL_PUBLIC gboolean ws_pipe_data_available(int pipe_fd);
100
101 /**
102 * @brief Read up to buffer_size - 1 bytes from a pipe and append '\0' to the buffer.
103 * @param read_pipe File descriptor, usually ws_pipe_t .stdout_fd or .stderr_fd.
104 * @param buffer String buffer.
105 * @param buffer_size String buffer size.
106 * @return TRUE if zero or more bytes were read without error, FALSE otherwise.
107 */
108 WS_DLL_PUBLIC gboolean ws_read_string_from_pipe(ws_pipe_handle read_pipe,
109 gchar *buffer, size_t buffer_size);
110
111 #endif /* __WS_PIPE_H__ */
112
113 /*
114 * Editor modelines - https://www.wireshark.org/tools/modelines.html
115 *
116 * Local variables:
117 * c-basic-offset: 4
118 * tab-width: 8
119 * indent-tabs-mode: nil
120 * End:
121 *
122 * vi: set shiftwidth=4 tabstop=8 expandtab:
123 * :indentSize=4:tabSize=8:noTabs=true:
124 */
125