diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-06-13 08:35:01 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-06-13 08:35:01 +0000 |
commit | 8bbc25e641ce26ecd424ffa12dd4f2f1d8c60cd1 (patch) | |
tree | 9026409aa6980f99a121c29e751aabe41e7dcc85 /src/util/os_priority.c | |
parent | 1b081dce5a25bf612d6711662b06483b18069617 (diff) | |
download | gnunet-8bbc25e641ce26ecd424ffa12dd4f2f1d8c60cd1.tar.gz gnunet-8bbc25e641ce26ecd424ffa12dd4f2f1d8c60cd1.zip |
-fixing #2240, untested on W32
Diffstat (limited to 'src/util/os_priority.c')
-rw-r--r-- | src/util/os_priority.c | 577 |
1 files changed, 194 insertions, 383 deletions
diff --git a/src/util/os_priority.c b/src/util/os_priority.c index b8b1ba180..cafb1504c 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE" | 42 | #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE" |
43 | 43 | ||
44 | |||
44 | struct GNUNET_OS_Process | 45 | struct GNUNET_OS_Process |
45 | { | 46 | { |
46 | /** | 47 | /** |
@@ -541,6 +542,7 @@ child_wait_thread (void *arg) | |||
541 | } | 542 | } |
542 | #endif | 543 | #endif |
543 | 544 | ||
545 | |||
544 | /** | 546 | /** |
545 | * Set process priority | 547 | * Set process priority |
546 | * | 548 | * |
@@ -646,6 +648,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc, | |||
646 | return GNUNET_OK; | 648 | return GNUNET_OK; |
647 | } | 649 | } |
648 | 650 | ||
651 | |||
649 | #if MINGW | 652 | #if MINGW |
650 | static char * | 653 | static char * |
651 | CreateCustomEnvTable (char **vars) | 654 | CreateCustomEnvTable (char **vars) |
@@ -760,29 +763,40 @@ CreateCustomEnvTable (char **vars) | |||
760 | * @param pipe_control should a pipe be used to send signals to the child? | 763 | * @param pipe_control should a pipe be used to send signals to the child? |
761 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | 764 | * @param pipe_stdin pipe to use to send input to child process (or NULL) |
762 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | 765 | * @param pipe_stdout pipe to use to get output from child process (or NULL) |
766 | * @param lsocks array of listen sockets to dup systemd-style (or NULL); | ||
767 | * must be NULL on platforms where dup is not supported | ||
763 | * @param filename name of the binary | 768 | * @param filename name of the binary |
764 | * @param argv NULL-terminated array of arguments to the process | 769 | * @param argv NULL-terminated list of arguments to the process |
765 | * @return pointer to process structure of the new process, NULL on error | 770 | * @return process ID of the new process, -1 on error |
766 | */ | 771 | */ |
767 | struct GNUNET_OS_Process * | 772 | static struct GNUNET_OS_Process * |
768 | GNUNET_OS_start_process_vap (int pipe_control, | 773 | start_process (int pipe_control, |
769 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | 774 | struct GNUNET_DISK_PipeHandle *pipe_stdin, |
770 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | 775 | struct GNUNET_DISK_PipeHandle *pipe_stdout, |
771 | const char *filename, | 776 | const SOCKTYPE *lsocks, |
772 | char *const argv[]) | 777 | const char *filename, |
778 | char *const argv[]) | ||
773 | { | 779 | { |
774 | #ifndef MINGW | 780 | #ifndef MINGW |
775 | char *childpipename = NULL; | ||
776 | struct GNUNET_OS_Process *gnunet_proc = NULL; | ||
777 | pid_t ret; | 781 | pid_t ret; |
782 | char lpid[16]; | ||
783 | char fds[16]; | ||
784 | struct GNUNET_OS_Process *gnunet_proc = NULL; | ||
785 | char *childpipename = NULL; | ||
786 | int i; | ||
787 | int j; | ||
788 | int k; | ||
789 | int tgt; | ||
790 | int flags; | ||
791 | int *lscp; | ||
792 | unsigned int ls; | ||
778 | int fd_stdout_write; | 793 | int fd_stdout_write; |
779 | int fd_stdout_read; | 794 | int fd_stdout_read; |
780 | int fd_stdin_read; | 795 | int fd_stdin_read; |
781 | int fd_stdin_write; | 796 | int fd_stdin_write; |
782 | 797 | ||
783 | if ( (GNUNET_YES == pipe_control) && | 798 | if ( (GNUNET_YES == pipe_control) && |
784 | (GNUNET_OK != | 799 | (GNUNET_OK != npipe_setup (&childpipename)) ) |
785 | npipe_setup (&childpipename)) ) | ||
786 | return NULL; | 800 | return NULL; |
787 | if (pipe_stdout != NULL) | 801 | if (pipe_stdout != NULL) |
788 | { | 802 | { |
@@ -807,7 +821,15 @@ GNUNET_OS_start_process_vap (int pipe_control, | |||
807 | (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE), | 821 | (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE), |
808 | &fd_stdin_write, sizeof (int))); | 822 | &fd_stdin_write, sizeof (int))); |
809 | } | 823 | } |
810 | 824 | lscp = NULL; | |
825 | ls = 0; | ||
826 | if (lsocks != NULL) | ||
827 | { | ||
828 | i = 0; | ||
829 | while (-1 != (k = lsocks[i++])) | ||
830 | GNUNET_array_append (lscp, ls, k); | ||
831 | GNUNET_array_append (lscp, ls, -1); | ||
832 | } | ||
811 | ret = fork (); | 833 | ret = fork (); |
812 | if (-1 == ret) | 834 | if (-1 == ret) |
813 | { | 835 | { |
@@ -815,6 +837,7 @@ GNUNET_OS_start_process_vap (int pipe_control, | |||
815 | 837 | ||
816 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); | 838 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); |
817 | GNUNET_free_non_null (childpipename); | 839 | GNUNET_free_non_null (childpipename); |
840 | GNUNET_array_grow (lscp, ls, 0); | ||
818 | errno = eno; | 841 | errno = eno; |
819 | return NULL; | 842 | return NULL; |
820 | } | 843 | } |
@@ -822,7 +845,8 @@ GNUNET_OS_start_process_vap (int pipe_control, | |||
822 | { | 845 | { |
823 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | 846 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); |
824 | gnunet_proc->pid = ret; | 847 | gnunet_proc->pid = ret; |
825 | gnunet_proc->childpipename = childpipename; | 848 | gnunet_proc->childpipename = childpipename; |
849 | GNUNET_array_grow (lscp, ls, 0); | ||
826 | return gnunet_proc; | 850 | return gnunet_proc; |
827 | } | 851 | } |
828 | if (NULL != childpipename) | 852 | if (NULL != childpipename) |
@@ -837,7 +861,6 @@ GNUNET_OS_start_process_vap (int pipe_control, | |||
837 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); | 861 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); |
838 | GNUNET_break (0 == close (fd_stdout_write)); | 862 | GNUNET_break (0 == close (fd_stdout_write)); |
839 | } | 863 | } |
840 | |||
841 | if (pipe_stdin != NULL) | 864 | if (pipe_stdin != NULL) |
842 | { | 865 | { |
843 | 866 | ||
@@ -846,368 +869,6 @@ GNUNET_OS_start_process_vap (int pipe_control, | |||
846 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); | 869 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); |
847 | GNUNET_break (0 == close (fd_stdin_read)); | 870 | GNUNET_break (0 == close (fd_stdin_read)); |
848 | } | 871 | } |
849 | execvp (filename, argv); | ||
850 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); | ||
851 | _exit (1); | ||
852 | #else | ||
853 | char *childpipename = NULL; | ||
854 | struct GNUNET_OS_Process *gnunet_proc = NULL; | ||
855 | char *arg; | ||
856 | unsigned int cmdlen; | ||
857 | char *cmd, *idx; | ||
858 | STARTUPINFOW start; | ||
859 | PROCESS_INFORMATION proc; | ||
860 | int argc, arg_count; | ||
861 | HANDLE stdin_handle; | ||
862 | HANDLE stdout_handle; | ||
863 | struct GNUNET_DISK_FileHandle *control_pipe; | ||
864 | |||
865 | char path[MAX_PATH + 1]; | ||
866 | |||
867 | char *our_env[3] = { NULL, NULL, NULL }; | ||
868 | char *env_block = NULL; | ||
869 | char *pathbuf; | ||
870 | DWORD pathbuf_len, alloc_len; | ||
871 | char *self_prefix; | ||
872 | char *bindir; | ||
873 | char *libdir; | ||
874 | char *ptr; | ||
875 | char *non_const_filename; | ||
876 | char win_path[MAX_PATH + 1]; | ||
877 | wchar_t *wpath, *wcmd; | ||
878 | size_t wpath_len, wcmd_len; | ||
879 | long lRet; | ||
880 | |||
881 | /* Search in prefix dir (hopefully - the directory from which | ||
882 | * the current module was loaded), bindir and libdir, then in PATH | ||
883 | */ | ||
884 | self_prefix = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX); | ||
885 | bindir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); | ||
886 | libdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); | ||
887 | |||
888 | pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0); | ||
889 | |||
890 | alloc_len = | ||
891 | pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 + | ||
892 | strlen (libdir); | ||
893 | |||
894 | pathbuf = GNUNET_malloc (alloc_len * sizeof (char)); | ||
895 | |||
896 | ptr = pathbuf; | ||
897 | ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir); | ||
898 | GNUNET_free (self_prefix); | ||
899 | GNUNET_free (bindir); | ||
900 | GNUNET_free (libdir); | ||
901 | |||
902 | alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len); | ||
903 | GNUNET_assert (alloc_len == (pathbuf_len - 1)); | ||
904 | |||
905 | cmdlen = strlen (filename); | ||
906 | if (cmdlen < 5 || strcmp (&filename[cmdlen - 4], ".exe") != 0) | ||
907 | GNUNET_asprintf (&non_const_filename, "%s.exe", filename); | ||
908 | else | ||
909 | GNUNET_asprintf (&non_const_filename, "%s", filename); | ||
910 | |||
911 | /* It could be in POSIX form, convert it to a DOS path early on */ | ||
912 | if (ERROR_SUCCESS != (lRet = plibc_conv_to_win_path (non_const_filename, win_path))) | ||
913 | { | ||
914 | SetErrnoFromWinError (lRet); | ||
915 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "plibc_conv_to_win_path", | ||
916 | non_const_filename); | ||
917 | GNUNET_free (non_const_filename); | ||
918 | GNUNET_free (pathbuf); | ||
919 | return NULL; | ||
920 | } | ||
921 | GNUNET_free (non_const_filename); | ||
922 | non_const_filename = GNUNET_strdup (win_path); | ||
923 | /* Check that this is the full path. If it isn't, search. */ | ||
924 | /* FIXME: convert it to wchar_t and use SearchPathW? | ||
925 | * Remember: arguments to _start_process() are technically in UTF-8... | ||
926 | */ | ||
927 | if (non_const_filename[1] == ':') | ||
928 | snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename); | ||
929 | else if (!SearchPathA | ||
930 | (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char), | ||
931 | path, NULL)) | ||
932 | { | ||
933 | SetErrnoFromWinError (GetLastError ()); | ||
934 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "SearchPath", | ||
935 | non_const_filename); | ||
936 | GNUNET_free (non_const_filename); | ||
937 | GNUNET_free (pathbuf); | ||
938 | return NULL; | ||
939 | } | ||
940 | GNUNET_free (pathbuf); | ||
941 | GNUNET_free (non_const_filename); | ||
942 | |||
943 | cmdlen = 0; | ||
944 | argc = 0; | ||
945 | while (NULL != (arg = argv[argc++])) | ||
946 | { | ||
947 | if (cmdlen == 0) | ||
948 | cmdlen = cmdlen + strlen (path) + 4; | ||
949 | else | ||
950 | cmdlen = cmdlen + strlen (arg) + 4; | ||
951 | } | ||
952 | arg_count = argc; | ||
953 | |||
954 | cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1)); | ||
955 | argc = 0; | ||
956 | while (NULL != (arg = argv[argc++])) | ||
957 | { | ||
958 | /* This is to escape trailing slash */ | ||
959 | char arg_lastchar = arg[strlen (arg) - 1]; | ||
960 | if (idx == cmd) | ||
961 | idx += sprintf (idx, "\"%s%s\"%s", path, | ||
962 | arg_lastchar == '\\' ? "\\" : "", argc + 1 == arg_count ? "" : " "); | ||
963 | else | ||
964 | idx += sprintf (idx, "\"%s%s\"%s", arg, | ||
965 | arg_lastchar == '\\' ? "\\" : "", argc + 1 == arg_count ? "" : " "); | ||
966 | } | ||
967 | |||
968 | memset (&start, 0, sizeof (start)); | ||
969 | start.cb = sizeof (start); | ||
970 | |||
971 | if ((pipe_stdin != NULL) || (pipe_stdout != NULL)) | ||
972 | start.dwFlags |= STARTF_USESTDHANDLES; | ||
973 | |||
974 | if (pipe_stdin != NULL) | ||
975 | { | ||
976 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle | ||
977 | (pipe_stdin, GNUNET_DISK_PIPE_END_READ), | ||
978 | &stdin_handle, sizeof (HANDLE)); | ||
979 | start.hStdInput = stdin_handle; | ||
980 | } | ||
981 | |||
982 | if (pipe_stdout != NULL) | ||
983 | { | ||
984 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle | ||
985 | (pipe_stdout, | ||
986 | GNUNET_DISK_PIPE_END_WRITE), | ||
987 | &stdout_handle, sizeof (HANDLE)); | ||
988 | start.hStdOutput = stdout_handle; | ||
989 | } | ||
990 | if (GNUNET_YES == pipe_control) | ||
991 | { | ||
992 | control_pipe = | ||
993 | npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, | ||
994 | GNUNET_DISK_PERM_USER_READ | | ||
995 | GNUNET_DISK_PERM_USER_WRITE); | ||
996 | if (control_pipe == NULL) | ||
997 | { | ||
998 | GNUNET_free (cmd); | ||
999 | GNUNET_free (path); | ||
1000 | return NULL; | ||
1001 | } | ||
1002 | } | ||
1003 | else | ||
1004 | control_pipe = NULL; | ||
1005 | if (NULL != childpipename) | ||
1006 | { | ||
1007 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", | ||
1008 | childpipename); | ||
1009 | GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE); | ||
1010 | GNUNET_asprintf (&our_env[1], "%s", childpipename); | ||
1011 | our_env[2] = NULL; | ||
1012 | } | ||
1013 | else | ||
1014 | { | ||
1015 | our_env[0] = NULL; | ||
1016 | } | ||
1017 | env_block = CreateCustomEnvTable (our_env); | ||
1018 | GNUNET_free_non_null (our_env[0]); | ||
1019 | GNUNET_free_non_null (our_env[1]); | ||
1020 | |||
1021 | wpath_len = 0; | ||
1022 | if (NULL == (wpath = u8_to_u16 ((uint8_t *) path, 1 + strlen (path), NULL, &wpath_len))) | ||
1023 | { | ||
1024 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1025 | "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", path, errno); | ||
1026 | GNUNET_free (env_block); | ||
1027 | GNUNET_free (cmd); | ||
1028 | return NULL; | ||
1029 | } | ||
1030 | |||
1031 | wcmd_len = 0; | ||
1032 | if (NULL == (wcmd = u8_to_u16 ((uint8_t *) cmd, 1 + strlen (cmd), NULL, &wcmd_len))) | ||
1033 | { | ||
1034 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1035 | "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", cmd, errno); | ||
1036 | GNUNET_free (env_block); | ||
1037 | GNUNET_free (cmd); | ||
1038 | free (wpath); | ||
1039 | return NULL; | ||
1040 | } | ||
1041 | |||
1042 | if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, | ||
1043 | DETACHED_PROCESS | CREATE_SUSPENDED, env_block, NULL, &start, &proc)) | ||
1044 | { | ||
1045 | SetErrnoFromWinError (GetLastError ()); | ||
1046 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path); | ||
1047 | GNUNET_free (env_block); | ||
1048 | GNUNET_free (cmd); | ||
1049 | free (wpath); | ||
1050 | free (wcmd); | ||
1051 | return NULL; | ||
1052 | } | ||
1053 | |||
1054 | GNUNET_free (env_block); | ||
1055 | |||
1056 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | ||
1057 | gnunet_proc->pid = proc.dwProcessId; | ||
1058 | gnunet_proc->handle = proc.hProcess; | ||
1059 | gnunet_proc->control_pipe = control_pipe; | ||
1060 | |||
1061 | CreateThread (NULL, 64000, &child_wait_thread, (void *) gnunet_proc, 0, NULL); | ||
1062 | |||
1063 | ResumeThread (proc.hThread); | ||
1064 | CloseHandle (proc.hThread); | ||
1065 | |||
1066 | GNUNET_free (cmd); | ||
1067 | free (wpath); | ||
1068 | free (wcmd); | ||
1069 | return gnunet_proc; | ||
1070 | #endif | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | /** | ||
1075 | * Start a process. | ||
1076 | * | ||
1077 | * @param pipe_control should a pipe be used to send signals to the child? | ||
1078 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | ||
1079 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | ||
1080 | * @param filename name of the binary | ||
1081 | * @param va NULL-terminated list of arguments to the process | ||
1082 | * @return pointer to process structure of the new process, NULL on error | ||
1083 | */ | ||
1084 | struct GNUNET_OS_Process * | ||
1085 | GNUNET_OS_start_process_va (int pipe_control, | ||
1086 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | ||
1087 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | ||
1088 | const char *filename, va_list va) | ||
1089 | { | ||
1090 | struct GNUNET_OS_Process *ret; | ||
1091 | va_list ap; | ||
1092 | char **argv; | ||
1093 | int argc; | ||
1094 | |||
1095 | argc = 0; | ||
1096 | va_copy (ap, va); | ||
1097 | while (NULL != va_arg (ap, char *)) | ||
1098 | argc++; | ||
1099 | va_end (ap); | ||
1100 | argv = GNUNET_malloc (sizeof (char *) * (argc + 1)); | ||
1101 | argc = 0; | ||
1102 | va_copy (ap, va); | ||
1103 | while (NULL != (argv[argc] = va_arg (ap, char *))) | ||
1104 | argc++; | ||
1105 | va_end (ap); | ||
1106 | ret = GNUNET_OS_start_process_vap (pipe_control, | ||
1107 | pipe_stdin, | ||
1108 | pipe_stdout, | ||
1109 | filename, | ||
1110 | argv); | ||
1111 | GNUNET_free (argv); | ||
1112 | return ret; | ||
1113 | } | ||
1114 | |||
1115 | |||
1116 | |||
1117 | /** | ||
1118 | * Start a process. | ||
1119 | * | ||
1120 | * @param pipe_control should a pipe be used to send signals to the child? | ||
1121 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | ||
1122 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | ||
1123 | * @param filename name of the binary | ||
1124 | * @param ... NULL-terminated list of arguments to the process | ||
1125 | * | ||
1126 | * @return pointer to process structure of the new process, NULL on error | ||
1127 | * | ||
1128 | */ | ||
1129 | struct GNUNET_OS_Process * | ||
1130 | GNUNET_OS_start_process (int pipe_control, | ||
1131 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | ||
1132 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | ||
1133 | const char *filename, ...) | ||
1134 | { | ||
1135 | struct GNUNET_OS_Process *ret; | ||
1136 | va_list ap; | ||
1137 | |||
1138 | va_start (ap, filename); | ||
1139 | ret = GNUNET_OS_start_process_va (pipe_control, pipe_stdin, pipe_stdout, filename, ap); | ||
1140 | va_end (ap); | ||
1141 | return ret; | ||
1142 | } | ||
1143 | |||
1144 | |||
1145 | /** | ||
1146 | * Start a process. | ||
1147 | * | ||
1148 | * @param pipe_control should a pipe be used to send signals to the child? | ||
1149 | * @param lsocks array of listen sockets to dup systemd-style (or NULL); | ||
1150 | * must be NULL on platforms where dup is not supported | ||
1151 | * @param filename name of the binary | ||
1152 | * @param argv NULL-terminated list of arguments to the process | ||
1153 | * @return process ID of the new process, -1 on error | ||
1154 | */ | ||
1155 | struct GNUNET_OS_Process * | ||
1156 | GNUNET_OS_start_process_v (int pipe_control, | ||
1157 | const SOCKTYPE *lsocks, | ||
1158 | const char *filename, | ||
1159 | char *const argv[]) | ||
1160 | { | ||
1161 | #ifndef MINGW | ||
1162 | pid_t ret; | ||
1163 | char lpid[16]; | ||
1164 | char fds[16]; | ||
1165 | struct GNUNET_OS_Process *gnunet_proc = NULL; | ||
1166 | char *childpipename = NULL; | ||
1167 | int i; | ||
1168 | int j; | ||
1169 | int k; | ||
1170 | int tgt; | ||
1171 | int flags; | ||
1172 | int *lscp; | ||
1173 | unsigned int ls; | ||
1174 | |||
1175 | if ( (GNUNET_YES == pipe_control) && | ||
1176 | (GNUNET_OK != npipe_setup (&childpipename)) ) | ||
1177 | return NULL; | ||
1178 | lscp = NULL; | ||
1179 | ls = 0; | ||
1180 | if (lsocks != NULL) | ||
1181 | { | ||
1182 | i = 0; | ||
1183 | while (-1 != (k = lsocks[i++])) | ||
1184 | GNUNET_array_append (lscp, ls, k); | ||
1185 | GNUNET_array_append (lscp, ls, -1); | ||
1186 | } | ||
1187 | ret = fork (); | ||
1188 | if (-1 == ret) | ||
1189 | { | ||
1190 | int eno = errno; | ||
1191 | |||
1192 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); | ||
1193 | GNUNET_free_non_null (childpipename); | ||
1194 | GNUNET_array_grow (lscp, ls, 0); | ||
1195 | errno = eno; | ||
1196 | return NULL; | ||
1197 | } | ||
1198 | if (0 != ret) | ||
1199 | { | ||
1200 | gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); | ||
1201 | gnunet_proc->pid = ret; | ||
1202 | gnunet_proc->childpipename = childpipename; | ||
1203 | GNUNET_array_grow (lscp, ls, 0); | ||
1204 | return gnunet_proc; | ||
1205 | } | ||
1206 | if (NULL != childpipename) | ||
1207 | { | ||
1208 | setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); | ||
1209 | GNUNET_free (childpipename); | ||
1210 | } | ||
1211 | if (lscp != NULL) | 872 | if (lscp != NULL) |
1212 | { | 873 | { |
1213 | /* read systemd documentation... */ | 874 | /* read systemd documentation... */ |
@@ -1257,9 +918,11 @@ GNUNET_OS_start_process_v (int pipe_control, | |||
1257 | #else | 918 | #else |
1258 | struct GNUNET_DISK_FileHandle *control_pipe = NULL; | 919 | struct GNUNET_DISK_FileHandle *control_pipe = NULL; |
1259 | char *childpipename = NULL; | 920 | char *childpipename = NULL; |
1260 | char **arg, **non_const_argv; | 921 | char **arg; |
922 | char **non_const_argv; | ||
1261 | unsigned int cmdlen; | 923 | unsigned int cmdlen; |
1262 | char *cmd, *idx; | 924 | char *cmd; |
925 | char *idx; | ||
1263 | STARTUPINFOW start; | 926 | STARTUPINFOW start; |
1264 | PROCESS_INFORMATION proc; | 927 | PROCESS_INFORMATION proc; |
1265 | int argcount = 0; | 928 | int argcount = 0; |
@@ -1268,7 +931,8 @@ GNUNET_OS_start_process_v (int pipe_control, | |||
1268 | char *our_env[5] = { NULL, NULL, NULL, NULL, NULL }; | 931 | char *our_env[5] = { NULL, NULL, NULL, NULL, NULL }; |
1269 | char *env_block = NULL; | 932 | char *env_block = NULL; |
1270 | char *pathbuf; | 933 | char *pathbuf; |
1271 | DWORD pathbuf_len, alloc_len; | 934 | DWORD pathbuf_len; |
935 | DWORD alloc_len; | ||
1272 | char *self_prefix; | 936 | char *self_prefix; |
1273 | char *bindir; | 937 | char *bindir; |
1274 | char *libdir; | 938 | char *libdir; |
@@ -1279,12 +943,16 @@ GNUNET_OS_start_process_v (int pipe_control, | |||
1279 | const struct GNUNET_DISK_FileHandle *lsocks_write_fd; | 943 | const struct GNUNET_DISK_FileHandle *lsocks_write_fd; |
1280 | HANDLE lsocks_read; | 944 | HANDLE lsocks_read; |
1281 | HANDLE lsocks_write; | 945 | HANDLE lsocks_write; |
1282 | wchar_t *wpath, *wcmd; | 946 | wchar_t *wpath; |
1283 | size_t wpath_len, wcmd_len; | 947 | wchar_t *wcmd; |
948 | size_t wpath_len; | ||
949 | size_t wcmd_len; | ||
1284 | int env_off; | 950 | int env_off; |
1285 | int fail; | 951 | int fail; |
1286 | long lRet; | 952 | long lRet; |
1287 | 953 | HANDLE stdin_handle; | |
954 | HANDLE stdout_handle; | ||
955 | |||
1288 | /* Search in prefix dir (hopefully - the directory from which | 956 | /* Search in prefix dir (hopefully - the directory from which |
1289 | * the current module was loaded), bindir and libdir, then in PATH | 957 | * the current module was loaded), bindir and libdir, then in PATH |
1290 | */ | 958 | */ |
@@ -1403,6 +1071,25 @@ GNUNET_OS_start_process_v (int pipe_control, | |||
1403 | 1071 | ||
1404 | memset (&start, 0, sizeof (start)); | 1072 | memset (&start, 0, sizeof (start)); |
1405 | start.cb = sizeof (start); | 1073 | start.cb = sizeof (start); |
1074 | if ((pipe_stdin != NULL) || (pipe_stdout != NULL)) | ||
1075 | start.dwFlags |= STARTF_USESTDHANDLES; | ||
1076 | |||
1077 | if (pipe_stdin != NULL) | ||
1078 | { | ||
1079 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle | ||
1080 | (pipe_stdin, GNUNET_DISK_PIPE_END_READ), | ||
1081 | &stdin_handle, sizeof (HANDLE)); | ||
1082 | start.hStdInput = stdin_handle; | ||
1083 | } | ||
1084 | |||
1085 | if (pipe_stdout != NULL) | ||
1086 | { | ||
1087 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle | ||
1088 | (pipe_stdout, | ||
1089 | GNUNET_DISK_PIPE_END_WRITE), | ||
1090 | &stdout_handle, sizeof (HANDLE)); | ||
1091 | start.hStdOutput = stdout_handle; | ||
1092 | } | ||
1406 | 1093 | ||
1407 | if (GNUNET_YES == pipe_control) | 1094 | if (GNUNET_YES == pipe_control) |
1408 | { | 1095 | { |
@@ -1595,6 +1282,130 @@ GNUNET_OS_start_process_v (int pipe_control, | |||
1595 | } | 1282 | } |
1596 | 1283 | ||
1597 | 1284 | ||
1285 | |||
1286 | |||
1287 | /** | ||
1288 | * Start a process. | ||
1289 | * | ||
1290 | * @param pipe_control should a pipe be used to send signals to the child? | ||
1291 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | ||
1292 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | ||
1293 | * @param filename name of the binary | ||
1294 | * @param argv NULL-terminated array of arguments to the process | ||
1295 | * @return pointer to process structure of the new process, NULL on error | ||
1296 | */ | ||
1297 | struct GNUNET_OS_Process * | ||
1298 | GNUNET_OS_start_process_vap (int pipe_control, | ||
1299 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | ||
1300 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | ||
1301 | const char *filename, | ||
1302 | char *const argv[]) | ||
1303 | { | ||
1304 | return start_process (pipe_control, | ||
1305 | pipe_stdin, | ||
1306 | pipe_stdout, | ||
1307 | NULL, | ||
1308 | filename, | ||
1309 | argv); | ||
1310 | } | ||
1311 | |||
1312 | |||
1313 | /** | ||
1314 | * Start a process. | ||
1315 | * | ||
1316 | * @param pipe_control should a pipe be used to send signals to the child? | ||
1317 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | ||
1318 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | ||
1319 | * @param filename name of the binary | ||
1320 | * @param va NULL-terminated list of arguments to the process | ||
1321 | * @return pointer to process structure of the new process, NULL on error | ||
1322 | */ | ||
1323 | struct GNUNET_OS_Process * | ||
1324 | GNUNET_OS_start_process_va (int pipe_control, | ||
1325 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | ||
1326 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | ||
1327 | const char *filename, va_list va) | ||
1328 | { | ||
1329 | struct GNUNET_OS_Process *ret; | ||
1330 | va_list ap; | ||
1331 | char **argv; | ||
1332 | int argc; | ||
1333 | |||
1334 | argc = 0; | ||
1335 | va_copy (ap, va); | ||
1336 | while (NULL != va_arg (ap, char *)) | ||
1337 | argc++; | ||
1338 | va_end (ap); | ||
1339 | argv = GNUNET_malloc (sizeof (char *) * (argc + 1)); | ||
1340 | argc = 0; | ||
1341 | va_copy (ap, va); | ||
1342 | while (NULL != (argv[argc] = va_arg (ap, char *))) | ||
1343 | argc++; | ||
1344 | va_end (ap); | ||
1345 | ret = GNUNET_OS_start_process_vap (pipe_control, | ||
1346 | pipe_stdin, | ||
1347 | pipe_stdout, | ||
1348 | filename, | ||
1349 | argv); | ||
1350 | GNUNET_free (argv); | ||
1351 | return ret; | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | |||
1356 | /** | ||
1357 | * Start a process. | ||
1358 | * | ||
1359 | * @param pipe_control should a pipe be used to send signals to the child? | ||
1360 | * @param pipe_stdin pipe to use to send input to child process (or NULL) | ||
1361 | * @param pipe_stdout pipe to use to get output from child process (or NULL) | ||
1362 | * @param filename name of the binary | ||
1363 | * @param ... NULL-terminated list of arguments to the process | ||
1364 | * | ||
1365 | * @return pointer to process structure of the new process, NULL on error | ||
1366 | * | ||
1367 | */ | ||
1368 | struct GNUNET_OS_Process * | ||
1369 | GNUNET_OS_start_process (int pipe_control, | ||
1370 | struct GNUNET_DISK_PipeHandle *pipe_stdin, | ||
1371 | struct GNUNET_DISK_PipeHandle *pipe_stdout, | ||
1372 | const char *filename, ...) | ||
1373 | { | ||
1374 | struct GNUNET_OS_Process *ret; | ||
1375 | va_list ap; | ||
1376 | |||
1377 | va_start (ap, filename); | ||
1378 | ret = GNUNET_OS_start_process_va (pipe_control, pipe_stdin, pipe_stdout, filename, ap); | ||
1379 | va_end (ap); | ||
1380 | return ret; | ||
1381 | } | ||
1382 | |||
1383 | |||
1384 | /** | ||
1385 | * Start a process. | ||
1386 | * | ||
1387 | * @param pipe_control should a pipe be used to send signals to the child? | ||
1388 | * @param lsocks array of listen sockets to dup systemd-style (or NULL); | ||
1389 | * must be NULL on platforms where dup is not supported | ||
1390 | * @param filename name of the binary | ||
1391 | * @param argv NULL-terminated list of arguments to the process | ||
1392 | * @return process ID of the new process, -1 on error | ||
1393 | */ | ||
1394 | struct GNUNET_OS_Process * | ||
1395 | GNUNET_OS_start_process_v (int pipe_control, | ||
1396 | const SOCKTYPE *lsocks, | ||
1397 | const char *filename, | ||
1398 | char *const argv[]) | ||
1399 | { | ||
1400 | return start_process (pipe_control, | ||
1401 | NULL, | ||
1402 | NULL, | ||
1403 | lsocks, | ||
1404 | filename, | ||
1405 | argv); | ||
1406 | } | ||
1407 | |||
1408 | |||
1598 | /** | 1409 | /** |
1599 | * Retrieve the status of a process, waiting on him if dead. | 1410 | * Retrieve the status of a process, waiting on him if dead. |
1600 | * Nonblocking version. | 1411 | * Nonblocking version. |