Exemple #1
0
static void
exec_extension (const char *filename, const char *data, int *move_dir,
		int start_line)
{
    char *file_name;
    int cmd_file_fd;
    FILE *cmd_file;
    char *cmd = NULL;
    int expand_prefix_found = 0;
    int parameter_found = 0;
    char prompt[80];
    int run_view = 0;
    int def_hex_mode = default_hex_mode, changed_hex_mode = 0;
    int def_nroff_flag = default_nroff_flag, changed_nroff_flag = 0;
    int written_nonspace = 0;
    int is_cd = 0;
    char buffer[1024];
    char *p = 0;
    char *localcopy = NULL;
    int do_local_copy;
    time_t localmtime = 0;
    struct stat mystat;
    quote_func_t quote_func = name_quote;

    g_return_if_fail (filename != NULL);
    g_return_if_fail (data != NULL);

    /* Avoid making a local copy if we are doing a cd */
    if (!vfs_file_is_local (filename))
	do_local_copy = 1;
    else
	do_local_copy = 0;

    /*
     * All commands should be run in /bin/sh regardless of user shell.
     * To do that, create temporary shell script and run it.
     * Sometimes it's not needed (e.g. for %cd and %view commands),
     * but it's easier to create it anyway.
     */
    cmd_file_fd = mc_mkstemps (&file_name, "mcext", SCRIPT_SUFFIX);

    if (cmd_file_fd == -1) {
	message (1, MSG_ERROR,
		 _(" Cannot create temporary command file \n %s "),
		 unix_error_string (errno));
	return;
    }
    cmd_file = fdopen (cmd_file_fd, "w");
    fputs ("#! /bin/sh\n", cmd_file);

    prompt[0] = 0;
    for (; *data && *data != '\n'; data++) {
	if (parameter_found) {
	    if (*data == '}') {
		char *parameter;
		parameter_found = 0;
		parameter = input_dialog (_(" Parameter "), prompt, "");
		if (!parameter) {
		    /* User canceled */
		    fclose (cmd_file);
		    unlink (file_name);
		    if (localcopy) {
			mc_ungetlocalcopy (filename, localcopy, 0);
		    }
		    g_free (file_name);
		    return;
		}
		fputs (parameter, cmd_file);
		written_nonspace = 1;
		g_free (parameter);
	    } else {
		int len = strlen (prompt);

		if (len < sizeof (prompt) - 1) {
		    prompt[len] = *data;
		    prompt[len + 1] = 0;
		}
	    }
	} else if (expand_prefix_found) {
	    expand_prefix_found = 0;
	    if (*data == '{')
		parameter_found = 1;
	    else {
		int i = check_format_view (data);
		char *v;

		if (i) {
		    data += i - 1;
		    run_view = 1;
		} else if ((i = check_format_cd (data)) > 0) {
		    is_cd = 1;
		    quote_func = fake_name_quote;
		    do_local_copy = 0;
		    p = buffer;
		    data += i - 1;
		} else if ((i = check_format_var (data, &v)) > 0 && v) {
		    fputs (v, cmd_file);
		    g_free (v);
		    data += i;
		} else {
		    char *text;

		    if (*data == 'f') {
			if (do_local_copy) {
			    localcopy = mc_getlocalcopy (filename);
			    if (localcopy == NULL) {
				fclose (cmd_file);
				unlink (file_name);
				g_free (file_name);
				return;
			    }
			    mc_stat (localcopy, &mystat);
			    localmtime = mystat.st_mtime;
			    text = (*quote_func) (localcopy, 0);
			} else {
			    text = (*quote_func) (filename, 0);
			}
		    } else
			text = expand_format (NULL, *data, !is_cd);
		    if (!is_cd)
			fputs (text, cmd_file);
		    else {
			strcpy (p, text);
			p = strchr (p, 0);
		    }
		    g_free (text);
		    written_nonspace = 1;
		}
	    }
	} else {
	    if (*data == '%')
		expand_prefix_found = 1;
	    else {
		if (*data != ' ' && *data != '\t')
		    written_nonspace = 1;
		if (is_cd)
		    *(p++) = *data;
		else
		    fputc (*data, cmd_file);
	    }
	}
    }				/* for */

    /*
     * Make the script remove itself when it finishes.
     * Don't do it for the viewer - it may need to rerun the script,
     * so we clean up after calling view().
     */
    if (!run_view) {
	fprintf (cmd_file, "\n/bin/rm -f %s\n", file_name);
    }

    fclose (cmd_file);

    if ((run_view && !written_nonspace) || is_cd) {
	unlink (file_name);
	g_free (file_name);
	file_name = NULL;
    } else {
	/* Set executable flag on the command file ... */
	chmod (file_name, S_IRWXU);
	/* ... but don't rely on it - run /bin/sh explicitly */
	cmd = g_strconcat ("/bin/sh ", file_name, NULL);
    }

    if (run_view) {
	altered_hex_mode = 0;
	altered_nroff_flag = 0;
	if (def_hex_mode != default_hex_mode)
	    changed_hex_mode = 1;
	if (def_nroff_flag != default_nroff_flag)
	    changed_nroff_flag = 1;

	/* If we've written whitespace only, then just load filename
	 * into view
	 */
	if (written_nonspace) {
	    view (cmd, filename, move_dir, start_line);
	    unlink (file_name);
	} else {
	    view (0, filename, move_dir, start_line);
	}
	if (changed_hex_mode && !altered_hex_mode)
	    default_hex_mode = def_hex_mode;
	if (changed_nroff_flag && !altered_nroff_flag)
	    default_nroff_flag = def_nroff_flag;
	repaint_screen ();
    } else if (is_cd) {
	char *q;
	*p = 0;
	p = buffer;
/*	while (*p == ' ' && *p == '\t')
 *	    p++;
 */
	/* Search last non-space character. Start search at the end in order
	   not to short filenames containing spaces. */
	q = p + strlen (p) - 1;
	while (q >= p && (*q == ' ' || *q == '\t'))
	    q--;
	q[1] = 0;
	do_cd (p, cd_parse_command);
    } else {
	shell_execute (cmd, EXECUTE_INTERNAL);
	if (console_flag) {
	    handle_console (CONSOLE_SAVE);
	    if (output_lines && keybar_visible) {
		show_console_contents (output_start_y,
				       LINES - keybar_visible -
				       output_lines - 1,
				       LINES - keybar_visible - 1);

	    }
	}
    }

    g_free (file_name);
    g_free (cmd);

    if (localcopy) {
	mc_stat (localcopy, &mystat);
	mc_ungetlocalcopy (filename, localcopy,
			   localmtime != mystat.st_mtime);
    }
}
Exemple #2
0
static void
execute_menu_command (WEdit * edit_widget, const char *commands, gboolean show_prompt)
{
    FILE *cmd_file;
    int cmd_file_fd;
    int expand_prefix_found = 0;
    char *parameter = 0;
    gboolean do_quote = FALSE;
    char lc_prompt[80];
    int col;
    vfs_path_t *file_name_vpath;
    int run_view = 0;

    /* Skip menu entry title line */
    commands = strchr (commands, '\n');
    if (!commands)
    {
        return;
    }

    cmd_file_fd = mc_mkstemps (&file_name_vpath, "mcusr", SCRIPT_SUFFIX);

    if (cmd_file_fd == -1)
    {
        message (D_ERROR, MSG_ERROR, _("Cannot create temporary command file\n%s"),
                 unix_error_string (errno));
        vfs_path_free (file_name_vpath);
        return;
    }
    cmd_file = fdopen (cmd_file_fd, "w");
    fputs ("#! /bin/sh\n", cmd_file);
    commands++;

    for (col = 0; *commands; commands++)
    {
        if (col == 0)
        {
            if (*commands != ' ' && *commands != '\t')
                break;
            while (*commands == ' ' || *commands == '\t')
                commands++;
            if (*commands == 0)
                break;
        }
        col++;
        if (*commands == '\n')
            col = 0;
        if (parameter)
        {
            if (*commands == '}')
            {
                *parameter = 0;
                parameter =
                    input_dialog (_("Parameter"), lc_prompt, MC_HISTORY_FM_MENU_EXEC_PARAM, "",
                                  INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD |
                                  INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_VARIABLES |
                                  INPUT_COMPLETE_USERNAMES);
                if (!parameter || !*parameter)
                {
                    /* User canceled */
                    fclose (cmd_file);
                    mc_unlink (file_name_vpath);
                    vfs_path_free (file_name_vpath);
                    return;
                }
                if (do_quote)
                {
                    char *tmp;

                    tmp = name_quote (parameter, 0);
                    fputs (tmp, cmd_file);
                    g_free (tmp);
                }
                else
                    fputs (parameter, cmd_file);
                g_free (parameter);
                parameter = 0;
            }
            else
            {
                if (parameter < &lc_prompt[sizeof (lc_prompt) - 1])
                {
                    *parameter++ = *commands;
                }
            }
        }
        else if (expand_prefix_found)
        {
            expand_prefix_found = 0;
            if (g_ascii_isdigit ((gchar) * commands))
            {
                do_quote = (atoi (commands) != 0);
                while (g_ascii_isdigit ((gchar) * commands))
                    commands++;
            }
            if (*commands == '{')
                parameter = lc_prompt;
            else
            {
                char *text = expand_format (edit_widget, *commands, do_quote);
                fputs (text, cmd_file);
                g_free (text);
            }
        }
        else
        {
            if (*commands == '%')
            {
                int i = check_format_view (commands + 1);
                if (i)
                {
                    commands += i;
                    run_view = 1;
                }
                else
                {
                    do_quote = TRUE;    /* Default: Quote expanded macro */
                    expand_prefix_found = 1;
                }
            }
            else
                fputc (*commands, cmd_file);
        }
    }
    fclose (cmd_file);
    mc_chmod (file_name_vpath, S_IRWXU);
    if (run_view)
    {
        mcview_viewer (vfs_path_as_str (file_name_vpath), NULL, 0);
        dialog_switch_process_pending ();
    }
    else
    {
        /* execute the command indirectly to allow execution even
         * on no-exec filesystems. */
        char *cmd;

        cmd = g_strconcat ("/bin/sh ", vfs_path_as_str (file_name_vpath), (char *) NULL);
        if (!show_prompt)
        {
            if (system (cmd) == -1)
                message (D_ERROR, MSG_ERROR, "%s", _("Error calling program"));
        }
        else
        {
            shell_execute (cmd, EXECUTE_HIDE);
        }
        g_free (cmd);
    }
    mc_unlink (file_name_vpath);
    vfs_path_free (file_name_vpath);
}
Exemple #3
0
Fichier : ext.c Projet : inso/mc
static vfs_path_t *
exec_extension (void *target, const vfs_path_t * filename_vpath, const char *lc_data,
                int start_line)
{
    char *shell_string, *export_variables;
    vfs_path_t *script_vpath = NULL;
    int cmd_file_fd;
    FILE *cmd_file;
    char *cmd = NULL;

    g_return_val_if_fail (lc_data != NULL, NULL);

    pbuffer = NULL;
    localmtime = 0;
    quote_func = name_quote;
    run_view = FALSE;
    is_cd = FALSE;
    written_nonspace = FALSE;

    /* Avoid making a local copy if we are doing a cd */
    do_local_copy = !vfs_file_is_local (filename_vpath);

    shell_string = exec_make_shell_string (lc_data, filename_vpath);

    if (shell_string == NULL)
        goto ret;

    if (is_cd)
    {
        exec_extension_cd ();
        g_free (shell_string);
        goto ret;
    }

    /*
     * All commands should be run in /bin/sh regardless of user shell.
     * To do that, create temporary shell script and run it.
     * Sometimes it's not needed (e.g. for %cd and %view commands),
     * but it's easier to create it anyway.
     */
    cmd_file_fd = mc_mkstemps (&script_vpath, "mcext", SCRIPT_SUFFIX);

    if (cmd_file_fd == -1)
    {
        message (D_ERROR, MSG_ERROR,
                 _("Cannot create temporary command file\n%s"), unix_error_string (errno));
        goto ret;
    }

    cmd_file = fdopen (cmd_file_fd, "w");
    fputs ("#! /bin/sh\n\n", cmd_file);

    export_variables = exec_get_export_variables (filename_vpath);
    if (export_variables != NULL)
    {
        fprintf (cmd_file, "%s\n", export_variables);
        g_free (export_variables);
    }

    fputs (shell_string, cmd_file);
    g_free (shell_string);

    /*
     * Make the script remove itself when it finishes.
     * Don't do it for the viewer - it may need to rerun the script,
     * so we clean up after calling view().
     */
    if (!run_view)
        fprintf (cmd_file, "\n/bin/rm -f %s\n", vfs_path_as_str (script_vpath));

    fclose (cmd_file);

    if ((run_view && !written_nonspace) || is_cd)
    {
        exec_cleanup_script (script_vpath);
        script_vpath = NULL;
    }
    else
    {
        /* Set executable flag on the command file ... */
        mc_chmod (script_vpath, S_IRWXU);
        /* ... but don't rely on it - run /bin/sh explicitly */
        cmd = g_strconcat ("/bin/sh ", vfs_path_as_str (script_vpath), (char *) NULL);
    }

    if (run_view)
    {
        /* If we've written whitespace only, then just load filename into view */
        if (!written_nonspace)
            exec_extension_view (target, NULL, filename_vpath, start_line);
        else
            exec_extension_view (target, cmd, filename_vpath, start_line);
    }
    else
    {
        shell_execute (cmd, EXECUTE_INTERNAL);
        if (mc_global.tty.console_flag != '\0')
        {
            handle_console (CONSOLE_SAVE);
            if (output_lines && mc_global.keybar_visible)
                show_console_contents (output_start_y,
                                       LINES - mc_global.keybar_visible -
                                       output_lines - 1, LINES - mc_global.keybar_visible - 1);
        }
    }

    g_free (cmd);

    exec_cleanup_file_name (filename_vpath, TRUE);
  ret:
    return script_vpath;
}
Exemple #4
0
void
chown_advanced_cmd (void)
{

    files_on_begin = current_panel->marked;

    do {			/* do while any files remaining */
	init_chown_advanced ();

	if (current_panel->marked)
	    fname = next_file ();	/* next marked file */
	else
	    fname = selection (current_panel)->fname;	/* single file */

	if (mc_stat (fname, sf_stat) != 0) {	/* get status of file */
	    destroy_dlg (ch_dlg);
	    break;
	}
	ch_cmode = sf_stat->st_mode;

	chown_refresh ();
	
	update_ownership ();

	/* game can begin */
	run_dlg (ch_dlg);

	switch (ch_dlg->ret_value) {
	case B_CANCEL:
	    end_chown = 1;
	    break;

	case B_ENTER:
	    need_update = 1;
	    if (mc_chmod (fname, get_mode ()) == -1)
		message (D_ERROR, MSG_ERROR, _(" Cannot chmod \"%s\" \n %s "),
			 fname, unix_error_string (errno));
	    /* call mc_chown only, if mc_chmod didn't fail */
	    else if (mc_chown (fname, (ch_flags[9] == '+') ? sf_stat->st_uid : (uid_t) -1,
	                       (ch_flags[10] == '+') ? sf_stat->st_gid : (gid_t) -1) == -1)
		message (D_ERROR, MSG_ERROR, _(" Cannot chown \"%s\" \n %s "),
			 fname, unix_error_string (errno));
	    break;
	case B_SETALL:
	    apply_advanced_chowns (sf_stat);
	    break;

	case B_SKIP:
	    break;

	}

	if (current_panel->marked && ch_dlg->ret_value != B_CANCEL) {
	    do_file_mark (current_panel, current_file, 0);
	    need_update = 1;
	}
	destroy_dlg (ch_dlg);
    } while (current_panel->marked && !end_chown);

    chown_advanced_done ();
}
Exemple #5
0
static gboolean
feed_subshell (int how, gboolean fail_on_error)
{
    fd_set read_set;            /* For 'select' */
    int bytes;                  /* For the return value from 'read' */
    int i;                      /* Loop counter */

    struct timeval wtime;       /* Maximum time we wait for the subshell */
    struct timeval *wptr;

    /* we wait up to 10 seconds if fail_on_error, forever otherwise */
    wtime.tv_sec = 10;
    wtime.tv_usec = 0;
    wptr = fail_on_error ? &wtime : NULL;

    while (TRUE)
    {
        int maxfdp;

        if (!subshell_alive)
            return FALSE;

        /* Prepare the file-descriptor set and call 'select' */

        FD_ZERO (&read_set);
        FD_SET (mc_global.tty.subshell_pty, &read_set);
        FD_SET (subshell_pipe[READ], &read_set);
        maxfdp = MAX (mc_global.tty.subshell_pty, subshell_pipe[READ]);
        if (how == VISIBLY)
        {
            FD_SET (STDIN_FILENO, &read_set);
            maxfdp = MAX (maxfdp, STDIN_FILENO);
        }

        if (select (maxfdp + 1, &read_set, NULL, NULL, wptr) == -1)
        {
            /* Despite using SA_RESTART, we still have to check for this */
            if (errno == EINTR)
            {
                if (mc_global.tty.winch_flag != 0)
                    tty_change_screen_size ();

                continue;       /* try all over again */
            }
            tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
            fprintf (stderr, "select (FD_SETSIZE, &read_set...): %s\r\n",
                     unix_error_string (errno));
            exit (EXIT_FAILURE);
        }

        if (FD_ISSET (mc_global.tty.subshell_pty, &read_set))
            /* Read from the subshell, write to stdout */

            /* This loop improves performance by reducing context switches
               by a factor of 20 or so... unfortunately, it also hangs MC
               randomly, because of an apparent Linux bug.  Investigate. */
            /* for (i=0; i<5; ++i)  * FIXME -- experimental */
        {
            bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer));

            /* The subshell has died */
            if (bytes == -1 && errno == EIO && !subshell_alive)
                return FALSE;

            if (bytes <= 0)
            {
                tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
                fprintf (stderr, "read (subshell_pty...): %s\r\n", unix_error_string (errno));
                exit (EXIT_FAILURE);
            }

            if (how == VISIBLY)
                write_all (STDOUT_FILENO, pty_buffer, bytes);
        }

        else if (FD_ISSET (subshell_pipe[READ], &read_set))
            /* Read the subshell's CWD and capture its prompt */
        {
            bytes = read (subshell_pipe[READ], subshell_cwd, sizeof (subshell_cwd));
            if (bytes <= 0)
            {
                tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
                fprintf (stderr, "read (subshell_pipe[READ]...): %s\r\n",
                         unix_error_string (errno));
                exit (EXIT_FAILURE);
            }

            subshell_cwd[bytes - 1] = 0;        /* Squash the final '\n' */

            synchronize ();

            subshell_ready = TRUE;
            if (subshell_state == RUNNING_COMMAND)
            {
                subshell_state = INACTIVE;
                return TRUE;
            }
        }

        else if (FD_ISSET (STDIN_FILENO, &read_set))
            /* Read from stdin, write to the subshell */
        {
            bytes = read (STDIN_FILENO, pty_buffer, sizeof (pty_buffer));
            if (bytes <= 0)
            {
                tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
                fprintf (stderr,
                         "read (STDIN_FILENO, pty_buffer...): %s\r\n", unix_error_string (errno));
                exit (EXIT_FAILURE);
            }

            for (i = 0; i < bytes; ++i)
                if (pty_buffer[i] == subshell_switch_key)
                {
                    write_all (mc_global.tty.subshell_pty, pty_buffer, i);
                    if (subshell_ready)
                        subshell_state = INACTIVE;
                    return TRUE;
                }

            write_all (mc_global.tty.subshell_pty, pty_buffer, bytes);

            if (pty_buffer[bytes - 1] == '\n' || pty_buffer[bytes - 1] == '\r')
                subshell_ready = FALSE;
        }
        else
            return FALSE;
    }
}
Exemple #6
0
gboolean
mcview_load (mcview_t * view, const char *command, const char *file, int start_line)
{
    gboolean retval = FALSE;
    vfs_path_t *vpath = NULL;

#ifdef HAVE_ASSERT_H
    assert (view->bytes_per_line != 0);
#endif

    view->filename_vpath = vfs_path_from_str (file);

    /* get working dir */
    if (file != NULL && file[0] != '\0')
    {
        vfs_path_free (view->workdir_vpath);

        if (!g_path_is_absolute (file))
        {
            vfs_path_t *p;

            p = vfs_path_clone (vfs_get_raw_current_dir ());
            view->workdir_vpath = vfs_path_append_new (p, file, (char *) NULL);
            vfs_path_free (p);
        }
        else
        {
            /* try extract path form filename */
            const char *fname;
            char *dir;

            fname = x_basename (file);
            dir = g_strndup (file, (size_t) (fname - file));
            view->workdir_vpath = vfs_path_from_str (dir);
            g_free (dir);
        }
    }

    if (!mcview_is_in_panel (view))
        view->dpy_text_column = 0;

    mcview_set_codeset (view);

    if (command != NULL && (view->magic_mode || file == NULL || file[0] == '\0'))
        retval = mcview_load_command_output (view, command);
    else if (file != NULL && file[0] != '\0')
    {
        int fd;
        char tmp[BUF_MEDIUM];
        struct stat st;

        /* Open the file */
        vpath = vfs_path_from_str (file);
        fd = mc_open (vpath, O_RDONLY | O_NONBLOCK);
        if (fd == -1)
        {
            g_snprintf (tmp, sizeof (tmp), _("Cannot open \"%s\"\n%s"),
                        file, unix_error_string (errno));
            mcview_show_error (view, tmp);
            vfs_path_free (view->filename_vpath);
            view->filename_vpath = NULL;
            vfs_path_free (view->workdir_vpath);
            view->workdir_vpath = NULL;
            goto finish;
        }

        /* Make sure we are working with a regular file */
        if (mc_fstat (fd, &st) == -1)
        {
            mc_close (fd);
            g_snprintf (tmp, sizeof (tmp), _("Cannot stat \"%s\"\n%s"),
                        file, unix_error_string (errno));
            mcview_show_error (view, tmp);
            vfs_path_free (view->filename_vpath);
            view->filename_vpath = NULL;
            vfs_path_free (view->workdir_vpath);
            view->workdir_vpath = NULL;
            goto finish;
        }

        if (!S_ISREG (st.st_mode))
        {
            mc_close (fd);
            mcview_show_error (view, _("Cannot view: not a regular file"));
            vfs_path_free (view->filename_vpath);
            view->filename_vpath = NULL;
            vfs_path_free (view->workdir_vpath);
            view->workdir_vpath = NULL;
            goto finish;
        }

        if (st.st_size == 0 || mc_lseek (fd, 0, SEEK_SET) == -1)
        {
            /* Must be one of those nice files that grow (/proc) */
            mcview_set_datasource_vfs_pipe (view, fd);
        }
        else
        {
            int type;

            type = get_compression_type (fd, file);

            if (view->magic_mode && (type != COMPRESSION_NONE))
            {
                char *tmp_filename;
                vfs_path_t *vpath1;
                int fd1;

                tmp_filename = g_strconcat (file, decompress_extension (type), (char *) NULL);
                vpath1 = vfs_path_from_str (tmp_filename);
                fd1 = mc_open (vpath1, O_RDONLY | O_NONBLOCK);
                if (fd1 == -1)
                {
                    g_snprintf (tmp, sizeof (tmp), _("Cannot open \"%s\" in parse mode\n%s"),
                                file, unix_error_string (errno));
                    mcview_show_error (view, tmp);
                }
                else
                {
                    mc_close (fd);
                    fd = fd1;
                    mc_fstat (fd, &st);
                }
                vfs_path_free (vpath1);

                g_free (tmp_filename);
            }
            mcview_set_datasource_file (view, fd, &st);
        }
        retval = TRUE;
    }

  finish:
    view->command = g_strdup (command);
    view->dpy_start = 0;
    view->search_start = 0;
    view->search_end = 0;
    view->dpy_text_column = 0;

    mcview_compute_areas (view);
    mcview_update_bytes_per_line (view);

    if (mcview_remember_file_position && view->filename_vpath != NULL && start_line == 0)
    {
        long line, col;
        off_t new_offset, max_offset;

        load_file_position (view->filename_vpath, &line, &col, &new_offset, &view->saved_bookmarks);
        max_offset = mcview_get_filesize (view) - 1;
        if (max_offset < 0)
            new_offset = 0;
        else
            new_offset = min (new_offset, max_offset);
        if (!view->hex_mode)
            view->dpy_start = mcview_bol (view, new_offset, 0);
        else
        {
            view->dpy_start = new_offset - new_offset % view->bytes_per_line;
            view->hex_cursor = new_offset;
        }
    }
    else if (start_line > 0)
        mcview_moveto (view, start_line - 1, 0);

    view->hexedit_lownibble = FALSE;
    view->hexview_in_text = FALSE;
    view->change_list = NULL;
    vfs_path_free (vpath);
    return retval;
}
Exemple #7
0
void
chown_cmd (void)
{
    char *fname;
    struct stat sf_stat;
    Dlg_head *ch_dlg;
    uid_t new_user;
    gid_t new_group;
    char buffer[BUF_TINY];

    do
    {                           /* do while any files remaining */
        ch_dlg = init_chown ();
        new_user = new_group = -1;

        if (current_panel->marked)
            fname = next_file ();       /* next marked file */
        else
            fname = selection (current_panel)->fname;   /* single file */

        if (mc_stat (fname, &sf_stat) != 0)
        {                       /* get status of file */
            destroy_dlg (ch_dlg);
            break;
        }

        /* select in listboxes */
        listbox_select_entry (l_user, listbox_search_text (l_user, get_owner (sf_stat.st_uid)));
        listbox_select_entry (l_group, listbox_search_text (l_group, get_group (sf_stat.st_gid)));

        chown_label (0, str_trunc (fname, 15));
        chown_label (1, str_trunc (get_owner (sf_stat.st_uid), 15));
        chown_label (2, str_trunc (get_group (sf_stat.st_gid), 15));
        size_trunc_len (buffer, 15, sf_stat.st_size, 0, panels_options.kilobyte_si);
        chown_label (3, buffer);
        chown_label (4, string_perm (sf_stat.st_mode));

        switch (run_dlg (ch_dlg))
        {
        case B_CANCEL:
            end_chown = 1;
            break;

        case B_SETUSR:
            {
                struct passwd *user;
                char *text;

                listbox_get_current (l_user, &text, NULL);
                user = getpwnam (text);
                if (user)
                {
                    new_user = user->pw_uid;
                    apply_chowns (new_user, new_group);
                }
                break;
            }

        case B_SETGRP:
            {
                struct group *grp;
                char *text;

                listbox_get_current (l_group, &text, NULL);
                grp = getgrnam (text);
                if (grp)
                {
                    new_group = grp->gr_gid;
                    apply_chowns (new_user, new_group);
                }
                break;
            }

        case B_SETALL:
        case B_ENTER:
            {
                struct group *grp;
                struct passwd *user;
                char *text;

                listbox_get_current (l_group, &text, NULL);
                grp = getgrnam (text);
                if (grp)
                    new_group = grp->gr_gid;
                listbox_get_current (l_user, &text, NULL);
                user = getpwnam (text);
                if (user)
                    new_user = user->pw_uid;
                if (ch_dlg->ret_value == B_ENTER)
                {
                    need_update = 1;
                    if (mc_chown (fname, new_user, new_group) == -1)
                        message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"),
                                 fname, unix_error_string (errno));
                }
                else
                    apply_chowns (new_user, new_group);
                break;
            }
        }                       /* switch */

        if (current_panel->marked && ch_dlg->ret_value != B_CANCEL)
        {
            do_file_mark (current_panel, current_file, 0);
            need_update = 1;
        }

        destroy_dlg (ch_dlg);
    }
    while (current_panel->marked && !end_chown);

    chown_done ();
}
Exemple #8
0
void
init_subshell (void)
{
    /* This must be remembered across calls to init_subshell() */
    static char pty_name[BUF_SMALL];
    char precmd[BUF_SMALL];

    switch (check_sid ())
    {
    case 1:
        mc_global.tty.use_subshell = FALSE;
        return;
    case 2:
        mc_global.tty.use_subshell = FALSE;
        mc_global.widget.midnight_shutdown = TRUE;
        return;
    }

    /* Take the current (hopefully pristine) tty mode and make */
    /* a raw mode based on it now, before we do anything else with it */
    init_raw_mode ();

    if (mc_global.tty.subshell_pty == 0)
    {                           /* First time through */
        /* Find out what type of shell we have */

        if (strstr (shell, "/zsh") || getenv ("ZSH_VERSION"))
            subshell_type = ZSH;
        else if (strstr (shell, "/tcsh"))
            subshell_type = TCSH;
        else if (strstr (shell, "/csh"))
            subshell_type = TCSH;
        else if (strstr (shell, "/bash") || getenv ("BASH"))
            subshell_type = BASH;
        else if (strstr (shell, "/fish"))
            subshell_type = FISH;
        else
        {
            mc_global.tty.use_subshell = FALSE;
            return;
        }

        /* Open a pty for talking to the subshell */

        /* FIXME: We may need to open a fresh pty each time on SVR4 */

        mc_global.tty.subshell_pty = pty_open_master (pty_name);
        if (mc_global.tty.subshell_pty == -1)
        {
            fprintf (stderr, "Cannot open master side of pty: %s\r\n", unix_error_string (errno));
            mc_global.tty.use_subshell = FALSE;
            return;
        }
        subshell_pty_slave = pty_open_slave (pty_name);
        if (subshell_pty_slave == -1)
        {
            fprintf (stderr, "Cannot open slave side of pty %s: %s\r\n",
                     pty_name, unix_error_string (errno));
            mc_global.tty.use_subshell = FALSE;
            return;
        }

        /* Create a pipe for receiving the subshell's CWD */

        if (subshell_type == TCSH)
        {
            g_snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d",
                        mc_tmpdir (), (int) getpid ());
            if (mkfifo (tcsh_fifo, 0600) == -1)
            {
                fprintf (stderr, "mkfifo(%s) failed: %s\r\n", tcsh_fifo, unix_error_string (errno));
                mc_global.tty.use_subshell = FALSE;
                return;
            }

            /* Opening the FIFO as O_RDONLY or O_WRONLY causes deadlock */

            if ((subshell_pipe[READ] = open (tcsh_fifo, O_RDWR)) == -1
                || (subshell_pipe[WRITE] = open (tcsh_fifo, O_RDWR)) == -1)
            {
                fprintf (stderr, _("Cannot open named pipe %s\n"), tcsh_fifo);
                perror (__FILE__ ": open");
                mc_global.tty.use_subshell = FALSE;
                return;
            }
        }
        else /* subshell_type is BASH or ZSH */ if (pipe (subshell_pipe))
        {
            perror (__FILE__ ": couldn't create pipe");
            mc_global.tty.use_subshell = FALSE;
            return;
        }
    }

    /* Fork the subshell */

    subshell_alive = TRUE;
    subshell_stopped = FALSE;
    subshell_pid = fork ();

    if (subshell_pid == -1)
    {
        fprintf (stderr, "Cannot spawn the subshell process: %s\r\n", unix_error_string (errno));
        /* We exit here because, if the process table is full, the */
        /* other method of running user commands won't work either */
        exit (EXIT_FAILURE);
    }

    if (subshell_pid == 0)
    {
        /* We are in the child process */
        init_subshell_child (pty_name);
    }

    /* Set up `precmd' or equivalent for reading the subshell's CWD */

    switch (subshell_type)
    {
    case BASH:
        g_snprintf (precmd, sizeof (precmd),
                    " PROMPT_COMMAND='pwd>&%d;kill -STOP $$'\n", subshell_pipe[WRITE]);
        break;

    case ZSH:
        g_snprintf (precmd, sizeof (precmd),
                    " precmd(){ pwd>&%d;kill -STOP $$ }\n", subshell_pipe[WRITE]);
        break;

    case TCSH:
        g_snprintf (precmd, sizeof (precmd),
                    "set echo_style=both;"
                    "alias precmd 'echo $cwd:q >>%s;kill -STOP $$'\n", tcsh_fifo);
        break;
    case FISH:
        g_snprintf (precmd, sizeof (precmd),
                    "function fish_prompt ; pwd>&%d;kill -STOP %%self; end\n",
                    subshell_pipe[WRITE]);
        break;

    }
    write_all (mc_global.tty.subshell_pty, precmd, strlen (precmd));

    /* Wait until the subshell has started up and processed the command */

    subshell_state = RUNNING_COMMAND;
    tty_enable_interrupt_key ();
    if (!feed_subshell (QUIETLY, TRUE))
    {
        mc_global.tty.use_subshell = FALSE;
    }
    tty_disable_interrupt_key ();
    if (!subshell_alive)
        mc_global.tty.use_subshell = FALSE;     /* Subshell died instantly, so don't use it */
}
Exemple #9
0
static int
sftpfs_open_socket (struct vfs_s_super *super, GError ** error)
{
    struct addrinfo hints, *res = NULL, *curr_res;
    int my_socket = 0;
    char port[BUF_TINY];
    int e;

    if (super->path_element->host == NULL || *super->path_element->host == '\0')
    {
        g_set_error (error, MC_ERROR, -1, _("sftp: Invalid host name."));
        return -1;
    }

    sprintf (port, "%hu", (unsigned short) super->path_element->port);
    if (port == NULL)
    {
        g_set_error (error, MC_ERROR, -1, _("sftp: Invalid port value."));
        return -1;
    }

    tty_enable_interrupt_key ();        /* clear the interrupt flag */

    memset (&hints, 0, sizeof (struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

#ifdef AI_ADDRCONFIG
    /* By default, only look up addresses using address types for
     * which a local interface is configured (i.e. no IPv6 if no IPv6
     * interfaces, likewise for IPv4 (see RFC 3493 for details). */
    hints.ai_flags = AI_ADDRCONFIG;
#endif

    e = getaddrinfo (super->path_element->host, port, &hints, &res);

#ifdef AI_ADDRCONFIG
    if (e == EAI_BADFLAGS)
    {
        /* Retry with no flags if AI_ADDRCONFIG was rejected. */
        hints.ai_flags = 0;
        e = getaddrinfo (super->path_element->host, port, &hints, &res);
    }
#endif

    if (e != 0)
    {
        g_set_error (error, MC_ERROR, -1, _("sftp: %s"), gai_strerror (e));
        my_socket = -1;
        goto ret;
    }

    for (curr_res = res; curr_res != NULL; curr_res = curr_res->ai_next)
    {
        my_socket = socket (curr_res->ai_family, curr_res->ai_socktype, curr_res->ai_protocol);

        if (my_socket < 0)
        {
            if (curr_res->ai_next != NULL)
                continue;

            vfs_print_message (_("sftp: %s"), unix_error_string (errno));
            my_socket = -1;
            goto ret;
        }

        vfs_print_message (_("sftp: making connection to %s"), super->path_element->host);

        if (connect (my_socket, curr_res->ai_addr, curr_res->ai_addrlen) >= 0)
            break;

        close (my_socket);

        if (errno == EINTR && tty_got_interrupt ())
            g_set_error (error, MC_ERROR, -1, _("sftp: connection interrupted by user"));
        else if (res->ai_next == NULL)
            g_set_error (error, MC_ERROR, -1, _("sftp: connection to server failed: %s"),
                         unix_error_string (errno));
        else
            continue;

        my_socket = -1;
        break;
    }

  ret:
    if (res != NULL)
        freeaddrinfo (res);
    tty_disable_interrupt_key ();
    return my_socket;
}
Exemple #10
0
const char *
mc_tmpdir (void)
{
    static char buffer[64];
    static const char *tmpdir;
    const char *sys_tmp;
    struct passwd *pwd;
    struct stat st;
    const char *error = NULL;

    /* Check if already correctly initialized */
    if (tmpdir && lstat (tmpdir, &st) == 0 && S_ISDIR (st.st_mode) &&
        st.st_uid == getuid () && (st.st_mode & 0777) == 0700)
        return tmpdir;

    sys_tmp = getenv ("TMPDIR");
    if (!sys_tmp || sys_tmp[0] != '/')
    {
        sys_tmp = TMPDIR_DEFAULT;
    }

    pwd = getpwuid (getuid ());

    if (pwd)
        g_snprintf (buffer, sizeof (buffer), "%s/mc-%s", sys_tmp, pwd->pw_name);
    else
        g_snprintf (buffer, sizeof (buffer), "%s/mc-%lu", sys_tmp, (unsigned long) getuid ());

    canonicalize_pathname (buffer);

    if (lstat (buffer, &st) == 0)
    {
        /* Sanity check for existing directory */
        if (!S_ISDIR (st.st_mode))
            error = _("%s is not a directory\n");
        else if (st.st_uid != getuid ())
            error = _("Directory %s is not owned by you\n");
        else if (((st.st_mode & 0777) != 0700) && (chmod (buffer, 0700) != 0))
            error = _("Cannot set correct permissions for directory %s\n");
    }
    else
    {
        /* Need to create directory */
        if (mkdir (buffer, S_IRWXU) != 0)
        {
            fprintf (stderr,
                     _("Cannot create temporary directory %s: %s\n"),
                     buffer, unix_error_string (errno));
            error = "";
        }
    }

    if (error != NULL)
    {
        int test_fd;
        char *test_fn, *fallback_prefix;
        int fallback_ok = 0;

        if (*error)
            fprintf (stderr, error, buffer);

        /* Test if sys_tmp is suitable for temporary files */
        fallback_prefix = g_strdup_printf ("%s/mctest", sys_tmp);
        test_fd = mc_mkstemps (&test_fn, fallback_prefix, NULL);
        g_free (fallback_prefix);
        if (test_fd != -1)
        {
            close (test_fd);
            test_fd = open (test_fn, O_RDONLY);
            if (test_fd != -1)
            {
                close (test_fd);
                unlink (test_fn);
                fallback_ok = 1;
            }
        }

        if (fallback_ok)
        {
            fprintf (stderr, _("Temporary files will be created in %s\n"), sys_tmp);
            g_snprintf (buffer, sizeof (buffer), "%s", sys_tmp);
            error = NULL;
        }
        else
        {
            fprintf (stderr, _("Temporary files will not be created\n"));
            g_snprintf (buffer, sizeof (buffer), "%s", "/dev/null/");
        }

        fprintf (stderr, "%s\n", _("Press any key to continue..."));
        getc (stdin);
    }

    tmpdir = buffer;

    if (!error)
        g_setenv ("MC_TMPDIR", tmpdir, TRUE);

    return tmpdir;
}
void
chown_cmd (void)
{
    char *fname;
    struct stat sf_stat;
    WLEntry *fe;
    uid_t new_user;
    gid_t new_group;
    char  buffer [15];

#if 0
    /* Please no */
    if (!vfs_current_is_local ()) {
	if (vfs_current_is_extfs ()) {
	    message (1, _(" Oops... "),
		     _(" I can't run the Chown command on an extfs "));
	    return;
	} else if (vfs_current_is_tarfs ()) {
	    message (1, _(" Oops... "),
		     _(" I can't run the Chown command on a tarfs "));
	    return;
	}
    }
#endif

    do {			/* do while any files remaining */
	init_chown ();
	new_user = new_group = -1;

	if (cpanel->marked)
	    fname = next_file ();	        /* next marked file */
	else
	    fname = selection (cpanel)->fname;	        /* single file */
	
	if (!stat_file (fname, &sf_stat)){	/* get status of file */
	    destroy_dlg (ch_dlg);
	    break;
	}
	
	/* select in listboxes */
	fe = listbox_search_text (l_user, get_owner(sf_stat.st_uid));
	if (fe)
	    listbox_select_entry (l_user, fe);
    
	fe = listbox_search_text (l_group, get_group(sf_stat.st_gid));
	if (fe)
	    listbox_select_entry (l_group, fe);

        chown_label (0, name_trunc (fname, 15));
        chown_label (1, name_trunc (get_owner (sf_stat.st_uid), 15));
	chown_label (2, name_trunc (get_group (sf_stat.st_gid), 15));
        sprintf (buffer, "%d", c_fsize);
	chown_label (3, buffer);
	chown_label (4, string_perm (sf_stat.st_mode));

	run_dlg (ch_dlg);
    
	switch (ch_dlg->ret_value) {
	case B_CANCEL:
	    end_chown = 1;
	    break;
	    
	case B_SETUSR:
	{
	    struct passwd *user;

	    user = getpwnam (l_user->current->text);
	    if (user){
		new_user = user->pw_uid;
		apply_chowns (new_user, new_group);
	    }
	    break;
	}   
	case B_SETGRP:
	{
	    struct group *grp;

	    grp = getgrnam (l_group->current->text);
	    if (grp){
		new_group = grp->gr_gid;
		apply_chowns (new_user, new_group);
	    }
	    break;
	}
	case B_SETALL:
	case B_ENTER:
	{
	    struct group *grp;
	    struct passwd *user;
	    
	    grp = getgrnam (l_group->current->text);
	    if (grp)
		new_group = grp->gr_gid;
	    user = getpwnam (l_user->current->text);
	    if (user)
		new_user = user->pw_uid;
	    if (ch_dlg->ret_value==B_ENTER) {
		need_update = 1;
		if (mc_chown (fname, new_user, new_group) == -1)
		    message (1, MSG_ERROR, _(" Couldn't chown \"%s\" \n %s "),
	 		 fname, unix_error_string (errno));
	    } else
		apply_chowns (new_user, new_group);
	    break;
	}
	}
	
	if (cpanel->marked && ch_dlg->ret_value != B_CANCEL){
	    do_file_mark (cpanel, current_file, 0);
	    need_update = 1;
	}
	destroy_dlg (ch_dlg);
    } while (cpanel->marked && !end_chown);
    
    chown_done ();
}
Exemple #12
0
void user_menu_cmd (void)
{
    char *menu, *p;
    int  col, i, accept_entry = 1;
    int  selected, old_patterns;
    Listbox *listbox;

    if (!vfs_current_is_local ()){
    message (1, _(" Oops... "),
         _(" I can't run programs while logged on a non local directory "));
    return;
    }

    menu = strdup (MC_LOCAL_MENU);
    if (!exist_file (menu) || !menu_file_own (menu)){
    free (menu);
#ifdef OS2_NT
    menu = strdup("NC.MNU");
    if (!exist_file (menu))
#endif
        {
        menu = concat_dir_and_file (home_dir, MC_HOME_MENU);
    if (!exist_file (menu)){
        free (menu);
        menu = concat_dir_and_file (mc_home, MC_GLOBAL_MENU);
    }
    }
    }

    if ((data = load_file (menu)) == NULL){
    message (1, MSG_ERROR, _(" Can't open file %s \n %s "),
         menu, unix_error_string (errno));
    free (menu);
    return;
    }
    free (menu);

    max_cols = 0;
    for (i = 0; i < MAX_ENTRIES; i++)
    entries [i] = 0;
    selected = 0;

    /* Parse the menu file */
    old_patterns = easy_patterns;
    p = check_patterns (data);
    for (menu_lines = col = 0; *p; p++){
    if (col == 0 && !entries [menu_lines]){
        if (*p == '#'){
        /* A commented menu entry */
        accept_entry = 1;
        } else if (*p == '+'){
        if (*(p+1) == '='){
            /* Combined adding and default */
            char *q = p++;

            p = test_line (q, &accept_entry);
            if (selected == 0 && accept_entry)
            selected = menu_lines;
        } else {
            /* A condition for adding the entry */
            p = test_line (p, &accept_entry);
        }
        } else if (*p == '='){
        if (*(p+1) == '+'){
            char *q = p++;
            /* Combined adding and default */
            p = test_line (q, &accept_entry);
            if (selected == 0 && accept_entry)
            selected = menu_lines;
        } else {
            /* A condition for making the entry default */
            i = 1;
            p = test_line (p, &i);
            if (selected == 0 && i)
            selected = menu_lines;
        }
        }
        else if (*p > ' ' && *p < 127){
        /* A menu entry title line */
        if (accept_entry)
            entries [menu_lines] = p;
        else
            accept_entry = 1;
        }
    }
    if (menu_lines == MAX_ENTRIES)
        break;
    if (*p == '\t')
        *p = ' ';
    col++;
    if (*p == '\n'){
        if (entries [menu_lines]){
        menu_lines++;
        accept_entry = 1;
        }
        max_cols = max (max_cols, col);
        col = 0;
    }
    }
    max_cols = min (max (max_cols, col), MAX_ENTRY_LEN);

    /* Create listbox */
    listbox = create_listbox_window (max_cols+2, menu_lines, _(" User menu "),
                     "[Menu File Edit]");

    /* insert all the items found */
    for (i = 0; i < menu_lines; i++)
    LISTBOX_APPEND_TEXT (listbox, entries [i][0],
                 extract_line (entries [i],
                       entries [i]+MAX_ENTRY_LEN),
                 entries [i]);

    /* Select the default entry */
    listbox_select_by_number (listbox->list, selected);

    selected = run_listbox (listbox);
    if (selected >= 0)
    execute_menu_command (entries [selected]);

    easy_patterns = old_patterns;
    do_refresh ();
    free (data);
}
Exemple #13
0
/* FIXME: recode this routine on version 3.0, it could be cleaner */
void execute_menu_command (char *s)
{
    char *commands;
    FILE *cmd_file;
    int  cmd_file_fd;
    int  expand_prefix_found = 0;
    int parameter_found = 0;
    int do_quote;
    char prompt [80] = "";
    int  col;
    char *file_name = tmpnam (0);

#ifdef OS2_NT
    /* OS/2 and NT requires the command to end in .cmd */
    file_name = copy_strings (file_name, ".cmd", NULL);
    file_name = "temp.bat";  // $$ fixme

    if ((cmd_file_fd = open (file_name, O_RDWR | O_CREAT | O_TRUNC | O_EXCL
                                                         | O_TEXT, 0600)) == -1){
    message (1, MSG_ERROR, _(" Can't create temporary command file \n %s "),
         unix_error_string (errno));
    return;
    }
#else
    if ((cmd_file_fd = open (file_name, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600)) == -1){
    message (1, MSG_ERROR, _(" Can't create temporary command file \n %s "),
         unix_error_string (errno));
    return;
    }
#endif
    cmd_file = fdopen (cmd_file_fd, "w");
    commands = strchr (s, '\n');
    if (!commands){
    fclose (cmd_file);
    unlink (file_name);
    return;
    }
    commands++;

    for (col = 0; *commands; commands++){
    if (col == 0 && (*commands != ' ' && *commands != '\t'))
        break;
        else if (col == 0)
        while (*commands == ' ' || *commands == '\t')
            commands++;
    col++;
    if (*commands == '\n')
        col = 0;
    if (parameter_found){
        if (*commands == '}'){
        char *parameter;
        char *tmp;
        parameter_found = 0;
        parameter = input_dialog (_(" Parameter "), prompt, "");
        if (!parameter || !*parameter){
            /* User canceled */
            fclose (cmd_file);
            unlink (file_name);
            return;
        }
        if (do_quote) {
                fputs (tmp = name_quote (parameter, 0), cmd_file);
            free (tmp);
        } else
            fputs (parameter, cmd_file);
        free (parameter);
        } else {
        int len = strlen (prompt);

        if (len+1 < sizeof (prompt)){
            prompt [len] = *commands;
            prompt [len+1] = 0;
        } else
            prompt [sizeof (prompt)-1] = 0;
        }
    } else if (expand_prefix_found){
        expand_prefix_found = 0;
        if (isdigit (*commands)) {
        do_quote = atoi (commands);
        for ( ; isdigit (*commands); commands++)
            ;
        }
        if (*commands == '{')
        parameter_found = 1;
        else{
        char *text = expand_format (*commands, do_quote);
        fputs (text, cmd_file);
        free (text);
        }
    } else {
        if (*commands == '%') {
        do_quote = 1; /* Default: Quote expanded macro */
        expand_prefix_found = 1;
        } else
        fputc (*commands, cmd_file);
    }
    }
    fclose (cmd_file);
    chmod (file_name, S_IRWXU);
    execute (file_name);
    unlink (file_name);
}
Exemple #14
0
gboolean
user_menu_cmd (struct WEdit * edit_widget, const char *menu_file, int selected_entry)
{
    char *p;
    char *data, **entries;
    int max_cols, menu_lines, menu_limit;
    int col, i, accept_entry = 1;
    int selected, old_patterns;
    gboolean res = FALSE;
    gboolean interactive = TRUE;

    if (!vfs_current_is_local ())
    {
        message (D_ERROR, MSG_ERROR, "%s", _("Cannot execute commands on non-local filesystems"));
        return FALSE;
    }
    if (menu_file != NULL)
        menu = g_strdup (menu_file);
    else
        menu = g_strdup (edit_widget ? EDIT_LOCAL_MENU : MC_LOCAL_MENU);
    if (!exist_file (menu) || !menu_file_own (menu))
    {
        if (menu_file != NULL)
        {
            message (D_ERROR, MSG_ERROR, _("Cannot open file %s\n%s"), menu,
                     unix_error_string (errno));
            MC_PTR_FREE (menu);
            return FALSE;
        }

        g_free (menu);
        if (edit_widget)
            menu = mc_config_get_full_path (EDIT_HOME_MENU);
        else
            menu = mc_config_get_full_path (MC_USERMENU_FILE);


        if (!exist_file (menu))
        {
            g_free (menu);
            menu =
                mc_build_filename (mc_config_get_home_dir (),
                                   edit_widget ? EDIT_GLOBAL_MENU : MC_GLOBAL_MENU, NULL);
            if (!exist_file (menu))
            {
                g_free (menu);
                menu =
                    mc_build_filename (mc_global.sysconfig_dir,
                                       edit_widget ? EDIT_GLOBAL_MENU : MC_GLOBAL_MENU, NULL);
                if (!exist_file (menu))
                {
                    g_free (menu);
                    menu = mc_build_filename
                        (mc_global.share_data_dir, edit_widget ? EDIT_GLOBAL_MENU : MC_GLOBAL_MENU,
                         NULL);
                }
            }
        }
    }

    if (!g_file_get_contents (menu, &data, NULL, NULL))
    {
        message (D_ERROR, MSG_ERROR, _("Cannot open file%s\n%s"), menu, unix_error_string (errno));
        MC_PTR_FREE (menu);
        return FALSE;
    }

    max_cols = 0;
    selected = 0;
    menu_limit = 0;
    entries = 0;

    /* Parse the menu file */
    old_patterns = easy_patterns;
    p = check_patterns (data);
    for (menu_lines = col = 0; *p; str_next_char (&p))
    {
        if (menu_lines >= menu_limit)
        {
            char **new_entries;

            menu_limit += MAX_ENTRIES;
            new_entries = g_try_realloc (entries, sizeof (new_entries[0]) * menu_limit);

            if (new_entries == NULL)
                break;

            entries = new_entries;
            new_entries += menu_limit;
            while (--new_entries >= &entries[menu_lines])
                *new_entries = NULL;
        }
        if (col == 0 && !entries[menu_lines])
        {
            if (*p == '#')
            {
                /* show prompt if first line of external script is #interactive */
                if (selected_entry >= 0 && strncmp (p, "#silent", 7) == 0)
                    interactive = FALSE;
                /* A commented menu entry */
                accept_entry = 1;
            }
            else if (*p == '+')
            {
                if (*(p + 1) == '=')
                {
                    /* Combined adding and default */
                    p = test_line (edit_widget, p + 1, &accept_entry);
                    if (selected == 0 && accept_entry)
                        selected = menu_lines;
                }
                else
                {
                    /* A condition for adding the entry */
                    p = test_line (edit_widget, p, &accept_entry);
                }
            }
            else if (*p == '=')
            {
                if (*(p + 1) == '+')
                {
                    /* Combined adding and default */
                    p = test_line (edit_widget, p + 1, &accept_entry);
                    if (selected == 0 && accept_entry)
                        selected = menu_lines;
                }
                else
                {
                    /* A condition for making the entry default */
                    i = 1;
                    p = test_line (edit_widget, p, &i);
                    if (selected == 0 && i)
                        selected = menu_lines;
                }
            }
            else if (*p != ' ' && *p != '\t' && str_isprint (p))
            {
                /* A menu entry title line */
                if (accept_entry)
                    entries[menu_lines] = p;
                else
                    accept_entry = 1;
            }
        }
        if (*p == '\n')
        {
            if (entries[menu_lines])
            {
                menu_lines++;
                accept_entry = 1;
            }
            max_cols = max (max_cols, col);
            col = 0;
        }
        else
        {
            if (*p == '\t')
                *p = ' ';
            col++;
        }
    }

    if (menu_lines == 0)
    {
        message (D_ERROR, MSG_ERROR, _("No suitable entries found in %s"), menu);
        res = FALSE;
    }
    else
    {
        if (selected_entry >= 0)
            selected = selected_entry;
        else
        {
            Listbox *listbox;

            max_cols = min (max (max_cols, col), MAX_ENTRY_LEN);

            /* Create listbox */
            listbox = create_listbox_window (menu_lines, max_cols + 2, _("User menu"),
                                             "[Menu File Edit]");
            /* insert all the items found */
            for (i = 0; i < menu_lines; i++)
            {
                p = entries[i];
                LISTBOX_APPEND_TEXT (listbox, (unsigned char) p[0],
                                     extract_line (p, p + MAX_ENTRY_LEN), p);
            }
            /* Select the default entry */
            listbox_select_entry (listbox->list, selected);

            selected = run_listbox (listbox);
        }
        if (selected >= 0)
        {
            execute_menu_command (edit_widget, entries[selected], interactive);
            res = TRUE;
        }

        do_refresh ();
    }

    easy_patterns = old_patterns;
    MC_PTR_FREE (menu);
    g_free (entries);
    g_free (data);
    return res;
}
Exemple #15
0
void
do_cd_command (char *orig_cmd)
{
    int len;
    int operand_pos = CD_OPERAND_OFFSET;
    const char *cmd;

    /* Any final whitespace should be removed here
       (to see why, try "cd fred "). */
    /* NOTE: I think we should not remove the extra space,
       that way, we can cd into hidden directories */
    /* FIXME: what about interpreting quoted strings like the shell.
       so one could type "cd <tab> M-a <enter>" and it would work. */
    len = strlen (orig_cmd) - 1;
    while (len >= 0 && (orig_cmd[len] == ' ' || orig_cmd[len] == '\t' || orig_cmd[len] == '\n'))
    {
        orig_cmd[len] = 0;
        len--;
    }

    cmd = orig_cmd;
    if (cmd[CD_OPERAND_OFFSET - 1] == 0)
        cmd = "cd ";            /* 0..2 => given text, 3 => \0 */

    /* allow any amount of white space in front of the path operand */
    while (cmd[operand_pos] == ' ' || cmd[operand_pos] == '\t')
        operand_pos++;

    if (get_current_type () == view_tree)
    {
        if (cmd[0] == 0)
        {
            sync_tree (mc_config_get_home_dir ());
        }
        else if (DIR_IS_DOTDOT (cmd + operand_pos))
        {
            if (vfs_path_elements_count (current_panel->cwd_vpath) != 1 ||
                strlen (vfs_path_get_by_index (current_panel->cwd_vpath, 0)->path) > 1)
            {
                vfs_path_t *tmp_vpath = current_panel->cwd_vpath;

                current_panel->cwd_vpath =
                    vfs_path_vtokens_get (tmp_vpath, 0, vfs_path_tokens_count (tmp_vpath) - 1);
                vfs_path_free (tmp_vpath);
            }
            sync_tree (vfs_path_as_str (current_panel->cwd_vpath));
        }
        else if (cmd[operand_pos] == PATH_SEP)
        {
            sync_tree (cmd + operand_pos);
        }
        else
        {
            vfs_path_t *new_vpath;

            new_vpath = vfs_path_append_new (current_panel->cwd_vpath, cmd + operand_pos, NULL);
            sync_tree (vfs_path_as_str (new_vpath));
            vfs_path_free (new_vpath);
        }
    }
    else
    {
        char *path;
        vfs_path_t *q_vpath;
        gboolean ok;

        path = examine_cd (&cmd[operand_pos]);

        if (*path == '\0')
            q_vpath = vfs_path_from_str (mc_config_get_home_dir ());
        else
            q_vpath = vfs_path_from_str_flags (path, VPF_NO_CANON);

        ok = do_cd (q_vpath, cd_parse_command);
        if (!ok)
            ok = handle_cdpath (path);

        if (!ok)
        {
            char *d;

            d = vfs_path_to_str_flags (q_vpath, 0, VPF_STRIP_PASSWORD);
            message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\"\n%s"), d,
                     unix_error_string (errno));
            g_free (d);
        }

        vfs_path_free (q_vpath);
        g_free (path);
    }
}
Exemple #16
0
void
chmod_cmd (void)
{
    chmod_i18n ();

    do
    {                           /* do while any files remaining */
        vfs_path_t *vpath;
        Dlg_head *ch_dlg;
        struct stat sf_stat;
        char *fname;
        int result;
        unsigned int i;

        do_refresh ();

        mode_change = FALSE;
        need_update = FALSE;
        end_chmod = FALSE;
        c_file = 0;

        if (current_panel->marked != 0)
            fname = next_file ();       /* next marked file */
        else
            fname = selection (current_panel)->fname;   /* single file */

        vpath = vfs_path_from_str (fname);

        if (mc_stat (vpath, &sf_stat) != 0)
        {
            vfs_path_free (vpath);
            break;
        }

        c_stat = sf_stat.st_mode;

        ch_dlg = init_chmod (fname, &sf_stat);

        /* do action */
        result = run_dlg (ch_dlg);

        switch (result)
        {
        case B_ENTER:
            if (mode_change && mc_chmod (vpath, c_stat) == -1)
                message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
                         fname, unix_error_string (errno));
            need_update = TRUE;
            break;

        case B_CANCEL:
            end_chmod = TRUE;
            break;

        case B_ALL:
        case B_MARKED:
            and_mask = or_mask = 0;
            and_mask = ~and_mask;

            for (i = 0; i < check_perm_num; i++)
                if (check_perm[i].selected || result == B_ALL)
                {
                    if (check_perm[i].check->state & C_BOOL)
                        or_mask |= check_perm[i].mode;
                    else
                        and_mask &= ~check_perm[i].mode;
                }

            apply_mask (&sf_stat);
            break;

        case B_SETMRK:
            and_mask = or_mask = 0;
            and_mask = ~and_mask;

            for (i = 0; i < check_perm_num; i++)
                if (check_perm[i].selected)
                    or_mask |= check_perm[i].mode;

            apply_mask (&sf_stat);
            break;

        case B_CLRMRK:
            and_mask = or_mask = 0;
            and_mask = ~and_mask;

            for (i = 0; i < check_perm_num; i++)
                if (check_perm[i].selected)
                    and_mask &= ~check_perm[i].mode;

            apply_mask (&sf_stat);
            break;
        }

        if (current_panel->marked != 0 && result != B_CANCEL)
        {
            do_file_mark (current_panel, c_file, 0);
            need_update = TRUE;
        }

        vfs_path_free (vpath);

        destroy_dlg (ch_dlg);
    }
    while (current_panel->marked != 0 && !end_chmod);

    chmod_done ();
}
Exemple #17
0
/* event callback */
gboolean
help_interactive_display (const gchar * event_group_name, const gchar * event_name,
                          gpointer init_data, gpointer data)
{
    const dlg_colors_t help_colors = {
        HELP_NORMAL_COLOR,      /* common text color */
        0,                      /* unused in help */
        HELP_BOLD_COLOR,        /* bold text color */
        0,                      /* unused in help */
        HELP_TITLE_COLOR        /* title color */
    };

    WButtonBar *help_bar;
    Widget *md;
    char *hlpfile = NULL;
    char *filedata;
    ev_help_t *event_data = (ev_help_t *) data;

    (void) event_group_name;
    (void) event_name;
    (void) init_data;

    if (event_data->filename != NULL)
        g_file_get_contents (event_data->filename, &filedata, NULL, NULL);
    else
        filedata = load_mc_home_file (mc_global.share_data_dir, MC_HELP, &hlpfile, NULL);

    if (filedata == NULL)
        message (D_ERROR, MSG_ERROR, _("Cannot open file %s\n%s"),
                 event_data->filename ? event_data->filename : hlpfile, unix_error_string (errno));

    g_free (hlpfile);

    if (filedata == NULL)
        return TRUE;

    translate_file (filedata);

    g_free (filedata);

    if (fdata == NULL)
        return TRUE;

    if ((event_data->node == NULL) || (*event_data->node == '\0'))
        event_data->node = "[main]";

    main_node = search_string (fdata, event_data->node);

    if (main_node == NULL)
    {
        message (D_ERROR, MSG_ERROR, _("Cannot find node %s in help file"), event_data->node);

        /* Fallback to [main], return if it also cannot be found */
        main_node = search_string (fdata, "[main]");
        if (main_node == NULL)
        {
            interactive_display_finish ();
            return TRUE;
        }
    }

    help_lines = MIN (LINES - 4, MAX (2 * LINES / 3, 18));

    whelp =
        dlg_create (TRUE, 0, 0, help_lines + 4, HELP_WINDOW_WIDTH + 4, WPOS_CENTER | WPOS_TRYUP,
                    FALSE, help_colors, help_callback, NULL, "[Help]", _("Help"));
    widget_want_tab (WIDGET (whelp), TRUE);

    selected_item = search_string_node (main_node, STRING_LINK_START) - 1;
    currentpoint = main_node + 1;       /* Skip the newline following the start of the node */

    for (history_ptr = HISTORY_SIZE; history_ptr;)
    {
        history_ptr--;
        history[history_ptr].page = currentpoint;
        history[history_ptr].link = selected_item;
    }

    help_bar = buttonbar_new (TRUE);
    WIDGET (help_bar)->y -= WIDGET (whelp)->y;
    WIDGET (help_bar)->x -= WIDGET (whelp)->x;

    md = mousedispatch_new (1, 1, help_lines, HELP_WINDOW_WIDTH - 2);

    add_widget (whelp, md);
    add_widget (whelp, help_bar);

    buttonbar_set_label (help_bar, 1, Q_ ("ButtonBar|Help"), help_map, NULL);
    buttonbar_set_label (help_bar, 2, Q_ ("ButtonBar|Index"), help_map, NULL);
    buttonbar_set_label (help_bar, 3, Q_ ("ButtonBar|Prev"), help_map, NULL);
    buttonbar_set_label (help_bar, 4, "", help_map, NULL);
    buttonbar_set_label (help_bar, 5, "", help_map, NULL);
    buttonbar_set_label (help_bar, 6, "", help_map, NULL);
    buttonbar_set_label (help_bar, 7, "", help_map, NULL);
    buttonbar_set_label (help_bar, 8, "", help_map, NULL);
    buttonbar_set_label (help_bar, 9, "", help_map, NULL);
    buttonbar_set_label (help_bar, 10, Q_ ("ButtonBar|Quit"), help_map, NULL);

    dlg_run (whelp);
    interactive_display_finish ();
    dlg_destroy (whelp);
    return TRUE;
}
Exemple #18
0
static void
init_subshell_child (const char *pty_name)
{
    char *init_file = NULL;
    char *putenv_str = NULL;
    pid_t mc_sid;

    (void) pty_name;
    setsid ();                  /* Get a fresh terminal session */

    /* Make sure that it has become our controlling terminal */

    /* Redundant on Linux and probably most systems, but just in case: */

#ifdef TIOCSCTTY
    ioctl (subshell_pty_slave, TIOCSCTTY, 0);
#endif

    /* Configure its terminal modes and window size */

    /* Set up the pty with the same termios flags as our own tty */
    if (tcsetattr (subshell_pty_slave, TCSANOW, &shell_mode))
    {
        fprintf (stderr, "Cannot set pty terminal modes: %s\r\n", unix_error_string (errno));
        my_exit (FORK_FAILURE);
    }

    /* Set the pty's size (80x25 by default on Linux) according to the */
    /* size of the real terminal as calculated by ncurses, if possible */
    tty_resize (subshell_pty_slave);

    /* Set up the subshell's environment and init file name */

    /* It simplifies things to change to our home directory here, */
    /* and the user's startup file may do a 'cd' command anyway   */
    {
        int ret;

        ret = chdir (mc_config_get_home_dir ());        /* FIXME? What about when we re-run the subshell? */
        (void) ret;
    }

    /* Set MC_SID to prevent running one mc from another */
    mc_sid = getsid (0);
    if (mc_sid != -1)
    {
        char sid_str[BUF_SMALL];

        g_snprintf (sid_str, sizeof (sid_str), "MC_SID=%ld", (long) mc_sid);
        putenv (g_strdup (sid_str));
    }

    switch (mc_global.shell->type)
    {
    case SHELL_BASH:
        /* Do we have a custom init file ~/.local/share/mc/bashrc? */
        init_file = mc_config_get_full_path ("bashrc");

        /* Otherwise use ~/.bashrc */
        if (!exist_file (init_file))
        {
            g_free (init_file);
            init_file = g_strdup (".bashrc");
        }

        /* Make MC's special commands not show up in bash's history and also suppress
         * consecutive identical commands*/
        putenv ((char *) "HISTCONTROL=ignoreboth");

        /* Allow alternative readline settings for MC */
        {
            char *input_file;

            input_file = mc_config_get_full_path ("inputrc");
            if (exist_file (input_file))
            {
                putenv_str = g_strconcat ("INPUTRC=", input_file, (char *) NULL);
                putenv (putenv_str);
            }
            g_free (input_file);
        }

        break;

    case SHELL_ASH_BUSYBOX:
    case SHELL_DASH:
        /* Do we have a custom init file ~/.local/share/mc/ashrc? */
        init_file = mc_config_get_full_path ("ashrc");

        /* Otherwise use ~/.profile */
        if (!exist_file (init_file))
        {
            g_free (init_file);
            init_file = g_strdup (".profile");
        }

        /* Put init file to ENV variable used by ash */
        putenv_str = g_strconcat ("ENV=", init_file, (char *) NULL);
        putenv (putenv_str);
        /* Do not use "g_free (putenv_str)" here, otherwise ENV will be undefined! */

        break;

        /* TODO: Find a way to pass initfile to TCSH, ZSH and FISH */
    case SHELL_TCSH:
    case SHELL_ZSH:
    case SHELL_FISH:
        break;

    default:
        fprintf (stderr, __FILE__ ": unimplemented subshell type %u\r\n", mc_global.shell->type);
        my_exit (FORK_FAILURE);
    }

    /* Attach all our standard file descriptors to the pty */

    /* This is done just before the fork, because stderr must still      */
    /* be connected to the real tty during the above error messages; */
    /* otherwise the user will never see them.                   */

    dup2 (subshell_pty_slave, STDIN_FILENO);
    dup2 (subshell_pty_slave, STDOUT_FILENO);
    dup2 (subshell_pty_slave, STDERR_FILENO);

    close (subshell_pipe[READ]);
    close (subshell_pty_slave); /* These may be FD_CLOEXEC, but just in case... */
    /* Close master side of pty.  This is important; apart from */
    /* freeing up the descriptor for use in the subshell, it also       */
    /* means that when MC exits, the subshell will get a SIGHUP and     */
    /* exit too, because there will be no more descriptors pointing     */
    /* at the master side of the pty and so it will disappear.  */
    close (mc_global.tty.subshell_pty);

    /* Execute the subshell at last */

    switch (mc_global.shell->type)
    {
    case SHELL_BASH:
        execl (mc_global.shell->path, "bash", "-rcfile", init_file, (char *) NULL);
        break;

    case SHELL_ZSH:
        /* Use -g to exclude cmds beginning with space from history
         * and -Z to use the line editor on non-interactive term */
        execl (mc_global.shell->path, "zsh", "-Z", "-g", (char *) NULL);

        break;

    case SHELL_ASH_BUSYBOX:
    case SHELL_DASH:
    case SHELL_TCSH:
    case SHELL_FISH:
        execl (mc_global.shell->path, mc_global.shell->path, (char *) NULL);
        break;

    default:
        break;
    }

    /* If we get this far, everything failed miserably */
    g_free (init_file);
    g_free (putenv_str);
    my_exit (FORK_FAILURE);
}
Exemple #19
0
ssize_t
read_with_timeout (int fd, char *buf, size_t mincnt, size_t maxcnt, unsigned int time_out)
{
    fd_set fds;
    int selrtn;
    ssize_t readret;
    size_t nread = 0;
    struct timeval timeout;

    /* just checking .... */
    if (maxcnt <= 0)
        return (0);

    smb_read_error = 0;

    /* Blocking read */
    if (time_out <= 0)
    {
        if (mincnt == 0)
            mincnt = maxcnt;

        while (nread < mincnt)
        {
#ifdef WITH_SSL
            if (fd == sslFd)
            {
                readret = SSL_read (ssl, buf + nread, maxcnt - nread);
            }
            else
            {
                readret = read (fd, buf + nread, maxcnt - nread);
            }
#else /* WITH_SSL */
            readret = read (fd, buf + nread, maxcnt - nread);
#endif /* WITH_SSL */

            if (readret == 0)
            {
                DEBUG (5, ("read_with_timeout: blocking read. EOF from client.\n"));
                smb_read_error = READ_EOF;
                return -1;
            }

            if (readret == -1)
            {
                DEBUG (0, ("read_with_timeout: read error = %s.\n", unix_error_string (errno)));
                smb_read_error = READ_ERROR;
                return -1;
            }
            nread += readret;
        }
        return ((ssize_t) nread);
    }

    /* Most difficult - timeout read */
    /* If this is ever called on a disk file and 
       mincnt is greater than the filesize then
       system performance will suffer severely as 
       select always returns true on disk files */

    /* Set initial timeout */
    timeout.tv_sec = (time_t) (time_out / 1000);
    timeout.tv_usec = (long) (1000 * (time_out % 1000));

    for (nread = 0; nread < mincnt;)
    {
        FD_ZERO (&fds);
        FD_SET (fd, &fds);

        selrtn = sys_select (fd + 1, &fds, &timeout);

        /* Check if error */
        if (selrtn == -1)
        {
            /* something is wrong. Maybe the socket is dead? */
            DEBUG (0,
                   ("read_with_timeout: timeout read. select error = %s.\n",
                    unix_error_string (errno)));
            smb_read_error = READ_ERROR;
            return -1;
        }

        /* Did we timeout ? */
        if (selrtn == 0)
        {
            DEBUG (10, ("read_with_timeout: timeout read. select timed out.\n"));
            smb_read_error = READ_TIMEOUT;
            return -1;
        }

#ifdef WITH_SSL
        if (fd == sslFd)
        {
            readret = SSL_read (ssl, buf + nread, maxcnt - nread);
        }
        else
        {
            readret = read (fd, buf + nread, maxcnt - nread);
        }
#else /* WITH_SSL */
        readret = read (fd, buf + nread, maxcnt - nread);
#endif /* WITH_SSL */

        if (readret == 0)
        {
            /* we got EOF on the file descriptor */
            DEBUG (5, ("read_with_timeout: timeout read. EOF from client.\n"));
            smb_read_error = READ_EOF;
            return -1;
        }

        if (readret == -1)
        {
            /* the descriptor is probably dead */
            DEBUG (0,
                   ("read_with_timeout: timeout read. read error = %s.\n",
                    unix_error_string (errno)));
            smb_read_error = READ_ERROR;
            return -1;
        }

        nread += readret;
    }

    /* Return the number we got */
    return ((ssize_t) nread);
}
Exemple #20
0
void
init_subshell (void)
{
    /* This must be remembered across calls to init_subshell() */
    static char pty_name[BUF_SMALL];
    /* Must be considerably longer than BUF_SMALL (128) to support fancy shell prompts */
    char precmd[BUF_MEDIUM];

    switch (check_sid ())
    {
    case 1:
        mc_global.tty.use_subshell = FALSE;
        return;
    case 2:
        mc_global.tty.use_subshell = FALSE;
        mc_global.midnight_shutdown = TRUE;
        return;
    default:
        break;
    }

    /* Take the current (hopefully pristine) tty mode and make */
    /* a raw mode based on it now, before we do anything else with it */
    init_raw_mode ();

    if (mc_global.tty.subshell_pty == 0)
    {                           /* First time through */
        if (mc_global.shell->type == SHELL_NONE)
            return;

        /* Open a pty for talking to the subshell */

        /* FIXME: We may need to open a fresh pty each time on SVR4 */

        mc_global.tty.subshell_pty = pty_open_master (pty_name);
        if (mc_global.tty.subshell_pty == -1)
        {
            fprintf (stderr, "Cannot open master side of pty: %s\r\n", unix_error_string (errno));
            mc_global.tty.use_subshell = FALSE;
            return;
        }
        subshell_pty_slave = pty_open_slave (pty_name);
        if (subshell_pty_slave == -1)
        {
            fprintf (stderr, "Cannot open slave side of pty %s: %s\r\n",
                     pty_name, unix_error_string (errno));
            mc_global.tty.use_subshell = FALSE;
            return;
        }

        /* Create a pipe for receiving the subshell's CWD */

        if (mc_global.shell->type == SHELL_TCSH)
        {
            g_snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d",
                        mc_tmpdir (), (int) getpid ());
            if (mkfifo (tcsh_fifo, 0600) == -1)
            {
                fprintf (stderr, "mkfifo(%s) failed: %s\r\n", tcsh_fifo, unix_error_string (errno));
                mc_global.tty.use_subshell = FALSE;
                return;
            }

            /* Opening the FIFO as O_RDONLY or O_WRONLY causes deadlock */

            if ((subshell_pipe[READ] = open (tcsh_fifo, O_RDWR)) == -1
                || (subshell_pipe[WRITE] = open (tcsh_fifo, O_RDWR)) == -1)
            {
                fprintf (stderr, _("Cannot open named pipe %s\n"), tcsh_fifo);
                perror (__FILE__ ": open");
                mc_global.tty.use_subshell = FALSE;
                return;
            }
        }
        else if (pipe (subshell_pipe))  /* subshell_type is BASH, ASH_BUSYBOX, DASH or ZSH */
        {
            perror (__FILE__ ": couldn't create pipe");
            mc_global.tty.use_subshell = FALSE;
            return;
        }
    }

    /* Fork the subshell */

    subshell_alive = TRUE;
    subshell_stopped = FALSE;
    subshell_pid = fork ();

    if (subshell_pid == -1)
    {
        fprintf (stderr, "Cannot spawn the subshell process: %s\r\n", unix_error_string (errno));
        /* We exit here because, if the process table is full, the */
        /* other method of running user commands won't work either */
        exit (EXIT_FAILURE);
    }

    if (subshell_pid == 0)
    {
        /* We are in the child process */
        init_subshell_child (pty_name);
    }

    init_subshell_precmd (precmd, BUF_MEDIUM);

    write_all (mc_global.tty.subshell_pty, precmd, strlen (precmd));

    /* Wait until the subshell has started up and processed the command */

    subshell_state = RUNNING_COMMAND;
    tty_enable_interrupt_key ();
    if (!feed_subshell (QUIETLY, TRUE))
    {
        mc_global.tty.use_subshell = FALSE;
    }
    tty_disable_interrupt_key ();
    if (!subshell_alive)
        mc_global.tty.use_subshell = FALSE;     /* Subshell died instantly, so don't use it */
}
Exemple #21
0
/****************************************************************************
open a socket of the specified type, port and address for incoming data
****************************************************************************/
int
open_socket_in (int type, int port, int dlevel, uint32 socket_addr, BOOL rebind)
{
    struct hostent *hp;
    struct sockaddr_in sock;
    pstring host_name;
    int res;

    /* get my host name */
    if (gethostname (host_name, MAXHOSTNAMELEN) == -1)
    {
        DEBUG (0, ("gethostname failed\n"));
        return -1;
    }

    /* get host info */
    if ((hp = Get_Hostbyname (host_name)) == 0)
    {
        DEBUG (0, ("Get_Hostbyname: Unknown host %s\n", host_name));
        return -1;
    }

    memset ((char *) &sock, '\0', sizeof (sock));
    memcpy ((char *) &sock.sin_addr, (char *) hp->h_addr, hp->h_length);

#ifdef HAVE_SOCK_SIN_LEN
    sock.sin_len = sizeof (sock);
#endif
    sock.sin_port = htons (port);
    sock.sin_family = hp->h_addrtype;
    sock.sin_addr.s_addr = socket_addr;
    res = socket (hp->h_addrtype, type, 0);
    if (res == -1)
    {
        DEBUG (0, ("socket failed\n"));
        return -1;
    }

    {
        int val = 1;
        if (rebind)
            val = 1;
        else
            val = 0;
        setsockopt (res, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof (val));
    }

    /* now we've got a socket - we need to bind it */
    if (bind (res, (struct sockaddr *) &sock, sizeof (sock)) < 0)
    {
        if (port)
        {
            if (port == SMB_PORT || port == NMB_PORT)
                DEBUG (dlevel, ("bind failed on port %d socket_addr=%s (%s)\n",
                                port, inet_ntoa (sock.sin_addr), unix_error_string (errno)));
            close (res);

            if (dlevel > 0 && port < 1000)
                port = 7999;

            if (port >= 1000 && port < 9000)
                return (open_socket_in (type, port + 1, dlevel, socket_addr, rebind));
        }

        return (-1);
    }
    DEBUG (3, ("bind succeeded on port %d\n", port));

    return res;
}
Exemple #22
0
static void
do_link (link_type_t link_type, const char *fname)
{
    char *dest = NULL, *src = NULL;
    vfs_path_t *fname_vpath, *dest_vpath = NULL;

    fname_vpath = vfs_path_from_str (fname);
    if (link_type == LINK_HARDLINK)
    {
        src = g_strdup_printf (_("Link %s to:"), str_trunc (fname, 46));
        dest =
            input_expand_dialog (_("Link"), src, MC_HISTORY_FM_LINK, "", INPUT_COMPLETE_FILENAMES);
        if (!dest || !*dest)
            goto cleanup;
        save_cwds_stat ();
        dest_vpath = vfs_path_from_str (dest);
        if (-1 == mc_link (fname_vpath, dest_vpath))
            message (D_ERROR, MSG_ERROR, _("link: %s"), unix_error_string (errno));
    }
    else
    {
        vfs_path_t *s, *d;

        /* suggest the full path for symlink, and either the full or
           relative path to the file it points to  */
        s = vfs_path_append_new (current_panel->cwd_vpath, fname, NULL);

        if (get_other_type () == view_listing)
            d = vfs_path_append_new (other_panel->cwd_vpath, fname, NULL);
        else
            d = vfs_path_from_str (fname);

        if (link_type == LINK_SYMLINK_RELATIVE)
        {
            char *s_str;

            s_str = diff_two_paths (other_panel->cwd_vpath, s);
            vfs_path_free (s);
            s = vfs_path_from_str_flags (s_str, VPF_NO_CANON);
            g_free (s_str);
        }

        symlink_dialog (s, d, &dest, &src);
        vfs_path_free (d);
        vfs_path_free (s);

        if (!dest || !*dest || !src || !*src)
            goto cleanup;
        save_cwds_stat ();

        dest_vpath = vfs_path_from_str_flags (dest, VPF_NO_CANON);

        s = vfs_path_from_str (src);
        if (mc_symlink (dest_vpath, s) == -1)
            message (D_ERROR, MSG_ERROR, _("symlink: %s"), unix_error_string (errno));
        vfs_path_free (s);
    }

    update_panels (UP_OPTIMIZE, UP_KEEPSEL);
    repaint_screen ();

  cleanup:
    vfs_path_free (fname_vpath);
    vfs_path_free (dest_vpath);
    g_free (src);
    g_free (dest);
}
Exemple #23
0
/****************************************************************************
  create an outgoing socket. timeout is in milliseconds.
  **************************************************************************/
