LCOV - code coverage report
Current view: top level - lib/process - process.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 255 262 97.3 %
Date: 2021-11-24 03:28:48 Functions: 40 41 97.6 %

          Line data    Source code
       1             : /* Copyright (c) 2003, Roger Dingledine
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : /**
       7             :  * \file process.c
       8             :  * \brief Module for working with other processes.
       9             :  **/
      10             : 
      11             : #define PROCESS_PRIVATE
      12             : #include "lib/buf/buffers.h"
      13             : #include "lib/net/buffers_net.h"
      14             : #include "lib/container/smartlist.h"
      15             : #include "lib/log/log.h"
      16             : #include "lib/log/util_bug.h"
      17             : #include "lib/process/process.h"
      18             : #include "lib/process/process_unix.h"
      19             : #include "lib/process/process_win32.h"
      20             : #include "lib/process/env.h"
      21             : 
      22             : #ifdef HAVE_STDDEF_H
      23             : #include <stddef.h>
      24             : #endif
      25             : 
      26             : /** A list of all <b>process_t</b> instances currently allocated. */
      27             : static smartlist_t *processes;
      28             : 
      29             : /**
      30             :  * Boolean.  If true, then Tor may call execve or CreateProcess via
      31             :  * tor_spawn_background.
      32             :  **/
      33             : static int may_spawn_background_process = 1;
      34             : 
      35             : /** Structure to represent a child process. */
      36             : struct process_t {
      37             :   /** Process status. */
      38             :   process_status_t status;
      39             : 
      40             :   /** Which protocol is the process using? */
      41             :   process_protocol_t protocol;
      42             : 
      43             :   /** Which function to call when we have data ready from stdout? */
      44             :   process_read_callback_t stdout_read_callback;
      45             : 
      46             :   /** Which function to call when we have data ready from stderr? */
      47             :   process_read_callback_t stderr_read_callback;
      48             : 
      49             :   /** Which function call when our process terminated? */
      50             :   process_exit_callback_t exit_callback;
      51             : 
      52             :   /** Our exit code when the process have terminated. */
      53             :   process_exit_code_t exit_code;
      54             : 
      55             :   /** Name of the command we want to execute (for example: /bin/ls). */
      56             :   char *command;
      57             : 
      58             :   /** The arguments used for the new process. The format here is one argument
      59             :    * per element of the smartlist_t. On Windows these arguments are combined
      60             :    * together using the <b>tor_join_win_cmdline</b> function. On Unix the
      61             :    * process name (argv[0]) and the trailing NULL is added automatically before
      62             :    * the process is executed. */
      63             :   smartlist_t *arguments;
      64             : 
      65             :   /** The environment used for the new process. */
      66             :   smartlist_t *environment;
      67             : 
      68             :   /** Buffer to store data from stdout when it is read. */
      69             :   buf_t *stdout_buffer;
      70             : 
      71             :   /** Buffer to store data from stderr when it is read. */
      72             :   buf_t *stderr_buffer;
      73             : 
      74             :   /** Buffer to store data to stdin before it is written. */
      75             :   buf_t *stdin_buffer;
      76             : 
      77             :   /** Do we need to store some custom data with the process? */
      78             :   void *data;
      79             : 
      80             : #ifndef _WIN32
      81             :   /** Our Unix process handle. */
      82             :   process_unix_t *unix_process;
      83             : #else
      84             :   /** Our Win32 process handle. */
      85             :   process_win32_t *win32_process;
      86             : #endif /* !defined(_WIN32) */
      87             : };
      88             : 
      89             : /** Convert a given process status in <b>status</b> to its string
      90             :  * representation. */
      91             : const char *
      92           3 : process_status_to_string(process_status_t status)
      93             : {
      94           3 :   switch (status) {
      95             :   case PROCESS_STATUS_NOT_RUNNING:
      96             :     return "not running";
      97           1 :   case PROCESS_STATUS_RUNNING:
      98           1 :     return "running";
      99           1 :   case PROCESS_STATUS_ERROR:
     100           1 :     return "error";
     101             :   }
     102             : 
     103             :   /* LCOV_EXCL_START */
     104             :   tor_assert_unreached();
     105             :   return NULL;
     106             :   /* LCOV_EXCL_STOP */
     107             : }
     108             : 
     109             : /** Convert a given process protocol in <b>protocol</b> to its string
     110             :  * representation. */
     111             : const char *
     112           2 : process_protocol_to_string(process_protocol_t protocol)
     113             : {
     114           2 :   switch (protocol) {
     115             :   case PROCESS_PROTOCOL_LINE:
     116             :     return "Line";
     117           1 :   case PROCESS_PROTOCOL_RAW:
     118           1 :     return "Raw";
     119             :   }
     120             : 
     121             :   /* LCOV_EXCL_START */
     122             :   tor_assert_unreached();
     123             :   return NULL;
     124             :   /* LCOV_EXCL_STOP */
     125             : }
     126             : 
     127             : /**
     128             :  * Turn off may_spawn_background_process, so that all future calls to
     129             :  * tor_spawn_background are guaranteed to fail.
     130             :  **/
     131             : void
     132           0 : tor_disable_spawning_background_processes(void)
     133             : {
     134           0 :   may_spawn_background_process = 0;
     135           0 : }
     136             : 
     137             : /** Initialize the Process subsystem.  This function initializes the Process
     138             :  * subsystem's global state. For cleaning up, <b>process_free_all()</b> should
     139             :  * be called. */
     140             : void
     141        5553 : process_init(void)
     142             : {
     143        5553 :   processes = smartlist_new();
     144             : 
     145             : #ifdef _WIN32
     146             :   process_win32_init();
     147             : #endif
     148        5553 : }
     149             : 
     150             : /** Free up all resources that is handled by the Process subsystem. Note that
     151             :  * this call does not terminate already running processes. */
     152             : void
     153         235 : process_free_all(void)
     154             : {
     155             : #ifdef _WIN32
     156             :   process_win32_deinit();
     157             : #endif
     158             : 
     159         250 :   SMARTLIST_FOREACH(processes, process_t *, x, process_free(x));
     160         235 :   smartlist_free(processes);
     161         235 : }
     162             : 
     163             : /** Get a list of all processes.  This function returns a smartlist of
     164             :  * <b>process_t</b> containing all the currently allocated processes. */
     165             : const smartlist_t *
     166           1 : process_get_all_processes(void)
     167             : {
     168           1 :   return processes;
     169             : }
     170             : 
     171             : /** Allocate and initialize a new process.  This function returns a newly
     172             :  * allocated and initialized process data, which can be used to configure and
     173             :  * later run a subprocess of Tor. Use the various <b>process_set_*()</b>
     174             :  * methods to configure it and run the process using <b>process_exec()</b>. Use
     175             :  * <b>command</b> to specify the path to the command to run. You can either
     176             :  * specify an absolute path to the command or relative where Tor will use the
     177             :  * underlying operating system's functionality for finding the command to run.
     178             :  * */
     179             : process_t *
     180          32 : process_new(const char *command)
     181             : {
     182          32 :   tor_assert(command);
     183             : 
     184          32 :   process_t *process;
     185          32 :   process = tor_malloc_zero(sizeof(process_t));
     186             : 
     187             :   /* Set our command. */
     188          32 :   process->command = tor_strdup(command);
     189             : 
     190             :   /* By default we are not running. */
     191          32 :   process->status = PROCESS_STATUS_NOT_RUNNING;
     192             : 
     193             :   /* Prepare process environment. */
     194          32 :   process->arguments = smartlist_new();
     195          32 :   process->environment = smartlist_new();
     196             : 
     197             :   /* Prepare the buffers. */
     198          32 :   process->stdout_buffer = buf_new();
     199          32 :   process->stderr_buffer = buf_new();
     200          32 :   process->stdin_buffer = buf_new();
     201             : 
     202             : #ifndef _WIN32
     203             :   /* Prepare our Unix process handle. */
     204          32 :   process->unix_process = process_unix_new();
     205             : #else
     206             :   /* Prepare our Win32 process handle. */
     207             :   process->win32_process = process_win32_new();
     208             : #endif /* !defined(_WIN32) */
     209             : 
     210          32 :   smartlist_add(processes, process);
     211             : 
     212          32 :   return process;
     213             : }
     214             : 
     215             : /** Deallocate the given process in <b>process</b>. */
     216             : void
     217          29 : process_free_(process_t *process)
     218             : {
     219          29 :   if (! process)
     220             :     return;
     221             : 
     222             :   /* Cleanup parameters. */
     223          29 :   tor_free(process->command);
     224             : 
     225             :   /* Cleanup arguments and environment. */
     226          35 :   SMARTLIST_FOREACH(process->arguments, char *, x, tor_free(x));
     227          29 :   smartlist_free(process->arguments);
     228             : 
     229          32 :   SMARTLIST_FOREACH(process->environment, char *, x, tor_free(x));
     230          29 :   smartlist_free(process->environment);
     231             : 
     232             :   /* Cleanup the buffers. */
     233          29 :   buf_free(process->stdout_buffer);
     234          29 :   buf_free(process->stderr_buffer);
     235          29 :   buf_free(process->stdin_buffer);
     236             : 
     237             : #ifndef _WIN32
     238             :   /* Cleanup our Unix process handle. */
     239          29 :   process_unix_free(process->unix_process);
     240             : #else
     241             :   /* Cleanup our Win32 process handle. */
     242             :   process_win32_free(process->win32_process);
     243             : #endif /* !defined(_WIN32) */
     244             : 
     245          29 :   smartlist_remove(processes, process);
     246             : 
     247          29 :   tor_free(process);
     248             : }
     249             : 
     250             : /** Execute the given process.  This function executes the given process as a
     251             :  * subprocess of Tor. Returns <b>PROCESS_STATUS_RUNNING</b> upon success. */
     252             : process_status_t
     253           3 : process_exec(process_t *process)
     254             : {
     255           3 :   tor_assert(process);
     256             : 
     257           3 :   if (BUG(may_spawn_background_process == 0))
     258           0 :     return PROCESS_STATUS_ERROR;
     259             : 
     260           3 :   process_status_t status = PROCESS_STATUS_NOT_RUNNING;
     261             : 
     262           3 :   log_info(LD_PROCESS, "Starting new process: %s", process->command);
     263             : 
     264             : #ifndef _WIN32
     265           3 :   status = process_unix_exec(process);
     266             : #else
     267             :   status = process_win32_exec(process);
     268             : #endif
     269             : 
     270             :   /* Update our state. */
     271           3 :   process_set_status(process, status);
     272             : 
     273           3 :   if (status != PROCESS_STATUS_RUNNING) {
     274           0 :     log_warn(LD_PROCESS, "Failed to start process: %s",
     275             :              process_get_command(process));
     276             :   }
     277             : 
     278             :   return status;
     279             : }
     280             : 
     281             : /** Terminate the given process. Returns true on success,
     282             :  * otherwise false. */
     283             : bool
     284          16 : process_terminate(process_t *process)
     285             : {
     286          16 :   tor_assert(process);
     287             : 
     288             :   /* Terminating a non-running process isn't going to work. */
     289          16 :   if (process_get_status(process) != PROCESS_STATUS_RUNNING)
     290             :     return false;
     291             : 
     292           1 :   log_debug(LD_PROCESS, "Terminating process");
     293             : 
     294             : #ifndef _WIN32
     295           1 :   return process_unix_terminate(process);
     296             : #else
     297             :   return process_win32_terminate(process);
     298             : #endif
     299             : }
     300             : 
     301             : /** Returns the unique process identifier for the given <b>process</b>. */
     302             : process_pid_t
     303           1 : process_get_pid(process_t *process)
     304             : {
     305           1 :   tor_assert(process);
     306             : 
     307             : #ifndef _WIN32
     308           1 :   return process_unix_get_pid(process);
     309             : #else
     310             :   return process_win32_get_pid(process);
     311             : #endif
     312             : }
     313             : 
     314             : /** Set the callback function for output from the child process's standard out
     315             :  * handle.  This function sets the callback function which is called every time
     316             :  * the child process have written output to its standard out file handle.
     317             :  *
     318             :  * Use <b>process_set_protocol(process, PROCESS_PROTOCOL_LINE)</b> if you want
     319             :  * the callback to only contain complete "\n" or "\r\n" terminated lines. */
     320             : void
     321           6 : process_set_stdout_read_callback(process_t *process,
     322             :                                  process_read_callback_t callback)
     323             : {
     324           6 :   tor_assert(process);
     325           6 :   process->stdout_read_callback = callback;
     326           6 : }
     327             : 
     328             : /** Set the callback function for output from the child process's standard
     329             :  * error handle.  This function sets the callback function which is called
     330             :  * every time the child process have written output to its standard error file
     331             :  * handle.
     332             :  *
     333             :  * Use <b>process_set_protocol(process, PROCESS_PROTOCOL_LINE)</b> if you want
     334             :  * the callback to only contain complete "\n" or "\r\n" terminated lines. */
     335             : void
     336           5 : process_set_stderr_read_callback(process_t *process,
     337             :                                  process_read_callback_t callback)
     338             : {
     339           5 :   tor_assert(process);
     340           5 :   process->stderr_read_callback = callback;
     341           5 : }
     342             : 
     343             : /** Set the callback function for process exit notification.  The
     344             :  * <b>callback</b> function will be called every time your child process have
     345             :  * terminated. */
     346             : void
     347           4 : process_set_exit_callback(process_t *process,
     348             :                           process_exit_callback_t callback)
     349             : {
     350           4 :   tor_assert(process);
     351           4 :   process->exit_callback = callback;
     352           4 : }
     353             : 
     354             : /** Get the current command of the given process. */
     355             : const char *
     356           1 : process_get_command(const process_t *process)
     357             : {
     358           1 :   tor_assert(process);
     359           1 :   return process->command;
     360             : }
     361             : 
     362             : void
     363           1 : process_set_protocol(process_t *process, process_protocol_t protocol)
     364             : {
     365           1 :   tor_assert(process);
     366           1 :   process->protocol = protocol;
     367           1 : }
     368             : 
     369             : /** Get the currently used protocol of the given process. */
     370             : process_protocol_t
     371          33 : process_get_protocol(const process_t *process)
     372             : {
     373          33 :   tor_assert(process);
     374          33 :   return process->protocol;
     375             : }
     376             : 
     377             : /** Set opaque pointer to data.  This function allows you to store a pointer to
     378             :  * your own data in the given process. Use <b>process_get_data()</b> in the
     379             :  * various callback functions to retrieve the data again.
     380             :  *
     381             :  * Note that the given process does NOT take ownership of the data and you are
     382             :  * responsible for freeing up any resources allocated by the given data.
     383             :  * */
     384             : void
     385          26 : process_set_data(process_t *process, void *data)
     386             : {
     387          26 :   tor_assert(process);
     388          26 :   process->data = data;
     389          26 : }
     390             : 
     391             : /** Get the opaque pointer to callback data from the given process.  This
     392             :  * function allows you get the data you stored with <b>process_set_data()</b>
     393             :  * in the different callback functions. */
     394             : void *
     395          55 : process_get_data(const process_t *process)
     396             : {
     397          55 :   tor_assert(process);
     398          55 :   return process->data;
     399             : }
     400             : 
     401             : /** Set the status of a given process. */
     402             : void
     403           8 : process_set_status(process_t *process, process_status_t status)
     404             : {
     405           8 :   tor_assert(process);
     406           8 :   process->status = status;
     407           8 : }
     408             : 
     409             : /** Get the status of the given process. */
     410             : process_status_t
     411          22 : process_get_status(const process_t *process)
     412             : {
     413          22 :   tor_assert(process);
     414          22 :   return process->status;
     415             : }
     416             : 
     417             : /** Append an argument to the list of arguments in the given process. */
     418             : void
     419           6 : process_append_argument(process_t *process, const char *argument)
     420             : {
     421           6 :   tor_assert(process);
     422           6 :   tor_assert(argument);
     423             : 
     424           6 :   smartlist_add(process->arguments, tor_strdup(argument));
     425           6 : }
     426             : 
     427             : /** Returns a list of arguments (excluding the command itself) from the
     428             :  * given process. */
     429             : const smartlist_t *
     430           2 : process_get_arguments(const process_t *process)
     431             : {
     432           2 :   tor_assert(process);
     433           2 :   return process->arguments;
     434             : }
     435             : 
     436             : /** Returns a newly allocated Unix style argument vector. Use <b>tor_free()</b>
     437             :  * to deallocate it after use. */
     438             : char **
     439           3 : process_get_argv(const process_t *process)
     440             : {
     441           3 :   tor_assert(process);
     442             : 
     443             :   /** Generate a Unix style process argument vector from our process's
     444             :    * arguments smartlist_t. */
     445           3 :   char **argv = NULL;
     446             : 
     447           3 :   char *filename = process->command;
     448           3 :   const smartlist_t *arguments = process->arguments;
     449           3 :   const size_t size = smartlist_len(arguments);
     450             : 
     451             :   /* Make space for the process filename as argv[0] and a trailing NULL. */
     452           3 :   argv = tor_malloc_zero(sizeof(char *) * (size + 2));
     453             : 
     454             :   /* Set our filename as first argument. */
     455           3 :   argv[0] = filename;
     456             : 
     457             :   /* Put in the rest of the values from arguments. */
     458           9 :   SMARTLIST_FOREACH_BEGIN(arguments, char *, arg_val) {
     459           6 :     tor_assert(arg_val != NULL);
     460             : 
     461           6 :     argv[arg_val_sl_idx + 1] = arg_val;
     462           6 :   } SMARTLIST_FOREACH_END(arg_val);
     463             : 
     464           3 :   return argv;
     465             : }
     466             : 
     467             : /** This function clears the internal environment and copies over every string
     468             :  * from <b>env</b> as the new environment. */
     469             : void
     470           1 : process_reset_environment(process_t *process, const smartlist_t *env)
     471             : {
     472           1 :   tor_assert(process);
     473           1 :   tor_assert(env);
     474             : 
     475             :   /* Cleanup old environment. */
     476           4 :   SMARTLIST_FOREACH(process->environment, char *, x, tor_free(x));
     477           1 :   smartlist_free(process->environment);
     478           1 :   process->environment = smartlist_new();
     479             : 
     480           3 :   SMARTLIST_FOREACH(env, char *, x,
     481             :                     smartlist_add(process->environment, tor_strdup(x)));
     482           1 : }
     483             : 
     484             : /** Set the given <b>key</b>/<b>value</b> pair as environment variable in the
     485             :  * given process. */
     486             : void
     487           4 : process_set_environment(process_t *process,
     488             :                         const char *key,
     489             :                         const char *value)
     490             : {
     491           4 :   tor_assert(process);
     492           4 :   tor_assert(key);
     493           4 :   tor_assert(value);
     494             : 
     495           4 :   smartlist_add_asprintf(process->environment, "%s=%s", key, value);
     496           4 : }
     497             : 
     498             : /** Returns a newly allocated <b>process_environment_t</b> containing the
     499             :  * environment variables for the given process. */
     500             : process_environment_t *
     501           4 : process_get_environment(const process_t *process)
     502             : {
     503           4 :   tor_assert(process);
     504           4 :   return process_environment_make(process->environment);
     505             : }
     506             : 
     507             : #ifndef _WIN32
     508             : /** Get the internal handle for the Unix backend. */
     509             : process_unix_t *
     510          27 : process_get_unix_process(const process_t *process)
     511             : {
     512          27 :   tor_assert(process);
     513          27 :   tor_assert(process->unix_process);
     514          27 :   return process->unix_process;
     515             : }
     516             : #else /* defined(_WIN32) */
     517             : /** Get the internal handle for Windows backend. */
     518             : process_win32_t *
     519             : process_get_win32_process(const process_t *process)
     520             : {
     521             :   tor_assert(process);
     522             :   tor_assert(process->win32_process);
     523             :   return process->win32_process;
     524             : }
     525             : #endif /* !defined(_WIN32) */
     526             : 
     527             : /** Write <b>size</b> bytes of <b>data</b> to the given process's standard
     528             :  * input. */
     529             : void
     530           6 : process_write(process_t *process,
     531             :               const uint8_t *data, size_t size)
     532             : {
     533           6 :   tor_assert(process);
     534           6 :   tor_assert(data);
     535             : 
     536           6 :   buf_add(process->stdin_buffer, (char *)data, size);
     537           6 :   process_write_stdin(process, process->stdin_buffer);
     538           6 : }
     539             : 
     540             : /** As tor_vsnprintf(), but write the data to the given process's standard
     541             :  * input. */
     542             : void
     543           5 : process_vprintf(process_t *process,
     544             :                 const char *format, va_list args)
     545             : {
     546           5 :   tor_assert(process);
     547           5 :   tor_assert(format);
     548             : 
     549           5 :   int size;
     550           5 :   char *data;
     551             : 
     552           5 :   size = tor_vasprintf(&data, format, args);
     553           5 :   tor_assert(data != NULL);
     554           5 :   process_write(process, (uint8_t *)data, size);
     555           5 :   tor_free(data);
     556           5 : }
     557             : 
     558             : /** As tor_snprintf(), but write the data to the given process's standard
     559             :  * input. */
     560             : void
     561           5 : process_printf(process_t *process,
     562             :                const char *format, ...)
     563             : {
     564           5 :   tor_assert(process);
     565           5 :   tor_assert(format);
     566             : 
     567           5 :   va_list ap;
     568           5 :   va_start(ap, format);
     569           5 :   process_vprintf(process, format, ap);
     570           5 :   va_end(ap);
     571           5 : }
     572             : 
     573             : /** This function is called by the Process backend when a given process have
     574             :  * data that is ready to be read from the child process's standard output
     575             :  * handle. */
     576             : void
     577          20 : process_notify_event_stdout(process_t *process)
     578             : {
     579          20 :   tor_assert(process);
     580             : 
     581          20 :   int ret;
     582          20 :   ret = process_read_stdout(process, process->stdout_buffer);
     583             : 
     584          20 :   if (ret > 0)
     585          18 :     process_read_data(process,
     586          18 :                       process->stdout_buffer,
     587             :                       process->stdout_read_callback);
     588          20 : }
     589             : 
     590             : /** This function is called by the Process backend when a given process have
     591             :  * data that is ready to be read from the child process's standard error
     592             :  * handle. */
     593             : void
     594          12 : process_notify_event_stderr(process_t *process)
     595             : {
     596          12 :   tor_assert(process);
     597             : 
     598          12 :   int ret;
     599          12 :   ret = process_read_stderr(process, process->stderr_buffer);
     600             : 
     601          12 :   if (ret > 0)
     602          10 :     process_read_data(process,
     603          10 :                       process->stderr_buffer,
     604             :                       process->stderr_read_callback);
     605          12 : }
     606             : 
     607             : /** This function is called by the Process backend when a given process is
     608             :  * allowed to begin writing data to the standard input of the child process. */
     609             : void
     610           3 : process_notify_event_stdin(process_t *process)
     611             : {
     612           3 :   tor_assert(process);
     613             : 
     614           3 :   process_write_stdin(process, process->stdin_buffer);
     615           3 : }
     616             : 
     617             : /** This function is called by the Process backend when a given process have
     618             :  * terminated. The exit status code is passed in <b>exit_code</b>. We mark the
     619             :  * process as no longer running and calls the <b>exit_callback</b> with
     620             :  * information about the process termination. The given <b>process</b> is
     621             :  * free'd iff the exit_callback returns true. */
     622             : void
     623           4 : process_notify_event_exit(process_t *process, process_exit_code_t exit_code)
     624             : {
     625           4 :   tor_assert(process);
     626             : 
     627           4 :   log_debug(LD_PROCESS,
     628             :             "Process terminated with exit code: %"PRIu64, exit_code);
     629             : 
     630             :   /* Update our state. */
     631           4 :   process_set_status(process, PROCESS_STATUS_NOT_RUNNING);
     632           4 :   process->exit_code = exit_code;
     633             : 
     634             :   /* Call our exit callback, if it exists. */
     635           4 :   bool free_process_handle = false;
     636             : 
     637             :   /* The exit callback will tell us if we should process_free() our handle. */
     638           4 :   if (process->exit_callback)
     639           4 :     free_process_handle = process->exit_callback(process, exit_code);
     640             : 
     641           4 :   if (free_process_handle)
     642           0 :     process_free(process);
     643           4 : }
     644             : 
     645             : /** This function is called whenever the Process backend have notified us that
     646             :  * there is data to be read from its standard out handle. Returns the number of
     647             :  * bytes that have been put into the given buffer. */
     648           5 : MOCK_IMPL(STATIC int, process_read_stdout, (process_t *process, buf_t *buffer))
     649             : {
     650           5 :   tor_assert(process);
     651           5 :   tor_assert(buffer);
     652             : 
     653             : #ifndef _WIN32
     654           5 :   return process_unix_read_stdout(process, buffer);
     655             : #else
     656             :   return process_win32_read_stdout(process, buffer);
     657             : #endif
     658             : }
     659             : 
     660             : /** This function is called whenever the Process backend have notified us that
     661             :  * there is data to be read from its standard error handle. Returns the number
     662             :  * of bytes that have been put into the given buffer. */
     663           5 : MOCK_IMPL(STATIC int, process_read_stderr, (process_t *process, buf_t *buffer))
     664             : {
     665           5 :   tor_assert(process);
     666           5 :   tor_assert(buffer);
     667             : 
     668             : #ifndef _WIN32
     669           5 :   return process_unix_read_stderr(process, buffer);
     670             : #else
     671             :   return process_win32_read_stderr(process, buffer);
     672             : #endif
     673             : }
     674             : 
     675             : /** This function calls the backend function for the given process whenever
     676             :  * there is data to be written to the backends' file handles. */
     677           5 : MOCK_IMPL(STATIC void, process_write_stdin,
     678             :           (process_t *process, buf_t *buffer))
     679             : {
     680           5 :   tor_assert(process);
     681           5 :   tor_assert(buffer);
     682             : 
     683             : #ifndef _WIN32
     684           5 :   process_unix_write(process, buffer);
     685             : #else
     686             :   process_win32_write(process, buffer);
     687             : #endif
     688           5 : }
     689             : 
     690             : /** This function calls the protocol handlers based on the value of
     691             :  * <b>process_get_protocol(process)</b>. Currently we call
     692             :  * <b>process_read_buffer()</b> for <b>PROCESS_PROTOCOL_RAW</b> and
     693             :  * <b>process_read_lines()</b> for <b>PROCESS_PROTOCOL_LINE</b>. */
     694             : STATIC void
     695          28 : process_read_data(process_t *process,
     696             :                   buf_t *buffer,
     697             :                   process_read_callback_t callback)
     698             : {
     699          28 :   tor_assert(process);
     700          28 :   tor_assert(buffer);
     701             : 
     702          28 :   switch (process_get_protocol(process)) {
     703           4 :   case PROCESS_PROTOCOL_RAW:
     704           4 :     process_read_buffer(process, buffer, callback);
     705           4 :     break;
     706          24 :   case PROCESS_PROTOCOL_LINE:
     707          24 :     process_read_lines(process, buffer, callback);
     708          24 :     break;
     709           0 :   default:
     710             :     /* LCOV_EXCL_START */
     711             :     tor_assert_unreached();
     712             :     return;
     713             :     /* LCOV_EXCL_STOP */
     714             :   }
     715          28 : }
     716             : 
     717             : /** This function takes the content of the given <b>buffer</b> and passes it to
     718             :  * the given <b>callback</b> function, but ensures that an additional zero byte
     719             :  * is added to the end of the data such that the given callback implementation
     720             :  * can threat the content as a ASCIIZ string. */
     721             : STATIC void
     722           4 : process_read_buffer(process_t *process,
     723             :                     buf_t *buffer,
     724             :                     process_read_callback_t callback)
     725             : {
     726           4 :   tor_assert(process);
     727           4 :   tor_assert(buffer);
     728             : 
     729           4 :   const size_t size = buf_datalen(buffer);
     730             : 
     731             :   /* We allocate an extra byte for the zero byte in the end. */
     732           4 :   char *data = tor_malloc_zero(size + 1);
     733             : 
     734           4 :   buf_get_bytes(buffer, data, size);
     735           4 :   log_debug(LD_PROCESS, "Read data from process");
     736             : 
     737           4 :   if (callback)
     738           4 :     callback(process, data, size);
     739             : 
     740           4 :   tor_free(data);
     741           4 : }
     742             : 
     743             : /** This function tries to extract complete lines from the given <b>buffer</b>
     744             :  * and calls the given <b>callback</b> function whenever it has a complete
     745             :  * line. Before calling <b>callback</b> we remove the trailing "\n" or "\r\n"
     746             :  * from the line. If we are unable to extract a complete line we leave the data
     747             :  * in the buffer for next call. */
     748             : STATIC void
     749          24 : process_read_lines(process_t *process,
     750             :                    buf_t *buffer,
     751             :                    process_read_callback_t callback)
     752             : {
     753          24 :   tor_assert(process);
     754          24 :   tor_assert(buffer);
     755             : 
     756          24 :   const size_t size = buf_datalen(buffer) + 1;
     757          24 :   size_t line_size = 0;
     758          24 :   char *data = tor_malloc_zero(size);
     759          68 :   int ret;
     760             : 
     761         112 :   while (true) {
     762          68 :     line_size = size;
     763          68 :     ret = buf_get_line(buffer, data, &line_size);
     764             : 
     765             :     /* A complete line should always be smaller than the size of our
     766             :      * buffer. */
     767          68 :     tor_assert(ret != -1);
     768             : 
     769             :     /* Remove \n from the end of the line. */
     770          68 :     if (line_size >= 1 && data[line_size - 1] == '\n') {
     771          44 :       data[line_size - 1] = '\0';
     772          44 :       --line_size;
     773             :     }
     774             : 
     775             :     /* Remove \r from the end of the line. */
     776          68 :     if (line_size >= 1 && data[line_size - 1] == '\r') {
     777           4 :       data[line_size - 1] = '\0';
     778           4 :       --line_size;
     779             :     }
     780             : 
     781          68 :     if (ret == 1) {
     782          44 :       log_debug(LD_PROCESS, "Read line from process: \"%s\"", data);
     783             : 
     784          44 :       if (callback)
     785          44 :         callback(process, data, line_size);
     786             : 
     787             :       /* We have read a whole line, let's see if there is more lines to read.
     788             :        * */
     789          44 :       continue;
     790             :     }
     791             : 
     792             :     /* No complete line for us to read. We are done for now. */
     793          24 :     tor_assert_nonfatal(ret == 0);
     794          24 :     break;
     795             :   }
     796             : 
     797          24 :   tor_free(data);
     798          24 : }

Generated by: LCOV version 1.14