Contents of /trunk/src/geotoad.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 193 - (hide 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 harbaum 193 /*
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     }