int
open_socket_out (int type, struct in_addr *addr, int port, int timeout)
{
    struct sockaddr_in sock_out;
    int res, ret;
    int connect_loop = 250;     /* 250 milliseconds */
    int loops = (timeout) / connect_loop;

    /* create a socket to write to */
    res = socket (PF_INET, type, 0);
    if (res == -1)
    {
        DEBUG (0, ("socket error\n"));
        return -1;
    }

    if (type != SOCK_STREAM)
        return (res);

    memset ((char *) &sock_out, '\0', sizeof (sock_out));
    putip ((char *) &sock_out.sin_addr, (char *) addr);

    sock_out.sin_port = htons (port);
    sock_out.sin_family = PF_INET;

    /* set it non-blocking */
    set_blocking (res, False);

    DEBUG (3, ("Connecting to %s at port %d\n", inet_ntoa (*addr), port));

    /* and connect it to the destination */
  connect_again:
    ret = connect (res, (struct sockaddr *) &sock_out, sizeof (sock_out));

    /* Some systems return EAGAIN when they mean EINPROGRESS */
    if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || errno == EAGAIN) && loops--)
    {
        msleep (connect_loop);
        goto connect_again;
    }

    if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || errno == EAGAIN))
    {
        DEBUG (1, ("timeout connecting to %s:%d\n", inet_ntoa (*addr), port));
        close (res);
        return -1;
    }

