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
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".
35 #include "libs/Parse.h"
36 #include "libs/Strings.h"
40 #include "functions.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
)
56 ERR
, "Read", "Nested Read limit %d is reached",
60 prev_read_files
[curr_read_depth
++] = curr_read_file
;
61 curr_read_file
= safestrdup(file
);
71 static void pop_read_file(void)
73 if (curr_read_depth
== 0)
81 curr_read_file
= prev_read_files
[--curr_read_depth
];
91 const char *get_current_read_file(void)
93 return curr_read_file
;
96 const char *get_current_read_dir(void)
105 /* it should be a library function parse_file_dir() */
106 dir_end
= strrchr(curr_read_file
, '/');
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
)
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. */
136 tline
= fgets(line
, (sizeof line
) - 1, f
);
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
);
146 while (isspace((unsigned char)*tline
))
151 if (l
> 0 && tline
[l
- 1] == '\n')
155 execute_function(cond_rc
, exc
, tline
, 0);
156 tline
= fgets(line
, (sizeof line
) - 1, f
);
164 * Parse the action string. We expect a filename, and optionally,
165 * the keyword "Quiet". The parameter `cmdname' is used for diagnostic
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
)
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");
187 /* optional "Quiet" argument -- flag defaults to `off' (noisy) */
189 rest
= GetNextToken(rest
,&option
);
192 *quiet_flag
= strncasecmp(option
, "Quiet", 5) == 0;
201 * Returns 0 if file not found
203 int run_command_file(
204 char *filename
, const exec_context_t
*exc
)
209 /* We attempt to open the filename by doing the following:
211 * - If the file does start with a "/" then it's treated as an
214 * - Otherwise, it's assumed to be in FVWM_USERDIR OR FVWM_DATADIR,
215 * whichever comes first.
217 * - If the file starts with "./" or "../" then try and
218 * open the file exactly as specified which means
221 * ../.././foo is catered for. At this point, we just try and open
222 * the specified file regardless.
224 * - *Hidden* files in the CWD would have to be specified as:
228 full_filename
= filename
;
230 if (full_filename
[0] == '/')
232 /* It's an absolute path */
233 f
= fopen(full_filename
,"r");
235 /* It's a relative path. Check in either FVWM_USERDIR or
238 full_filename
= CatString3(fvwm_userdir
, "/", filename
);
240 if((f
= fopen(full_filename
, "r")) == NULL
)
242 full_filename
= CatString3(
243 FVWM_DATADIR
, "/", filename
);
244 f
= fopen(full_filename
, "r");
249 (f
= fopen(filename
, "r")) == NULL
) {
250 /* We really couldn't open the file. */
254 if (push_read_file(full_filename
) == 0)
258 run_command_stream(NULL
, f
, exc
);
266 * Busy Cursor Stuff for Read
268 static void cursor_control(Bool grab
)
270 static int read_depth
= 0;
271 static Bool need_ungrab
= False
;
273 if (!(Scr
.BusyCursor
& BUSY_READ
) && !need_ungrab
)
279 if (!read_depth
&& GrabEm(CRS_WAIT
, GRAB_BUSY
))
288 else if (need_ungrab
)
291 if (!read_depth
|| !(Scr
.BusyCursor
& BUSY_READ
))
302 void CMD_Read(F_CMD_ARGS
)
307 DoingCommandLine
= False
;
311 cond_rc
->rc
= COND_RC_OK
;
313 if (!parse_filename("Read", action
, &filename
, &read_quietly
))
317 cond_rc
->rc
= COND_RC_ERROR
;
321 cursor_control(True
);
322 if (!run_command_file(filename
, exc
))
326 if (filename
[0] == '/')
330 "file '%s' not found", filename
);
336 "file '%s' not found in %s or "
337 FVWM_DATADIR
, filename
, fvwm_userdir
);
342 cond_rc
->rc
= COND_RC_ERROR
;
346 cursor_control(False
);
351 void CMD_PipeRead(F_CMD_ARGS
)
357 DoingCommandLine
= False
;
361 cond_rc
->rc
= COND_RC_OK
;
363 if (!parse_filename("PipeRead", action
, &command
, &read_quietly
))
367 cond_rc
->rc
= COND_RC_ERROR
;
371 cursor_control(True
);
372 f
= popen(command
, "r");
377 cond_rc
->rc
= COND_RC_ERROR
;
382 ERR
, "PipeRead", "command '%s' not run",
386 cursor_control(False
);
391 run_command_stream(cond_rc
,f
, exc
);
393 cursor_control(False
);