1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <libgen.h>
5 #include <grass/gis.h>
6 #include <grass/spawn.h>
7 #include <grass/display.h>
8 #include <grass/glocale.h>
9 
10 #include "proto.h"
11 
12 static char *start(const char *, const char *, int, int, int);
13 static char *start_wx(const char *, const char *, int, int, int);
14 static void error_handler(void *);
15 
16 /* start file-based monitor */
start(const char * name,const char * output,int width,int height,int update)17 char *start(const char *name, const char *output, int width, int height, int update)
18 {
19     char *output_path;
20     const char *output_name;
21 
22     /* stop monitor on failure */
23     G_add_error_handler(error_handler, (char *)name);
24 
25     /* full path for output file */
26     output_path = (char *) G_malloc(GPATH_MAX);
27     output_path[0] = '\0';
28 
29     if (!output) {
30         char buff[512];
31 
32         sprintf(buff, "GRASS_RENDER_IMMEDIATE=%s", name);
33         putenv(G_store(buff));
34         sprintf(buff, "GRASS_RENDER_WIDTH=%d", width);
35         putenv(G_store(buff));
36         sprintf(buff, "GRASS_RENDER_HEIGHT=%d", height);
37         putenv(G_store(buff));
38 
39         D_open_driver();
40 
41         output_name = D_get_file();
42         if (!output_name)
43             return NULL;
44         if (!update && access(output_name, F_OK) == 0) {
45             if (G_get_overwrite()) {
46                 G_warning(_("File <%s> already exists and will be overwritten"), output_name);
47                 D_setup_unity(0);
48                 D_erase("white");
49             }
50             else
51                 G_fatal_error(_("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"),
52                               "output", output_name);
53         }
54         D_close_driver(); /* must be called after check because this
55                            * function produces default map file */
56         putenv("GRASS_RENDER_IMMEDIATE=");
57     }
58     else {
59         char *dir_name;
60 
61         output_name = output;
62         /* check write permission */
63         dir_name = G_store(output_name);
64         if (access(dirname(dir_name), W_OK) != 0)
65             G_fatal_error(_("Unable to start monitor, don't have "
66                             "write permission for <%s>"), output_name);
67         G_free(dir_name);
68 
69         /* check if file exists */
70         if (!update && access(output_name, F_OK) == 0) {
71             if (G_get_overwrite()) {
72                 G_warning(_("File <%s> already exists and will be overwritten"), output_name);
73                 if (0 != unlink(output_name))
74                     G_fatal_error(_("Unable to delete <%s>"), output_name);
75             }
76         }
77     }
78 
79 
80     if (!strchr(output_name, HOST_DIRSEP)) { /* relative path */
81         char *ptr;
82 
83         if (!getcwd(output_path, GPATH_MAX))
84             G_fatal_error(_("Unable to get current working directory"));
85         ptr = output_path + strlen(output_path) - 1;
86         if (*(ptr++) != HOST_DIRSEP) {
87             *(ptr++) = HOST_DIRSEP;
88             *(ptr) = '\0';
89         }
90         strcat(output_path, output_name);
91         G_message(_("Output file: %s"), output_path);
92     }
93     else {
94         strcpy(output_path, output_name); /* already full path */
95     }
96 
97     return output_path;
98 }
99 
100 /* start wxGUI display monitor */
start_wx(const char * name,const char * element,int width,int height,int x_only)101 char *start_wx(const char *name, const char *element, int width, int height, int x_only)
102 {
103     char progname[GPATH_MAX], mon_path[GPATH_MAX];
104     char str_width[1024], str_height[1024], *str_x_only;
105     char *mapfile;
106 
107     /* full path */
108     mapfile = (char *) G_malloc(GPATH_MAX);
109     mapfile[0] = '\0';
110 
111     sprintf(progname, "%s/gui/wxpython/mapdisp/main.py", G_gisbase());
112     sprintf(str_width, "%d", width);
113     sprintf(str_height, "%d", height);
114 
115     if (x_only)
116         str_x_only = "1";
117     else
118         str_x_only = "0";
119 
120     G_file_name(mon_path, element, NULL, G_mapset());
121     G_spawn_ex(getenv("GRASS_PYTHON"), progname, progname,
122                name, mon_path, str_width, str_height, str_x_only, SF_BACKGROUND, NULL);
123 
124     G_file_name(mapfile, element, "map.ppm", G_mapset());
125 
126     return mapfile;
127 }
128 
start_mon(const char * name,const char * output,int select,int width,int height,const char * bgcolor,int truecolor,int x_only,int update)129 int start_mon(const char *name, const char *output, int select,
130 	      int width, int height, const char *bgcolor,
131 	      int truecolor, int x_only, int update)
132 {
133     char *mon_path;
134     char *out_file, *env_file, *cmd_file, *leg_file;
135     char  buf[1024];
136     char file_path[GPATH_MAX], render_cmd_path[GPATH_MAX];
137     int  fd;
138 
139     if (check_mon(name)) {
140         const char *curr_mon;
141 
142         curr_mon = G_getenv_nofatal("MONITOR");
143 	if (select && (!curr_mon || strcmp(curr_mon, name) != 0))
144 	    G_setenv("MONITOR", name);
145 
146         G_fatal_error(_("Monitor <%s> already running"), name);
147     }
148 
149     G_verbose_message(_("Starting monitor <%s>..."), name);
150 
151     /* create .tmp/HOSTNAME/u_name directory */
152     mon_path = get_path(name, FALSE);
153     G_make_mapset_element(mon_path);
154 
155     G_file_name(file_path, mon_path, "env", G_mapset());
156     env_file = G_store(file_path);
157     G_file_name(file_path, mon_path, "cmd", G_mapset());
158     cmd_file = G_store(file_path);
159     G_file_name(file_path, mon_path, "leg", G_mapset());
160     leg_file = G_store(file_path);
161 
162     /* create py file (renderer) */
163     sprintf(render_cmd_path, "%s/etc/d.mon/render_cmd.py", getenv("GISBASE"));
164     G_file_name(file_path, mon_path, "render.py", G_mapset());
165     G_debug(1, "Monitor name=%s, pyfile = %s", name, file_path);
166     if (1 != G_copy_file(render_cmd_path, file_path))
167         G_fatal_error(_("Unable to copy render command file"));
168 
169     /* start monitor */
170     if (strncmp(name, "wx", 2) == 0)
171         out_file = start_wx(name, mon_path, width, height, x_only);
172     else
173         out_file = start(name, output, width, height, update);
174 
175     /* create env file (environmental variables used for rendering) */
176     G_debug(1, "Monitor name=%s, envfile=%s", name, env_file);
177     fd = creat(env_file, 0666);
178     if (fd < 0)
179 	G_fatal_error(_("Unable to create file <%s>"), env_file);
180 
181     if (G_strncasecmp(name, "wx", 2) == 0) {
182         sprintf(buf, "GRASS_RENDER_IMMEDIATE=default\n"); /* TODO: read settings from wxGUI */
183         write(fd, buf, strlen(buf));
184         sprintf(buf, "GRASS_RENDER_FILE_READ=FALSE\n");
185         write(fd, buf, strlen(buf));
186         sprintf(buf, "GRASS_RENDER_TRANSPARENT=TRUE\n");
187         write(fd, buf, strlen(buf));
188     }
189     else {
190         sprintf(buf, "GRASS_RENDER_IMMEDIATE=%s\n", name);
191         write(fd, buf, strlen(buf));
192         sprintf(buf, "GRASS_RENDER_FILE_READ=TRUE\n");
193         write(fd, buf, strlen(buf));
194 
195     }
196     sprintf(buf, "GRASS_RENDER_FILE=%s\n", out_file);
197     write(fd, buf, strlen(buf));
198     sprintf(buf, "GRASS_RENDER_WIDTH=%d\n", width);
199     write(fd, buf, strlen(buf));
200     sprintf(buf, "GRASS_RENDER_HEIGHT=%d\n", height);
201     write(fd, buf, strlen(buf));
202     sprintf(buf, "GRASS_LEGEND_FILE=%s\n", leg_file);
203     write(fd, buf, strlen(buf));
204 
205 
206     if (bgcolor) {
207 	if (strcmp(bgcolor, "none") == 0)
208 	    sprintf(buf, "GRASS_RENDER_TRANSPARENT=TRUE\n");
209 	else
210 	    sprintf(buf, "GRASS_RENDER_BACKGROUNDCOLOR=%s\n", bgcolor);
211 	write(fd, buf, strlen(buf));
212     }
213     if (truecolor) {
214 	sprintf(buf, "GRASS_RENDER_TRUECOLOR=TRUE\n");
215 	write(fd, buf, strlen(buf));
216     }
217     close(fd);
218 
219     /* create cmd file (list of GRASS display commands to render) */
220     G_debug(1, "Monitor name=%s, cmdfile = %s", name, cmd_file);
221     if (0 > creat(cmd_file, 0666))
222         G_fatal_error(_("Unable to create file <%s>"), cmd_file);
223 
224     /* select monitor if requested */
225     if (select)
226 	G_setenv("MONITOR", name);
227 
228     G_free(mon_path);
229     G_free(out_file);
230     G_free(env_file);
231 
232     return 0;
233 }
234 
error_handler(void * p)235 void error_handler(void *p)
236 {
237     const char *name = (const char *) p;
238     stop_mon(name);
239 }
240