aboutsummaryrefslogtreecommitdiff
path: root/src/util/os_priority.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-06-13 08:35:01 +0000
committerChristian Grothoff <christian@grothoff.org>2012-06-13 08:35:01 +0000
commit8bbc25e641ce26ecd424ffa12dd4f2f1d8c60cd1 (patch)
tree9026409aa6980f99a121c29e751aabe41e7dcc85 /src/util/os_priority.c
parent1b081dce5a25bf612d6711662b06483b18069617 (diff)
downloadgnunet-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.c577
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
44struct GNUNET_OS_Process 45struct 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
650static char * 653static char *
651CreateCustomEnvTable (char **vars) 654CreateCustomEnvTable (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 */
767struct GNUNET_OS_Process * 772static struct GNUNET_OS_Process *
768GNUNET_OS_start_process_vap (int pipe_control, 773start_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 */
1084struct GNUNET_OS_Process *
1085GNUNET_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 */
1129struct GNUNET_OS_Process *
1130GNUNET_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 */
1155struct GNUNET_OS_Process *
1156GNUNET_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 */
1297struct GNUNET_OS_Process *
1298GNUNET_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 */
1323struct GNUNET_OS_Process *
1324GNUNET_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 */
1368struct GNUNET_OS_Process *
1369GNUNET_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 */
1394struct GNUNET_OS_Process *
1395GNUNET_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.