home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / ext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  15.1 KB  |  512 lines

  1. /* Extension dependent execution.
  2.    Copyright (C) 1994, 1995 The Free Software Foundation
  3.    
  4.    Written by: 1995 Jakub Jelinek
  5.                1994 Miguel de Icaza
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. #include <config.h>
  22. #include <stdio.h> 
  23. #include "tty.h"
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #include <fcntl.h>
  28. #include <malloc.h>
  29. #include <string.h>
  30. #include <errno.h>
  31. #include "mad.h"
  32. #include "user.h"
  33. #include "main.h"
  34. #include "fs.h"
  35. #include "util.h"
  36. #include "dialog.h"
  37. #include "global.h"
  38. #include "ext.h"
  39. #include "view.h"
  40. #include "main.h"
  41. #include "../vfs/vfs.h"
  42.  
  43. /* "$Id: ext.c,v 1.10 1995/02/21 19:05:45 miguel Exp $" */
  44. int use_file_to_check_type = 1;
  45.  
  46. void exec_extension (char *filename, char *data, char *drops, int *move_dir)
  47. {
  48.     char *file_name;
  49.     FILE *cmd_file;
  50.     int  expand_prefix_found = 0;
  51.     int parameter_found = 0;
  52.     char prompt [80];
  53.     int run_view = 0;
  54.     int def_hex_mode = default_hex_mode, changed_hex_mode = 0;
  55.     int def_nroff_flag = default_nroff_flag, changed_nroff_flag = 0;
  56.     int written_nonspace = 0;
  57.     int is_cd = 0;
  58.     char buffer [1024];
  59.     char *p = 0;
  60.     char *localcopy = NULL;
  61.     time_t localmtime = 0;
  62.     struct stat mystat;
  63.     int    do_local_copy;
  64.  
  65.     /* Avoid making a local copy if we are doing a cd */
  66.     if (!vfs_file_is_local(filename))
  67.     do_local_copy = 1;
  68.     else
  69.     do_local_copy = 0;
  70.     
  71.     /* Note: this has to be done after the getlocalcopy call,
  72.      * since it uses tmpnam as well
  73.      */
  74.     file_name = strdup (tmpnam (NULL));
  75.  
  76.     if ((cmd_file = fopen (file_name, "w+")) == NULL){
  77.     message (1, " Error ", " Can't create temporary command file \n %s ",
  78.          unix_error_string (errno));
  79.     return;
  80.     }
  81.     prompt [0] = 0;
  82.     for (;*data && *data != '\n'; data++){
  83.     if (parameter_found){
  84.         if (*data == '}'){
  85.         char *parameter;
  86.         parameter_found = 0;
  87.         parameter = input_dialog (" Parameter ", prompt, "");
  88.         if (!parameter){
  89.             /* User canceled */
  90.             fclose (cmd_file);
  91.             unlink (file_name);
  92.             if (localcopy) {
  93.                 mc_ungetlocalcopy (filename, localcopy, 0);
  94.             }
  95.             free (file_name);
  96.             return;
  97.         }
  98.         fputs (parameter, cmd_file);
  99.         written_nonspace = 1;
  100.         free (parameter);
  101.         } else {
  102.         int len = strlen (prompt);
  103.  
  104.         if (len < sizeof (prompt) - 1){
  105.             prompt [len] = *data;
  106.             prompt [len+1] = 0;
  107.         }
  108.         }
  109.     } else if (expand_prefix_found){
  110.         expand_prefix_found = 0;
  111.         if (*data == '{')
  112.         parameter_found = 1;
  113.         else {
  114.             int i = check_format_view (data);
  115.         char *v;
  116.         
  117.             if (i){
  118.                 data += i - 1;
  119.                 run_view = 1;
  120.             } else if ((i = check_format_cd (data)) > 0) {
  121.                 is_cd = 1;
  122.             do_local_copy = 0;
  123.                 p = buffer;
  124.                 data += i - 1;
  125.         } else if ((i = check_format_var (data, &v)) > 0 && v){
  126.             fputs (v, cmd_file);
  127.             free (v);
  128.             data += i;
  129.             } else {
  130.             char *text;
  131.  
  132.             if (*data == 'f' && do_local_copy){
  133.             localcopy = mc_getlocalcopy (filename);
  134.             if (localcopy == NULL) {
  135.                 fclose(cmd_file);
  136.                 unlink(file_name);
  137.                 free(file_name);
  138.                 return;
  139.             }
  140.             mc_stat (localcopy, &mystat);
  141.             localmtime = mystat.st_mtime;
  142.                 text = strdup (localcopy);
  143.             } else if (*data == 'q') {
  144.                 text = strdup (drops);
  145.             } else
  146.                 text = expand_format (*data);
  147.             if (!is_cd)
  148.                 fputs (text, cmd_file);
  149.             else {
  150.                 strcpy (p, text);
  151.                 p = strchr (p, 0);
  152.             }
  153.             free (text);
  154.             written_nonspace = 1;
  155.             }
  156.         }
  157.     } else {
  158.         if (*data == '%')
  159.         expand_prefix_found = 1;
  160.         else {
  161.             if (*data != ' ' && *data != '\t')
  162.                 written_nonspace = 1;
  163.             if (is_cd)
  164.                 *(p++) = *data;
  165.             else
  166.             fputc (*data, cmd_file);
  167.         }
  168.     }
  169.     } /* for */
  170.     fputc ('\n', cmd_file);
  171.     fclose (cmd_file);
  172.     chmod (file_name, S_IRWXU);
  173.     if (run_view){
  174.         altered_hex_mode = 0;
  175.         altered_nroff_flag = 0;
  176.         if (def_hex_mode != default_hex_mode)
  177.             changed_hex_mode = 1;
  178.         if (def_nroff_flag != default_nroff_flag)
  179.             changed_nroff_flag = 1;
  180.     
  181.         /* If we've written whitespace only, then just load filename
  182.      * into view
  183.      */
  184.         if (written_nonspace) 
  185.             view (file_name, filename, move_dir);
  186.         else
  187.             view (0, filename, move_dir);
  188.         if (changed_hex_mode && !altered_hex_mode)
  189.             default_hex_mode = def_hex_mode;
  190.         if (changed_nroff_flag && !altered_nroff_flag)
  191.             default_nroff_flag = def_nroff_flag;
  192.         repaint_screen ();
  193.     } else if (is_cd) {
  194.         char *q;
  195.         *p = 0;
  196.         p = buffer;
  197.         while (*p == ' ' || *p == '\t')
  198.             p++;
  199.         q = p;
  200.         while (*q && *q != ' ' && *q != '\t')
  201.             q++;
  202.         *q = 0;
  203.         do_cd (p);
  204.     } else {
  205.     if (vfs_current_is_local ())
  206.         shell_execute (file_name, 1);
  207.     else
  208.         message (1, " Warning ", " Can't execute commands on a Virtual File System directory ");
  209.     }
  210.     unlink (file_name);
  211.     if (localcopy) {
  212.         mc_stat (localcopy, &mystat);
  213.         mc_ungetlocalcopy (filename, localcopy, localmtime != mystat.st_mtime);
  214.     }
  215.     free (file_name);
  216. }
  217.  
  218. #ifdef FILE_L
  219. #   define FILE_CMD "file -L "
  220. #else
  221. #   define FILE_CMD "file "
  222. #endif
  223.  
  224. /* The second argument is action, i.e. Open, View, Edit, Drop, or NULL if
  225.  * we want regex_command to return a list of all user defined actions.
  226.  * Third argument is space separated list of dropped files (for actions
  227.  * other then Drop it should be NULL);
  228.  *
  229.  * This function returns:
  230.  *
  231.  * If action != NULL, then it returns "Success" (not allocated) if it ran
  232.  * some command or NULL if not.
  233.  *
  234.  * If action == NULL, it returns NULL if there are no user defined commands
  235.  * or an allocated space separated list of user defined Actions.
  236.  *
  237.  * If action == "Icon", we are doing again something special. We return
  238.  * icon name and we set the variable regex_command_title to Title for
  239.  * that icon.
  240.  */
  241. static char *data = NULL;
  242. char *regex_command_title = NULL;
  243. char *regex_command (char *filename, char *action, char *drops, int *move_dir)
  244. {
  245.     char *extension_file;
  246.     char *p, *q, *r, c;
  247.     char *buffer;
  248.     int  file_len = strlen (filename);
  249.     int found = 0;
  250.     char content_string [2048];
  251.     int content_shift = 0;
  252.     char *to_return = NULL;
  253.     int old_patterns;
  254.     struct stat mystat;
  255.     int asked_file;
  256.  
  257. #ifdef FILE_STDIN
  258.     int file_supports_stdin = 1;
  259. #else
  260.     int file_supports_stdin = 0;
  261. #endif    
  262.     
  263.     /* Have we asked file for the file contents? */
  264.     asked_file = 0;
  265.  
  266.     if (data == NULL) {
  267.         int home_error = 0;
  268.         
  269.         buffer = copy_strings (home_dir, PATH_SEP_STR ".mc.ext", 0);
  270.         if (exist_file (buffer))
  271.         extension_file = buffer;
  272.         else
  273. check_stock_mc_ext:
  274.         extension_file = LIBDIR "mc.ext";
  275.         if ((data = load_file (extension_file)) == NULL) {
  276.         free (buffer);
  277.         return 0;
  278.     }
  279.     if (!strstr (data, "default/")) {
  280.         if (!strstr (data, "regex/") && !strstr (data, "shell/") &&
  281.             !strstr (data, "type/")) {
  282.             free (data);
  283.             data = NULL;
  284.             if (extension_file == buffer) {
  285.             home_error = 1;
  286.             goto check_stock_mc_ext;            
  287.             } else {
  288.                 message (1, " " LIBDIR "mc.ext file error", "\
  289. Format of the " LIBDIR "mc.ext file has changed\n\
  290. with version 3.0. It seems that installation\n\
  291. failed. Please fetch a fresh new copy from the\n\
  292. Midnight Commander package or in case you don't\n\
  293. have any, get it from ftp://ftp.nuclecu.unam.mx.");
  294.             free (buffer);
  295.             return 0;
  296.             }
  297.         }
  298.     }
  299.     if (home_error)
  300.         message (1, " ~/.mc.ext file error ", "\
  301. Format of the ~/.mc.ext file has changed\n\
  302. with version 3.0. You may want either to\n\
  303. copy it from " LIBDIR "mc.ext or use that\n\
  304. file as an example of how to write it.\n\
  305. " LIBDIR "mc.ext will be used for this moment.");
  306.         free (buffer);
  307.     }
  308.     mc_stat (filename, &mystat);
  309.     
  310.     regex_command_title = NULL;
  311.     old_patterns = easy_patterns;
  312.     easy_patterns = 0; /* Real regular expressions are needed :) */
  313.     for (p = data; *p; p++) {
  314.         for (q = p; *q == ' ' || *q == '\t'; q++);
  315.         if (*q == '\n' || !*q)
  316.             p = q; /* empty line */
  317.         if (*p == '#') /* comment */
  318.             while (*p && *p != '\n')
  319.                 p++;
  320.     if (*p == '\n')
  321.         continue;
  322.     if (!*p)
  323.         break;
  324.     if (p == q) { /* i.e. starts in the first column, should be
  325.                    * keyword/descNL
  326.                    */
  327.         if (found && action == NULL) /* We have already accumulated all
  328.                           * the user actions 
  329.                           */
  330.             break;
  331.         found = 0;
  332.         q = strchr (p, '\n'); 
  333.         if (q == NULL)
  334.             q = strchr (p, 0);
  335.         c = *q;
  336.         *q = 0;
  337.         if (!strncmp (p, "regex/", 6)) {
  338.             p += 6;
  339.             /* Do not transform shell patterns, you can use shell/ for
  340.              * that
  341.              */
  342.             if (regexp_match (p, filename, match_normal))
  343.                 found = 1;
  344.         } else if (!strncmp (p, "directory/", 10)) {
  345.             if (S_ISDIR (mystat.st_mode) && regexp_match (p, filename, match_normal))
  346.                 found = 1;
  347.         } else if (!strncmp (p, "shell/", 6)) {
  348.             p += 6;
  349.             if (*p == '.') {
  350.                 if (!strncmp (p, filename + file_len - (q - p), 
  351.                     q - p))
  352.                     found = 1;
  353.             } else {
  354.                 if (q - p == file_len && !strncmp (p, filename, q - p))
  355.                     found = 1;
  356.             }
  357.         } else if (!strncmp (p, "type/", 5)) {
  358.         int islocal = vfs_file_is_local (filename);
  359.             p += 5;
  360.         
  361.             if (islocal || file_supports_stdin) {
  362.                 char *pp;
  363.                 int hasread = use_file_to_check_type;
  364.  
  365.             if (asked_file || !use_file_to_check_type)
  366.             goto match_file_output;
  367.  
  368.             hasread = 0;
  369.                 if (islocal) {
  370.                     char *command =
  371.                 copy_strings (FILE_CMD, "'", filename, "'", NULL);
  372.                     FILE *f = popen (command, "r");
  373.                 
  374.                     free (command);
  375.                     if (f != NULL) {
  376.                         hasread = (fgets (content_string, 2047, f) 
  377.                             != NULL);
  378.                         if (!hasread)
  379.                             content_string [0] = 0;
  380.                         pclose (f);
  381.                     }
  382.                 } else {
  383. #ifdef _OS_NT
  384.             message (1, " NT: Unimplemented file prediction ");
  385. #else
  386.                     int pipehandle, remotehandle;
  387.                     pid_t p;
  388.             
  389.                     remotehandle = mc_open (filename, O_RDONLY);
  390.                 if (remotehandle != -1) {
  391.                 /* 8192 is HOWMANY hardcoded value in the file-3.14
  392.                  * sources. Tell me if any other file uses larger
  393.                  * chunk from beginning 
  394.                  */
  395.                         pipehandle = mc_doublepopen
  396.                 (remotehandle, 8192, &p,"file", "file", "-", NULL);
  397.                 if (pipehandle != -1) {
  398.                             int i;
  399.                             while ((i = read (pipehandle, content_string 
  400.                                  + hasread, 2047 - hasread)) > 0)
  401.                                 hasread += i;
  402.                             mc_doublepclose (pipehandle, p);
  403.                             content_string [hasread] = 0;
  404.                         }
  405.                         mc_close (remotehandle);
  406.                     }
  407. #endif /* _OS_NT */
  408.                 }
  409.             asked_file = 1;
  410. match_file_output:
  411.                 if (hasread) {
  412.                     if ((pp = strchr (content_string, '\n')) != 0)
  413.                         *pp = 0;
  414.                     if (islocal && !strncmp (content_string, 
  415.                         filename, file_len)) {
  416.                         content_shift = file_len;
  417.                         if (content_string [content_shift] == ':')
  418.                             for (content_shift++; 
  419.                                 content_string [content_shift] == ' '; 
  420.                                 content_shift++);
  421.                     } else if (!islocal 
  422.                    && !strncmp (content_string, 
  423.                         "standard input:", 15)) {
  424.                         for (content_shift = 15;
  425.                             content_string [content_shift] == ' ';
  426.                             content_shift++);
  427.                     }
  428.                 if (content_string && 
  429.                     regexp_match (p, content_string + 
  430.                         content_shift, match_normal)){
  431.                     found = 1;
  432.                 }
  433.                 }
  434.             }
  435.         } else if (!strncmp (p, "default/", 8)) {
  436.             p += 8;
  437.             found = 1;
  438.         }
  439.         *q = c;
  440.         p = q;
  441.         if (!*p)
  442.             break;
  443.         } else { /* List of actions */
  444.             p = q;
  445.             q = strchr (p, '\n');
  446.             if (q == NULL)
  447.                 q = strchr (p, 0);
  448.             if (found) {
  449.                 r = strchr (p, '=');
  450.                 if (r != NULL) {
  451.                     c = *r;
  452.                     *r = 0;
  453.                     if (action == NULL) {
  454.                         if (strcmp (p, "Open") && 
  455.                             strcmp (p, "View") &&
  456.                             strcmp (p, "Edit") &&
  457.                             strcmp (p, "Drop") &&
  458.                             strcmp (p, "Icon") &&
  459.                             strcmp (p, "Title")) {
  460.                             /* I.e. this is a name of a user defined action */
  461.                                 static char *q;
  462.                                 
  463.                                 if (to_return == NULL) {
  464.                                     to_return = xmalloc (512, "Action list");
  465.                                     q = to_return;
  466.                                 } else 
  467.                                     *(q++) = ' ';
  468.                                 strcpy (q, p);
  469.                                 q = strchr (q, 0);
  470.                         }
  471.                         *r = c;
  472.                     } else if (!strcmp (action, "Icon")) {
  473.                         if (!strcmp (p, "Icon") && to_return == NULL) {
  474.                             *r = c;
  475.                             c = *q;
  476.                             *q = 0;
  477.                             to_return = strdup (r + 1);
  478.                         } else if (!strcmp (p, "Title") && regex_command_title == NULL) {
  479.                             *r = c;
  480.                             c = *q;
  481.                             *q = 0;
  482.                             regex_command_title = strdup (r + 1);
  483.                         } else {
  484.                             *r = c;
  485.                             c = *q;
  486.                         }
  487.                         *q = c;
  488.                         if (to_return != NULL && regex_command_title != NULL)
  489.                             break;
  490.                     } else if (!strcmp (action, p)) {
  491.                         *r = c;
  492.                         for (p = r + 1; *p == ' ' || *p == '\t'; p++);
  493.                         if (p < q) { /* Empty commands just stop searching
  494.                                       * through, they don't do anything
  495.                                       */
  496.                             exec_extension (filename, r + 1, drops, move_dir);
  497.                             to_return = "Success";
  498.                         }
  499.                         break;
  500.                     } else
  501.                         *r = c;
  502.                 }
  503.             }
  504.             p = q;
  505.             if (!*p)
  506.                 break;
  507.         }
  508.     }
  509.     easy_patterns = old_patterns;
  510.     return to_return;
  511. }
  512.