#ifdef EISCONN
    if (ret < 0 && errno == EISCONN)
    {
        errno = 0;
        ret = 0;
    }
#endif

    if (ret < 0)
    {
        DEBUG (1, ("error connecting to %s:%d (%s)\n",
                   inet_ntoa (*addr), port, unix_error_string (errno)));
        close (res);
        return -1;
    }

    /* set it blocking again */
    set_blocking (res, True);

    return res;
}
Exemple #24
0
void
chown_advanced_cmd (void)
{
    /* Number of files at startup */
    int files_on_begin;

    files_on_begin = MAX (1, current_panel->marked);

    do
    {                           /* do while any files remaining */
        int file_idx;
        char buffer[BUF_MEDIUM];
        vfs_path_t *vpath;
        int result;

        init_chown_advanced ();

        if (current_panel->marked)
            fname = next_file ();       /* next marked file */
        else
            fname = selection (current_panel)->fname;   /* single file */
        vpath = vfs_path_from_str (fname);

        if (mc_stat (vpath, sf_stat) != 0)
        {                       /* get status of file */
            dlg_destroy (ch_dlg);
            vfs_path_free (vpath);
            break;
        }

        ch_cmode = sf_stat->st_mode;

        file_idx = files_on_begin == 1 ? 1 : (files_on_begin - current_panel->marked + 1);
        g_snprintf (buffer, sizeof (buffer), "%s (%d/%d)",
                    str_fit_to_term (fname, WIDGET (ch_dlg)->cols - 20, J_LEFT_FIT),
                    file_idx, files_on_begin);
        label_set_text (l_filename, buffer);
        chown_refresh ();
        update_ownership ();

        result = dlg_run (ch_dlg);

        switch (result)
        {
        case B_CANCEL:
            end_chown = TRUE;
            break;

        case B_ENTER:
            need_update = TRUE;
            if (mc_chmod (vpath, get_mode ()) == -1)
                message (D_ERROR, MSG_ERROR, _("Cannot chmod \"%s\"\n%s"),
                         fname, unix_error_string (errno));
            /* call mc_chown only, if mc_chmod didn't fail */
            else if (mc_chown
                     (vpath, (ch_flags[9] == '+') ? sf_stat->st_uid : (uid_t) (-1),
                      (ch_flags[10] == '+') ? sf_stat->st_gid : (gid_t) (-1)) == -1)
                message (D_ERROR, MSG_ERROR, _("Cannot chown \"%s\"\n%s"), fname,
                         unix_error_string (errno));
            break;

        case B_SETALL:
            apply_advanced_chowns (sf_stat);
            break;

        case B_SKIP:
        default:
            break;
        }

        if (current_panel->marked && result != B_CANCEL)
        {
            do_file_mark (current_panel, current_file, 0);
            need_update = TRUE;
        }
        dlg_destroy (ch_dlg);
        vfs_path_free (vpath);
    }
    while (current_panel->marked && !end_chown);

    chown_advanced_done ();
}
Exemple #25
0
void
mcview_growbuf_read_until (WView * view, off_t ofs)
{
    gboolean short_read = FALSE;

#ifdef HAVE_ASSERT_H
    assert (view->growbuf_in_use);
#endif

    if (view->growbuf_finished)
        return;

    while (mcview_growbuf_filesize (view) < ofs || short_read)
    {
        ssize_t nread = 0;
        byte *p;
        size_t bytesfree;

        if (view->growbuf_lastindex == VIEW_PAGE_SIZE)
        {
            /* Append a new block to the growing buffer */
            byte *newblock = g_try_malloc (VIEW_PAGE_SIZE);
            if (newblock == NULL)
                return;

            g_ptr_array_add (view->growbuf_blockptr, newblock);
            view->growbuf_lastindex = 0;
        }

        p = (byte *) g_ptr_array_index (view->growbuf_blockptr,
                                        view->growbuf_blockptr->len - 1) + view->growbuf_lastindex;

        bytesfree = VIEW_PAGE_SIZE - view->growbuf_lastindex;

        if (view->datasource == DS_STDIO_PIPE)
        {
            mc_pipe_t *sp = view->ds_stdio_pipe;
            GError *error = NULL;

            if (bytesfree > MC_PIPE_BUFSIZE)
                bytesfree = MC_PIPE_BUFSIZE;

            sp->out.len = bytesfree;
            sp->err.len = MC_PIPE_BUFSIZE;

            mc_pread (sp, &error);

            if (error != NULL)
            {
                mcview_show_error (view, error->message);
                g_error_free (error);
                mcview_growbuf_done (view);
                return;
            }

            if (view->pipe_first_err_msg && sp->err.len > 0)
            {
                /* ignore possible following errors */
                /* reset this flag before call of mcview_show_error() to break
                 * endless recursion: mcview_growbuf_read_until() -> mcview_show_error() ->
                 * MSG_DRAW -> mcview_display() -> mcview_get_byte() -> mcview_growbuf_read_until()
                 */
                view->pipe_first_err_msg = FALSE;

                mcview_show_error (view, sp->err.buf);
            }

            if (sp->out.len > 0)
            {
                memmove (p, sp->out.buf, sp->out.len);
                nread = sp->out.len;
            }
            else if (sp->out.len == MC_PIPE_STREAM_EOF || sp->out.len == MC_PIPE_ERROR_READ)
            {
                if (sp->out.len == MC_PIPE_ERROR_READ)
                {
                    char *err_msg;

                    err_msg = g_strdup_printf (_("Failed to read data from child stdout:\n%s"),
                                               unix_error_string (sp->out.error));
                    mcview_show_error (view, err_msg);
                    g_free (err_msg);
                }

                if (view->ds_stdio_pipe != NULL)
                {
                    /* when switch from parse to raw mode and back,
                     * do not close the already closed pipe after following loop:
                     * mcview_growbuf_read_until() -> mcview_show_error() ->
                     * MSG_DRAW -> mcview_display() -> mcview_get_byte() -> mcview_growbuf_read_until()
                     */
                    mcview_growbuf_done (view);
                }
                mcview_display (view);
                return;
            }
        }
        else
        {
#ifdef HAVE_ASSERT_H
            assert (view->datasource == DS_VFS_PIPE);
#endif
            do
            {
                nread = mc_read (view->ds_vfs_pipe, p, bytesfree);
            }
            while (nread == -1 && errno == EINTR);

            if (nread <= 0)
            {
                mcview_growbuf_done (view);
                return;
            }
        }
        short_read = ((size_t) nread < bytesfree);
        view->growbuf_lastindex += nread;
    }
}