home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
595.lha
/
Notify_v1.1
/
Source
/
Notify.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-11
|
10KB
|
536 lines
/*
* Notify -- Start programs when detect file creation.
*
* The source are not very clean because there so many
* #ifdef everywhere.
*
* There's two level of debug info. The first, invoked when
* DEBUG is defined, prints out file that are matched and the
* option used.
*
* The second level prints all file it can see, with the symbol
* DEBUGALL.
*
* This file should only compile under SAS 5.10, it uses alot
* of compiler stuff.
*/
#include "arpbase.h"
#include "arp_proto.h"
#ifdef DEBUGALL /* display ALL opens, closes and renames*/
#ifndef DEBUG
#define DEBUG
#endif
#endif
/*
* A little typedef for clearer declarations...
*/
typedef LONG (*__asm DosClose)(register __d1 LONG, register __a6 struct Library *);
typedef LONG (*__asm DosOpen)(register __d1 char *, register __d2 LONG, register __a6 struct Library *);
typedef LONG (*__asm DosRename)(register __d1 char *, register __d2 char *, register __a6 struct Library *);
struct Match
{
struct Match *Next;
struct Match *Prev;
LONG File;
char Name[256];
};
/*
* Ok, there are a lot of weird declarations, but it works !
*/
void main (UWORD argc, char **argv);
void StartPrg (char *);
UWORD Match (char *);
BPTR GetFile (char *);
void AddArg (char *Buff, char *arg);
__fptr __stdargs DosWedge (struct DosBase *, LONG Offset, WORD *BackUp, __fptr NewFunc);
void __stdargs UnWedge (struct DosBase *, LONG Offset, WORD *Backup);
LONG __asm __saveds NewClose (register __d1 LONG, register __a6 struct Library *);
LONG __asm __saveds NewOpen (register __d1 char *, register __d2 LONG, register __a6 struct Library *);
LONG __asm __saveds NewRename (register __d1 char *, register __d2 char *, register __a6 struct Library *);
#ifdef DEBUG
void WriteDB (char *);
#endif
/* The old function of DOS */
DosClose CallClose;
DosOpen CallOpen;
DosRename CallRename;
/* Library I like to have around... */
extern struct DosBase *DOSBase;
struct Library *ArpBase;
/* Template for the command */
char *Template = "RENAME/s,NEW/s,APPEND/s,Pattern/a,Command/a,Arg/...,</k,>/k";
char *Help = "Usage: Notify [RENAME] [NEW] [APPEND] wildcards cmd <infile >outfile [arguments] [FILENAME] [arguments]";
/* command and arguments when file match */
#define RENAME 0
#define NEW 1
#define APPEND 2
#define PATTERN 3
#define COMMAND 4
#define ARG 5
#define INFILE 6
#define OUTFILE 7
void *Arg[8];
char Pattern[256];
#ifdef DEBUG
BPTR out;
#endif
/* Match linked list */
struct Match *Matches;
struct SignalSemaphore Semaphore;
void _main(char *line)
{
struct Match *m, *next;
WORD OBackup[10],
CBackup[10],
RBackup[10];
__fptr NewFuncPtr;
#ifdef DEBUG
char t[256];
out = Output();
if (out == NULL)
exit (5);
#endif
if ( ! (ArpBase = OpenLibrary ("arp.library", 33L)) )
exit (10);
/*
* Initialize semaphore guarding our list of matched filenames and
* the output file handle.
*/
InitSemaphore (&Semaphore);
/*
* Get command line arguments.
*/
#ifdef DEBUG
sprintf (t, "%s\n", line);
WriteDB (t);
#endif
if ( GADS (line, strlen (line), Help, (char **)Arg, Template) < 0 )
{
Puts (Arg[0]);
CloseLibrary (ArpBase);
exit (5);
}
#ifdef DEBUG
sprintf (t, " RENAME = %lx\n NEW = %lx\n APPEND = %lx\n Pattern = %s\n Command = %s\n",
Arg[RENAME], Arg[NEW], Arg[APPEND], Arg[PATTERN], Arg[COMMAND]);
WriteDB (t);
#endif
/*
* Get the filename pattern ready for inspection...
*/
PreParse ( strlwr(Arg[PATTERN]), Pattern );
/*
* We replace the functions that the user wants. We used a
* function pointer because the compiler needs a modifiable
* value for function call (C problem).
*/
if ( Arg[NEW] || Arg[APPEND] )
{
NewFuncPtr = (__fptr) NewClose;
CallClose = (DosClose) DosWedge ( DOSBase, -36L, CBackup, NewFuncPtr );
NewFuncPtr = (__fptr) NewOpen;
CallOpen = (DosOpen) DosWedge ( DOSBase, -30L, OBackup, NewFuncPtr );
}
if ( Arg[RENAME] )
{
NewFuncPtr = (__fptr) NewRename;
CallRename = (DosRename) DosWedge ( DOSBase, -78L, RBackup, NewFuncPtr );
}
/*
* Wait for control-C
*/
Wait (SIGBREAKF_CTRL_C);
/*
* Remove ourselves safely. Be sure nobody is using the semaphore.
*/
Forbid ();
ObtainSemaphore (&Semaphore);
if ( Arg[NEW] || Arg[APPEND] )
{
UnWedge (DOSBase, -30L, OBackup);
UnWedge (DOSBase, -36L, CBackup);
}
if ( Arg[RENAME] )
{
UnWedge (DOSBase, -78L, RBackup);
}
Permit ();
ReleaseSemaphore (&Semaphore);
/*
* Free all matches that have not been closed yet.
*/
for (m = Matches; m != NULL; m = next)
{
next = m->Next;
FreeMem (m, sizeof (struct Match));
}
CloseLibrary (ArpBase);
}
/*
* The function that will be placed for DOS Close.
*/
LONG __asm __saveds NewClose (register __d1 LONG File, register __a6 struct Library *Dos)
{
struct Match *m;
LONG Result;
#ifdef DEBUG
char t[256];
#endif
/*
* Call real DOS Close...
*/
Result = CallClose (File, Dos);
#ifdef DEBUGALL
sprintf (t, "\n
%lx
closed.
\n", File);
WriteDB (t);
#endif
/*
* Check if file was matched earlier.
*/
ObtainSemaphore (&Semaphore);
for (m = Matches; m != NULL; m = m->Next)
{
if (File == m->File)
{
if (m->Prev)
m->Prev->Next = m->Next;
else
Matches = m->Next;
if (m->Next)
m->Next->Prev = m->Prev;
break;
}
}
ReleaseSemaphore (&Semaphore);
/*
* If the file was matched, start the program the user specified.
*/
if (m)
{
#ifdef DEBUG
sprintf (t, "\n
%s (%lx)
matched in Close().
\n", m->Name, File);
WriteDB (t);
#endif
StartPrg (m->Name);
FreeMem (m, sizeof (struct Match));
}
return Result;
}
/*
* The function that will be placed for DOS Open.
*/
LONG __asm __saveds NewOpen (register __d1 char *Name, register __d2 LONG Mode, register __a6 struct Library *Dos)
{
struct Match *m;
LONG File;
#ifdef DEBUG
char t[256];
#endif
/*
* Call real DOS Open...
*/
File = CallOpen (Name, Mode, Dos);
#ifdef DEBUGALL
sprintf (t, "\n
%s (%lx)
opened.
\n", Name, File);
WriteDB (t);
#endif
/*
* If the mode matches and is enabled and the filename matches
* then create a match structure.
*/
if ( ( (MODE_NEWFILE == Mode && Arg[NEW]) || (MODE_READWRITE == Mode && Arg[APPEND]) ) && Match (Name) )
{
m = AllocMem (sizeof (struct Match), MEMF_PUBLIC);
if (m)
{
m->File = File;
strcpy (m->Name, Name);
m->Prev = NULL;
ObtainSemaphore (&Semaphore);
m->Next = Matches;
Matches = m;
ReleaseSemaphore (&Semaphore);
}
#ifdef DEBUG
sprintf (t, "\n
%s (%lx)
matched in Open().
\n", Name, File);
WriteDB (t);
#endif
}
return File;
}
/*
* The function that will be placed for DOS Rename.
*/
LONG __asm __saveds NewRename (register __d1 char *Old, register __d2 char *New, register __a6 struct Library *Dos)
{
LONG Result;
#ifdef DEBUG
char t[256];
#endif
/*
* Call real DOS Rename...
*/
Result = CallRename (Old, New, Dos);
#ifdef DEBUGALL
sprintf (t, "\n
%s
renamed to
%s
.
\n", Old, New);
WriteDB (t);
#endif
/*
* Check if file matches pattern.
*/
if (Match (New))
{
#ifdef DEBUG
sprintf (t, "\n
%s
matched in Rename().
\n", New);
WriteDB (t);
#endif
StartPrg (New);
}
return Result;
}
/*
* Check if a filename matches a pattern, not taking care of case.
*/
UWORD Match (char *Name)
{
char n[256];
strcpy (n, Name);
return (UWORD)PatternMatch (Pattern, strlwr(n));
}
/*
* This start a program, inserting the proper arguments.
*/
void StartPrg (char *Name)
{
char **argv;
char arg[256] = { '\0' };
struct ProcessControlBlock
PCB = { 6072L, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#ifdef DEBUG
char t[256];
#endif
/*
* Add the arguments and the filename together to form the
* command line of the program to be started.
*/
if (Arg[ARG] != NULL)
for (argv = Arg[ARG]; *argv != NULL; argv++)
if (stricmp (*argv, "filename") == 0)
AddArg (arg, Name);
else
AddArg (arg, *argv);
/*
* Set the input and output handles.
*/
PCB.pcb_Input = GetFile (Arg[INFILE]);
PCB.pcb_Output = GetFile (Arg[OUTFILE]);
/*
* Start the program.
*/
#ifdef DEBUG
if (ASyncRun(Arg[COMMAND],arg,&PCB) < 0)
{
sprintf (t, "\n
%s %s
impossible to start.
\n", Arg[COMMAND], arg);
WriteDB (t);
}
else
{
sprintf (t, "\n
%s %s
started.
\n", Arg[COMMAND], arg);
WriteDB (t);
}
#else
ASyncRun(Arg[COMMAND],arg,&PCB);
#endif
}
/*
* Check if filename is valid and try to open the file.
*/
BPTR GetFile (char *Name)
{
if (Name != NULL && *Name != '\0')
return Open (Name, MODE_NEWFILE);
else
return NULL;
}
/*
* This is an elegant (somewhat) way to add an argument and quoting
* it if it contains a space.
*/
void AddArg (char *to, char *from)
{
UWORD HasSpace = 0;
char *downer,
*begin = to + strlen (to);
/*
* if the destination contained something, add a space and put the
* destination pointer at the next free byte.
*/
if (to != begin)
{
*begin++ = ' ';
to = begin;
}
/*
* While there's a destination byte to transfer, copy it to the
* destination.
*
* But before that, check if it's a space. If it is scroll back
* to the beginning of the text we just added, shifting bytes to
* make place for an opening quote. We do this only for the first
* space of this argument, of course...
*/
do
if (*from == ' ' && !HasSpace)
for (HasSpace = 1, downer = to++; downer != begin; *downer = *(downer-- -1));
while ( (*to++ = *from++) != '\0' );
/*
* If the source text had space, put it under quote.
*/
if (HasSpace)
{
*begin = '"';
*(to-1) = '"';
*to = '\0';
}
}
#ifdef DEBUG
void WriteDB (char *t)
{
ObtainSemaphore (&Semaphore);
Write (out, t, strlen (t));
ReleaseSemaphore (&Semaphore);
}
#endif