ObjFW  Check-in [79548b3c29]

Overview
Comment:Rename OFProcess to OFSubprocess
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 79548b3c2995e35853b4cd0a1887bbedb7dcd193822ff0c2c8b2cbe81b57969a
User & Date: js on 2021-03-30 21:06:33
Other Links: manifest | tags
Context
2021-04-04
13:25
Rename +[pluginFromFile:] to +[pluginWithPath:] check-in: 45f8195351 user: js tags: trunk
2021-03-30
21:23
Merge trunk into 1.0 branch check-in: 564d6d6b6f user: js tags: 1.0
21:06
Rename OFProcess to OFSubprocess check-in: 79548b3c29 user: js tags: trunk
2021-03-24
00:57
*-x86-win32.S: Add .scl and .type check-in: 30ddefaf51 user: js tags: trunk
Changes

Modified configure.ac from [ec187ae771] to [bfb050aa3d].

1557
1558
1559
1560
1561
1562
1563
1564

1565
1566
1567

1568
1569
1570
1571

1572
1573
1574

1575
1576
1577
1578
1579
1580
1581
1582

1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594

1595
1596
1597
1598
1599
1600
1601
1602
1603
1604



1605
1606
1607
1608
1609
1610
1611
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566

1567
1568
1569
1570

1571
1572
1573

1574
1575
1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593

1594
1595
1596
1597
1598
1599
1600
1601



1602
1603
1604
1605
1606
1607
1608
1609
1610
1611







-
+


-
+



-
+


-
+







-
+











-
+







-
-
-
+
+
+








		#if (!defined(TARGET_OS_IPHONE) || !TARGET_OS_IPHONE) && \
		    (!defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR)
		egrep_cpp_yes
		#endif
	], [
		AC_MSG_RESULT(yes)
		have_processes="yes"
		have_subprocesses="yes"
	], [
		AC_MSG_RESULT(no)
		have_processes="no"
		have_subprocesses="no"
	])
	;;
mingw*)
	have_processes="yes"
	have_subprocesses="yes"
	;;
msdosdjgpp*)
	have_processes="no"
	have_subprocesses="no"
	;;
*)
	AC_HEADER_SYS_WAIT
	AC_CHECK_FUNCS(kill)

	AC_CHECK_FUNCS(posix_spawnp, [
		AS_IF([test x"$ac_cv_func_kill" = x"yes"], [
			have_processes="yes"
			have_subprocesses="yes"

			AC_CHECK_HEADERS(spawn.h)
		])
	], [
		AC_CHECK_FUNCS([vfork dup2 execvp _exit], [
			AS_IF([test x"$ac_cv_func_vfork" = x"yes" \
			    -a x"$ac_cv_func_pipe" = x"yes" \
			    -a x"$ac_cv_func_dup2" = x"yes" \
			    -a x"$ac_cv_func_execvp" = x"yes" \
			    -a x"$ac_cv_func_kill" = x"yes" \
			    -a x"$ac_cv_func__exit" = x"yes"], [
				have_processes="yes"
				have_subprocesses="yes"
			])
		], [
			break
		])
	])
	;;
