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 >
C/C++ Source or Header  |  1991-09-11  |  10KB  |  536 lines

  1. /*
  2.  *    Notify -- Start programs when detect file creation.
  3.  *
  4.  *        The source are not very clean because there so many
  5.  *        #ifdef everywhere.
  6.  *
  7.  *        There's two level of debug info.  The first, invoked when
  8.  *        DEBUG is defined, prints out file that are matched and the
  9.  *        option used.
  10.  *
  11.  *        The second level prints all file it can see, with the symbol
  12.  *        DEBUGALL.
  13.  *
  14.  *        This file should only compile under SAS 5.10, it uses alot
  15.  *        of compiler stuff.
  16.  */
  17.  
  18.  
  19. #include "arpbase.h"
  20. #include "arp_proto.h"
  21.  
  22.  
  23. #ifdef DEBUGALL        /* display ALL opens, closes and renames*/
  24. #ifndef DEBUG
  25. #define DEBUG
  26. #endif
  27. #endif
  28.  
  29.  
  30. /*
  31.  *    A little typedef for clearer declarations...
  32.  */
  33.  
  34. typedef LONG (*__asm DosClose)(register __d1 LONG, register __a6 struct Library *);
  35. typedef LONG (*__asm DosOpen)(register __d1 char *, register __d2 LONG, register __a6 struct Library *);
  36. typedef LONG (*__asm DosRename)(register __d1 char *, register __d2 char *, register __a6 struct Library *);
  37.  
  38. struct Match
  39. {
  40.     struct Match *Next;
  41.     struct Match *Prev;
  42.     LONG File;
  43.     char Name[256];
  44. };
  45.  
  46.  
  47. /*
  48.  *    Ok, there are a lot of weird declarations, but it works !
  49.  */
  50.  
  51. void    main        (UWORD argc, char **argv);
  52. void    StartPrg    (char *);
  53. UWORD    Match        (char *);
  54. BPTR    GetFile        (char *);
  55. void    AddArg        (char *Buff, char *arg);
  56.  
  57. __fptr __stdargs DosWedge (struct DosBase *, LONG Offset, WORD *BackUp, __fptr NewFunc);
  58. void __stdargs UnWedge (struct DosBase *, LONG Offset, WORD *Backup);
  59. LONG __asm __saveds NewClose (register __d1 LONG, register __a6 struct Library *);
  60. LONG __asm __saveds NewOpen (register __d1 char *, register __d2 LONG, register __a6 struct Library *);
  61. LONG __asm __saveds NewRename (register __d1 char *, register __d2 char *, register __a6 struct Library *);
  62.  
  63. #ifdef DEBUG
  64. void WriteDB (char *);
  65. #endif
  66.  
  67. /* The old function of DOS */
  68.  
  69. DosClose                CallClose;
  70. DosOpen                    CallOpen;
  71. DosRename                CallRename;
  72.  
  73.  
  74. /* Library I like to have around... */
  75.  
  76. extern struct DosBase    *DOSBase;
  77. struct Library            *ArpBase;
  78.  
  79.  
  80. /*    Template for the command */
  81.  
  82. char                    *Template = "RENAME/s,NEW/s,APPEND/s,Pattern/a,Command/a,Arg/...,</k,>/k";
  83. char                    *Help = "Usage: Notify [RENAME] [NEW] [APPEND] wildcards cmd <infile >outfile [arguments] [FILENAME] [arguments]";
  84.  
  85.  
  86. /* command and arguments when file match */
  87.  
  88. #define RENAME            0
  89. #define NEW                1
  90. #define APPEND            2
  91. #define PATTERN            3
  92. #define COMMAND            4
  93. #define ARG                5
  94. #define INFILE            6
  95. #define OUTFILE            7
  96.  
  97. void                    *Arg[8];
  98. char                     Pattern[256];
  99.  
  100. #ifdef DEBUG
  101. BPTR                    out;
  102. #endif
  103.  
  104. /* Match linked list */
  105.  
  106. struct Match            *Matches;
  107. struct SignalSemaphore    Semaphore;
  108.  
  109.  
  110. void _main(char *line)
  111. {
  112.     struct Match     *m, *next;
  113.     WORD            OBackup[10],
  114.                     CBackup[10],
  115.                     RBackup[10];
  116.     __fptr            NewFuncPtr;
  117.  
  118. #ifdef DEBUG
  119.     char            t[256];
  120.  
  121.     out = Output();
  122.     if (out == NULL)
  123.         exit (5);
  124. #endif
  125.  
  126.     if ( ! (ArpBase = OpenLibrary ("arp.library", 33L)) )
  127.         exit (10);
  128.  
  129.  
  130.     /*
  131.      *    Initialize semaphore guarding our list of matched filenames and
  132.      *    the output file handle.
  133.      */
  134.  
  135.     InitSemaphore (&Semaphore);
  136.  
  137.  
  138.     /*
  139.      *    Get command line arguments.
  140.      */
  141.  
  142. #ifdef DEBUG
  143.     sprintf (t, "%s\n", line);
  144.     WriteDB (t);
  145. #endif
  146.  
  147.     if ( GADS (line, strlen (line), Help, (char **)Arg, Template) < 0 )
  148.     {
  149.         Puts (Arg[0]);
  150.         CloseLibrary (ArpBase);
  151.         exit (5);
  152.     }
  153.  
  154. #ifdef DEBUG
  155.     sprintf (t, "  RENAME = %lx\n  NEW = %lx\n  APPEND = %lx\n  Pattern = %s\n  Command = %s\n",
  156.             Arg[RENAME], Arg[NEW], Arg[APPEND], Arg[PATTERN], Arg[COMMAND]);
  157.     WriteDB (t);
  158. #endif
  159.  
  160.  
  161.     /*
  162.      *    Get the filename pattern ready for inspection...
  163.      */
  164.  
  165.     PreParse ( strlwr(Arg[PATTERN]), Pattern );
  166.  
  167.  
  168.     /*
  169.      *    We replace the functions that the user wants.  We used a
  170.      *    function pointer because the compiler needs a modifiable
  171.      *    value for function call (C problem).
  172.      */
  173.  
  174.     if ( Arg[NEW] || Arg[APPEND] )
  175.     {
  176.         NewFuncPtr = (__fptr) NewClose;
  177.         CallClose = (DosClose) DosWedge ( DOSBase, -36L, CBackup, NewFuncPtr );
  178.         NewFuncPtr = (__fptr) NewOpen;
  179.         CallOpen = (DosOpen) DosWedge ( DOSBase, -30L, OBackup, NewFuncPtr );
  180.     }
  181.  
  182.     if ( Arg[RENAME] )
  183.     {
  184.         NewFuncPtr = (__fptr) NewRename;
  185.         CallRename = (DosRename) DosWedge ( DOSBase, -78L, RBackup, NewFuncPtr );
  186.     }
  187.  
  188.  
  189.     /*
  190.      *    Wait for control-C
  191.      */
  192.  
  193.     Wait (SIGBREAKF_CTRL_C);
  194.  
  195.  
  196.     /*
  197.      *    Remove ourselves safely.  Be sure nobody is using the semaphore.
  198.      */
  199.  
  200.     Forbid ();
  201.     ObtainSemaphore (&Semaphore);
  202.  
  203.     if ( Arg[NEW] || Arg[APPEND] )
  204.     {
  205.         UnWedge (DOSBase, -30L, OBackup);
  206.         UnWedge (DOSBase, -36L, CBackup);
  207.     }
  208.  
  209.     if ( Arg[RENAME] )
  210.     {
  211.         UnWedge (DOSBase, -78L, RBackup);
  212.     }
  213.  
  214.     Permit ();
  215.     ReleaseSemaphore (&Semaphore);
  216.  
  217.     /*
  218.      *    Free all matches that have not been closed yet.
  219.      */
  220.  
  221.     for (m = Matches; m != NULL; m = next)
  222.     {
  223.         next = m->Next;
  224.         FreeMem (m, sizeof (struct Match));
  225.     }
  226.  
  227.     CloseLibrary (ArpBase);
  228. }
  229.  
  230.  
  231. /*
  232.  *    The function that will be placed for DOS Close.
  233.  */
  234.  
  235. LONG __asm __saveds NewClose (register __d1 LONG File, register __a6 struct Library *Dos)
  236. {
  237.     struct Match    *m;
  238.     LONG            Result;
  239.  
  240. #ifdef DEBUG
  241.     char            t[256];
  242. #endif
  243.  
  244.  
  245.     /*
  246.      *    Call real DOS Close...
  247.      */
  248.  
  249.     Result = CallClose (File, Dos);
  250.  
  251. #ifdef DEBUGALL
  252.     sprintf (t, "\n %lx closed. \n", File);
  253.     WriteDB (t);
  254. #endif
  255.  
  256.  
  257.     /*
  258.      *    Check if file was matched earlier.
  259.      */
  260.  
  261.     ObtainSemaphore (&Semaphore);
  262.     for (m = Matches; m != NULL; m = m->Next)
  263.     {
  264.         if (File == m->File)
  265.         {
  266.             if (m->Prev)
  267.                 m->Prev->Next = m->Next;
  268.             else
  269.                 Matches = m->Next;
  270.             if (m->Next)
  271.                 m->Next->Prev = m->Prev;
  272.             break;
  273.         }
  274.     }
  275.     ReleaseSemaphore (&Semaphore);
  276.  
  277.  
  278.     /*
  279.      *    If the file was matched, start the program the user specified.
  280.      */
  281.  
  282.     if (m)
  283.     {
  284. #ifdef DEBUG
  285.         sprintf (t, "\n %s (%lx) matched in Close(). \n", m->Name, File);
  286.         WriteDB (t);
  287. #endif
  288.         StartPrg (m->Name);
  289.         FreeMem (m, sizeof (struct Match));
  290.     }
  291.  
  292.     return Result;
  293. }
  294.  
  295.  
  296. /*
  297.  *    The function that will be placed for DOS Open.
  298.  */
  299.  
  300. LONG __asm __saveds NewOpen (register __d1 char *Name, register __d2 LONG Mode, register __a6 struct Library *Dos)
  301. {
  302.     struct Match    *m;
  303.     LONG            File;
  304.  
  305. #ifdef DEBUG
  306.     char            t[256];
  307. #endif
  308.  
  309.  
  310.     /*
  311.      *    Call real DOS Open...
  312.      */
  313.  
  314.     File = CallOpen (Name, Mode, Dos);
  315.  
  316. #ifdef DEBUGALL
  317.     sprintf (t, "\n %s (%lx) opened. \n", Name, File);
  318.     WriteDB (t);
  319. #endif
  320.  
  321.  
  322.     /*
  323.      *    If the mode matches and is enabled and the filename matches
  324.      *    then create a match structure.
  325.      */
  326.  
  327.     if ( ( (MODE_NEWFILE == Mode && Arg[NEW]) || (MODE_READWRITE == Mode && Arg[APPEND]) ) && Match (Name) )
  328.     {
  329.         m = AllocMem (sizeof (struct Match), MEMF_PUBLIC);
  330.         if (m)
  331.         {
  332.             m->File = File;
  333.             strcpy (m->Name, Name);
  334.             m->Prev = NULL;
  335.             ObtainSemaphore (&Semaphore);
  336.             m->Next = Matches;
  337.             Matches = m;
  338.             ReleaseSemaphore (&Semaphore);
  339.         }
  340.  
  341. #ifdef DEBUG
  342.         sprintf (t, "\n %s (%lx) matched in Open(). \n", Name, File);
  343.         WriteDB (t);
  344. #endif
  345.     }
  346.     return File;
  347. }
  348.  
  349.  
  350. /*
  351.  *    The function that will be placed for DOS Rename.
  352.  */
  353.  
  354. LONG __asm __saveds NewRename (register __d1 char *Old, register __d2 char *New, register __a6 struct Library *Dos)
  355. {
  356.     LONG    Result;
  357.  
  358. #ifdef DEBUG
  359.     char    t[256];
  360. #endif
  361.  
  362.  
  363.     /*
  364.      *    Call real DOS Rename...
  365.      */
  366.  
  367.     Result = CallRename (Old, New, Dos);
  368.  
  369. #ifdef DEBUGALL
  370.     sprintf (t, "\n %s renamed to %s\n", Old, New);
  371.     WriteDB (t);
  372. #endif
  373.  
  374.  
  375.     /*
  376.      *    Check if file matches pattern.
  377.      */
  378.  
  379.     if (Match (New))
  380.     {
  381. #ifdef DEBUG
  382.         sprintf (t, "\n %s matched in Rename(). \n", New);
  383.         WriteDB (t);
  384. #endif
  385.         StartPrg (New);
  386.     }
  387.  
  388.     return Result;
  389. }
  390.  
  391.  
  392. /*
  393.  *    Check if a filename matches a pattern, not taking care of case.
  394.  */
  395.  
  396. UWORD Match (char *Name)
  397. {
  398.     char n[256];
  399.  
  400.     strcpy (n, Name);
  401.     return (UWORD)PatternMatch (Pattern, strlwr(n));
  402. }
  403.  
  404.  
  405. /*
  406.  *    This start a program, inserting the proper arguments.
  407.  */
  408.  
  409. void StartPrg (char *Name)
  410. {
  411.     char    **argv;
  412.     char    arg[256] = { '\0' };
  413.     struct ProcessControlBlock
  414.             PCB = { 6072L, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  415.  
  416. #ifdef DEBUG
  417.     char    t[256];
  418. #endif
  419.  
  420.  
  421.     /*
  422.      *    Add the arguments and the filename together to form the
  423.      *    command line of the program to be started.
  424.      */
  425.  
  426.     if (Arg[ARG] != NULL)
  427.         for (argv = Arg[ARG]; *argv != NULL; argv++)
  428.             if (stricmp (*argv, "filename") == 0)
  429.                 AddArg (arg, Name);
  430.             else
  431.                 AddArg (arg, *argv);
  432.  
  433.     /*
  434.      *    Set the input and output handles.
  435.      */
  436.  
  437.         PCB.pcb_Input = GetFile (Arg[INFILE]);
  438.         PCB.pcb_Output = GetFile (Arg[OUTFILE]);
  439.  
  440.  
  441.     /*
  442.      *    Start the program.
  443.      */
  444.  
  445. #ifdef DEBUG
  446.     if (ASyncRun(Arg[COMMAND],arg,&PCB) < 0)
  447.     {
  448.         sprintf (t, "\n %s %s impossible to start. \n", Arg[COMMAND], arg);
  449.         WriteDB (t);
  450.     }
  451.     else
  452.     {
  453.         sprintf (t, "\n %s %s started. \n", Arg[COMMAND], arg);
  454.         WriteDB (t);
  455.     }
  456. #else
  457.     ASyncRun(Arg[COMMAND],arg,&PCB);
  458. #endif
  459. }
  460.  
  461.  
  462. /*
  463.  *    Check if filename is valid and try to open the file.
  464.  */
  465.  
  466. BPTR GetFile (char *Name)
  467. {
  468.     if (Name != NULL && *Name != '\0')
  469.         return Open (Name, MODE_NEWFILE);
  470.     else
  471.         return NULL;
  472. }
  473.  
  474.  
  475. /*
  476.  *    This is an elegant (somewhat) way to add an argument and quoting
  477.  *    it if it contains a space.
  478.  */
  479.  
  480. void AddArg (char *to, char *from)
  481. {
  482.     UWORD    HasSpace = 0;
  483.     char    *downer,
  484.             *begin = to + strlen (to);
  485.  
  486.     /*
  487.      *    if the destination contained something, add a space and put the
  488.      *    destination pointer at the next free byte.
  489.      */
  490.  
  491.     if (to != begin)
  492.     {
  493.         *begin++ = ' ';
  494.         to = begin;
  495.     }
  496.  
  497.  
  498.     /*
  499.      *    While there's a destination byte to transfer, copy it to the
  500.      *    destination.
  501.      *
  502.      *    But before that, check if it's a space.  If it is scroll back
  503.      *    to the beginning of the text we just added, shifting bytes to
  504.      *    make place for an opening quote.  We do this only for the first
  505.      *    space of this argument, of course...
  506.      */
  507.      
  508.  
  509.     do
  510.         if (*from == ' ' && !HasSpace)
  511.             for (HasSpace = 1, downer = to++; downer != begin; *downer = *(downer-- -1));
  512.     while ( (*to++ = *from++) != '\0' );
  513.  
  514.  
  515.     /*
  516.      *    If the source text had space, put it under quote.
  517.      */
  518.  
  519.     if (HasSpace)
  520.     {
  521.         *begin = '"';
  522.         *(to-1) = '"';
  523.         *to = '\0';
  524.     }
  525. }
  526.  
  527.  
  528. #ifdef DEBUG
  529. void WriteDB (char *t)
  530. {
  531.     ObtainSemaphore (&Semaphore);
  532.     Write (out, t, strlen (t));
  533.     ReleaseSemaphore (&Semaphore);
  534. }
  535. #endif
  536.