1 " |
1 " |
2 COPYRIGHT (c) 1989 by Claus Gittinger |
2 COPYRIGHT (c) 1989 by Claus Gittinger |
3 All Rights Reserved |
3 All Rights Reserved |
4 |
4 |
5 This software is furnished under a license and may be used |
5 This software is furnished under a license and may be used |
6 only in accordance with the terms of that license and with the |
6 only in accordance with the terms of that license and with the |
7 inclusion of the above copyright notice. This software may not |
7 inclusion of the above copyright notice. This software may not |
8 be provided or otherwise made available to, or used by, any |
8 be provided or otherwise made available to, or used by, any |
9 other person. No title to or ownership of the software is |
9 other person. No title to or ownership of the software is |
10 hereby transferred. |
10 hereby transferred. |
11 " |
11 " |
12 |
12 |
13 NonPositionableExternalStream subclass:#PipeStream |
13 UnboundedExternalStream subclass:#PipeStream |
14 instanceVariableNames:'commandString' |
14 instanceVariableNames:'commandString' |
15 classVariableNames:'BrokenPipeSignal' |
15 classVariableNames:'BrokenPipeSignal' |
16 poolDictionaries:'' |
16 poolDictionaries:'' |
17 category:'Streams-External' |
17 category:'Streams-External' |
18 ! |
18 ! |
19 |
19 |
20 PipeStream comment:' |
20 PipeStream comment:' |
21 COPYRIGHT (c) 1989 by Claus Gittinger |
21 COPYRIGHT (c) 1989 by Claus Gittinger |
22 All Rights Reserved |
22 All Rights Reserved |
23 |
23 |
24 $Header: /cvs/stx/stx/libbasic/Attic/PipeStr.st,v 1.13 1994-08-06 10:32:00 claus Exp $ |
24 $Header: /cvs/stx/stx/libbasic/Attic/PipeStr.st,v 1.14 1994-10-10 00:27:18 claus Exp $ |
25 '! |
25 '! |
26 |
26 |
27 !PipeStream class methodsFor:'documentation'! |
27 !PipeStream class methodsFor:'documentation'! |
28 |
28 |
29 copyright |
29 copyright |
30 " |
30 " |
31 COPYRIGHT (c) 1989 by Claus Gittinger |
31 COPYRIGHT (c) 1989 by Claus Gittinger |
32 All Rights Reserved |
32 All Rights Reserved |
33 |
33 |
34 This software is furnished under a license and may be used |
34 This software is furnished under a license and may be used |
35 only in accordance with the terms of that license and with the |
35 only in accordance with the terms of that license and with the |
36 inclusion of the above copyright notice. This software may not |
36 inclusion of the above copyright notice. This software may not |
37 be provided or otherwise made available to, or used by, any |
37 be provided or otherwise made available to, or used by, any |
40 " |
40 " |
41 ! |
41 ! |
42 |
42 |
43 version |
43 version |
44 " |
44 " |
45 $Header: /cvs/stx/stx/libbasic/Attic/PipeStr.st,v 1.13 1994-08-06 10:32:00 claus Exp $ |
45 $Header: /cvs/stx/stx/libbasic/Attic/PipeStr.st,v 1.14 1994-10-10 00:27:18 claus Exp $ |
46 " |
46 " |
47 ! |
47 ! |
48 |
48 |
49 documentation |
49 documentation |
50 " |
50 " |
51 Pipestreams allow reading or writing from/to a unix command. |
51 Pipestreams allow reading or writing from/to a unix command. |
52 For example, to get a stream reading the output of an 'ls -l' |
52 For example, to get a stream reading the output of an 'ls -l' |
53 command, a PipeStream can be created with: |
53 command, a PipeStream can be created with: |
54 |
54 |
55 PipeStream readingFrom:'ls -l' |
55 PipeStream readingFrom:'ls -l' |
56 |
56 |
57 the characters of the commands output can be read using the |
57 the characters of the commands output can be read using the |
58 standard stream messages as next, nextLine etc. |
58 standard stream messages as next, nextLine etc. |
59 |
59 |
60 If a writing pipeStream is written to, after the command has finished, |
60 If a writing pipeStream is written to, after the command has finished, |
61 UNIX will generate an error-signal (SIGPIPE), which will raise the |
61 UNIX will generate an error-signal (SIGPIPE), which will raise the |
62 BrokenPipeSignal. |
62 BrokenPipeSignal. |
63 Thus, to handle this condition correctly, the following code is suggested: |
63 Thus, to handle this condition correctly, the following code is suggested: |
64 |
64 |
65 |p| |
65 |p| |
66 p := PipeStream writingTo:'echo hello'. |
66 p := PipeStream writingTo:'echo hello'. |
67 PipeStream brokenPipeSignal handle:[:ex | |
67 PipeStream brokenPipeSignal handle:[:ex | |
68 'broken pipe' printNewline. |
68 'broken pipe' printNewline. |
69 p shutDown. |
69 p shutDown. |
70 ex return |
70 ex return |
71 ] do:[ |
71 ] do:[ |
72 p nextPutLine:'oops'. |
72 p nextPutLine:'oops'. |
73 'after write' printNewline. |
73 'after write' printNewline. |
74 p close. |
74 p close. |
75 'after close' printNewline |
75 'after close' printNewline |
76 ] |
76 ] |
77 |
77 |
78 Notice, that if the Stream is buffered, the Signal may occur some time after |
78 Notice, that if the Stream is buffered, the Signal may occur some time after |
79 the write - or even at close time; to avoid a recursive signal in the exception |
79 the write - or even at close time; to avoid a recursive signal in the exception |
80 handler, a shutDown is useful there. |
80 handler, a shutDown is useful there. |
81 " |
81 " |
151 %{ /* UNLIMITEDSTACK */ |
154 %{ /* UNLIMITEDSTACK */ |
152 #ifndef transputer |
155 #ifndef transputer |
153 extern int _immediateInterrupt; |
156 extern int _immediateInterrupt; |
154 |
157 |
155 if (_INST(filePointer) != nil) { |
158 if (_INST(filePointer) != nil) { |
156 /* |
159 /* |
157 * allow interrupt even when blocking here ... |
160 * allow interrupt even when blocking here ... |
158 */ |
161 */ |
159 _immediateInterrupt = 1; |
162 _immediateInterrupt = 1; |
160 pclose(MKFD(_INST(filePointer))); |
163 pclose(MKFD(_INST(filePointer))); |
161 _immediateInterrupt = 0; |
164 _immediateInterrupt = 0; |
162 } |
165 } |
163 #endif |
166 #endif |
164 %} |
167 %} |
165 ! ! |
168 ! ! |
166 |
169 |
167 !PipeStream methodsFor:'private'! |
170 !PipeStream methodsFor:'private'! |
168 |
171 |
169 atEnd |
172 XXatEnd |
170 "return true, if position is at end" |
173 "return true, if position is at end" |
171 |
174 |
172 %{ /* NOCONTEXT */ |
175 %{ /* NOCONTEXT */ |
173 #ifdef IRIX5 |
176 #ifdef IRIX5 |
174 FILE *f; |
177 FILE *f; |
175 OBJ t; |
178 OBJ t; |
176 OBJ _true = true; |
179 OBJ _true = true; |
177 int c; |
180 int c; |
178 |
181 |
179 if (_INST(hitEOF) == _true) { |
182 if (_INST(hitEOF) == _true) { |
180 RETURN (_true); |
183 RETURN (_true); |
181 } |
184 } |
182 if ((t = _INST(filePointer)) != nil) { |
185 if ((t = _INST(filePointer)) != nil) { |
183 f = MKFD(t); |
186 f = MKFD(t); |
184 if (feof(f)) { |
187 if (feof(f)) { |
185 _INST(hitEOF) = true; |
188 _INST(hitEOF) = true; |
186 RETURN (true); |
189 RETURN (true); |
187 } |
190 } |
188 RETURN ( false ); |
191 RETURN ( false ); |
189 } |
192 } |
190 #endif |
193 #endif |
191 %} |
194 %} |
192 . |
195 . |
193 ^ super atEnd |
196 ^ super atEnd |
201 |retVal| |
204 |retVal| |
202 |
205 |
203 %{ /* STACK: 32000 */ |
206 %{ /* STACK: 32000 */ |
204 #ifndef transputer |
207 #ifndef transputer |
205 { |
208 { |
206 FILE *f; |
209 FILE *f; |
207 extern errno; |
210 extern errno; |
208 extern int _immediateInterrupt; |
211 extern int _immediateInterrupt; |
209 |
212 |
210 if (__isString(aCommandString) && __isString(mode)) { |
213 if (__isString(aCommandString) && __isString(mode)) { |
211 _immediateInterrupt = 1; |
214 _immediateInterrupt = 1; |
212 do { |
215 do { |
213 #ifdef LINUX |
216 #ifdef LINUX |
214 /* LINUX returns a non-NULL f even when interrupted */ |
217 /* LINUX returns a non-NULL f even when interrupted */ |
215 errno = 0; |
218 errno = 0; |
216 f = (FILE *)popen((char *) _stringVal(aCommandString), |
219 f = (FILE *)popen((char *) _stringVal(aCommandString), |
217 (char *) _stringVal(mode)); |
220 (char *) _stringVal(mode)); |
218 if (errno == EINTR) |
221 if (errno == EINTR) |
219 f = NULL; |
222 f = NULL; |
220 #else |
223 #else |
221 f = (FILE *)popen((char *) _stringVal(aCommandString), |
224 f = (FILE *)popen((char *) _stringVal(aCommandString), |
222 (char *) _stringVal(mode)); |
225 (char *) _stringVal(mode)); |
223 #endif |
226 #endif |
224 } while ((f == NULL) && (errno == EINTR)); |
227 } while ((f == NULL) && (errno == EINTR)); |
225 _immediateInterrupt = 0; |
228 _immediateInterrupt = 0; |
226 if (f == NULL) { |
229 if (f == NULL) { |
227 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
230 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
228 } else { |
231 } else { |
229 _INST(filePointer) = MKOBJ(f); |
232 _INST(filePointer) = MKOBJ(f); |
230 retVal = self; |
233 retVal = self; |
231 } |
234 } |
232 } |
235 } |
233 } |
236 } |
234 #endif |
237 #endif |
235 %} |
238 %} |
236 . |
239 . |
237 retVal notNil ifTrue:[ |
240 retVal notNil ifTrue:[ |
238 commandString := aCommandString. |
241 commandString := aCommandString. |
239 buffered := true. |
242 buffered := true. |
240 hitEOF := false. |
243 hitEOF := false. |
241 Lobby register:self |
244 Lobby register:self |
242 ]. |
245 ]. |
243 ^ retVal |
246 ^ retVal |
244 ! |
247 ! |
245 |
248 |
246 readingFrom:command |
249 readingFrom:command |