esac
AS_IF([test x"$have_processes" = x"yes"], [
	AC_SUBST(OF_PROCESS_M, "OFProcess.m")
	AC_DEFINE(OF_HAVE_PROCESSES, 1, [Whether we have processes])
AS_IF([test x"$have_subprocesses" = x"yes"], [
	AC_SUBST(OF_SUBPROCESS_M, "OFSubprocess.m")
	AC_DEFINE(OF_HAVE_SUBPROCESSES, 1, [Whether we have subprocesses])
])

AC_CHECK_HEADERS_ONCE([complex.h sys/ioctl.h sys/ttycom.h])
AC_CHECK_FUNCS(isatty)

AC_CHECK_FUNC(pledge, [
	AC_DEFINE(OF_HAVE_PLEDGE, 1, [Whether we have pledge()])

Modified extra.mk.in from [104b6a10da] to [b1888f97ac].

33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62







-

+











-


+







LIBBASES_M = @LIBBASES_M@
LIBOBJFWRT_DEP = @LIBOBJFWRT_DEP@
LIBOBJFWRT_DEP_LVL2 = @LIBOBJFWRT_DEP_LVL2@
LIBOBJFW_DEP = @LIBOBJFW_DEP@
LIBOBJFW_DEP_LVL2 = @LIBOBJFW_DEP_LVL2@
LINKLIB = @LINKLIB@
LOOKUP_ASM_A = @LOOKUP_ASM_A@
LOOKUP_ASM_LIB_A = @LOOKUP_ASM_LIB_A@
LOOKUP_ASM_AMIGALIB_A = @LOOKUP_ASM_AMIGALIB_A@
LOOKUP_ASM_LIB_A = @LOOKUP_ASM_LIB_A@
MAP_LDFLAGS = @MAP_LDFLAGS@
OFARC = @OFARC@
OFDNS = @OFDNS@
OFHASH = @OFHASH@
OFHTTP = @OFHTTP@
OFSOCK = @OFSOCK@
OF_BLOCK_TESTS_M = @OF_BLOCK_TESTS_M@
OF_EPOLL_KERNEL_EVENT_OBSERVER_M = @OF_EPOLL_KERNEL_EVENT_OBSERVER_M@
OF_HTTP_CLIENT_TESTS_M = @OF_HTTP_CLIENT_TESTS_M@
OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_M@
OF_POLL_KERNEL_EVENT_OBSERVER_M = @OF_POLL_KERNEL_EVENT_OBSERVER_M@
OF_PROCESS_M = @OF_PROCESS_M@
OF_SCTP_SOCKET_M = @OF_SCTP_SOCKET_M@
OF_SELECT_KERNEL_EVENT_OBSERVER_M = @OF_SELECT_KERNEL_EVENT_OBSERVER_M@
OF_SUBPROCESS_M = @OF_SUBPROCESS_M@
REEXPORT_RUNTIME = @REEXPORT_RUNTIME@
REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@
RUNTIME = @RUNTIME@
RUNTIME_ARC_TESTS_M = @RUNTIME_ARC_TESTS_M@
RUNTIME_AUTORELEASE_M = @RUNTIME_AUTORELEASE_M@
RUNTIME_FRAMEWORK_LIBS = @RUNTIME_FRAMEWORK_LIBS@
RUNTIME_INSTANCE_M = @RUNTIME_INSTANCE_M@

Modified src/Makefile from [cec3ab337b] to [1b174a549a].

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
63
64
65
66
67
68
69

70
71
72
73
74
75
76







-







       OFNull.m				\
       OFNumber.m			\
       OFObject.m			\
       OFObject+KeyValueCoding.m	\
       OFObject+Serialization.m		\
       OFOptionsParser.m		\
       OFPair.m				\
       ${OF_PROCESS_M}			\
       OFRIPEMD160Hash.m		\
       OFRunLoop.m			\
       OFSandbox.m			\
       OFSecureData.m			\
       OFSeekableStream.m		\
       OFSet.m				\
       OFSHA1Hash.m			\
88
89
90
91
92
93
94

95
96
97
98
99
100
101
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101







+







       OFString+CryptoHashing.m		\
       OFString+JSONParsing.m		\
       OFString+PropertyListParsing.m	\
       OFString+Serialization.m		\
       OFString+URLEncoding.m		\
       OFString+XMLEscaping.m		\
       OFString+XMLUnescaping.m		\
       ${OF_SUBUPROCESS_M}		\
       OFSystemInfo.m			\
       OFTarArchive.m			\
       OFTarArchiveEntry.m		\
       OFThread.m			\
       OFTimer.m			\
       OFTriple.m			\
       OFURL.m				\

Renamed and modified src/OFProcess.h [a7b8fab4c5] to src/OFSubprocess.h [a6ce8bbc81].

36
37
38
39
40
41
42
43

44
45

46
47
48

49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64

65
66
67
68
69

70
71

72
73
74
75


76
77
78
79
80

81
82
83
84


85
86
87
88


89
90
91
92
93
94
95

96
97
98
99
100



101
102
103

104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123





124
125
126
127
128
129


130
131
132
133

134
135
136
137
138
139


140
141
142
143
144

145
146
147
148
149
150
151
152


153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168



169
170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199
200

201
202


203
204
205
206
207
36
37
38
39
40
41
42

43
44

45
46
47

48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63

64
65
66
67
68

69
70

71
72
73


74
75
76
77
78
79

80
81
82


83
84
85
86


87
88
89
90
91
92
93
94

95
96
97



98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
113
114
115

116
117
118





119
120
121
122
123
124
125
126
127


128
129
130
131
132

133
134
135
136
137


138
139
140
141
142
143

144
145
146
147
148
149
150


151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166


167
168
169
170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199
200

201
202

203
204
205
206
207
208
209







-
+

-
+


-
+








-
+






-
+




-
+

-
+


-
-
+
+




-
+


-
-
+
+


-
-
+
+






-
+


-
-
-
+
+
+


-
+












-
+


-
-
-
-
-
+
+
+
+
+




-
-
+
+



-
+




-
-
+
+




-
+






-
-
+
+






-
+







-
-
+
+
+











-
+










-
+








-
+

-
+
+






OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDictionary OF_GENERIC(KeyType, ObjectType);

/**
 * @class OFProcess OFProcess.h ObjFW/OFProcess.h
 * @class OFSubprocess OFSubprocess.h ObjFW/OFSubprocess.h
 *
 * @brief A class for stream-like communication with a newly created process.
 * @brief A class for stream-like communication with a newly created subprocess.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFProcess: OFStream
@interface OFSubprocess: OFStream
#ifndef OF_WINDOWS
    <OFReadyForReadingObserving, OFReadyForWritingObserving>
#endif
{
#ifndef OF_WINDOWS
	pid_t _pid;
	int _readPipe[2], _writePipe[2];
#else
	HANDLE _process, _readPipe[2], _writePipe[2];
	HANDLE _handle, _readPipe[2], _writePipe[2];
#endif
	int _status;
	bool _atEndOfStream;
}

/**
 * @brief Creates a new OFProcess with the specified program and invokes the
 * @brief Creates a new OFSubprocess with the specified program and invokes the
 *	  program.
 *
 * @param program The program to execute. If it does not start with a slash, the
 *		  search path specified in PATH is used.
 * @return A new, autoreleased OFProcess.
 * @return A new, autoreleased OFSubprocess.
 */
+ (instancetype)processWithProgram: (OFString *)program;
+ (instancetype)subprocessWithProgram: (OFString *)program;

/**
 * @brief Creates a new OFProcess with the specified program and arguments and
 *	  invokes the program.
 * @brief Creates a new OFSubprocess with the specified program and arguments
 *	  and invokes the program.
 *
 * @param program The program to execute. If it does not start with a slash, the
 *		  search path specified in PATH is used.
 * @param arguments The arguments to pass to the program, or `nil`
 * @return A new, autoreleased OFProcess.
 * @return A new, autoreleased OFSubprocess.
 */
+ (instancetype)
    processWithProgram: (OFString *)program
	     arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments;
    subProcessWithProgram: (OFString *)program
		arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments;

/**
 * @brief Creates a new OFProcess with the specified program, program name and
 *	  arguments and invokes the program.
 * @brief Creates a new OFSubprocess with the specified program, program name
 *	  and arguments and invokes the program.
 *
 * @param program The program to execute. If it does not start with a slash, the
 *		  search path specified in PATH is used.
 * @param programName The program name for the program to invoke (argv[0]).
 *		      Usually, this is equal to program.
 * @param arguments The arguments to pass to the program, or `nil`
 * @return A new, autoreleased OFProcess.
 * @return A new, autoreleased OFSubprocess.
 */
+ (instancetype)
    processWithProgram: (OFString *)program
	   programName: (OFString *)programName
	     arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments;
    subprocessWithProgram: (OFString *)program
	      programName: (OFString *)programName
		arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments;

/**
 * @brief Creates a new OFProcess with the specified program, program name,
 * @brief Creates a new OFSubprocess with the specified program, program name,
 *	  arguments and environment and invokes the program.
 *
 * @param program The program to execute. If it does not start with a slash, the
 *		  search path specified in PATH is used.
 * @param programName The program name for the program to invoke (argv[0]).
 *		      Usually, this is equal to program.
 * @param arguments The arguments to pass to the program, or `nil`
 * @param environment The environment to pass to the program, or `nil`. If it
 *		      is not `nil`, the passed dictionary will be used to
 *		      override the environment. If you want to add to the
 *		      existing environment, you need to get the existing
 *		      environment first, copy it, modify it and then pass it.
 * @return A new, autoreleased OFProcess.
 * @return A new, autoreleased OFSubprocess.
 */
+ (instancetype)
    processWithProgram: (OFString *)program
	   programName: (OFString *)programName
	     arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments
	   environment: (nullable OFDictionary
			    OF_GENERIC(OFString *, OFString *) *)environment;
    subprocessWithProgram: (OFString *)program
	      programName: (OFString *)programName
		arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments
	      environment: (nullable OFDictionary
			       OF_GENERIC(OFString *, OFString *) *)environment;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFProcess with the specified program
 *	  and invokes the program.
 * @brief Initializes an already allocated OFSubprocess with the specified
 *	  program and invokes the program.
 *
 * @param program The program to execute. If it does not start with a slash, the
 *		  search path specified in PATH is used.
 * @return An initialized OFProcess.
 * @return An initialized OFSubprocess.
 */
- (instancetype)initWithProgram: (OFString *)program;

/**
 * @brief Initializes an already allocated OFProcess with the specified program
 *	  and arguments and invokes the program.
 * @brief Initializes an already allocated OFSubprocess with the specified
 *	  program and arguments and invokes the program.
 *
 * @param program The program to execute. If it does not start with a slash, the
 *		  search path specified in PATH is used.
 * @param arguments The arguments to pass to the program, or `nil`
 * @return An initialized OFProcess.
 * @return An initialized OFSubprocess.
 */
- (instancetype)
    initWithProgram: (OFString *)program
	  arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments;

/**
 * @brief Initializes an already allocated OFProcess with the specified program,
 *	  program name and arguments and invokes the program.
 * @brief Initializes an already allocated OFSubprocess with the specified
 *	  program, program name and arguments and invokes the program.
 *
 * @param program The program to execute. If it does not start with a slash, the
 *		  search path specified in PATH is used.
 * @param programName The program name for the program to invoke (argv[0]).
 *		      Usually, this is equal to program.
 * @param arguments The arguments to pass to the program, or `nil`
 * @return An initialized OFProcess.
 * @return An initialized OFSubprocess.
 */
- (instancetype)
    initWithProgram: (OFString *)program
	programName: (OFString *)programName
	  arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments;

/**
 * @brief Initializes an already allocated OFProcess with the specified program,
 *	  program name, arguments and environment and invokes the program.
 * @brief Initializes an already allocated OFSubprocess with the specified
 *	  program, program name, arguments and environment and invokes the
 *	  program.
 *
 * @param program The program to execute. If it does not start with a slash, the
 *		  search path specified in PATH is used.
 * @param programName The program name for the program to invoke (argv[0]).
 *		      Usually, this is equal to program.
 * @param arguments The arguments to pass to the program, or `nil`
 * @param environment The environment to pass to the program, or `nil`. If it
 *		      is not `nil`, the passed dictionary will be used to
 *		      override the environment. If you want to add to the
 *		      existing environment, you need to get the existing
 *		      environment first, copy it, modify it and then pass it.
 * @return An initialized OFProcess.
 * @return An initialized OFSubprocess.
 */
- (instancetype)
    initWithProgram: (OFString *)program
	programName: (OFString *)programName
	  arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments
	environment: (nullable OFDictionary
			 OF_GENERIC(OFString *, OFString *) *)environment
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Closes the write direction of the process.
 * @brief Closes the write direction of the subprocess.
 *
 * This method needs to be called for some programs before data can be read,
 * since some programs don't start processing before the write direction is
 * closed.
 */
- (void)closeForWriting;

/**
 * @brief Waits for the process to terminate and returns the exit status.
 * @brief Waits for the subprocess to terminate and returns the exit status.
 *
 * If the process has already exited, this returns the exit status immediately.
 * If the subprocess has already exited, this returns the exit status
 * immediately.
 */
- (int)waitForTermination;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFProcess.m [80953e8b4c] to src/OFSubprocess.m [6a65d9f1d2].

14
15
16
17
18
19
20
21

22
23

24
14
15
16
17
18
19
20

21
22

23
24







-
+

-
+

 */

#include "config.h"

#include "platform.h"

#ifdef OF_WINDOWS
# include "platform/windows/OFProcess.m"
# include "platform/windows/OFSubprocess.m"
#else
# include "platform/posix/OFProcess.m"
# include "platform/posix/OFSubprocess.m"
#endif

Modified src/ObjFW.h from [b6085669fc] to [ff04d9fe70].

94
95
96
97
98
99
100
101
102


103
104
105
106
107
108
109
94
95
96
97
98
99
100


101
102
103
104
105
106
107
108
109







-
-
+
+







# import "OFHTTPCookie.h"
# import "OFHTTPCookieManager.h"
# import "OFHTTPRequest.h"
# import "OFHTTPResponse.h"
# import "OFHTTPServer.h"
#endif

#ifdef OF_HAVE_PROCESSES
# import "OFProcess.h"
#ifdef OF_HAVE_SUBPROCESSES
# import "OFSubprocess.h"
#endif

#import "OFCryptoHash.h"
#import "OFMD5Hash.h"
#import "OFRIPEMD160Hash.h"
#import "OFSHA1Hash.h"
#import "OFSHA224Hash.h"

Renamed and modified src/platform/posix/OFProcess.m [e243a4e88a] to src/platform/posix/OFSubprocess.m [d13ad2c4b0].

25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56


57
58
59
60
61
62


63
64
65
66
67
68
69
70



71
72
73
74
75
76
77
78
79
80




81
82
83
84
85
86
87
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54


55
56
57
58
59
60


61
62
63
64
65
66
67



68
69
70
71
72
73
74
75
76




77
78
79
80
81
82
83
84
85
86
87







-
+















-
+






-
-
+
+




-
-
+
+





-
-
-
+
+
+






-
-
-
-
+
+
+
+







#endif

#include "unistd_wrapper.h"
#ifdef HAVE_SPAWN_H
# include <spawn.h>
#endif

#import "OFProcess.h"
#import "OFSubprocess.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFLocale.h"

#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#ifndef HAVE_POSIX_SPAWNP
extern char **environ;
#endif

@interface OFProcess ()
@interface OFSubprocess ()
- (void)of_getArgv: (char ***)argv
    forProgramName: (OFString *)programName
      andArguments: (OFArray *)arguments;
- (char **)of_environmentForDictionary: (OFDictionary *)dictionary;
@end

@implementation OFProcess
+ (instancetype)processWithProgram: (OFString *)program
@implementation OFSubprocess
+ (instancetype)subprocessWithProgram: (OFString *)program
{
	return [[[self alloc] initWithProgram: program] autorelease];
}

+ (instancetype)processWithProgram: (OFString *)program
			 arguments: (OFArray *)arguments
+ (instancetype)subprocessWithProgram: (OFString *)program
			    arguments: (OFArray *)arguments
{
	return [[[self alloc] initWithProgram: program
				    arguments: arguments] autorelease];
}

+ (instancetype)processWithProgram: (OFString *)program
		       programName: (OFString *)programName
			 arguments: (OFArray *)arguments
+ (instancetype)subprocessWithProgram: (OFString *)program
			  programName: (OFString *)programName
			    arguments: (OFArray *)arguments
{
	return [[[self alloc] initWithProgram: program
				  programName: programName
				    arguments: arguments] autorelease];
}

+ (instancetype)processWithProgram: (OFString *)program
		       programName: (OFString *)programName
			 arguments: (OFArray *)arguments
		       environment: (OFDictionary *)environment
+ (instancetype)subprocessWithProgram: (OFString *)program
			  programName: (OFString *)programName
			    arguments: (OFArray *)arguments
			  environment: (OFDictionary *)environment
{
	return [[[self alloc] initWithProgram: program
				  programName: programName
				    arguments: arguments
				  environment: environment] autorelease];
}

Renamed and modified src/platform/windows/OFProcess.m [ed2642bf1e] to src/platform/windows/OFSubprocess.m [be45f52a11].

14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43


44
45
46
47
48
49


50
51
52
53
54
55
56
57



58
59
60
61
62
63
64
65
66
67




68
69
70
71
72
73
74
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41


42
43
44
45
46
47


48
49
50
51
52
53
54



55
56
57
58
59
60
61
62
63




64
65
66
67
68
69
70
71
72
73
74







-
+















-
+




-
-
+
+




-
-
+
+





-
-
-
+
+
+






-
-
-
-
+
+
+
+







 */

#include "config.h"

#include <errno.h>
#include <string.h>

#import "OFProcess.h"
#import "OFSubprocess.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFLocale.h"
#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#include <windows.h>

@interface OFProcess ()
@interface OFSubprocess ()
- (of_char16_t *)of_wideEnvironmentForDictionary: (OFDictionary *)dictionary;
- (char *)of_environmentForDictionary: (OFDictionary *)environment;
@end

@implementation OFProcess
+ (instancetype)processWithProgram: (OFString *)program
@implementation OFSubprocess
+ (instancetype)subprocessWithProgram: (OFString *)program
{
	return [[[self alloc] initWithProgram: program] autorelease];
}

+ (instancetype)processWithProgram: (OFString *)program
			 arguments: (OFArray *)arguments
+ (instancetype)subprocessWithProgram: (OFString *)program
			    arguments: (OFArray *)arguments
{
	return [[[self alloc] initWithProgram: program
				    arguments: arguments] autorelease];
}

+ (instancetype)processWithProgram: (OFString *)program
		       programName: (OFString *)programName
			 arguments: (OFArray *)arguments
+ (instancetype)subprocessWithProgram: (OFString *)program
			  programName: (OFString *)programName
			    arguments: (OFArray *)arguments
{
	return [[[self alloc] initWithProgram: program
				  programName: programName
				    arguments: arguments] autorelease];
}

+ (instancetype)processWithProgram: (OFString *)program
		       programName: (OFString *)programName
			 arguments: (OFArray *)arguments
		       environment: (OFDictionary *)environment
+ (instancetype)subprocessWithProgram: (OFString *)program
			  programName: (OFString *)programName
			    arguments: (OFArray *)arguments
			  environment: (OFDictionary *)environment
{
	return [[[self alloc] initWithProgram: program
				  programName: programName
				    arguments: arguments
				  environment: environment] autorelease];
}

113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
+








	@try {
		SECURITY_ATTRIBUTES sa;
		PROCESS_INFORMATION pi;
		void *pool;
		OFMutableString *argumentsString;

		_process = INVALID_HANDLE_VALUE;
		_handle = INVALID_HANDLE_VALUE;
		_readPipe[0] = _writePipe[1] = NULL;

		sa.nLength = sizeof(sa);
		sa.bInheritHandle = TRUE;
		sa.lpSecurityDescriptor = NULL;

		if (!CreatePipe(&_readPipe[0], &_readPipe[1], &sa, 0))
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240







-
+







			    NULL, &si, &pi))
				@throw [OFInitializationFailedException
				    exceptionWithClass: self.class];
		}

		objc_autoreleasePoolPop(pool);

		_process = pi.hProcess;
		_handle = pi.hProcess;
		CloseHandle(pi.hThread);

		CloseHandle(_readPipe[1]);
		CloseHandle(_writePipe[0]);
	} @catch (id e) {
		[self release];
		@throw e;
380
381
382
383
384
385
386
387
388
389



390
391
392

393
394
395
396
397
398
399
400
401
402
403

404
405
406

407
408

409
410
411
412
413
414


415
416
417
418
419
380
381
382
383
384
385
386



387
388
389
390
391

392
393
394
395
396
397
398
399
400
401
402

403
404
405

406
407

408
409
410
411
412


413
414
415
416
417
418
419







-
-
-
+
+
+


-
+










-
+


-
+

-
+




-
-
+
+





{
	if (_readPipe[0] == NULL)
		@throw [OFNotOpenException exceptionWithObject: self];

	[self closeForWriting];
	CloseHandle(_readPipe[0]);

	if (_process != INVALID_HANDLE_VALUE) {
		TerminateProcess(_process, 0);
		CloseHandle(_process);
	if (_handle != INVALID_HANDLE_VALUE) {
		TerminateProcess(_handle, 0);
		CloseHandle(_handle);
	}

	_process = INVALID_HANDLE_VALUE;
	_handle = INVALID_HANDLE_VALUE;
	_readPipe[0] = NULL;

	[super close];
}

- (int)waitForTermination
{
	if (_readPipe[0] == NULL)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_process != INVALID_HANDLE_VALUE) {
	if (_handle != INVALID_HANDLE_VALUE) {
		DWORD exitCode;

		WaitForSingleObject(_process, INFINITE);
		WaitForSingleObject(_handle, INFINITE);

		if (GetExitCodeProcess(_process, &exitCode))
		if (GetExitCodeProcess(_handle, &exitCode))
			_status = exitCode;
		else
			_status = GetLastError();

		CloseHandle(_process);
		_process = INVALID_HANDLE_VALUE;
		CloseHandle(_handle);
		_handle = INVALID_HANDLE_VALUE;
	}

	return _status;
}
@end