* detect and disallow circular transient-for hints
[fvwm.git] / fvwm / read.c
blob5cd2b7bd08de74b847c3ebd210f939ce2dad5004
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * This module is all original code
19 * by Rob Nation
20 * Copyright 1993, Robert Nation
21 * You may use this code for any purpose, as long as the original
22 * copyright remains in the source code and all documentation
24 * Changed 09/24/98 by Dan Espen:
25 * - remove logic that processed and saved module configuration commands.
26 * Its now in "modconf.c".
28 #include "config.h"
30 #include <stdio.h>
31 #ifdef HAVE_FCNTL_H
32 #include <fcntl.h>
33 #endif
35 #include "libs/Parse.h"
36 #include "libs/Strings.h"
37 #include "fvwm.h"
38 #include "externs.h"
39 #include "cursor.h"
40 #include "functions.h"
41 #include "events.h"
42 #include "misc.h"
43 #include "screen.h"
45 #define MAX_READ_DEPTH 40
46 static char *curr_read_file = NULL;
47 static char *curr_read_dir = NULL;
48 static int curr_read_depth = 0;
49 static char *prev_read_files[MAX_READ_DEPTH];
51 static int push_read_file(const char *file)
53 if (curr_read_depth >= MAX_READ_DEPTH)
55 fvwm_msg(
56 ERR, "Read", "Nested Read limit %d is reached",
57 MAX_READ_DEPTH);
58 return 0;
60 prev_read_files[curr_read_depth++] = curr_read_file;
61 curr_read_file = safestrdup(file);
62 if (curr_read_dir)
64 free(curr_read_dir);
66 curr_read_dir = NULL;
68 return 1;
71 static void pop_read_file(void)
73 if (curr_read_depth == 0)
75 return;
77 if (curr_read_file)
79 free(curr_read_file);
81 curr_read_file = prev_read_files[--curr_read_depth];
82 if (curr_read_dir)
84 free(curr_read_dir);
86 curr_read_dir = NULL;
88 return;
91 const char *get_current_read_file(void)
93 return curr_read_file;
96 const char *get_current_read_dir(void)
98 if (!curr_read_dir)
100 char *dir_end;
101 if (!curr_read_file)
103 return ".";
105 /* it should be a library function parse_file_dir() */
106 dir_end = strrchr(curr_read_file, '/');
107 if (!dir_end)
109 dir_end = curr_read_file;
111 curr_read_dir = safemalloc(dir_end - curr_read_file + 1);
112 strncpy(curr_read_dir, curr_read_file,
113 dir_end - curr_read_file);
114 curr_read_dir[dir_end - curr_read_file] = '\0';
116 return curr_read_dir;
121 * Read and execute each line from stream.
123 void run_command_stream(
124 cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc)
126 char *tline;
127 char line[1024];
129 /* Set close-on-exec flag */
130 fcntl(fileno(f), F_SETFD, 1);
132 /* Update window decorations in case we were called from a menu that
133 * has now popped down. */
134 handle_all_expose();
136 tline = fgets(line, (sizeof line) - 1, f);
137 while (tline)
139 int l;
140 while (tline && (l = strlen(line)) < sizeof(line) && l >= 2 &&
141 line[l-2]=='\\' && line[l-1]=='\n')
143 tline = fgets(line+l-2,sizeof(line)-l+1,f);
145 tline=line;
146 while (isspace((unsigned char)*tline))
148 tline++;
150 l = strlen(tline);
151 if (l > 0 && tline[l - 1] == '\n')
153 tline[l - 1] = '\0';
155 execute_function(cond_rc, exc, tline, 0);
156 tline = fgets(line, (sizeof line) - 1, f);
159 return;
164 * Parse the action string. We expect a filename, and optionally,
165 * the keyword "Quiet". The parameter `cmdname' is used for diagnostic
166 * messages only.
168 * Returns true if the parse succeeded.
169 * The filename and the presence of the quiet flag are returned
170 * using the pointer arguments.
172 static int parse_filename(
173 char *cmdname, char *action, char **filename, int *quiet_flag)
175 char *rest;
176 char *option;
178 /* fvwm_msg(INFO,cmdname,"action == '%s'",action); */
180 /* read file name arg */
181 rest = GetNextToken(action,filename);
182 if (*filename == NULL)
184 fvwm_msg(ERR, cmdname, "missing filename parameter");
185 return 0;
187 /* optional "Quiet" argument -- flag defaults to `off' (noisy) */
188 *quiet_flag = 0;
189 rest = GetNextToken(rest,&option);
190 if (option != NULL)
192 *quiet_flag = strncasecmp(option, "Quiet", 5) == 0;
193 free(option);
196 return 1;
201 * Returns 0 if file not found
203 int run_command_file(
204 char *filename, const exec_context_t *exc)
206 char *full_filename;
207 FILE* f;
209 if (filename[0] == '/')
210 { /* if absolute path */
211 f = fopen(filename,"r");
212 full_filename = filename;
214 else
215 { /* else its a relative path */
216 full_filename = CatString3(fvwm_userdir, "/", filename);
217 f = fopen(full_filename, "r");
218 if (f == NULL)
220 full_filename = CatString3(
221 FVWM_DATADIR, "/", filename);
222 f = fopen(full_filename, "r");
225 if (f == NULL)
227 return 0;
229 if (push_read_file(full_filename) == 0)
231 return 0;
233 run_command_stream(NULL, f, exc);
234 fclose(f);
235 pop_read_file();
237 return 1;
241 * Busy Cursor Stuff for Read
243 static void cursor_control(Bool grab)
245 static int read_depth = 0;
246 static Bool need_ungrab = False;
248 if (!(Scr.BusyCursor & BUSY_READ) && !need_ungrab)
250 return;
252 if (grab)
254 if (!read_depth && GrabEm(CRS_WAIT, GRAB_BUSY))
256 need_ungrab = True;
258 if (need_ungrab)
260 read_depth++;
263 else if (need_ungrab)
265 read_depth--;
266 if (!read_depth || !(Scr.BusyCursor & BUSY_READ))
268 UngrabEm(GRAB_BUSY);
269 need_ungrab = False;
270 read_depth = 0;
274 return;
277 void CMD_Read(F_CMD_ARGS)
279 char* filename;
280 int read_quietly;
282 DoingCommandLine = False;
284 if (cond_rc != NULL)
286 cond_rc->rc = COND_RC_OK;
288 if (!parse_filename("Read", action, &filename, &read_quietly))
290 if (cond_rc != NULL)
292 cond_rc->rc = COND_RC_ERROR;
294 return;
296 cursor_control(True);
297 if (!run_command_file(filename, exc))
299 if (!read_quietly)
301 if (filename[0] == '/')
303 fvwm_msg(
304 ERR, "Read",
305 "file '%s' not found", filename);
307 else
309 fvwm_msg(
310 ERR, "Read",
311 "file '%s' not found in %s or "
312 FVWM_DATADIR, filename, fvwm_userdir);
315 if (cond_rc != NULL)
317 cond_rc->rc = COND_RC_ERROR;
320 free(filename);
321 cursor_control(False);
323 return;
326 void CMD_PipeRead(F_CMD_ARGS)
328 char* command;
329 int read_quietly;
330 FILE* f;
332 DoingCommandLine = False;
334 if (cond_rc != NULL)
336 cond_rc->rc = COND_RC_OK;
338 if (!parse_filename("PipeRead", action, &command, &read_quietly))
340 if (cond_rc != NULL)
342 cond_rc->rc = COND_RC_ERROR;
344 return;
346 cursor_control(True);
347 f = popen(command, "r");
348 if (f == NULL)
350 if (cond_rc != NULL)
352 cond_rc->rc = COND_RC_ERROR;
354 if (!read_quietly)
356 fvwm_msg(
357 ERR, "PipeRead", "command '%s' not run",
358 command);
360 free(command);
361 cursor_control(False);
362 return;
364 free(command);
366 run_command_stream(cond_rc,f, exc);
367 pclose(f);
368 cursor_control(False);
370 return;