forked from enlightenment/efl
360 lines
8.5 KiB
C
360 lines
8.5 KiB
C
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <Ecore.h>
|
|
|
|
#include "ecore_private.h"
|
|
|
|
#define MY_CLASS EFL_TASK_CLASS
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
static void
|
|
_clear_args(Efl_Task_Data *pd)
|
|
{
|
|
unsigned int count, i;
|
|
|
|
if (!pd->args) return;
|
|
count = eina_array_count(pd->args);
|
|
for (i = 0; i < count; i++)
|
|
eina_stringshare_del(eina_array_data_get(pd->args, i));
|
|
eina_array_free(pd->args);
|
|
pd->args = NULL;
|
|
}
|
|
|
|
static Eina_Array *
|
|
_unescape(const char *s)
|
|
{
|
|
Eina_Array *args;
|
|
const char *p;
|
|
char *tmp = NULL, *d = NULL;
|
|
if (!s) return NULL;
|
|
|
|
Eina_Bool in_quote_dbl = EINA_FALSE;
|
|
Eina_Bool in_quote = EINA_FALSE;
|
|
|
|
args = eina_array_new(16);
|
|
if (!args) return NULL;
|
|
for (p = s; *p; p++)
|
|
{
|
|
if (!tmp) tmp = d = strdup(p);
|
|
if (tmp)
|
|
{
|
|
if (in_quote_dbl)
|
|
{
|
|
switch (*p)
|
|
{
|
|
case '\"':
|
|
in_quote_dbl = EINA_FALSE;
|
|
*d = 0;
|
|
eina_array_push(args, eina_stringshare_add(tmp));
|
|
free(tmp);
|
|
tmp = d = NULL;
|
|
break;
|
|
case '\\':
|
|
p++;
|
|
EINA_FALLTHROUGH
|
|
default:
|
|
*d = *p;
|
|
d++;
|
|
break;
|
|
}
|
|
}
|
|
else if (in_quote)
|
|
{
|
|
switch (*p)
|
|
{
|
|
case '\'':
|
|
in_quote = EINA_FALSE;
|
|
*d = 0;
|
|
eina_array_push(args, eina_stringshare_add(tmp));
|
|
free(tmp);
|
|
tmp = d = NULL;
|
|
break;
|
|
case '\\':
|
|
p++;
|
|
EINA_FALLTHROUGH
|
|
default:
|
|
*d = *p;
|
|
d++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (*p)
|
|
{
|
|
case ' ':
|
|
case '\t':
|
|
case '\r':
|
|
case '\n':
|
|
*d = 0;
|
|
eina_array_push(args, eina_stringshare_add(tmp));
|
|
free(tmp);
|
|
tmp = d = NULL;
|
|
break;
|
|
case '\"':
|
|
in_quote_dbl = EINA_TRUE;
|
|
break;
|
|
case '\'':
|
|
in_quote = EINA_TRUE;
|
|
break;
|
|
case '\\':
|
|
p++;
|
|
EINA_FALLTHROUGH
|
|
default:
|
|
*d = *p;
|
|
d++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (tmp)
|
|
{
|
|
*d = 0;
|
|
eina_array_push(args, eina_stringshare_add(tmp));
|
|
free(tmp);
|
|
}
|
|
return args;
|
|
}
|
|
|
|
static char *
|
|
_escape(const char *s)
|
|
{
|
|
Eina_Bool need_quote = EINA_FALSE;
|
|
const char *p;
|
|
char *s2 = malloc((strlen(s) * 2) + 1 + 2), *d;
|
|
|
|
if (!s2) return NULL;
|
|
|
|
for (p = s; *p; p++)
|
|
{
|
|
switch (*p)
|
|
{
|
|
case '\'':
|
|
case '\"':
|
|
case '$':
|
|
case '#':
|
|
case ';':
|
|
case '&':
|
|
case '`':
|
|
case '|':
|
|
case '(':
|
|
case ')':
|
|
case '[':
|
|
case ']':
|
|
case '{':
|
|
case '}':
|
|
case '>':
|
|
case '<':
|
|
case '\n':
|
|
case '\r':
|
|
case '\t':
|
|
need_quote = EINA_TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
d = s2;
|
|
if (need_quote)
|
|
{
|
|
*d = '\"';
|
|
d++;
|
|
}
|
|
for (p = s; *p; p++, d++)
|
|
{
|
|
switch (*p)
|
|
{
|
|
case ' ':
|
|
case '\\':
|
|
case '\'':
|
|
case '\"':
|
|
*d = '\\';
|
|
d++;
|
|
EINA_FALLTHROUGH
|
|
default:
|
|
*d = *p;
|
|
break;
|
|
}
|
|
}
|
|
if (need_quote)
|
|
{
|
|
*d = '\"';
|
|
d++;
|
|
}
|
|
*d = 0;
|
|
return s2;
|
|
}
|
|
|
|
static void
|
|
_rebuild_command(Efl_Task_Data *pd)
|
|
{
|
|
unsigned int count, i;
|
|
Eina_Strbuf *sb;
|
|
const char *arg, *cmd;
|
|
Eina_Bool have_args = EINA_FALSE;
|
|
|
|
if (!pd->command_dirty) return;
|
|
pd->command_dirty = EINA_FALSE;
|
|
eina_stringshare_del(pd->command);
|
|
pd->command = NULL;
|
|
if (!pd->args) return;
|
|
sb = eina_strbuf_new();
|
|
if (!sb) return;
|
|
count = eina_array_count(pd->args);
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
arg = eina_array_data_get(pd->args, i);
|
|
if (arg)
|
|
{
|
|
char *str = _escape(arg);
|
|
if (str)
|
|
{
|
|
if (have_args) eina_strbuf_append(sb, " ");
|
|
eina_strbuf_append(sb, str);
|
|
free(str);
|
|
have_args = EINA_TRUE;
|
|
}
|
|
}
|
|
}
|
|
cmd = eina_strbuf_string_get(sb);
|
|
if (cmd) pd->command = eina_stringshare_add(cmd);
|
|
eina_strbuf_free(sb);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
EOLIAN static void
|
|
_efl_task_command_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *command)
|
|
{
|
|
eina_stringshare_replace(&pd->command, command);
|
|
_clear_args(pd);
|
|
pd->args = _unescape(pd->command);
|
|
}
|
|
|
|
EOLIAN static const char *
|
|
_efl_task_command_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
|
|
{
|
|
_rebuild_command(pd);
|
|
return pd->command;
|
|
}
|
|
|
|
EOLIAN static unsigned int
|
|
_efl_task_arg_count_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
|
|
{
|
|
if (!pd->args) return 0;
|
|
return eina_array_count(pd->args);
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_task_arg_value_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, unsigned int num, const char *arg)
|
|
{
|
|
const char *parg = NULL;
|
|
unsigned int count;
|
|
|
|
if (!pd->args) pd->args = eina_array_new(16);
|
|
count = eina_array_count(pd->args);
|
|
if ((count > 0) && (count > num))
|
|
parg = eina_array_data_get(pd->args, num);
|
|
else
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = count; i <= num; i++)
|
|
{
|
|
eina_array_push(pd->args, "");
|
|
eina_array_data_set(pd->args, i, NULL);
|
|
}
|
|
}
|
|
|
|
if (arg)
|
|
eina_array_data_set(pd->args, num, eina_stringshare_add(arg));
|
|
else
|
|
eina_array_data_set(pd->args, num, NULL);
|
|
if (parg) eina_stringshare_del(parg);
|
|
pd->command_dirty = EINA_TRUE;
|
|
}
|
|
|
|
EOLIAN static const char *
|
|
_efl_task_arg_value_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd, unsigned int num)
|
|
{
|
|
unsigned int count;
|
|
|
|
if (!pd->args) return NULL;
|
|
count = eina_array_count(pd->args);
|
|
if (num >= count) return NULL;
|
|
return eina_array_data_get(pd->args, num);
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_task_arg_append(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *arg)
|
|
{
|
|
if (!pd->args) pd->args = eina_array_new(16);
|
|
if (arg)
|
|
eina_array_push(pd->args, eina_stringshare_add(arg));
|
|
else
|
|
eina_array_push(pd->args, NULL);
|
|
pd->command_dirty = EINA_TRUE;
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_task_arg_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
|
|
{
|
|
_clear_args(pd);
|
|
pd->command_dirty = EINA_TRUE;
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority)
|
|
{
|
|
pd->priority = priority;
|
|
}
|
|
|
|
EOLIAN static Efl_Task_Priority
|
|
_efl_task_priority_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
|
|
{
|
|
return pd->priority;
|
|
}
|
|
|
|
EOLIAN static int
|
|
_efl_task_exit_code_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
|
|
{
|
|
return pd->exit_code;
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_task_flags_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Flags flags)
|
|
{
|
|
pd->flags = flags;
|
|
}
|
|
|
|
EOLIAN static Efl_Task_Flags
|
|
_efl_task_flags_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
|
|
{
|
|
return pd->flags;
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_task_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
|
|
{
|
|
eina_stringshare_del(pd->command);
|
|
pd->command = NULL;
|
|
_clear_args(pd);
|
|
efl_destructor(efl_super(obj, MY_CLASS));
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd EINA_UNUSED, Efl_Object *parent)
|
|
{
|
|
efl_parent_set(efl_super(obj, MY_CLASS), parent);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "efl_task.eo.c"
|