Example #1
0
/* The second argument is action, i.e. Open, View or Edit
 *
 * This function returns:
 *
 * -1 for a failure or user interrupt
 * 0 if no command was run
 * 1 if some command was run
 *
 * If action == "View" then a parameter is checked in the form of "View:%d",
 * if the value for %d exists, then the viewer is started up at that line number.
 */
int
regex_command (const char *filename, const char *action, int *move_dir)
{
    char *p, *q, *r, c;
    int file_len = strlen (filename);
    int found = 0;
    int error_flag = 0;
    int ret = 0;
    struct stat mystat;
    int view_at_line_number;
    char *include_target;
    int include_target_len;
    int have_type = 0;		/* Flag used by regex_check_type() */

    /* Check for the special View:%d parameter */
    if (strncmp (action, "View:", 5) == 0) {
	view_at_line_number = atoi (action + 5);
	action = "View";
    } else {
	view_at_line_number = 0;
    }

    if (data == NULL) {
	char *extension_file;
	int mc_user_ext = 1;
	int home_error = 0;

	extension_file = concat_dir_and_file (home_dir, MC_USER_EXT);
	if (!exist_file (extension_file)) {
	    g_free (extension_file);
	  check_stock_mc_ext:
	    extension_file = concat_dir_and_file (mc_home, MC_LIB_EXT);
	    mc_user_ext = 0;
	}
	data = load_file (extension_file);
	g_free (extension_file);
	if (data == NULL)
	    return 0;

	if (!strstr (data, "default/")) {
	    if (!strstr (data, "regex/") && !strstr (data, "shell/")
		&& !strstr (data, "type/")) {
		g_free (data);
		data = NULL;
		if (mc_user_ext) {
		    home_error = 1;
		    goto check_stock_mc_ext;
		} else {
		    char *msg;
		    char *msg2;
		    msg =
			g_strconcat (" ", mc_home, MC_LIB_EXT,
				     _(" file error "), (char *) NULL);
		    msg2 =
			g_strconcat (_("Format of the "), mc_home,
				     _("mc.ext file has changed\n"
				       "with version 3.0. It seems that installation\n"
				       "failed. Please fetch a fresh new copy from the\n"
				       "Midnight Commander package."),
				     (char *) NULL);
		    message (1, msg, "%s", msg2);
		    g_free (msg);
		    g_free (msg2);
		    return 0;
		}
	    }
	}
	if (home_error) {
	    char *msg;
	    char *msg2;
	    msg =
		g_strconcat (" ~/", MC_USER_EXT, _(" file error "), (char *) NULL);
	    msg2 =
		g_strconcat (_("Format of the "), "~/", MC_USER_EXT,
			     _(" file has changed\n"
			       "with version 3.0. You may want either to\n"
			       "copy it from "), mc_home,
			     _("mc.ext or use that\n"
			       "file as an example of how to write it.\n"),
			     mc_home,
			     _("mc.ext will be used for this moment."),
			     (char *) NULL);
	    message (1, msg, "%s", msg2);
	    g_free (msg);
	    g_free (msg2);
	}
    }
    mc_stat (filename, &mystat);

    include_target = NULL;
    include_target_len = 0;
    for (p = data; *p; p++) {
	for (q = p; *q == ' ' || *q == '\t'; q++);
	if (*q == '\n' || !*q)
	    p = q;		/* empty line */
	if (*p == '#')		/* comment */
	    while (*p && *p != '\n')
		p++;
	if (*p == '\n')
	    continue;
	if (!*p)
	    break;
	if (p == q) {		/* i.e. starts in the first column, should be
				 * keyword/descNL
				 */
	    found = 0;
	    q = strchr (p, '\n');
	    if (q == NULL)
		q = strchr (p, 0);
	    c = *q;
	    *q = 0;
	    if (include_target) {
		if ((strncmp (p, "include/", 8) == 0)
		    && (strncmp (p + 8, include_target, include_target_len)
			== 0))
		    found = 1;
	    } else if (!strncmp (p, "regex/", 6)) {
		p += 6;
		/* Do not transform shell patterns, you can use shell/ for
		 * that
		 */
		if (regexp_match (p, filename, match_regex))
		    found = 1;
	    } else if (!strncmp (p, "directory/", 10)) {
		if (S_ISDIR (mystat.st_mode)
		    && regexp_match (p + 10, filename, match_regex))
		    found = 1;
	    } else if (!strncmp (p, "shell/", 6)) {
		p += 6;
		if (*p == '.' && file_len >= (q - p)) {
		    if (!strncmp (p, filename + file_len - (q - p), q - p))
			found = 1;
		} else {
		    if (q - p == file_len && !strncmp (p, filename, q - p))
			found = 1;
		}
	    } else if (!strncmp (p, "type/", 5)) {
		int res;
		p += 5;
		res = regex_check_type (filename, p, &have_type);
		if (res == 1)
		    found = 1;
		if (res == -1)
		    error_flag = 1;	/* leave it if file cannot be opened */
	    } else if (!strncmp (p, "default/", 8)) {
		found = 1;
	    }
	    *q = c;
	    p = q;
	    if (!*p)
		break;
	} else {		/* List of actions */
	    p = q;
	    q = strchr (p, '\n');
	    if (q == NULL)
		q = strchr (p, 0);
	    if (found && !error_flag) {
		r = strchr (p, '=');
		if (r != NULL) {
		    c = *r;
		    *r = 0;
		    if (strcmp (p, "Include") == 0) {
			char *t;

			include_target = p + 8;
			t = strchr (include_target, '\n');
			if (t)
			    *t = 0;
			include_target_len = strlen (include_target);
			if (t)
			    *t = '\n';

			*r = c;
			p = q;
			found = 0;

			if (!*p)
			    break;
			continue;
		    }
		    if (!strcmp (action, p)) {
			*r = c;
			for (p = r + 1; *p == ' ' || *p == '\t'; p++);

			/* Empty commands just stop searching
			 * through, they don't do anything
			 *
			 * We need to copy the filename because exec_extension
			 * may end up invoking update_panels thus making the
			 * filename parameter invalid (ie, most of the time,
			 * we get filename as a pointer from current_panel->dir).
			 */
			if (p < q) {
			    char *filename_copy = g_strdup (filename);

			    exec_extension (filename_copy, r + 1, move_dir,
					    view_at_line_number);
			    g_free (filename_copy);

			    ret = 1;
			}
			break;
		    } else
			*r = c;
		}
	    }
	    p = q;
	    if (!*p)
		break;
	}
    }
    if (error_flag)
	return -1;
    return ret;
}
Example #2
0
File: ext.c Project: inso/mc
int
regex_command_for (void *target, const vfs_path_t * filename_vpath, const char *action,
                   vfs_path_t ** script_vpath)
{
    char *p, *q, *r, c;
    size_t file_len;
    gboolean found = FALSE;
    gboolean error_flag = FALSE;
    int ret = 0;
    struct stat mystat;
    int view_at_line_number;
    char *include_target;
    int include_target_len;
    int have_type = 0;          /* Flag used by regex_check_type() */

    if (filename_vpath == NULL)
        return 0;

    if (script_vpath != NULL)
        *script_vpath = NULL;

    /* Check for the special View:%d parameter */
    if (strncmp (action, "View:", 5) == 0)
    {
        view_at_line_number = atoi (action + 5);
        action = "View";
    }
    else
    {
        view_at_line_number = 0;
    }

    if (data == NULL)
    {
        char *extension_file;
        gboolean mc_user_ext = TRUE;
        gboolean home_error = FALSE;

        extension_file = mc_config_get_full_path (MC_FILEBIND_FILE);
        if (!exist_file (extension_file))
        {
            g_free (extension_file);
          check_stock_mc_ext:
            extension_file = mc_build_filename (mc_global.sysconfig_dir, MC_LIB_EXT, NULL);
            if (!exist_file (extension_file))
            {
                g_free (extension_file);
                extension_file = mc_build_filename (mc_global.share_data_dir, MC_LIB_EXT, NULL);
            }
            mc_user_ext = FALSE;
        }

        g_file_get_contents (extension_file, &data, NULL, NULL);
        g_free (extension_file);
        if (data == NULL)
            return 0;

        if (strstr (data, "default/") == NULL)
        {
            if (strstr (data, "regex/") == NULL && strstr (data, "shell/") == NULL &&
                strstr (data, "type/") == NULL)
            {
                g_free (data);
                data = NULL;

                if (!mc_user_ext)
                {
                    char *title;

                    title = g_strdup_printf (_(" %s%s file error"),
                                             mc_global.sysconfig_dir, MC_LIB_EXT);
                    message (D_ERROR, title, _("The format of the %smc.ext "
                                               "file has changed with version 3.0. It seems that "
                                               "the installation failed. Please fetch a fresh "
                                               "copy from the Midnight Commander package."),
                             mc_global.sysconfig_dir);
                    g_free (title);
                    return 0;
                }

                home_error = TRUE;
                goto check_stock_mc_ext;
            }
        }

        if (home_error)
        {
            char *filebind_filename;
            char *title;

            filebind_filename = mc_config_get_full_path (MC_FILEBIND_FILE);
            title = g_strdup_printf (_("%s file error"), filebind_filename);
            message (D_ERROR, title,
                     _("The format of the %s file has "
                       "changed with version 3.0. You may either want to copy "
                       "it from %smc.ext or use that file as an example of how to write it."),
                     filebind_filename, mc_global.sysconfig_dir);
            g_free (filebind_filename);
            g_free (title);
        }
    }

    mc_stat (filename_vpath, &mystat);

    include_target = NULL;
    include_target_len = 0;
    file_len = vfs_path_len (filename_vpath);

    for (p = data; *p != '\0'; p++)
    {
        for (q = p; *q == ' ' || *q == '\t'; q++)
            ;
        if (*q == '\n' || *q == '\0')
            p = q;              /* empty line */
        if (*p == '#')          /* comment */
            while (*p != '\0' && *p != '\n')
                p++;
        if (*p == '\n')
            continue;
        if (*p == '\0')
            break;
        if (p == q)
        {                       /* i.e. starts in the first column, should be
                                 * keyword/descNL
                                 */
            gboolean case_insense;

            found = FALSE;
            q = strchr (p, '\n');
            if (q == NULL)
                q = strchr (p, '\0');
            c = *q;
            *q = '\0';
            if (include_target)
            {
                if ((strncmp (p, "include/", 8) == 0)
                    && (strncmp (p + 8, include_target, include_target_len) == 0))
                    found = TRUE;
            }
            else if (strncmp (p, "regex/", 6) == 0)
            {
                mc_search_t *search;

                p += 6;
                case_insense = (strncmp (p, "i/", 2) == 0);
                if (case_insense)
                    p += 2;

                search = mc_search_new (p, -1);
                if (search != NULL)
                {
                    search->search_type = MC_SEARCH_T_REGEX;
                    search->is_case_sensitive = !case_insense;
                    found =
                        mc_search_run (search, vfs_path_as_str (filename_vpath), 0, file_len, NULL);
                    mc_search_free (search);
                }
            }
            else if (strncmp (p, "directory/", 10) == 0)
            {
                if (S_ISDIR (mystat.st_mode)
                    && mc_search (p + 10, vfs_path_as_str (filename_vpath), MC_SEARCH_T_REGEX))
                    found = TRUE;
            }
            else if (strncmp (p, "shell/", 6) == 0)
            {
                int (*cmp_func) (const char *s1, const char *s2, size_t n) = strncmp;

                p += 6;
                case_insense = (strncmp (p, "i/", 2) == 0);
                if (case_insense)
                {
                    p += 2;
                    cmp_func = strncasecmp;
                }

                if (*p == '.' && file_len >= (size_t) (q - p))
                {
                    if (cmp_func
                        (p, vfs_path_as_str (filename_vpath) + file_len - (q - p), q - p) == 0)
                        found = TRUE;
                }
                else
                {
                    if ((size_t) (q - p) == file_len
                        && cmp_func (p, vfs_path_as_str (filename_vpath), q - p) == 0)
                        found = TRUE;
                }
            }
            else if (strncmp (p, "type/", 5) == 0)
            {
                GError *error = NULL;

                p += 5;

                case_insense = (strncmp (p, "i/", 2) == 0);
                if (case_insense)
                    p += 2;

                found = regex_check_type (filename_vpath, p, &have_type, case_insense, &error);
                if (error != NULL)
                {
                    g_error_free (error);
                    error_flag = TRUE;  /* leave it if file cannot be opened */
                }
            }
            else if (strncmp (p, "default/", 8) == 0)
                found = TRUE;

            *q = c;
            p = q;
            if (*p == '\0')
                break;
        }
        else
        {                       /* List of actions */
            p = q;
            q = strchr (p, '\n');
            if (q == NULL)
                q = strchr (p, '\0');
            if (found && !error_flag)
            {
                r = strchr (p, '=');
                if (r != NULL)
                {
                    c = *r;
                    *r = '\0';
                    if (strcmp (p, "Include") == 0)
                    {
                        char *t;

                        include_target = p + 8;
                        t = strchr (include_target, '\n');
                        if (t != NULL)
                            *t = '\0';
                        include_target_len = strlen (include_target);
                        if (t != NULL)
                            *t = '\n';

                        *r = c;
                        p = q;
                        found = FALSE;

                        if (*p == '\0')
                            break;
                        continue;
                    }

                    if (strcmp (action, p) != 0)
                        *r = c;
                    else
                    {
                        *r = c;

                        for (p = r + 1; *p == ' ' || *p == '\t'; p++)
                            ;

                        /* Empty commands just stop searching
                         * through, they don't do anything
                         */
                        if (p < q)
                        {
                            vfs_path_t *sv;

                            sv = exec_extension (target, filename_vpath, r + 1,
                                                 view_at_line_number);
                            if (script_vpath != NULL)
                                *script_vpath = sv;
                            else
                                exec_cleanup_script (sv);

                            ret = 1;
                        }
                        break;
                    }
                }
            }
            p = q;
            if (*p == '\0')
                break;
        }
    }
    if (error_flag)
        ret = -1;
    return ret;
}