/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* *************************************************************************
* This module is all original code
* by Rob Nation
* Copyright 1993, Robert Nation
* You may use this code for any purpose, as long as the original
* copyright remains in the source code and all documentation
*
* Changed 09/24/98 by Dan Espen:
* - remove logic that processed and saved module configuration commands.
* Its now in "modconf.c".
* *************************************************************************
*/
#include "config.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef I18N_MB
#include <X11/Xlocale.h>
#endif
#include "libs/fvwmlib.h"
#include "fvwm.h"
#include "externs.h"
#include "cursor.h"
#include "functions.h"
#include "events.h"
#include "bindings.h"
#include "misc.h"
#include "screen.h"
#include "read.h"
#define MAX_READ_DEPTH 40
static char *curr_read_file = NULL;
static char *curr_read_dir = NULL;
static unsigned int curr_read_depth = 0;
static char *prev_read_files[MAX_READ_DEPTH];
static int push_read_file(const char *file)
{
if (curr_read_depth >= MAX_READ_DEPTH)
{
fvwm_msg(ERR, "Read", "Nested Read limit %d is reached", MAX_READ_DEPTH);
return FALSE;
}
prev_read_files[curr_read_depth++] = curr_read_file;
curr_read_file = safestrdup(file);
if (curr_read_dir)
free(curr_read_dir);
curr_read_dir = NULL;
return TRUE;
}
static void pop_read_file(void)
{
if (curr_read_depth == 0)
return;
if (curr_read_file)
free(curr_read_file);
curr_read_file = prev_read_files[--curr_read_depth];
if (curr_read_dir)
free(curr_read_dir);
curr_read_dir = NULL;
}
const char *get_current_read_file(void)
{
return curr_read_file;
}
const char *get_current_read_dir(void)
{
if (!curr_read_dir)
{
char *dir_end;
if (!curr_read_file)
return ".";
/* it should be a library function parse_file_dir() */
dir_end = strrchr(curr_read_file, '/');
if (!dir_end)
dir_end = curr_read_file;
curr_read_dir = safemalloc(dir_end - curr_read_file + 1);
strncpy(curr_read_dir, curr_read_file, dir_end - curr_read_file);
curr_read_dir[dir_end - curr_read_file] = '\0';
}
return curr_read_dir;
}
/**
* Read and execute each line from stream.
**/
void run_command_stream( FILE* f, XEvent *eventp, FvwmWindow *tmp_win,
unsigned long context, int Module )
{
char *tline;
char line[1024];
/* Set close-on-exec flag */
fcntl(fileno(f), F_SETFD, 1);
/* Update window decorations in case we were called from a menu that has now
* popped down. */
handle_all_expose();
tline = fgets(line, (sizeof line) - 1, f);
while(tline)
{
int l;
while(tline && (l = strlen(line)) < sizeof(line) && l >= 2 &&
line[l-2]=='\\' && line[l-1]=='\n')
{
tline = fgets(line+l-2,sizeof(line)-l+1,f);
}
tline=line;
while(isspace((unsigned char)*tline))
tline++;
l = strlen(tline);
if (l > 0 && tline[l - 1] == '\n')
tline[l - 1] = '\0';
if (debugging)
fvwm_msg(DBG, "ReadSubFunc", "Module switch %d, about to exec: '%s'",
Module, tline);
old_execute_function(tline, tmp_win, eventp, context, Module, 0, NULL);
tline = fgets(line, (sizeof line) - 1, f);
}
}
/**
* Parse the action string. We expect a filename, and optionally,
* the keyword "Quiet". The parameter `cmdname' is used for diagnostic
* messages only.
*
* Returns true if the parse succeeded.
* The filename and the presence of the quiet flag are returned
* using the pointer arguments.
**/
static int parse_filename(
char *cmdname, char *action, char **filename, int *quiet_flag)
{
char *rest;
char *option;
/* fvwm_msg(INFO,cmdname,"action == '%s'",action); */
/* read file name arg */
rest = GetNextToken(action,filename);
if (*filename == NULL)
{
fvwm_msg(ERR, cmdname, "missing filename parameter");
return 0;
}
/* optional "Quiet" argument -- flag defaults to `off' (noisy) */
*quiet_flag = 0;
rest = GetNextToken(rest,&option);
if ( option != NULL)
{
*quiet_flag = strncasecmp(option, "Quiet", 5) == 0;
free(option);
}
return 1;
}
/**
* Returns FALSE if file not found
**/
int run_command_file( char* filename, XEvent *eventp, FvwmWindow *tmp_win,
unsigned long context, int Module )
{
char *full_filename;
FILE* f;
if (filename[0] == '/')
{ /* if absolute path */
f = fopen(filename,"r");
full_filename = filename;
}
else
{ /* else its a relative path */
full_filename = CatString3( fvwm_userdir, "/", filename );
f = fopen( full_filename, "r" );
if ( f == NULL )
{
full_filename = CatString3( FVWM_DATADIR, "/", filename );
f = fopen( full_filename, "r" );
}
}
if (f == NULL)
return FALSE;
if (push_read_file(full_filename) == FALSE)
return FALSE;
run_command_stream( f, eventp, tmp_win, context, Module );
fclose( f );
pop_read_file();
return TRUE;
}
/**
* Busy Cursor Stuff for Read
**/
static void cursor_control(Bool grab)
{
static unsigned int read_depth = 0;
static Bool need_ungrab = False;
if (!(Scr.BusyCursor & BUSY_READ) && !need_ungrab)
return;
if (grab)
{
if (!read_depth && GrabEm(CRS_WAIT, GRAB_BUSY))
need_ungrab = True;
if (need_ungrab) read_depth++;
}
else if (need_ungrab)
{
read_depth--;
if (!read_depth || !(Scr.BusyCursor & BUSY_READ))
{
UngrabEm(GRAB_BUSY);
need_ungrab = False;
read_depth = 0;
}
}
}
void CMD_Read(F_CMD_ARGS)
{
char* filename;
int read_quietly;
DoingCommandLine = False;
if (debugging)
fvwm_msg(DBG, "ReadFile", "Module flag %d, about to attempt %s",
*Module, action);
if ( !parse_filename( "Read", action, &filename, &read_quietly ) )
return;
cursor_control(True);
if ( !run_command_file( filename, eventp, tmp_win, context, *Module ) &&
!read_quietly )
{
fvwm_msg( ERR, "Read",
"file '%s' not found in %s or "FVWM_DATADIR,
filename, fvwm_userdir );
}
free( filename );
cursor_control(False);
}
void CMD_PipeRead(F_CMD_ARGS)
{
char* command;
int read_quietly;
FILE* f;
DoingCommandLine = False;
if (debugging)
fvwm_msg(DBG,"PipeRead","about to attempt '%s'", action);
if (!parse_filename("PipeRead", action, &command, &read_quietly))
return;
cursor_control(True);
f = popen(command, "r");
if (f == NULL)
{
if (!read_quietly)
fvwm_msg( ERR, "PipeRead", "command '%s' not run", command );
free(command);
cursor_control(False);
return;
}
free(command);
run_command_stream(f, eventp, tmp_win, context, *Module);
pclose(f);
cursor_control(False);
}
syntax highlighted by Code2HTML, v. 0.9.1