C   69
efl exe
Guest on 8th February 2023 03:03:52 AM


  1. #ifdef HAVE_CONFIG_H
  2. # include <config.h>
  3. #endif
  4.  
  5. #define EFL_IO_READER_PROTECTED 1
  6. #define EFL_IO_WRITER_PROTECTED 1
  7. #define EFL_IO_CLOSER_PROTECTED 1
  8.  
  9. #include <Ecore.h>
  10.  
  11. #include "ecore_private.h"
  12.  
  13. #ifdef _WIN32
  14. #else
  15. # include <sys/time.h>
  16. # include <sys/resource.h>
  17. # include <stdlib.h>
  18. # include <stdio.h>
  19. # include <string.h>
  20. # include <errno.h>
  21. # include <sys/types.h>
  22. # include <unistd.h>
  23. # include <fcntl.h>
  24. # include <signal.h>
  25. # include <sys/socket.h>
  26. # ifdef HAVE_PRCTL
  27. #  include <sys/prctl.h>
  28. # endif
  29. # ifdef HAVE_SYS_WAIT_H
  30. #  include <sys/wait.h>
  31. # endif
  32. #endif
  33.  
  34. #define MY_CLASS EFL_EXE_CLASS
  35.  
  36. typedef struct _Efl_Exe_Data Efl_Exe_Data;
  37.  
  38. struct _Efl_Exe_Data
  39. {
  40.    int exit_signal;
  41. #ifdef _WIN32
  42.    struct {
  43.       Eina_Bool can_read : 1;
  44.       Eina_Bool eos_read : 1;
  45.       Eina_Bool can_write : 1;
  46.    } fd;
  47. #else
  48.    Eo *exit_handler;
  49.    pid_t pid;
  50.    struct {
  51.       int in, out, exited_read, exited_write;
  52.       Eo *in_handler, *out_handler;
  53.       Eina_Bool can_read : 1;
  54.       Eina_Bool eos_read : 1;
  55.       Eina_Bool can_write : 1;
  56.    } fd;
  57. #endif
  58.    Eina_Bool exit_called : 1;
  59.    Efl_Exe_Flags flags;
  60. };
  61.  
  62. //////////////////////////////////////////////////////////////////////////
  63.  
  64. #ifdef _WIN32
  65. #else
  66. static const signed char primap[EFL_TASK_PRIORITY_ULTRA + 1] =
  67. {
  68.    10, // EFL_TASK_PRIORITY_NORMAL
  69.    19, // EFL_TASK_PRIORITY_BACKGROUND
  70.    15, // EFL_TASK_PRIORITY_LOW
  71.     5, // EFL_TASK_PRIORITY_HIGH
  72.     0  // EFL_TASK_PRIORITY_ULTRA
  73. };
  74.  
  75. static void
  76. _close_fds(Efl_Exe_Data *pd)
  77. {
  78.    if (pd->fd.in >= 0) close(pd->fd.in);
  79.    if (pd->fd.out >= 0) close(pd->fd.out);
  80.    if (pd->fd.exited_read >= 0) close(pd->fd.exited_read);
  81.    if (pd->fd.exited_write >= 0) close(pd->fd.exited_write);
  82.    pd->fd.in = -1;
  83.    pd->fd.out = -1;
  84.    pd->fd.exited_read = -1;
  85.    pd->fd.exited_write = -1;
  86. }
  87.  
  88. static void
  89. _exec(const char *cmd, Efl_Exe_Flags flags)
  90. {
  91.    char use_sh = 1, *buf = NULL, **args = NULL;
  92.  
  93.    // Try to avoid wrapping the exe call with /bin/sh -c.
  94.    // We conservatively search for certain shell meta characters,
  95.    // If we don't find them, we can call the exe directly.
  96.    if (!strpbrk(cmd, "|&;<>()$\\\"'*?#"))
  97.      {
  98.         char *token, pre_command = 1;
  99.         int num_tokens = 0, len;
  100.  
  101.         len = strlen(cmd);
  102.         buf = alloca(len + 1);
  103.         strcpy(buf, cmd);
  104.         buf[len] = 0;
  105.  
  106.         token = strtok(buf, " \t\n\v");
  107.         while (token)
  108.           {
  109.              if (token[0] == '~') break;
  110.              if (pre_command)
  111.                {
  112.                   if (token[0] == '[') break;
  113.                   if (strchr(token, '=')) break;
  114.                   else pre_command = 0;
  115.                }
  116.              num_tokens++;
  117.              token = strtok(NULL, " \t\n\v");
  118.           }
  119.         if ((!token) && (num_tokens))
  120.           {
  121.              int i = 0;
  122.  
  123.              len = strlen(cmd);
  124.              buf = alloca(len + 1);
  125.              strcpy(buf, cmd);
  126.              buf[len] = 0;
  127.  
  128.              token = strtok(buf, " \t\n\v");
  129.              use_sh = 0;
  130.              args = alloca((num_tokens + 1) * sizeof(char *));
  131.              for (i = 0; i < num_tokens; i++)
  132.                {
  133.                   if (token) args[i] = token;
  134.                   token = strtok(NULL, " \t\n\v");
  135.                }
  136.              args[num_tokens] = NULL;
  137.           }
  138.      }
  139. # ifdef HAVE_PRCTL
  140.    if (flags & EFL_EXE_FLAGS_EXIT_WITH_PARENT)
  141.      prctl(PR_SET_PDEATHSIG, SIGTERM);
  142. # endif
  143.  
  144.    if (flags & EFL_EXE_FLAGS_GROUP_LEADER) setsid();
  145.    if (use_sh) // We have to use a shell to run this.
  146.      {
  147.         errno = 0;
  148.         execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
  149.      }
  150.    else
  151.      { // We can run this directly.
  152.         if (!args)
  153.           {
  154.              ERR("arg[0] is NULL!");
  155.              return;
  156.           }
  157.         errno = 0;
  158.         if (args[0]) execvp(args[0], args);
  159.      }
  160. }
  161.  
  162. static Eina_Bool
  163. _foreach_env(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata EINA_UNUSED)
  164. {
  165.    int keylen;
  166.    char *buf, *s;
  167.  
  168.    if (!data) return EINA_TRUE;
  169.    keylen = strlen(key);
  170.    buf = alloca(keylen + 1 + strlen(data) + 1);
  171.    strcpy(buf, key);
  172.    buf[keylen] = '=';
  173.    strcpy(buf + keylen + 1, data);
  174.    if ((s = strdup(buf))) putenv(s);
  175.    return EINA_TRUE;
  176. }
  177.  
  178. static void
  179. _exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
  180. {
  181.    // XXX: defer the below in a job
  182.    if ((pd->fd.out == -1) && (pd->fd.in == -1) && (pd->fd.exited_read == -1) &&
  183.       (!pd->exit_called))
  184.      {
  185.         pd->exit_called = EINA_TRUE;
  186.         efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
  187.      }
  188. }
  189.  
  190. static void
  191. _cb_exe_exit_read(void *data, const Efl_Event *event EINA_UNUSED)
  192. {
  193.    Eo *obj = data;
  194.    Efl_Exe_Data *pd = efl_data_scope_get(obj, MY_CLASS);
  195.    Ecore_Signal_Pid_Info pinfo;
  196.  
  197.    if (!pd) return;
  198.    if (read(pd->fd.exited_read, &pinfo, sizeof(Ecore_Signal_Pid_Info)) ==
  199.        sizeof(Ecore_Signal_Pid_Info))
  200.      {
  201.         Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
  202.         if (td)
  203.           {
  204.              td->exited = EINA_TRUE;
  205.              td->exit_code = pinfo.exit_code;
  206.              pd->exit_signal = pinfo.exit_signal;
  207.           }
  208.      }
  209.    // we don't need this fd and handler anymore now we code exit status
  210.    close(pd->fd.exited_read);
  211.    pd->fd.exited_read = -1;
  212.    efl_del(pd->exit_handler);
  213.    pd->exit_handler = NULL;
  214.    _exe_exit_eval(obj, pd);
  215.    // XXX: autodel of object here is the sensible easy thing to do in C
  216.    // because then you can just run exe's and not have to listen to them exit
  217.    // and do your own del every time - they will then not leak and just
  218.    // self-cleanup without needing a del of the obj on run. but other
  219.    // languages don't like this, so if you dont care to listen to end/death
  220.    // and then del/unref the obj there... always del/unref it immediately.
  221. }
  222.  
  223. static void
  224. _cb_exe_out(void *data, const Efl_Event *event EINA_UNUSED)
  225. {
  226.    Eo *obj = data;
  227.    efl_io_reader_can_read_set(obj, EINA_TRUE);
  228. }
  229.  
  230. static void
  231. _cb_exe_in(void *data, const Efl_Event *event EINA_UNUSED)
  232. {
  233.    Eo *obj = data;
  234.    efl_io_writer_can_write_set(obj, EINA_TRUE);
  235. }
  236. #endif
  237.  
  238. //////////////////////////////////////////////////////////////////////////
  239.  
  240. EOLIAN static void
  241. _efl_exe_signal(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Signal sig)
  242. {
  243.    int s = 0;
  244.    if (pd->pid == -1) return;
  245.  
  246. #ifdef _WIN32
  247. #else
  248.    switch (sig)
  249.      {
  250.       case EFL_EXE_SIGNAL_INT:  s = SIGINT;  break;
  251.       case EFL_EXE_SIGNAL_QUIT: s = SIGQUIT; break;
  252.       case EFL_EXE_SIGNAL_TERM: s = SIGTERM; break;
  253.       case EFL_EXE_SIGNAL_KILL: s = SIGKILL; break;
  254.       case EFL_EXE_SIGNAL_CONT: s = SIGCONT; break;
  255.       case EFL_EXE_SIGNAL_STOP: s = SIGSTOP; break;
  256.       case EFL_EXE_SIGNAL_HUP:  s = SIGHUP;  break;
  257.       case EFL_EXE_SIGNAL_USR1: s = SIGUSR1; break;
  258.       case EFL_EXE_SIGNAL_USR2: s = SIGUSR2; break;
  259.       default: return;
  260.      }
  261.    kill(pd->pid, s);
  262. #endif
  263. }
  264.  
  265. EOLIAN static void
  266. _efl_exe_flags_set(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Flags flags)
  267. {
  268.    pd->flags = flags;
  269. }
  270.  
  271. EOLIAN static Efl_Exe_Flags
  272. _efl_exe_flags_get(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  273. {
  274.    return pd->flags;
  275. }
  276.  
  277. EOLIAN static void
  278. _efl_exe_efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Task_Priority priority)
  279. {
  280. #ifdef _WIN32
  281. #else
  282.    int p = 0;
  283.  
  284.    if (pd->pid != -1)
  285.      {
  286.         if ((priority >= EFL_TASK_PRIORITY_NORMAL) &&
  287.             (priority <= EFL_TASK_PRIORITY_ULTRA))
  288.           p = primap[priority];
  289.      }
  290.    setpriority(PRIO_PROCESS, pd->pid, p);
  291. #endif
  292.    efl_task_priority_set(efl_super(obj, MY_CLASS), priority);
  293. }
  294.  
  295. EOLIAN static Efl_Task_Priority
  296. _efl_exe_efl_task_priority_get(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  297. {
  298.    Efl_Task_Priority pri = EFL_TASK_PRIORITY_NORMAL;
  299.  
  300.    if (pd->pid == -1)
  301.      return efl_task_priority_get(efl_super(obj, MY_CLASS));
  302. #ifdef _WIN32
  303. #else
  304.    int p, i, dist = 0x7fffffff, d;
  305.  
  306.    // p is -20 -> 19
  307.    errno = 0;
  308.    p = getpriority(PRIO_PROCESS, pd->pid);
  309.    if (errno != 0)
  310.      return efl_task_priority_get(efl_super(obj, MY_CLASS));
  311.  
  312.    // find the closest matching priority in primap
  313.    for (i = EFL_TASK_PRIORITY_NORMAL; i <= EFL_TASK_PRIORITY_ULTRA; i++)
  314.      {
  315.         d = primap[i] - p;
  316.         if (d < 0) d = -d;
  317.         if (d < dist)
  318.           {
  319.              pri = i;
  320.              dist = d;
  321.           }
  322.      }
  323.  
  324.    Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
  325.    if (td) td->priority = pri;
  326. #endif
  327.    return pri;
  328. }
  329.  
  330. EOLIAN static Eina_Bool
  331. _efl_exe_efl_task_run(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  332. {
  333.    Eo *loop;
  334.    Efl_Task_Data *tdl, *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
  335.    const char *cmd;
  336.  
  337.    if (pd->pid != -1) return EINA_FALSE;
  338.    if (!td) return EINA_FALSE;
  339. #ifdef _WIN32
  340.    return EINA_FALSE;
  341. #else
  342.    // forked child from here...
  343.    int devnull;
  344.    int pipe_stdin[2];
  345.    int pipe_stdout[2];
  346.    int pipe_exited[2];
  347.  
  348.    // get a cmdline to run
  349.    cmd = efl_task_command_get(obj);
  350.    if (!cmd) return EINA_FALSE;
  351.  
  352.    pipe(pipe_exited);
  353.    pd->fd.exited_read = pipe_exited[0];
  354.    eina_file_close_on_exec(pd->fd.exited_write,  EINA_TRUE);
  355.    pd->fd.exited_write = pipe_exited[1];
  356.    eina_file_close_on_exec(pd->fd.exited_read,  EINA_TRUE);
  357.  
  358.    if (pd->flags & EFL_EXE_FLAGS_USE_STDIN)
  359.      {
  360.         pipe(pipe_stdin);
  361.         pd->fd.in = pipe_stdin[1];
  362.         fcntl(pd->fd.in, F_SETFL, O_NONBLOCK);
  363.         eina_file_close_on_exec(pd->fd.in, EINA_TRUE);
  364.         pd->fd.in_handler =
  365.           efl_add(EFL_LOOP_HANDLER_CLASS, obj,
  366.                   efl_event_callback_add
  367.                     (efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_exe_in, obj),
  368.                   efl_loop_handler_fd_set(efl_added, pd->fd.in));
  369.      }
  370.    if (pd->flags & EFL_EXE_FLAGS_USE_STDOUT)
  371.      {
  372.         pipe(pipe_stdout);
  373.         pd->fd.out = pipe_stdout[0];
  374.         fcntl(pd->fd.out, F_SETFL, O_NONBLOCK);
  375.         eina_file_close_on_exec(pd->fd.out, EINA_TRUE);
  376.         pd->fd.out_handler =
  377.           efl_add(EFL_LOOP_HANDLER_CLASS, obj,
  378.                   efl_event_callback_add
  379.                     (efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_exe_out, obj),
  380.                   efl_loop_handler_fd_set(efl_added, pd->fd.out),
  381.                   efl_loop_handler_active_set
  382.                     (efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
  383.      }
  384.  
  385.    _ecore_signal_pid_lock();
  386.    pd->pid = fork();
  387.    if (pd->pid != 0)
  388.      {
  389.         // parent process is here inside this if block
  390.         if (pd->flags & EFL_EXE_FLAGS_USE_STDIN)  close(pipe_stdin[0]);
  391.         if (pd->flags & EFL_EXE_FLAGS_USE_STDOUT) close(pipe_stdout[1]);
  392.         // fork failed... close up and clean and release locks
  393.         if (pd->pid == -1)
  394.           {
  395.              _close_fds(pd);
  396.              _ecore_signal_pid_unlock();
  397.              return EINA_FALSE;
  398.           }
  399.         // register this pid in the core sigchild/pid exit code watcher
  400.         _ecore_signal_pid_register(pd->pid, pd->fd.exited_write);
  401.         pd->exit_handler =
  402.           efl_add(EFL_LOOP_HANDLER_CLASS, obj,
  403.                   efl_loop_handler_fd_set(efl_added, pd->fd.exited_read),
  404.                   efl_loop_handler_active_set(efl_added,
  405.                                               EFL_LOOP_HANDLER_FLAGS_READ),
  406.                   efl_event_callback_add(efl_added,
  407.                                          EFL_LOOP_HANDLER_EVENT_READ,
  408.                                          _cb_exe_exit_read, obj));
  409.         _ecore_signal_pid_unlock();
  410.         return EINA_TRUE;
  411.      }
  412.    // this code is in the child here, and is temporary setup until we
  413.    // exec() the child to replace everything.
  414.  
  415.    if (pd->flags & EFL_EXE_FLAGS_USE_STDIN)  close(pipe_stdin[1]);
  416.    if (pd->flags & EFL_EXE_FLAGS_USE_STDOUT) close(pipe_stdout[0]);
  417.    // set priority of self
  418.    if ((td->priority >= EFL_TASK_PRIORITY_NORMAL) &&
  419.        (td->priority <= EFL_TASK_PRIORITY_ULTRA))
  420.      setpriority(PRIO_PROCESS, 0, primap[td->priority]);
  421.  
  422.    // if we want to hide or use any of the stdio, close the fd's
  423.    if ((pd->flags & EFL_EXE_FLAGS_USE_STDIN) ||
  424.        (pd->flags & EFL_EXE_FLAGS_HIDE_IO))
  425.      close(STDIN_FILENO);
  426.    if ((pd->flags & EFL_EXE_FLAGS_USE_STDOUT) ||
  427.        (pd->flags & EFL_EXE_FLAGS_HIDE_IO))
  428.      close(STDOUT_FILENO);
  429.    if ((pd->flags & EFL_EXE_FLAGS_HIDE_IO))
  430.      close(STDERR_FILENO);
  431.  
  432.    if (!(pd->flags & EFL_EXE_FLAGS_USE_STDIN) &&
  433.        (pd->flags & EFL_EXE_FLAGS_HIDE_IO))
  434.      {
  435.         // hide stdin
  436.         devnull = open("/dev/null", O_RDONLY);
  437.         dup2(devnull, STDIN_FILENO);
  438.         close(devnull);
  439.      }
  440.    else if ((pd->flags & EFL_EXE_FLAGS_USE_STDIN))
  441.      {
  442.         // hook up stdin to the pipe going to the parent
  443.         dup2(pipe_stdin[0], STDIN_FILENO);
  444.         close(pipe_stdin[0]);
  445.      }
  446.  
  447.    if (!(pd->flags & EFL_EXE_FLAGS_USE_STDOUT) &&
  448.        (pd->flags & EFL_EXE_FLAGS_HIDE_IO))
  449.      {
  450.         // hide stdout
  451.         devnull = open("/dev/null", O_WRONLY);
  452.         dup2(devnull, STDOUT_FILENO);
  453.         close(devnull);
  454.      }
  455.    else if ((pd->flags & EFL_EXE_FLAGS_USE_STDOUT))
  456.      {
  457.         // hook up stdout to the pipe going to the parent
  458.         dup2(pipe_stdout[1], STDOUT_FILENO);
  459.         close(pipe_stdout[1]);
  460.      }
  461.  
  462.    if ((pd->flags & EFL_EXE_FLAGS_HIDE_IO))
  463.      {
  464.         // hide stderr
  465.         devnull = open("/dev/null", O_WRONLY);
  466.         dup2(devnull, STDERR_FILENO);
  467.         close(devnull);
  468.      }
  469.  
  470.    if (!(loop = efl_provider_find(obj, EFL_LOOP_CLASS))) exit(-120);
  471.  
  472.    if (!(tdl = efl_data_scope_get(loop, EFL_TASK_CLASS))) exit(-121);
  473.  
  474.    // clear systemd notify socket... only relevant for systemd world,
  475.    // otherwise shouldn't be trouble
  476.    putenv("NOTIFY_SOCKET=");
  477.    // force the env hash to update from env vars
  478.    efl_task_env_get(loop, "HOME");
  479.  
  480.    // actually setenv the env hash (clear what was there before so it is
  481.    // the only env there)
  482.    clearenv();
  483.    eina_hash_foreach(td->env, _foreach_env, NULL);
  484.  
  485.    // actually execute!
  486.    _exec(cmd, pd->flags);
  487.    // we couldn't exec... uh oh. HAAAAAAAALP!
  488.    exit(-122);
  489.    return EINA_FALSE;
  490. #endif
  491. }
  492.  
  493. EOLIAN static void
  494. _efl_exe_efl_task_end(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  495. {
  496.    if (pd->pid == -1) return;
  497. #ifdef _WIN32
  498. #else
  499.    kill(pd->pid, SIGINT);
  500. #endif
  501. }
  502.  
  503. EOLIAN static int
  504. _efl_exe_exit_signal_get(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  505. {
  506.    return pd->exit_signal;
  507. }
  508.  
  509. EOLIAN static Efl_Object *
  510. _efl_exe_efl_object_constructor(Eo *obj, Efl_Exe_Data *pd)
  511. {
  512.    obj = efl_constructor(efl_super(obj, MY_CLASS));
  513. #ifdef _WIN32
  514. #else
  515.    pd->pid = -1;
  516.    pd->fd.in = -1;
  517.    pd->fd.out = -1;
  518.    pd->fd.exited_read = -1;
  519. #endif
  520.    pd->flags = EFL_EXE_FLAGS_EXIT_WITH_PARENT;
  521.    pd->exit_signal = -1;
  522.    return obj;
  523. }
  524.  
  525. EOLIAN static void
  526. _efl_exe_efl_object_destructor(Eo *obj, Efl_Exe_Data *pd)
  527. {
  528. #ifdef _WIN32
  529. #else
  530.    _close_fds(pd);
  531.    if (pd->fd.exited_read >= 0)
  532.      {
  533.         _ecore_signal_pid_lock();
  534.         _ecore_signal_pid_unregister(pd->pid, pd->fd.exited_read);
  535.         _ecore_signal_pid_unlock();
  536.         close(pd->fd.exited_read);
  537.         pd->fd.exited_read = -1;
  538.         efl_del(pd->exit_handler);
  539.         pd->exit_handler = NULL;
  540.      }
  541. #endif
  542.    efl_destructor(efl_super(obj, MY_CLASS));
  543. }
  544.  
  545. EOLIAN static Eina_Error
  546. _efl_exe_efl_io_closer_close(Eo *obj, Efl_Exe_Data *pd)
  547. {
  548.    EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
  549.    efl_io_writer_can_write_set(obj, EINA_FALSE);
  550.    efl_io_reader_can_read_set(obj, EINA_FALSE);
  551.    efl_io_reader_eos_set(obj, EINA_TRUE);
  552. #ifdef _WIN32
  553. #else
  554.    if (pd->fd.in >= 0) close(pd->fd.in);
  555.    if (pd->fd.out >= 0) close(pd->fd.out);
  556.    if (pd->fd.exited_read >= 0) close(pd->fd.exited_read);
  557.    if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
  558.    if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
  559.    pd->fd.in = -1;
  560.    pd->fd.out = -1;
  561.    pd->fd.exited_read = -1;
  562.    pd->fd.in_handler = NULL;
  563.    pd->fd.out_handler = NULL;
  564. #endif
  565.    return 0;
  566. }
  567.  
  568. EOLIAN static Eina_Bool
  569. _efl_exe_efl_io_closer_closed_get(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  570. {
  571. #ifdef _WIN32
  572.    return EINA_FALSE;
  573. #else
  574.    if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
  575. #endif
  576.    return EINA_FALSE;
  577. }
  578.  
  579. EOLIAN static Eina_Error
  580. _efl_exe_efl_io_reader_read(Eo *obj, Efl_Exe_Data *pd, Eina_Rw_Slice *rw_slice)
  581. {
  582. #ifdef _WIN32
  583.    return EINVAL;
  584. #else
  585.    ssize_t r;
  586.  
  587.    errno = 0;
  588.    if (pd->fd.out == -1) goto err;
  589.  
  590.    do
  591.      {
  592.         errno = 0;
  593.         r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
  594.         if (r == -1)
  595.           {
  596.              if (errno == EINTR) continue;
  597.              goto err;
  598.           }
  599.      }
  600.    while (r == -1);
  601.  
  602.    rw_slice->len = r;
  603.    if (r == 0)
  604.      {
  605.         efl_io_reader_can_read_set(obj, EINA_FALSE);
  606.         efl_io_reader_eos_set(obj, EINA_TRUE);
  607.         close(pd->fd.out);
  608.         pd->fd.out = -1;
  609.         efl_del(pd->fd.out_handler);
  610.         pd->fd.out_handler = NULL;
  611.         _exe_exit_eval(obj, pd);
  612.         return EPIPE;
  613.      }
  614.    return 0;
  615. err:
  616.    if ((pd->fd.out != -1) && (errno != EAGAIN))
  617.      {
  618.         close(pd->fd.out);
  619.         pd->fd.out = -1;
  620.         efl_del(pd->fd.out_handler);
  621.         pd->fd.out_handler = NULL;
  622.      }
  623.    rw_slice->len = 0;
  624.    rw_slice->mem = NULL;
  625.    efl_io_reader_can_read_set(obj, EINA_FALSE);
  626.    _exe_exit_eval(obj, pd);
  627.    return EINVAL;
  628. #endif
  629. }
  630.  
  631. EOLIAN static void
  632. _efl_exe_efl_io_reader_can_read_set(Eo *obj, Efl_Exe_Data *pd, Eina_Bool can_read)
  633. {
  634.    Eina_Bool old = efl_io_reader_can_read_get(obj);
  635.    if (old == can_read) return;
  636.    pd->fd.can_read = can_read;
  637.    efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
  638. }
  639.  
  640. EOLIAN static Eina_Bool
  641. _efl_exe_efl_io_reader_can_read_get(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  642. {
  643.    return pd->fd.can_read;
  644. }
  645.  
  646. EOLIAN static void
  647. _efl_exe_efl_io_reader_eos_set(Eo *obj, Efl_Exe_Data *pd, Eina_Bool is_eos)
  648. {
  649.    Eina_Bool old = efl_io_reader_eos_get(obj);
  650.    if (old == is_eos) return;
  651.  
  652.    pd->fd.eos_read = is_eos;
  653.    if (!is_eos) return;
  654.    if (pd->fd.out_handler)
  655.      efl_loop_handler_active_set(pd->fd.out_handler, 0);
  656.    efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
  657. }
  658.  
  659. EOLIAN static Eina_Bool
  660. _efl_exe_efl_io_reader_eos_get(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  661. {
  662.    return pd->fd.eos_read;
  663. }
  664.  
  665. EOLIAN static Eina_Error
  666. _efl_exe_efl_io_writer_write(Eo *obj, Efl_Exe_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
  667. {
  668. #ifdef _WIN32
  669.    return EINVAL;
  670. #else
  671.    ssize_t r;
  672.  
  673.    errno = 0;
  674.    if (pd->fd.in == -1) goto err;
  675.  
  676.    do
  677.      {
  678.         errno = 0;
  679.         r = write(pd->fd.in, slice->mem, slice->len);
  680.         printf("> write %p %i size=%i ret=%i errno=%i\n",
  681.                obj, pd->fd.in, (int)slice->len, (int)r, errno);
  682.         if (r == -1)
  683.           {
  684.              if (errno == EINTR) continue;
  685.              goto err;
  686.           }
  687.      }
  688.    while (r == -1);
  689.  
  690.    if (remaining)
  691.      {
  692.         remaining->len = slice->len - r;
  693.         remaining->bytes = slice->bytes + r;
  694.      }
  695.    slice->len = r;
  696.  
  697.    printf("> ... wrote %i\n", (int)slice->len);
  698.    if ((slice) && (slice->len > 0))
  699.      {
  700.         printf("> ... set can write to false\n");
  701.         efl_io_writer_can_write_set(obj, EINA_FALSE);
  702.      }
  703.    if (r == 0)
  704.      {
  705.         close(pd->fd.in);
  706.         pd->fd.in = -1;
  707.         efl_del(pd->fd.in_handler);
  708.         pd->fd.in_handler = NULL;
  709.         _exe_exit_eval(obj, pd);
  710.         return EPIPE;
  711.      }
  712.    return 0;
  713. err:
  714.    printf("> err....\n");
  715.    if ((pd->fd.in != -1) && (errno != EAGAIN))
  716.      {
  717.         printf("> close\n");
  718.         close(pd->fd.in);
  719.         pd->fd.in = -1;
  720.         efl_del(pd->fd.in_handler);
  721.         pd->fd.in_handler = NULL;
  722.      }
  723.    if (remaining) *remaining = *slice;
  724.    slice->len = 0;
  725.    slice->mem = NULL;
  726.    efl_io_writer_can_write_set(obj, EINA_FALSE);
  727.    _exe_exit_eval(obj, pd);
  728.    return EINVAL;
  729. #endif
  730. }
  731.  
  732. EOLIAN static void
  733. _efl_exe_efl_io_writer_can_write_set(Eo *obj, Efl_Exe_Data *pd, Eina_Bool can_write)
  734. {
  735.    Eina_Bool old = efl_io_writer_can_write_get(obj);
  736.    if (old == can_write) return;
  737.    pd->fd.can_write = can_write;
  738.    printf("CAN WRITE %i\n", can_write);
  739.    if (can_write)
  740.      efl_loop_handler_active_set(pd->fd.in_handler, 0);
  741.    else
  742.      efl_loop_handler_active_set(pd->fd.in_handler,
  743.                                  EFL_LOOP_HANDLER_FLAGS_WRITE);
  744.    efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
  745. }
  746.  
  747. EOLIAN static Eina_Bool
  748. _efl_exe_efl_io_writer_can_write_get(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
  749. {
  750.    return pd->fd.can_write;
  751. }
  752.  
  753. //////////////////////////////////////////////////////////////////////////
  754.  
  755. #include "efl_exe.eo.c"

Raw Paste

Login or Register to edit or fork this paste. It's free.