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