mirror of
https://github.com/MidnightCommander/mc
synced 2025-01-03 10:04:32 +03:00
Merge branch 'mc-4.6'
* mc-4.6: (38 commits) mhl: mhl_shell_unescape_buf(): fixed memory array OOB. completion: fixed complete already escaped secuences. completion: added changelog entry for solved #147 completion: fixed completion of escaped commands in commandline Removed unused char*. mhl: added mhl_strmove() function (memmove semantics) completion: added escapes in command line on completion complete: cleanup: #define to enum INPUT_COMPLETION_FLAGS added a new parameter for completion flags to input_new fish: cleanup: unboxed quoted strings when generate shell commands introduced new type SHELL_ESCAPED_STR for more type safety added mhl/types.h which defines bool enum, escape.h now using this type Removed unused variable Changes for use MHL. Fixed bug with renamig/copying files with backshashes in names Remove some testing stuff Temporarry commit. Fixed completion in browse by directoryes. Fixed some memory leaks. Add $ and ` for escaping and reorder it according to the ascii values Rewrite it to use g_string_append_c instead of some homebrew stuff ...
This commit is contained in:
commit
df4129517b
13
ChangeLog
13
ChangeLog
@ -1,3 +1,11 @@
|
||||
2009-01-31 Enrico Weigelt, metux ITS <weigelt@metux.de>, Patrick Winnertz <winnie@debian.org>, Slava Zanko <slavazanko@gmail.com>, Sergei Trofimovich <slyfox@inbox.ru>
|
||||
|
||||
* edit/editcmd.c, mhl/escape.h, mhl/string.h, mhl/types.h, src/Makefile.am,
|
||||
* src/boxes.c, src/command.c, src/complete.c, src/complete.h, src/file.c,
|
||||
* src/find.c, src/main.c, src/panelize.c, src/util.c, src/utilunix.c,
|
||||
* src/widget.c, src/widget.h, src/wtools.c, vfs/fish.c:
|
||||
fixed shell escaping issues in commandline completion engine
|
||||
|
||||
2009-01-31 Enrico Weigelt, metux ITS <weigelt@metux.de>
|
||||
|
||||
* replaced buggy concat_dir_and_file() by mhl_str_dir_plus_file() (in mhl/string.h)
|
||||
@ -17,6 +25,11 @@
|
||||
This solves "strange" rename cases, when copying/moving is performed into
|
||||
deleted directory.
|
||||
|
||||
2009-01-27 Enrico Weigelt, metux ITS <weigelt@metux.de>
|
||||
|
||||
* mhl/escape.h, src/complete.c, vfs/fish.c: introduced new type
|
||||
SHELL_ESCAPED_STR for more type safety
|
||||
|
||||
2009-01-27 Enrico Weigelt, metux IT service <weigelt@metux.de>
|
||||
|
||||
* mhl/escape.h, mhl/string.h: fixed comments to use /* ... */
|
||||
|
@ -626,7 +626,7 @@ edit_raw_key_query (const char *heading, const char *query, int cancel)
|
||||
NULL, heading,
|
||||
DLG_CENTER | DLG_TRYUP | DLG_WANT_TAB);
|
||||
add_widget (raw_dlg,
|
||||
input_new (3 - cancel, w - 5, INPUT_COLOR, 2, "", 0));
|
||||
input_new (3 - cancel, w - 5, INPUT_COLOR, 2, "", 0, INPUT_COMPLETE_DEFAULT));
|
||||
add_widget (raw_dlg, label_new (3 - cancel, 2, query));
|
||||
if (cancel)
|
||||
add_widget (raw_dlg,
|
||||
|
49
mhl/escape.h
49
mhl/escape.h
@ -6,6 +6,8 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <mhl/types.h>
|
||||
|
||||
#define mhl_shell_escape_toesc(x) \
|
||||
(((x)==' ')||((x)=='!')||((x)=='#')||((x)=='$')||((x)=='%')|| \
|
||||
((x)=='(')||((x)==')')||((x)=='\'')||((x)=='&')||((x)=='~')|| \
|
||||
@ -16,10 +18,21 @@
|
||||
#define mhl_shell_escape_nottoesc(x) \
|
||||
(((x)!=0) && (!mhl_shell_escape_toesc((x))))
|
||||
|
||||
static inline char* mhl_shell_escape_dup(const char* src)
|
||||
/* type for escaped string - just for a bit more type safety ;-p */
|
||||
typedef struct { char* s; } SHELL_ESCAPED_STR;
|
||||
|
||||
/** To be compatible with the general posix command lines we have to escape
|
||||
strings for the command line
|
||||
|
||||
/params const char * in
|
||||
string for escaping
|
||||
/returns
|
||||
return escaped string (later need to free)
|
||||
*/
|
||||
static inline SHELL_ESCAPED_STR mhl_shell_escape_dup(const char* src)
|
||||
{
|
||||
if ((src==NULL)||(!(*src)))
|
||||
return strdup("");
|
||||
return (SHELL_ESCAPED_STR){ .s = strdup("") };
|
||||
|
||||
char* buffer = calloc(1, strlen(src)*2+2);
|
||||
char* ptr = buffer;
|
||||
@ -38,7 +51,7 @@ static inline char* mhl_shell_escape_dup(const char* src)
|
||||
|
||||
/* at this point we either have an \0 or an char to escape */
|
||||
if (!c)
|
||||
return buffer;
|
||||
return (SHELL_ESCAPED_STR){ .s = buffer };
|
||||
|
||||
*ptr = '\\';
|
||||
ptr++;
|
||||
@ -48,7 +61,14 @@ static inline char* mhl_shell_escape_dup(const char* src)
|
||||
}
|
||||
}
|
||||
|
||||
/* shell-unescape within a given buffer (writing to it!) */
|
||||
/** Unescape paths or other strings for e.g the internal cd
|
||||
shell-unescape within a given buffer (writing to it!)
|
||||
|
||||
/params const char * in
|
||||
string for unescaping
|
||||
/returns
|
||||
return unescaped string
|
||||
*/
|
||||
static inline char* mhl_shell_unescape_buf(char* text)
|
||||
{
|
||||
if (!text)
|
||||
@ -93,6 +113,8 @@ static inline char* mhl_shell_unescape_buf(char* text)
|
||||
case '`':
|
||||
case '"':
|
||||
case ';':
|
||||
case '\0': /* end of line! malformed escape string */
|
||||
goto out;
|
||||
default:
|
||||
(*writeptr) = c; writeptr++; break;
|
||||
}
|
||||
@ -104,9 +126,28 @@ static inline char* mhl_shell_unescape_buf(char* text)
|
||||
}
|
||||
readptr++;
|
||||
}
|
||||
out:
|
||||
*writeptr = 0;
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/** Check if char in pointer contain escape'd chars
|
||||
|
||||
/params const char * in
|
||||
string for checking
|
||||
/returns
|
||||
return TRUE if string contain escaped chars
|
||||
otherwise return FALSE
|
||||
*/
|
||||
static inline bool
|
||||
mhl_shell_is_char_escaped ( const char *in )
|
||||
{
|
||||
if (in == NULL || !*in || in[0] != '\\')
|
||||
return false;
|
||||
if (mhl_shell_escape_toesc(in[1]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
14
mhl/string.h
14
mhl/string.h
@ -3,6 +3,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <mhl/memory.h>
|
||||
|
||||
#define mhl_str_dup(str) ((str ? strdup(str) : strdup("")))
|
||||
@ -121,6 +122,19 @@ static inline char* mhl_str_reverse(char* ptr)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* strcpy is unsafe on overlapping memory areas, so define memmove-alike
|
||||
* string function. Has sense only when dest <= src.
|
||||
*/
|
||||
static inline char * mhl_strmove(char * dest, const char * src)
|
||||
{
|
||||
size_t n = strlen (src) + 1; /* + '\0' */
|
||||
|
||||
assert (dest<=src);
|
||||
|
||||
return memmove(dest, src, n);
|
||||
}
|
||||
|
||||
static inline char* mhl_str_dir_plus_file(const char* dirname, const char* filename)
|
||||
{
|
||||
/* make sure we have valid strings */
|
||||
|
16
mhl/types.h
Normal file
16
mhl/types.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
|
||||
Micro Helper Library: generic type declarations
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __MHL_TYPES_H
|
||||
#define __MHL_TYPES_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
false = 0,
|
||||
true = 1
|
||||
} bool;
|
||||
|
||||
#endif
|
@ -45,7 +45,7 @@ CHARSET_SRC = charsets.c charsets.h selcodepage.c selcodepage.h
|
||||
|
||||
SRCS = achown.c achown.h background.c background.h boxes.c boxes.h \
|
||||
chmod.c chmod.h chown.c chown.h cmd.c cmd.h color.c color.h \
|
||||
command.c command.h complete.c complete.h cons.handler.c \
|
||||
command.c command.h complete.c cons.handler.c \
|
||||
cons.saver.h dialog.c dialog.h dir.c dir.h \
|
||||
eregex.h execute.c execute.h ext.c ext.h file.c filegui.c \
|
||||
filegui.h file.h filenot.c fileopctx.c fileopctx.h find.c \
|
||||
|
10
src/boxes.c
10
src/boxes.c
@ -197,7 +197,7 @@ display_init (int radio_sel, char *init_text, int _check_status,
|
||||
|
||||
status =
|
||||
input_new (10, 9, INPUT_COLOR, DISPLAY_X - 14, _status[radio_sel],
|
||||
"mini-input");
|
||||
"mini-input", INPUT_COMPLETE_DEFAULT);
|
||||
add_widget (dd, status);
|
||||
input_set_point (status, 0);
|
||||
|
||||
@ -207,7 +207,7 @@ display_init (int radio_sel, char *init_text, int _check_status,
|
||||
|
||||
user =
|
||||
input_new (7, 9, INPUT_COLOR, DISPLAY_X - 14, init_text,
|
||||
"user-fmt-input");
|
||||
"user-fmt-input", INPUT_COMPLETE_DEFAULT);
|
||||
add_widget (dd, user);
|
||||
input_set_point (user, 0);
|
||||
|
||||
@ -1085,17 +1085,17 @@ vfs_smb_get_authinfo (const char *host, const char *share, const char *domain,
|
||||
|
||||
g_free (title);
|
||||
|
||||
in_user = input_new (5, istart, INPUT_COLOR, ilen, user, "auth_name");
|
||||
in_user = input_new (5, istart, INPUT_COLOR, ilen, user, "auth_name", INPUT_COMPLETE_DEFAULT);
|
||||
add_widget (auth_dlg, in_user);
|
||||
|
||||
in_domain = input_new (3, istart, INPUT_COLOR, ilen, domain, "auth_domain");
|
||||
in_domain = input_new (3, istart, INPUT_COLOR, ilen, domain, "auth_domain", INPUT_COMPLETE_DEFAULT);
|
||||
add_widget (auth_dlg, in_domain);
|
||||
add_widget (auth_dlg, button_new (9, b2, B_CANCEL, NORMAL_BUTTON,
|
||||
buts[1], 0));
|
||||
add_widget (auth_dlg, button_new (9, b0, B_ENTER, DEFPUSH_BUTTON,
|
||||
buts[0], 0));
|
||||
|
||||
in_password = input_new (7, istart, INPUT_COLOR, ilen, "", "auth_password");
|
||||
in_password = input_new (7, istart, INPUT_COLOR, ilen, "", "auth_password", INPUT_COMPLETE_DEFAULT);
|
||||
in_password->completion_flags = 0;
|
||||
in_password->is_password = 1;
|
||||
add_widget (auth_dlg, in_password);
|
||||
|
@ -27,13 +27,14 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mhl/memory.h>
|
||||
#include <mhl/escape.h>
|
||||
#include <mhl/string.h>
|
||||
|
||||
#include "global.h" /* home_dir */
|
||||
#include "tty.h"
|
||||
#include "widget.h" /* WInput */
|
||||
#include "command.h"
|
||||
#include "complete.h" /* completion constants */
|
||||
#include "wtools.h" /* message () */
|
||||
#include "panel.h" /* view_tree enum. Also, needed by main.h */
|
||||
#include "main.h" /* do_cd */
|
||||
@ -66,6 +67,7 @@ examine_cd (char *path)
|
||||
const char *t;
|
||||
|
||||
/* Tilde expansion */
|
||||
path = mhl_shell_unescape_buf(path);
|
||||
path_tilde = tilde_expand (path);
|
||||
|
||||
/* Leave space for further expansion */
|
||||
@ -137,6 +139,7 @@ examine_cd (char *path)
|
||||
}
|
||||
g_free (q);
|
||||
g_free (path_tilde);
|
||||
// mhl_mem_free(path);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -292,7 +295,8 @@ command_new (int y, int x, int cols)
|
||||
{
|
||||
WInput *cmd;
|
||||
|
||||
cmd = input_new (y, x, DEFAULT_COLOR, cols, "", "cmdline");
|
||||
cmd = input_new (y, x, DEFAULT_COLOR, cols, "", "cmdline",
|
||||
INPUT_COMPLETE_DEFAULT | INPUT_COMPLETE_CD | INPUT_COMPLETE_COMMANDS | INPUT_COMPLETE_SHELL_ESC);
|
||||
|
||||
/* Add our hooks */
|
||||
cmd->widget.callback = command_callback;
|
||||
|
222
src/complete.c
222
src/complete.c
@ -30,6 +30,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mhl/memory.h>
|
||||
#include <mhl/escape.h>
|
||||
#include <mhl/string.h>
|
||||
|
||||
#include "global.h"
|
||||
@ -39,21 +41,38 @@
|
||||
#include "dialog.h"
|
||||
#include "widget.h"
|
||||
#include "wtools.h"
|
||||
#include "complete.h"
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
#include "key.h" /* XCTRL and ALT macros */
|
||||
|
||||
typedef char *CompletionFunction (char *, int);
|
||||
typedef char *CompletionFunction (char * text, int state, INPUT_COMPLETE_FLAGS flags);
|
||||
|
||||
/* This flag is used in filename_completion_function */
|
||||
static int ignore_filenames = 0;
|
||||
//#define DO_COMPLETION_DEBUG
|
||||
#ifdef DO_COMPLETION_DEBUG
|
||||
/*
|
||||
* Useful to print/debug completion flags
|
||||
*/
|
||||
static const char * show_c_flags(INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
static char s_cf[] = "FHCVUDS";
|
||||
|
||||
/* This flag is used by command_completion_function */
|
||||
/* to hint the filename_completion_function */
|
||||
static int look_for_executables = 0;
|
||||
s_cf[0] = (flags & INPUT_COMPLETE_FILENAMES) ? 'F' : ' ';
|
||||
s_cf[1] = (flags & INPUT_COMPLETE_HOSTNAMES) ? 'H' : ' ';
|
||||
s_cf[2] = (flags & INPUT_COMPLETE_COMMANDS) ? 'C' : ' ';
|
||||
s_cf[3] = (flags & INPUT_COMPLETE_VARIABLES) ? 'V' : ' ';
|
||||
s_cf[4] = (flags & INPUT_COMPLETE_USERNAMES) ? 'U' : ' ';
|
||||
s_cf[5] = (flags & INPUT_COMPLETE_CD) ? 'D' : ' ';
|
||||
s_cf[6] = (flags & INPUT_COMPLETE_SHELL_ESC) ? 'S' : ' ';
|
||||
|
||||
return s_cf;
|
||||
}
|
||||
#define SHOW_C_CTX(func) fprintf(stderr, "%s: text='%s' flags=%s\n", func, text, show_c_flags(flags))
|
||||
#else
|
||||
#define SHOW_C_CTX(func)
|
||||
#endif /* DO_CMPLETION_DEBUG */
|
||||
|
||||
static char *
|
||||
filename_completion_function (char *text, int state)
|
||||
filename_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
static DIR *directory;
|
||||
static char *filename = NULL;
|
||||
@ -64,6 +83,11 @@ filename_completion_function (char *text, int state)
|
||||
|
||||
struct dirent *entry = NULL;
|
||||
|
||||
SHOW_C_CTX("filename_completion_function");
|
||||
|
||||
if (text && (flags & INPUT_COMPLETE_SHELL_ESC))
|
||||
text = mhl_shell_unescape_buf (text);
|
||||
|
||||
/* If we're starting the match process, initialize us a bit. */
|
||||
if (!state){
|
||||
const char *temp;
|
||||
@ -85,6 +109,7 @@ filename_completion_function (char *text, int state)
|
||||
/* Save the version of the directory that the user typed. */
|
||||
users_dirname = dirname;
|
||||
{
|
||||
// FIXME: memleak ?
|
||||
dirname = tilde_expand (dirname);
|
||||
canonicalize_pathname (dirname);
|
||||
/* Here we should do something with variable expansion
|
||||
@ -136,18 +161,15 @@ filename_completion_function (char *text, int state)
|
||||
}
|
||||
g_free (tmp);
|
||||
}
|
||||
switch (look_for_executables)
|
||||
{
|
||||
case 2: if (!isexec)
|
||||
continue;
|
||||
break;
|
||||
case 1: if (!isexec && !isdir)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (ignore_filenames && !isdir)
|
||||
continue;
|
||||
break;
|
||||
if ((flags & INPUT_COMPLETE_COMMANDS)
|
||||
&& (isexec || isdir))
|
||||
break;
|
||||
if ((flags & INPUT_COMPLETE_CD)
|
||||
&& isdir)
|
||||
break;
|
||||
if (flags & (INPUT_COMPLETE_FILENAMES))
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!entry){
|
||||
@ -181,18 +203,28 @@ filename_completion_function (char *text, int state)
|
||||
}
|
||||
if (isdir)
|
||||
strcat (temp, PATH_SEP_STR);
|
||||
return temp;
|
||||
|
||||
if (temp && (flags & INPUT_COMPLETE_SHELL_ESC))
|
||||
{
|
||||
SHELL_ESCAPED_STR e_temp = mhl_shell_escape_dup(temp);
|
||||
mhl_mem_free (temp);
|
||||
temp = e_temp.s;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* We assume here that text[0] == '~' , if you want to call it in another way,
|
||||
you have to change the code */
|
||||
static char *
|
||||
username_completion_function (char *text, int state)
|
||||
username_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
static struct passwd *entry;
|
||||
static int userlen;
|
||||
|
||||
SHOW_C_CTX("username_completion_function");
|
||||
|
||||
if (text[0] == '\\' && text[1] == '~') text++;
|
||||
if (!state){ /* Initialization stuff */
|
||||
setpwent ();
|
||||
userlen = strlen (text + 1);
|
||||
@ -227,12 +259,14 @@ extern char **environ;
|
||||
/* We assume text [0] == '$' and want to have a look at text [1], if it is
|
||||
equal to '{', so that we should append '}' at the end */
|
||||
static char *
|
||||
variable_completion_function (char *text, int state)
|
||||
variable_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
static char **env_p;
|
||||
static int varlen, isbrace;
|
||||
const char *p = NULL;
|
||||
|
||||
SHOW_C_CTX("variable_completion_function");
|
||||
|
||||
if (!state){ /* Initialization stuff */
|
||||
isbrace = (text [1] == '{');
|
||||
varlen = strlen (text + 1 + isbrace);
|
||||
@ -342,11 +376,13 @@ static void fetch_hosts (const char *filename)
|
||||
}
|
||||
|
||||
static char *
|
||||
hostname_completion_function (char *text, int state)
|
||||
hostname_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
static char **host_p;
|
||||
static int textstart, textlen;
|
||||
|
||||
SHOW_C_CTX("hostname_completion_function");
|
||||
|
||||
if (!state){ /* Initialization stuff */
|
||||
const char *p;
|
||||
|
||||
@ -396,7 +432,7 @@ hostname_completion_function (char *text, int state)
|
||||
* table of shell built-ins.
|
||||
*/
|
||||
static char *
|
||||
command_completion_function (char *text, int state)
|
||||
command_completion_function (char *text, int state, INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
static const char *path_end;
|
||||
static int isabsolute;
|
||||
@ -422,9 +458,16 @@ command_completion_function (char *text, int state)
|
||||
};
|
||||
char *p, *found;
|
||||
|
||||
SHOW_C_CTX("command_completion_function");
|
||||
|
||||
if (!(flags & INPUT_COMPLETE_COMMANDS))
|
||||
return 0;
|
||||
|
||||
text = mhl_shell_unescape_buf(text);
|
||||
flags &= ~INPUT_COMPLETE_SHELL_ESC;
|
||||
|
||||
if (!state) { /* Initialize us a little bit */
|
||||
isabsolute = strchr (text, PATH_SEP) != 0;
|
||||
look_for_executables = isabsolute ? 1 : 2;
|
||||
if (!isabsolute) {
|
||||
words = bash_reserved;
|
||||
phase = 0;
|
||||
@ -440,10 +483,12 @@ command_completion_function (char *text, int state)
|
||||
}
|
||||
|
||||
if (isabsolute) {
|
||||
p = filename_completion_function (text, state);
|
||||
p = filename_completion_function (text, state, flags);
|
||||
if (!p)
|
||||
look_for_executables = 0;
|
||||
return p;
|
||||
return 0;
|
||||
SHELL_ESCAPED_STR e_p = mhl_shell_escape_dup(p);
|
||||
mhl_mem_free(p);
|
||||
return e_p.s;
|
||||
}
|
||||
|
||||
found = NULL;
|
||||
@ -483,7 +528,7 @@ command_completion_function (char *text, int state)
|
||||
}
|
||||
found =
|
||||
filename_completion_function (cur_word,
|
||||
state - init_state);
|
||||
state - init_state, flags);
|
||||
if (!found) {
|
||||
g_free (cur_word);
|
||||
cur_word = NULL;
|
||||
@ -492,16 +537,16 @@ command_completion_function (char *text, int state)
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
look_for_executables = 0;
|
||||
g_free (path);
|
||||
path = NULL;
|
||||
return NULL;
|
||||
}
|
||||
if ((p = strrchr (found, PATH_SEP)) != NULL) {
|
||||
p++;
|
||||
p = g_strdup (p);
|
||||
g_free (found);
|
||||
return p;
|
||||
|
||||
SHELL_ESCAPED_STR e_p = mhl_shell_escape_dup(p);
|
||||
mhl_mem_free(found);
|
||||
return e_p.s;
|
||||
}
|
||||
return found;
|
||||
|
||||
@ -521,7 +566,7 @@ match_compare (const void *a, const void *b)
|
||||
as the second.
|
||||
In case no matches were found we return NULL. */
|
||||
static char **
|
||||
completion_matches (char *text, CompletionFunction entry_function)
|
||||
completion_matches (char *text, CompletionFunction entry_function, INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
/* Number of slots in match_list. */
|
||||
int match_list_size;
|
||||
@ -537,7 +582,7 @@ completion_matches (char *text, CompletionFunction entry_function)
|
||||
|
||||
match_list[1] = NULL;
|
||||
|
||||
while ((string = (*entry_function) (text, matches)) != NULL){
|
||||
while ((string = (*entry_function) (text, matches, flags)) != NULL){
|
||||
if (matches + 1 == match_list_size)
|
||||
match_list = (char **) g_realloc (match_list, ((match_list_size += 30) + 1) * sizeof (char *));
|
||||
match_list[++matches] = string;
|
||||
@ -597,14 +642,12 @@ completion_matches (char *text, CompletionFunction entry_function)
|
||||
|
||||
/* Check if directory completion is needed */
|
||||
static int
|
||||
check_is_cd (const char *text, int start, int flags)
|
||||
check_is_cd (const char *text, int start, INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
const char *p, *q;
|
||||
|
||||
if (flags & INPUT_COMPLETE_CD)
|
||||
return 1;
|
||||
|
||||
if (!(flags & INPUT_COMPLETE_COMMANDS))
|
||||
SHOW_C_CTX("check_is_cd");
|
||||
if (!(flags & INPUT_COMPLETE_CD))
|
||||
return 0;
|
||||
|
||||
/* Skip initial spaces */
|
||||
@ -623,16 +666,17 @@ check_is_cd (const char *text, int start, int flags)
|
||||
|
||||
/* Returns an array of matches, or NULL if none. */
|
||||
static char **
|
||||
try_complete (char *text, int *start, int *end, int flags)
|
||||
try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
|
||||
{
|
||||
int in_command_position = 0, i;
|
||||
int in_command_position = 0;
|
||||
char *word, c;
|
||||
char **matches = NULL;
|
||||
const char *command_separator_chars = ";|&{(`";
|
||||
char *p = NULL, *q = NULL, *r = NULL;
|
||||
int is_cd = check_is_cd (text, *start, flags);
|
||||
|
||||
ignore_filenames = 0;
|
||||
SHOW_C_CTX("try_complete");
|
||||
|
||||
c = text [*end];
|
||||
text [*end] = 0;
|
||||
word = g_strdup (text + *start);
|
||||
@ -643,9 +687,16 @@ try_complete (char *text, int *start, int *end, int flags)
|
||||
appears after a character that separates commands. And we have to
|
||||
be in a INPUT_COMPLETE_COMMANDS flagged Input line. */
|
||||
if (!is_cd && (flags & INPUT_COMPLETE_COMMANDS)){
|
||||
i = *start - 1;
|
||||
while (i > -1 && (text[i] == ' ' || text[i] == '\t'))
|
||||
i--;
|
||||
int i = *start - 1;
|
||||
for (i = *start - 1; i > -1; i--) {
|
||||
if (text[i] == ' ' || text[i] == '\t'){
|
||||
if (i == 0 ) continue;
|
||||
if (text[i-1] != '\\') {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i < 0)
|
||||
in_command_position++;
|
||||
else if (strchr (command_separator_chars, text[i])){
|
||||
@ -679,17 +730,19 @@ try_complete (char *text, int *start, int *end, int flags)
|
||||
p = q + 1;
|
||||
q = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Command substitution? */
|
||||
if (p > q && p > r){
|
||||
matches = completion_matches (p + 1, command_completion_function);
|
||||
SHOW_C_CTX("try_complete:cmd_backq_subst");
|
||||
matches = completion_matches (p + 1, command_completion_function, flags & (~INPUT_COMPLETE_FILENAMES));
|
||||
if (matches)
|
||||
*start += p + 1 - word;
|
||||
}
|
||||
|
||||
/* Variable name? */
|
||||
else if (q > p && q > r){
|
||||
matches = completion_matches (q, variable_completion_function);
|
||||
SHOW_C_CTX("try_complete:var_subst");
|
||||
matches = completion_matches (q, variable_completion_function, flags);
|
||||
if (matches)
|
||||
*start += q - word;
|
||||
}
|
||||
@ -697,7 +750,8 @@ try_complete (char *text, int *start, int *end, int flags)
|
||||
/* Starts with '@', then look through the known hostnames for
|
||||
completion first. */
|
||||
else if (r > p && r > q){
|
||||
matches = completion_matches (r, hostname_completion_function);
|
||||
SHOW_C_CTX("try_complete:host_subst");
|
||||
matches = completion_matches (r, hostname_completion_function, flags);
|
||||
if (matches)
|
||||
*start += r - word;
|
||||
}
|
||||
@ -705,26 +759,46 @@ try_complete (char *text, int *start, int *end, int flags)
|
||||
/* Starts with `~' and there is no slash in the word, then
|
||||
try completing this word as a username. */
|
||||
if (!matches && *word == '~' && (flags & INPUT_COMPLETE_USERNAMES) && !strchr (word, PATH_SEP))
|
||||
matches = completion_matches (word, username_completion_function);
|
||||
{
|
||||
SHOW_C_CTX("try_complete:user_subst");
|
||||
matches = completion_matches (word, username_completion_function, flags);
|
||||
}
|
||||
|
||||
|
||||
/* And finally if this word is in a command position, then
|
||||
complete over possible command names, including aliases, functions,
|
||||
and command names. */
|
||||
if (!matches && in_command_position)
|
||||
matches = completion_matches (word, command_completion_function);
|
||||
{
|
||||
SHOW_C_CTX("try_complete:cmd_subst");
|
||||
matches = completion_matches (word, command_completion_function, flags & (~INPUT_COMPLETE_FILENAMES));
|
||||
}
|
||||
|
||||
else if (!matches && (flags & INPUT_COMPLETE_FILENAMES)){
|
||||
if (is_cd)
|
||||
ignore_filenames = 1;
|
||||
matches = completion_matches (word, filename_completion_function);
|
||||
ignore_filenames = 0;
|
||||
if (is_cd)
|
||||
flags &= ~(INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS);
|
||||
SHOW_C_CTX("try_complete:filename_subst_1");
|
||||
matches = completion_matches (word, filename_completion_function, flags);
|
||||
if (!matches && is_cd && *word != PATH_SEP && *word != '~'){
|
||||
char *p, *q = text + *start;
|
||||
|
||||
for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); p++);
|
||||
|
||||
for (p = text; *p && p < q; p++){
|
||||
if (*p == ' ' || *p == '\t') {
|
||||
if (p == text) continue;
|
||||
if (*(p-1) == '\\') {
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!strncmp (p, "cd", 2))
|
||||
for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); p++);
|
||||
for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); p++){
|
||||
if (p == text) continue;
|
||||
if (*(p-1) == '\\') {
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p == q){
|
||||
char * const cdpath_ref = g_strdup (getenv ("CDPATH"));
|
||||
char *cdpath = cdpath_ref;
|
||||
@ -742,10 +816,9 @@ try_complete (char *text, int *start, int *end, int flags)
|
||||
*s = 0;
|
||||
if (*cdpath){
|
||||
r = mhl_str_dir_plus_file (cdpath, word);
|
||||
ignore_filenames = 1;
|
||||
matches = completion_matches (r, filename_completion_function);
|
||||
ignore_filenames = 0;
|
||||
g_free (r);
|
||||
SHOW_C_CTX("try_complete:filename_subst_2");
|
||||
matches = completion_matches (r, filename_completion_function, flags);
|
||||
g_free (r);
|
||||
}
|
||||
*s = c;
|
||||
cdpath = s + 1;
|
||||
@ -917,15 +990,21 @@ complete_engine (WInput *in, int what_to_do)
|
||||
if (!in->completions){
|
||||
end = in->point;
|
||||
for (start = end ? end - 1 : 0; start > -1; start--)
|
||||
if (strchr (" \t;|<>", in->buffer [start]))
|
||||
break;
|
||||
if (strchr (" \t;|<>", in->buffer [start])){
|
||||
if (start > 0 && in->buffer [start-1] == '\\')
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (start < end)
|
||||
start++;
|
||||
in->completions = try_complete (in->buffer, &start, &end, in->completion_flags);
|
||||
}
|
||||
|
||||
if (in->completions){
|
||||
if (what_to_do & DO_INSERTION || ((what_to_do & DO_QUERY) && !in->completions[1])) {
|
||||
if (insert_text (in, in->completions [0], strlen (in->completions [0]))){
|
||||
char * complete = in->completions [0];
|
||||
if (insert_text (in, complete, strlen (complete))){
|
||||
if (in->completions [1])
|
||||
beep ();
|
||||
else
|
||||
@ -940,10 +1019,11 @@ complete_engine (WInput *in, int what_to_do)
|
||||
char **p, *q;
|
||||
Dlg_head *query_dlg;
|
||||
WListbox *query_list;
|
||||
|
||||
for (p=in->completions + 1; *p; count++, p++)
|
||||
if ((i = strlen (*p)) > maxlen)
|
||||
maxlen = i;
|
||||
|
||||
for (p=in->completions + 1; *p; count++, p++) {
|
||||
if ((i = strlen (*p)) > maxlen)
|
||||
maxlen = i;
|
||||
}
|
||||
start_x = in->widget.x;
|
||||
start_y = in->widget.y;
|
||||
if (start_y - 2 >= count) {
|
||||
|
@ -1,16 +0,0 @@
|
||||
#ifndef MC_COMPLETE_H
|
||||
#define MC_COMPLETE_H
|
||||
|
||||
#define INPUT_COMPLETE_FILENAMES 1
|
||||
#define INPUT_COMPLETE_HOSTNAMES 2
|
||||
#define INPUT_COMPLETE_COMMANDS 4
|
||||
#define INPUT_COMPLETE_VARIABLES 8
|
||||
#define INPUT_COMPLETE_USERNAMES 16
|
||||
#define INPUT_COMPLETE_CD 32
|
||||
|
||||
#include "widget.h"
|
||||
|
||||
void free_completions (WInput *);
|
||||
void complete (WInput *);
|
||||
|
||||
#endif
|
74
src/file.c
74
src/file.c
@ -50,6 +50,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mhl/memory.h>
|
||||
#include <mhl/escape.h>
|
||||
#include <mhl/string.h>
|
||||
|
||||
#include "global.h"
|
||||
@ -65,6 +67,7 @@
|
||||
#include "widget.h"
|
||||
#include "wtools.h"
|
||||
#include "background.h" /* we_are_background */
|
||||
#include "util.h"
|
||||
|
||||
/* Needed for current_panel, other_panel and WTree */
|
||||
#include "dir.h"
|
||||
@ -178,37 +181,43 @@ do_transform_source (FileOpContext *ctx, const char *source)
|
||||
for (next_reg = 1, j = 0, k = 0; j < strlen (ctx->dest_mask); j++) {
|
||||
switch (ctx->dest_mask[j]) {
|
||||
case '\\':
|
||||
j++;
|
||||
if (!isdigit ((unsigned char) ctx->dest_mask[j])) {
|
||||
/* Backslash followed by non-digit */
|
||||
switch (ctx->dest_mask[j]) {
|
||||
case 'U':
|
||||
case_conv |= UP_SECT;
|
||||
case_conv &= ~LOW_SECT;
|
||||
break;
|
||||
case 'u':
|
||||
case_conv |= UP_CHAR;
|
||||
break;
|
||||
case 'L':
|
||||
case_conv |= LOW_SECT;
|
||||
case_conv &= ~UP_SECT;
|
||||
break;
|
||||
case 'l':
|
||||
case_conv |= LOW_CHAR;
|
||||
break;
|
||||
case 'E':
|
||||
case_conv = NO_CONV;
|
||||
break;
|
||||
default:
|
||||
/* Backslash as quote mark */
|
||||
fntarget[k++] =
|
||||
convert_case (ctx->dest_mask[j], &case_conv);
|
||||
}
|
||||
if (mhl_shell_is_char_escaped (&ctx->dest_mask[j])){
|
||||
fntarget[k++] = ctx->dest_mask[j++];
|
||||
fntarget[k++] = ctx->dest_mask[j];
|
||||
break;
|
||||
} else {
|
||||
/* Backslash followed by digit */
|
||||
next_reg = ctx->dest_mask[j] - '0';
|
||||
/* Fall through */
|
||||
j++;
|
||||
if (!isdigit ((unsigned char) ctx->dest_mask[j])) {
|
||||
/* Backslash followed by non-digit */
|
||||
switch (ctx->dest_mask[j]) {
|
||||
case 'U':
|
||||
case_conv |= UP_SECT;
|
||||
case_conv &= ~LOW_SECT;
|
||||
break;
|
||||
case 'u':
|
||||
case_conv |= UP_CHAR;
|
||||
break;
|
||||
case 'L':
|
||||
case_conv |= LOW_SECT;
|
||||
case_conv &= ~UP_SECT;
|
||||
break;
|
||||
case 'l':
|
||||
case_conv |= LOW_CHAR;
|
||||
break;
|
||||
case 'E':
|
||||
case_conv = NO_CONV;
|
||||
break;
|
||||
default:
|
||||
/* Backslash as quote mark */
|
||||
fntarget[k++] =
|
||||
convert_case (ctx->dest_mask[j], &case_conv);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
/* Backslash followed by digit */
|
||||
next_reg = ctx->dest_mask[j] - '0';
|
||||
/* Fall through */
|
||||
}
|
||||
}
|
||||
|
||||
case '*':
|
||||
@ -793,7 +802,7 @@ copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path,
|
||||
}
|
||||
}
|
||||
|
||||
if (!appending) {
|
||||
if (!appending && ctx->preserve) {
|
||||
while (mc_chmod (dst_path, (src_mode & ctx->umask_kill))) {
|
||||
temp_status = file_error (
|
||||
_(" Cannot chmod target file \"%s\" \n %s "), dst_path);
|
||||
@ -1896,7 +1905,7 @@ panel_operate (void *source_panel, FileOperation operation,
|
||||
g_free (dest);
|
||||
dest = temp2;
|
||||
temp = NULL;
|
||||
|
||||
|
||||
switch (operation) {
|
||||
case OP_COPY:
|
||||
/*
|
||||
@ -1988,6 +1997,9 @@ panel_operate (void *source_panel, FileOperation operation,
|
||||
else {
|
||||
char *temp2 = mhl_str_dir_plus_file (dest, temp);
|
||||
|
||||
source_with_path = mhl_shell_unescape_buf(source_with_path);
|
||||
temp2 = mhl_shell_unescape_buf(temp2);
|
||||
|
||||
switch (operation) {
|
||||
case OP_COPY:
|
||||
/*
|
||||
|
@ -276,16 +276,16 @@ find_parameters (char **start_dir, char **pattern, char **content)
|
||||
add_widget (find_dlg, case_sense);
|
||||
|
||||
in_with =
|
||||
input_new (8, istart, INPUT_COLOR, ilen, in_contents, "content");
|
||||
input_new (8, istart, INPUT_COLOR, ilen, in_contents, "content", INPUT_COMPLETE_DEFAULT);
|
||||
add_widget (find_dlg, in_with);
|
||||
|
||||
add_widget (find_dlg, recursively_cbox);
|
||||
in_name =
|
||||
input_new (5, istart, INPUT_COLOR, ilen, in_start_name, "name");
|
||||
input_new (5, istart, INPUT_COLOR, ilen, in_start_name, "name", INPUT_COMPLETE_DEFAULT);
|
||||
add_widget (find_dlg, in_name);
|
||||
|
||||
in_start =
|
||||
input_new (3, istart, INPUT_COLOR, ilen, in_start_dir, "start");
|
||||
input_new (3, istart, INPUT_COLOR, ilen, in_start_dir, "start", INPUT_COMPLETE_DEFAULT);
|
||||
add_widget (find_dlg, in_start);
|
||||
|
||||
add_widget (find_dlg, label_new (8, 3, labs[2]));
|
||||
|
@ -67,7 +67,6 @@
|
||||
#include "widget.h"
|
||||
#include "command.h"
|
||||
#include "wtools.h"
|
||||
#include "complete.h" /* For the free_completion */
|
||||
|
||||
#include "chmod.h"
|
||||
#include "chown.h"
|
||||
|
@ -165,7 +165,7 @@ init_panelize (void)
|
||||
|
||||
pname =
|
||||
input_new (UY + 14, UX, INPUT_COLOR, panelize_dlg->cols - 10, "",
|
||||
"in");
|
||||
"in", INPUT_COMPLETE_DEFAULT);
|
||||
add_widget (panelize_dlg, pname);
|
||||
|
||||
add_widget (panelize_dlg, label_new (UY + 13, UX, _("Command")));
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mhl/escape.h>
|
||||
#include <mhl/string.h>
|
||||
|
||||
#include "global.h"
|
||||
@ -1516,4 +1517,3 @@ Q_ (const char *s)
|
||||
sep = strchr(result, '|');
|
||||
return (sep != NULL) ? sep + 1 : result;
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,8 @@
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mhl/string.h>
|
||||
|
||||
#include "global.h"
|
||||
#include "execute.h"
|
||||
#include "wtools.h" /* message() */
|
||||
@ -426,7 +428,7 @@ canonicalize_pathname (char *path)
|
||||
if (p[0] == PATH_SEP && p[1] == PATH_SEP) {
|
||||
s = p + 1;
|
||||
while (*(++s) == PATH_SEP);
|
||||
strcpy (p + 1, s);
|
||||
mhl_strmove (p + 1, s);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
@ -435,7 +437,7 @@ canonicalize_pathname (char *path)
|
||||
p = lpath;
|
||||
while (*p) {
|
||||
if (p[0] == PATH_SEP && p[1] == '.' && p[2] == PATH_SEP)
|
||||
strcpy (p, p + 2);
|
||||
mhl_strmove (p, p + 2);
|
||||
else
|
||||
p++;
|
||||
}
|
||||
@ -451,7 +453,7 @@ canonicalize_pathname (char *path)
|
||||
lpath[1] = 0;
|
||||
return;
|
||||
} else {
|
||||
strcpy (lpath, lpath + 2);
|
||||
mhl_strmove (lpath, lpath + 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,10 +499,10 @@ canonicalize_pathname (char *path)
|
||||
if (p[3] != 0) {
|
||||
if (s == lpath && *s == PATH_SEP) {
|
||||
/* "/../foo" -> "/foo" */
|
||||
strcpy (s + 1, p + 4);
|
||||
mhl_strmove (s + 1, p + 4);
|
||||
} else {
|
||||
/* "token/../foo" -> "foo" */
|
||||
strcpy (s, p + 4);
|
||||
mhl_strmove (s, p + 4);
|
||||
}
|
||||
p = (s > lpath) ? s - 1 : s;
|
||||
continue;
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "dialog.h"
|
||||
#include "widget.h"
|
||||
#include "win.h"
|
||||
#include "complete.h"
|
||||
#include "key.h" /* XCTRL and ALT macros */
|
||||
#include "profile.h" /* for history loading and saving */
|
||||
#include "wtools.h" /* For common_dialog_repaint() */
|
||||
@ -1660,7 +1659,7 @@ input_event (Gpm_Event * event, void *data)
|
||||
|
||||
WInput *
|
||||
input_new (int y, int x, int color, int len, const char *def_text,
|
||||
const char *histname)
|
||||
const char *histname, INPUT_COMPLETE_FLAGS completion_flags)
|
||||
{
|
||||
WInput *in = g_new (WInput, 1);
|
||||
int initial_buffer_len;
|
||||
@ -1689,9 +1688,7 @@ input_new (int y, int x, int color, int len, const char *def_text,
|
||||
initial_buffer_len = 1 + max ((size_t) len, strlen (def_text));
|
||||
in->widget.options |= W_IS_INPUT;
|
||||
in->completions = NULL;
|
||||
in->completion_flags =
|
||||
INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_HOSTNAMES |
|
||||
INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES;
|
||||
in->completion_flags = completion_flags;
|
||||
in->current_max_len = initial_buffer_len;
|
||||
in->buffer = g_malloc (initial_buffer_len);
|
||||
in->color = color;
|
||||
|
25
src/widget.h
25
src/widget.h
@ -3,6 +3,23 @@
|
||||
|
||||
#include "dialog.h" /* Widget */
|
||||
|
||||
/* Completion stuff */
|
||||
|
||||
typedef enum {
|
||||
INPUT_COMPLETE_FILENAMES = 1<<0,
|
||||
INPUT_COMPLETE_HOSTNAMES = 1<<1,
|
||||
INPUT_COMPLETE_COMMANDS = 1<<2,
|
||||
INPUT_COMPLETE_VARIABLES = 1<<3,
|
||||
INPUT_COMPLETE_USERNAMES = 1<<4,
|
||||
INPUT_COMPLETE_CD = 1<<5,
|
||||
INPUT_COMPLETE_SHELL_ESC = 1<<6,
|
||||
|
||||
INPUT_COMPLETE_DEFAULT = INPUT_COMPLETE_FILENAMES
|
||||
| INPUT_COMPLETE_HOSTNAMES
|
||||
| INPUT_COMPLETE_VARIABLES
|
||||
| INPUT_COMPLETE_USERNAMES
|
||||
} INPUT_COMPLETE_FLAGS;
|
||||
|
||||
/* Please note that the first element in all the widgets is a */
|
||||
/* widget variable of type Widget. We abuse this fact everywhere */
|
||||
|
||||
@ -70,7 +87,7 @@ typedef struct {
|
||||
GList *history; /* The history */
|
||||
int need_push; /* need to push the current Input on hist? */
|
||||
char **completions; /* Possible completions array */
|
||||
int completion_flags; /* INPUT_COMPLETE* bitwise flags(complete.h) */
|
||||
INPUT_COMPLETE_FLAGS completion_flags; /* INPUT_COMPLETE* bitwise flags(complete.h) */
|
||||
char *history_name; /* name of history for loading and saving */
|
||||
} WInput;
|
||||
|
||||
@ -122,12 +139,13 @@ typedef struct WGroupbox {
|
||||
char *title;
|
||||
} WGroupbox;
|
||||
|
||||
|
||||
/* Constructors */
|
||||
WButton *button_new (int y, int x, int action, int flags, const char *text,
|
||||
bcback callback);
|
||||
WRadio *radio_new (int y, int x, int count, const char **text);
|
||||
WCheck *check_new (int y, int x, int state, const char *text);
|
||||
WInput *input_new (int y, int x, int color, int len, const char *text, const char *histname);
|
||||
WInput *input_new (int y, int x, int color, int len, const char *text, const char *histname, INPUT_COMPLETE_FLAGS completion_flags);
|
||||
WLabel *label_new (int y, int x, const char *text);
|
||||
WGauge *gauge_new (int y, int x, int shown, int max, int current);
|
||||
WListbox *listbox_new (int x, int y, int width, int height, lcback callback);
|
||||
@ -200,4 +218,7 @@ void buttonbar_set_label_data (Dlg_head *h, int idx, const char *text,
|
||||
void buttonbar_set_visible (WButtonBar *, gboolean);
|
||||
void buttonbar_redraw (Dlg_head *h);
|
||||
|
||||
void free_completions (WInput *);
|
||||
void complete (WInput *);
|
||||
|
||||
#endif
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "widget.h"
|
||||
#include "wtools.h"
|
||||
#include "key.h" /* mi_getch() */
|
||||
#include "complete.h" /* INPUT_COMPLETE_CD */
|
||||
#include "background.h" /* parent_call */
|
||||
|
||||
|
||||
@ -361,7 +360,7 @@ quick_dialog_skip (QuickDialog *qd, int nskip)
|
||||
case quick_input:
|
||||
input =
|
||||
input_new (ypos, xpos, INPUT_COLOR, qw->hotkey_pos,
|
||||
qw->text, qw->histname);
|
||||
qw->text, qw->histname, INPUT_COMPLETE_DEFAULT);
|
||||
input->is_password = qw->value == 1;
|
||||
input->point = 0;
|
||||
if (qw->value & 2)
|
||||
|
107
vfs/fish.c
107
vfs/fish.c
@ -144,7 +144,7 @@ fish_command (struct vfs_class *me, struct vfs_s_super *super,
|
||||
enable_interrupt_key ();
|
||||
|
||||
status = write (SUP.sockw, str, strlen (str));
|
||||
g_free (str);
|
||||
mhl_mem_free (str);
|
||||
|
||||
disable_interrupt_key ();
|
||||
if (status < 0)
|
||||
@ -168,10 +168,10 @@ fish_free_archive (struct vfs_class *me, struct vfs_s_super *super)
|
||||
close (SUP.sockr);
|
||||
SUP.sockw = SUP.sockr = -1;
|
||||
}
|
||||
g_free (SUP.host);
|
||||
g_free (SUP.user);
|
||||
g_free (SUP.cwdir);
|
||||
g_free (SUP.password);
|
||||
mhl_mem_free (SUP.host);
|
||||
mhl_mem_free (SUP.user);
|
||||
mhl_mem_free (SUP.cwdir);
|
||||
mhl_mem_free (SUP.password);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -260,7 +260,7 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
|
||||
p = g_strconcat (_(" fish: Password required for "),
|
||||
SUP.user, " ", (char *) NULL);
|
||||
op = vfs_get_password (p);
|
||||
g_free (p);
|
||||
mhl_mem_free (p);
|
||||
if (op == NULL)
|
||||
ERRNOR (EPERM, -1);
|
||||
SUP.password = op;
|
||||
@ -323,7 +323,7 @@ fish_open_archive (struct vfs_class *me, struct vfs_s_super *super,
|
||||
p = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags,
|
||||
&password, 0, URL_NOSLASH);
|
||||
|
||||
g_free (p);
|
||||
mhl_mem_free (p);
|
||||
|
||||
SUP.host = host;
|
||||
SUP.user = user;
|
||||
@ -350,12 +350,12 @@ fish_archive_same (struct vfs_class *me, struct vfs_s_super *super,
|
||||
op = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags, 0, 0,
|
||||
URL_NOSLASH);
|
||||
|
||||
g_free (op);
|
||||
mhl_mem_free (op);
|
||||
|
||||
flags = ((strcmp (host, SUP.host) == 0)
|
||||
&& (strcmp (user, SUP.user) == 0) && (flags == SUP.flags));
|
||||
g_free (host);
|
||||
g_free (user);
|
||||
mhl_mem_free (host);
|
||||
mhl_mem_free (user);
|
||||
|
||||
return flags;
|
||||
}
|
||||
@ -367,7 +367,7 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
|
||||
char buffer[8192];
|
||||
struct vfs_s_entry *ent = NULL;
|
||||
FILE *logfile;
|
||||
char *quoted_path;
|
||||
SHELL_ESCAPED_STR quoted_path;
|
||||
int reply_code;
|
||||
|
||||
#if 0
|
||||
@ -462,8 +462,8 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
|
||||
"else\n"
|
||||
"echo '### 500'\n"
|
||||
"fi\n",
|
||||
quoted_path, quoted_path, quoted_path, quoted_path, quoted_path, quoted_path);
|
||||
mhl_mem_free (quoted_path);
|
||||
quoted_path.s, quoted_path.s, quoted_path.s, quoted_path.s, quoted_path.s, quoted_path.s);
|
||||
mhl_mem_free (quoted_path.s);
|
||||
ent = vfs_s_generate_entry(me, NULL, dir, 0);
|
||||
while (1) {
|
||||
int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr);
|
||||
@ -594,7 +594,7 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
|
||||
vfs_s_free_entry (me, ent);
|
||||
reply_code = fish_decode_reply(buffer + 4, 0);
|
||||
if (reply_code == COMPLETE) {
|
||||
g_free (SUP.cwdir);
|
||||
mhl_mem_free (SUP.cwdir);
|
||||
SUP.cwdir = g_strdup (remote_path);
|
||||
print_vfs_message (_("%s: done."), me->name);
|
||||
return 0;
|
||||
@ -618,7 +618,7 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
|
||||
struct stat s;
|
||||
int was_error = 0;
|
||||
int h;
|
||||
char *quoted_name;
|
||||
SHELL_ESCAPED_STR quoted_name;
|
||||
|
||||
h = open (localname, O_RDONLY);
|
||||
|
||||
@ -659,7 +659,7 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
|
||||
*/
|
||||
|
||||
quoted_name = mhl_shell_escape_dup(name);
|
||||
print_vfs_message(_("fish: store %s: sending command..."), quoted_name );
|
||||
print_vfs_message(_("fish: store %s: sending command..."), quoted_name.s );
|
||||
|
||||
/* FIXME: File size is limited to ULONG_MAX */
|
||||
if (!fh->u.fish.append)
|
||||
@ -683,8 +683,8 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
|
||||
" rest=`expr $rest - $n`\n"
|
||||
"done\n"
|
||||
"}; echo '### 200'\n",
|
||||
(unsigned long) s.st_size, quoted_name,
|
||||
quoted_name, (unsigned long) s.st_size,
|
||||
(unsigned long) s.st_size, quoted_name.s,
|
||||
quoted_name.s, (unsigned long) s.st_size,
|
||||
(unsigned long) s.st_size);
|
||||
else
|
||||
n = fish_command (me, super, WAIT_REPLY,
|
||||
@ -700,8 +700,8 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
|
||||
" rest=`expr $rest - $n`\n"
|
||||
"done\n"
|
||||
"}; echo '### 200'\n",
|
||||
(unsigned long) s.st_size, quoted_name,
|
||||
quoted_name, (unsigned long) s.st_size);
|
||||
(unsigned long) s.st_size, quoted_name.s,
|
||||
quoted_name.s, (unsigned long) s.st_size);
|
||||
|
||||
if (n != PRELIM) {
|
||||
close (h);
|
||||
@ -735,14 +735,14 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
|
||||
(unsigned long) s.st_size);
|
||||
}
|
||||
close(h);
|
||||
mhl_mem_free(quoted_name);
|
||||
mhl_mem_free(quoted_name.s);
|
||||
if ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE) || was_error)
|
||||
ERRNOR (E_REMOTE, -1);
|
||||
return 0;
|
||||
error_return:
|
||||
close(h);
|
||||
fish_get_reply(me, SUP.sockr, NULL, 0);
|
||||
mhl_mem_free(quoted_name);
|
||||
mhl_mem_free(quoted_name.s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -750,7 +750,7 @@ static int
|
||||
fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
|
||||
{
|
||||
char *name;
|
||||
char *quoted_name;
|
||||
SHELL_ESCAPED_STR quoted_name;
|
||||
if (offset)
|
||||
ERRNOR (E_NOTSUPP, 0);
|
||||
name = vfs_s_fullpath (me, fh->ino);
|
||||
@ -779,8 +779,8 @@ fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
|
||||
"else\n"
|
||||
"echo '### 500'\n"
|
||||
"fi\n",
|
||||
quoted_name, quoted_name, quoted_name, quoted_name );
|
||||
g_free (quoted_name);
|
||||
quoted_name.s, quoted_name.s, quoted_name.s, quoted_name.s );
|
||||
mhl_mem_free (quoted_name.s);
|
||||
if (offset != PRELIM) ERRNOR (E_REMOTE, 0);
|
||||
fh->linear = LS_LINEAR_OPEN;
|
||||
fh->u.fish.got = 0;
|
||||
@ -889,17 +889,18 @@ fish_send_command(struct vfs_class *me, struct vfs_s_super *super, const char *c
|
||||
#define PREFIX \
|
||||
char buf[BUF_LARGE]; \
|
||||
const char *crpath; \
|
||||
char *rpath, *mpath = g_strdup (path); \
|
||||
char *mpath = mhl_str_dup (path); \
|
||||
SHELL_ESCAPED_STR rpath; \
|
||||
struct vfs_s_super *super; \
|
||||
if (!(crpath = vfs_s_get_path_mangle (me, mpath, &super, 0))) { \
|
||||
g_free (mpath); \
|
||||
mhl_mem_free (mpath); \
|
||||
return -1; \
|
||||
} \
|
||||
rpath = mhl_shell_escape_dup(crpath); \
|
||||
g_free (mpath);
|
||||
mhl_mem_free (mpath);
|
||||
|
||||
#define POSTFIX(flags) \
|
||||
g_free (rpath); \
|
||||
mhl_mem_free (rpath.s); \
|
||||
return fish_send_command(me, super, buf, flags);
|
||||
|
||||
static int
|
||||
@ -909,8 +910,8 @@ fish_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
g_snprintf(buf, sizeof(buf), "#CHMOD %4.4o /%s\n"
|
||||
"chmod %4.4o /%s 2>/dev/null\n"
|
||||
"echo '### 000'\n",
|
||||
mode & 07777, rpath,
|
||||
mode & 07777, rpath);
|
||||
mode & 07777, rpath.s,
|
||||
mode & 07777, rpath.s);
|
||||
POSTFIX(OPT_FLUSH);
|
||||
}
|
||||
|
||||
@ -919,24 +920,24 @@ static int fish_##name (struct vfs_class *me, const char *path1, const char *pat
|
||||
{ \
|
||||
char buf[BUF_LARGE]; \
|
||||
const char *crpath1, *crpath2; \
|
||||
char *rpath1, *rpath2, *mpath1, *mpath2; \
|
||||
char *mpath1, *mpath2; \
|
||||
struct vfs_s_super *super1, *super2; \
|
||||
if (!(crpath1 = vfs_s_get_path_mangle (me, mpath1 = g_strdup(path1), &super1, 0))) { \
|
||||
g_free (mpath1); \
|
||||
mhl_mem_free (mpath1); \
|
||||
return -1; \
|
||||
} \
|
||||
if (!(crpath2 = vfs_s_get_path_mangle (me, mpath2 = g_strdup(path2), &super2, 0))) { \
|
||||
g_free (mpath1); \
|
||||
g_free (mpath2); \
|
||||
mhl_mem_free (mpath1); \
|
||||
mhl_mem_free (mpath2); \
|
||||
return -1; \
|
||||
} \
|
||||
rpath1 = mhl_shell_escape_dup (crpath1); \
|
||||
g_free (mpath1); \
|
||||
rpath2 = mhl_shell_escape_dup (crpath2); \
|
||||
g_free (mpath2); \
|
||||
g_snprintf(buf, sizeof(buf), string "\n", rpath1, rpath2, rpath1, rpath2); \
|
||||
mhl_mem_free (rpath1); \
|
||||
mhl_mem_free (rpath2); \
|
||||
SHELL_ESCAPED_STR rpath1 = mhl_shell_escape_dup (crpath1); \
|
||||
mhl_mem_free (mpath1); \
|
||||
SHELL_ESCAPED_STR rpath2 = mhl_shell_escape_dup (crpath2); \
|
||||
mhl_mem_free (mpath2); \
|
||||
g_snprintf(buf, sizeof(buf), string "\n", rpath1.s, rpath2.s, rpath1.s, rpath2.s); \
|
||||
mhl_mem_free (rpath1.s); \
|
||||
mhl_mem_free (rpath2.s); \
|
||||
return fish_send_command(me, super2, buf, OPT_FLUSH); \
|
||||
}
|
||||
|
||||
@ -949,15 +950,15 @@ FISH_OP(link, "#LINK /%s /%s\n"
|
||||
|
||||
static int fish_symlink (struct vfs_class *me, const char *setto, const char *path)
|
||||
{
|
||||
char *qsetto;
|
||||
SHELL_ESCAPED_STR qsetto;
|
||||
PREFIX
|
||||
qsetto = mhl_shell_escape_dup (setto);
|
||||
g_snprintf(buf, sizeof(buf),
|
||||
"#SYMLINK %s /%s\n"
|
||||
"ln -s %s /%s 2>/dev/null\n"
|
||||
"echo '### 000'\n",
|
||||
qsetto, rpath, qsetto, rpath);
|
||||
mhl_mem_free (qsetto);
|
||||
qsetto.s, rpath.s, qsetto.s, rpath.s);
|
||||
mhl_mem_free (qsetto.s);
|
||||
POSTFIX(OPT_FLUSH);
|
||||
}
|
||||
|
||||
@ -982,16 +983,16 @@ fish_chown (struct vfs_class *me, const char *path, int owner, int group)
|
||||
"#CHOWN %s /%s\n"
|
||||
"chown %s /%s 2>/dev/null\n"
|
||||
"echo '### 000'\n",
|
||||
sowner, rpath,
|
||||
sowner, rpath);
|
||||
sowner, rpath.s,
|
||||
sowner, rpath.s);
|
||||
fish_send_command (me, super, buf, OPT_FLUSH);
|
||||
/* FIXME: what should we report if chgrp succeeds but chown fails? */
|
||||
g_snprintf (buf, sizeof(buf),
|
||||
"#CHGRP /%s \"/%s\"\n"
|
||||
"chgrp %s \"/%s\" 2>/dev/null\n"
|
||||
"echo '### 000'\n",
|
||||
sgroup, rpath,
|
||||
sgroup, rpath);
|
||||
sgroup, rpath.s,
|
||||
sgroup, rpath.s);
|
||||
/* fish_send_command(me, super, buf, OPT_FLUSH); */
|
||||
POSTFIX (OPT_FLUSH)
|
||||
}
|
||||
@ -1004,7 +1005,7 @@ static int fish_unlink (struct vfs_class *me, const char *path)
|
||||
"#DELE /%s\n"
|
||||
"rm -f /%s 2>/dev/null\n"
|
||||
"echo '### 000'\n",
|
||||
rpath, rpath);
|
||||
rpath.s, rpath.s);
|
||||
POSTFIX(OPT_FLUSH);
|
||||
}
|
||||
|
||||
@ -1018,7 +1019,7 @@ static int fish_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
"#MKD /%s\n"
|
||||
"mkdir /%s 2>/dev/null\n"
|
||||
"echo '### 000'\n",
|
||||
rpath, rpath);
|
||||
rpath.s, rpath.s);
|
||||
POSTFIX(OPT_FLUSH);
|
||||
}
|
||||
|
||||
@ -1029,7 +1030,7 @@ static int fish_rmdir (struct vfs_class *me, const char *path)
|
||||
"#RMD /%s\n"
|
||||
"rmdir /%s 2>/dev/null\n"
|
||||
"echo '### 000'\n",
|
||||
rpath, rpath);
|
||||
rpath.s, rpath.s);
|
||||
POSTFIX(OPT_FLUSH);
|
||||
}
|
||||
|
||||
@ -1093,7 +1094,7 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
|
||||
name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, flags,
|
||||
"/", SUP.cwdir, (char *) NULL);
|
||||
(*func)(name);
|
||||
g_free (name);
|
||||
mhl_mem_free (name);
|
||||
super = super->next;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user