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 : }
|