Check for PFNAME #define as it is a common substitute for a literal string for the...
[metze/wireshark/wip.git] / ui / pipe_input.c
1 /* pipe_input.c
2  * Pipe input routines. Declared in pipe_input.h
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <glib.h>
30
31 #include "pipe_input.h"
32
33 #ifdef _WIN32
34 #include <windows.h>
35 #include <io.h>
36 #endif
37
38 #ifdef HAVE_LIBPCAP
39
40 typedef struct pipe_input_tag {
41     gint                source;
42     gpointer            user_data;
43     int                 *child_process;
44     pipe_input_cb_t     input_cb;
45     guint               pipe_input_id;
46 #ifdef _WIN32
47 #else
48     GIOChannel          *channel;
49 #endif
50 } pipe_input_t;
51
52
53 #ifdef _WIN32
54 /* The timer has expired, see if there's stuff to read from the pipe,
55    if so, do the callback */
56 static gboolean
57 pipe_timer_cb(gpointer data)
58 {
59     HANDLE handle;
60     DWORD avail = 0;
61     gboolean result, result1;
62     DWORD childstatus;
63     pipe_input_t *pipe_input = data;
64     gint iterations = 0;
65
66
67     /* try to read data from the pipe only 5 times, to avoid blocking */
68     while(iterations < 5) {
69         /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: new iteration");*/
70
71         /* Oddly enough although Named pipes don't work on win9x,
72            PeekNamedPipe does !!! */
73         handle = (HANDLE) _get_osfhandle (pipe_input->source);
74         result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
75
76         /* Get the child process exit status */
77         result1 = GetExitCodeProcess((HANDLE)*(pipe_input->child_process),
78                                      &childstatus);
79
80         /* If the Peek returned an error, or there are bytes to be read
81            or the childwatcher thread has terminated then call the normal
82            callback */
83         if (!result || avail > 0 || childstatus != STILL_ACTIVE) {
84
85             /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: data avail");*/
86
87             if(pipe_input->pipe_input_id != 0) {
88                 /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: stop timer");*/
89                 /* avoid reentrancy problems and stack overflow */
90                 g_source_remove(pipe_input->pipe_input_id);
91                 pipe_input->pipe_input_id = 0;
92             }
93
94             /* And call the real handler */
95             if (!pipe_input->input_cb(pipe_input->source, pipe_input->user_data)) {
96                 g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: input pipe closed, iterations: %u", iterations);
97                 /* pipe closed, return false so that the old timer is not run again */
98                 return FALSE;
99             }
100         }
101         else {
102             /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: no data avail");*/
103             /* No data, stop now */
104             break;
105         }
106
107         iterations++;
108     }
109
110     if(pipe_input->pipe_input_id == 0) {
111         /* restore pipe handler */
112         pipe_input->pipe_input_id = g_timeout_add(200, pipe_timer_cb, data);
113         /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: finished with iterations: %u, new timer", iterations);*/
114
115         /* Return false so that the old timer is not run again */
116         return FALSE;
117     } else {
118         /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: finished with iterations: %u, old timer", iterations);*/
119
120         /* we didn't stopped the old timer, so let it run */
121         return TRUE;
122     }
123 }
124
125 #else /* _WIN32 */
126
127 /* There's stuff to read from the sync pipe, meaning the child has sent
128    us a message, or the sync pipe has closed, meaning the child has
129    closed it (perhaps because it exited). */
130 static gboolean
131 pipe_input_cb(GIOChannel *source _U_, GIOCondition condition _U_,
132                gpointer data)
133 {
134     pipe_input_t *pipe_input = data;
135
136
137     /* avoid reentrancy problems and stack overflow */
138     g_source_remove(pipe_input->pipe_input_id);
139
140     if (pipe_input->input_cb(pipe_input->source, pipe_input->user_data)) {
141         /* restore pipe handler */
142         pipe_input->pipe_input_id = g_io_add_watch_full (pipe_input->channel,
143                                                          G_PRIORITY_HIGH,
144                                                          G_IO_IN|G_IO_ERR|G_IO_HUP,
145                                                          pipe_input_cb,
146                                                          pipe_input,
147                                                          NULL);
148     }
149     return TRUE;
150 }
151 #endif
152
153 void pipe_input_set_handler(gint source, gpointer user_data, int *child_process, pipe_input_cb_t input_cb)
154 {
155     static pipe_input_t pipe_input;
156
157     pipe_input.source        = source;
158     pipe_input.child_process = child_process;
159     pipe_input.user_data     = user_data;
160     pipe_input.input_cb      = input_cb;
161
162 #ifdef _WIN32
163     /* Tricky to use pipes in win9x, as no concept of wait.  NT can
164        do this but that doesn't cover all win32 platforms.  GTK can do
165        this but doesn't seem to work over processes.  Attempt to do
166        something similar here, start a timer and check for data on every
167        timeout. */
168        /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_input_set_handler: new");*/
169     pipe_input.pipe_input_id = g_timeout_add(200, pipe_timer_cb, &pipe_input);
170 #else /* _WIN32 */
171     pipe_input.channel = g_io_channel_unix_new(source);
172     g_io_channel_set_encoding(pipe_input.channel, NULL, NULL);
173     pipe_input.pipe_input_id = g_io_add_watch_full(pipe_input.channel,
174                                                    G_PRIORITY_HIGH,
175                                                    G_IO_IN|G_IO_ERR|G_IO_HUP,
176                                                    pipe_input_cb,
177                                                    &pipe_input,
178                                                    NULL);
179 #endif /* _WIN32 */
180 }
181
182 #endif /* HAVE_LIBPCAP */