home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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
-