GNUnet 0.26.2-32-gd298f7855
 
Loading...
Searching...
No Matches
os_process.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2011, 2026 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "disk.h"
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "util-os-process", __VA_ARGS__)
32
33#define LOG_STRERROR(kind, syscall) \
34 GNUNET_log_from_strerror (kind, "util-os-process", syscall)
35
36#define LOG_STRERROR_FILE(kind, syscall, filename) \
37 GNUNET_log_from_strerror_file (kind, "util-os-process", syscall, \
38 filename)
39
40#define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE"
41
42
65
66
71{
75 char *key;
76
80 char *value;
81};
82
83
85{
89 pid_t pid;
90
96
102
106 unsigned int map_size;
107
112
116 unsigned int envs_size;
117
122
126 char *filename;
127
131 char **argv;
132
137
141 unsigned long exit_code;
142};
143
144
149
154
159
160
166static void
167shutdown_pch (void *cls)
168{
169 struct GNUNET_DISK_FileHandle *control_pipe = cls;
170
172 pch = NULL;
173 GNUNET_DISK_file_close (control_pipe);
174 control_pipe = NULL;
175}
176
177
183static void
185{
186 struct GNUNET_DISK_FileHandle *control_pipe = cls;
187 char sig;
188 ssize_t ret;
189
190 pch = NULL;
191 ret = GNUNET_DISK_file_read (control_pipe,
192 &sig,
193 sizeof(sig));
194 if (sizeof(sig) != ret)
195 {
196 if (-1 == ret)
198 "GNUNET_DISK_file_read");
200 "Closing control pipe\n");
201 GNUNET_DISK_file_close (control_pipe);
203 spch = NULL;
204 return;
205 }
207 "Got control code %d from parent via pipe\n",
208 sig);
210 control_pipe,
212 control_pipe);
213 GNUNET_SIGNAL_raise ((int) sig);
214}
215
216
217void
219{
220 const char *env_buf;
221 char *env_buf_end;
222 struct GNUNET_DISK_FileHandle *control_pipe;
223 uint64_t pipe_fd;
224
225 if (NULL != pch)
226 {
227 /* already done, we've been called twice... */
228 GNUNET_break (0);
229 return;
230 }
231 env_buf = getenv (GNUNET_OS_CONTROL_PIPE);
232 if ( (NULL == env_buf) ||
233 (strlen (env_buf) <= 0) )
234 {
236 "Not installing a handler because $%s is empty\n",
238 setenv (GNUNET_OS_CONTROL_PIPE, "", 1);
239 return;
240 }
241 errno = 0;
242 pipe_fd = strtoull (env_buf,
243 &env_buf_end,
244 16);
245 if ( (0 != errno) ||
246 (env_buf == env_buf_end) )
247 {
249 "strtoull",
250 env_buf);
252 "",
253 1);
254 return;
255 }
256 if (pipe_fd >= FD_SETSIZE)
257 {
259 "GNUNET_OS_CONTROL_PIPE `%s' contains garbage?\n",
260 env_buf);
262 "",
263 1);
264 return;
265 }
266
267 control_pipe = GNUNET_DISK_get_handle_from_int_fd ((int) pipe_fd);
268 if (NULL == control_pipe)
269 {
271 "open",
272 env_buf);
274 "",
275 1);
276 return;
277 }
279 "Adding parent control handler pipe `%s' to the scheduler\n",
280 env_buf);
282 control_pipe,
284 control_pipe);
286 control_pipe);
288 "",
289 1);
290}
291
292
293struct GNUNET_Process *
299
300
303 int sig)
304{
305 if (NULL != proc->control_pipe)
306 {
307 char csig = (char) sig;
308 ssize_t iret;
309
311 "Sending signal %d to pid: %u via pipe\n",
312 sig,
313 proc->pid);
315 &csig,
316 sizeof(csig));
317 if (sizeof(csig) == iret)
318 return GNUNET_OK;
319 }
320 /* pipe failed or non-existent, try other methods */
322 "Sending signal %d to pid: %u via system call\n",
323 sig,
324 proc->pid);
325 {
326 int ret;
327
328 ret = kill (proc->pid,
329 sig);
330 if (0 != ret)
331 {
333 "kill");
334 }
335 return (0 == ret)
336 ? GNUNET_OK
338 }
339}
340
341
342pid_t
344{
345 return proc->pid;
346}
347
348
349void
351{
352 if (NULL != proc->control_pipe)
354 GNUNET_free (proc->filename);
355 for (unsigned int i = 0; i < proc->envs_size; i++)
356 {
357 GNUNET_free (proc->envs[i].key);
358 GNUNET_free (proc->envs[i].value);
359 }
360 GNUNET_free (proc->envs);
361 for (unsigned int i = 0; i < proc->map_size; i++)
362 {
363 int pfd = proc->map[i].parent_fd;
364
365 if (-1 == pfd)
366 continue;
367 GNUNET_break (0 == close (pfd));
368 }
369 GNUNET_free (proc->map);
370 for (unsigned int i = 0; NULL != proc->argv[i]; i++)
371 GNUNET_free (proc->argv[i]);
372 GNUNET_free (proc->argv);
373 GNUNET_free (proc);
374}
375
376
384static int
385safe_dup2 (int oldfd,
386 int newfd)
387{
388 int ret;
389
390 while (1)
391 {
392 ret = dup2 (oldfd,
393 newfd);
394 if (-1 != ret)
395 break;
396 if ( (EBADF == errno) ||
397 (EINVAL == errno) ||
398 (EMFILE == errno) )
399 break;
400 /* should be EBUSY/EINTR, so try again */
402 "dup2");
403 }
404 return ret;
405}
406
407
416open_dev_null (int target_fd,
417 int flags)
418{
419 int fd;
420
421 fd = open ("/dev/null",
422 flags);
423 if (-1 == fd)
424 {
426 "open",
427 "/dev/null");
428 return GNUNET_SYSERR;
429 }
430 if (fd == target_fd)
431 return GNUNET_OK;
432 if (-1 == dup2 (fd,
433 target_fd))
434 {
436 "dup2");
437 GNUNET_break (0 == close (fd));
438 return GNUNET_SYSERR;
439 }
440 GNUNET_break (0 == close (fd));
441 return GNUNET_OK;
442}
443
444
445struct GNUNET_Process *
447{
448 struct GNUNET_Process *p;
449
450 p = GNUNET_new (struct GNUNET_Process);
451 p->pid = -1;
453 return p;
454}
455
456
465{
466 int flags;
467
468 flags = fcntl (fd,
469 F_GETFD);
470 if (flags == -1)
471 {
473 "fcntl(F_GETFD)");
474 return GNUNET_SYSERR;
475 }
476
477 flags &= ~FD_CLOEXEC;
478
479 if (-1 ==
480 fcntl (fd,
481 F_SETFD,
482 flags))
483 {
485 "fcntl(F_SETFD)");
486 return GNUNET_SYSERR;
487 }
488 return GNUNET_OK;
489}
490
491
500{
501 int flags;
502
503 flags = fcntl (fd,
504 F_GETFD);
505 if (flags == -1)
506 {
508 "fcntl(F_GETFD)");
509 return GNUNET_SYSERR;
510 }
511
512 flags |= FD_CLOEXEC;
513
514 if (-1 ==
515 fcntl (fd,
516 F_SETFD,
517 flags))
518 {
520 "fcntl(F_SETFD)");
521 return GNUNET_SYSERR;
522 }
523 return GNUNET_OK;
524}
525
526
539 int fd,
540 int flags)
541{
542 for (unsigned int i=0; i<proc->map_size; i++)
543 {
544 struct ProcessFileMapEntry *me = &proc->map[i];
545
546 if (fd == me->target_fd)
547 {
548 if (fd !=
549 safe_dup2 (me->parent_fd,
550 fd))
551 return GNUNET_SYSERR;
552 GNUNET_break (0 == close (me->parent_fd));
553 me->parent_fd = -1;
554 return GNUNET_OK;
555 }
556 }
557 return open_dev_null (fd,
558 flags);
559}
560
561
564{
565 pid_t ret;
566 int childpipe_read_fd;
567
568 if (-1 != proc->pid)
569 {
570 GNUNET_break (0);
571 return GNUNET_SYSERR;
572 }
573 if (NULL == proc->filename)
574 {
575 GNUNET_break (0);
576 return GNUNET_SYSERR;
577 }
578
580 {
581 struct GNUNET_DISK_PipeHandle *childpipe;
582 struct GNUNET_DISK_FileHandle *childpipe_read;
583 int dup_childpipe_read_fd = -1;
584
586 if (NULL == childpipe)
587 {
588 GNUNET_break (0);
589 return GNUNET_SYSERR;
590 }
591 childpipe_read =
594 proc->control_pipe =
597 GNUNET_DISK_pipe_close (childpipe);
598 if ( (NULL == childpipe_read) ||
599 (NULL == proc->control_pipe) ||
600 (GNUNET_OK !=
601 GNUNET_DISK_internal_file_handle_ (childpipe_read,
602 &childpipe_read_fd)) ||
603 (-1 == (dup_childpipe_read_fd = dup (childpipe_read_fd))) )
604 {
605 GNUNET_break (0);
606 if (NULL != childpipe_read)
607 GNUNET_DISK_file_close (childpipe_read);
608 if (NULL != proc->control_pipe)
609 {
611 proc->control_pipe = NULL;
612 }
613 return GNUNET_SYSERR;
614 }
615 childpipe_read_fd = dup_childpipe_read_fd;
616 GNUNET_DISK_file_close (childpipe_read);
617 }
618 else
619 {
620 childpipe_read_fd = -1;
621 }
622
623 {
624 /* Make sure none of the parent_fds conflict with the target_fds in the client process */
625 unsigned int max_fd = 3; /* never use stdin/stdout/stderr */
626 unsigned int pos;
627
628 for (unsigned int i=0; i<proc->map_size; i++)
629 {
630 struct ProcessFileMapEntry *me = &proc->map[i];
631
632 max_fd = GNUNET_MAX (max_fd,
633 me->target_fd);
634 }
635 pos = max_fd + 1;
636 for (unsigned int i=0; i<proc->map_size; i++)
637 {
638 struct ProcessFileMapEntry *me = &proc->map[i];
639
640 if (me->parent_fd < pos)
641 {
642 if (me->target_fd == me->parent_fd)
643 {
644 /* same FD, so no conflict, but make sure FD is not closed
645 on exec() */
646 clear_cloexec (me->parent_fd);
647 }
648 else
649 {
650 int dst;
651
652 /* search for FD that is not yet open */
653 while (-1 !=
654 fcntl (pos,
655 F_GETFD))
656 pos++;
657 while (1)
658 {
659 dst = dup2 (me->parent_fd,
660 pos);
661 if (-1 != dst)
662 break;
663 if ( (EBADF == errno) ||
664 (EINVAL == errno) ||
665 (EMFILE == errno) )
666 {
667 GNUNET_break (0);
668 return GNUNET_SYSERR;
669 }
670 /* leaves interrupt/busy, try again */
671 }
672 GNUNET_break (0 == close (me->parent_fd));
673 me->parent_fd = dst;
674 }
675 }
676 }
677 }
678
679 ret = fork ();
680 if (-1 == ret)
681 {
682 int eno = errno;
683
685 "fork");
686 if (NULL != proc->control_pipe)
687 {
689 proc->control_pipe = NULL;
690 }
691 if (0 <= childpipe_read_fd)
692 GNUNET_break (0 == close (childpipe_read_fd));
693 errno = eno;
694 return GNUNET_SYSERR;
695 }
696 if (0 != ret)
697 {
698 proc->pid = ret;
699 if (0 <= childpipe_read_fd)
700 GNUNET_break (0 == close (childpipe_read_fd));
701 for (unsigned int i=0; i<proc->map_size; i++)
702 {
703 struct ProcessFileMapEntry *me = &proc->map[i];
704
705 GNUNET_break (0 ==
706 close (me->parent_fd));
707 me->parent_fd = -1;
708 }
709 return GNUNET_OK;
710 }
711
712 /* in child process! */
713
714 /* deploy control pipe */
715 if (0 <= childpipe_read_fd)
716 {
717 char fdbuf[100];
718
720 snprintf (fdbuf,
721 sizeof (fdbuf),
722 "%x",
723 childpipe_read_fd);
724 GNUNET_assert (0 ==
726 fdbuf,
727 1));
728 }
729 else
730 {
731 GNUNET_assert (0 ==
732 unsetenv (GNUNET_OS_CONTROL_PIPE));
733 }
734
735 /* map stdin/stdout/stderr */
736 if (0 == (proc->std_inheritance & GNUNET_OS_INHERIT_STD_IN))
737 {
739 map_std (proc,
740 STDIN_FILENO,
741 O_RDONLY));
742 }
744 {
746 map_std (proc,
747 STDOUT_FILENO,
748 O_WRONLY));
749 }
751 {
753 map_std (proc,
754 STDERR_FILENO,
755 O_WRONLY));
756 }
757
758 /* map all other file descriptors */
759 {
760 char *fdnames = GNUNET_strdup ("");
761 unsigned int total_lfds = 0;
762
763 for (unsigned int i=0; i<proc->map_size; i++)
764 {
765 struct ProcessFileMapEntry *me = &proc->map[i];
766
767 if (-1 == me->parent_fd)
768 continue; /* already taken care of */
769 if (-1 == me->target_fd)
770 {
771 me->target_fd = dup (me->parent_fd);
772 GNUNET_assert (-1 != me->target_fd);
773 }
774 else if (me->parent_fd != me->target_fd)
775 {
776 GNUNET_assert (me->target_fd ==
777 safe_dup2 (me->parent_fd,
778 me->target_fd));
779 }
780 GNUNET_assert (0 == close (me->parent_fd));
781 me->parent_fd = -1;
783 set_cloexec (me->target_fd));
784 if (me->systemd_listen_socket)
785 {
786 char *tmp;
787
788 GNUNET_asprintf (&tmp,
789 "%s:%d",
790 fdnames,
791 me->target_fd);
792 GNUNET_free (fdnames);
793 fdnames = tmp;
794 total_lfds++;
795 }
796 }
797 if (0 != total_lfds)
798 {
799 char fds[16];
800
801 GNUNET_snprintf (fds,
802 sizeof(fds),
803 "%u",
804 total_lfds);
805 GNUNET_assert (0 ==
806 setenv ("LISTEN_FDS",
807 fds,
808 1));
809 GNUNET_assert (0 ==
810 setenv ("LISTEN_FDNAMES",
811 fdnames + 1, /* skip leading ':' */
812 1));
813 }
814 GNUNET_free (fdnames);
815 }
816
817 /* setup environment */
818 for (unsigned int i=0; i<proc->envs_size; i++)
819 {
820 struct EnviEntry *ee = &proc->envs[i];
821
822 if (NULL == ee->value)
823 GNUNET_assert (0 ==
824 unsetenv (ee->key));
825 else
826 GNUNET_assert (0 ==
827 setenv (ee->key,
828 ee->value,
829 1));
830 }
831
832 /* finally execute */
833 execvp (proc->filename,
834 proc->argv);
836 "execvp",
837 proc->filename);
838 _exit (1);
839}
840
841
844 struct GNUNET_Process *p,
845 const char *filename,
846 const char **argv)
847{
848 const char *av;
849 int argc;
850
851 if (GNUNET_SYSERR ==
853 GNUNET_NO,
854 NULL))
855 return GNUNET_SYSERR; /* not executable */
856 GNUNET_assert (NULL == p->argv);
858 argc = 0;
859 while (NULL != argv[argc])
860 argc++;
861 p->argv = GNUNET_new_array (argc + 1,
862 char *);
863 for (argc = 0; NULL != argv[argc]; argc++)
864 p->argv[argc] = GNUNET_strdup (argv[argc]);
865 return GNUNET_OK;
866}
867
868
871 struct GNUNET_Process *p,
872 const char *filename,
873 va_list va)
874{
875 va_list ap;
876 const char *av;
877 int argc;
878
879 if (GNUNET_SYSERR ==
881 GNUNET_NO,
882 NULL))
883 return GNUNET_SYSERR; /* not executable */
884 GNUNET_assert (NULL == p->argv);
886 argc = 0;
887 va_copy (ap,
888 va);
889 while (NULL != va_arg (ap,
890 const char *))
891 argc++;
892 va_end (ap);
893 p->argv = GNUNET_new_array (argc + 1,
894 char *);
895 argc = 0;
896 va_copy (ap,
897 va);
898 while (NULL != (av = va_arg (ap,
899 const char *)))
900 p->argv[argc++] = GNUNET_strdup (av);
901 va_end (ap);
902 return GNUNET_OK;
903}
904
905
908 const char *filename,
909 ...)
910{
912 va_list ap;
913
914 va_start (ap,
915 filename);
917 filename,
918 ap);
919 va_end (ap);
920 return ret;
921}
922
923
926 const char *command)
927{
928 char *cmd = GNUNET_strdup (command);
929 size_t len = strlen (command);
930 size_t cnt = 1;
931 size_t start = 0;
932 bool quote_on = false;
933 size_t i;
934 size_t skip = 0;
935
936 GNUNET_assert (NULL == p->argv);
937 for (i=0; i<len; i++)
938 {
939 char c = cmd[i];
940
941 switch (c)
942 {
943 case '"':
944 quote_on = ! quote_on;
945 break;
946 case '\\':
947 i++;
948 break;
949 case ' ':
950 if (! quote_on)
951 cnt++;
952 while (' ' == cmd[i + 1])
953 i++;
954 break;
955 }
956 }
957
958 p->argv = GNUNET_new_array (cnt + 1,
959 char *);
960 cnt = 0;
961 for (i=0; i<len; i++)
962 {
963 char c = cmd[i];
964
965 switch (c)
966 {
967 case '"':
968 quote_on = ! quote_on;
969 skip++;
970 break;
971 case ' ':
972 if ( (! quote_on) &&
973 (i != start) )
974 {
975 p->argv[cnt] = GNUNET_strndup (&cmd[start],
976 i - start - skip);
977 cnt++;
978 skip = 0;
979 }
980 while (' ' == cmd[i + 1])
981 i++;
982 if (! quote_on)
983 start = i;
984 break;
985 case '\\':
986 i++;
987 skip++;
988 cmd[i - skip] = cmd[i];
989 break;
990 default:
991 cmd[i - skip] = c;
992 break;
993 }
994 }
995 if (i != start)
996 p->argv[cnt] = GNUNET_strndup (&cmd[start],
997 i - start);
998 GNUNET_free (cmd);
999 if (quote_on)
1000 {
1002 "Cmd `%s' has imbalanced quotes\n",
1003 cmd);
1004 }
1005 if (NULL == p->argv[0])
1006 {
1008 "Empty command specified, cannot execute\n");
1009 return GNUNET_SYSERR;
1010 }
1011 if (GNUNET_SYSERR ==
1013 GNUNET_NO,
1014 NULL))
1015 {
1017 "Specified binary `%s' is not executable\n",
1018 p->argv[0]);
1019 return GNUNET_SYSERR;
1020 }
1021 p->filename = GNUNET_strdup (p->argv[0]);
1022 return GNUNET_OK;
1023}
1024
1025
1028 struct GNUNET_Process *proc,
1029 unsigned int num_options,
1030 const struct GNUNET_ProcessOptionValue options[])
1031{
1032 for (unsigned int i=0; i<num_options; i++)
1033 {
1034 const struct GNUNET_ProcessOptionValue *ov = &options[i];
1035
1036 switch (ov->option)
1037 {
1039 return GNUNET_OK;
1042 continue;
1044 {
1045 struct EnviEntry ee = {
1047 };
1048
1049 if (NULL != ov->details.set_environment.value)
1052 proc->envs_size,
1053 ee);
1054 }
1055 continue;
1057 {
1058 struct ProcessFileMapEntry pme = {
1060 .parent_fd = ov->details.inherit_fd.parent_fd
1061 };
1062
1063 GNUNET_array_append (proc->map,
1064 proc->map_size,
1065 pme);
1066 }
1067 continue;
1069 {
1070 struct ProcessFileMapEntry pme = {
1071 .target_fd = -1, /* any */
1072 .parent_fd = ov->details.inherit_fd.parent_fd,
1073 .systemd_listen_socket = true
1074 };
1075
1076 GNUNET_array_append (proc->map,
1077 proc->map_size,
1078 pme);
1079 }
1080 continue;
1081 }
1082 GNUNET_break (0);
1083 return GNUNET_SYSERR;
1084 }
1085 return GNUNET_OK;
1086}
1087
1088
1091 bool blocking,
1093 unsigned long *code)
1094{
1095 pid_t ret;
1096 int status;
1097
1098 if (-1 == proc->pid)
1099 {
1100 if (NULL != type)
1101 *type = proc->exit_type;
1102 if (NULL != code)
1103 *code = proc->exit_code;
1104 return GNUNET_OK;
1105 }
1106 while ( (proc->pid !=
1107 (ret = waitpid (proc->pid,
1108 &status,
1109 blocking ? 0 : WNOHANG))) &&
1110 (EINTR == errno) )
1111 ;
1112 if (0 == ret)
1113 {
1114 if (NULL != type)
1116 if (NULL != code)
1117 *code = 0;
1118 return GNUNET_NO;
1119 }
1120#ifdef WIFCONTINUED
1121 if ( (proc->pid == ret) &&
1122 (WIFCONTINUED (status)) )
1123 {
1124 if (NULL != type)
1126 if (NULL != code)
1127 *code = 0;
1128 return GNUNET_NO;
1129 }
1130#endif
1131 if (proc->pid != ret)
1132 {
1134 "waitpid");
1135 return GNUNET_SYSERR;
1136 }
1137 /* process did exit! */
1138 proc->pid = -1;
1139 if (WIFEXITED (status))
1140 {
1142 proc->exit_code = WEXITSTATUS (status);
1143 }
1144 else if (WIFSIGNALED (status))
1145 {
1147 proc->exit_code = WTERMSIG (status);
1148 }
1149 else if (WIFSTOPPED (status))
1150 {
1152 proc->exit_code = WSTOPSIG (status);
1153 }
1154 else
1155 {
1157 proc->exit_code = 0;
1158 }
1159 if (NULL != type)
1160 *type = proc->exit_type;
1161 if (NULL != code)
1162 *code = proc->exit_code;
1163 return GNUNET_OK;
1164}
1165
1166
1167/* end of os_process.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
enum GNUNET_GenericReturnValue GNUNET_DISK_internal_file_handle_(const struct GNUNET_DISK_FileHandle *fh, int *dst)
Retrieve OS file handle.
Definition disk.c:1719
Internal DISK related helper functions.
char * getenv()
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static char * filename
static uint32_t type
Type string converted to DNS type value.
static int status
The program status; 0 for success.
Definition gnunet-nse.c:39
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_detach_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Detaches one of the ends from the pipe.
Definition disk.c:1643
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition disk.c:745
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition disk.c:1523
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition disk.c:1670
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1386
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition disk.c:1409
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition disk.c:704
@ GNUNET_DISK_PF_NONE
No special options, use non-blocking read/write operations.
@ GNUNET_DISK_PIPE_END_WRITE
The writing-end of a pipe.
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_OS_InheritStdioFlags
Flags that determine which of the standard streams should be inherited by the child process.
void GNUNET_process_install_parent_control_handler()
Connects this process to its parent via pipe; essentially, the parent control handler will read signa...
Definition os_process.c:218
struct GNUNET_Process * GNUNET_process_create()
Create a process handle.
Definition os_process.c:446
enum GNUNET_GenericReturnValue GNUNET_process_set_command(struct GNUNET_Process *p, const char *command)
Set the command to start a process.
Definition os_process.c:925
enum GNUNET_GenericReturnValue GNUNET_process_set_command_ap(struct GNUNET_Process *p, const char *filename, va_list va)
Set the command to start a process.
Definition os_process.c:870
enum GNUNET_GenericReturnValue GNUNET_process_wait(struct GNUNET_Process *proc, bool blocking, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Wait for a process to terminate.
enum GNUNET_GenericReturnValue GNUNET_process_set_options_(struct GNUNET_Process *proc, unsigned int num_options, const struct GNUNET_ProcessOptionValue options[])
Set the requested options for the process.
void GNUNET_process_destroy(struct GNUNET_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition os_process.c:350
enum GNUNET_GenericReturnValue GNUNET_process_start(struct GNUNET_Process *proc)
Start a process.
Definition os_process.c:563
enum GNUNET_GenericReturnValue GNUNET_process_set_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command to start a process.
Definition os_process.c:907
struct GNUNET_Process * GNUNET_process_current()
Get process structure for current process.
Definition os_process.c:294
GNUNET_OS_ProcessStatusType
Process status types.
enum GNUNET_GenericReturnValue GNUNET_process_set_command_argv(struct GNUNET_Process *p, const char *filename, const char **argv)
Set the command to start a process.
Definition os_process.c:843
enum GNUNET_GenericReturnValue GNUNET_OS_check_helper_binary(const char *binary, bool check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
pid_t GNUNET_process_get_pid(const struct GNUNET_Process *proc)
Get the pid of the process in question.
Definition os_process.c:343
enum GNUNET_GenericReturnValue GNUNET_process_kill(struct GNUNET_Process *proc, int sig)
Sends a signal to the process.
Definition os_process.c:302
@ GNUNET_OS_INHERIT_STD_IN
When this flag is set, the child process will inherit stdin of the parent.
@ GNUNET_OS_INHERIT_STD_OUT
When this flag is set, the child process will inherit stdout of the parent.
@ GNUNET_OS_INHERIT_STD_ERR
When this flag is set, the child process will inherit stderr of the parent.
@ GNUNET_OS_USE_PIPE_CONTROL
Should a pipe be used to send signals to the child?
@ GNUNET_PROCESS_OPTION_INHERIT_FD
Option to inherit file descriptors.
@ GNUNET_PROCESS_OPTION_END
End of list of options.
@ GNUNET_PROCESS_OPTION_INHERIT_LSOCK
Option to inherit a listen socket systemd-style.
@ GNUNET_PROCESS_OPTION_SET_ENVIRONMENT
Option to set environment variables.
@ GNUNET_PROCESS_OPTION_STD_INHERITANCE
Option to set inheritance flags.
@ GNUNET_OS_PROCESS_SIGNALED
The process was killed by a signal.
@ GNUNET_OS_PROCESS_EXITED
The process exited with a return code.
@ GNUNET_OS_PROCESS_UNKNOWN
The process is not known to the OS (or at least not one of our children).
@ GNUNET_OS_PROCESS_RUNNING
The process is still running.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1667
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
void GNUNET_SIGNAL_raise(const int sig)
Raise the given signal by calling the installed signal handlers.
Definition signal.c:98
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_OS_CONTROL_PIPE
Definition os_process.c:40
static void parent_control_handler(void *cls)
This handler is called when there are control data to be read on the pipe.
Definition os_process.c:184
static enum GNUNET_GenericReturnValue set_cloexec(int fd)
Set the close-on-exec flag of fd.
Definition os_process.c:499
static struct GNUNET_Process current_process
Handle for 'this' process.
Definition os_process.c:148
static struct GNUNET_SCHEDULER_Task * pch
Handle for the parent_control_handler() Task.
Definition os_process.c:153
static int safe_dup2(int oldfd, int newfd)
Call dup2() in a way that races and interrupts are safely handled.
Definition os_process.c:385
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition os_process.c:36
static enum GNUNET_GenericReturnValue map_std(struct GNUNET_Process *proc, int fd, int flags)
Map the standard input/output/error file descriptor fd based on the mapping given in proc.
Definition os_process.c:538
static void shutdown_pch(void *cls)
This handler is called on shutdown to remove the pch.
Definition os_process.c:167
static struct GNUNET_SCHEDULER_Task * spch
Handle for the shutdown_pch() Task.
Definition os_process.c:158
#define LOG(kind,...)
Definition os_process.c:31
#define LOG_STRERROR(kind, syscall)
Definition os_process.c:33
static enum GNUNET_GenericReturnValue clear_cloexec(int fd)
Clear the close-on-exec flag of fd.
Definition os_process.c:464
static enum GNUNET_GenericReturnValue open_dev_null(int target_fd, int flags)
Open '/dev/null' and make the result the given file descriptor.
Definition os_process.c:416
Key-value pairs for setenv().
Definition os_process.c:71
char * value
Value of the environment variable.
Definition os_process.c:80
char * key
Environment key to use.
Definition os_process.c:75
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition disk.c:69
Possible options we can set for a process.
struct GNUNET_ProcessOptionValue::@34::@35 set_environment
Value of if option is GNUNET_PROCESS_OPTION_SET_ENVIRONMENT.
int target_fd
File descriptor in the target process.
const char * key
Name of the environment variable to set.
struct GNUNET_ProcessOptionValue::@34::@36 inherit_fd
Value of if option is GNUNET_PROCESS_OPTION_INHERIT_FD.
int parent_fd
File descriptor in the parent process (must be open!).
enum GNUNET_ProcessOption option
Type of the option being set.
const char * value
Value to set, NULL to clear.
union GNUNET_ProcessOptionValue::@34 details
Specific option value.
enum GNUNET_OS_InheritStdioFlags std_inheritance
Value of if option is GNUNET_PROCESS_OPTION_STD_INHERITANCE.
struct EnviEntry * envs
Environment variables to set in the target process.
Definition os_process.c:121
enum GNUNET_OS_ProcessStatusType exit_type
Runtime status of the process.
Definition os_process.c:136
unsigned int envs_size
Length of the envs.
Definition os_process.c:116
pid_t pid
PID of the process.
Definition os_process.c:89
enum GNUNET_OS_InheritStdioFlags std_inheritance
What to do with stdin/stdout/stderr unless already specified in the file map.
Definition os_process.c:101
struct ProcessFileMapEntry * map
Map of file descriptors to keep and dup2 for the new process.
Definition os_process.c:111
char * filename
Name of the binary to execute.
Definition os_process.c:126
char ** argv
Command-line arguments to pass, NULL-terminated.
Definition os_process.c:131
unsigned long exit_code
Exit status code of the process, interpretation depends on exit_type.
Definition os_process.c:141
unsigned int map_size
Length of the map.
Definition os_process.c:106
struct GNUNET_DISK_FileHandle * control_pipe
Pipe we use to signal the process.
Definition os_process.c:95
Entry in list of pending tasks.
Definition scheduler.c:141
Mapping of file descriptors of the current process to (desired) file descriptors of the child process...
Definition os_process.c:48
int parent_fd
Original file descriptor of the parent process.
Definition os_process.c:57
bool systemd_listen_socket
True if this descriptor should be passed in the style of a systemd listen socket with the respective ...
Definition os_process.c:63
int target_fd
File descriptor to be used in the target process, -1 if it does not matter.
Definition os_process.c:52