Contents of /trunk/src/geotoad.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 193 - (show annotations)
Tue Nov 17 20:13:09 2009 UTC (14 years, 6 months ago) by harbaum
File MIME type: text/plain
File size: 4553 byte(s)
Started work on GeoToad
1 /*
2 * Copyright (C) 2009 Till Harbaum <till@harbaum.org>.
3 *
4 * This file is part of GPXView.
5 *
6 * GPXView is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GPXView is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GPXView. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "gpxview.h"
21
22 #include <fcntl.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <errno.h>
26
27 #define BUFFER_SIZE 1500
28
29 typedef struct {
30 char buf[BUFFER_SIZE];
31 int bused;
32
33 /** gdk input tag for async IO */
34 gint stdout_tag, stderr_tag;
35 gint stdin_fd, stdout_fd, stderr_fd;
36
37 } gt_context_t;
38
39 /* watch child process and receive events */
40 static void child_state_cb(GPid pid, gint status, gpointer data) {
41
42 puts("child state");
43
44 if(WIFEXITED(status)) {
45 }
46
47 puts("gt exited");
48
49 /* Reap child if needed. */
50 waitpid (pid, NULL, WNOHANG);
51 }
52
53 static void child_input_cb(gpointer data, int fd, GdkInputCondition cond) {
54 gt_context_t *context = (gt_context_t*)data;
55
56 ssize_t bytes;
57 int errnosave=0;
58
59 if(cond != GDK_INPUT_READ) {
60 puts("fixme");
61 return;
62 }
63
64 /* append to current buffer content */
65 while( (bytes = read(fd, context->buf+context->bused,
66 sizeof(context->buf) - context->bused - 1)) > 0) {
67 context->bused += bytes;
68 context->buf[context->bused]='\0';
69
70 /* consume line by line */
71 gchar *ptr = context->buf;
72
73 /* parse as long as the buffer contains a newline */
74 while( strchr(ptr, '\n') != NULL) {
75 char *p = strchr(ptr, '\n');
76 *p = '\0';
77
78 printf("line: %s\n", ptr);
79
80 ptr = p+1;
81 }
82
83 /* move remaining bytes down the buffer */
84 memmove(context->buf, ptr, sizeof(context->buf)-(ptr-context->buf));
85 context->bused -= ptr - context->buf;
86
87 /* check if buffer is full but doesn't contain any newline */
88 if(context->bused >= sizeof(context->buf)-1) {
89 printf("ERROR: reply buffer overflow\n");
90 context->bused = 0;
91 }
92 }
93
94 /* save errno from read */
95 errnosave=errno;
96
97 if(errnosave != EAGAIN && errnosave != 0) {
98 /* we probably hit EOF */
99 puts("removing io");
100
101 // TODO: fixme, make sure process is dead! kill it otherwise, but dont
102 // issue an vpnc_disconnect(NULL) !!!!
103
104 gdk_input_remove(context->stdout_tag);
105 gdk_input_remove(context->stderr_tag);
106
107 printf("freeing context\n");
108 g_free(context);
109 }
110 }
111
112 void geotoad(appdata_t *appdata) {
113 gt_context_t *context = g_new0(gt_context_t, 1);
114
115 printf("geoToad\n");
116
117 /* setup context */
118 context->bused = 0;
119 context->stdout_tag = -1;
120 context->stderr_tag = -1;
121 context->stdin_fd = -1;
122 context->stderr_fd = -1;
123 context->stderr_fd = -1;
124
125 /* build list of arguments */
126 GPtrArray *gt_argv = g_ptr_array_new();
127 g_ptr_array_add (gt_argv, "/usr/bin/env");
128 // g_ptr_array_add (gt_argv, "/tmp");
129 g_ptr_array_add (gt_argv, NULL);
130
131 GError *error=NULL;
132 GPid pid;
133 GSource *gt_watch;
134
135 if (!g_spawn_async_with_pipes (NULL, /* CWD */
136 (char **) gt_argv->pdata, /* argv */
137 NULL, /* envp */
138 G_SPAWN_DO_NOT_REAP_CHILD, /* flags */
139 NULL, /* child setup */
140 NULL, /* user data */
141 &pid,
142 &context->stdin_fd,
143 &context->stdout_fd,
144 &context->stderr_fd,
145 &error)) {
146 g_ptr_array_free(gt_argv, TRUE);
147 errorf(_("GeoToad failed to start.\n\nError: '%s'"), error->message);
148 g_error_free(error);
149 return;
150 }
151 g_ptr_array_free (gt_argv, TRUE);
152
153 printf("GeoToad: pid = %d\n", pid);
154
155 gt_watch = g_child_watch_source_new(pid);
156 g_source_set_callback(gt_watch, (GSourceFunc) child_state_cb, NULL, NULL);
157
158 g_source_attach(gt_watch, NULL);
159 g_source_unref(gt_watch);
160
161 /* make nonblocking */
162 if(fcntl(context->stdout_fd, F_SETFL, O_NONBLOCK) == -1)
163 perror("fcntl failed");
164
165 if(fcntl(context->stderr_fd, F_SETFL, O_NONBLOCK) == -1)
166 perror("fcntl failed");
167
168 /* use gdk to monitor read end of stdout */
169 context->stdout_tag =
170 gdk_input_add(context->stdout_fd, GDK_INPUT_READ, child_input_cb, context);
171 context->stderr_tag =
172 gdk_input_add(context->stderr_fd, GDK_INPUT_READ, child_input_cb, context);
173 }